Procházet zdrojové kódy

Merge branch '4.15-rc1-clkctrl-mach-omap2' of https://github.com/t-kristo/linux-pm into omap-for-v4.16/soc

Tony Lindgren před 7 roky
rodič
revize
fdf3632938

+ 0 - 8
arch/arm/mach-omap2/clockdomain.c

@@ -1224,14 +1224,6 @@ ccd_exit:
 	return 0;
 }
 
-u32 clkdm_xlate_address(struct clockdomain *clkdm)
-{
-	if (arch_clkdm->clkdm_xlate_address)
-		return arch_clkdm->clkdm_xlate_address(clkdm);
-
-	return 0;
-}
-
 /**
  * clkdm_hwmod_enable - add an enabled downstream hwmod to this clkdm
  * @clkdm: struct clockdomain *

+ 0 - 2
arch/arm/mach-omap2/clockdomain.h

@@ -175,7 +175,6 @@ struct clkdm_ops {
 	void	(*clkdm_deny_idle)(struct clockdomain *clkdm);
 	int	(*clkdm_clk_enable)(struct clockdomain *clkdm);
 	int	(*clkdm_clk_disable)(struct clockdomain *clkdm);
-	u32	(*clkdm_xlate_address)(struct clockdomain *clkdm);
 };
 
 int clkdm_register_platform_funcs(struct clkdm_ops *co);
@@ -214,7 +213,6 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
 int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
 int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
-u32 clkdm_xlate_address(struct clockdomain *clkdm);
 
 extern void __init omap242x_clockdomains_init(void);
 extern void __init omap243x_clockdomains_init(void);

+ 3 - 0
arch/arm/mach-omap2/cm.h

@@ -52,6 +52,7 @@ extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2);
  * @wait_module_idle: ptr to the SoC CM-specific wait_module_idle impl
  * @module_enable: ptr to the SoC CM-specific module_enable impl
  * @module_disable: ptr to the SoC CM-specific module_disable impl
+ * @xlate_clkctrl: ptr to the SoC CM-specific clkctrl xlate addr impl
  */
 struct cm_ll_data {
 	int (*split_idlest_reg)(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
@@ -62,6 +63,7 @@ struct cm_ll_data {
 				u8 idlest_shift);
 	void (*module_enable)(u8 mode, u8 part, u16 inst, u16 clkctrl_offs);
 	void (*module_disable)(u8 part, u16 inst, u16 clkctrl_offs);
+	u32 (*xlate_clkctrl)(u8 part, u16 inst, u16 clkctrl_offs);
 };
 
 extern int cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
@@ -72,6 +74,7 @@ int omap_cm_wait_module_idle(u8 part, s16 prcm_mod, u16 idlest_reg,
 			     u8 idlest_shift);
 int omap_cm_module_enable(u8 mode, u8 part, u16 inst, u16 clkctrl_offs);
 int omap_cm_module_disable(u8 part, u16 inst, u16 clkctrl_offs);
+u32 omap_cm_xlate_clkctrl(u8 part, u16 inst, u16 clkctrl_offs);
 extern int cm_register(const struct cm_ll_data *cld);
 extern int cm_unregister(const struct cm_ll_data *cld);
 int omap_cm_init(void);

+ 6 - 0
arch/arm/mach-omap2/cm33xx.c

@@ -333,6 +333,11 @@ static int am33xx_clkdm_clk_disable(struct clockdomain *clkdm)
 	return 0;
 }
 
+static u32 am33xx_cm_xlate_clkctrl(u8 part, u16 inst, u16 offset)
+{
+	return cm_base.pa + inst + offset;
+}
+
 struct clkdm_ops am33xx_clkdm_operations = {
 	.clkdm_sleep		= am33xx_clkdm_sleep,
 	.clkdm_wakeup		= am33xx_clkdm_wakeup,
@@ -347,6 +352,7 @@ static const struct cm_ll_data am33xx_cm_ll_data = {
 	.wait_module_idle	= &am33xx_cm_wait_module_idle,
 	.module_enable		= &am33xx_cm_module_enable,
 	.module_disable		= &am33xx_cm_module_disable,
+	.xlate_clkctrl		= &am33xx_cm_xlate_clkctrl,
 };
 
 int __init am33xx_cm_init(const struct omap_prcm_init_data *data)

+ 10 - 0
arch/arm/mach-omap2/cm_common.c

@@ -175,6 +175,16 @@ int omap_cm_module_disable(u8 part, u16 inst, u16 clkctrl_offs)
 	return 0;
 }
 
