summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-ux500/board-mop500-usb.h13
-rw-r--r--arch/arm/mach-ux500/board-mop500.c2
-rw-r--r--arch/arm/mach-ux500/include/mach/usb.h8
-rw-r--r--arch/arm/mach-ux500/usb.c35
-rw-r--r--drivers/usb/otg/ab8500-usb.c16
-rw-r--r--include/linux/mfd/ab8500.h1
6 files changed, 75 insertions, 0 deletions
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 <sakethram.bommisetti@stericsson.com>
+ * 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 212fa8df561..a333fa5e7e8 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -63,6 +63,7 @@
#include "board-mop500-regulators.h"
#include "board-mop500-bm.h"
#include "board-mop500-wlan.h"
+#include "board-mop500-usb.h"
#ifdef CONFIG_AB8500_DENC
static struct ab8500_denc_platform_data ab8500_denc_pdata = {
@@ -260,6 +261,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 <plat/ste_dma40.h>
#include <mach/hardware.h>
#include <mach/usb.h>
+#include <plat/pincfg.h>
+#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 <linux/mfd/ab8500.h>
#include <linux/regulator/consumer.h>
#include <mach/prcmu.h>
+#include <mach/usb.h>
#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);