0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define DEBUG
0011
0012 #include <linux/kernel.h>
0013 #include <linux/types.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/list.h>
0016 #include <linux/gpio.h>
0017 #include <linux/timer.h>
0018 #include <linux/init.h>
0019 #include <linux/device.h>
0020 #include <linux/io.h>
0021
0022 #include <asm/mach/arch.h>
0023 #include <asm/mach/map.h>
0024 #include <asm/mach/irq.h>
0025
0026 #include "gpio-samsung.h"
0027 #include "irqs.h"
0028 #include <asm/irq.h>
0029
0030 #include <linux/platform_data/usb-ohci-s3c2410.h>
0031 #include "devs.h"
0032
0033 #include "bast.h"
0034 #include "simtec.h"
0035
0036
0037
0038
0039
0040 static unsigned int power_state[2];
0041
0042 static void
0043 usb_simtec_powercontrol(int port, int to)
0044 {
0045 pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
0046
0047 power_state[port] = to;
0048
0049 if (power_state[0] && power_state[1])
0050 gpio_set_value(S3C2410_GPB(4), 0);
0051 else
0052 gpio_set_value(S3C2410_GPB(4), 1);
0053 }
0054
0055 static irqreturn_t
0056 usb_simtec_ocirq(int irq, void *pw)
0057 {
0058 struct s3c2410_hcd_info *info = pw;
0059
0060 if (gpio_get_value(S3C2410_GPG(10)) == 0) {
0061 pr_debug("usb_simtec: over-current irq (oc detected)\n");
0062 s3c2410_usb_report_oc(info, 3);
0063 } else {
0064 pr_debug("usb_simtec: over-current irq (oc cleared)\n");
0065 s3c2410_usb_report_oc(info, 0);
0066 }
0067
0068 return IRQ_HANDLED;
0069 }
0070
0071 static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on)
0072 {
0073 int ret;
0074
0075 if (on) {
0076 ret = request_irq(BAST_IRQ_USBOC, usb_simtec_ocirq,
0077 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
0078 "USB Over-current", info);
0079 if (ret != 0) {
0080 printk(KERN_ERR "failed to request usb oc irq\n");
0081 }
0082 } else {
0083 free_irq(BAST_IRQ_USBOC, info);
0084 }
0085 }
0086
0087 static struct s3c2410_hcd_info usb_simtec_info __initdata = {
0088 .port[0] = {
0089 .flags = S3C_HCDFLG_USED
0090 },
0091 .port[1] = {
0092 .flags = S3C_HCDFLG_USED
0093 },
0094
0095 .power_control = usb_simtec_powercontrol,
0096 .enable_oc = usb_simtec_enableoc,
0097 };
0098
0099
0100 int __init usb_simtec_init(void)
0101 {
0102 int ret;
0103
0104 printk("USB Power Control, Copyright 2004 Simtec Electronics\n");
0105
0106 ret = gpio_request(S3C2410_GPB(4), "USB power control");
0107 if (ret < 0) {
0108 pr_err("%s: failed to get GPB4\n", __func__);
0109 return ret;
0110 }
0111
0112 ret = gpio_request(S3C2410_GPG(10), "USB overcurrent");
0113 if (ret < 0) {
0114 pr_err("%s: failed to get GPG10\n", __func__);
0115 gpio_free(S3C2410_GPB(4));
0116 return ret;
0117 }
0118
0119
0120 gpio_direction_output(S3C2410_GPB(4), 1);
0121 gpio_direction_input(S3C2410_GPG(10));
0122
0123 s3c_ohci_set_platdata(&usb_simtec_info);
0124 return 0;
0125 }