usb-simtec.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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/gpio.h>
  20. #include <linux/timer.h>
  21. #include <linux/init.h>
  22. #include <linux/device.h>
  23. #include <linux/gpio.h>
  24. #include <linux/io.h>
  25. #include <asm/mach/arch.h>
  26. #include <asm/mach/map.h>
  27. #include <asm/mach/irq.h>
  28. #include <mach/bast-map.h>
  29. #include <mach/bast-irq.h>
  30. #include <mach/hardware.h>
  31. #include <asm/irq.h>
  32. #include <plat/usb-control.h>
  33. #include <plat/devs.h>
  34. #include "usb-simtec.h"
  35. /* control power and monitor over-current events on various Simtec
  36. * designed boards.
  37. */
  38. static unsigned int power_state[2];
  39. static void
  40. usb_simtec_powercontrol(int port, int to)
  41. {
  42. pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
  43. power_state[port] = to;
  44. if (power_state[0] && power_state[1])
  45. gpio_set_value(S3C2410_GPB(4), 0);
  46. else
  47. gpio_set_value(S3C2410_GPB(4), 1);
  48. }
  49. static irqreturn_t
  50. usb_simtec_ocirq(int irq, void *pw)
  51. {
  52. struct s3c2410_hcd_info *info = pw;
  53. if (gpio_get_value(S3C2410_GPG(10)) == 0) {
  54. pr_debug("usb_simtec: over-current irq (oc detected)\n");
  55. s3c2410_usb_report_oc(info, 3);
  56. } else {
  57. pr_debug("usb_simtec: over-current irq (oc cleared)\n");
  58. s3c2410_usb_report_oc(info, 0);
  59. }
  60. return IRQ_HANDLED;
  61. }
  62. static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on)
  63. {
  64. int ret;
  65. if (on) {
  66. ret = request_irq(IRQ_USBOC, usb_simtec_ocirq,
  67. IRQF_DISABLED | IRQF_TRIGGER_RISING |
  68. IRQF_TRIGGER_FALLING,
  69. "USB Over-current", info);
  70. if (ret != 0) {
  71. printk(KERN_ERR "failed to request usb oc irq\n");
  72. }
  73. } else {
  74. free_irq(IRQ_USBOC, info);
  75. }
  76. }
  77. static struct s3c2410_hcd_info usb_simtec_info = {
  78. .port[0] = {
  79. .flags = S3C_HCDFLG_USED
  80. },
  81. .port[1] = {
  82. .flags = S3C_HCDFLG_USED
  83. },
  84. .power_control = usb_simtec_powercontrol,
  85. .enable_oc = usb_simtec_enableoc,
  86. };
  87. int usb_simtec_init(void)
  88. {
  89. int ret;
  90. printk("USB Power Control, (c) 2004 Simtec Electronics\n");
  91. ret = gpio_request(S3C2410_GPB(4), "USB power control");
  92. if (ret < 0) {
  93. pr_err("%s: failed to get GPB4\n", __func__);
  94. return ret;
  95. }
  96. ret = gpio_request(S3C2410_GPG(10), "USB overcurrent");
  97. if (ret < 0) {
  98. pr_err("%s: failed to get GPG10\n", __func__);
  99. gpio_free(S3C2410_GPB(4));
  100. return ret;
  101. }
  102. /* turn power on */
  103. gpio_direction_output(S3C2410_GPB(4), 1);
  104. gpio_direction_input(S3C2410_GPG(10));
  105. s3c_device_usb.dev.platform_data = &usb_simtec_info;
  106. return 0;
  107. }