usb-simtec.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /* linux/arch/arm/mach-s3c2410/usb-simtec.c
  2. *
  3. * Copyright (c) 2004,2005 Simtec Electronics
  4. * Ben Dooks <ben@simtec.co.uk>
  5. *
  6. * http://www.simtec.co.uk/products/EB2410ITX/
  7. *
  8. * Simtec BAST and Thorcom VR1000 USB port support functions
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #define DEBUG
  15. #include <linux/kernel.h>
  16. #include <linux/types.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/list.h>
  19. #include <linux/timer.h>
  20. #include <linux/init.h>
  21. #include <linux/device.h>
  22. #include <asm/mach/arch.h>
  23. #include <asm/mach/map.h>
  24. #include <asm/mach/irq.h>
  25. #include <asm/arch/bast-map.h>
  26. #include <asm/arch/bast-irq.h>
  27. #include <asm/arch/usb-control.h>
  28. #include <asm/arch/regs-gpio.h>
  29. #include <asm/hardware.h>
  30. #include <asm/io.h>
  31. #include <asm/irq.h>
  32. #include <asm/plat-s3c24xx/devs.h>
  33. #include "usb-simtec.h"
  34. /* control power and monitor over-current events on various Simtec
  35. * designed boards.
  36. */
  37. static unsigned int power_state[2];
  38. static void
  39. usb_simtec_powercontrol(int port, int to)
  40. {
  41. pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
  42. power_state[port] = to;
  43. if (power_state[0] && power_state[1])
  44. s3c2410_gpio_setpin(S3C2410_GPB4, 0);
  45. else
  46. s3c2410_gpio_setpin(S3C2410_GPB4, 1);
  47. }
  48. static irqreturn_t
  49. usb_simtec_ocirq(int irq, void *pw)
  50. {
  51. struct s3c2410_hcd_info *info = (struct s3c2410_hcd_info *)pw;
  52. if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
  53. pr_debug("usb_simtec: over-current irq (oc detected)\n");
  54. s3c2410_usb_report_oc(info, 3);
  55. } else {
  56. pr_debug("usb_simtec: over-current irq (oc cleared)\n");
  57. s3c2410_usb_report_oc(info, 0);
  58. }
  59. return IRQ_HANDLED;
  60. }
  61. static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on)
  62. {
  63. int ret;
  64. if (on) {
  65. ret = request_irq(IRQ_USBOC, usb_simtec_ocirq,
  66. IRQF_DISABLED | IRQF_TRIGGER_RISING |
  67. IRQF_TRIGGER_FALLING,
  68. "USB Over-current", info);
  69. if (ret != 0) {
  70. printk(KERN_ERR "failed to request usb oc irq\n");
  71. }
  72. } else {
  73. free_irq(IRQ_USBOC, info);
  74. }
  75. }
  76. static struct s3c2410_hcd_info usb_simtec_info = {
  77. .port[0] = {
  78. .flags = S3C_HCDFLG_USED
  79. },
  80. .port[1] = {
  81. .flags = S3C_HCDFLG_USED
  82. },
  83. .power_control = usb_simtec_powercontrol,
  84. .enable_oc = usb_simtec_enableoc,
  85. };
  86. int usb_simtec_init(void)
  87. {
  88. printk("USB Power Control, (c) 2004 Simtec Electronics\n");
  89. s3c_device_usb.dev.platform_data = &usb_simtec_info;
  90. s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
  91. s3c2410_gpio_setpin(S3C2410_GPB4, 1);
  92. return 0;
  93. }