|
@@ -185,15 +185,15 @@
|
|
|
/**
|
|
|
* struct clkctrl_provider - clkctrl provider mapping data
|
|
|
* @addr: base address for the provider
|
|
|
- * @offset: base offset for the provider
|
|
|
- * @clkdm: base clockdomain for provider
|
|
|
+ * @size: size of the provider address space
|
|
|
+ * @offset: offset of the provider from PRCM instance base
|
|
|
* @node: device node associated with the provider
|
|
|
* @link: list link
|
|
|
*/
|
|
|
struct clkctrl_provider {
|
|
|
u32 addr;
|
|
|
+ u32 size;
|
|
|
u16 offset;
|
|
|
- struct clockdomain *clkdm;
|
|
|
struct device_node *node;
|
|
|
struct list_head link;
|
|
|
};
|
|
@@ -223,8 +223,7 @@ struct omap_hwmod_soc_ops {
|
|
|
void (*update_context_lost)(struct omap_hwmod *oh);
|
|
|
int (*get_context_lost)(struct omap_hwmod *oh);
|
|
|
int (*disable_direct_prcm)(struct omap_hwmod *oh);
|
|
|
- u32 (*xlate_clkctrl)(struct omap_hwmod *oh,
|
|
|
- struct clkctrl_provider *provider);
|
|
|
+ u32 (*xlate_clkctrl)(struct omap_hwmod *oh);
|
|
|
};
|
|
|
|
|
|
/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
|
|
@@ -716,45 +715,28 @@ static const struct of_device_id ti_clkctrl_match_table[] __initconst = {
|
|
|
{ }
|
|
|
};
|
|
|
|
|
|
-static int _match_clkdm(struct clockdomain *clkdm, void *user)
|
|
|
-{
|
|
|
- struct clkctrl_provider *provider = user;
|
|
|
-
|
|
|
- if (clkdm_xlate_address(clkdm) == provider->addr) {
|
|
|
- pr_debug("%s: Matched clkdm %s for addr %x (%s)\n", __func__,
|
|
|
- clkdm->name, provider->addr,
|
|
|
- provider->node->parent->name);
|
|
|
- provider->clkdm = clkdm;
|
|
|
-
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int _setup_clkctrl_provider(struct device_node *np)
|
|
|
{
|
|
|
const __be32 *addrp;
|
|
|
struct clkctrl_provider *provider;
|
|
|
+ u64 size;
|
|
|
|
|
|
provider = memblock_virt_alloc(sizeof(*provider), 0);
|
|
|
if (!provider)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- addrp = of_get_address(np, 0, NULL, NULL);
|
|
|
+ addrp = of_get_address(np, 0, &size, NULL);
|
|
|
provider->addr = (u32)of_translate_address(np, addrp);
|
|
|
- provider->offset = provider->addr & 0xff;
|
|
|
+ addrp = of_get_address(np->parent, 0, NULL, NULL);
|
|
|
+ provider->offset = provider->addr -
|
|
|
+ (u32)of_translate_address(np->parent, addrp);
|
|
|
provider->addr &= ~0xff;
|
|
|
+ provider->size = size | 0xff;
|
|
|
provider->node = np;
|
|
|
|
|
|
- clkdm_for_each(_match_clkdm, provider);
|
|
|
-
|
|
|
- if (!provider->clkdm) {
|
|
|
- pr_err("%s: nothing matched for node %s (%x)\n",
|
|
|
- __func__, np->parent->name, provider->addr);
|
|
|
- memblock_free_early(__pa(provider), sizeof(*provider));
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
+ pr_debug("%s: %s: %x...%x [+%x]\n", __func__, np->parent->name,
|
|
|
+ provider->addr, provider->addr + provider->size,
|
|
|
+ provider->offset);
|
|
|
|
|
|
list_add(&provider->link, &clkctrl_providers);
|
|
|
|
|
@@ -775,32 +757,48 @@ static int _init_clkctrl_providers(void)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static u32 _omap4_xlate_clkctrl(struct omap_hwmod *oh,
|
|
|
- struct clkctrl_provider *provider)
|
|
|
+static u32 _omap4_xlate_clkctrl(struct omap_hwmod *oh)
|
|
|
{
|
|
|
- return oh->prcm.omap4.clkctrl_offs -
|
|
|
- provider->offset - provider->clkdm->clkdm_offs;
|
|
|
+ if (!oh->prcm.omap4.modulemode)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return omap_cm_xlate_clkctrl(oh->clkdm->prcm_partition,
|
|
|
+ oh->clkdm->cm_inst,
|
|
|
+ oh->prcm.omap4.clkctrl_offs);
|
|
|
}
|
|
|
|
|
|
static struct clk *_lookup_clkctrl_clk(struct omap_hwmod *oh)
|
|
|
{
|
|
|
struct clkctrl_provider *provider;
|
|
|
struct clk *clk;
|
|
|
+ u32 addr;
|
|
|
|
|
|
if (!soc_ops.xlate_clkctrl)
|
|
|
return NULL;
|
|
|
|
|
|
+ addr = soc_ops.xlate_clkctrl(oh);
|
|
|
+ if (!addr)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ pr_debug("%s: %s: addr=%x\n", __func__, oh->name, addr);
|
|
|
+
|
|
|
list_for_each_entry(provider, &clkctrl_providers, link) {
|
|
|
- if (provider->clkdm == oh->clkdm) {
|
|
|
+ if (provider->addr <= addr &&
|
|
|
+ provider->addr + provider->size >= addr) {
|
|
|
struct of_phandle_args clkspec;
|
|
|
|
|
|
clkspec.np = provider->node;
|
|
|
clkspec.args_count = 2;
|
|
|
- clkspec.args[0] = soc_ops.xlate_clkctrl(oh, provider);
|
|
|
+ clkspec.args[0] = addr - provider->addr -
|
|
|
+ provider->offset;
|
|
|
clkspec.args[1] = 0;
|
|
|
|
|
|
clk = of_clk_get_from_provider(&clkspec);
|
|
|
|
|
|
+ pr_debug("%s: %s got %p (offset=%x, provider=%s)\n",
|
|
|
+ __func__, oh->name, clk, clkspec.args[0],
|
|
|
+ provider->node->parent->name);
|
|
|
+
|
|
|
return clk;
|
|
|
}
|
|
|
}
|