From 23207090cb8ec01171ea29fdad4a3fd70b6e744e Mon Sep 17 00:00:00 2001 From: Koen Kooi Date: Tue, 26 Jul 2011 09:50:32 +0200 Subject: linux-omap 2.6.39: sync with meta-ti Signed-off-by: Koen Kooi --- ...ap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch | 67 ++ ...-omap_usbhs_alloc_children-error-handling.patch | 50 ++ ...003-mfd-Add-omap-usbhs-runtime-PM-support.patch | 245 +++++++ ...b-ehci-and-ohci-hwmod-structures-for-omap.patch | 406 ++++++++++++ ...005-arm-omap-usb-register-hwmods-of-usbhs.patch | 160 +++++ ...b-device-name-change-for-the-clk-names-of.patch | 123 ++++ ...Suspend-and-resume-support-of-ehci-and-oh.patch | 165 +++++ ...-Correct-the-warning-print-during-script-.patch | 36 ++ ...-Modifying-the-macro-name-Main_Ref-to-all.patch | 61 ++ ...FD-TWL4030-power-scripts-for-OMAP3-boards.patch | 705 +++++++++++++++++++++ .../0011-MFD-TWL4030-TWL-version-checking.patch | 164 +++++ ...TWL4030-workaround-changes-for-Erratum-27.patch | 341 ++++++++++ ...TWL4030-optimizing-resource-configuration.patch | 184 ++++++ 13 files changed, 2707 insertions(+) create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch create mode 100644 recipes/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch (limited to 'recipes/linux/linux-omap-2.6.39/mfd') diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch b/recipes/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch new file mode 100644 index 0000000000..c9f1e6a917 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch @@ -0,0 +1,67 @@ +From 46be90d202c36db19e27c2991cbff401c6c3ee81 Mon Sep 17 00:00:00 2001 +From: Keshava Munegowda +Date: Mon, 16 May 2011 14:24:58 +0530 +Subject: [PATCH 01/13] mfd: Fix omap usbhs crash when rmmoding ehci or ohci + +The disabling of clocks and freeing GPIO are changed +to fix the occurrence of the crash of rmmod of ehci and ohci +drivers. The GPIOs should be freed after the spin locks are +unlocked. + +Signed-off-by: Keshava Munegowda +Acked-by: Felipe Balbi +Cc: stable@kernel.org +Signed-off-by: Samuel Ortiz +--- + drivers/mfd/omap-usb-host.c | 27 +++++++++++++++++++-------- + 1 files changed, 19 insertions(+), 8 deletions(-) + +diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c +index 3ab9ffa..55c5d47 100644 +--- a/drivers/mfd/omap-usb-host.c ++++ b/drivers/mfd/omap-usb-host.c +@@ -994,22 +994,33 @@ static void usbhs_disable(struct device *dev) + dev_dbg(dev, "operation timed out\n"); + } + +- if (pdata->ehci_data->phy_reset) { +- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) +- gpio_free(pdata->ehci_data->reset_gpio_port[0]); +- +- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) +- gpio_free(pdata->ehci_data->reset_gpio_port[1]); ++ if (is_omap_usbhs_rev2(omap)) { ++ if (is_ehci_tll_mode(pdata->port_mode[0])) ++ clk_enable(omap->usbtll_p1_fck); ++ if (is_ehci_tll_mode(pdata->port_mode[1])) ++ clk_enable(omap->usbtll_p2_fck); ++ clk_disable(omap->utmi_p2_fck); ++ clk_disable(omap->utmi_p1_fck); + } + +- clk_disable(omap->utmi_p2_fck); +- clk_disable(omap->utmi_p1_fck); + clk_disable(omap->usbtll_ick); + clk_disable(omap->usbtll_fck); + clk_disable(omap->usbhost_fs_fck); + clk_disable(omap->usbhost_hs_fck); + clk_disable(omap->usbhost_ick); + ++ /* The gpio_free migh sleep; so unlock the spinlock */ ++ spin_unlock_irqrestore(&omap->lock, flags); ++ ++ if (pdata->ehci_data->phy_reset) { ++ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) ++ gpio_free(pdata->ehci_data->reset_gpio_port[0]); ++ ++ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) ++ gpio_free(pdata->ehci_data->reset_gpio_port[1]); ++ } ++ return; ++ + end_disble: + spin_unlock_irqrestore(&omap->lock, flags); + } +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch b/recipes/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch new file mode 100644 index 0000000000..380dd82a51 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch @@ -0,0 +1,50 @@ +From 89a903aca8fda3dcf1a6f9a424247e772afdd44e Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Sat, 14 May 2011 14:15:36 +0800 +Subject: [PATCH 02/13] mfd: Fix omap_usbhs_alloc_children error handling + +1. Return proper error if omap_usbhs_alloc_child fails +2. In the case of goto err_ehci, we should call platform_device_unregister(ehci) + instead of platform_device_put(ehci) because we have already added the + platform device to device hierarchy. + +Signed-off-by: Axel Lin +Signed-off-by: Axel Lin +Tested-by: Keshava Munegowda +Acked-by: Felipe Balbi +Signed-off-by: Samuel Ortiz +--- + drivers/mfd/omap-usb-host.c | 4 +++- + 1 files changed, 3 insertions(+), 1 deletions(-) + +diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c +index 55c5d47..1717144 100644 +--- a/drivers/mfd/omap-usb-host.c ++++ b/drivers/mfd/omap-usb-host.c +@@ -281,6 +281,7 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev) + + if (!ehci) { + dev_err(dev, "omap_usbhs_alloc_child failed\n"); ++ ret = -ENOMEM; + goto err_end; + } + +@@ -304,13 +305,14 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev) + sizeof(*ohci_data), dev); + if (!ohci) { + dev_err(dev, "omap_usbhs_alloc_child failed\n"); ++ ret = -ENOMEM; + goto err_ehci; + } + + return 0; + + err_ehci: +- platform_device_put(ehci); ++ platform_device_unregister(ehci); + + err_end: + return ret; +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch b/recipes/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch new file mode 100644 index 0000000000..b47deb2c1f --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch @@ -0,0 +1,245 @@ +From edc881f9c4897fab11542cd5c36a33b288f702be Mon Sep 17 00:00:00 2001 +From: Keshava Munegowda +Date: Sun, 22 May 2011 22:51:26 +0200 +Subject: [PATCH 03/13] mfd: Add omap-usbhs runtime PM support + +The usbhs core driver does not enable/disable the interface and +functional clocks; These clocks are handled by hwmod and runtime pm, +hence insted of the clock enable/disable, the runtime pm APIS are +used. however,the port clocks and tll clocks are handled +by the usbhs core. + +Signed-off-by: Keshava Munegowda +Signed-off-by: Samuel Ortiz +--- + drivers/mfd/omap-usb-host.c | 131 +++---------------------------------------- + 1 files changed, 9 insertions(+), 122 deletions(-) + +diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c +index 1717144..8552195 100644 +--- a/drivers/mfd/omap-usb-host.c ++++ b/drivers/mfd/omap-usb-host.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #define USBHS_DRIVER_NAME "usbhs-omap" + #define OMAP_EHCI_DEVICE "ehci-omap" +@@ -146,9 +147,6 @@ + + + struct usbhs_hcd_omap { +- struct clk *usbhost_ick; +- struct clk *usbhost_hs_fck; +- struct clk *usbhost_fs_fck; + struct clk *xclk60mhsp1_ck; + struct clk *xclk60mhsp2_ck; + struct clk *utmi_p1_fck; +@@ -158,8 +156,6 @@ struct usbhs_hcd_omap { + struct clk *usbhost_p2_fck; + struct clk *usbtll_p2_fck; + struct clk *init_60m_fclk; +- struct clk *usbtll_fck; +- struct clk *usbtll_ick; + + void __iomem *uhh_base; + void __iomem *tll_base; +@@ -353,46 +349,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev) + omap->platdata.ehci_data = pdata->ehci_data; + omap->platdata.ohci_data = pdata->ohci_data; + +- omap->usbhost_ick = clk_get(dev, "usbhost_ick"); +- if (IS_ERR(omap->usbhost_ick)) { +- ret = PTR_ERR(omap->usbhost_ick); +- dev_err(dev, "usbhost_ick failed error:%d\n", ret); +- goto err_end; +- } +- +- omap->usbhost_hs_fck = clk_get(dev, "hs_fck"); +- if (IS_ERR(omap->usbhost_hs_fck)) { +- ret = PTR_ERR(omap->usbhost_hs_fck); +- dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret); +- goto err_usbhost_ick; +- } +- +- omap->usbhost_fs_fck = clk_get(dev, "fs_fck"); +- if (IS_ERR(omap->usbhost_fs_fck)) { +- ret = PTR_ERR(omap->usbhost_fs_fck); +- dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret); +- goto err_usbhost_hs_fck; +- } +- +- omap->usbtll_fck = clk_get(dev, "usbtll_fck"); +- if (IS_ERR(omap->usbtll_fck)) { +- ret = PTR_ERR(omap->usbtll_fck); +- dev_err(dev, "usbtll_fck failed error:%d\n", ret); +- goto err_usbhost_fs_fck; +- } +- +- omap->usbtll_ick = clk_get(dev, "usbtll_ick"); +- if (IS_ERR(omap->usbtll_ick)) { +- ret = PTR_ERR(omap->usbtll_ick); +- dev_err(dev, "usbtll_ick failed error:%d\n", ret); +- goto err_usbtll_fck; +- } ++ pm_runtime_enable(&pdev->dev); + + omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); + if (IS_ERR(omap->utmi_p1_fck)) { + ret = PTR_ERR(omap->utmi_p1_fck); + dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); +- goto err_usbtll_ick; ++ goto err_end; + } + + omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); +@@ -522,22 +485,8 @@ err_xclk60mhsp1_ck: + err_utmi_p1_fck: + clk_put(omap->utmi_p1_fck); + +-err_usbtll_ick: +- clk_put(omap->usbtll_ick); +- +-err_usbtll_fck: +- clk_put(omap->usbtll_fck); +- +-err_usbhost_fs_fck: +- clk_put(omap->usbhost_fs_fck); +- +-err_usbhost_hs_fck: +- clk_put(omap->usbhost_hs_fck); +- +-err_usbhost_ick: +- clk_put(omap->usbhost_ick); +- + err_end: ++ pm_runtime_disable(&pdev->dev); + kfree(omap); + + end_probe: +@@ -571,11 +520,7 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev) + clk_put(omap->utmi_p2_fck); + clk_put(omap->xclk60mhsp1_ck); + clk_put(omap->utmi_p1_fck); +- clk_put(omap->usbtll_ick); +- clk_put(omap->usbtll_fck); +- clk_put(omap->usbhost_fs_fck); +- clk_put(omap->usbhost_hs_fck); +- clk_put(omap->usbhost_ick); ++ pm_runtime_disable(&pdev->dev); + kfree(omap); + + return 0; +@@ -695,7 +640,6 @@ static int usbhs_enable(struct device *dev) + struct usbhs_omap_platform_data *pdata = &omap->platdata; + unsigned long flags = 0; + int ret = 0; +- unsigned long timeout; + unsigned reg; + + dev_dbg(dev, "starting TI HSUSB Controller\n"); +@@ -708,11 +652,7 @@ static int usbhs_enable(struct device *dev) + if (omap->count > 0) + goto end_count; + +- clk_enable(omap->usbhost_ick); +- clk_enable(omap->usbhost_hs_fck); +- clk_enable(omap->usbhost_fs_fck); +- clk_enable(omap->usbtll_fck); +- clk_enable(omap->usbtll_ick); ++ pm_runtime_get_sync(dev); + + if (pdata->ehci_data->phy_reset) { + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) { +@@ -736,50 +676,6 @@ static int usbhs_enable(struct device *dev) + omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); + dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); + +- /* perform TLL soft reset, and wait until reset is complete */ +- usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, +- OMAP_USBTLL_SYSCONFIG_SOFTRESET); +- +- /* Wait for TLL reset to complete */ +- timeout = jiffies + msecs_to_jiffies(1000); +- while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) +- & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { +- cpu_relax(); +- +- if (time_after(jiffies, timeout)) { +- dev_dbg(dev, "operation timed out\n"); +- ret = -EINVAL; +- goto err_tll; +- } +- } +- +- dev_dbg(dev, "TLL RESET DONE\n"); +- +- /* (1<<3) = no idle mode only for initial debugging */ +- usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, +- OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | +- OMAP_USBTLL_SYSCONFIG_SIDLEMODE | +- OMAP_USBTLL_SYSCONFIG_AUTOIDLE); +- +- /* Put UHH in NoIdle/NoStandby mode */ +- reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG); +- if (is_omap_usbhs_rev1(omap)) { +- reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP +- | OMAP_UHH_SYSCONFIG_SIDLEMODE +- | OMAP_UHH_SYSCONFIG_CACTIVITY +- | OMAP_UHH_SYSCONFIG_MIDLEMODE); +- reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; +- +- +- } else if (is_omap_usbhs_rev2(omap)) { +- reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; +- reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; +- reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; +- reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; +- } +- +- usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); +- + reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); + /* setup ULPI bypass and burst configurations */ + reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN +@@ -919,6 +815,8 @@ end_count: + return 0; + + err_tll: ++ pm_runtime_put_sync(dev); ++ spin_unlock_irqrestore(&omap->lock, flags); + if (pdata->ehci_data->phy_reset) { + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) + gpio_free(pdata->ehci_data->reset_gpio_port[0]); +@@ -926,13 +824,6 @@ err_tll: + if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) + gpio_free(pdata->ehci_data->reset_gpio_port[1]); + } +- +- clk_disable(omap->usbtll_ick); +- clk_disable(omap->usbtll_fck); +- clk_disable(omap->usbhost_fs_fck); +- clk_disable(omap->usbhost_hs_fck); +- clk_disable(omap->usbhost_ick); +- spin_unlock_irqrestore(&omap->lock, flags); + return ret; + } + +@@ -1005,11 +896,7 @@ static void usbhs_disable(struct device *dev) + clk_disable(omap->utmi_p1_fck); + } + +- clk_disable(omap->usbtll_ick); +- clk_disable(omap->usbtll_fck); +- clk_disable(omap->usbhost_fs_fck); +- clk_disable(omap->usbhost_hs_fck); +- clk_disable(omap->usbhost_ick); ++ pm_runtime_put_sync(dev); + + /* The gpio_free migh sleep; so unlock the spinlock */ + spin_unlock_irqrestore(&omap->lock, flags); +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch b/recipes/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch new file mode 100644 index 0000000000..3d4d8a2d6d --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch @@ -0,0 +1,406 @@ +From 339b167f6f76707a2d6ae3a7c0b921b8278564af Mon Sep 17 00:00:00 2001 +From: Keshava Munegowda +Date: Wed, 1 Jun 2011 11:02:49 -0700 +Subject: [PATCH 04/13] arm: omap: usb: ehci and ohci hwmod structures for omap3 and omap4 + +Following 2 hwmod strcuture are added: +UHH hwmod of usbhs with uhh base address and +EHCI , OHCI irq and base addresses. +TLL hwmod of usbhs with the TLL base address and irq. + +Signed-off-by: Keshava Munegowda +--- + arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 184 ++++++++++++++++++++++++++++ + arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 153 +++++++++++++++++++++++ + 2 files changed, 337 insertions(+), 0 deletions(-) + +diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +index 909a84d..fe9a176 100644 +--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +@@ -84,6 +84,8 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod; + static struct omap_hwmod omap3xxx_mcbsp5_hwmod; + static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod; + static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod; ++static struct omap_hwmod omap34xx_usb_host_hs_hwmod; ++static struct omap_hwmod omap34xx_usb_tll_hs_hwmod; + + /* L3 -> L4_CORE interface */ + static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = { +@@ -3574,6 +3576,185 @@ static struct omap_hwmod omap3xxx_mmc3_hwmod = { + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + }; + ++/* ++ * 'usb_host_hs' class ++ * high-speed multi-port usb host controller ++ */ ++static struct omap_hwmod_ocp_if omap34xx_usb_host_hs__l3_main_2 = { ++ .master = &omap34xx_usb_host_hs_hwmod, ++ .slave = &omap3xxx_l3_main_hwmod, ++ .clk = "core_l3_ick", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_class_sysconfig omap34xx_usb_host_hs_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .syss_offs = 0x0014, ++ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | ++ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class omap34xx_usb_host_hs_hwmod_class = { ++ .name = "usbhs_uhh", ++ .sysc = &omap34xx_usb_host_hs_sysc, ++}; ++ ++static struct omap_hwmod_ocp_if *omap34xx_usb_host_hs_masters[] = { ++ &omap34xx_usb_host_hs__l3_main_2, ++}; ++ ++static struct omap_hwmod_irq_info omap34xx_usb_host_hs_irqs[] = { ++ { .name = "ohci-irq", .irq = 76 }, ++ { .name = "ehci-irq", .irq = 77 }, ++}; ++ ++static struct omap_hwmod_addr_space omap34xx_usb_host_hs_addrs[] = { ++ { ++ .name = "uhh", ++ .pa_start = 0x48064000, ++ .pa_end = 0x480643ff, ++ .flags = ADDR_TYPE_RT ++ }, ++ { ++ .name = "ohci", ++ .pa_start = 0x48064400, ++ .pa_end = 0x480647FF, ++ .flags = ADDR_MAP_ON_INIT ++ }, ++ { ++ .name = "ehci", ++ .pa_start = 0x48064800, ++ .pa_end = 0x48064CFF, ++ .flags = ADDR_MAP_ON_INIT ++ } ++}; ++ ++static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usb_host_hs = { ++ .master = &omap3xxx_l4_core_hwmod, ++ .slave = &omap34xx_usb_host_hs_hwmod, ++ .clk = "l4_ick", ++ .addr = omap34xx_usb_host_hs_addrs, ++ .addr_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_addrs), ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++static struct omap_hwmod_ocp_if omap34xx_f128m_cfg__usb_host_hs = { ++ .clk = "usbhost_120m_fck", ++ .user = OCP_USER_MPU, ++ .flags = OCPIF_SWSUP_IDLE, ++}; ++ ++static struct omap_hwmod_ocp_if omap34xx_f48m_cfg__usb_host_hs = { ++ .clk = "usbhost_48m_fck", ++ .user = OCP_USER_MPU, ++ .flags = OCPIF_SWSUP_IDLE, ++}; ++ ++static struct omap_hwmod_ocp_if *omap34xx_usb_host_hs_slaves[] = { ++ &omap34xx_l4_cfg__usb_host_hs, ++ &omap34xx_f128m_cfg__usb_host_hs, ++ &omap34xx_f48m_cfg__usb_host_hs, ++}; ++ ++static struct omap_hwmod omap34xx_usb_host_hs_hwmod = { ++ .name = "usbhs_uhh", ++ .class = &omap34xx_usb_host_hs_hwmod_class, ++ .mpu_irqs = omap34xx_usb_host_hs_irqs, ++ .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_irqs), ++ .main_clk = "usbhost_ick", ++ .prcm = { ++ .omap2 = { ++ .module_offs = OMAP3430ES2_USBHOST_MOD, ++ .prcm_reg_id = 1, ++ .module_bit = 0, ++ .idlest_reg_id = 1, ++ .idlest_idle_bit = 1, ++ .idlest_stdby_bit = 0, ++ }, ++ }, ++ .slaves = omap34xx_usb_host_hs_slaves, ++ .slaves_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_slaves), ++ .masters = omap34xx_usb_host_hs_masters, ++ .masters_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_masters), ++ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, ++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), ++}; ++ ++/* ++ * 'usb_tll_hs' class ++ * usb_tll_hs module is the adapter on the usb_host_hs ports ++ */ ++static struct omap_hwmod_class_sysconfig omap34xx_usb_tll_hs_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .syss_offs = 0x0014, ++ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class omap34xx_usb_tll_hs_hwmod_class = { ++ .name = "usbhs_tll", ++ .sysc = &omap34xx_usb_tll_hs_sysc, ++}; ++ ++static struct omap_hwmod_irq_info omap34xx_usb_tll_hs_irqs[] = { ++ { .name = "tll-irq", .irq = 78 }, ++}; ++ ++static struct omap_hwmod_addr_space omap34xx_usb_tll_hs_addrs[] = { ++ { ++ .name = "tll", ++ .pa_start = 0x48062000, ++ .pa_end = 0x48062fff, ++ .flags = ADDR_TYPE_RT ++ }, ++}; ++ ++static struct omap_hwmod_ocp_if omap34xx_f_cfg__usb_tll_hs = { ++ .clk = "usbtll_fck", ++ .user = OCP_USER_MPU, ++ .flags = OCPIF_SWSUP_IDLE, ++}; ++ ++static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usb_tll_hs = { ++ .master = &omap3xxx_l4_core_hwmod, ++ .slave = &omap34xx_usb_tll_hs_hwmod, ++ .clk = "l4_ick", ++ .addr = omap34xx_usb_tll_hs_addrs, ++ .addr_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_addrs), ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++static struct omap_hwmod_ocp_if *omap34xx_usb_tll_hs_slaves[] = { ++ &omap34xx_l4_cfg__usb_tll_hs, ++ &omap34xx_f_cfg__usb_tll_hs, ++}; ++ ++static struct omap_hwmod omap34xx_usb_tll_hs_hwmod = { ++ .name = "usbhs_tll", ++ .class = &omap34xx_usb_tll_hs_hwmod_class, ++ .mpu_irqs = omap34xx_usb_tll_hs_irqs, ++ .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_irqs), ++ .main_clk = "usbtll_ick", ++ .prcm = { ++ .omap2 = { ++ .module_offs = CORE_MOD, ++ .prcm_reg_id = 3, ++ .module_bit = 2, ++ .idlest_reg_id = 3, ++ .idlest_idle_bit = 2, ++ }, ++ }, ++ .slaves = omap34xx_usb_tll_hs_slaves, ++ .slaves_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_slaves), ++ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, ++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), ++}; ++ + static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { + &omap3xxx_l3_main_hwmod, + &omap3xxx_l4_core_hwmod, +@@ -3656,6 +3837,9 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { + /* usbotg for am35x */ + &am35xx_usbhsotg_hwmod, + ++ &omap34xx_usb_host_hs_hwmod, ++ &omap34xx_usb_tll_hs_hwmod, ++ + NULL, + }; + +diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +index abc548a..d7112b0 100644 +--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +@@ -66,6 +66,8 @@ static struct omap_hwmod omap44xx_mmc2_hwmod; + static struct omap_hwmod omap44xx_mpu_hwmod; + static struct omap_hwmod omap44xx_mpu_private_hwmod; + static struct omap_hwmod omap44xx_usb_otg_hs_hwmod; ++static struct omap_hwmod omap44xx_usb_host_hs_hwmod; ++static struct omap_hwmod omap44xx_usb_tll_hs_hwmod; + + /* + * Interconnects omap_hwmod structures +@@ -5027,6 +5029,155 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = { + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), + }; + ++/* ++ * 'usb_host_hs' class ++ * high-speed multi-port usb host controller ++ */ ++static struct omap_hwmod_ocp_if omap44xx_usb_host_hs__l3_main_2 = { ++ .master = &omap44xx_usb_host_hs_hwmod, ++ .slave = &omap44xx_l3_main_2_hwmod, ++ .clk = "l3_div_ck", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .syss_offs = 0x0014, ++ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | ++ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type2, ++}; ++ ++static struct omap_hwmod_class omap44xx_usb_host_hs_hwmod_class = { ++ .name = "usbhs_uhh", ++ .sysc = &omap44xx_usb_host_hs_sysc, ++}; ++ ++static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_masters[] = { ++ &omap44xx_usb_host_hs__l3_main_2, ++}; ++ ++static struct omap_hwmod_irq_info omap44xx_usb_host_hs_irqs[] = { ++ { .name = "ohci-irq", .irq = 76 + OMAP44XX_IRQ_GIC_START }, ++ { .name = "ehci-irq", .irq = 77 + OMAP44XX_IRQ_GIC_START }, ++}; ++ ++static struct omap_hwmod_addr_space omap44xx_usb_host_hs_addrs[] = { ++ { ++ .name = "uhh", ++ .pa_start = 0x4a064000, ++ .pa_end = 0x4a0647ff, ++ .flags = ADDR_TYPE_RT ++ }, ++ { ++ .name = "ohci", ++ .pa_start = 0x4A064800, ++ .pa_end = 0x4A064BFF, ++ .flags = ADDR_MAP_ON_INIT ++ }, ++ { ++ .name = "ehci", ++ .pa_start = 0x4A064C00, ++ .pa_end = 0x4A064FFF, ++ .flags = ADDR_MAP_ON_INIT ++ } ++}; ++ ++static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_host_hs = { ++ .master = &omap44xx_l4_cfg_hwmod, ++ .slave = &omap44xx_usb_host_hs_hwmod, ++ .clk = "l4_div_ck", ++ .addr = omap44xx_usb_host_hs_addrs, ++ .addr_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_addrs), ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_slaves[] = { ++ &omap44xx_l4_cfg__usb_host_hs, ++}; ++ ++static struct omap_hwmod omap44xx_usb_host_hs_hwmod = { ++ .name = "usbhs_uhh", ++ .class = &omap44xx_usb_host_hs_hwmod_class, ++ .mpu_irqs = omap44xx_usb_host_hs_irqs, ++ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_irqs), ++ .main_clk = "usb_host_hs_fck", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL, ++ }, ++ }, ++ .slaves = omap44xx_usb_host_hs_slaves, ++ .slaves_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_slaves), ++ .masters = omap44xx_usb_host_hs_masters, ++ .masters_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_masters), ++ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, ++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), ++}; ++ ++/* ++ * 'usb_tll_hs' class ++ * usb_tll_hs module is the adapter on the usb_host_hs ports ++ */ ++static struct omap_hwmod_class_sysconfig omap44xx_usb_tll_hs_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .syss_offs = 0x0014, ++ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class omap44xx_usb_tll_hs_hwmod_class = { ++ .name = "usbhs_tll", ++ .sysc = &omap44xx_usb_tll_hs_sysc, ++}; ++ ++static struct omap_hwmod_irq_info omap44xx_usb_tll_hs_irqs[] = { ++ { .name = "tll-irq", .irq = 78 + OMAP44XX_IRQ_GIC_START }, ++}; ++ ++static struct omap_hwmod_addr_space omap44xx_usb_tll_hs_addrs[] = { ++ { ++ .name = "tll", ++ .pa_start = 0x4a062000, ++ .pa_end = 0x4a063fff, ++ .flags = ADDR_TYPE_RT ++ }, ++}; ++ ++static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_tll_hs = { ++ .master = &omap44xx_l4_cfg_hwmod, ++ .slave = &omap44xx_usb_tll_hs_hwmod, ++ .clk = "l4_div_ck", ++ .addr = omap44xx_usb_tll_hs_addrs, ++ .addr_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_addrs), ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++static struct omap_hwmod_ocp_if *omap44xx_usb_tll_hs_slaves[] = { ++ &omap44xx_l4_cfg__usb_tll_hs, ++}; ++ ++static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = { ++ .name = "usbhs_tll", ++ .class = &omap44xx_usb_tll_hs_hwmod_class, ++ .mpu_irqs = omap44xx_usb_tll_hs_irqs, ++ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_irqs), ++ .main_clk = "usb_tll_hs_ick", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL, ++ }, ++ }, ++ .slaves = omap44xx_usb_tll_hs_slaves, ++ .slaves_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_slaves), ++ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, ++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), ++}; ++ + static __initdata struct omap_hwmod *omap44xx_hwmods[] = { + + /* dmm class */ +@@ -5173,6 +5324,8 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { + &omap44xx_wd_timer2_hwmod, + &omap44xx_wd_timer3_hwmod, + ++ &omap44xx_usb_host_hs_hwmod, ++ &omap44xx_usb_tll_hs_hwmod, + NULL, + }; + +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch b/recipes/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch new file mode 100644 index 0000000000..8e9a4ba48b --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch @@ -0,0 +1,160 @@ +From 70f5e1a0e6639710503a9ffb9008ddcd2bb3f06e Mon Sep 17 00:00:00 2001 +From: Keshava Munegowda +Date: Wed, 1 Jun 2011 11:02:54 -0700 +Subject: [PATCH 05/13] arm: omap: usb: register hwmods of usbhs + +The hwmod structure of uhh and tll are retrived +and registered with omap device + +Signed-off-by: Keshava Munegowda +--- + arch/arm/mach-omap2/usb-host.c | 99 ++++++++++++++-------------------------- + 1 files changed, 35 insertions(+), 64 deletions(-) + +diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c +index 89ae298..9d762c4 100644 +--- a/arch/arm/mach-omap2/usb-host.c ++++ b/arch/arm/mach-omap2/usb-host.c +@@ -28,51 +28,28 @@ + #include + #include + #include ++#include + + #include "mux.h" + + #ifdef CONFIG_MFD_OMAP_USB_HOST + +-#define OMAP_USBHS_DEVICE "usbhs-omap" +- +-static struct resource usbhs_resources[] = { +- { +- .name = "uhh", +- .flags = IORESOURCE_MEM, +- }, +- { +- .name = "tll", +- .flags = IORESOURCE_MEM, +- }, +- { +- .name = "ehci", +- .flags = IORESOURCE_MEM, +- }, +- { +- .name = "ehci-irq", +- .flags = IORESOURCE_IRQ, +- }, +- { +- .name = "ohci", +- .flags = IORESOURCE_MEM, +- }, +- { +- .name = "ohci-irq", +- .flags = IORESOURCE_IRQ, +- } +-}; +- +-static struct platform_device usbhs_device = { +- .name = OMAP_USBHS_DEVICE, +- .id = 0, +- .num_resources = ARRAY_SIZE(usbhs_resources), +- .resource = usbhs_resources, +-}; ++#define OMAP_USBHS_DEVICE "usbhs_omap" ++#define USBHS_UHH_HWMODNAME "usbhs_uhh" ++#define USBHS_TLL_HWMODNAME "usbhs_tll" + + static struct usbhs_omap_platform_data usbhs_data; + static struct ehci_hcd_omap_platform_data ehci_data; + static struct ohci_hcd_omap_platform_data ohci_data; + ++static struct omap_device_pm_latency omap_uhhtll_latency[] = { ++ { ++ .deactivate_func = omap_device_idle_hwmods, ++ .activate_func = omap_device_enable_hwmods, ++ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, ++ }, ++}; ++ + /* MUX settings for EHCI pins */ + /* + * setup_ehci_io_mux - initialize IO pad mux for USBHOST +@@ -508,7 +485,10 @@ static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode) + + void __init usbhs_init(const struct usbhs_omap_board_data *pdata) + { +- int i; ++ struct omap_hwmod *oh[2]; ++ struct omap_device *od; ++ int bus_id = -1; ++ int i; + + for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { + usbhs_data.port_mode[i] = pdata->port_mode[i]; +@@ -523,44 +503,35 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata) + usbhs_data.ohci_data = &ohci_data; + + if (cpu_is_omap34xx()) { +- usbhs_resources[0].start = OMAP34XX_UHH_CONFIG_BASE; +- usbhs_resources[0].end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1; +- usbhs_resources[1].start = OMAP34XX_USBTLL_BASE; +- usbhs_resources[1].end = OMAP34XX_USBTLL_BASE + SZ_4K - 1; +- usbhs_resources[2].start = OMAP34XX_EHCI_BASE; +- usbhs_resources[2].end = OMAP34XX_EHCI_BASE + SZ_1K - 1; +- usbhs_resources[3].start = INT_34XX_EHCI_IRQ; +- usbhs_resources[4].start = OMAP34XX_OHCI_BASE; +- usbhs_resources[4].end = OMAP34XX_OHCI_BASE + SZ_1K - 1; +- usbhs_resources[5].start = INT_34XX_OHCI_IRQ; + setup_ehci_io_mux(pdata->port_mode); + setup_ohci_io_mux(pdata->port_mode); + } else if (cpu_is_omap44xx()) { +- usbhs_resources[0].start = OMAP44XX_UHH_CONFIG_BASE; +- usbhs_resources[0].end = OMAP44XX_UHH_CONFIG_BASE + SZ_1K - 1; +- usbhs_resources[1].start = OMAP44XX_USBTLL_BASE; +- usbhs_resources[1].end = OMAP44XX_USBTLL_BASE + SZ_4K - 1; +- usbhs_resources[2].start = OMAP44XX_HSUSB_EHCI_BASE; +- usbhs_resources[2].end = OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1; +- usbhs_resources[3].start = OMAP44XX_IRQ_EHCI; +- usbhs_resources[4].start = OMAP44XX_HSUSB_OHCI_BASE; +- usbhs_resources[4].end = OMAP44XX_HSUSB_OHCI_BASE + SZ_1K - 1; +- usbhs_resources[5].start = OMAP44XX_IRQ_OHCI; + setup_4430ehci_io_mux(pdata->port_mode); + setup_4430ohci_io_mux(pdata->port_mode); + } + +- if (platform_device_add_data(&usbhs_device, +- &usbhs_data, sizeof(usbhs_data)) < 0) { +- printk(KERN_ERR "USBHS platform_device_add_data failed\n"); +- goto init_end; ++ oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME); ++ if (!oh[0]) { ++ pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME); ++ return; + } + +- if (platform_device_register(&usbhs_device) < 0) +- printk(KERN_ERR "USBHS platform_device_register failed\n"); ++ oh[1] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME); ++ if (!oh[1]) { ++ pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME); ++ return; ++ } + +-init_end: +- return; ++ od = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 2, ++ (void *)&usbhs_data, sizeof(usbhs_data), ++ omap_uhhtll_latency, ++ ARRAY_SIZE(omap_uhhtll_latency), false); ++ ++ if (IS_ERR(od)) { ++ pr_err("Could not build hwmod devices %s, %s\n", ++ USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME); ++ return; ++ } + } + + #else +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch b/recipes/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch new file mode 100644 index 0000000000..c0ac58bfb2 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch @@ -0,0 +1,123 @@ +From 64bc651bb56435e4cd86d2ebfa4f301abdbac6e5 Mon Sep 17 00:00:00 2001 +From: Keshava Munegowda +Date: Wed, 1 Jun 2011 11:02:58 -0700 +Subject: [PATCH 06/13] arm: omap: usb: device name change for the clk names of usbhs + +device name usbhs clocks are changed from +usbhs-omap.0 to usbhs_omap; this is because +in the hwmod registration the device name is set +as usbhs_omap + +Signed-off-by: Keshava Munegowda +--- + arch/arm/mach-omap2/clock3xxx_data.c | 28 ++++++++++++++-------------- + arch/arm/mach-omap2/clock44xx_data.c | 10 +++++----- + drivers/mfd/omap-usb-host.c | 2 +- + 3 files changed, 20 insertions(+), 20 deletions(-) + +diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c +index 75b119b..fabe482 100644 +--- a/arch/arm/mach-omap2/clock3xxx_data.c ++++ b/arch/arm/mach-omap2/clock3xxx_data.c +@@ -3285,7 +3285,7 @@ static struct omap_clk omap3xxx_clks[] = { + CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), +- CLK("usbhs-omap.0", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), ++ CLK("usbhs_omap", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX), + CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX), + CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX), +@@ -3321,7 +3321,7 @@ static struct omap_clk omap3xxx_clks[] = { + CLK(NULL, "pka_ick", &pka_ick, CK_34XX | CK_36XX), + CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX), + CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), +- CLK("usbhs-omap.0", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), ++ CLK("usbhs_omap", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX), + CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX), +@@ -3367,20 +3367,20 @@ static struct omap_clk omap3xxx_clks[] = { + CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX), + CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX), + CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), +- CLK("usbhs-omap.0", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), ++ CLK("usbhs_omap", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), +- CLK("usbhs-omap.0", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), ++ CLK("usbhs_omap", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), +- CLK("usbhs-omap.0", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), +- CLK("usbhs-omap.0", "utmi_p1_gfclk", &dummy_ck, CK_3XXX), +- CLK("usbhs-omap.0", "utmi_p2_gfclk", &dummy_ck, CK_3XXX), +- CLK("usbhs-omap.0", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), +- CLK("usbhs-omap.0", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), +- CLK("usbhs-omap.0", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), +- CLK("usbhs-omap.0", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), +- CLK("usbhs-omap.0", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX), +- CLK("usbhs-omap.0", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX), +- CLK("usbhs-omap.0", "init_60m_fclk", &dummy_ck, CK_3XXX), ++ CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), ++ CLK("usbhs_omap", "utmi_p1_gfclk", &dummy_ck, CK_3XXX), ++ CLK("usbhs_omap", "utmi_p2_gfclk", &dummy_ck, CK_3XXX), ++ CLK("usbhs_omap", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), ++ CLK("usbhs_omap", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), ++ CLK("usbhs_omap", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), ++ CLK("usbhs_omap", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), ++ CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX), ++ CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX), ++ CLK("usbhs_omap", "init_60m_fclk", &dummy_ck, CK_3XXX), + CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX), + CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX), + CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX), +diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c +index 8c96567..34e91eb 100644 +--- a/arch/arm/mach-omap2/clock44xx_data.c ++++ b/arch/arm/mach-omap2/clock44xx_data.c +@@ -3205,7 +3205,7 @@ static struct omap_clk omap44xx_clks[] = { + CLK(NULL, "uart3_fck", &uart3_fck, CK_443X), + CLK(NULL, "uart4_fck", &uart4_fck, CK_443X), + CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X), +- CLK("usbhs-omap.0", "fs_fck", &usb_host_fs_fck, CK_443X), ++ CLK("usbhs_omap", "fs_fck", &usb_host_fs_fck, CK_443X), + CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X), + CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X), + CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_443X), +@@ -3217,8 +3217,8 @@ static struct omap_clk omap44xx_clks[] = { + CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X), + CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X), + CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_443X), +- CLK("usbhs-omap.0", "hs_fck", &usb_host_hs_fck, CK_443X), +- CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X), ++ CLK("usbhs_omap", "hs_fck", &usb_host_hs_fck, CK_443X), ++ CLK("usbhs_omap", "usbhost_ick", &dummy_ck, CK_443X), + CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X), + CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X), + CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_443X), +@@ -3227,8 +3227,8 @@ static struct omap_clk omap44xx_clks[] = { + CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X), + CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X), + CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_443X), +- CLK("usbhs-omap.0", "usbtll_ick", &usb_tll_hs_ick, CK_443X), +- CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X), ++ CLK("usbhs_omap", "usbtll_ick", &usb_tll_hs_ick, CK_443X), ++ CLK("usbhs_omap", "usbtll_fck", &dummy_ck, CK_443X), + CLK(NULL, "usim_ck", &usim_ck, CK_443X), + CLK(NULL, "usim_fclk", &usim_fclk, CK_443X), + CLK(NULL, "usim_fck", &usim_fck, CK_443X), +diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c +index 8552195..43de12a 100644 +--- a/drivers/mfd/omap-usb-host.c ++++ b/drivers/mfd/omap-usb-host.c +@@ -28,7 +28,7 @@ + #include + #include + +-#define USBHS_DRIVER_NAME "usbhs-omap" ++#define USBHS_DRIVER_NAME "usbhs_omap" + #define OMAP_EHCI_DEVICE "ehci-omap" + #define OMAP_OHCI_DEVICE "ohci-omap3" + +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch b/recipes/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch new file mode 100644 index 0000000000..94d5f5917f --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch @@ -0,0 +1,165 @@ +From bf583f2924fd9b2f0356cbd0bbfd58c48d98ef15 Mon Sep 17 00:00:00 2001 +From: Keshava Munegowda +Date: Wed, 1 Jun 2011 11:03:03 -0700 +Subject: [PATCH 07/13] mfd: global Suspend and resume support of ehci and ohci + +The global suspend and resume functions for usbhs core driver +are implemented.These routine are called when the global suspend +and resume occurs. Before calling these functions, the +bus suspend and resume of ehci and ohci drivers are called +from runtime pm. + +Signed-off-by: Keshava Munegowda +--- + drivers/mfd/omap-usb-host.c | 103 +++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 103 insertions(+), 0 deletions(-) + +diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c +index 43de12a..32d19e2 100644 +--- a/drivers/mfd/omap-usb-host.c ++++ b/drivers/mfd/omap-usb-host.c +@@ -146,6 +146,10 @@ + #define is_ehci_hsic_mode(x) (x == OMAP_EHCI_PORT_MODE_HSIC) + + ++/* USBHS state bits */ ++#define OMAP_USBHS_INIT 0 ++#define OMAP_USBHS_SUSPEND 4 ++ + struct usbhs_hcd_omap { + struct clk *xclk60mhsp1_ck; + struct clk *xclk60mhsp2_ck; +@@ -165,6 +169,7 @@ struct usbhs_hcd_omap { + u32 usbhs_rev; + spinlock_t lock; + int count; ++ unsigned long state; + }; + /*-------------------------------------------------------------------------*/ + +@@ -809,6 +814,8 @@ static int usbhs_enable(struct device *dev) + (pdata->ehci_data->reset_gpio_port[1], 1); + } + ++ set_bit(OMAP_USBHS_INIT, &omap->state); ++ + end_count: + omap->count++; + spin_unlock_irqrestore(&omap->lock, flags); +@@ -897,6 +904,7 @@ static void usbhs_disable(struct device *dev) + } + + pm_runtime_put_sync(dev); ++ clear_bit(OMAP_USBHS_INIT, &omap->state); + + /* The gpio_free migh sleep; so unlock the spinlock */ + spin_unlock_irqrestore(&omap->lock, flags); +@@ -926,10 +934,105 @@ void omap_usbhs_disable(struct device *dev) + } + EXPORT_SYMBOL_GPL(omap_usbhs_disable); + ++#ifdef CONFIG_PM ++ ++static int usbhs_resume(struct device *dev) ++{ ++ struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); ++ struct usbhs_omap_platform_data *pdata = &omap->platdata; ++ unsigned long flags = 0; ++ ++ dev_dbg(dev, "Resuming TI HSUSB Controller\n"); ++ ++ if (!pdata) { ++ dev_dbg(dev, "missing platform_data\n"); ++ return -ENODEV; ++ } ++ ++ spin_lock_irqsave(&omap->lock, flags); ++ ++ if (!test_bit(OMAP_USBHS_INIT, &omap->state) || ++ !test_bit(OMAP_USBHS_SUSPEND, &omap->state)) ++ goto end_resume; ++ ++ pm_runtime_get_sync(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); ++ } ++ if (is_ehci_tll_mode(pdata->port_mode[1])) { ++ clk_enable(omap->usbhost_p2_fck); ++ clk_enable(omap->usbtll_p2_fck); ++ } ++ clk_enable(omap->utmi_p1_fck); ++ clk_enable(omap->utmi_p2_fck); ++ } ++ clear_bit(OMAP_USBHS_SUSPEND, &omap->state); ++ ++end_resume: ++ spin_unlock_irqrestore(&omap->lock, flags); ++ return 0; ++} ++ ++ ++static int usbhs_suspend(struct device *dev) ++{ ++ struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); ++ struct usbhs_omap_platform_data *pdata = &omap->platdata; ++ unsigned long flags = 0; ++ ++ dev_dbg(dev, "Suspending TI HSUSB Controller\n"); ++ ++ if (!pdata) { ++ dev_dbg(dev, "missing platform_data\n"); ++ return -ENODEV; ++ } ++ ++ spin_lock_irqsave(&omap->lock, flags); ++ ++ if (!test_bit(OMAP_USBHS_INIT, &omap->state) || ++ test_bit(OMAP_USBHS_SUSPEND, &omap->state)) ++ goto end_suspend; ++ ++ 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); ++ } ++ if (is_ehci_tll_mode(pdata->port_mode[1])) { ++ clk_disable(omap->usbhost_p2_fck); ++ clk_disable(omap->usbtll_p2_fck); ++ } ++ clk_disable(omap->utmi_p2_fck); ++ clk_disable(omap->utmi_p1_fck); ++ } ++ ++ set_bit(OMAP_USBHS_SUSPEND, &omap->state); ++ pm_runtime_put_sync(dev); ++ ++end_suspend: ++ spin_unlock_irqrestore(&omap->lock, flags); ++ return 0; ++} ++ ++ ++static const struct dev_pm_ops usbhsomap_dev_pm_ops = { ++ .suspend = usbhs_suspend, ++ .resume = usbhs_resume, ++}; ++ ++#define USBHS_OMAP_DEV_PM_OPS (&usbhsomap_dev_pm_ops) ++#else ++#define USBHS_OMAP_DEV_PM_OPS NULL ++#endif ++ + static struct platform_driver usbhs_omap_driver = { + .driver = { + .name = (char *)usbhs_driver_name, + .owner = THIS_MODULE, ++ .pm = USBHS_OMAP_DEV_PM_OPS, + }, + .remove = __exit_p(usbhs_omap_remove), + }; +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch b/recipes/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch new file mode 100644 index 0000000000..e3de467269 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch @@ -0,0 +1,36 @@ +From 1f2e639755b920398d6592775e0e31f7fb1ca955 Mon Sep 17 00:00:00 2001 +From: Lesly A M +Date: Wed, 1 Jun 2011 14:56:38 -0700 +Subject: [PATCH 08/13] MFD: TWL4030: Correct the warning print during script loading + +Correcting the if condition check for printing the warning, +if wakeup script is not updated before updating the sleep script. + +Since the flag 'order' is set to '1' while updating the wakeup script for P1P2, +the condition checking for printing the warning should be if(!order) +(ie: print the warning if wakeup script is not updated before updating the sleep script) + +Signed-off-by: Lesly A M +Cc: Nishanth Menon +Cc: David Derrick +Cc: Samuel Ortiz +--- + drivers/mfd/twl4030-power.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c +index 2c0d4d1..8373d79 100644 +--- a/drivers/mfd/twl4030-power.c ++++ b/drivers/mfd/twl4030-power.c +@@ -448,7 +448,7 @@ static int __init load_twl4030_script(struct twl4030_script *tscript, + goto out; + } + if (tscript->flags & TWL4030_SLEEP_SCRIPT) { +- if (order) ++ if (!order) + pr_warning("TWL4030: Bad order of scripts (sleep "\ + "script before wakeup) Leads to boot"\ + "failure on some boards\n"); +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch b/recipes/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch new file mode 100644 index 0000000000..6be454aad8 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch @@ -0,0 +1,61 @@ +From ea9acebfe2d3ca8fb3969eaf327665632142b85d Mon Sep 17 00:00:00 2001 +From: Lesly A M +Date: Wed, 1 Jun 2011 14:56:45 -0700 +Subject: [PATCH 09/13] MFD: TWL4030: Modifying the macro name Main_Ref to all caps + +Modifying the macro name Main_Ref to all caps(MAIN_REF). + +Suggested by Nishanth Menon + +Signed-off-by: Lesly A M +Cc: Nishanth Menon +Cc: David Derrick +Cc: Samuel Ortiz +--- + arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +- + drivers/mfd/twl4030-power.c | 2 +- + include/linux/i2c/twl.h | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c +index bbcb677..01ee0a1 100644 +--- a/arch/arm/mach-omap2/board-rx51-peripherals.c ++++ b/arch/arm/mach-omap2/board-rx51-peripherals.c +@@ -730,7 +730,7 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = { + { .resource = RES_RESET, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, +- { .resource = RES_Main_Ref, .devgroup = -1, ++ { .resource = RES_MAIN_REF, .devgroup = -1, + .type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1 + }, + { 0, 0}, +diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c +index 8373d79..8162e43 100644 +--- a/drivers/mfd/twl4030-power.c ++++ b/drivers/mfd/twl4030-power.c +@@ -120,7 +120,7 @@ static u8 res_config_addrs[] = { + [RES_HFCLKOUT] = 0x8b, + [RES_32KCLKOUT] = 0x8e, + [RES_RESET] = 0x91, +- [RES_Main_Ref] = 0x94, ++ [RES_MAIN_REF] = 0x94, + }; + + static int __init twl4030_write_script_byte(u8 address, u8 byte) +diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h +index cbbf3b3..aee3a22 100644 +--- a/include/linux/i2c/twl.h ++++ b/include/linux/i2c/twl.h +@@ -502,7 +502,7 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) + #define RES_32KCLKOUT 26 + #define RES_RESET 27 + /* Power Reference */ +-#define RES_Main_Ref 28 ++#define RES_MAIN_REF 28 + + #define TOTAL_RESOURCES 28 + /* +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch b/recipes/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch new file mode 100644 index 0000000000..84e1ae7ec1 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch @@ -0,0 +1,705 @@ +From 0b29e1f61b85dd2d04f035088b70dc287d15b9f0 Mon Sep 17 00:00:00 2001 +From: Lesly A M +Date: Wed, 1 Jun 2011 14:56:49 -0700 +Subject: [PATCH 10/13] MFD: TWL4030: power scripts for OMAP3 boards + +Power bus message sequence for TWL4030 to enter sleep/wakeup/warm_reset. + +TWL4030 power scripts which can be used by different OMAP3 boards +with the power companion chip (TWL4030 series). + +The twl4030 generic script can be used by any board file to update +the power data in twl4030_platform_data. + +Since the TWL4030 power script has dependency with APIs in twl4030-power.c +removing the __init for these APIs. + +For more information please see: + http://omapedia.org/wiki/TWL4030_power_scripts + +Signed-off-by: Lesly A M +Cc: Nishanth Menon +Cc: David Derrick +Cc: Samuel Ortiz +--- + arch/arm/configs/omap2plus_defconfig | 1 + + arch/arm/mach-omap2/devices.c | 15 ++ + drivers/mfd/Kconfig | 11 + + drivers/mfd/Makefile | 1 + + drivers/mfd/twl4030-power.c | 31 ++-- + drivers/mfd/twl4030-script-omap.c | 373 ++++++++++++++++++++++++++++++++++ + include/linux/i2c/twl.h | 41 ++++- + 7 files changed, 454 insertions(+), 19 deletions(-) + create mode 100644 drivers/mfd/twl4030-script-omap.c + +diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig +index 076db52..d9b9858 100644 +--- a/arch/arm/configs/omap2plus_defconfig ++++ b/arch/arm/configs/omap2plus_defconfig +@@ -184,6 +184,7 @@ CONFIG_TWL4030_WATCHDOG=y + CONFIG_MENELAUS=y + CONFIG_TWL4030_CORE=y + CONFIG_TWL4030_POWER=y ++CONFIG_TWL4030_SCRIPT=m + CONFIG_REGULATOR=y + CONFIG_REGULATOR_TWL4030=y + CONFIG_REGULATOR_TPS65023=y +diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c +index 7b85585..7653329 100644 +--- a/arch/arm/mach-omap2/devices.c ++++ b/arch/arm/mach-omap2/devices.c +@@ -329,6 +329,20 @@ static void omap_init_audio(void) + static inline void omap_init_audio(void) {} + #endif + ++#ifdef CONFIG_ARCH_OMAP3 ++static struct platform_device omap_twl4030_script = { ++ .name = "twl4030_script", ++ .id = -1, ++}; ++ ++static void omap_init_twl4030_script(void) ++{ ++ platform_device_register(&omap_twl4030_script); ++} ++#else ++static inline void omap_init_twl4030_script(void) {} ++#endif ++ + #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE) + + #include +@@ -691,6 +705,7 @@ static int __init omap2_init_devices(void) + omap_init_sham(); + omap_init_aes(); + omap_init_vout(); ++ omap_init_twl4030_script(); + + return 0; + } +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index fe2370a..ea25d93 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -204,6 +204,17 @@ config TWL4030_POWER + and load scripts controlling which resources are switched off/on + or reset when a sleep, wakeup or warm reset event occurs. + ++config TWL4030_SCRIPT ++ tristate "Support TWL4030 script for OMAP3 boards" ++ depends on TWL4030_CORE && TWL4030_POWER ++ help ++ Say yes here if you want to use the twl4030 power scripts ++ for OMAP3 boards. Power bus message sequence for ++ TWL4030 to enter sleep/wakeup/warm_reset. ++ ++ TWL4030 power scripts which can be used by different ++ OMAP3 boards with the power companion chip (TWL4030 series). ++ + config TWL4030_CODEC + bool + depends on TWL4030_CORE +diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile +index 419caa9..53ada21 100644 +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -42,6 +42,7 @@ obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o + obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o + obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o + obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o ++obj-$(CONFIG_TWL4030_SCRIPT) += twl4030-script-omap.o + + obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o + +diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c +index 8162e43..91d5bc8 100644 +--- a/drivers/mfd/twl4030-power.c ++++ b/drivers/mfd/twl4030-power.c +@@ -123,7 +123,7 @@ static u8 res_config_addrs[] = { + [RES_MAIN_REF] = 0x94, + }; + +-static int __init twl4030_write_script_byte(u8 address, u8 byte) ++static int twl4030_write_script_byte(u8 address, u8 byte) + { + int err; + +@@ -137,7 +137,7 @@ out: + return err; + } + +-static int __init twl4030_write_script_ins(u8 address, u16 pmb_message, ++static int twl4030_write_script_ins(u8 address, u16 pmb_message, + u8 delay, u8 next) + { + int err; +@@ -157,7 +157,7 @@ out: + return err; + } + +-static int __init twl4030_write_script(u8 address, struct twl4030_ins *script, ++static int twl4030_write_script(u8 address, struct twl4030_ins *script, + int len) + { + int err; +@@ -182,7 +182,7 @@ static int __init twl4030_write_script(u8 address, struct twl4030_ins *script, + return err; + } + +-static int __init twl4030_config_wakeup3_sequence(u8 address) ++static int twl4030_config_wakeup3_sequence(u8 address) + { + int err; + u8 data; +@@ -207,7 +207,7 @@ out: + return err; + } + +-static int __init twl4030_config_wakeup12_sequence(u8 address) ++static int twl4030_config_wakeup12_sequence(u8 address) + { + int err = 0; + u8 data; +@@ -261,7 +261,7 @@ out: + return err; + } + +-static int __init twl4030_config_sleep_sequence(u8 address) ++static int twl4030_config_sleep_sequence(u8 address) + { + int err; + +@@ -275,7 +275,7 @@ static int __init twl4030_config_sleep_sequence(u8 address) + return err; + } + +-static int __init twl4030_config_warmreset_sequence(u8 address) ++static int twl4030_config_warmreset_sequence(u8 address) + { + int err; + u8 rd_data; +@@ -323,7 +323,7 @@ out: + return err; + } + +-static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) ++static int twl4030_configure_resource(struct twl4030_resconfig *rconfig) + { + int rconfig_addr; + int err; +@@ -415,7 +415,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) + return 0; + } + +-static int __init load_twl4030_script(struct twl4030_script *tscript, ++static int load_twl4030_script(struct twl4030_script *tscript, + u8 address) + { + int err; +@@ -510,8 +510,9 @@ int twl4030_remove_script(u8 flags) + + return err; + } ++EXPORT_SYMBOL_GPL(twl4030_remove_script); + +-void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) ++int twl4030_power_init(struct twl4030_power_data *twl4030_scripts) + { + int err = 0; + int i; +@@ -529,7 +530,6 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) + TWL4030_PM_MASTER_PROTECT_KEY); + if (err) + goto unlock; +- + for (i = 0; i < twl4030_scripts->num; i++) { + err = load_twl4030_script(twl4030_scripts->scripts[i], address); + if (err) +@@ -552,18 +552,19 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) + TWL4030_PM_MASTER_PROTECT_KEY); + if (err) + pr_err("TWL4030 Unable to relock registers\n"); +- return; ++ return err; + + unlock: + if (err) + pr_err("TWL4030 Unable to unlock registers\n"); +- return; ++ return err; + load: + if (err) + pr_err("TWL4030 failed to load scripts\n"); +- return; ++ return err; + resource: + if (err) + pr_err("TWL4030 failed to configure resource\n"); +- return; ++ return err; + } ++EXPORT_SYMBOL_GPL(twl4030_power_init); +diff --git a/drivers/mfd/twl4030-script-omap.c b/drivers/mfd/twl4030-script-omap.c +new file mode 100644 +index 0000000..867a442 +--- /dev/null ++++ b/drivers/mfd/twl4030-script-omap.c +@@ -0,0 +1,373 @@ ++/* ++ * OMAP power script for PMIC TWL4030 ++ * ++ * Author: Lesly A M ++ * ++ * Copyright (C) 2010 Texas Instruments, Inc. ++ * Lesly A M ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++/* ++ * power management signal connections for OMAP3430 with TWL5030 ++ * ++ * TWL5030 OMAP3430 ++ * ______________________ _____________________ ++ * | | | | ++ * | (P1) NSLEEP1|<----------|SYS_OFFMODE | ++ * | NRESWARM|<----------|NWARMRESET | ++ * | (P2) NSLEEP2|---| | | ++ * | | === | | ++ * | | - | | ++ * | | | | ++ * | VDD1 |---------->| VDD1 | ++ * | VDD2 |---------->| VDD2 | ++ * | VIO |---------->| VDDS | ++ * ________ | VAUX1 | | | ++ * | | | ... | | | ++ * | ENABLE|<--------|CLKEN CLKREQ|<----------|SYS_CLKREQ | ++ * | CLKOUT|-------->|HFCLKIN (P3) HFCLKOUT|---------->|XTALIN | ++ * |________| |______________________| |_____________________| ++ * ++ * ++ * Signal descriptions: ++ * ++ * SYS_OFFMODE - OMAP drives this signal low only when the OMAP is in the ++ * OFF idle mode. It is driven high when a wake up event is detected. ++ * This signal should control the P1 device group in the PMIC. ++ * ++ * SYS_CLKREQ - OMAP should drive this signal low when the OMAP goes into ++ * any idle mode. This signal should control the P3 device group ++ * in the PMIC. It is used to notify PMIC when XTALIN is no longer needed. ++ * ++ * NSLEEP1(P1) - When this signal goes low the P1 sleep sequence is executed ++ * in the PMIC turning off certain resources. When this signal goes high ++ * the P1 active sequence is executed turning back on certain resources. ++ * ++ * NSLEEP2(P2) - This signal controls the P2 device group of the PMIC. ++ * It is not used in this setup and should be tied to ground. ++ * This can be used for connecting a different processor or MODEM chip. ++ * ++ * CLKREQ(P3) - When this signal goes low the P3 sleep sequence is executed ++ * in the PMIC turning off HFCLKOUT. When this signal goes high ++ * the P3 active sequence is executed turning back on HFCLKOUT and other ++ * resources. ++ * ++ * CLKEN - Enable signal for oscillator. Should only go low when OMAP is ++ * in the OFF idle mode due to long oscillator startup times. ++ * ++ * HFCLKIN - Oscillator output clock into PMIC. ++ * ++ * HFCLKOUT - System clock output from PMIC to OMAP. ++ * ++ * XTALIN - OMAP system clock input(HFCLKOUT). ++ */ ++ ++/* ++ * Recommended sleep and active sequences for TWL5030 when connected to OMAP3 ++ * ++ * WARNING: If the board is using NSLEEP2(P2), should modify this script and ++ * setuptime values accordingly. ++ * ++ * Chip Retention/Off (using i2c for scaling voltage): ++ * When OMAP de-assert the SYS_CLKREQ signal, only HFCLKOUT is affected ++ * since it is the only resource assigned to P3 only. ++ * ++ * Sysoff (using sys_off signal): ++ * When OMAP de-assert the SYS_OFFMODE signal A2S(active to sleep sequence) ++ * on the PMIC is executed. This will put resources of TYPE2=1 and TYPE2=2 ++ * into sleep. At this point only resources assigned to P1 only will be ++ * affected (VDD1, VDD2 & VPLL1). ++ * ++ * Next the OMAP will lower SYS_CLKREQ which will allow the A2S sequence ++ * in PMIC to execute again. This will put resources of TYPE2=1 and TYPE2=2 ++ * into sleep but will affect resources that are assigned to P3(HFCLKOUT) ++ * only or assigned to P1 and P3. ++ * ++ * On wakeup event OMAP goes active and pulls the SYS_CLKREQ high, ++ * which will execute the P3 S2A sequence on the PMIC. This will turn on ++ * resources assigned to P3 or assigned to P1 and P3 and of TYPE2=2. ++ * ++ * Next the OMAP will wait the PRM_VOLTOFFSET time and then de-assert ++ * the SYS_OFFMODE pin allowing the PMIC to execute the P1 S2A active ++ * sequence. This will turn on resources assigned to P1 or assigned to ++ * P1 and P3 and of TYPE2=1. ++ * ++ * Timing diagram for OMAP wakeup from OFFMODE using sys_off signal ++ * _____________________________________________________________ ++ * OMAP active __/ ++ * |<--------------------PRM_CLKSETP-------------------->| ++ * ______________________________________________________ ++ * SYS_CLKREQ _________/ ++ * ___________________________________________________ ++ * CLKEN ____________/ ++ * ++ * HFCLKIN _______________________________________________///////////////// ++ * ++ * HFCLKOUT __________________________________________________////////////// ++ * |<---PRM_VOLTOFFSET-->| ++ * ________________________________ ++ * SYS_OFFMODE _______________________________/ ++ * |<--------PRM_VOLTSETUP2------->| ++ * ___________ ++ * VPLL1 ____________________________________________________/ ++ * __ ++ * VDD1 _____________________________________________________________/ ++ * __ ++ * VDD2 _____________________________________________________________/ ++ * ++ * Other resources which are not handled by this script should be ++ * controlled by the respective drivers using them (VAUX1, VAUX2, VAUX3, ++ * VAUX4, VMMC1, VMMC2, VPLL2, VSIM, VDAC, VUSB1V5, VUSB1V8 & VUSB3V1). ++ * ++ * More info: ++ * http://omapedia.org/wiki/TWL4030_power_scripts ++ */ ++ ++/** ++ * DOC: Sleep to active sequence for P1/P2 ++ * ++ * Sequence to control the TWL4030 Power resources, ++ * when the system wakeup from sleep. ++ * Executed upon P1_P2 transition for wakeup ++ * (sys_offmode signal de-asserted on OMAP). ++ */ ++static struct twl4030_ins wakeup_p12_seq[] __initdata = { ++ /* ++ * Broadcast message to put resources to active ++ * ++ * Since we are not using TYPE, resources which have TYPE2 configured ++ * as 1 will be targeted (VPLL1, VDD1, VDD2, REGEN, NRES_PWRON, SYSEN). ++ */ ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, ++ RES_STATE_ACTIVE), 2}, ++}; ++ ++static struct twl4030_script wakeup_p12_script __initdata = { ++ .script = wakeup_p12_seq, ++ .size = ARRAY_SIZE(wakeup_p12_seq), ++ .flags = TWL4030_WAKEUP12_SCRIPT, ++}; ++ ++/** ++ * DOC: Sleep to active sequence for P3 ++ * ++ * Sequence to control the TWL4030 Power resources, ++ * when the system wakeup from sleep. ++ * Executed upon P3 transition for wakeup ++ * (clkreq signal asserted on OMAP). ++ */ ++static struct twl4030_ins wakeup_p3_seq[] __initdata = { ++ /* ++ * Broadcast message to put resources to active ++ * ++ * Since we are not using TYPE, resources which have TYPE2 configured ++ * as 2 will be targeted ++ * (VINTANA1, VINTANA2, VINTDIG, VIO, CLKEN, HFCLKOUT). ++ */ ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, ++ RES_STATE_ACTIVE), 2}, ++}; ++ ++static struct twl4030_script wakeup_p3_script __initdata = { ++ .script = wakeup_p3_seq, ++ .size = ARRAY_SIZE(wakeup_p3_seq), ++ .flags = TWL4030_WAKEUP3_SCRIPT, ++}; ++ ++/** ++ * DOC: Active to sleep sequence for P1/P2/P3 ++ * ++ * Sequence to control the TWL4030 Power resources, ++ * when the system goes into sleep. ++ * Executed upon P1_P2/P3 transition for sleep. ++ * (sys_offmode signal asserted/clkreq de-asserted on OMAP). ++ */ ++static struct twl4030_ins sleep_on_seq[] __initdata = { ++ /* Broadcast message to put res to sleep (TYPE2 = 1, 2) */ ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, ++ RES_STATE_SLEEP), 2}, ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, ++ RES_STATE_SLEEP), 2}, ++}; ++ ++static struct twl4030_script sleep_on_script __initdata = { ++ .script = sleep_on_seq, ++ .size = ARRAY_SIZE(sleep_on_seq), ++ .flags = TWL4030_SLEEP_SCRIPT, ++}; ++ ++/** ++ * DOC: Warm reset sequence ++ * ++ * Sequence to reset the TWL4030 Power resources, ++ * when the system gets warm reset. ++ * Executed upon warm reset signal. ++ * ++ * First the device is put in reset, then the system clock is requested to ++ * the external oscillator, and default ON power reference and power providers ++ * are enabled. Next some additional resources which are software controlled ++ * are enabled. Finally sequence is ended by the release of TWL5030 reset. ++ */ ++static struct twl4030_ins wrst_seq[] __initdata = { ++ /* ++ * As a workaround for OMAP Erratum (ID: i537 - OMAP HS devices are ++ * not recovering from warm reset while in OFF mode) ++ * NRESPWRON is toggled to force a power on reset condition to OMAP ++ */ ++ /* Trun OFF NRES_PWRON */ ++ {MSG_SINGULAR(DEV_GRP_NULL, RES_NRES_PWRON, RES_STATE_OFF), 2}, ++ /* Reset twl4030 */ ++ {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 2}, ++ /* Reset MAIN_REF */ ++ {MSG_SINGULAR(DEV_GRP_NULL, RES_MAIN_REF, RES_STATE_WRST), 2}, ++ /* Reset All type2_group2 */ ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, ++ RES_STATE_WRST), 2}, ++ /* Reset VUSB_3v1 */ ++ {MSG_SINGULAR(DEV_GRP_NULL, RES_VUSB_3V1, RES_STATE_WRST), 2}, ++ /* Reset All type2_group1 */ ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, ++ RES_STATE_WRST), 2}, ++ /* Reset the Reset & Contorl_signals */ ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0, ++ RES_STATE_WRST), 2}, ++ /* Re-enable twl4030 */ ++ {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 2}, ++ /* Trun ON NRES_PWRON */ ++ {MSG_SINGULAR(DEV_GRP_NULL, RES_NRES_PWRON, RES_STATE_ACTIVE), 2}, ++}; ++ ++static struct twl4030_script wrst_script __initdata = { ++ .script = wrst_seq, ++ .size = ARRAY_SIZE(wrst_seq), ++ .flags = TWL4030_WRST_SCRIPT, ++}; ++ ++/* TWL4030 script for sleep, wakeup & warm_reset */ ++static struct twl4030_script *twl4030_scripts[] __initdata = { ++ &wakeup_p12_script, ++ &wakeup_p3_script, ++ &sleep_on_script, ++ &wrst_script, ++}; ++ ++/** ++ * DOC: TWL4030 resource configuration ++ * ++ * Resource which are attached to P1 device group alone ++ * will go to sleep state, when sys_off signal from OMAP is de-asserted. ++ * (VPLL1, VDD1, VDD2) ++ * ++ * None of the resources are attached to P2 device group alone. ++ * (WARNING: If MODEM or connectivity chip is connected to NSLEEP2 PIN on ++ * TWL4030, should modify the resource configuration accordingly). ++ * ++ * Resource which are attached to P3 device group alone ++ * will go to sleep state, when clk_req signal from OMAP is de-asserted. ++ * (HFCLKOUT) ++ * ++ * Resource which are attached to more than one device group ++ * will go to sleep state, when corresponding signals are de-asserted. ++ * (VINTANA1, VINTANA2, VINTDIG, VIO, REGEN, NRESPWRON, CLKEN, SYSEN) ++ * ++ * REGEN is an output of the device which can be connected to slave power ICs ++ * or external LDOs that power on before voltage for the IO interface (VIO). ++ * ++ * SYSEN is a bidirectional signal of the device that controls slave power ICs. ++ * In master mode, the device sets SYSEN high to enable the slave power ICs. ++ * In slave mode, when one of the power ICs drives the SYSEN signal low, ++ * all devices of the platform stay in the wait-on state. ++ * ++ * Resource which are attached to none of the device group by default ++ * will be in sleep state. These resource should be controlled by ++ * the respective drivers using them. ++ * Resource which are controlled by drivers are not modified here. ++ * (VAUX1, VAUX2, VAUX3, VAUX4, VMMC1, VMMC2, VPLL2, VSIM, VDAC, ++ * VUSB1V5, VUSB1V8, VUSB3V1) ++ * ++ * Resource using reset values. ++ * (32KCLKOUT, TRITON_RESET, MAINREF) ++ */ ++static struct twl4030_resconfig twl4030_rconfig[] __initdata = { ++ { .resource = RES_VPLL1, .devgroup = DEV_GRP_P1, .type = 3, ++ .type2 = 1, .remap_sleep = RES_STATE_OFF }, ++ { .resource = RES_VINTANA1, .devgroup = DEV_GRP_ALL, .type = 1, ++ .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_VINTANA2, .devgroup = DEV_GRP_ALL, .type = 0, ++ .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_VINTDIG, .devgroup = DEV_GRP_ALL, .type = 1, ++ .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_VIO, .devgroup = DEV_GRP_ALL, .type = 2, ++ .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_VDD1, .devgroup = DEV_GRP_P1, ++ .type = 4, .type2 = 1, .remap_sleep = RES_STATE_OFF }, ++ { .resource = RES_VDD2, .devgroup = DEV_GRP_P1, ++ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF }, ++ { .resource = RES_REGEN, .devgroup = DEV_GRP_ALL, .type = 2, ++ .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_ALL, .type = 0, ++ .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_CLKEN, .devgroup = DEV_GRP_ALL, .type = 3, ++ .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_SYSEN, .devgroup = DEV_GRP_ALL, .type = 6, ++ .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3, ++ .type = 0, .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { 0, 0}, ++}; ++ ++struct twl4030_power_data twl4030_generic_script __initdata = { ++ .scripts = twl4030_scripts, ++ .num = ARRAY_SIZE(twl4030_scripts), ++ .resource_config = twl4030_rconfig, ++}; ++ ++static int __init twl4030_script_probe(struct platform_device *pdev) ++{ ++ return twl4030_power_init(&twl4030_generic_script); ++} ++ ++static int twl4030_script_remove(struct platform_device *pdev) ++{ ++ return twl4030_remove_script(TWL4030_SLEEP_SCRIPT | ++ TWL4030_WAKEUP12_SCRIPT | TWL4030_WAKEUP3_SCRIPT | ++ TWL4030_WRST_SCRIPT); ++} ++ ++static struct platform_driver twl4030_script_driver = { ++ .remove = twl4030_script_remove, ++ .driver = { ++ .name = "twl4030_script", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init twl4030_script_init(void) ++{ ++ /* Register the TWL4030 script driver */ ++ return platform_driver_probe(&twl4030_script_driver, ++ twl4030_script_probe); ++} ++ ++static void __exit twl4030_script_cleanup(void) ++{ ++ /* Unregister TWL4030 script driver */ ++ platform_driver_unregister(&twl4030_script_driver); ++} ++ ++module_init(twl4030_script_init); ++module_exit(twl4030_script_cleanup); ++ ++MODULE_DESCRIPTION("OMAP TWL4030 script driver"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Texas Instruments Inc"); +diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h +index aee3a22..f343974 100644 +--- a/include/linux/i2c/twl.h ++++ b/include/linux/i2c/twl.h +@@ -205,6 +205,12 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) + return -EIO; + } + #endif ++ ++#ifdef CONFIG_TWL4030_POWER ++extern struct twl4030_power_data twl4030_generic_script; ++#else ++#define twl4030_generic_script NULL; ++#endif + /*----------------------------------------------------------------------*/ + + /* +@@ -437,9 +443,23 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) + + /* Power bus message definitions */ + +-/* The TWL4030/5030 splits its power-management resources (the various +- * regulators, clock and reset lines) into 3 processor groups - P1, P2 and +- * P3. These groups can then be configured to transition between sleep, wait-on ++/* ++ * The TWL4030/5030 splits its power-management resources (the various ++ * regulators, clock and reset lines) into 3 processor groups - P1, P2 and P3. ++ * ++ * Resources attached to device group P1 is managed depending on the state of ++ * NSLEEP1 pin of TWL4030, which is connected to sys_off signal from OMAP ++ * ++ * Resources attached to device group P2 is managed depending on the state of ++ * NSLEEP2 pin of TWL4030, which is can be connected to a modem or ++ * connectivity chip ++ * ++ * Resources attached to device group P3 is managed depending on the state of ++ * CLKREQ pin of TWL4030, which is connected to clk request signal from OMAP ++ * ++ * If required these resources can be attached to combination of P1/P2/P3. ++ * ++ * These groups can then be configured to transition between sleep, wait-on + * and active states by sending messages to the power bus. See Section 5.4.2 + * Power Resources of TWL4030 TRM + */ +@@ -449,7 +469,17 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) + #define DEV_GRP_P1 0x1 /* P1: all OMAP devices */ + #define DEV_GRP_P2 0x2 /* P2: all Modem devices */ + #define DEV_GRP_P3 0x4 /* P3: all peripheral devices */ ++#define DEV_GRP_ALL 0x7 /* P1/P2/P3: all devices */ + ++/* ++ * The 27 power resources in TWL4030 is again divided into ++ * analog resources: ++ * Power Providers - LDO regulators, dc-to-dc regulators ++ * Power Reference - analog reference ++ * ++ * and digital resources: ++ * Reset & Clock - reset and clock signals. ++ */ + /* Resource groups */ + #define RES_GRP_RES 0x0 /* Reserved */ + #define RES_GRP_PP 0x1 /* Power providers */ +@@ -461,7 +491,10 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot) + #define RES_GRP_ALL 0x7 /* All resource groups */ + + #define RES_TYPE2_R0 0x0 ++#define RES_TYPE2_R1 0x1 ++#define RES_TYPE2_R2 0x2 + ++#define RES_TYPE_R0 0x0 + #define RES_TYPE_ALL 0x7 + + /* Resource states */ +@@ -636,7 +669,7 @@ struct twl4030_power_data { + #define TWL4030_RESCONFIG_UNDEF ((u8)-1) + }; + +-extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts); ++extern int twl4030_power_init(struct twl4030_power_data *triton2_scripts); + extern int twl4030_remove_script(u8 flags); + + struct twl4030_codec_audio_data { +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch b/recipes/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch new file mode 100644 index 0000000000..6de2193d0f --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0011-MFD-TWL4030-TWL-version-checking.patch @@ -0,0 +1,164 @@ +From 3ceb224732230934aba7d082f3e2ca96c14a9ca0 Mon Sep 17 00:00:00 2001 +From: Lesly A M +Date: Wed, 1 Jun 2011 14:56:56 -0700 +Subject: [PATCH 11/13] MFD: TWL4030: TWL version checking + +Added API to get the TWL5030 Si version from the IDCODE register. +It is used for enabling the workaround for TWL erratum 27. + +Signed-off-by: Lesly A M +Cc: Nishanth Menon +Cc: David Derrick +Cc: Samuel Ortiz +--- + drivers/mfd/twl-core.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/i2c/twl.h | 17 ++++++++++++- + 2 files changed, 78 insertions(+), 1 deletions(-) + +diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c +index 9096d7d..a60601d 100644 +--- a/drivers/mfd/twl-core.c ++++ b/drivers/mfd/twl-core.c +@@ -251,6 +251,9 @@ + /* is driver active, bound to a chip? */ + static bool inuse; + ++/* TWL IDCODE Register value */ ++static u32 twl_idcode; ++ + static unsigned int twl_id; + unsigned int twl_rev(void) + { +@@ -509,6 +512,58 @@ EXPORT_SYMBOL(twl_i2c_read_u8); + + /*----------------------------------------------------------------------*/ + ++/** ++ * twl_read_idcode_register - API to read the IDCODE register. ++ * ++ * Unlocks the IDCODE register and read the 32 bit value. ++ */ ++static int twl_read_idcode_register(void) ++{ ++ int err; ++ ++ err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, TWL_EEPROM_R_UNLOCK, ++ REG_UNLOCK_TEST_REG); ++ if (err) { ++ pr_err("TWL4030 Unable to unlock IDCODE registers -%d\n", err); ++ goto fail; ++ } ++ ++ err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_idcode), ++ REG_IDCODE_7_0, 4); ++ if (err) { ++ pr_err("TWL4030: unable to read IDCODE -%d\n", err); ++ goto fail; ++ } ++ ++ err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x0, REG_UNLOCK_TEST_REG); ++ if (err) ++ pr_err("TWL4030 Unable to relock IDCODE registers -%d\n", err); ++fail: ++ return err; ++} ++ ++/** ++ * twl_get_type - API to get TWL Si type. ++ * ++ * Api to get the TWL Si type from IDCODE value. ++ */ ++int twl_get_type(void) ++{ ++ return TWL_SIL_TYPE(twl_idcode); ++} ++EXPORT_SYMBOL_GPL(twl_get_type); ++ ++/** ++ * twl_get_version - API to get TWL Si version. ++ * ++ * Api to get the TWL Si version from IDCODE value. ++ */ ++int twl_get_version(void) ++{ ++ return TWL_SIL_REV(twl_idcode); ++} ++EXPORT_SYMBOL_GPL(twl_get_version); ++ + static struct device * + add_numbered_child(unsigned chip, const char *name, int num, + void *pdata, unsigned pdata_len, +@@ -1071,6 +1126,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) + unsigned i; + struct twl4030_platform_data *pdata = client->dev.platform_data; + u8 temp; ++ int ret = 0; + + if (!pdata) { + dev_dbg(&client->dev, "no platform data?\n"); +@@ -1117,6 +1173,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) + /* setup clock framework */ + clocks_init(&client->dev, pdata->clock); + ++ /* read TWL IDCODE Register */ ++ if (twl_id == TWL4030_CLASS_ID) { ++ ret = twl_read_idcode_register(); ++ WARN(ret < 0, "Error: reading twl_idcode register value\n"); ++ } ++ + /* load power event scripts */ + if (twl_has_power() && pdata->power) + twl4030_power_init(pdata->power); +diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h +index f343974..23ec058 100644 +--- a/include/linux/i2c/twl.h ++++ b/include/linux/i2c/twl.h +@@ -151,7 +151,12 @@ + #define MMC_PU (0x1 << 3) + #define MMC_PD (0x1 << 2) + +- ++#define TWL_SIL_TYPE(rev) ((rev) & 0x00FFFFFF) ++#define TWL_SIL_REV(rev) ((rev) >> 24) ++#define TWL_SIL_5030 0x09002F ++#define TWL5030_REV_1_0 0x00 ++#define TWL5030_REV_1_1 0x10 ++#define TWL5030_REV_1_2 0x30 + + #define TWL4030_CLASS_ID 0x4030 + #define TWL6030_CLASS_ID 0x6030 +@@ -181,6 +186,9 @@ int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg); + int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); + int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes); + ++int twl_get_type(void); ++int twl_get_version(void); ++ + int twl6030_interrupt_unmask(u8 bit_mask, u8 offset); + int twl6030_interrupt_mask(u8 bit_mask, u8 offset); + +@@ -286,7 +294,12 @@ extern struct twl4030_power_data twl4030_generic_script; + *(Use TWL_4030_MODULE_INTBR) + */ + ++#define REG_IDCODE_7_0 0x00 ++#define REG_IDCODE_15_8 0x01 ++#define REG_IDCODE_16_23 0x02 ++#define REG_IDCODE_31_24 0x03 + #define REG_GPPUPDCTR1 0x0F ++#define REG_UNLOCK_TEST_REG 0x12 + + /*I2C1 and I2C4(SR) SDA/SCL pull-up control bits */ + +@@ -295,6 +308,8 @@ extern struct twl4030_power_data twl4030_generic_script; + #define SR_I2C_SCL_CTRL_PU BIT(4) + #define SR_I2C_SDA_CTRL_PU BIT(6) + ++#define TWL_EEPROM_R_UNLOCK 0x49 ++ + /*----------------------------------------------------------------------*/ + + /* +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch b/recipes/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch new file mode 100644 index 0000000000..6fe9dbfb0e --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch @@ -0,0 +1,341 @@ +From 0bec9f7b20e7c61e0bab93195ec39cf94f1f8e25 Mon Sep 17 00:00:00 2001 +From: Lesly A M +Date: Wed, 1 Jun 2011 14:57:01 -0700 +Subject: [PATCH 12/13] MFD: TWL4030: workaround changes for Erratum 27 + +Workaround for TWL5030 Silicon Errata 27 & 28: + 27 - VDD1, VDD2, may have glitches when their output value is updated. + 28 - VDD1 and / or VDD2 DCDC clock may stop working when internal clock + is switched from internal to external. + +Erratum 27: + If the DCDC regulators is running on their internal oscillator, + negative glitches may occur on VDD1, VDD2 output when voltage is changed. + The OMAP device may reboot if the VDD1 or VDD2 go below the + core minimum operating voltage. + + WORKAROUND + Set up the TWL5030 DC-DC power supplies to use the HFCLKIN instead of + the internal oscillator. + +Erratum 28: + VDD1/VDD2 clock system may hang during switching the clock source from + internal oscillator to external. VDD1/VDD2 output voltages may collapse + if clock stops. + + WORKAROUND + If HFCLK is disabled in OFFMODE, modify the sleep/wakeup sequence and + setuptimes to make sure the switching will happen only when HFCLKIN is stable. + Also use the TWL5030 watchdog to safeguard the first switching from + internal oscillator to HFCLKIN during the TWL5030 init. + + IMPACT + power sequence is changed. + sleep/wakeup time values will be changed. + +The workaround changes are called from twl4030_power_init(), since we have to +make some i2c_read calls to check the TWL4030 version & the i2c will not be +initialized in the early stage. + +This workaround is required for TWL5030 Silicon version less than ES1.2 +The power script & setup time changes are recommended by TI HW team. + +For more information please see: + http://omapedia.org/wiki/TWL4030_power_scripts + +Changes taken from TWL4030 Erratum 27 workaround patch by Nishanth Menon. + +Signed-off-by: Lesly A M +Cc: Nishanth Menon +Cc: David Derrick +Cc: Samuel Ortiz +--- + drivers/mfd/twl4030-power.c | 79 +++++++++++++++++++ + drivers/mfd/twl4030-script-omap.c | 150 +++++++++++++++++++++++++++++++++++++ + include/linux/i2c/twl.h | 1 + + 3 files changed, 230 insertions(+), 0 deletions(-) + +diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c +index 91d5bc8..8af3fe3 100644 +--- a/drivers/mfd/twl4030-power.c ++++ b/drivers/mfd/twl4030-power.c +@@ -63,6 +63,14 @@ static u8 twl4030_start_script_address = 0x2b; + #define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59) + #define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a) + ++#define R_VDD1_OSC 0x5C ++#define R_VDD2_OSC 0x6A ++#define R_VIO_OSC 0x52 ++#define EXT_FS_CLK_EN BIT(6) ++ ++#define R_WDT_CFG 0x03 ++#define WDT_WRK_TIMEOUT 0x03 ++ + /* resource configuration registers + _DEV_GRP at address 'n+0' + _TYPE at address 'n+1' +@@ -512,6 +520,67 @@ int twl4030_remove_script(u8 flags) + } + EXPORT_SYMBOL_GPL(twl4030_remove_script); + ++/** ++ * twl_dcdc_use_hfclk - API to use HFCLK for TWL DCDCs ++ * ++ * TWL DCDCs switching to HFCLK instead of using internal RC oscillator. ++ */ ++static int twl_dcdc_use_hfclk(void) ++{ ++ u8 val; ++ u8 smps_osc_reg[] = {R_VDD1_OSC, R_VDD2_OSC, R_VIO_OSC}; ++ int i; ++ int err; ++ ++ for (i = 0; i < sizeof(smps_osc_reg); i++) { ++ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &val, ++ smps_osc_reg[i]); ++ val |= EXT_FS_CLK_EN; ++ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val, ++ smps_osc_reg[i]); ++ } ++ return err; ++} ++ ++/** ++ * twl_erratum27_workaround - Workaround for TWL5030 Silicon Erratum 27 ++ * 27 - VDD1, VDD2, may have glitches when their output value is updated. ++ * 28 - VDD1 and / or VDD2 DCDC clock may stop working when internal clock is ++ * switched from internal to external. ++ * ++ * Workaround requires the TWL DCDCs to use HFCLK instead of ++ * internal oscillator. Also enable TWL watchdog before switching the osc ++ * to recover if the VDD1/VDD2 stop working. ++ */ ++static void twl_erratum27_workaround(void) ++{ ++ u8 wdt_counter_val = 0; ++ int err; ++ ++ /* Setup the twl wdt to take care of borderline failure case */ ++ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &wdt_counter_val, ++ R_WDT_CFG); ++ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, WDT_WRK_TIMEOUT, ++ R_WDT_CFG); ++ ++ /* TWL DCDC switching to HFCLK */ ++ err |= twl_dcdc_use_hfclk(); ++ ++ /* restore the original value */ ++ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, wdt_counter_val, ++ R_WDT_CFG); ++ if (err) ++ pr_warning("TWL4030: workaround setup failed!\n"); ++} ++ ++static bool is_twl5030_erratum27wa_required(void) ++{ ++ if (twl_get_type() == TWL_SIL_5030) ++ return (twl_get_version() < TWL5030_REV_1_2); ++ ++ return 0; ++} ++ + int twl4030_power_init(struct twl4030_power_data *twl4030_scripts) + { + int err = 0; +@@ -530,6 +599,16 @@ int twl4030_power_init(struct twl4030_power_data *twl4030_scripts) + TWL4030_PM_MASTER_PROTECT_KEY); + if (err) + goto unlock; ++ ++ /* Applying TWL5030 Erratum 27 WA based on Si revision & ++ * flag updated from board file*/ ++ if (is_twl5030_erratum27wa_required()) { ++ pr_info("TWL5030: Enabling workaround for Si Erratum 27\n"); ++ twl_erratum27_workaround(); ++ if (twl4030_scripts->twl5030_erratum27wa_script) ++ twl4030_scripts->twl5030_erratum27wa_script(); ++ } ++ + for (i = 0; i < twl4030_scripts->num; i++) { + err = load_twl4030_script(twl4030_scripts->scripts[i], address); + if (err) +diff --git a/drivers/mfd/twl4030-script-omap.c b/drivers/mfd/twl4030-script-omap.c +index 867a442..ff93fd2 100644 +--- a/drivers/mfd/twl4030-script-omap.c ++++ b/drivers/mfd/twl4030-script-omap.c +@@ -326,10 +326,160 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = { + { 0, 0}, + }; + ++/* ++ * Sleep and active sequences with changes for TWL5030 Erratum 27 workaround ++ * ++ * Sysoff (using sys_off signal): ++ * When SYS_CLKREQ goes low during retention no resources will be affected ++ * since no resources are assigned to P3 only. ++ * ++ * Since all resources are assigned to P1 and P3 then all resources ++ * will be affected on the falling edge of P3 (SYS_CLKREQ). ++ * When OMAP lower the SYS_CLKREQ signal PMIC will execute the ++ * A2S sequence in which HFCLKOUT is dissabled first and ++ * after 488.32 usec(PRM_VOLTOFFSET) resources assigned to P1 and P3 ++ * and of TYPE2=1 are put to sleep ++ * (VDD1, VDD2, VPLL1, REGEN, NRESPWRON & SYSEN). ++ * Again after a 61.04 usec resources assigned to P1 and P3 ++ * and of TYPE2=2 are put to sleep ++ * (VINTANA1, VINTANA2, VINTDIG, VIO & CLKEN). ++ * ++ * On wakeup event OMAP goes active and pulls the SYS_CLKREQ high, ++ * and will execute the S2A sequence which is same for P1_P2 & P3. ++ * This will turn on all resources of TYPE2=2 to go to the active state. ++ * Three dummy broadcast messages are added to get a delay of ~10 ms ++ * before enabling the HFCLKOUT resource. And after a 30.52 usec ++ * all resources of TYPE2=1 are put to the active state. ++ * ++ * This 10ms delay can be reduced if the oscillator is having less ++ * stabilization time. A should be taken care if it needs more time ++ * for stabilization. ++ * ++ */ ++ ++/** ++ * DOC: Sleep to Active sequence for P1/P2/P3 ++ * ++ * The wakeup sequence is adjusted to do the VDD1/VDD2 voltage ramp-up ++ * only after HFCLKIN is stabilized and the HFCLKOUT is enabled. ++ */ ++static struct twl4030_ins wakeup_seq_erratum27[] __initdata = { ++ /* ++ * Broadcast message to put res(TYPE2 = 2) to active. ++ * Wait for ~10 mS (ramp-up time for OSC on the board) ++ * after HFCLKIN is enabled ++ */ ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, ++ RES_STATE_ACTIVE), 55}, ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, ++ RES_STATE_ACTIVE), 55}, ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, ++ RES_STATE_ACTIVE), 54}, ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, ++ RES_STATE_ACTIVE), 1}, ++ /* Singular message to enable HCLKOUT after HFCLKIN is stabilized */ ++ {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_ACTIVE), 1}, ++ /* ++ * Broadcast message to put res(TYPE2 = 1) to active. ++ * VDD1/VDD2 ramp-up after HFCLKIN is stable and HFCLKOUT is enabled. ++ */ ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, ++ RES_STATE_ACTIVE), 2}, ++}; ++ ++static struct twl4030_script wakeup_script_erratum27 __initdata = { ++ .script = wakeup_seq_erratum27, ++ .size = ARRAY_SIZE(wakeup_seq_erratum27), ++ .flags = TWL4030_WAKEUP12_SCRIPT | TWL4030_WAKEUP3_SCRIPT, ++}; ++ ++/** ++ * DOC: Active to Sleep sequence for P1/P2/P3 ++ * ++ * The sleep sequence is adjusted to do the switching of VDD1/VDD2/VIO OSC from ++ * HFCLKIN to internal oscillator when the HFCLKIN is stable. ++ */ ++static struct twl4030_ins sleep_on_seq_erratum27[] __initdata = { ++ /* ++ * Singular message to disable HCLKOUT. ++ * Wait for ~488.32 uS to do the switching of VDD1/VDD2/VIO OSC from ++ * HFCLKIN to internal oscillator before disabling HFCLKIN. ++ */ ++ {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_SLEEP), 20}, ++ /* Broadcast message to put res(TYPE2 = 1) to sleep */ ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, ++ RES_STATE_SLEEP), 2}, ++ /* Broadcast message to put res(TYPE2 = 2) to sleep, disable HFCLKIN */ ++ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, ++ RES_STATE_SLEEP), 2}, ++}; ++ ++static struct twl4030_script sleep_on_script_erratum27 __initdata = { ++ .script = sleep_on_seq_erratum27, ++ .size = ARRAY_SIZE(sleep_on_seq_erratum27), ++ .flags = TWL4030_SLEEP_SCRIPT, ++}; ++ ++/* TWL4030 script for sleep, wakeup & warm_reset */ ++static struct twl4030_script *twl4030_scripts_erratum27[] __initdata = { ++ &wakeup_script_erratum27, ++ &sleep_on_script_erratum27, ++ &wrst_script, ++}; ++ ++/** ++ * DOC: TWL4030 resource configuration ++ * ++ * VDD1/VDD2/VPLL are assigned to P1 and P3, to have better control ++ * during OFFMODE. HFCLKOUT is assigned to P1 and P3 (*p2) to turn off ++ * only during OFFMODE. ++ * (*P2 is included if the platform uses it for modem/some other processor) ++ */ ++static struct twl4030_resconfig twl4030_rconfig_erratum27[] __initdata = { ++ { .resource = RES_VPLL1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, ++ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF }, ++ { .resource = RES_VINTANA1, .devgroup = DEV_GRP_ALL, .type = 1, ++ .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_VINTANA2, .devgroup = DEV_GRP_ALL, .type = 0, ++ .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_VINTDIG, .devgroup = DEV_GRP_ALL, .type = 1, ++ .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_VIO, .devgroup = DEV_GRP_ALL, .type = 2, ++ .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_VDD1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, ++ .type = 4, .type2 = 1, .remap_sleep = RES_STATE_OFF }, ++ { .resource = RES_VDD2, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, ++ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF }, ++ { .resource = RES_REGEN, .devgroup = DEV_GRP_ALL, .type = 2, ++ .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_ALL, .type = 0, ++ .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_CLKEN, .devgroup = DEV_GRP_ALL, .type = 3, ++ .type2 = 2, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_SYSEN, .devgroup = DEV_GRP_ALL, .type = 6, ++ .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, ++ { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P1 | DEV_GRP_P3, ++ .type = 0, .type2 = 1, .remap_sleep = RES_STATE_SLEEP }, ++ { 0, 0}, ++}; ++ ++/** ++ * twl5030_script_erratum27() - API to modify TWL4030 script ++ * ++ * Updating the TWL4030 script & resource configuration ++ */ ++static void __init twl5030_script_erratum27(void) ++{ ++ twl4030_generic_script.scripts = twl4030_scripts_erratum27; ++ twl4030_generic_script.num = ARRAY_SIZE(twl4030_scripts_erratum27); ++ twl4030_generic_script.resource_config = twl4030_rconfig_erratum27; ++} ++ + struct twl4030_power_data twl4030_generic_script __initdata = { + .scripts = twl4030_scripts, + .num = ARRAY_SIZE(twl4030_scripts), + .resource_config = twl4030_rconfig, ++ .twl5030_erratum27wa_script = twl5030_script_erratum27, + }; + + static int __init twl4030_script_probe(struct platform_device *pdev) +diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h +index 23ec058..10cb6e2 100644 +--- a/include/linux/i2c/twl.h ++++ b/include/linux/i2c/twl.h +@@ -681,6 +681,7 @@ struct twl4030_power_data { + struct twl4030_script **scripts; + unsigned num; + struct twl4030_resconfig *resource_config; ++ void (*twl5030_erratum27wa_script)(void); + #define TWL4030_RESCONFIG_UNDEF ((u8)-1) + }; + +-- +1.6.6.1 + diff --git a/recipes/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch b/recipes/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch new file mode 100644 index 0000000000..8904f8de96 --- /dev/null +++ b/recipes/linux/linux-omap-2.6.39/mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch @@ -0,0 +1,184 @@ +From bf171753a162d07753208c6bcfae8ca1e5c94af3 Mon Sep 17 00:00:00 2001 +From: Lesly A M +Date: Wed, 1 Jun 2011 14:57:05 -0700 +Subject: [PATCH 13/13] MFD: TWL4030: optimizing resource configuration + +Skip the i2c register writes in twl4030_configure_resource() if the new value +is same as the old value, for devgrp/type/remap regs. + +Suggested by David Derrick + +Signed-off-by: Lesly A M +Cc: Nishanth Menon +Cc: David Derrick +Cc: Samuel Ortiz +--- + drivers/mfd/twl4030-power.c | 126 ++++++++++++++++++++++++------------------ + 1 files changed, 72 insertions(+), 54 deletions(-) + +diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c +index 8af3fe3..d82632f 100644 +--- a/drivers/mfd/twl4030-power.c ++++ b/drivers/mfd/twl4030-power.c +@@ -335,9 +335,9 @@ static int twl4030_configure_resource(struct twl4030_resconfig *rconfig) + { + int rconfig_addr; + int err; +- u8 type; +- u8 grp; +- u8 remap; ++ u8 type, type_value; ++ u8 grp, grp_value; ++ u8 remap, remap_value; + + if (rconfig->resource > TOTAL_RESOURCES) { + pr_err("TWL4030 Resource %d does not exist\n", +@@ -348,76 +348,94 @@ static int twl4030_configure_resource(struct twl4030_resconfig *rconfig) + rconfig_addr = res_config_addrs[rconfig->resource]; + + /* Set resource group */ +- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp, ++ if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) { ++ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp, + rconfig_addr + DEV_GRP_OFFSET); +- if (err) { +- pr_err("TWL4030 Resource %d group could not be read\n", +- rconfig->resource); +- return err; +- } ++ if (err) { ++ pr_err("TWL4030 Resource %d group could not be read\n", ++ rconfig->resource); ++ return err; ++ } + +- if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) { +- grp &= ~DEV_GRP_MASK; +- grp |= rconfig->devgroup << DEV_GRP_SHIFT; +- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, ++ grp_value = (grp & DEV_GRP_MASK) >> DEV_GRP_SHIFT; ++ ++ if (rconfig->devgroup != grp_value) { ++ grp &= ~DEV_GRP_MASK; ++ grp |= rconfig->devgroup << DEV_GRP_SHIFT; ++ err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + grp, rconfig_addr + DEV_GRP_OFFSET); +- if (err < 0) { +- pr_err("TWL4030 failed to program devgroup\n"); +- return err; ++ if (err < 0) { ++ pr_err("TWL4030 failed to program devgroup\n"); ++ return err; ++ } + } + } + + /* Set resource types */ +- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type, ++ if ((rconfig->type != TWL4030_RESCONFIG_UNDEF) || ++ (rconfig->type2 != TWL4030_RESCONFIG_UNDEF)) { ++ ++ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type, + rconfig_addr + TYPE_OFFSET); +- if (err < 0) { +- pr_err("TWL4030 Resource %d type could not be read\n", +- rconfig->resource); +- return err; +- } ++ if (err < 0) { ++ pr_err("TWL4030 Resource %d type could not be read\n", ++ rconfig->resource); ++ return err; ++ } + +- if (rconfig->type != TWL4030_RESCONFIG_UNDEF) { +- type &= ~TYPE_MASK; +- type |= rconfig->type << TYPE_SHIFT; +- } ++ type_value = type; + +- if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) { +- type &= ~TYPE2_MASK; +- type |= rconfig->type2 << TYPE2_SHIFT; +- } ++ if (rconfig->type != TWL4030_RESCONFIG_UNDEF) { ++ type &= ~TYPE_MASK; ++ type |= rconfig->type << TYPE_SHIFT; ++ } + +- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, ++ if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) { ++ type &= ~TYPE2_MASK; ++ type |= rconfig->type2 << TYPE2_SHIFT; ++ } ++ ++ if (type != type_value) { ++ err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + type, rconfig_addr + TYPE_OFFSET); +- if (err < 0) { +- pr_err("TWL4030 failed to program resource type\n"); +- return err; ++ if (err < 0) { ++ pr_err("TWL4030 failed to program resource type\n"); ++ return err; ++ } ++ } + } + + /* Set remap states */ +- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap, ++ if ((rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) || ++ (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF)) { ++ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap, + rconfig_addr + REMAP_OFFSET); +- if (err < 0) { +- pr_err("TWL4030 Resource %d remap could not be read\n", +- rconfig->resource); +- return err; +- } ++ if (err < 0) { ++ pr_err("TWL4030 Resource %d remap could not be read\n", ++ rconfig->resource); ++ return err; ++ } + +- if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) { +- remap &= ~OFF_STATE_MASK; +- remap |= rconfig->remap_off << OFF_STATE_SHIFT; +- } ++ remap_value = remap; + +- if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { +- remap &= ~SLEEP_STATE_MASK; +- remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT; +- } ++ if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) { ++ remap &= ~OFF_STATE_MASK; ++ remap |= rconfig->remap_off << OFF_STATE_SHIFT; ++ } + +- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, +- remap, +- rconfig_addr + REMAP_OFFSET); +- if (err < 0) { +- pr_err("TWL4030 failed to program remap\n"); +- return err; ++ if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) { ++ remap &= ~SLEEP_STATE_MASK; ++ remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT; ++ } ++ ++ if (remap != remap_value) { ++ err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, ++ remap, rconfig_addr + REMAP_OFFSET); ++ if (err < 0) { ++ pr_err("TWL4030 failed to program remap\n"); ++ return err; ++ } ++ } + } + + return 0; +-- +1.6.6.1 + -- cgit 1.2.3-korg