+u32 omap_cm_xlate_clkctrl(u8 part, u16 inst, u16 clkctrl_offs)
+{
+	if (!cm_ll_data->xlate_clkctrl) {
+		WARN_ONCE(1, "cm: %s: no low-level function defined\n",
+			  __func__);
+		return 0;
+	}
+	return cm_ll_data->xlate_clkctrl(part, inst, clkctrl_offs);
+}
+
 /**
  * cm_register - register per-SoC low-level data with the CM
  * @cld: low-level per-SoC OMAP CM data & function pointers to register

+ 3 - 7
arch/arm/mach-omap2/cminst44xx.c

@@ -476,12 +476,9 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
 	return 0;
 }
 
-static u32 omap4_clkdm_xlate_address(struct clockdomain *clkdm)
+static u32 omap4_cminst_xlate_clkctrl(u8 part, u16 inst, u16 offset)
 {
-	u32 addr = _cm_bases[clkdm->prcm_partition].pa + clkdm->cm_inst +
-		clkdm->clkdm_offs;
-
-	return addr;
+	return _cm_bases[part].pa + inst + offset;
 }
 
 struct clkdm_ops omap4_clkdm_operations = {
@@ -499,7 +496,6 @@ struct clkdm_ops omap4_clkdm_operations = {
 	.clkdm_deny_idle	= omap4_clkdm_deny_idle,
 	.clkdm_clk_enable	= omap4_clkdm_clk_enable,
 	.clkdm_clk_disable	= omap4_clkdm_clk_disable,
-	.clkdm_xlate_address	= omap4_clkdm_xlate_address,
 };
 
 struct clkdm_ops am43xx_clkdm_operations = {
@@ -509,7 +505,6 @@ struct clkdm_ops am43xx_clkdm_operations = {
 	.clkdm_deny_idle	= omap4_clkdm_deny_idle,
 	.clkdm_clk_enable	= omap4_clkdm_clk_enable,
 	.clkdm_clk_disable	= omap4_clkdm_clk_disable,
-	.clkdm_xlate_address	= omap4_clkdm_xlate_address,
 };
 
 static const struct cm_ll_data omap4xxx_cm_ll_data = {
@@ -517,6 +512,7 @@ static const struct cm_ll_data omap4xxx_cm_ll_data = {
 	.wait_module_idle	= &omap4_cminst_wait_module_idle,
 	.module_enable		= &omap4_cminst_module_enable,
 	.module_disable		= &omap4_cminst_module_disable,
+	.xlate_clkctrl		= &omap4_cminst_xlate_clkctrl,
 };
 
 int __init omap4_cm_init(const struct omap_prcm_init_data *data)

+ 36 - 37
arch/arm/mach-omap2/omap_hwmod.c

@@ -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;
 		}
 	}
@@ -3521,6 +3519,7 @@ void __init omap_hwmod_init(void)
 		soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
 		soc_ops.init_clkdm = _init_clkdm;
 		soc_ops.disable_direct_prcm = _omap4_disable_direct_prcm;
+		soc_ops.xlate_clkctrl = _omap4_xlate_clkctrl;
 	} else {
 		WARN(1, "omap_hwmod: unknown SoC type\n");
 	}

+ 1 - 1
arch/arm/mach-omap2/omap_hwmod_81xx_data.c

@@ -988,7 +988,7 @@ static struct omap_hwmod_class dm81xx_sata_hwmod_class = {
 
 static struct omap_hwmod dm81xx_sata_hwmod = {
 	.name		= "sata",
-	.clkdm_name	= "default_sata_clkdm",
+	.clkdm_name	= "default_clkdm",
 	.flags		= HWMOD_NO_IDLEST,
 	.prcm = {
 		.omap4 = {