diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-22 09:24:55 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-22 09:24:55 -0700 |
commit | 8b3c8ba3d8c2680dab5363a80c024965cac08b1e (patch) | |
tree | 18150efb36891e6e76e2cad89c1b2fcc5faeae93 /arch/arm/mach-omap2/control.c | |
parent | d34dc4f9e88e4b6beefb819e4e743fd6160a9b75 (diff) | |
parent | 48c1078509b47b38802329028ccfd77783bcff99 (diff) | |
download | linux-rt-8b3c8ba3d8c2680dab5363a80c024965cac08b1e.tar.gz |
Merge tag 'armsoc-late' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC late changes from Olof Johansson:
"We were expecting to sit on this branch through most of the merge
window since the contents was merged into our tree late, but we ended
up sitting on all of our contents so it can go in with the rest.
The contents here is:
- a large branch of cleanups of the CM/PRM blocks on OMAP.
- a couple of patches plumbing up CM/PRM on OMAP5 and DRA7.
- a branch with DT updates for Freescale i.MX. including some
shuffling from .dts to .dtsi (include) files that causes a little
churn"
* tag 'armsoc-late' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (78 commits)
ARM: OMAP2+: Fix booting with configs that don't have MFD_SYSCON
ARM: OMAP4+: control: add support for initializing control module via DT
ARM: dts: dra7: add minimal l4 bus layout with control module support
ARM: dts: omap5: add minimal l4 bus layout with control module support
ARM: OMAP4+: control: remove support for legacy pad read/write
ARM: OMAP4: display: convert display to use syscon for dsi muxing
ARM: dts: omap4: add minimal l4 bus layout with control module support
ARM: dts: am4372: add minimal l4 bus layout with control module support
ARM: dts: am43xx-epos-evm: fix pinmux node layout
ARM: dts: am33xx: add minimal l4 bus layout with control module support
ARM: dts: omap3: add minimal l4 bus layout with control module support
ARM: dts: omap24xx: add minimal l4 bus layout with control module support
ARM: OMAP2+: control: add syscon support for register accesses
ARM: OMAP2+: id: cache omap_type value
ARM: OMAP2+: control: remove API for getting control module base address
ARM: OMAP2+: clock: add low-level support for regmap
ARM: OMAP4+: PRM: get rid of cpu_is_omap44xx calls from interrupt init
ARM: OMAP4+: PRM: setup prm_features from the PRM init time flags
ARM: OMAP2+: CM: move SoC specific init calls within a generic API
ARM: OMAP4+: PRM: determine prm_device_inst based on DT compatibility
...
Diffstat (limited to 'arch/arm/mach-omap2/control.c')
-rw-r--r-- | arch/arm/mach-omap2/control.c | 201 |
1 files changed, 168 insertions, 33 deletions
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index da041b4ab29c..af95a624fe71 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -14,6 +14,9 @@ #include <linux/kernel.h> #include <linux/io.h> +#include <linux/of_address.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> #include "soc.h" #include "iomap.h" @@ -25,13 +28,15 @@ #include "sdrc.h" #include "pm.h" #include "control.h" +#include "clock.h" /* Used by omap3_ctrl_save_padconf() */ #define START_PADCONF_SAVE 0x2 #define PADCONF_SAVE_DONE 0x1 static void __iomem *omap2_ctrl_base; -static void __iomem *omap4_ctrl_pad_base; +static s16 omap2_ctrl_offset; +static struct regmap *omap2_ctrl_syscon; #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) struct omap3_scratchpad { @@ -133,66 +138,79 @@ struct omap3_control_regs { static struct omap3_control_regs control_context; #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */ -#define OMAP_CTRL_REGADDR(reg) (omap2_ctrl_base + (reg)) -#define OMAP4_CTRL_PAD_REGADDR(reg) (omap4_ctrl_pad_base + (reg)) - -void __init omap2_set_globals_control(void __iomem *ctrl, - void __iomem *ctrl_pad) +void __init omap2_set_globals_control(void __iomem *ctrl) { omap2_ctrl_base = ctrl; - omap4_ctrl_pad_base = ctrl_pad; -} - -void __iomem *omap_ctrl_base_get(void) -{ - return omap2_ctrl_base; } u8 omap_ctrl_readb(u16 offset) { - return readb_relaxed(OMAP_CTRL_REGADDR(offset)); + u32 val; + u8 byte_offset = offset & 0x3; + + val = omap_ctrl_readl(offset); + + return (val >> (byte_offset * 8)) & 0xff; } u16 omap_ctrl_readw(u16 offset) { - return readw_relaxed(OMAP_CTRL_REGADDR(offset)); + u32 val; + u16 byte_offset = offset & 0x2; + + val = omap_ctrl_readl(offset); + + return (val >> (byte_offset * 8)) & 0xffff; } u32 omap_ctrl_readl(u16 offset) { - return readl_relaxed(OMAP_CTRL_REGADDR(offset)); + u32 val; + + offset &= 0xfffc; + if (!omap2_ctrl_syscon) + val = readl_relaxed(omap2_ctrl_base + offset); + else + regmap_read(omap2_ctrl_syscon, omap2_ctrl_offset + offset, + &val); + + return val; } void omap_ctrl_writeb(u8 val, u16 offset) { - writeb_relaxed(val, OMAP_CTRL_REGADDR(offset)); + u32 tmp; + u8 byte_offset = offset & 0x3; + + tmp = omap_ctrl_readl(offset); + + tmp &= 0xffffffff ^ (0xff << (byte_offset * 8)); + tmp |= val << (byte_offset * 8); + + omap_ctrl_writel(tmp, offset); } void omap_ctrl_writew(u16 val, u16 offset) { - writew_relaxed(val, OMAP_CTRL_REGADDR(offset)); -} + u32 tmp; + u8 byte_offset = offset & 0x2; -void omap_ctrl_writel(u32 val, u16 offset) -{ - writel_relaxed(val, OMAP_CTRL_REGADDR(offset)); -} + tmp = omap_ctrl_readl(offset); -/* - * On OMAP4 control pad are not addressable from control - * core base. So the common omap_ctrl_read/write APIs breaks - * Hence export separate APIs to manage the omap4 pad control - * registers. This APIs will work only for OMAP4 - */ + tmp &= 0xffffffff ^ (0xffff << (byte_offset * 8)); + tmp |= val << (byte_offset * 8); -u32 omap4_ctrl_pad_readl(u16 offset) -{ - return readl_relaxed(OMAP4_CTRL_PAD_REGADDR(offset)); + omap_ctrl_writel(tmp, offset); } -void omap4_ctrl_pad_writel(u32 val, u16 offset) +void omap_ctrl_writel(u32 val, u16 offset) { - writel_relaxed(val, OMAP4_CTRL_PAD_REGADDR(offset)); + offset &= 0xfffc; + if (!omap2_ctrl_syscon) + writel_relaxed(val, omap2_ctrl_base + offset); + else + regmap_write(omap2_ctrl_syscon, omap2_ctrl_offset + offset, + val); } #ifdef CONFIG_ARCH_OMAP3 @@ -611,3 +629,120 @@ void __init omap3_ctrl_init(void) omap3_ctrl_setup_d2d_padconf(); } #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */ + +struct control_init_data { + int index; + s16 offset; +}; + +static struct control_init_data ctrl_data = { + .index = TI_CLKM_CTRL, +}; + +static const struct control_init_data omap2_ctrl_data = { + .index = TI_CLKM_CTRL, + .offset = -OMAP2_CONTROL_GENERAL, +}; + +static const struct of_device_id omap_scrm_dt_match_table[] = { + { .compatible = "ti,am3-scm", .data = &ctrl_data }, + { .compatible = "ti,am4-scm", .data = &ctrl_data }, + { .compatible = "ti,omap2-scm", .data = &omap2_ctrl_data }, + { .compatible = "ti,omap3-scm", .data = &omap2_ctrl_data }, + { .compatible = "ti,dm816-scrm", .data = &ctrl_data }, + { .compatible = "ti,omap4-scm-core", .data = &ctrl_data }, + { .compatible = "ti,omap5-scm-core", .data = &ctrl_data }, + { .compatible = "ti,dra7-scm-core", .data = &ctrl_data }, + { } +}; + +/** + * omap2_control_base_init - initialize iomappings for the control driver + * + * Detects and initializes the iomappings for the control driver, based + * on the DT data. Returns 0 in success, negative error value + * otherwise. + */ +int __init omap2_control_base_init(void) +{ + struct device_node *np; + const struct of_device_id *match; + struct control_init_data *data; + + for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) { + data = (struct control_init_data *)match->data; + + omap2_ctrl_base = of_iomap(np, 0); + if (!omap2_ctrl_base) + return -ENOMEM; + + omap2_ctrl_offset = data->offset; + } + + return 0; +} + +/** + * omap_control_init - low level init for the control driver + * + * Initializes the low level clock infrastructure for control driver. + * Returns 0 in success, negative error value in failure. + */ +int __init omap_control_init(void) +{ + struct device_node *np, *scm_conf; + const struct of_device_id *match; + const struct omap_prcm_init_data *data; + int ret; + struct regmap *syscon; + + for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) { + data = match->data; + + /* + * Check if we have scm_conf node, if yes, use this to + * access clock registers. + */ + scm_conf = of_get_child_by_name(np, "scm_conf"); + + if (scm_conf) { + syscon = syscon_node_to_regmap(scm_conf); + + if (IS_ERR(syscon)) + return PTR_ERR(syscon); + + omap2_ctrl_syscon = syscon; + + if (of_get_child_by_name(scm_conf, "clocks")) { + ret = omap2_clk_provider_init(scm_conf, + data->index, + syscon, NULL); + if (ret) + return ret; + } + + iounmap(omap2_ctrl_base); + omap2_ctrl_base = NULL; + } else { + /* No scm_conf found, direct access */ + ret = omap2_clk_provider_init(np, data->index, NULL, + omap2_ctrl_base); + if (ret) + return ret; + } + } + + return 0; +} + +/** + * omap3_control_legacy_iomap_init - legacy iomap init for clock providers + * + * Legacy iomap init for clock provider. Needed only by legacy boot mode, + * where the base addresses are not parsed from DT, but still required + * by the clock driver to be setup properly. + */ +void __init omap3_control_legacy_iomap_init(void) +{ + omap2_clk_legacy_provider_init(TI_CLKM_SCRM, omap2_ctrl_base); +} |