simtec-usb.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* linux/arch/arm/mach-s3c2410/usb-simtec.c
  2. *
  3. * Copyright 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/gpio.h>
  20. #include <linux/timer.h>
  21. #include <linux/init.h>
  22. #include <linux/device.h>
  23. #include <linux/io.h>
  24. #include <asm/mach/arch.h>
  25. #include <asm/mach/map.h>
  26. #include <asm/mach/irq.h>
  27. #include <mach/hardware.h>
  28. #include <mach/gpio-samsung.h>
  29. #include <asm/irq.h>
  30. #include <linux/platform_data/usb-ohci-s3c2410.h>
  31. #include <plat/devs.h>
  32. #include "bast.h"
  33. #include "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. gpio_set_value(S3C2410_GPB(4), 0);
  45. else
  46. gpio_set_value(S3C2410_GPB(4), 1);
  47. }
  48. static irqreturn_t
  49. usb_simtec_ocirq(int irq, void *pw)
  50. {
  51. struct s3c2410_hcd_info *info = pw;
  52. if (gpio_get_value(S3C2410_GPG(10)) == 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(BAST_IRQ_USBOC, usb_simtec_ocirq,
  66. IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  67. "USB Over-current", info);
  68. if (ret != 0) {
  69. printk(KERN_ERR "failed to request usb oc irq\n");
  70. }
  71. } else {
  72. free_irq(BAST_IRQ_USBOC, info);
  73. }
  74. }
  75. static struct s3c2410_hcd_info usb_simtec_info __initdata = {
  76. .port[0] = {
  77. .flags = S3C_HCDFLG_USED
  78. },
  79. .port[1] = {
  80. .flags = S3C_HCDFLG_USED
  81. },
  82. .power_control = usb_simtec_powercontrol,
  83. .enable_oc = usb_simtec_enableoc,
  84. };
  85. int __init usb_simtec_init(void)
  86. {
  87. int ret;
  88. printk("USB Power Control, Copyright 2004 Simtec Electronics\n");
  89. ret = gpio_request(S3C2410_GPB(4), "USB power control");
  90. if (ret < 0) {
  91. pr_err("%s: failed to get GPB4\n", __func__);
  92. return ret;
  93. }
  94. ret = gpio_request(S3C2410_GPG(10), "USB overcurrent");
  95. if (ret < 0) {
  96. pr_err("%s: failed to get GPG10\n", __func__);
  97. gpio_free(S3C2410_GPB(4));
  98. return ret;
  99. }
  100. /* turn power on */
  101. gpio_direction_output(S3C2410_GPB(4), 1);
  102. gpio_direction_input(S3C2410_GPG(10));
  103. s3c_ohci_set_platdata(&usb_simtec_info);
  104. return 0;
  105. }