]> Pileus Git - ~andy/linux/commitdiff
ARM: OMAP2+: hwmod: use init-time function ptrs for enable/disable module
authorKevin Hilman <khilman@ti.com>
Mon, 18 Jun 2012 18:12:23 +0000 (12:12 -0600)
committerPaul Walmsley <paul@pwsan.com>
Mon, 18 Jun 2012 18:12:23 +0000 (12:12 -0600)
The enable/disable module functions are specific to SoCs with
OMAP4-class PRCM.  Rather than use cpu_is* checks at runtime inside
the enable/disable module functions, use cpu_is at init time to
initialize function pointers only for SoCs that need them.

NOTE: the cpu_is* check for _enable_module was different than
      the one for _disable_module, and this patch uses
      cpu_is_omap44xx() for both.

Signed-off-by: Kevin Hilman <khilman@ti.com>
[paul@pwsan.com: moved soc_ops function pointers to be per-kernel rather than
 per-hwmod since they do not vary by hwmod; added kerneldoc]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/plat-omap/include/plat/omap_hwmod.h

index 939032a427fd641325c0ea9329ecb99196419b22..634a79836c646cebded12c005633afbefe0eaa76 100644 (file)
  */
 #define LINKS_PER_OCP_IF               2
 
+/**
+ * struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations
+ * @enable_module: function to enable a module (via MODULEMODE)
+ * @disable_module: function to disable a module (via MODULEMODE)
+ *
+ * XXX Eventually this functionality will be hidden inside the PRM/CM
+ * device drivers.  Until then, this should avoid huge blocks of cpu_is_*()
+ * conditionals in this code.
+ */
+struct omap_hwmod_soc_ops {
+       void (*enable_module)(struct omap_hwmod *oh);
+       int (*disable_module)(struct omap_hwmod *oh);
+};
+
+/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
+static struct omap_hwmod_soc_ops soc_ops;
+
 /* omap_hwmod_list contains all registered struct omap_hwmods */
 static LIST_HEAD(omap_hwmod_list);
 
@@ -186,6 +203,9 @@ static struct omap_hwmod_link *linkspace;
  */
 static unsigned short free_ls, max_ls, ls_supp;
 
+/* inited: set to true once the hwmod code is initialized */
+static bool inited;
+
 /* Private functions */
 
 /**
@@ -779,10 +799,6 @@ static void _disable_optional_clocks(struct omap_hwmod *oh)
  */
 static void _omap4_enable_module(struct omap_hwmod *oh)
 {
-       /* The module mode does not exist prior OMAP4 */
-       if (cpu_is_omap24xx() || cpu_is_omap34xx())
-               return;
-
        if (!oh->clkdm || !oh->prcm.omap4.modulemode)
                return;
 
@@ -1571,10 +1587,6 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
 {
        int v;
 
-       /* The module mode does not exist prior OMAP4 */
-       if (!cpu_is_omap44xx())
-               return -EINVAL;
-
        if (!oh->clkdm || !oh->prcm.omap4.modulemode)
                return -EINVAL;
 
@@ -1814,7 +1826,8 @@ static int _enable(struct omap_hwmod *oh)
        }
 
        _enable_clocks(oh);
-       _omap4_enable_module(oh);
+       if (soc_ops.enable_module)
+               soc_ops.enable_module(oh);
 
        r = _wait_target_ready(oh);
        if (!r) {
@@ -1870,7 +1883,8 @@ static int _idle(struct omap_hwmod *oh)
                _idle_sysc(oh);
        _del_initiator_dep(oh, mpu_oh);
 
-       _omap4_disable_module(oh);
+       if (soc_ops.disable_module)
+               soc_ops.disable_module(oh);
 
        /*
         * The module must be in idle mode before disabling any parents
@@ -1975,7 +1989,8 @@ static int _shutdown(struct omap_hwmod *oh)
        if (oh->_state == _HWMOD_STATE_ENABLED) {
                _del_initiator_dep(oh, mpu_oh);
                /* XXX what about the other system initiators here? dma, dsp */
-               _omap4_disable_module(oh);
+               if (soc_ops.disable_module)
+                       soc_ops.disable_module(oh);
                _disable_clocks(oh);
                if (oh->clkdm)
                        clkdm_hwmod_disable(oh->clkdm, oh);
@@ -2563,12 +2578,18 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
  *
  * Intended to be called early in boot before the clock framework is
  * initialized.  If @ois is not null, will register all omap_hwmods
- * listed in @ois that are valid for this chip.  Returns 0.
+ * listed in @ois that are valid for this chip.  Returns -EINVAL if
+ * omap_hwmod_init() hasn't been called before calling this function,
+ * -ENOMEM if the link memory area can't be allocated, or 0 upon
+ * success.
  */
 int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois)
 {
        int r, i;
 
+       if (!inited)
+               return -EINVAL;
+
        if (!ois)
                return 0;
 
@@ -3401,3 +3422,20 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx)
 
        return 0;
 }
+
+/**
+ * omap_hwmod_init - initialize the hwmod code
+ *
+ * Sets up some function pointers needed by the hwmod code to operate on the
+ * currently-booted SoC.  Intended to be called once during kernel init
+ * before any hwmods are registered.  No return value.
+ */
+void __init omap_hwmod_init(void)
+{
+       if (cpu_is_omap44xx()) {
+               soc_ops.enable_module = _omap4_enable_module;
+               soc_ops.disable_module = _omap4_disable_module;
+       }
+
+       inited = true;
+}
index a7640d1b215e7f94f5dc8fea09738930d75a0208..5b1938b52d09bd31e897351672c304cb89994582 100644 (file)
@@ -585,5 +585,6 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 
 int __init omap2420_hwmod_init(void)
 {
+       omap_hwmod_init();
        return omap_hwmod_register_links(omap2420_hwmod_ocp_ifs);
 }
index 4d72649812303cddc2c1eeb73f6bee3bcd4c4027..71f199783c63c007db59f53d962ed8a1ee51468e 100644 (file)
@@ -938,5 +938,6 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 
 int __init omap2430_hwmod_init(void)
 {
+       omap_hwmod_init();
        return omap_hwmod_register_links(omap2430_hwmod_ocp_ifs);
 }
index b26d3c9bca1621cab9ac87eea39aff6cc489fc24..abb1f6b56ee51b1e7dee47d23742184349a811d7 100644 (file)
@@ -3283,6 +3283,8 @@ int __init omap3xxx_hwmod_init(void)
        struct omap_hwmod_ocp_if **h = NULL;
        unsigned int rev;
 
+       omap_hwmod_init();
+
        /* Register hwmod links common to all OMAP3 */
        r = omap_hwmod_register_links(omap3xxx_hwmod_ocp_ifs);
        if (r < 0)
index 950454a3fa314da4448c99eeaaf50f81201b382b..d3c48dc26af1e1757776cbc76c678c504b85e7a8 100644 (file)
@@ -6144,6 +6144,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
 
 int __init omap44xx_hwmod_init(void)
 {
+       omap_hwmod_init();
        return omap_hwmod_register_links(omap44xx_hwmod_ocp_ifs);
 }
 
index c835b7194ff57ba71d5448746ea21e6134e39ef7..a8ecc53b3670cea57fcce1a9c3487d0a2f786a47 100644 (file)
@@ -629,6 +629,8 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
 int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx);
 
+extern void __init omap_hwmod_init(void);
+
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out