simtec-usb.c (2657B)
1// SPDX-License-Identifier: GPL-2.0 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#define DEBUG 11 12#include <linux/kernel.h> 13#include <linux/types.h> 14#include <linux/interrupt.h> 15#include <linux/list.h> 16#include <linux/gpio.h> 17#include <linux/timer.h> 18#include <linux/init.h> 19#include <linux/device.h> 20#include <linux/io.h> 21 22#include <asm/mach/arch.h> 23#include <asm/mach/map.h> 24#include <asm/mach/irq.h> 25 26#include "gpio-samsung.h" 27#include "irqs.h" 28#include <asm/irq.h> 29 30#include <linux/platform_data/usb-ohci-s3c2410.h> 31#include "devs.h" 32 33#include "bast.h" 34#include "simtec.h" 35 36/* control power and monitor over-current events on various Simtec 37 * designed boards. 38*/ 39 40static unsigned int power_state[2]; 41 42static void 43usb_simtec_powercontrol(int port, int to) 44{ 45 pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to); 46 47 power_state[port] = to; 48 49 if (power_state[0] && power_state[1]) 50 gpio_set_value(S3C2410_GPB(4), 0); 51 else 52 gpio_set_value(S3C2410_GPB(4), 1); 53} 54 55static irqreturn_t 56usb_simtec_ocirq(int irq, void *pw) 57{ 58 struct s3c2410_hcd_info *info = pw; 59 60 if (gpio_get_value(S3C2410_GPG(10)) == 0) { 61 pr_debug("usb_simtec: over-current irq (oc detected)\n"); 62 s3c2410_usb_report_oc(info, 3); 63 } else { 64 pr_debug("usb_simtec: over-current irq (oc cleared)\n"); 65 s3c2410_usb_report_oc(info, 0); 66 } 67 68 return IRQ_HANDLED; 69} 70 71static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on) 72{ 73 int ret; 74 75 if (on) { 76 ret = request_irq(BAST_IRQ_USBOC, usb_simtec_ocirq, 77 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 78 "USB Over-current", info); 79 if (ret != 0) { 80 printk(KERN_ERR "failed to request usb oc irq\n"); 81 } 82 } else { 83 free_irq(BAST_IRQ_USBOC, info); 84 } 85} 86 87static struct s3c2410_hcd_info usb_simtec_info __initdata = { 88 .port[0] = { 89 .flags = S3C_HCDFLG_USED 90 }, 91 .port[1] = { 92 .flags = S3C_HCDFLG_USED 93 }, 94 95 .power_control = usb_simtec_powercontrol, 96 .enable_oc = usb_simtec_enableoc, 97}; 98 99 100int __init usb_simtec_init(void) 101{ 102 int ret; 103 104 printk("USB Power Control, Copyright 2004 Simtec Electronics\n"); 105 106 ret = gpio_request(S3C2410_GPB(4), "USB power control"); 107 if (ret < 0) { 108 pr_err("%s: failed to get GPB4\n", __func__); 109 return ret; 110 } 111 112 ret = gpio_request(S3C2410_GPG(10), "USB overcurrent"); 113 if (ret < 0) { 114 pr_err("%s: failed to get GPG10\n", __func__); 115 gpio_free(S3C2410_GPB(4)); 116 return ret; 117 } 118 119 /* turn power on */ 120 gpio_direction_output(S3C2410_GPB(4), 1); 121 gpio_direction_input(S3C2410_GPG(10)); 122 123 s3c_ohci_set_platdata(&usb_simtec_info); 124 return 0; 125}