From ad105d6f230148e545bcd6cb6944b3ca071ab44f Mon Sep 17 00:00:00 2001 From: Sakethram Bommisetti Date: Thu, 14 Jul 2011 17:30:24 +0530 Subject: USB:Enable GPIO configuration at connect GPIO alternate configuration is set when the USB is connected and reset at USB disconnect. Change-Id: I07d9c2ed5028879ecff309aa9e4ac25deac148f5 Signed-off-by: Sakethram Bommisetti Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/27203 Reviewed-by: QATOOLS Reviewed-by: Praveena NADAHALLY Reviewed-by: Philippe LANGLAIS --- arch/arm/mach-ux500/board-mop500-usb.h | 13 +++++++++++++ arch/arm/mach-ux500/board-mop500.c | 2 ++ arch/arm/mach-ux500/include/mach/usb.h | 8 ++++++++ arch/arm/mach-ux500/usb.c | 35 ++++++++++++++++++++++++++++++++++ drivers/usb/otg/ab8500-usb.c | 16 ++++++++++++++++ include/linux/mfd/ab8500.h | 1 + 6 files changed, 75 insertions(+) create mode 100644 arch/arm/mach-ux500/board-mop500-usb.h diff --git a/arch/arm/mach-ux500/board-mop500-usb.h b/arch/arm/mach-ux500/board-mop500-usb.h new file mode 100644 index 00000000000..85288463a73 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-usb.h @@ -0,0 +1,13 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Saketh Ram Bommisetti + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __BOARD_MOP500_USB_H +#define __BOARD_MOP500_USB_H + +extern struct ab8500_usbgpio_platform_data ab8500_usbgpio_plat_data; + +#endif diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index be1730bd765..62418a4c444 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -60,6 +60,7 @@ #include "board-mop500-regulators.h" #include "board-mop500-bm.h" #include "board-mop500-wlan.h" +#include "board-mop500-usb.h" #include "pins.h" #ifdef CONFIG_AB8500_DENC @@ -258,6 +259,7 @@ static struct ab8500_platform_data ab8500_platdata = { .fg = &ab8500_fg_plat_data, .chargalg = &ab8500_chargalg_plat_data, .gpio = &ab8500_gpio_pdata, + .usb = &ab8500_usbgpio_plat_data, #ifdef CONFIG_INPUT_AB8500_ACCDET .accdet = &ab8500_accdet_pdata, #endif diff --git a/arch/arm/mach-ux500/include/mach/usb.h b/arch/arm/mach-ux500/include/mach/usb.h index d3739d41881..5c27a72c10d 100644 --- a/arch/arm/mach-ux500/include/mach/usb.h +++ b/arch/arm/mach-ux500/include/mach/usb.h @@ -22,4 +22,12 @@ struct ux500_musb_board_data { void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg, int *dma_tx_cfg); + +struct ab8500_usbgpio_platform_data { + int (*get)(struct device *device); + void (*enable)(void); + void (*disable)(void); + void (*put)(void); +}; + #endif diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c index 82e535953fd..dc6a6970c35 100644 --- a/arch/arm/mach-ux500/usb.c +++ b/arch/arm/mach-ux500/usb.c @@ -9,6 +9,9 @@ #include #include #include +#include +#include "pins.h" +#include "board-mop500-usb.h" #define MUSB_DMA40_RX_CH { \ .mode = STEDMA40_MODE_LOGICAL, \ @@ -85,6 +88,7 @@ static struct ux500_musb_board_data musb_board_data = { }; static u64 ux500_musb_dmamask = DMA_BIT_MASK(32); +static struct ux500_pins *usb_gpio_pins; static struct musb_hdrc_config musb_hdrc_config = { .multipoint = true, @@ -129,6 +133,37 @@ struct platform_device ux500_musb_device = { .resource = usb_resources, }; +static void enable_gpio(void) +{ + ux500_pins_enable(usb_gpio_pins); +} +static void disable_gpio(void) +{ + ux500_pins_disable(usb_gpio_pins); +} +static int get_gpio(struct device *device) +{ + usb_gpio_pins = ux500_pins_get(dev_name(device)); + + if (usb_gpio_pins == NULL) { + dev_err(device, "Could not get %s:usb_gpio_pins structure\n", + dev_name(device)); + + return PTR_ERR(usb_gpio_pins); + } + return 0; +} +static void put_gpio(void) +{ + ux500_pins_put(usb_gpio_pins); +} +struct ab8500_usbgpio_platform_data ab8500_usbgpio_plat_data = { + .get = &get_gpio, + .enable = &enable_gpio, + .disable = &disable_gpio, + .put = &put_gpio, +}; + static inline void ux500_usb_dma_update_rx_ch_config(int *src_dev_type) { u32 idx; diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index fd5943b7d38..fcd3847e6d5 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c @@ -35,6 +35,7 @@ #include #include #include +#include #define AB8500_MAIN_WD_CTRL_REG 0x01 #define AB8500_USB_LINE_STAT_REG 0x80 @@ -99,6 +100,7 @@ struct ab8500_usb { struct regulator *v_ape; struct regulator *v_musb; struct regulator *v_ulpi; + struct ab8500_usbgpio_platform_data *usb_gpio; }; static inline struct ab8500_usb *xceiv_to_ab(struct otg_transceiver *x) @@ -168,6 +170,8 @@ static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host) bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN : AB8500_BIT_PHY_CTRL_DEVICE_EN; + ab->usb_gpio->enable(); + clk_enable(ab->sysclk); ab8500_usb_regulator_ctrl(ab, sel_host, true); @@ -215,6 +219,8 @@ static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host) ab8500_usb_regulator_ctrl(ab, sel_host, false); + ab->usb_gpio->disable(); + prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)dev_name(ab->dev), 50); } @@ -354,6 +360,7 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work) if (!ab->otg.gadget) ab8500_usb_peri_phy_dis(ab); + } static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA) @@ -621,6 +628,8 @@ irq_fail: static int __devinit ab8500_usb_probe(struct platform_device *pdev) { struct ab8500_usb *ab; + struct ab8500_platform_data *ab8500_pdata = + dev_get_platdata(pdev->dev.parent); int err; int rev; @@ -646,6 +655,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) ab->otg.set_peripheral = ab8500_usb_set_peripheral; ab->otg.set_suspend = ab8500_usb_set_suspend; ab->otg.set_power = ab8500_usb_set_power; + ab->usb_gpio = ab8500_pdata->usb; platform_set_drvdata(pdev, ab); @@ -685,6 +695,10 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) /* Needed to enable ID detection. */ ab8500_usb_wd_workaround(ab); + err = ab->usb_gpio->get(ab->dev); + if (err < 0) + goto fail3; + prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)dev_name(ab->dev), 50); @@ -723,6 +737,8 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev) ab8500_usb_regulator_put(ab); + ab->usb_gpio->put(); + platform_set_drvdata(pdev, NULL); kfree(ab); diff --git a/include/linux/mfd/ab8500.h b/include/linux/mfd/ab8500.h index dbf80e51327..b81df84e83c 100644 --- a/include/linux/mfd/ab8500.h +++ b/include/linux/mfd/ab8500.h @@ -207,6 +207,7 @@ struct ab8500_platform_data { struct ab8500_fg_platform_data *fg; struct ab8500_chargalg_platform_data *chargalg; struct ab8500_gpio_platform_data *gpio; + struct ab8500_usbgpio_platform_data *usb; }; extern int __devinit ab8500_init(struct ab8500 *ab8500); -- cgit v1.2.3