diff options
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 234 |
1 files changed, 58 insertions, 176 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index a136788db839..ba71928c0fcb 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -627,6 +627,9 @@ static struct clockdomain *_get_clkdm(struct omap_hwmod *oh) { struct clk_hw_omap *clk; + if (!oh) + return NULL; + if (oh->clkdm) { return oh->clkdm; } else if (oh->_clk) { @@ -703,9 +706,7 @@ static const struct of_device_id ti_clkctrl_match_table[] __initconst = { static int __init _setup_clkctrl_provider(struct device_node *np) { - const __be32 *addrp; struct clkctrl_provider *provider; - u64 size; int i; provider = memblock_alloc(sizeof(*provider), SMP_CACHE_BYTES); @@ -714,8 +715,7 @@ static int __init _setup_clkctrl_provider(struct device_node *np) provider->node = np; - provider->num_addrs = - of_property_count_elems_of_size(np, "reg", sizeof(u32)) / 2; + provider->num_addrs = of_address_count(np); provider->addr = memblock_alloc(sizeof(void *) * provider->num_addrs, @@ -730,11 +730,11 @@ static int __init _setup_clkctrl_provider(struct device_node *np) return -ENOMEM; for (i = 0; i < provider->num_addrs; i++) { - addrp = of_get_address(np, i, &size, NULL); - provider->addr[i] = (u32)of_translate_address(np, addrp); - provider->size[i] = size; - pr_debug("%s: %pOF: %x...%x\n", __func__, np, provider->addr[i], - provider->addr[i] + provider->size[i]); + struct resource res; + of_address_to_resource(np, i, &res); + provider->addr[i] = res.start; + provider->size[i] = resource_size(&res); + pr_debug("%s: %pOF: %pR\n", __func__, np, &res); } list_add(&provider->link, &clkctrl_providers); @@ -749,8 +749,10 @@ static int __init _init_clkctrl_providers(void) for_each_matching_node(np, ti_clkctrl_match_table) { ret = _setup_clkctrl_provider(np); - if (ret) + if (ret) { + of_node_put(np); break; + } } return ret; @@ -809,7 +811,7 @@ static struct clk *_lookup_clkctrl_clk(struct omap_hwmod *oh) } /** - * _init_main_clk - get a struct clk * for the the hwmod's main functional clk + * _init_main_clk - get a struct clk * for the hwmod's main functional clk * @oh: struct omap_hwmod * * * Called from _init_clocks(). Populates the @oh _clk (main @@ -859,7 +861,7 @@ static int _init_main_clk(struct omap_hwmod *oh) } /** - * _init_interface_clks - get a struct clk * for the the hwmod's interface clks + * _init_interface_clks - get a struct clk * for the hwmod's interface clks * @oh: struct omap_hwmod * * * Called from _init_clocks(). Populates the @oh OCP slave interface @@ -898,7 +900,7 @@ static int _init_interface_clks(struct omap_hwmod *oh) } /** - * _init_opt_clk - get a struct clk * for the the hwmod's optional clocks + * _init_opt_clk - get a struct clk * for the hwmod's optional clocks * @oh: struct omap_hwmod * * * Called from _init_clocks(). Populates the @oh omap_hwmod_opt_clk @@ -1853,23 +1855,6 @@ static int _omap4_get_context_lost(struct omap_hwmod *oh) } /** - * _enable_preprogram - Pre-program an IP block during the _enable() process - * @oh: struct omap_hwmod * - * - * Some IP blocks (such as AESS) require some additional programming - * after enable before they can enter idle. If a function pointer to - * do so is present in the hwmod data, then call it and pass along the - * return value; otherwise, return 0. - */ -static int _enable_preprogram(struct omap_hwmod *oh) -{ - if (!oh->class->enable_preprogram) - return 0; - - return oh->class->enable_preprogram(oh); -} - -/** * _enable - enable an omap_hwmod * @oh: struct omap_hwmod * * @@ -1952,7 +1937,6 @@ static int _enable(struct omap_hwmod *oh) _update_sysc_cache(oh); _enable_sysc(oh); } - r = _enable_preprogram(oh); } else { if (soc_ops.disable_module) soc_ops.disable_module(oh); @@ -2152,6 +2136,7 @@ static int of_dev_hwmod_lookup(struct device_node *np, if (res == 0) { *found = fc; *index = i; + of_node_put(np0); return 0; } } @@ -2209,23 +2194,8 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh, struct resource *res) { struct property *prop; - const __be32 *ranges; const char *name; - u32 nr_addr, nr_size; - u64 base, size; - int len, error; - - if (!res) - return -EINVAL; - - ranges = of_get_property(np, "ranges", &len); - if (!ranges) - return -ENOENT; - - len /= sizeof(*ranges); - - if (len < 3) - return -EINVAL; + int err; of_property_for_each_string(np, "compatible", prop, name) if (!strncmp("ti,sysc-", name, 8)) @@ -2234,26 +2204,12 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh, if (!name) return -ENOENT; - error = of_property_read_u32(np, "#address-cells", &nr_addr); - if (error) - return -ENOENT; + err = of_range_to_resource(np, 0, res); + if (err) + return err; - error = of_property_read_u32(np, "#size-cells", &nr_size); - if (error) - return -ENOENT; - - if (nr_addr != 1 || nr_size != 1) { - pr_err("%s: invalid range for %s->%pOFn\n", __func__, - oh->name, np); - return -EINVAL; - } - - ranges++; - base = of_translate_address(np, ranges++); - size = be32_to_cpup(ranges); - - pr_debug("omap_hwmod: %s %pOFn at 0x%llx size 0x%llx\n", - oh->name, np, base, size); + pr_debug("omap_hwmod: %s %pOFn at %pR\n", + oh->name, np, res); if (oh && oh->mpu_rt_idx) { omap_hwmod_fix_mpu_rt_idx(oh, np, res); @@ -2261,10 +2217,6 @@ int omap_hwmod_parse_module_range(struct omap_hwmod *oh, return 0; } - res->start = base; - res->end = base + size - 1; - res->flags = IORESOURCE_MEM; - return 0; } @@ -2334,11 +2286,11 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, static void __init parse_module_flags(struct omap_hwmod *oh, struct device_node *np) { - if (of_find_property(np, "ti,no-reset-on-init", NULL)) + if (of_property_read_bool(np, "ti,no-reset-on-init")) oh->flags |= HWMOD_INIT_NO_RESET; - if (of_find_property(np, "ti,no-idle-on-init", NULL)) + if (of_property_read_bool(np, "ti,no-idle-on-init")) oh->flags |= HWMOD_INIT_NO_IDLE; - if (of_find_property(np, "ti,no-idle", NULL)) + if (of_property_read_bool(np, "ti,no-idle")) oh->flags |= HWMOD_NO_IDLE; } @@ -3066,6 +3018,8 @@ int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois) return 0; } +static int __init omap_hwmod_setup_one(const char *oh_name); + /** * _ensure_mpu_hwmod_is_setup - ensure the MPU SS hwmod is init'ed and set up * @oh: pointer to the hwmod currently being set up (usually not the MPU) @@ -3096,7 +3050,7 @@ static void __init _ensure_mpu_hwmod_is_setup(struct omap_hwmod *oh) * registered omap_hwmod. Also calls _setup() on each hwmod. Returns * -EINVAL upon error or 0 upon success. */ -int __init omap_hwmod_setup_one(const char *oh_name) +static int __init omap_hwmod_setup_one(const char *oh_name) { struct omap_hwmod *oh; @@ -3166,15 +3120,14 @@ static int omap_hwmod_check_sysc(struct device *dev, /** * omap_hwmod_init_regbits - init sysconfig specific register bits * @dev: struct device + * @oh: module * @data: module data * @sysc_fields: new sysc configuration */ -static int omap_hwmod_init_regbits(struct device *dev, +static int omap_hwmod_init_regbits(struct device *dev, struct omap_hwmod *oh, 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: @@ -3209,6 +3162,12 @@ static int omap_hwmod_init_regbits(struct device *dev, *sysc_fields = &omap_hwmod_sysc_type_usb_host_fs; break; default: + *sysc_fields = NULL; + if (!oh->class->sysc->sysc_fields) + return 0; + + dev_err(dev, "sysc_fields not found\n"); + return -EINVAL; } @@ -3374,9 +3333,9 @@ static int omap_hwmod_check_module(struct device *dev, 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 (oh->class->sysc->sysc_fields && + sysc_fields != oh->class->sysc->sysc_fields) + dev_warn(dev, "sysc_fields mismatch\n"); if (rev_offs != oh->class->sysc->rev_offs) dev_warn(dev, "rev_offs %08x != %08x\n", rev_offs, @@ -3448,7 +3407,7 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, regs = ioremap(data->module_pa, data->module_size); if (!regs) - return -ENOMEM; + goto out_free_sysc; } /* @@ -3458,13 +3417,13 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, if (oh->class->name && strcmp(oh->class->name, data->name)) { class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL); if (!class) - return -ENOMEM; + goto out_unmap; } if (list_empty(&oh->slave_ports)) { - oi = kcalloc(1, sizeof(*oi), GFP_KERNEL); + oi = kzalloc(sizeof(*oi), GFP_KERNEL); if (!oi) - return -ENOMEM; + goto out_free_class; /* * Note that we assume interconnect interface clocks will be @@ -3491,18 +3450,22 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, spin_unlock_irqrestore(&oh->_lock, flags); return 0; + +out_free_class: + kfree(class); +out_unmap: + iounmap(regs); +out_free_sysc: + kfree(sysc); + return -ENOMEM; } static const struct omap_hwmod_reset omap24xx_reset_quirks[] = { { .match = "msdi", .len = 4, .reset = omap_msdi_reset, }, }; -static const struct omap_hwmod_reset dra7_reset_quirks[] = { - { .match = "pcie", .len = 4, .reset = dra7xx_pciess_reset, }, -}; - static const struct omap_hwmod_reset omap_reset_quirks[] = { - { .match = "dss", .len = 3, .reset = omap_dss_reset, }, + { .match = "dss_core", .len = 8, .reset = omap_dss_reset, }, { .match = "hdq1w", .len = 5, .reset = omap_hdq1w_reset, }, { .match = "i2c", .len = 3, .reset = omap_i2c_reset, }, { .match = "wd_timer", .len = 8, .reset = omap2_wd_timer_reset, }, @@ -3536,10 +3499,6 @@ omap_hwmod_init_reset_quirks(struct device *dev, struct omap_hwmod *oh, omap24xx_reset_quirks, ARRAY_SIZE(omap24xx_reset_quirks)); - if (soc_is_dra7xx()) - omap_hwmod_init_reset_quirk(dev, oh, data, dra7_reset_quirks, - ARRAY_SIZE(dra7_reset_quirks)); - omap_hwmod_init_reset_quirk(dev, oh, data, omap_reset_quirks, ARRAY_SIZE(omap_reset_quirks)); } @@ -3592,7 +3551,7 @@ int omap_hwmod_init_module(struct device *dev, cookie->data = oh; - error = omap_hwmod_init_regbits(dev, data, &sysc_fields); + error = omap_hwmod_init_regbits(dev, oh, data, &sysc_fields); if (error) return error; @@ -3623,6 +3582,8 @@ int omap_hwmod_init_module(struct device *dev, oh->flags |= HWMOD_SWSUP_SIDLE_ACT; if (data->cfg->quirks & SYSC_QUIRK_SWSUP_MSTANDBY) oh->flags |= HWMOD_SWSUP_MSTANDBY; + if (data->cfg->quirks & SYSC_QUIRK_CLKDM_NOAUTO) + oh->flags |= HWMOD_CLKDM_NOAUTO; error = omap_hwmod_check_module(dev, oh, data, sysc_fields, rev_offs, sysc_offs, syss_offs, @@ -3682,6 +3643,9 @@ static void __init omap_hwmod_setup_earlycon_flags(void) */ static int __init omap_hwmod_setup_all(void) { + if (!inited) + return 0; + _ensure_mpu_hwmod_is_setup(NULL); omap_hwmod_for_each(_init, NULL); @@ -3766,47 +3730,6 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh) */ /** - * omap_hwmod_get_pwrdm - return pointer to this module's main powerdomain - * @oh: struct omap_hwmod * - * - * Return the powerdomain pointer associated with the OMAP module - * @oh's main clock. If @oh does not have a main clk, return the - * powerdomain associated with the interface clock associated with the - * module's MPU port. (XXX Perhaps this should use the SDMA port - * instead?) Returns NULL on error, or a struct powerdomain * on - * success. - */ -struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh) -{ - struct clk *c; - struct omap_hwmod_ocp_if *oi; - struct clockdomain *clkdm; - struct clk_hw_omap *clk; - - if (!oh) - return NULL; - - if (oh->clkdm) - return oh->clkdm->pwrdm.ptr; - - if (oh->_clk) { - c = oh->_clk; - } else { - oi = _find_mpu_rt_port(oh); - if (!oi) - return NULL; - c = oi->_clk; - } - - clk = to_clk_hw_omap(__clk_get_hw(c)); - clkdm = clk->clkdm; - if (!clkdm) - return NULL; - - return clkdm->pwrdm.ptr; -} - -/** * omap_hwmod_get_mpu_rt_va - return the module's base address (for the MPU) * @oh: struct omap_hwmod * * @@ -3972,32 +3895,6 @@ ohsps_unlock: } /** - * omap_hwmod_get_context_loss_count - get lost context count - * @oh: struct omap_hwmod * - * - * Returns the context loss count of associated @oh - * upon success, or zero if no context loss data is available. - * - * On OMAP4, this queries the per-hwmod context loss register, - * assuming one exists. If not, or on OMAP2/3, this queries the - * enclosing powerdomain context loss count. - */ -int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh) -{ - struct powerdomain *pwrdm; - int ret = 0; - - if (soc_ops.get_context_lost) - return soc_ops.get_context_lost(oh); - - pwrdm = omap_hwmod_get_pwrdm(oh); - if (pwrdm) - ret = pwrdm_get_context_loss_count(pwrdm); - - return ret; -} - -/** * omap_hwmod_init - initialize the hwmod code * * Sets up some function pointers needed by the hwmod code to operate on the @@ -4048,18 +3945,3 @@ void __init omap_hwmod_init(void) inited = true; } - -/** - * omap_hwmod_get_main_clk - get pointer to main clock name - * @oh: struct omap_hwmod * - * - * Returns the main clock name assocated with @oh upon success, - * or NULL if @oh is NULL. - */ -const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh) -{ - if (!oh) - return NULL; - - return oh->main_clk; -} |