diff options
author | Ruslan Bilovol <ruslan.bilovol@ti.com> | 2012-07-27 15:26:16 +0300 |
---|---|---|
committer | Ziyann <jaraidaniel@gmail.com> | 2014-10-01 12:59:04 +0200 |
commit | e6339e4595e035ab82fd17966784c79275ff3ad5 (patch) | |
tree | bd33a656585646e3fd972e454a8c8acbe2c0e52f /drivers/mfd | |
parent | 009a5c561493197e1cd2daf8e3c6d1a3df17b3e2 (diff) | |
download | kernel_samsung_tuna-e6339e4595e035ab82fd17966784c79275ff3ad5.tar.gz kernel_samsung_tuna-e6339e4595e035ab82fd17966784c79275ff3ad5.tar.bz2 kernel_samsung_tuna-e6339e4595e035ab82fd17966784c79275ff3ad5.zip |
usb: omap4: add HSIC support
The OMAP4 HS USB host subsystem supports the configurations
with two HSIC interfaces. This patch adds the ability
to use both of them
Change-Id: I95478563e07bba6811fed56abe442e640ccd71e4
Signed-off-by: Ruslan Bilovol <ruslan.bilovol@ti.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/omap-usb-host.c | 143 |
1 files changed, 129 insertions, 14 deletions
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 130d950fa62..86f88a798fe 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -57,6 +57,7 @@ #define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0) #define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) +#define OMAP_TLL_CHANNEL_CONF_CHANMODE_MASK (3 << 1) #define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT 24 #define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) #define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) @@ -64,6 +65,7 @@ #define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) #define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS (1 << 1) #define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) +#define OMAP_TLL_CHANNEL_CONF_CHANMODE_TRANSPARENT_UTMI (2 << 1) #define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0 0x0 #define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM 0x1 @@ -157,6 +159,11 @@ struct usbhs_hcd_omap { struct clk *usbtll_p2_fck; struct clk *init_60m_fclk; + struct clk *hsic_p1_fck; + struct clk *hsic_p1_480m_fck; + struct clk *hsic_p2_fck; + struct clk *hsic_p2_480m_fck; + void __iomem *uhh_base; void __iomem *tll_base; @@ -414,6 +421,36 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) goto err_usbtll_p2_fck; } + omap->hsic_p1_fck = clk_get(dev, "usb_host_hs_hsic60m_p1_clk"); + if (IS_ERR(omap->hsic_p1_fck)) { + ret = PTR_ERR(omap->hsic_p1_fck); + dev_err(dev, "usb_host_hs_hsic60m_p1_clk failed error:%d\n", + ret); + goto err_init_60m_fclk; + } + + omap->hsic_p1_480m_fck = clk_get(dev, "usb_host_hs_hsic480m_p1_clk"); + if (IS_ERR(omap->hsic_p1_480m_fck)) { + ret = PTR_ERR(omap->hsic_p1_480m_fck); + dev_err(dev, "usb_host_hs_hsic480m_p1_clk failed error:%d\n", + ret); + goto err_hsic_p1_fck; + } + + omap->hsic_p2_fck = clk_get(dev, "usb_host_hs_hsic60m_p2_clk"); + if (IS_ERR(omap->hsic_p2_fck)) { + ret = PTR_ERR(omap->hsic_p2_fck); + dev_err(dev, "Unable to get usb_host_hs_hsic60m_p2_clk\n"); + goto err_hsic_p1_480m_fck; + } + + omap->hsic_p2_480m_fck = clk_get(dev, "usb_host_hs_hsic480m_p2_clk"); + if (IS_ERR(omap->hsic_p1_480m_fck)) { + ret = PTR_ERR(omap->hsic_p1_480m_fck); + dev_err(dev, "Unable to get usb_host_hs_hsic480m_p2_clk\n"); + goto err_hsic_p2_fck; + } + if (is_ehci_phy_mode(pdata->port_mode[0])) { /* for OMAP3 , the clk set paretn fails */ ret = clk_set_parent(omap->utmi_p1_fck, @@ -447,14 +484,14 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) if (!res) { dev_err(dev, "UHH EHCI get resource failed\n"); ret = -ENODEV; - goto err_init_60m_fclk; + goto err_hsic_p2_480m_fck; } omap->uhh_base = ioremap(res->start, resource_size(res)); if (!omap->uhh_base) { dev_err(dev, "UHH ioremap failed\n"); ret = -ENOMEM; - goto err_init_60m_fclk; + goto err_hsic_p2_480m_fck; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll"); @@ -489,6 +526,18 @@ err_alloc: err_tll: iounmap(omap->uhh_base); +err_hsic_p2_480m_fck: + clk_put(omap->hsic_p2_480m_fck); + +err_hsic_p2_fck: + clk_put(omap->hsic_p2_fck); + +err_hsic_p1_480m_fck: + clk_put(omap->hsic_p1_480m_fck); + +err_hsic_p1_fck: + clk_put(omap->hsic_p1_fck); + err_init_60m_fclk: clk_put(omap->init_60m_fclk); @@ -538,6 +587,10 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev) omap_usbhs_deinit(&pdev->dev); iounmap(omap->tll_base); iounmap(omap->uhh_base); + clk_put(omap->hsic_p2_480m_fck); + clk_put(omap->hsic_p2_fck); + clk_put(omap->hsic_p1_480m_fck); + clk_put(omap->hsic_p1_fck); clk_put(omap->init_60m_fclk); clk_put(omap->usbtll_p2_fck); clk_put(omap->usbhost_p2_fck); @@ -660,6 +713,30 @@ static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count) } } +static void usbhs_omap_hsic_init(struct device *dev, u8 hsic_channel_count) +{ + struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); + struct usbhs_omap_platform_data *pdata = dev->platform_data; + u32 reg; + int i; + + /* Program Common TLL register */ + reg = usbhs_read(omap->tll_base, OMAP_TLL_SHARED_CONF); + reg |= OMAP_TLL_SHARED_CONF_FCLK_IS_ON; + usbhs_write(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); + + /* Enable channels now */ + for (i = 0; i < hsic_channel_count; i++) { + if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_HSIC) { + reg = usbhs_read(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); + reg &= ~OMAP_TLL_CHANNEL_CONF_CHANMODE_MASK; + reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_TRANSPARENT_UTMI + | OMAP_TLL_CHANNEL_CONF_CHANEN; + usbhs_write(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); + } + } +} + static int usbhs_runtime_resume(struct device *dev) { struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); @@ -673,13 +750,27 @@ static int usbhs_runtime_resume(struct device *dev) } if (is_omap_usbhs_rev2(omap)) { - if (is_ehci_tll_mode(pdata->port_mode[0])) { - clk_enable(omap->usbhost_p1_fck); - clk_enable(omap->usbtll_p1_fck); + switch (pdata->port_mode[0]) { + case OMAP_EHCI_PORT_MODE_HSIC: + clk_enable(omap->hsic_p1_fck); + clk_enable(omap->hsic_p1_480m_fck); + case OMAP_EHCI_PORT_MODE_TLL: + clk_enable(omap->usbhost_p1_fck); + clk_enable(omap->usbtll_p1_fck); + break; + default: + break; } - if (is_ehci_tll_mode(pdata->port_mode[1])) { - clk_enable(omap->usbhost_p2_fck); - clk_enable(omap->usbtll_p2_fck); + switch (pdata->port_mode[1]) { + case OMAP_EHCI_PORT_MODE_HSIC: + clk_enable(omap->hsic_p2_fck); + clk_enable(omap->hsic_p2_480m_fck); + case OMAP_EHCI_PORT_MODE_TLL: + clk_enable(omap->usbhost_p2_fck); + clk_enable(omap->usbtll_p2_fck); + break; + default: + break; } clk_enable(omap->utmi_p1_fck); clk_enable(omap->utmi_p2_fck); @@ -700,13 +791,27 @@ static int usbhs_runtime_suspend(struct device *dev) } if (is_omap_usbhs_rev2(omap)) { - if (is_ehci_tll_mode(pdata->port_mode[0])) { - clk_disable(omap->usbhost_p1_fck); - clk_disable(omap->usbtll_p1_fck); + switch (pdata->port_mode[0]) { + case OMAP_EHCI_PORT_MODE_HSIC: + clk_disable(omap->hsic_p1_fck); + clk_disable(omap->hsic_p1_480m_fck); + case OMAP_EHCI_PORT_MODE_TLL: + clk_disable(omap->usbhost_p1_fck); + clk_disable(omap->usbtll_p1_fck); + break; + default: + break; } - if (is_ehci_tll_mode(pdata->port_mode[1])) { - clk_disable(omap->usbhost_p2_fck); - clk_disable(omap->usbtll_p2_fck); + switch (pdata->port_mode[1]) { + case OMAP_EHCI_PORT_MODE_HSIC: + clk_disable(omap->hsic_p2_fck); + clk_disable(omap->hsic_p2_480m_fck); + case OMAP_EHCI_PORT_MODE_TLL: + clk_disable(omap->usbhost_p2_fck); + clk_disable(omap->usbtll_p2_fck); + break; + default: + break; } clk_disable(omap->utmi_p2_fck); clk_disable(omap->utmi_p1_fck); @@ -833,6 +938,16 @@ static void omap_usbhs_init(struct device *dev) usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT); } + if (is_ehci_hsic_mode(pdata->port_mode[0]) || + is_ehci_hsic_mode(pdata->port_mode[1])) { + + if (is_omap_usbhs_rev2(omap)) + usbhs_omap_hsic_init(dev, OMAP_REV2_TLL_CHANNEL_COUNT); + else + dev_dbg(dev, "HSIC is not supported on revision 0x%x\n", + omap->usbhs_rev); + } + if (pdata->ehci_data->phy_reset) { /* Hold the PHY in RESET for enough time till * PHY is settled and ready |