usb-simtec.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. * Modifications:
  15. * 14-Sep-2004 BJD Created
  16. * 18-Oct-2004 BJD Cleanups, and added code to report OC cleared
  17. * 09-Aug-2005 BJD Renamed s3c2410_report_oc to s3c2410_usb_report_oc
  18. * 09-Aug-2005 BJD Ports powered only if both are enabled
  19. */
  20. #define DEBUG
  21. #include <linux/kernel.h>
  22. #include <linux/types.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/list.h>
  25. #include <linux/timer.h>
  26. #include <linux/init.h>
  27. #include <linux/device.h>
  28. #include <asm/mach/arch.h>
  29. #include <asm/mach/map.h>
  30. #include <asm/mach/irq.h>
  31. #include <asm/arch/bast-map.h>
  32. #include <asm/arch/bast-irq.h>
  33. #include <asm/arch/usb-control.h>
  34. #include <asm/arch/regs-gpio.h>
  35. #include <asm/hardware.h>
  36. #include <asm/io.h>
  37. #include <asm/irq.h>
  38. #include <asm/mach-types.h>
  39. #include "devs.h"
  40. #include "usb-simtec.h"
  41. /* control power and monitor over-current events on various Simtec
  42. * designed boards.
  43. */
  44. static unsigned int power_state[2];
  45. static void
  46. usb_simtec_powercontrol(int port, int to)
  47. {
  48. pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
  49. power_state[port] = to;
  50. if (power_state[0] && power_state[1])
  51. s3c2410_gpio_setpin(S3C2410_GPB4, 0);
  52. else
  53. s3c2410_gpio_setpin(S3C2410_GPB4, 1);
  54. }
  55. static irqreturn_t
  56. usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs)
  57. {
  58. struct s3c2410_hcd_info *info = (struct s3c2410_hcd_info *)pw;
  59. if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
  60. pr_debug("usb_simtec: over-current irq (oc detected)\n");
  61. s3c2410_usb_report_oc(info, 3);
  62. } else {
  63. pr_debug("usb_simtec: over-current irq (oc cleared)\n");
  64. s3c2410_usb_report_oc(info, 0);
  65. }
  66. return IRQ_HANDLED;
  67. }
  68. static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on)
  69. {
  70. int ret;
  71. if (on) {
  72. ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, SA_INTERRUPT,
  73. "USB Over-current", info);
  74. if (ret != 0) {
  75. printk(KERN_ERR "failed to request usb oc irq\n");
  76. }
  77. set_irq_type(IRQ_USBOC, IRQT_BOTHEDGE);
  78. } else {
  79. free_irq(IRQ_USBOC, info);
  80. }
  81. }
  82. static struct s3c2410_hcd_info usb_simtec_info = {
  83. .port[0] = {
  84. .flags = S3C_HCDFLG_USED
  85. },
  86. .port[1] = {
  87. .flags = S3C_HCDFLG_USED
  88. },
  89. .power_control = usb_simtec_powercontrol,
  90. .enable_oc = usb_simtec_enableoc,
  91. };
  92. int usb_simtec_init(void)
  93. {
  94. printk("USB Power Control, (c) 2004 Simtec Electronics\n");
  95. s3c_device_usb.dev.platform_data = &usb_simtec_info;
  96. s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
  97. s3c2410_gpio_setpin(S3C2410_GPB4, 1);
  98. return 0;
  99. }