Patch abstracts and moves common USB OHCI platform setup code of da8xx based boards to mach-davinci/usb.c file, thereby it avoids repetition of code. Patch is based on consolidation concern raised by Sekhar Nori. https://lkml.org/lkml/2011/12/21/48 Signed-off-by: Manjunathappa, Prakash <prakash.pm@xxxxxx> --- arch/arm/mach-davinci/board-da830-evm.c | 86 +++----------------- arch/arm/mach-davinci/board-omapl138-hawk.c | 93 +++------------------- arch/arm/mach-davinci/include/mach/da8xx.h | 2 + arch/arm/mach-davinci/include/mach/usb.h | 32 +++++++- arch/arm/mach-davinci/usb.c | 116 +++++++++++++++++++++++++++ drivers/usb/host/ohci-da8xx.c | 15 ++-- 6 files changed, 178 insertions(+), 166 deletions(-) diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index dc1afe5..edc8277 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -46,59 +46,23 @@ static const short da830_evm_usb11_pins[] = { -1 }; -static da8xx_ocic_handler_t da830_evm_usb_ocic_handler; - -static int da830_evm_usb_set_power(unsigned port, int on) -{ - gpio_set_value(ON_BD_USB_DRV, on); - return 0; -} - -static int da830_evm_usb_get_power(unsigned port) -{ - return gpio_get_value(ON_BD_USB_DRV); -} - -static int da830_evm_usb_get_oci(unsigned port) -{ - return !gpio_get_value(ON_BD_USB_OVC); -} - static irqreturn_t da830_evm_usb_ocic_irq(int, void *); -static int da830_evm_usb_ocic_notify(da8xx_ocic_handler_t handler) -{ - int irq = gpio_to_irq(ON_BD_USB_OVC); - int error = 0; - - if (handler != NULL) { - da830_evm_usb_ocic_handler = handler; - - error = request_irq(irq, da830_evm_usb_ocic_irq, IRQF_DISABLED | - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "OHCI over-current indicator", NULL); - if (error) - printk(KERN_ERR "%s: could not request IRQ to watch " - "over-current indicator changes\n", __func__); - } else - free_irq(irq, NULL); - - return error; -} - static struct da8xx_ohci_root_hub da830_evm_usb11_pdata = { - .set_power = da830_evm_usb_set_power, - .get_power = da830_evm_usb_get_power, - .get_oci = da830_evm_usb_get_oci, - .ocic_notify = da830_evm_usb_ocic_notify, - - /* TPS2065 switch @ 5V */ - .potpgt = (3 + 1) / 2, /* 3 ms max */ + .type = GPIO_BASED, + .method = { + .gpio_method = { + .power_control_pin = ON_BD_USB_DRV, + .over_current_indicator = ON_BD_USB_OVC, + }, + }, + .board_ocic_handler = da830_evm_usb_ocic_irq, }; -static irqreturn_t da830_evm_usb_ocic_irq(int irq, void *dev_id) +static irqreturn_t da830_evm_usb_ocic_irq(int irq, void *handler) { - da830_evm_usb_ocic_handler(&da830_evm_usb11_pdata, 1); + if (handler != NULL) + ((da8xx_ocic_handler_t)handler)(&da830_evm_usb11_pdata, 1); return IRQ_HANDLED; } @@ -156,33 +120,7 @@ static __init void da830_evm_usb_init(void) __func__, ret); } - ret = davinci_cfg_reg_list(da830_evm_usb11_pins); - if (ret) { - pr_warning("%s: USB 1.1 PinMux setup failed: %d\n", - __func__, ret); - return; - } - - ret = gpio_request(ON_BD_USB_DRV, "ON_BD_USB_DRV"); - if (ret) { - printk(KERN_ERR "%s: failed to request GPIO for USB 1.1 port " - "power control: %d\n", __func__, ret); - return; - } - gpio_direction_output(ON_BD_USB_DRV, 0); - - ret = gpio_request(ON_BD_USB_OVC, "ON_BD_USB_OVC"); - if (ret) { - printk(KERN_ERR "%s: failed to request GPIO for USB 1.1 port " - "over-current indicator: %d\n", __func__, ret); - return; - } - gpio_direction_input(ON_BD_USB_OVC); - - ret = da8xx_register_usb11(&da830_evm_usb11_pdata); - if (ret) - pr_warning("%s: USB 1.1 registration failed: %d\n", - __func__, ret); + da8xx_board_usb_init(da830_evm_usb11_pins, &da830_evm_usb11_pdata); } static struct davinci_uart_config da830_evm_uart_config __initdata = { diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index 45e8157..9214923 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -184,77 +184,34 @@ mmc_setup_wp_fail: } static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id); -static da8xx_ocic_handler_t hawk_usb_ocic_handler; static const short da850_hawk_usb11_pins[] = { DA850_GPIO2_4, DA850_GPIO6_13, -1 }; -static int hawk_usb_set_power(unsigned port, int on) -{ - gpio_set_value(DA850_USB1_VBUS_PIN, on); - return 0; -} - -static int hawk_usb_get_power(unsigned port) -{ - return gpio_get_value(DA850_USB1_VBUS_PIN); -} - -static int hawk_usb_get_oci(unsigned port) -{ - return !gpio_get_value(DA850_USB1_OC_PIN); -} - -static int hawk_usb_ocic_notify(da8xx_ocic_handler_t handler) -{ - int irq = gpio_to_irq(DA850_USB1_OC_PIN); - int error = 0; - - if (handler != NULL) { - hawk_usb_ocic_handler = handler; - - error = request_irq(irq, omapl138_hawk_usb_ocic_irq, - IRQF_DISABLED | IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING, - "OHCI over-current indicator", NULL); - if (error) - pr_err("%s: could not request IRQ to watch " - "over-current indicator changes\n", __func__); - } else { - free_irq(irq, NULL); - } - return error; -} - static struct da8xx_ohci_root_hub omapl138_hawk_usb11_pdata = { - .set_power = hawk_usb_set_power, - .get_power = hawk_usb_get_power, - .get_oci = hawk_usb_get_oci, - .ocic_notify = hawk_usb_ocic_notify, - /* TPS2087 switch @ 5V */ - .potpgt = (3 + 1) / 2, /* 3 ms max */ + .type = GPIO_BASED, + .method = { + .gpio_method = { + .power_control_pin = DA850_USB1_VBUS_PIN, + .over_current_indicator = DA850_USB1_OC_PIN, + }, + }, + .board_ocic_handler = omapl138_hawk_usb_ocic_irq, }; -static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id) +static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *handler) { - hawk_usb_ocic_handler(&omapl138_hawk_usb11_pdata, 1); + if (handler != NULL) + ((da8xx_ocic_handler_t)handler)(&omapl138_hawk_usb11_pdata, 1); return IRQ_HANDLED; } static __init void omapl138_hawk_usb_init(void) { - int ret; u32 cfgchip2; - ret = davinci_cfg_reg_list(da850_hawk_usb11_pins); - if (ret) { - pr_warning("%s: USB 1.1 PinMux setup failed: %d\n", - __func__, ret); - return; - } - /* Setup the Ref. clock frequency for the HAWK at 24 MHz. */ cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); @@ -262,35 +219,9 @@ static __init void omapl138_hawk_usb_init(void) cfgchip2 |= CFGCHIP2_REFFREQ_24MHZ; __raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)); - ret = gpio_request_one(DA850_USB1_VBUS_PIN, - GPIOF_DIR_OUT, "USB1 VBUS"); - if (ret < 0) { - pr_err("%s: failed to request GPIO for USB 1.1 port " - "power control: %d\n", __func__, ret); - return; - } - - ret = gpio_request_one(DA850_USB1_OC_PIN, - GPIOF_DIR_IN, "USB1 OC"); - if (ret < 0) { - pr_err("%s: failed to request GPIO for USB 1.1 port " - "over-current indicator: %d\n", __func__, ret); - goto usb11_setup_oc_fail; - } - - ret = da8xx_register_usb11(&omapl138_hawk_usb11_pdata); - if (ret) { - pr_warning("%s: USB 1.1 registration failed: %d\n", - __func__, ret); - goto usb11_setup_fail; - } + da8xx_board_usb_init(da850_hawk_usb11_pins, &omapl138_hawk_usb11_pdata); return; - -usb11_setup_fail: - gpio_free(DA850_USB1_OC_PIN); -usb11_setup_oc_fail: - gpio_free(DA850_USB1_VBUS_PIN); } static struct davinci_uart_config omapl138_hawk_uart_config __initdata = { diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index ee3461d..691e1cc 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -78,6 +78,8 @@ int da850_register_edma(struct edma_rsv_info *rsv[2]); int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata); int da8xx_register_spi(int instance, struct spi_board_info *info, unsigned len); int da8xx_register_watchdog(void); +void __init da8xx_board_usb_init(const short pins[], + struct da8xx_ohci_root_hub *usb11_pdata); int da8xx_register_usb20(unsigned mA, unsigned potpgt); int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata); int da8xx_register_emac(void); diff --git a/arch/arm/mach-davinci/include/mach/usb.h b/arch/arm/mach-davinci/include/mach/usb.h index e0bc4ab..1a6f211 100644 --- a/arch/arm/mach-davinci/include/mach/usb.h +++ b/arch/arm/mach-davinci/include/mach/usb.h @@ -11,6 +11,8 @@ #ifndef __ASM_ARCH_USB_H #define __ASM_ARCH_USB_H +#include <linux/interrupt.h> + /* DA8xx CFGCHIP2 (USB 2.0 PHY Control) register bits */ #define CFGCHIP2_PHYCLKGD (1 << 17) #define CFGCHIP2_VBUSSENSE (1 << 16) @@ -33,25 +35,47 @@ #define CFGCHIP2_REFFREQ_12MHZ (1 << 0) #define CFGCHIP2_REFFREQ_24MHZ (2 << 0) #define CFGCHIP2_REFFREQ_48MHZ (3 << 0) +enum usb_power_n_ovc_method { + GPIO_BASED = 1, +}; struct da8xx_ohci_root_hub; typedef void (*da8xx_ocic_handler_t)(struct da8xx_ohci_root_hub *hub, unsigned port); +struct gpio_based { + u32 power_control_pin; + u32 over_current_indicator; +}; + /* Passed as the platform data to the OHCI driver */ struct da8xx_ohci_root_hub { /* Switch the port power on/off */ - int (*set_power)(unsigned port, int on); + int (*set_power)(unsigned port, struct da8xx_ohci_root_hub *hub, + int on); /* Read the port power status */ - int (*get_power)(unsigned port); + int (*get_power)(unsigned port, struct da8xx_ohci_root_hub *hub); /* Read the port over-current indicator */ - int (*get_oci)(unsigned port); + int (*get_oci)(unsigned port, struct da8xx_ohci_root_hub *hub); /* Over-current indicator change notification (pass NULL to disable) */ - int (*ocic_notify)(da8xx_ocic_handler_t handler); + int (*ocic_notify)(da8xx_ocic_handler_t handler, + struct da8xx_ohci_root_hub *hub); /* Time from power on to power good (in 2 ms units) */ u8 potpgt; + + /* Power control and over current control method */ + unsigned int type; + union power_n_overcurrent_pins { + struct gpio_based gpio_method; + /* Add data pertaining other methods here. For example if its + * I2C based. + */ + } method; + + /* board specific handler */ + irq_handler_t board_ocic_handler; }; void davinci_setup_usb(unsigned mA, unsigned potpgt_ms); diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c index 23d2b6d..25c3520 100644 --- a/arch/arm/mach-davinci/usb.c +++ b/arch/arm/mach-davinci/usb.c @@ -4,6 +4,7 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/gpio.h> #include <linux/usb/musb.h> @@ -11,12 +12,70 @@ #include <mach/irqs.h> #include <mach/cputype.h> #include <mach/usb.h> +#include <mach/mux.h> #define DAVINCI_USB_OTG_BASE 0x01c64000 #define DA8XX_USB0_BASE 0x01e00000 #define DA8XX_USB1_BASE 0x01e25000 +static int da8xx_usb_set_power(unsigned port, struct da8xx_ohci_root_hub *hub, + int on) +{ + struct gpio_based *gpio = (hub->type == GPIO_BASED) ? + &hub->method.gpio_method : NULL; + + if (hub->type == GPIO_BASED) + gpio_set_value(gpio->power_control_pin, on); + return 0; +} + +static int da8xx_usb_get_power(unsigned port, struct da8xx_ohci_root_hub *hub) +{ + struct gpio_based *gpio = (hub->type == GPIO_BASED) ? + &hub->method.gpio_method : NULL; + + if (hub->type == GPIO_BASED) + return gpio_get_value(gpio->power_control_pin); + return 0; +} + +static int da8xx_usb_get_oci(unsigned port, struct da8xx_ohci_root_hub *hub) +{ + struct gpio_based *gpio = (hub->type == GPIO_BASED) ? + &hub->method.gpio_method : NULL; + + if (hub->type == GPIO_BASED) + return !gpio_get_value(gpio->over_current_indicator); + return 0; +} + +static int da8xx_usb_ocic_notify(da8xx_ocic_handler_t handler, + struct da8xx_ohci_root_hub *hub) +{ + int irq = -1; + int error = 0; + struct gpio_based *gpio = (hub->type == GPIO_BASED) ? + &hub->method.gpio_method : NULL; + + if (hub->type == GPIO_BASED) + irq = gpio_to_irq(gpio->over_current_indicator); + + if (handler != NULL) { + + error = request_irq(irq, hub->board_ocic_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "OHCI over-current indicator", handler); + if (error) + pr_err("%s: could not request IRQ to watch " + "over-current indicator changes\n", __func__); + } else { + free_irq(irq, NULL); + } + return error; +} + #if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) static struct musb_hdrc_eps_bits musb_eps[] = { { "ep1_tx", 8, }, @@ -177,4 +236,61 @@ int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata) da8xx_usb11_device.dev.platform_data = pdata; return platform_device_register(&da8xx_usb11_device); } + +void __init da8xx_board_usb_init(const short pins[], + struct da8xx_ohci_root_hub *usb11_pdata) +{ + int ret; + struct gpio_based *gpio = (usb11_pdata->type == GPIO_BASED) ? + &usb11_pdata->method.gpio_method : NULL; + + ret = davinci_cfg_reg_list(pins); + if (ret) { + pr_warning("%s: USB 1.1 PinMux setup failed: %d\n", + __func__, ret); + return; + } + + if (usb11_pdata->type == GPIO_BASED) { + + ret = gpio_request_one(gpio->power_control_pin, + GPIOF_OUT_INIT_LOW, "ON_BD_USB_DRV"); + if (ret) { + pr_err("%s: failed to request GPIO for USB 1.1 port " + "power control: %d\n", __func__, ret); + return; + } + + ret = gpio_request_one(gpio->over_current_indicator, GPIOF_IN, + "ON_BD_USB_OVC"); + if (ret) { + pr_err("%s: failed to request GPIO for USB 1.1 port " + "over-current indicator: %d\n", __func__, ret); + goto usb11_setup_oc_fail; + } + } + + usb11_pdata->set_power = da8xx_usb_set_power; + usb11_pdata->get_power = da8xx_usb_get_power; + usb11_pdata->get_oci = da8xx_usb_get_oci; + usb11_pdata->ocic_notify = da8xx_usb_ocic_notify; + /* TPS2087 switch @ 5V */ + usb11_pdata->potpgt = (3 + 1) / 2; + + ret = da8xx_register_usb11(usb11_pdata); + if (ret) { + pr_warning("%s: USB 1.1 registration failed: %d\n", + __func__, ret); + goto usb11_setup_fail; + } + + return; + +usb11_setup_fail: + if (usb11_pdata->type == GPIO_BASED) + gpio_free(gpio->over_current_indicator); +usb11_setup_oc_fail: + if (usb11_pdata->type == GPIO_BASED) + gpio_free(gpio->power_control_pin); +} #endif /* CONFIG_DAVINCI_DA8XX */ diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 8435097..b3e2413 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -78,8 +78,8 @@ static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub, ocic_mask |= 1 << port; /* Once over-current is detected, the port needs to be powered down */ - if (hub->get_oci(port) > 0) - hub->set_power(port, 0); + if (hub->get_oci(port, hub) > 0) + hub->set_power(port, hub, 0); } static int ohci_da8xx_init(struct usb_hcd *hcd) @@ -185,11 +185,11 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = roothub_portstatus(hcd_to_ohci(hcd), wIndex - 1); /* The port power status (PPS) bit defaults to 1 */ - if (hub->get_power && hub->get_power(wIndex) == 0) + if (hub->get_power && hub->get_power(wIndex, hub) == 0) temp &= ~RH_PS_PPS; /* The port over-current indicator (POCI) bit is always 0 */ - if (hub->get_oci && hub->get_oci(wIndex) > 0) + if (hub->get_oci && hub->get_oci(wIndex, hub) > 0) temp |= RH_PS_POCI; /* The over-current indicator change (OCIC) bit is 0 too */ @@ -217,7 +217,8 @@ check_port: if (!hub->set_power) return -EPIPE; - return hub->set_power(wIndex, temp) ? -EPIPE : 0; + return hub->set_power(wIndex, hub, + temp) ? -EPIPE : 0; case USB_PORT_FEAT_C_OVER_CURRENT: dev_dbg(dev, "%sPortFeature(%u): %s\n", temp ? "Set" : "Clear", wIndex, @@ -349,7 +350,7 @@ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, goto err4; if (hub->ocic_notify) { - error = hub->ocic_notify(ohci_da8xx_ocic_handler); + error = hub->ocic_notify(ohci_da8xx_ocic_handler, hub); if (!error) return 0; } @@ -382,7 +383,7 @@ usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev) { struct da8xx_ohci_root_hub *hub = pdev->dev.platform_data; - hub->ocic_notify(NULL); + hub->ocic_notify(NULL, NULL); usb_remove_hcd(hcd); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html