summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2018-03-07 16:26:43 +0100
committerArnd Bergmann <arnd@arndb.de>2018-03-07 16:26:43 +0100
commit3bf5c70d06ce1d91cc73cee68bc6c4f850192cb0 (patch)
tree7d1fab0c67d26ebde22ea4c5e7eb8625f388ccf1 /arch/arm/mach-omap2
parent18b4788badeae8ed3a9bd3c240d83dffe5db8f37 (diff)
parent695eea3d2c7f3e70e852226c338d464a6251c70b (diff)
downloadop-kernel-dev-3bf5c70d06ce1d91cc73cee68bc6c4f850192cb0.zip
op-kernel-dev-3bf5c70d06ce1d91cc73cee68bc6c4f850192cb0.tar.gz
Merge tag 'omap-for-v4.17/ti-sysc-signed' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/soc
Pull "Driver changes for ti-sysc for v4.17" from Tony Lindgren: This series of changes enables the use device tree based sysconfig data for ti-sysc driver. As we already have SmartReflex data configured, we use that as the first driver to enable. To do that in a way where SmartReflex is not probed twice, we need to prepare the SmartReflex driver before flipping dts data on for it in the last patch of the series. To avoid regressions, we are checking the passed dts data against existing platform data since we still have it available. Then after the dts files are converted, we can simply drop the related platform data at some point in the future. * tag 'omap-for-v4.17/ti-sysc-signed' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: ARM: OMAP2+: Enable ti-sysc to use device tree data for smartreflex PM / AVS: SmartReflex: Prepare to use device tree based probing ARM: OMAP2+: Try to parse earlycon from parent too ARM: OMAP2+: Add checks for device tree based sysconfig data ARM: OMAP2+: Add functions to allocate module data from device tree bus: ti-sysc: Handle some devices in omap_device compatible way bus: ti-sysc: Add support for platform data callbacks bus: ti-sysc: Remove unnecessary debugging statements bus: ti-sysc: Improve handling for no-reset-on-init and no-idle-on-init bus: ti-sysc: Handle stdout-path for debug console bus: ti-sysc: Add suspend and resume handling bus: ti-sysc: Add fck clock alias for children with notifier_block ARM: OMAP2+: Prepare to pass auxdata for smartreflex
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/board-n8x0.c4
-rw-r--r--arch/arm/mach-omap2/omap_device.c5
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c418
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.h7
-rw-r--r--arch/arm/mach-omap2/pdata-quirks.c54
-rw-r--r--arch/arm/mach-omap2/sr_device.c27
6 files changed, 500 insertions, 15 deletions
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 20f2553..75bc186 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -566,11 +566,11 @@ static int n8x0_menelaus_late_init(struct device *dev)
}
#endif
-struct menelaus_platform_data n8x0_menelaus_platform_data __initdata = {
+struct menelaus_platform_data n8x0_menelaus_platform_data = {
.late_init = n8x0_menelaus_late_init,
};
-struct aic3x_pdata n810_aic33_data __initdata = {
+struct aic3x_pdata n810_aic33_data = {
.gpio_reset = 118,
};
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index f038805..3b829a5 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -140,6 +140,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
struct omap_device *od;
struct omap_hwmod *oh;
struct device_node *node = pdev->dev.of_node;
+ struct resource res;
const char *oh_name;
int oh_cnt, i, ret = 0;
bool device_active = false;
@@ -150,6 +151,10 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
return -ENODEV;
}
+ /* Use ti-sysc driver instead of omap_device? */
+ if (!omap_hwmod_parse_module_range(NULL, node, &res))
+ return -ENODEV;
+
hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
if (!hwmods) {
ret = -ENOMEM;
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 34156ec..e7d23e20 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -145,6 +145,8 @@
#include <linux/platform_data/ti-sysc.h>
+#include <dt-bindings/bus/ti-sysc.h>
+
#include <asm/system_misc.h>
#include "clock.h"
@@ -2498,7 +2500,7 @@ static void __init _setup_postsetup(struct omap_hwmod *oh)
* affects the IP block hardware, or system integration hardware
* associated with the IP block. Returns 0.
*/
-static int __init _setup(struct omap_hwmod *oh, void *data)
+static int _setup(struct omap_hwmod *oh, void *data)
{
if (oh->_state != _HWMOD_STATE_INITIALIZED)
return 0;
@@ -3060,6 +3062,414 @@ int __init omap_hwmod_setup_one(const char *oh_name)
return 0;
}
+static void omap_hwmod_check_one(struct device *dev,
+ const char *name, s8 v1, u8 v2)
+{
+ if (v1 < 0)
+ return;
+
+ if (v1 != v2)
+ dev_warn(dev, "%s %d != %d\n", name, v1, v2);
+}
+
+/**
+ * omap_hwmod_check_sysc - check sysc against platform sysc
+ * @dev: struct device
+ * @data: module data
+ * @sysc_fields: new sysc configuration
+ */
+static int omap_hwmod_check_sysc(struct device *dev,
+ const struct ti_sysc_module_data *data,
+ struct sysc_regbits *sysc_fields)
+{
+ const struct sysc_regbits *regbits = data->cap->regbits;
+
+ omap_hwmod_check_one(dev, "dmadisable_shift",
+ regbits->dmadisable_shift,
+ sysc_fields->dmadisable_shift);
+ omap_hwmod_check_one(dev, "midle_shift",
+ regbits->midle_shift,
+ sysc_fields->midle_shift);
+ omap_hwmod_check_one(dev, "sidle_shift",
+ regbits->sidle_shift,
+ sysc_fields->sidle_shift);
+ omap_hwmod_check_one(dev, "clkact_shift",
+ regbits->clkact_shift,
+ sysc_fields->clkact_shift);
+ omap_hwmod_check_one(dev, "enwkup_shift",
+ regbits->enwkup_shift,
+ sysc_fields->enwkup_shift);
+ omap_hwmod_check_one(dev, "srst_shift",
+ regbits->srst_shift,
+ sysc_fields->srst_shift);
+ omap_hwmod_check_one(dev, "autoidle_shift",
+ regbits->autoidle_shift,
+ sysc_fields->autoidle_shift);
+
+ return 0;
+}
+
+/**
+ * omap_hwmod_init_regbits - init sysconfig specific register bits
+ * @dev: struct device
+ * @data: module data
+ * @sysc_fields: new sysc configuration
+ */
+static int omap_hwmod_init_regbits(struct device *dev,
+ const struct ti_sysc_module_data *data,
+ struct sysc_regbits **sysc_fields)
+{
+ *sysc_fields = NULL;
+
+ switch (data->cap->type) {
+ case TI_SYSC_OMAP2:
+ case TI_SYSC_OMAP2_TIMER:
+ *sysc_fields = &omap_hwmod_sysc_type1;
+ break;
+ case TI_SYSC_OMAP3_SHAM:
+ *sysc_fields = &omap3_sham_sysc_fields;
+ break;
+ case TI_SYSC_OMAP3_AES:
+ *sysc_fields = &omap3xxx_aes_sysc_fields;
+ break;
+ case TI_SYSC_OMAP4:
+ case TI_SYSC_OMAP4_TIMER:
+ *sysc_fields = &omap_hwmod_sysc_type2;
+ break;
+ case TI_SYSC_OMAP4_SIMPLE:
+ *sysc_fields = &omap_hwmod_sysc_type3;
+ break;
+ case TI_SYSC_OMAP34XX_SR:
+ *sysc_fields = &omap34xx_sr_sysc_fields;
+ break;
+ case TI_SYSC_OMAP36XX_SR:
+ *sysc_fields = &omap36xx_sr_sysc_fields;
+ break;
+ case TI_SYSC_OMAP4_SR:
+ *sysc_fields = &omap36xx_sr_sysc_fields;
+ break;
+ case TI_SYSC_OMAP4_MCASP:
+ *sysc_fields = &omap_hwmod_sysc_type_mcasp;
+ break;
+ case TI_SYSC_OMAP4_USB_HOST_FS:
+ *sysc_fields = &omap_hwmod_sysc_type_usb_host_fs;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return omap_hwmod_check_sysc(dev, data, *sysc_fields);
+}
+
+/**
+ * omap_hwmod_init_reg_offs - initialize sysconfig register offsets
+ * @dev: struct device
+ * @data: module data
+ * @rev_offs: revision register offset
+ * @sysc_offs: sysc register offset
+ * @syss_offs: syss register offset
+ */
+int omap_hwmod_init_reg_offs(struct device *dev,
+ const struct ti_sysc_module_data *data,
+ u32 *rev_offs, u32 *sysc_offs, u32 *syss_offs)
+{
+ *rev_offs = 0;
+ *sysc_offs = 0;
+ *syss_offs = 0;
+
+ if (data->offsets[SYSC_REVISION] > 0)
+ *rev_offs = data->offsets[SYSC_REVISION];
+
+ if (data->offsets[SYSC_SYSCONFIG] > 0)
+ *sysc_offs = data->offsets[SYSC_SYSCONFIG];
+
+ if (data->offsets[SYSC_SYSSTATUS] > 0)
+ *syss_offs = data->offsets[SYSC_SYSSTATUS];
+
+ return 0;
+}
+
+/**
+ * omap_hwmod_init_sysc_flags - initialize sysconfig features
+ * @dev: struct device
+ * @data: module data
+ * @sysc_flags: module configuration
+ */
+int omap_hwmod_init_sysc_flags(struct device *dev,
+ const struct ti_sysc_module_data *data,
+ u32 *sysc_flags)
+{
+ *sysc_flags = 0;
+
+ switch (data->cap->type) {
+ case TI_SYSC_OMAP2:
+ case TI_SYSC_OMAP2_TIMER:
+ /* See SYSC_OMAP2_* in include/dt-bindings/bus/ti-sysc.h */
+ if (data->cfg->sysc_val & SYSC_OMAP2_CLOCKACTIVITY)
+ *sysc_flags |= SYSC_HAS_CLOCKACTIVITY;
+ if (data->cfg->sysc_val & SYSC_OMAP2_EMUFREE)
+ *sysc_flags |= SYSC_HAS_EMUFREE;
+ if (data->cfg->sysc_val & SYSC_OMAP2_ENAWAKEUP)
+ *sysc_flags |= SYSC_HAS_ENAWAKEUP;
+ if (data->cfg->sysc_val & SYSC_OMAP2_SOFTRESET)
+ *sysc_flags |= SYSC_HAS_SOFTRESET;
+ if (data->cfg->sysc_val & SYSC_OMAP2_AUTOIDLE)
+ *sysc_flags |= SYSC_HAS_AUTOIDLE;
+ break;
+ case TI_SYSC_OMAP4:
+ case TI_SYSC_OMAP4_TIMER:
+ /* See SYSC_OMAP4_* in include/dt-bindings/bus/ti-sysc.h */
+ if (data->cfg->sysc_val & SYSC_OMAP4_DMADISABLE)
+ *sysc_flags |= SYSC_HAS_DMADISABLE;
+ if (data->cfg->sysc_val & SYSC_OMAP4_FREEEMU)
+ *sysc_flags |= SYSC_HAS_EMUFREE;
+ if (data->cfg->sysc_val & SYSC_OMAP4_SOFTRESET)
+ *sysc_flags |= SYSC_HAS_SOFTRESET;
+ break;
+ case TI_SYSC_OMAP34XX_SR:
+ case TI_SYSC_OMAP36XX_SR:
+ /* See SYSC_OMAP3_SR_* in include/dt-bindings/bus/ti-sysc.h */
+ if (data->cfg->sysc_val & SYSC_OMAP3_SR_ENAWAKEUP)
+ *sysc_flags |= SYSC_HAS_ENAWAKEUP;
+ break;
+ default:
+ if (data->cap->regbits->emufree_shift >= 0)
+ *sysc_flags |= SYSC_HAS_EMUFREE;
+ if (data->cap->regbits->enwkup_shift >= 0)
+ *sysc_flags |= SYSC_HAS_ENAWAKEUP;
+ if (data->cap->regbits->srst_shift >= 0)
+ *sysc_flags |= SYSC_HAS_SOFTRESET;
+ if (data->cap->regbits->autoidle_shift >= 0)
+ *sysc_flags |= SYSC_HAS_AUTOIDLE;
+ break;
+ }
+
+ if (data->cap->regbits->midle_shift >= 0 &&
+ data->cfg->midlemodes)
+ *sysc_flags |= SYSC_HAS_MIDLEMODE;
+
+ if (data->cap->regbits->sidle_shift >= 0 &&
+ data->cfg->sidlemodes)
+ *sysc_flags |= SYSC_HAS_SIDLEMODE;
+
+ if (data->cfg->quirks & SYSC_QUIRK_UNCACHED)
+ *sysc_flags |= SYSC_NO_CACHE;
+ if (data->cfg->quirks & SYSC_QUIRK_RESET_STATUS)
+ *sysc_flags |= SYSC_HAS_RESET_STATUS;
+
+ if (data->cfg->syss_mask & 1)
+ *sysc_flags |= SYSS_HAS_RESET_STATUS;
+
+ return 0;
+}
+
+/**
+ * omap_hwmod_init_idlemodes - initialize module idle modes
+ * @dev: struct device
+ * @data: module data
+ * @idlemodes: module supported idle modes
+ */
+int omap_hwmod_init_idlemodes(struct device *dev,
+ const struct ti_sysc_module_data *data,
+ u32 *idlemodes)
+{
+ *idlemodes = 0;
+
+ if (data->cfg->midlemodes & BIT(SYSC_IDLE_FORCE))
+ *idlemodes |= MSTANDBY_FORCE;
+ if (data->cfg->midlemodes & BIT(SYSC_IDLE_NO))
+ *idlemodes |= MSTANDBY_NO;
+ if (data->cfg->midlemodes & BIT(SYSC_IDLE_SMART))
+ *idlemodes |= MSTANDBY_SMART;
+ if (data->cfg->midlemodes & BIT(SYSC_IDLE_SMART_WKUP))
+ *idlemodes |= MSTANDBY_SMART_WKUP;
+
+ if (data->cfg->sidlemodes & BIT(SYSC_IDLE_FORCE))
+ *idlemodes |= SIDLE_FORCE;
+ if (data->cfg->sidlemodes & BIT(SYSC_IDLE_NO))
+ *idlemodes |= SIDLE_NO;
+ if (data->cfg->sidlemodes & BIT(SYSC_IDLE_SMART))
+ *idlemodes |= SIDLE_SMART;
+ if (data->cfg->sidlemodes & BIT(SYSC_IDLE_SMART_WKUP))
+ *idlemodes |= SIDLE_SMART_WKUP;
+
+ return 0;
+}
+
+/**
+ * omap_hwmod_check_module - check new module against platform data
+ * @dev: struct device
+ * @oh: module
+ * @data: new module data
+ * @sysc_fields: sysc register bits
+ * @rev_offs: revision register offset
+ * @sysc_offs: sysconfig register offset
+ * @syss_offs: sysstatus register offset
+ * @sysc_flags: sysc specific flags
+ * @idlemodes: sysc supported idlemodes
+ */
+static int omap_hwmod_check_module(struct device *dev,
+ struct omap_hwmod *oh,
+ const struct ti_sysc_module_data *data,
+ struct sysc_regbits *sysc_fields,
+ u32 rev_offs, u32 sysc_offs,
+ u32 syss_offs, u32 sysc_flags,
+ u32 idlemodes)
+{
+ if (!oh->class->sysc)
+ return -ENODEV;
+
+ if (sysc_fields != oh->class->sysc->sysc_fields)
+ dev_warn(dev, "sysc_fields %p != %p\n", sysc_fields,
+ oh->class->sysc->sysc_fields);
+
+ if (rev_offs != oh->class->sysc->rev_offs)
+ dev_warn(dev, "rev_offs %08x != %08x\n", rev_offs,
+ oh->class->sysc->rev_offs);
+ if (sysc_offs != oh->class->sysc->sysc_offs)
+ dev_warn(dev, "sysc_offs %08x != %08x\n", sysc_offs,
+ oh->class->sysc->sysc_offs);
+ if (syss_offs != oh->class->sysc->syss_offs)
+ dev_warn(dev, "syss_offs %08x != %08x\n", syss_offs,
+ oh->class->sysc->syss_offs);
+
+ if (sysc_flags != oh->class->sysc->sysc_flags)
+ dev_warn(dev, "sysc_flags %08x != %08x\n", sysc_flags,
+ oh->class->sysc->sysc_flags);
+
+ if (idlemodes != oh->class->sysc->idlemodes)
+ dev_warn(dev, "idlemodes %08x != %08x\n", idlemodes,
+ oh->class->sysc->idlemodes);
+
+ if (data->cfg->srst_udelay != oh->class->sysc->srst_udelay)
+ dev_warn(dev, "srst_udelay %i != %i\n",
+ data->cfg->srst_udelay,
+ oh->class->sysc->srst_udelay);
+
+ return 0;
+}
+
+/**
+ * omap_hwmod_allocate_module - allocate new module
+ * @dev: struct device
+ * @oh: module
+ * @sysc_fields: sysc register bits
+ * @rev_offs: revision register offset
+ * @sysc_offs: sysconfig register offset
+ * @syss_offs: sysstatus register offset
+ * @sysc_flags: sysc specific flags
+ * @idlemodes: sysc supported idlemodes
+ *
+ * Note that the allocations here cannot use devm as ti-sysc can rebind.
+ */
+int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
+ const struct ti_sysc_module_data *data,
+ struct sysc_regbits *sysc_fields,
+ u32 rev_offs, u32 sysc_offs, u32 syss_offs,
+ u32 sysc_flags, u32 idlemodes)
+{
+ struct omap_hwmod_class_sysconfig *sysc;
+ struct omap_hwmod_class *class;
+ void __iomem *regs = NULL;
+ unsigned long flags;
+
+ sysc = kzalloc(sizeof(*sysc), GFP_KERNEL);
+ if (!sysc)
+ return -ENOMEM;
+
+ sysc->sysc_fields = sysc_fields;
+ sysc->rev_offs = rev_offs;
+ sysc->sysc_offs = sysc_offs;
+ sysc->syss_offs = syss_offs;
+ sysc->sysc_flags = sysc_flags;
+ sysc->idlemodes = idlemodes;
+ sysc->srst_udelay = data->cfg->srst_udelay;
+
+ if (!oh->_mpu_rt_va) {
+ regs = ioremap(data->module_pa,
+ data->module_size);
+ if (!regs)
+ return -ENOMEM;
+ }
+
+ /*
+ * We need new oh->class as the other devices in the same class
+ * may not yet have ioremapped their registers.
+ */
+ class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL);
+ if (!class)
+ return -ENOMEM;
+
+ class->sysc = sysc;
+
+ spin_lock_irqsave(&oh->_lock, flags);
+ if (regs)
+ oh->_mpu_rt_va = regs;
+ oh->class = class;
+ oh->_state = _HWMOD_STATE_INITIALIZED;
+ _setup(oh, NULL);
+ spin_unlock_irqrestore(&oh->_lock, flags);
+
+ return 0;
+}
+
+/**
+ * omap_hwmod_init_module - initialize new module
+ * @dev: struct device
+ * @data: module data
+ * @cookie: cookie for the caller to use for later calls
+ */
+int omap_hwmod_init_module(struct device *dev,
+ const struct ti_sysc_module_data *data,
+ struct ti_sysc_cookie *cookie)
+{
+ struct omap_hwmod *oh;
+ struct sysc_regbits *sysc_fields;
+ u32 rev_offs, sysc_offs, syss_offs, sysc_flags, idlemodes;
+ int error;
+
+ if (!dev || !data)
+ return -EINVAL;
+
+ oh = _lookup(data->name);
+ if (!oh)
+ return -ENODEV;
+
+ cookie->data = oh;
+
+ error = omap_hwmod_init_regbits(dev, data, &sysc_fields);
+ if (error)
+ return error;
+
+ error = omap_hwmod_init_reg_offs(dev, data, &rev_offs,
+ &sysc_offs, &syss_offs);
+ if (error)
+ return error;
+
+ error = omap_hwmod_init_sysc_flags(dev, data, &sysc_flags);
+ if (error)
+ return error;
+
+ error = omap_hwmod_init_idlemodes(dev, data, &idlemodes);
+ if (error)
+ return error;
+
+ if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE_ON_INIT)
+ oh->flags |= HWMOD_INIT_NO_IDLE;
+ if (data->cfg->quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
+ oh->flags |= HWMOD_INIT_NO_RESET;
+
+ error = omap_hwmod_check_module(dev, oh, data, sysc_fields,
+ rev_offs, sysc_offs, syss_offs,
+ sysc_flags, idlemodes);
+ if (!error)
+ return error;
+
+ return omap_hwmod_allocate_module(dev, oh, data, sysc_fields,
+ rev_offs, sysc_offs, syss_offs,
+ sysc_flags, idlemodes);
+}
+
/**
* omap_hwmod_setup_earlycon_flags - set up flags for early console
*
@@ -3082,6 +3492,12 @@ static void __init omap_hwmod_setup_earlycon_flags(void)
if (np) {
uart = of_get_property(np, "ti,hwmods", NULL);
oh = omap_hwmod_lookup(uart);
+ if (!oh) {
+ uart = of_get_property(np->parent,
+ "ti,hwmods",
+ NULL);
+ oh = omap_hwmod_lookup(uart);
+ }
if (oh)
oh->flags |= DEBUG_OMAPUART_FLAGS;
}
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
index 0b8e19f..c7122ab 100644
--- a/arch/arm/mach-omap2/omap_hwmod.h
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -620,6 +620,13 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh,
struct device_node *np,
struct resource *res);
+struct ti_sysc_module_data;
+struct ti_sysc_cookie;
+
+int omap_hwmod_init_module(struct device *dev,
+ const struct ti_sysc_module_data *data,
+ struct ti_sysc_cookie *cookie);
+
int omap_hwmod_enable(struct omap_hwmod *oh);
int omap_hwmod_idle(struct omap_hwmod *oh);
int omap_hwmod_shutdown(struct omap_hwmod *oh);
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index e7d7fc7..6459816 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -17,12 +17,14 @@
#include <linux/wl12xx.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
+#include <linux/power/smartreflex.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/platform_data/pinctrl-single.h>
#include <linux/platform_data/hsmmc-omap.h>
#include <linux/platform_data/iommu-omap.h>
+#include <linux/platform_data/ti-sysc.h>
#include <linux/platform_data/wkup_m3.h>
#include <linux/platform_data/media/ir-rx51.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
@@ -452,6 +454,43 @@ static void __init dra7x_evm_mmc_quirk(void)
}
#endif
+static int ti_sysc_enable_module(struct device *dev,
+ const struct ti_sysc_cookie *cookie)
+{
+ if (!cookie->data)
+ return -EINVAL;
+
+ return omap_hwmod_enable(cookie->data);
+}
+
+static int ti_sysc_idle_module(struct device *dev,
+ const struct ti_sysc_cookie *cookie)
+{
+ if (!cookie->data)
+ return -EINVAL;
+
+ return omap_hwmod_idle(cookie->data);
+}
+
+static int ti_sysc_shutdown_module(struct device *dev,
+ const struct ti_sysc_cookie *cookie)
+{
+ if (!cookie->data)
+ return -EINVAL;
+
+ return omap_hwmod_shutdown(cookie->data);
+}
+
+static struct of_dev_auxdata omap_auxdata_lookup[];
+
+static struct ti_sysc_platform_data ti_sysc_pdata = {
+ .auxdata = omap_auxdata_lookup,
+ .init_module = omap_hwmod_init_module,
+ .enable_module = ti_sysc_enable_module,
+ .idle_module = ti_sysc_idle_module,
+ .shutdown_module = ti_sysc_shutdown_module,
+};
+
static struct pcs_pdata pcs_pdata;
void omap_pcs_legacy_init(int irq, void (*rearm)(void))
@@ -513,7 +552,9 @@ static struct pdata_init auxdata_quirks[] __initdata = {
{ /* sentinel */ },
};
-static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
+struct omap_sr_data __maybe_unused omap_sr_pdata[OMAP_SR_NR];
+
+static struct of_dev_auxdata omap_auxdata_lookup[] = {
#ifdef CONFIG_MACH_NOKIA_N8X0
OF_DEV_AUXDATA("ti,omap2420-mmc", 0x4809c000, "mmci-omap.0", NULL),
OF_DEV_AUXDATA("menelaus", 0x72, "1-0072", &n8x0_menelaus_platform_data),
@@ -522,6 +563,10 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
#ifdef CONFIG_ARCH_OMAP3
OF_DEV_AUXDATA("ti,omap2-iommu", 0x5d000000, "5d000000.mmu",
&omap3_iommu_pdata),
+ OF_DEV_AUXDATA("ti,omap3-smartreflex-core", 0x480cb000,
+ "480cb000.smartreflex", &omap_sr_pdata[OMAP_SR_CORE]),
+ OF_DEV_AUXDATA("ti,omap3-smartreflex-mpu-iva", 0x480c9000,
+ "480c9000.smartreflex", &omap_sr_pdata[OMAP_SR_MPU]),
OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x4809c000, "4809c000.mmc", &mmc_pdata[0]),
OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x480b4000, "480b4000.mmc", &mmc_pdata[1]),
OF_DEV_AUXDATA("nokia,n900-ir", 0, "n900-ir", &rx51_ir_data),
@@ -548,6 +593,12 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
&omap4_iommu_pdata),
OF_DEV_AUXDATA("ti,omap4-iommu", 0x55082000, "55082000.mmu",
&omap4_iommu_pdata),
+ OF_DEV_AUXDATA("ti,omap4-smartreflex-iva", 0x4a0db000,
+ "4a0db000.smartreflex", &omap_sr_pdata[OMAP_SR_IVA]),
+ OF_DEV_AUXDATA("ti,omap4-smartreflex-core", 0x4a0dd000,
+ "4a0dd000.smartreflex", &omap_sr_pdata[OMAP_SR_CORE]),
+ OF_DEV_AUXDATA("ti,omap4-smartreflex-mpu", 0x4a0d9000,
+ "4a0d9000.smartreflex", &omap_sr_pdata[OMAP_SR_MPU]),
#endif
#ifdef CONFIG_SOC_DRA7XX
OF_DEV_AUXDATA("ti,dra7-hsmmc", 0x4809c000, "4809c000.mmc",
@@ -558,6 +609,7 @@ static struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
&dra7_hsmmc_data_mmc3),
#endif
/* Common auxdata */
+ OF_DEV_AUXDATA("ti,sysc", 0, NULL, &ti_sysc_pdata),
OF_DEV_AUXDATA("pinctrl-single", 0, NULL, &pcs_pdata),
{ /* sentinel */ },
};
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index eef6935..0854ed9 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -89,18 +89,27 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
sr_data->nvalue_count = j;
}
+extern struct omap_sr_data omap_sr_pdata[];
+
static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
{
- struct omap_sr_data *sr_data;
- struct platform_device *pdev;
+ struct omap_sr_data *sr_data = NULL;
struct omap_volt_data *volt_data;
struct omap_smartreflex_dev_attr *sr_dev_attr;
- char *name = "smartreflex";
static int i;
- sr_data = kzalloc(sizeof(*sr_data), GFP_KERNEL);
- if (!sr_data)
- return -ENOMEM;
+ if (!strncmp(oh->name, "smartreflex_mpu_iva", 20) ||
+ !strncmp(oh->name, "smartreflex_mpu", 16))
+ sr_data = &omap_sr_pdata[OMAP_SR_MPU];
+ else if (!strncmp(oh->name, "smartreflex_core", 17))
+ sr_data = &omap_sr_pdata[OMAP_SR_CORE];
+ else if (!strncmp(oh->name, "smartreflex_iva", 16))
+ sr_data = &omap_sr_pdata[OMAP_SR_IVA];
+
+ if (!sr_data) {
+ pr_err("%s: Unknown instance %s\n", __func__, oh->name);
+ return -EINVAL;
+ }
sr_dev_attr = (struct omap_smartreflex_dev_attr *)oh->dev_attr;
if (!sr_dev_attr || !sr_dev_attr->sensor_voltdm_name) {
@@ -145,13 +154,9 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
sr_data->enable_on_init = sr_enable_on_init;
- pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data));
- if (IS_ERR(pdev))
- pr_warn("%s: Could not build omap_device for %s: %s\n",
- __func__, name, oh->name);
exit:
i++;
- kfree(sr_data);
+
return 0;
}
OpenPOWER on IntegriCloud