ARM: OMAP2+: preparation for clk/clkctrl support
Subsystems (7)
v4 cover ARM: OMAP2+: preparation for clk/clkctrl support
Hi,
This series is evolution of the v3b of the same series:
https://www.spinics.net/lists/arm-kernel/msg584344.html
Changes compared to v3b:
- Added patch #3 which stores the physical address for PRCM instances in addition to the virtual addresses
- Fixed patch #5 to use physical base address for xlate instead of the OMAP2_L4_IO_ADDRESS hack
- Dropped unnecessary device node passing from patch #6 which makes the code slightly more readable also
Integrated test branch here:
Tree: https://github.com/t-kristo/linux-pm.git
Branch: 4.12-rc1-clkctrl-integ-v4
-Tero
PATCH v4 1/6 ARM: OMAP2+: timer: add support for fetching fck handle from DT
The mux clock handle shall be provided via "fck" DT handle. This avoids the need to lookup the main clock via hwmod core, which will not work with the clkctrl clock support anymore; the main clock is not going to be a mux.
--- arch/arm/mach-omap2/timer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/timer.c +4 -1
@@ -255,6 +255,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, timer->io_base =of_iomap (np,0 ); + timer->fclk =of_clk_get_by_name (np,"fck" ); +of_node_put (np); }else {if (omap_dm_timer_reserve_systimer (timer->id))
@@ -292,7 +294,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,omap_hwmod_setup_one (oh_name);/* After the dmtimer is using hwmod these clocks won't be needed */ - timer->fclk =clk_get (NULL ,omap_hwmod_get_main_clk (oh)); +if (IS_ERR_OR_NULL (timer->fclk)) + timer->fclk =clk_get (NULL ,omap_hwmod_get_main_clk (oh));if (IS_ERR (timer->fclk))return PTR_ERR (timer->fclk);
Signature · 1 line
1.9.1
PATCH v4 2/6 ARM: OMAP4: hwmod_data: add opt clks for dss_hdmi and dss_venc
In reply to Tero KristoThese extra optional clocks are required as main clock for these modules are going to be routed to the main module clock. Otherwise, the hdmi / tv clocks are not going to be enabled during usage, leading to failure.
--- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/omap_hwmod_44xx_data.c +9 -1
@@ -775,6 +775,7 @@static struct omap_hwmod_opt_clk dss_hdmi_opt_clks[] = { { .role ="sys_clk" , .clk ="dss_sys_clk" }, + { .role ="hdmi_clk" , .clk ="dss_48mhz_clk" }, };static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
@@ -785,7 +786,7 @@* HDMI audio requires to use no-idle mode. Hence, * set idle mode by software. */ - .flags = HWMOD_SWSUP_SIDLE, + .flags = HWMOD_SWSUP_SIDLE | HWMOD_OPT_CLKS_NEEDED, .mpu_irqs = omap44xx_dss_hdmi_irqs, .xlate_irq = omap4_xlate_irq, .sdma_reqs = omap44xx_dss_hdmi_sdma_reqs,
@@ -858,11 +859,16 @@ };/* dss_venc */ +static struct omap_hwmod_opt_clk dss_venc_opt_clks[] = { + { .role ="tv_clk" , .clk ="dss_tv_clk" }, +}; +static struct omap_hwmod omap44xx_dss_venc_hwmod = { .name ="dss_venc" , .class = &omap44xx_venc_hwmod_class, .clkdm_name ="l3_dss_clkdm" , .main_clk ="dss_tv_clk" , + .flags =HWMOD_OPT_CLKS_NEEDED , .prcm = { .omap4 = { .clkctrl_offs =OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET ,
@@ -870,6 +876,8 @@ }, }, .parent_hwmod = &omap44xx_dss_hwmod, + .opt_clks = dss_venc_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_venc_opt_clks), };/*
Signature · 1 line
1.9.1
PATCH v4 3/6 ARM: OMAP2+: PRCM: store also physical addresses for instances
In reply to Tero KristoIn some cases the physical address info is needed, so store this under the existing cm*_base, prm_base and prcm_mpu_base variables. These are converted now to structs that contain both virtual and physical address base for the instance.
--- arch/arm/mach-omap2/cm.h | 7 +++++-- arch/arm/mach-omap2/cm2xxx_3xxx.h | 4 ++-- arch/arm/mach-omap2/cm33xx.c | 4 ++-- arch/arm/mach-omap2/cm3xxx.c | 3 ++- arch/arm/mach-omap2/cm_common.c | 31 +++++++++++++++++++------------ arch/arm/mach-omap2/cminst44xx.c | 19 ++++++++++--------- arch/arm/mach-omap2/prcm-common.h | 7 +++++++ arch/arm/mach-omap2/prcm_mpu44xx.c | 4 ++-- arch/arm/mach-omap2/prcm_mpu_44xx_54xx.h | 4 +++- arch/arm/mach-omap2/prm.h | 2 +- arch/arm/mach-omap2/prm2xxx_3xxx.h | 4 ++-- arch/arm/mach-omap2/prm33xx.c | 4 ++-- arch/arm/mach-omap2/prm3xxx.c | 2 +- arch/arm/mach-omap2/prm44xx.c | 4 ++-- arch/arm/mach-omap2/prm_common.c | 23 +++++++++++++---------- arch/arm/mach-omap2/prminst44xx.c | 16 +++++++++------- 16 files changed, 82 insertions(+), 56 deletions(-)
arch/arm/mach-omap2/cm.h +5 -2
@@ -24,8 +24,11 @@# ifndef __ASSEMBLER__#include <linux/clk/ti.h> -extern void __iomem *cm_base; -extern void __iomem *cm2_base; + +#include "prcm-common.h" + +extern struct omap_domain_base cm_base; +extern struct omap_domain_base cm2_base;extern void omap2_set_globals_cm (void __iomem *cm,void __iomem *cm2);# endif
arch/arm/mach-omap2/cm2xxx_3xxx.h +2 -2
@@ -52,12 +52,12 @@static inline u32 omap2_cm_read_mod_reg (s16 module,u16 idx) { -return readl_relaxed (cm_base + module + idx); +return readl_relaxed (cm_base.va + module + idx); }static inline void omap2_cm_write_mod_reg (u32 val,s16 module,u16 idx) { -writel_relaxed (val, cm_base + module + idx); +writel_relaxed (val, cm_base.va + module + idx); }/* Read-modify-write a register in a CM module. Caller must lock */
arch/arm/mach-omap2/cm33xx.c +2 -2
@@ -50,13 +50,13 @@/* Read a register in a CM instance */ static inline u32 am33xx_cm_read_reg (u16 inst,u16 idx) { -return readl_relaxed (cm_base + inst + idx); +return readl_relaxed (cm_base.va + inst + idx); }/* Write into a register in a CM */ static inline void am33xx_cm_write_reg (u32 val,u16 inst,u16 idx) { -writel_relaxed (val, cm_base + inst + idx); +writel_relaxed (val, cm_base.va + inst + idx); }/* Read-modify-write a register in CM */
arch/arm/mach-omap2/cm3xxx.c +2 -1
@@ -669,7 +669,8 @@ void omap3_cm_save_scratchpad_contents(u32 *ptr)int __init omap3xxx_cm_init (const struct omap_prcm_init_data *data) { -omap2_clk_legacy_provider_init (TI_CLKM_CM , cm_base +OMAP3430_IVA2_MOD ); +omap2_clk_legacy_provider_init (TI_CLKM_CM , cm_base.va + +OMAP3430_IVA2_MOD );return cm_register (&omap3xxx_cm_ll_data); }
arch/arm/mach-omap2/cm_common.c +19 -12
@@ -32,10 +32,10 @@static struct cm_ll_data *cm_ll_data = &null_cm_ll_data;/* cm_base: base virtual address of the CM IP block */ -void __iomem *cm_base; +struct omap_domain_base cm_base;/* cm2_base: base virtual address of the CM2 IP block (OMAP44xx only) */ -void __iomem *cm2_base; +struct omap_domain_base cm2_base;#define CM_NO_CLOCKS 0x1#define CM_SINGLE_INSTANCE 0x2
@@ -49,8 +49,8 @@*/ void __init omap2_set_globals_cm (void __iomem *cm,void __iomem *cm2) { - cm_base = cm; - cm2_base = cm2; + cm_base.va = cm; + cm2_base.va = cm2; }/**
@@ -315,27 +315,34 @@ int __init omap2_cm_base_init(void)struct device_node *np;const struct of_device_id *match;struct omap_prcm_init_data *data; -void __iomem *mem; +struct resource res; +int ret; +struct omap_domain_base *mem =NULL ;for_each_matching_node_and_match (np, omap_cm_dt_match_table, &match) { data = (struct omap_prcm_init_data *)match->data; - mem =of_iomap (np,0 ); -if (!mem) -return -ENOMEM ; + ret =of_address_to_resource (np,0 , &res); +if (ret) +return ret;if (data->index ==TI_CLKM_CM ) - cm_base = mem + data->offset; + mem = &cm_base;if (data->index ==TI_CLKM_CM2 ) - cm2_base = mem + data->offset; + mem = &cm2_base; + + data->mem =ioremap (res.start,resource_size (&res)); - data->mem = mem; +if (mem) { + mem->pa = res.start + data->offset; + mem->va = data->mem + data->offset; + } data->np = np;if (data->init && (data->flags &CM_SINGLE_INSTANCE || - (cm_base && cm2_base))) + (cm_base.va && cm2_base.va))) data->init (data); }
arch/arm/mach-omap2/cminst44xx.c +10 -9
@@ -55,7 +55,7 @@#define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2#define CLKCTRL_IDLEST_DISABLED 0x3 -static void __iomem *_cm_bases[OMAP4_MAX_PRCM_PARTITIONS ]; +static struct omap_domain_base _cm_bases[OMAP4_MAX_PRCM_PARTITIONS ];/** * omap_cm_base_init - Populates the cm partitions
@@ -65,10 +65,11 @@*/ static void omap_cm_base_init (void ) { - _cm_bases[OMAP4430_PRM_PARTITION ] = prm_base; - _cm_bases[OMAP4430_CM1_PARTITION ] = cm_base; - _cm_bases[OMAP4430_CM2_PARTITION ] = cm2_base; - _cm_bases[OMAP4430_PRCM_MPU_PARTITION ] = prcm_mpu_base; +memcpy (&_cm_bases[OMAP4430_PRM_PARTITION ], &prm_base,sizeof (prm_base)); +memcpy (&_cm_bases[OMAP4430_CM1_PARTITION ], &cm_base,sizeof (cm_base)); +memcpy (&_cm_bases[OMAP4430_CM2_PARTITION ], &cm2_base,sizeof (cm2_base)); +memcpy (&_cm_bases[OMAP4430_PRCM_MPU_PARTITION ], &prcm_mpu_base, +sizeof (prcm_mpu_base)); }/* Private functions */
@@ -116,8 +117,8 @@ static u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx) {BUG_ON (part >=OMAP4_MAX_PRCM_PARTITIONS || part ==OMAP4430_INVALID_PRCM_PARTITION || - !_cm_bases[part]); -return readl_relaxed (_cm_bases[part] + inst + idx); + !_cm_bases[part].va); +return readl_relaxed (_cm_bases[part].va + inst + idx); }/* Write into a register in a CM instance */
@@ -125,8 +126,8 @@ static void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx) {BUG_ON (part >=OMAP4_MAX_PRCM_PARTITIONS || part ==OMAP4430_INVALID_PRCM_PARTITION || - !_cm_bases[part]); -writel_relaxed (val, _cm_bases[part] + inst + idx); + !_cm_bases[part].va); +writel_relaxed (val, _cm_bases[part].va + inst + idx); }/* Read-modify-write a register in CM1. Caller must lock */
arch/arm/mach-omap2/prcm-common.h +7 -0
@@ -526,10 +526,16 @@ struct omap_prcm_irq_setup { .priority = _priority \ } +struct omap_domain_base { +u32 pa; +void __iomem *va; +}; +/** * struct omap_prcm_init_data - PRCM driver init data * @index: clock memory mapping index to be used * @mem: IO mem pointer for this module +* @phys: IO mem physical base address for this module * @offset: module base address offset from the IO base * @flags: PRCM module init flags * @device_inst_offset: device instance offset within the module address space
@@ -539,6 +545,7 @@ struct omap_prcm_irq_setup {struct omap_prcm_init_data {int index;void __iomem *mem; +u32 phys;s16 offset;u16 flags;s32 device_inst_offset;
arch/arm/mach-omap2/prcm_mpu44xx.c +2 -2
@@ -24,7 +24,7 @@* prcm_mpu_base: the virtual address of the start of the PRCM_MPU IP * block registers */ -void __iomem *prcm_mpu_base; +struct omap_domain_base prcm_mpu_base;/* PRCM_MPU low-level functions */
@@ -58,5 +58,5 @@ u32 omap4_prcm_mpu_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)*/ void __init omap2_set_globals_prcm_mpu (void __iomem *prcm_mpu) { - prcm_mpu_base = prcm_mpu; + prcm_mpu_base.va = prcm_mpu; }
arch/arm/mach-omap2/prcm_mpu_44xx_54xx.h +3 -1
@@ -24,7 +24,9 @@#define __ARCH_ARM_MACH_OMAP2_PRCM_MPU_44XX_54XX_H#ifndef __ASSEMBLER__ -extern void __iomem *prcm_mpu_base; +#include "prcm-common.h" + +extern struct omap_domain_base prcm_mpu_base;extern u32 omap4_prcm_mpu_read_inst_reg (s16 inst,u16 idx);extern void omap4_prcm_mpu_write_inst_reg (u32 val,s16 inst,u16 idx);
arch/arm/mach-omap2/prm.h +1 -1
@@ -16,7 +16,7 @@#include "prcm-common.h" # ifndef __ASSEMBLER__ -extern void __iomem *prm_base; +extern struct omap_domain_base prm_base;extern u16 prm_features;extern void omap2_set_globals_prm (void __iomem *prm);int omap_prcm_init (void );
arch/arm/mach-omap2/prm2xxx_3xxx.h +2 -2
@@ -55,12 +55,12 @@/* Power/reset management domain register get/set */ static inline u32 omap2_prm_read_mod_reg (s16 module,u16 idx) { -return readl_relaxed (prm_base + module + idx); +return readl_relaxed (prm_base.va + module + idx); }static inline void omap2_prm_write_mod_reg (u32 val,s16 module,u16 idx) { -writel_relaxed (val, prm_base + module + idx); +writel_relaxed (val, prm_base.va + module + idx); }/* Read-modify-write a register in a PRM module. Caller must lock */
arch/arm/mach-omap2/prm33xx.c +2 -2
@@ -30,13 +30,13 @@/* Read a register in a PRM instance */ static u32 am33xx_prm_read_reg (s16 inst,u16 idx) { -return readl_relaxed (prm_base + inst + idx); +return readl_relaxed (prm_base.va + inst + idx); }/* Write into a register in a PRM instance */ static void am33xx_prm_write_reg (u32 val,s16 inst,u16 idx) { -writel_relaxed (val, prm_base + inst + idx); +writel_relaxed (val, prm_base.va + inst + idx); }/* Read-modify-write a register in PRM. Caller must lock */
arch/arm/mach-omap2/prm3xxx.c +1 -1
@@ -676,7 +676,7 @@ struct pwrdm_ops omap3_pwrdm_operations = {int __init omap3xxx_prm_init (const struct omap_prcm_init_data *data) {omap2_clk_legacy_provider_init (TI_CLKM_PRM , - prm_base +OMAP3430_IVA2_MOD ); + prm_base.va +OMAP3430_IVA2_MOD );if (omap3_has_io_wakeup ()) prm_features |=PRM_HAS_IO_WAKEUP ;
arch/arm/mach-omap2/prm44xx.c +2 -2
@@ -91,13 +91,13 @@/* Read a register in a CM/PRM instance in the PRM module */ static u32 omap4_prm_read_inst_reg (s16 inst,u16 reg) { -return readl_relaxed (prm_base + inst + reg); +return readl_relaxed (prm_base.va + inst + reg); }/* Write into a register in a CM/PRM instance in the PRM module */ static void omap4_prm_write_inst_reg (u32 val,s16 inst,u16 reg) { -writel_relaxed (val, prm_base + inst + reg); +writel_relaxed (val, prm_base.va + inst + reg); }/* Read-modify-write a register in a PRM module. Caller must lock */
arch/arm/mach-omap2/prm_common.c +13 -10
@@ -66,7 +66,7 @@static struct omap_prcm_irq_setup *prcm_irq_setup;/* prm_base: base virtual address of the PRM IP block */ -void __iomem *prm_base; +struct omap_domain_base prm_base;u16 prm_features;
@@ -325,7 +325,7 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)for (i =0 ; i < irq_setup->nr_regs; i++) { gc =irq_alloc_generic_chip ("PRCM" ,1 , - irq_setup->base_irq + i *32 , prm_base, + irq_setup->base_irq + i *32 , prm_base.va, handle_level_irq);if (!gc) {
@@ -364,7 +364,7 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)*/ void __init omap2_set_globals_prm (void __iomem *prm) { - prm_base = prm; + prm_base.va = prm; }/**
@@ -755,19 +755,22 @@ int __init omap2_prm_base_init(void)struct device_node *np;const struct of_device_id *match;struct omap_prcm_init_data *data; -void __iomem *mem; +struct resource res; +int ret;for_each_matching_node_and_match (np, omap_prcm_dt_match_table, &match) { data = (struct omap_prcm_init_data *)match->data; - mem =of_iomap (np,0 ); -if (!mem) -return -ENOMEM ; + ret =of_address_to_resource (np,0 , &res); +if (ret) +return ret; -if (data->index ==TI_CLKM_PRM ) - prm_base = mem + data->offset; + data->mem =ioremap (res.start,resource_size (&res)); - data->mem = mem; +if (data->index ==TI_CLKM_PRM ) { + prm_base.va = data->mem + data->offset; + prm_base.pa = res.start + data->offset; + } data->np = np;
arch/arm/mach-omap2/prminst44xx.c +9 -7
@@ -29,7 +29,7 @@#include "prcm_mpu44xx.h" #include "soc.h" -static void __iomem *_prm_bases[OMAP4_MAX_PRCM_PARTITIONS ]; +static struct omap_domain_base _prm_bases[OMAP4_MAX_PRCM_PARTITIONS ];static s32 prm_dev_inst =PRM_INSTANCE_UNKNOWN ;
@@ -41,8 +41,10 @@*/ void omap_prm_base_init (void ) { - _prm_bases[OMAP4430_PRM_PARTITION ] = prm_base; - _prm_bases[OMAP4430_PRCM_MPU_PARTITION ] = prcm_mpu_base; +memcpy (&_prm_bases[OMAP4430_PRM_PARTITION ], &prm_base, +sizeof (prm_base)); +memcpy (&_prm_bases[OMAP4430_PRCM_MPU_PARTITION ], &prcm_mpu_base, +sizeof (prcm_mpu_base)); }s32 omap4_prmst_get_prm_dev_inst (void )
@@ -60,8 +62,8 @@ u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx) {BUG_ON (part >=OMAP4_MAX_PRCM_PARTITIONS || part ==OMAP4430_INVALID_PRCM_PARTITION || - !_prm_bases[part]); -return readl_relaxed (_prm_bases[part] + inst + idx); + !_prm_bases[part].va); +return readl_relaxed (_prm_bases[part].va + inst + idx); }/* Write into a register in a PRM instance */
@@ -69,8 +71,8 @@ void omap4_prminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx) {BUG_ON (part >=OMAP4_MAX_PRCM_PARTITIONS || part ==OMAP4430_INVALID_PRCM_PARTITION || - !_prm_bases[part]); -writel_relaxed (val, _prm_bases[part] + inst + idx); + !_prm_bases[part].va); +writel_relaxed (val, _prm_bases[part].va + inst + idx); }/* Read-modify-write a register in PRM. Caller must lock */
Signature · 1 line
1.9.1
PATCH v4 4/6 ARM: omap2+: clockdomain: add clkdm_xlate_address
In reply to Tero KristoThis new function can be used to get the physical address of a clockdomain. Required for mapping the clkctrl clocks under hwmod without modification to DT data.
--- arch/arm/mach-omap2/clockdomain.c | 8 ++++++++ arch/arm/mach-omap2/clockdomain.h | 2 ++ 2 files changed, 10 insertions(+)
arch/arm/mach-omap2/clockdomain.c +8 -0
@@ -1224,6 +1224,14 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)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 *
arch/arm/mach-omap2/clockdomain.h +2 -0
@@ -175,6 +175,7 @@ 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);
@@ -213,6 +214,7 @@ int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),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 );
Signature · 1 line
1.9.1
PATCH v4 5/6 ARM: OMAP4: cminst: add support for clkdm_xlate_address
In reply to Tero KristoThis function gets the physical base address of a clockdomain.
--- arch/arm/mach-omap2/cminst44xx.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
arch/arm/mach-omap2/cminst44xx.c +10 -0
@@ -476,6 +476,14 @@ static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)return 0 ; } +static u32 omap4_clkdm_xlate_address (struct clockdomain *clkdm) +{ +u32 addr = _cm_bases[clkdm->prcm_partition].pa + clkdm->cm_inst + + clkdm->clkdm_offs; + +return addr; +} +struct clkdm_ops omap4_clkdm_operations = { .clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep, .clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep,
@@ -491,6 +499,7 @@ 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 = {
@@ -500,6 +509,7 @@ 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 struct cm_ll_data omap4xxx_cm_ll_data = {
Signature · 1 line
1.9.1
PATCH v4 6/6 ARM: OMAP2+: hwmod: populate clkctrl clocks for hwmods if available
In reply to Tero KristoIf clkctrl clocks are available on a device, populate these automatically to replace hwmod main_clk info. First, the patch parses all "ti,clkctrl" compatible nodes and maps these against existing clockdomain data. Once done, individual hwmod init routines can search for a clkctrl clock handle based on the clockdomain info and the created mapping.
This patch also drops the obsolete "_mod_ck" search as the implementation required for this was not accepted usptream.
--- arch/arm/mach-omap2/omap_hwmod.c | 145 +++++++++++++++++++++++++++++++++++---- 1 file changed, 130 insertions(+), 15 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +130 -15
@@ -141,6 +141,7 @@#include <linux/cpu.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/bootmem.h> #include <asm/system_misc.h>
@@ -182,6 +183,24 @@#define MOD_CLK_MAX_NAME_LEN 32/** +* struct clkctrl_provider - clkctrl provider mapping data +* @addr: base address for the provider +* @offset: base offset for the provider +* @clkdm: base clockdomain for provider +* @node: device node associated with the provider +* @link: list link +*/ +struct clkctrl_provider { +u32 addr; +u16 offset; +struct clockdomain *clkdm; +struct device_node *node; +struct list_head link; +}; + +static LIST_HEAD (clkctrl_providers); + +/** * 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)
@@ -204,6 +223,8 @@ 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); };/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
@@ -690,6 +711,103 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)return clkdm_del_sleepdep (clkdm, init_clkdm); } +static const struct of_device_id ti_clkctrl_match_table[]__initconst = { + { .compatible ="ti,clkctrl" }, + { } +}; + +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; + + provider =memblock_virt_alloc (sizeof (*provider),0 ); +if (!provider) +return -ENOMEM ; + + addrp =of_get_address (np,0 ,NULL ,NULL ); + provider->addr = (u32 )of_translate_address (np, addrp); + provider->offset = provider->addr &0xff ; + provider->addr &= ~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 ; + } + +list_add (&provider->link, &clkctrl_providers); + +return 0 ; +} + +static int _init_clkctrl_providers (void ) +{ +struct device_node *np; +int ret =0 ; + +for_each_matching_node (np, ti_clkctrl_match_table) { + ret =_setup_clkctrl_provider (np); +if (ret) +break ; + } + +return ret; +} + +static u32 _omap4_xlate_clkctrl (struct omap_hwmod *oh, +struct clkctrl_provider *provider) +{ +return oh->prcm.omap4.clkctrl_offs - + provider->offset - provider->clkdm->clkdm_offs; +} + +static struct clk *_lookup_clkctrl_clk (struct omap_hwmod *oh) +{ +struct clkctrl_provider *provider; +struct clk *clk; + +if (!soc_ops.xlate_clkctrl) +return NULL ; + +list_for_each_entry (provider, &clkctrl_providers, link) { +if (provider->clkdm == oh->clkdm) { +struct of_phandle_args clkspec; + + clkspec.np = provider->node; + clkspec.args_count =2 ; + clkspec.args[0 ] = soc_ops.xlate_clkctrl (oh, provider); + clkspec.args[1 ] =0 ; + + clk =of_clk_get_from_provider (&clkspec); + +return clk; + } + } + +return NULL ; +} +/** * _init_main_clk - get a struct clk * for the the hwmod's main functional clk * @oh: struct omap_hwmod *
@@ -701,22 +819,16 @@ static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)static int _init_main_clk (struct omap_hwmod *oh) {int ret =0 ; -char name[MOD_CLK_MAX_NAME_LEN ]; -struct clk *clk; -static const char modck[] ="_mod_ck" ; +struct clk *clk =NULL ; -if (strlen (oh->name) >=MOD_CLK_MAX_NAME_LEN -strlen (modck)) -pr_warn ("%s: warning: cropping name for %s\n" , __func__, - oh->name); - -strlcpy (name, oh->name,MOD_CLK_MAX_NAME_LEN -strlen (modck)); -strlcat (name, modck,MOD_CLK_MAX_NAME_LEN ); + clk =_lookup_clkctrl_clk (oh); - clk =clk_get (NULL , name); -if (!IS_ERR (clk)) { +if (!IS_ERR_OR_NULL (clk)) { +pr_debug ("%s: mapped main_clk %s for %s\n" , __func__, +__clk_get_name (clk), oh->name); + oh->main_clk =__clk_get_name (clk); oh->_clk = clk; soc_ops.disable_direct_prcm (oh); - oh->main_clk =kstrdup (name,GFP_KERNEL ); }else {if (!oh->main_clk)return 0 ;
@@ -1482,13 +1594,13 @@ static int _init_clkdm(struct omap_hwmod *oh)* _init_clocks - clk_get() all clocks associated with this hwmod. Retrieve as * well the clockdomain. * @oh: struct omap_hwmod * -* @data: not used; pass NULL +* @np: device_node mapped to this hwmod * * Called by omap_hwmod_setup_*() (after omap2_clk_init()). * Resolves all clock names embedded in the hwmod. Returns 0 on * success, or a negative error code on failure. */ -static int _init_clocks (struct omap_hwmod *oh,void *data) +static int _init_clocks (struct omap_hwmod *oh,struct device_node *np) {int ret =0 ;
@@ -2360,7 +2472,7 @@ static int __init _init(struct omap_hwmod *oh, void *data)return 0 ; } - r =_init_clocks (oh,NULL ); + r =_init_clocks (oh, np);if (r <0 ) {WARN (1 ,"omap_hwmod: %s: couldn't init clocks\n" , oh->name);return -EINVAL ;
@@ -3722,6 +3834,7 @@ void __init omap_hwmod_init(void) soc_ops.update_context_lost = _omap4_update_context_lost; soc_ops.get_context_lost = _omap4_get_context_lost; soc_ops.disable_direct_prcm = _omap4_disable_direct_prcm; + soc_ops.xlate_clkctrl = _omap4_xlate_clkctrl; }else if (cpu_is_ti814x () ||cpu_is_ti816x () ||soc_is_am33xx () ||soc_is_am43xx ()) { soc_ops.enable_module = _omap4_enable_module;
@@ -3736,6 +3849,8 @@ void __init omap_hwmod_init(void)WARN (1 ,"omap_hwmod: unknown SoC type\n" ); } +_init_clkctrl_providers (); + inited = true; }
Signature · 1 line
1.9.1
Tony Lindgren
maintainerv4 cover ARM: OMAP2+: preparation for clk/clkctrl support
In reply to Tero KristoQuoted 5 lines · Tero Kristo
Hi,
This series is evolution of the v3b of the same series:
https://www.spinics.net/lists/arm-kernel/msg584344.html
Quoted 8 lines
Changes compared to v3b:
- Added patch #3 which stores the physical address for PRCM instances in addition to the virtual addresses
- Fixed patch #5 to use physical base address for xlate instead of theOMAP2_L4_IO_ADDRESShack
- Dropped unnecessary device node passing from patch #6 which makes the code slightly more readable also
I gave this series a quick test with no other changes and noticed that n8x0 stopped booting. Other than that looks pretty good to me.
Regards,
Tony
Tony Lindgren
maintainerv4 cover ARM: OMAP2+: preparation for clk/clkctrl support
Quoted 15 lines · Tony Lindgren
Quoted 5 lines · Tero Kristo
Hi,
This series is evolution of the v3b of the same series:
https://www.spinics.net/lists/arm-kernel/msg584344.htmlQuoted 8 lines
Changes compared to v3b:
- Added patch #3 which stores the physical address for PRCM instances in addition to the virtual addresses
- Fixed patch #5 to use physical base address for xlate instead of theOMAP2_L4_IO_ADDRESShack
- Dropped unnecessary device node passing from patch #6 which makes the code slightly more readable also
Quoted 3 lines
I gave this series a quick test with no other changes and noticed that n8x0 stopped booting. Other than that looks pretty good to me.
Sorry that was a false alert, n8x0 is booting just fine. It's the loading of kernel over USB that's flakey for me again..
Regards,
Tony
Tony Lindgren
maintainerv4 cover ARM: OMAP2+: preparation for clk/clkctrl support
Quoted 4 lines · Tony Lindgren
Sorry that was a false alert, n8x0 is booting just fine. It's the loading of kernel over USB that's flakey for me again..
So I'll apply the whole series into omap-for-v4.13/clkctrl today so we get this into Linux next for few weeks.
Regards,
Tony