From 138f7ca78f5a0677f591fdf23d0309c2f4774bf7 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 31 May 2017 17:59:58 +0300 Subject: 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. Signed-off-by: Tero Kristo Acked-by: Tony Lindgren Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/timer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 07dd692c4737..af90f95c2433 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -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); -- cgit From 24d8d498a8703462f0141f2fcdcd325de1ab2bb8 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 31 May 2017 17:59:59 +0300 Subject: ARM: OMAP4: hwmod_data: add opt clks for dss_hdmi and dss_venc These 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. Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 94f09c720f29..0855434773fa 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -775,6 +775,7 @@ static struct omap_hwmod_dma_info omap44xx_dss_hdmi_sdma_reqs[] = { 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 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = { * 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 @@ static struct omap_hwmod_class omap44xx_venc_hwmod_class = { }; /* 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 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = { }, }, .parent_hwmod = &omap44xx_dss_hwmod, + .opt_clks = dss_venc_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dss_venc_opt_clks), }; /* -- cgit From 90129336712c3c8dcd0d81a5dfaea52dd8391e62 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 31 May 2017 18:00:00 +0300 Subject: ARM: OMAP2+: PRCM: store also physical addresses for instances In 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. Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- 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(-) (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h index de75cbcdc9d1..e833984cc85e 100644 --- a/arch/arm/mach-omap2/cm.h +++ b/arch/arm/mach-omap2/cm.h @@ -24,8 +24,11 @@ # ifndef __ASSEMBLER__ #include -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 diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h index 72928a3ce2aa..aa148cd57cc1 100644 --- a/arch/arm/mach-omap2/cm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h @@ -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 */ diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c index 6f2d0aec0513..a9e08d89104e 100644 --- a/arch/arm/mach-omap2/cm33xx.c +++ b/arch/arm/mach-omap2/cm33xx.c @@ -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 */ diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c index 55b046a719dc..961bc478b9de 100644 --- a/arch/arm/mach-omap2/cm3xxx.c +++ b/arch/arm/mach-omap2/cm3xxx.c @@ -669,7 +669,8 @@ static struct cm_ll_data omap3xxx_cm_ll_data = { 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); } diff --git a/arch/arm/mach-omap2/cm_common.c b/arch/arm/mach-omap2/cm_common.c index bbe41f4c9dc8..d555791cf349 100644 --- a/arch/arm/mach-omap2/cm_common.c +++ b/arch/arm/mach-omap2/cm_common.c @@ -32,10 +32,10 @@ static struct cm_ll_data null_cm_ll_data; 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 __iomem *cm2_base; */ 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); } diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index 2ab27ade136a..cfa10a31b953 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -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 __iomem *_cm_bases[OMAP4_MAX_PRCM_PARTITIONS]; */ 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 */ diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index c8f590b7c32d..ee7041d523cf 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -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; diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.c b/arch/arm/mach-omap2/prcm_mpu44xx.c index cdbee6326d29..9c782f5c3f94 100644 --- a/arch/arm/mach-omap2/prcm_mpu44xx.c +++ b/arch/arm/mach-omap2/prcm_mpu44xx.c @@ -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; } diff --git a/arch/arm/mach-omap2/prcm_mpu_44xx_54xx.h b/arch/arm/mach-omap2/prcm_mpu_44xx_54xx.h index ca149e70bed0..f565f7f73175 100644 --- a/arch/arm/mach-omap2/prcm_mpu_44xx_54xx.h +++ b/arch/arm/mach-omap2/prcm_mpu_44xx_54xx.h @@ -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); diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h index 233bc84fbc0e..94dc3565add8 100644 --- a/arch/arm/mach-omap2/prm.h +++ b/arch/arm/mach-omap2/prm.h @@ -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); diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h index f57e29b0e041..6775e10883fb 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h @@ -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 */ diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c index dcb5001d77da..d2c5bcabdbeb 100644 --- a/arch/arm/mach-omap2/prm33xx.c +++ b/arch/arm/mach-omap2/prm33xx.c @@ -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 */ diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c index 718981bb80cd..50291a063aab 100644 --- a/arch/arm/mach-omap2/prm3xxx.c +++ b/arch/arm/mach-omap2/prm3xxx.c @@ -676,7 +676,7 @@ static struct prm_ll_data omap3xxx_prm_ll_data = { 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; diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index 30768003f854..090a13173589 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -91,13 +91,13 @@ static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = { /* 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 */ diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index 2b138b65129a..ae13aa710c75 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -66,7 +66,7 @@ static struct irq_chip_generic **prcm_irq_chips; 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 @@ err: */ 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; diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c index d0b15dbafa2e..48b8127b4e99 100644 --- a/arch/arm/mach-omap2/prminst44xx.c +++ b/arch/arm/mach-omap2/prminst44xx.c @@ -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 @@ static s32 prm_dev_inst = PRM_INSTANCE_UNKNOWN; */ 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 */ -- cgit From 0bf76e00e5d8410a77b07b32ac9afea61d1e0ecd Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 31 May 2017 18:00:01 +0300 Subject: ARM: omap2+: clockdomain: add clkdm_xlate_address This 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. Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clockdomain.c | 8 ++++++++ arch/arm/mach-omap2/clockdomain.h | 2 ++ 2 files changed, 10 insertions(+) (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index b79b1ca9aee9..518926410b62 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -1224,6 +1224,14 @@ 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 * diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 24667a5a9dc0..827f01e2d0af 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -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_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); -- cgit From 308b4e381b5849c190ca4a93388c9ccfbc525e3b Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 31 May 2017 18:00:02 +0300 Subject: ARM: OMAP4: cminst: add support for clkdm_xlate_address This function gets the physical base address of a clockdomain. Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/cminst44xx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index cfa10a31b953..8774e983bea1 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -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 = { -- cgit From 70f05be3213393f20f01e4d59625df7ee49fe32f Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 31 May 2017 18:00:03 +0300 Subject: ARM: OMAP2+: hwmod: populate clkctrl clocks for hwmods if available If 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. Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod.c | 145 +++++++++++++++++++++++++++++++++++---- 1 file changed, 130 insertions(+), 15 deletions(-) (limited to 'arch/arm/mach-omap2') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 8bcea0d83fa0..e1107670acb6 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -141,6 +141,7 @@ #include #include #include +#include #include @@ -181,6 +182,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) @@ -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; } -- cgit