diff options
Diffstat (limited to 'arch/arm/mach-imx')
81 files changed, 2153 insertions, 1836 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 33567aa5880f..8d42eab76d53 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -1,19 +1,15 @@ config ARCH_MXC bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7 + select ARCH_HAS_CPUFREQ + select ARCH_HAS_OPP select ARCH_REQUIRE_GPIOLIB select ARM_CPU_SUSPEND if PM - select ARM_PATCH_PHYS_VIRT select CLKSRC_MMIO - select COMMON_CLK - select GENERIC_ALLOCATOR - select GENERIC_CLOCKEVENTS select GENERIC_IRQ_CHIP - select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7 - select MULTI_IRQ_HANDLER select PINCTRL + select PM_OPP if PM select SOC_BUS - select SPARSE_IRQ - select USE_OF + select SRAM help Support for Freescale MXC/iMX-based family of processors @@ -121,18 +117,16 @@ config SOC_IMX31 config SOC_IMX35 bool select ARCH_MXC_IOMUX_V3 - select CPU_V6K select HAVE_EPIT select MXC_AVIC + select PINCTRL_IMX35 select SMP_ON_UP if SMP - select PINCTRL config SOC_IMX5 bool select ARCH_HAS_CPUFREQ select ARCH_HAS_OPP select ARCH_MXC_IOMUX_V3 - select CPU_V7 select MXC_TZIC config SOC_IMX51 @@ -708,61 +702,6 @@ endif if ARCH_MULTI_V7 -comment "i.MX51 machines:" - -config MACH_IMX51_DT - bool "Support i.MX51 platforms from device tree" - select SOC_IMX51 - help - Include support for Freescale i.MX51 based platforms - using the device tree for discovery - -config MACH_MX51_BABBAGE - bool "Support MX51 BABBAGE platforms" - select IMX_HAVE_PLATFORM_FSL_USB2_UDC - select IMX_HAVE_PLATFORM_IMX2_WDT - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_MXC_EHCI - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select IMX_HAVE_PLATFORM_SPI_IMX - select SOC_IMX51 - help - Include support for MX51 Babbage platform, also known as MX51EVK in - u-boot. This includes specific configurations for the board and its - peripherals. - -config MACH_EUKREA_CPUIMX51SD - bool "Support Eukrea CPUIMX51SD module" - select IMX_HAVE_PLATFORM_FSL_USB2_UDC - select IMX_HAVE_PLATFORM_IMX2_WDT - select IMX_HAVE_PLATFORM_IMX_I2C - select IMX_HAVE_PLATFORM_IMX_UART - select IMX_HAVE_PLATFORM_MXC_EHCI - select IMX_HAVE_PLATFORM_MXC_NAND - select IMX_HAVE_PLATFORM_SPI_IMX - select SOC_IMX51 - help - Include support for Eukrea CPUIMX51SD platform. This includes - specific configurations for the module and its peripherals. - -choice - prompt "Baseboard" - depends on MACH_EUKREA_CPUIMX51SD - default MACH_EUKREA_MBIMXSD51_BASEBOARD - -config MACH_EUKREA_MBIMXSD51_BASEBOARD - prompt "Eukrea MBIMXSD development board" - bool - select IMX_HAVE_PLATFORM_IMX_SSI - select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX - select LEDS_GPIO_REGISTER - help - This adds board specific devices that can be found on Eukrea's - MBIMXSD evaluation board. - -endchoice - comment "Device tree only" config SOC_IMX50 @@ -774,68 +713,66 @@ config SOC_IMX50 help This enables support for Freescale i.MX50 processor. +config MACH_IMX51_DT + bool "i.MX51 support" + select SOC_IMX51 + help + This enables support for Freescale i.MX51 processor + config SOC_IMX53 bool "i.MX53 support" select HAVE_IMX_SRC - select IMX_HAVE_PLATFORM_IMX2_WDT select PINCTRL_IMX53 select SOC_IMX5 help This enables support for Freescale i.MX53 processor. -config SOC_IMX6Q - bool "i.MX6 Quad/DualLite support" - select ARCH_HAS_CPUFREQ - select ARCH_HAS_OPP +config SOC_IMX6 + bool select ARM_ERRATA_754322 - select ARM_ERRATA_764369 if SMP select ARM_ERRATA_775420 select ARM_GIC - select CPU_V7 - select HAVE_ARM_SCU if SMP - select HAVE_ARM_TWD if SMP select HAVE_IMX_ANATOP select HAVE_IMX_GPC select HAVE_IMX_MMDC select HAVE_IMX_SRC - select HAVE_SMP select MFD_SYSCON - select MIGHT_HAVE_PCI - select PCI_DOMAINS if PCI - select PINCTRL_IMX6Q select PL310_ERRATA_588369 if CACHE_PL310 select PL310_ERRATA_727915 if CACHE_PL310 select PL310_ERRATA_769419 if CACHE_PL310 - select PM_OPP if PM + +config SOC_IMX6Q + bool "i.MX6 Quad/DualLite support" + select ARM_ERRATA_764369 if SMP + select HAVE_ARM_SCU if SMP + select HAVE_ARM_TWD if SMP + select PCI_DOMAINS if PCI + select PINCTRL_IMX6Q + select SOC_IMX6 help This enables support for Freescale i.MX6 Quad processor. config SOC_IMX6SL bool "i.MX6 SoloLite support" - select ARM_ERRATA_754322 - select ARM_ERRATA_775420 - select ARM_GIC - select CPU_V7 - select HAVE_IMX_ANATOP - select HAVE_IMX_GPC - select HAVE_IMX_MMDC - select HAVE_IMX_SRC - select MFD_SYSCON select PINCTRL_IMX6SL - select PL310_ERRATA_588369 if CACHE_PL310 - select PL310_ERRATA_727915 if CACHE_PL310 - select PL310_ERRATA_769419 if CACHE_PL310 + select SOC_IMX6 help This enables support for Freescale i.MX6 SoloLite processor. +config SOC_IMX6SX + bool "i.MX6 SoloX support" + select PINCTRL_IMX6SX + select SOC_IMX6 + + help + This enables support for Freescale i.MX6 SoloX processor. + config SOC_VF610 bool "Vybrid Family VF610 support" - select CPU_V7 select ARM_GIC - select CLKSRC_OF select PINCTRL_VF610 select VF_PIT_TIMER select PL310_ERRATA_588369 if CACHE_PL310 diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index ec419649320f..bbe93bbfd003 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o ifeq ($(CONFIG_CPU_IDLE),y) obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o +obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o endif ifdef CONFIG_SND_IMX_SOC @@ -100,15 +101,13 @@ obj-$(CONFIG_SMP) += headsmp.o platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o +obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o mach-imx6sx.o -obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o -# i.MX6SL reuses i.MX6Q code -obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o - -# i.MX5 based machines -obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o -obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o -obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd51-baseboard.o +ifeq ($(CONFIG_SUSPEND),y) +AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a +obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o +endif +obj-$(CONFIG_SOC_IMX6) += pm-imx6.o obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o obj-$(CONFIG_SOC_IMX50) += mach-imx50.o diff --git a/arch/arm/mach-imx/avic.c b/arch/arm/mach-imx/avic.c index 8d1df2e4b7ac..24b103c67f82 100644 --- a/arch/arm/mach-imx/avic.c +++ b/arch/arm/mach-imx/avic.c @@ -135,7 +135,7 @@ static __init void avic_init_gc(int idx, unsigned int irq_start) irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); } -asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs) +static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs) { u32 nivector; @@ -190,6 +190,8 @@ void __init mxc_init_irq(void __iomem *irqbase) for (i = 0; i < 8; i++) __raw_writel(0, avic_base + AVIC_NIPRIORITY(i)); + set_handle_irq(avic_handle_irq); + #ifdef CONFIG_FIQ /* Initialize FIQ */ init_FIQ(FIQ_START); diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c index a2ecc006b322..4ba587da89d2 100644 --- a/arch/arm/mach-imx/clk-gate2.c +++ b/arch/arm/mach-imx/clk-gate2.c @@ -27,48 +27,61 @@ * parent - fixed parent. No clk_set_parent support */ -#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) +struct clk_gate2 { + struct clk_hw hw; + void __iomem *reg; + u8 bit_idx; + u8 flags; + spinlock_t *lock; + unsigned int *share_count; +}; + +#define to_clk_gate2(_hw) container_of(_hw, struct clk_gate2, hw) static int clk_gate2_enable(struct clk_hw *hw) { - struct clk_gate *gate = to_clk_gate(hw); + struct clk_gate2 *gate = to_clk_gate2(hw); u32 reg; unsigned long flags = 0; - if (gate->lock) - spin_lock_irqsave(gate->lock, flags); + spin_lock_irqsave(gate->lock, flags); + + if (gate->share_count && (*gate->share_count)++ > 0) + goto out; reg = readl(gate->reg); reg |= 3 << gate->bit_idx; writel(reg, gate->reg); - if (gate->lock) - spin_unlock_irqrestore(gate->lock, flags); +out: + spin_unlock_irqrestore(gate->lock, flags); return 0; } static void clk_gate2_disable(struct clk_hw *hw) { - struct clk_gate *gate = to_clk_gate(hw); + struct clk_gate2 *gate = to_clk_gate2(hw); u32 reg; unsigned long flags = 0; - if (gate->lock) - spin_lock_irqsave(gate->lock, flags); + spin_lock_irqsave(gate->lock, flags); + + if (gate->share_count && --(*gate->share_count) > 0) + goto out; reg = readl(gate->reg); reg &= ~(3 << gate->bit_idx); writel(reg, gate->reg); - if (gate->lock) - spin_unlock_irqrestore(gate->lock, flags); +out: + spin_unlock_irqrestore(gate->lock, flags); } static int clk_gate2_is_enabled(struct clk_hw *hw) { u32 reg; - struct clk_gate *gate = to_clk_gate(hw); + struct clk_gate2 *gate = to_clk_gate2(hw); reg = readl(gate->reg); @@ -87,21 +100,23 @@ static struct clk_ops clk_gate2_ops = { struct clk *clk_register_gate2(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx, - u8 clk_gate2_flags, spinlock_t *lock) + u8 clk_gate2_flags, spinlock_t *lock, + unsigned int *share_count) { - struct clk_gate *gate; + struct clk_gate2 *gate; struct clk *clk; struct clk_init_data init; - gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); + gate = kzalloc(sizeof(struct clk_gate2), GFP_KERNEL); if (!gate) return ERR_PTR(-ENOMEM); - /* struct clk_gate assignments */ + /* struct clk_gate2 assignments */ gate->reg = reg; gate->bit_idx = bit_idx; gate->flags = clk_gate2_flags; gate->lock = lock; + gate->share_count = share_count; init.name = name; init.ops = &clk_gate2_ops; diff --git a/arch/arm/mach-imx/clk-imx1.c b/arch/arm/mach-imx/clk-imx1.c index 15f9d223cf0b..7f739be3de2c 100644 --- a/arch/arm/mach-imx/clk-imx1.c +++ b/arch/arm/mach-imx/clk-imx1.c @@ -40,12 +40,14 @@ #define SCM_GCCR IO_ADDR_SCM(0xc) static const char *prem_sel_clks[] = { "clk32_premult", "clk16m", }; -static const char *clko_sel_clks[] = { "per1", "hclk", "clk48m", "clk16m", "prem", - "fclk", }; +static const char *clko_sel_clks[] = { "per1", "hclk", "clk48m", "clk16m", + "prem", "fclk", }; + enum imx1_clks { - dummy, clk32, clk16m_ext, clk16m, clk32_premult, prem, mpll, spll, mcu, - fclk, hclk, clk48m, per1, per2, per3, clko, dma_gate, csi_gate, - mma_gate, usbd_gate, clk_max + dummy, clk32, clk16m_ext, clk16m, clk32_premult, prem, mpll, mpll_gate, + spll, spll_gate, mcu, fclk, hclk, clk48m, per1, per2, per3, clko, + uart3_gate, ssi2_gate, brom_gate, dma_gate, csi_gate, mma_gate, + usbd_gate, clk_max }; static struct clk *clk[clk_max]; @@ -62,17 +64,22 @@ int __init mx1_clocks_init(unsigned long fref) clk[prem] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks, ARRAY_SIZE(prem_sel_clks)); clk[mpll] = imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0); + clk[mpll_gate] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0); clk[spll] = imx_clk_pllv1("spll", "prem", CCM_SPCTL0); + clk[spll_gate] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1); clk[mcu] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1); - clk[fclk] = imx_clk_divider("fclk", "mpll", CCM_CSCR, 15, 1); - clk[hclk] = imx_clk_divider("hclk", "spll", CCM_CSCR, 10, 4); - clk[clk48m] = imx_clk_divider("clk48m", "spll", CCM_CSCR, 26, 3); - clk[per1] = imx_clk_divider("per1", "spll", CCM_PCDR, 0, 4); - clk[per2] = imx_clk_divider("per2", "spll", CCM_PCDR, 4, 4); - clk[per3] = imx_clk_divider("per3", "spll", CCM_PCDR, 16, 7); + clk[fclk] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 15, 1); + clk[hclk] = imx_clk_divider("hclk", "spll_gate", CCM_CSCR, 10, 4); + clk[clk48m] = imx_clk_divider("clk48m", "spll_gate", CCM_CSCR, 26, 3); + clk[per1] = imx_clk_divider("per1", "spll_gate", CCM_PCDR, 0, 4); + clk[per2] = imx_clk_divider("per2", "spll_gate", CCM_PCDR, 4, 4); + clk[per3] = imx_clk_divider("per3", "spll_gate", CCM_PCDR, 16, 7); clk[clko] = imx_clk_mux("clko", CCM_CSCR, 29, 3, clko_sel_clks, ARRAY_SIZE(clko_sel_clks)); - clk[dma_gate] = imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 4); + clk[uart3_gate] = imx_clk_gate("uart3_gate", "hclk", SCM_GCCR, 6); + clk[ssi2_gate] = imx_clk_gate("ssi2_gate", "hclk", SCM_GCCR, 5); + clk[brom_gate] = imx_clk_gate("brom_gate", "hclk", SCM_GCCR, 4); + clk[dma_gate] = imx_clk_gate("dma_gate", "hclk", SCM_GCCR, 3); clk[csi_gate] = imx_clk_gate("csi_gate", "hclk", SCM_GCCR, 2); clk[mma_gate] = imx_clk_gate("mma_gate", "hclk", SCM_GCCR, 1); clk[usbd_gate] = imx_clk_gate("usbd_gate", "clk48m", SCM_GCCR, 0); @@ -84,9 +91,6 @@ int __init mx1_clocks_init(unsigned long fref) clk_register_clkdev(clk[dma_gate], "ahb", "imx1-dma"); clk_register_clkdev(clk[hclk], "ipg", "imx1-dma"); - clk_register_clkdev(clk[csi_gate], NULL, "mx1-camera.0"); - clk_register_clkdev(clk[mma_gate], "mma", NULL); - clk_register_clkdev(clk[usbd_gate], NULL, "imx_udc.0"); clk_register_clkdev(clk[per1], "per", "imx-gpt.0"); clk_register_clkdev(clk[hclk], "ipg", "imx-gpt.0"); clk_register_clkdev(clk[per1], "per", "imx1-uart.0"); @@ -94,20 +98,15 @@ int __init mx1_clocks_init(unsigned long fref) clk_register_clkdev(clk[per1], "per", "imx1-uart.1"); clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.1"); clk_register_clkdev(clk[per1], "per", "imx1-uart.2"); - clk_register_clkdev(clk[hclk], "ipg", "imx1-uart.2"); + clk_register_clkdev(clk[uart3_gate], "ipg", "imx1-uart.2"); clk_register_clkdev(clk[hclk], NULL, "imx1-i2c.0"); clk_register_clkdev(clk[per2], "per", "imx1-cspi.0"); clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.0"); clk_register_clkdev(clk[per2], "per", "imx1-cspi.1"); clk_register_clkdev(clk[dummy], "ipg", "imx1-cspi.1"); - clk_register_clkdev(clk[per2], NULL, "imx-mmc.0"); clk_register_clkdev(clk[per2], "per", "imx1-fb.0"); clk_register_clkdev(clk[dummy], "ipg", "imx1-fb.0"); clk_register_clkdev(clk[dummy], "ahb", "imx1-fb.0"); - clk_register_clkdev(clk[hclk], "mshc", NULL); - clk_register_clkdev(clk[per3], "ssi", NULL); - clk_register_clkdev(clk[clk32], NULL, "imx1-rtc.0"); - clk_register_clkdev(clk[clko], "clko", NULL); mxc_timer_init(MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), MX1_TIM1_INT); diff --git a/arch/arm/mach-imx/clk-imx21.c b/arch/arm/mach-imx/clk-imx21.c index d7ed66091a2a..bdc2e4630a08 100644 --- a/arch/arm/mach-imx/clk-imx21.c +++ b/arch/arm/mach-imx/clk-imx21.c @@ -149,7 +149,6 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href) clk_register_clkdev(clk[per1], "per", "imx-gpt.1"); clk_register_clkdev(clk[gpt3_ipg_gate], "ipg", "imx-gpt.2"); clk_register_clkdev(clk[per1], "per", "imx-gpt.2"); - clk_register_clkdev(clk[pwm_ipg_gate], "pwm", "mxc_pwm.0"); clk_register_clkdev(clk[per2], "per", "imx21-cspi.0"); clk_register_clkdev(clk[cspi1_ipg_gate], "ipg", "imx21-cspi.0"); clk_register_clkdev(clk[per2], "per", "imx21-cspi.1"); diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c index 69858c78f40d..ae578c096ad8 100644 --- a/arch/arm/mach-imx/clk-imx25.c +++ b/arch/arm/mach-imx/clk-imx25.c @@ -62,6 +62,10 @@ static struct clk_onecell_data clk_data; static const char *cpu_sel_clks[] = { "mpll", "mpll_cpu_3_4", }; static const char *per_sel_clks[] = { "ahb", "upll", }; +static const char *cko_sel_clks[] = { "dummy", "osc", "cpu", "ahb", + "ipg", "dummy", "dummy", "dummy", + "dummy", "dummy", "per0", "per2", + "per13", "per14", "usbotg_ahb", "dummy",}; enum mx25_clks { dummy, osc, mpll, upll, mpll_cpu_3_4, cpu_sel, cpu, ahb, usb_div, ipg, @@ -82,7 +86,7 @@ enum mx25_clks { pwm2_ipg, pwm3_ipg, pwm4_ipg, rngb_ipg, reserved16, scc_ipg, sdma_ipg, sim1_ipg, sim2_ipg, slcdc_ipg, spba_ipg, ssi1_ipg, ssi2_ipg, tsc_ipg, uart1_ipg, uart2_ipg, uart3_ipg, uart4_ipg, uart5_ipg, reserved17, - wdt_ipg, clk_max + wdt_ipg, cko_div, cko_sel, cko, clk_max }; static struct clk *clk[clk_max]; @@ -117,6 +121,9 @@ static int __init __mx25_clocks_init(unsigned long osc_rate) clk[per13_sel] = imx_clk_mux("per13_sel", ccm(CCM_MCR), 13, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); clk[per14_sel] = imx_clk_mux("per14_sel", ccm(CCM_MCR), 14, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); clk[per15_sel] = imx_clk_mux("per15_sel", ccm(CCM_MCR), 15, 1, per_sel_clks, ARRAY_SIZE(per_sel_clks)); + clk[cko_div] = imx_clk_divider("cko_div", "cko_sel", ccm(CCM_MCR), 24, 6); + clk[cko_sel] = imx_clk_mux("cko_sel", ccm(CCM_MCR), 20, 4, cko_sel_clks, ARRAY_SIZE(cko_sel_clks)); + clk[cko] = imx_clk_gate("cko", "cko_div", ccm(CCM_MCR), 30); clk[per0] = imx_clk_divider("per0", "per0_sel", ccm(CCM_PCDR0), 0, 6); clk[per1] = imx_clk_divider("per1", "per1_sel", ccm(CCM_PCDR0), 8, 6); clk[per2] = imx_clk_divider("per2", "per2_sel", ccm(CCM_PCDR0), 16, 6); @@ -230,6 +237,12 @@ static int __init __mx25_clocks_init(unsigned long osc_rate) clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0"); clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0"); + /* + * Let's initially set up CLKO parent as ipg, since this configuration + * is used on some imx25 board designs to clock the audio codec. + */ + clk_set_parent(clk[cko_sel], clk[ipg]); + return 0; } @@ -265,14 +278,6 @@ int __init mx25_clocks_init(void) clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0"); clk_register_clkdev(clk[cspi2_ipg], NULL, "imx35-cspi.1"); clk_register_clkdev(clk[cspi3_ipg], NULL, "imx35-cspi.2"); - clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.0"); - clk_register_clkdev(clk[per10], "per", "mxc_pwm.0"); - clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.1"); - clk_register_clkdev(clk[per10], "per", "mxc_pwm.1"); - clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.2"); - clk_register_clkdev(clk[per10], "per", "mxc_pwm.2"); - clk_register_clkdev(clk[pwm1_ipg], "ipg", "mxc_pwm.3"); - clk_register_clkdev(clk[per10], "per", "mxc_pwm.3"); clk_register_clkdev(clk[kpp_ipg], NULL, "imx-keypad"); clk_register_clkdev(clk[tsc_ipg], NULL, "mx25-adc"); clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.0"); @@ -312,8 +317,6 @@ int __init mx25_clocks_init(void) int __init mx25_clocks_init_dt(void) { struct device_node *np; - void __iomem *base; - int irq; unsigned long osc_rate = 24000000; /* retrieve the freqency of fixed clocks from device tree */ @@ -333,12 +336,7 @@ int __init mx25_clocks_init_dt(void) __mx25_clocks_init(osc_rate); - np = of_find_compatible_node(NULL, NULL, "fsl,imx25-gpt"); - base = of_iomap(np, 0); - WARN_ON(!base); - irq = irq_of_parse_and_map(np, 0); - - mxc_timer_init(base, irq); + mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx25-gpt")); return 0; } diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c index c6b40f386786..317a662626d6 100644 --- a/arch/arm/mach-imx/clk-imx27.c +++ b/arch/arm/mach-imx/clk-imx27.c @@ -82,7 +82,8 @@ enum mx27_clks { csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate, uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate, uart2_ipg_gate, uart1_ipg_gate, ckih_div1p5, fpm, mpll_osc_sel, - mpll_sel, spll_gate, clk_max + mpll_sel, spll_gate, mshc_div, rtic_ipg_gate, mshc_ipg_gate, + rtic_ahb_gate, mshc_baud_gate, clk_max }; static struct clk *clk[clk_max]; @@ -117,6 +118,7 @@ int __init mx27_clocks_init(unsigned long fref) clk[ipg] = imx_clk_divider("ipg", "ahb", CCM_CSCR, 8, 1); } + clk[mshc_div] = imx_clk_divider("mshc_div", "ahb", CCM_PCDR0, 0, 6); clk[nfc_div] = imx_clk_divider("nfc_div", "ahb", CCM_PCDR0, 6, 4); clk[per1_div] = imx_clk_divider("per1_div", "mpll_main2", CCM_PCDR1, 0, 6); clk[per2_div] = imx_clk_divider("per2_div", "mpll_main2", CCM_PCDR1, 8, 6); @@ -145,9 +147,11 @@ int __init mx27_clocks_init(unsigned long fref) clk[sdhc1_ipg_gate] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 5); clk[scc_ipg_gate] = imx_clk_gate("scc_ipg_gate", "ipg", CCM_PCCR0, 6); clk[sahara_ipg_gate] = imx_clk_gate("sahara_ipg_gate", "ipg", CCM_PCCR0, 7); + clk[rtic_ipg_gate] = imx_clk_gate("rtic_ipg_gate", "ipg", CCM_PCCR0, 8); clk[rtc_ipg_gate] = imx_clk_gate("rtc_ipg_gate", "ipg", CCM_PCCR0, 9); clk[pwm_ipg_gate] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR0, 11); clk[owire_ipg_gate] = imx_clk_gate("owire_ipg_gate", "ipg", CCM_PCCR0, 12); + clk[mshc_ipg_gate] = imx_clk_gate("mshc_ipg_gate", "ipg", CCM_PCCR0, 13); clk[lcdc_ipg_gate] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 14); clk[kpp_ipg_gate] = imx_clk_gate("kpp_ipg_gate", "ipg", CCM_PCCR0, 15); clk[iim_ipg_gate] = imx_clk_gate("iim_ipg_gate", "ipg", CCM_PCCR0, 16); @@ -166,6 +170,7 @@ int __init mx27_clocks_init(unsigned long fref) clk[cspi3_ipg_gate] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR0, 29); clk[cspi2_ipg_gate] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 30); clk[cspi1_ipg_gate] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 31); + clk[mshc_baud_gate] = imx_clk_gate("mshc_baud_gate", "mshc_div", CCM_PCCR1, 2); clk[nfc_baud_gate] = imx_clk_gate("nfc_baud_gate", "nfc_div", CCM_PCCR1, 3); clk[ssi2_baud_gate] = imx_clk_gate("ssi2_baud_gate", "ssi2_div", CCM_PCCR1, 4); clk[ssi1_baud_gate] = imx_clk_gate("ssi1_baud_gate", "ssi1_div", CCM_PCCR1, 5); @@ -177,6 +182,7 @@ int __init mx27_clocks_init(unsigned long fref) clk[usb_ahb_gate] = imx_clk_gate("usb_ahb_gate", "ahb", CCM_PCCR1, 11); clk[slcdc_ahb_gate] = imx_clk_gate("slcdc_ahb_gate", "ahb", CCM_PCCR1, 12); clk[sahara_ahb_gate] = imx_clk_gate("sahara_ahb_gate", "ahb", CCM_PCCR1, 13); + clk[rtic_ahb_gate] = imx_clk_gate("rtic_ahb_gate", "ahb", CCM_PCCR1, 14); clk[lcdc_ahb_gate] = imx_clk_gate("lcdc_ahb_gate", "ahb", CCM_PCCR1, 15); clk[vpu_ahb_gate] = imx_clk_gate("vpu_ahb_gate", "ahb", CCM_PCCR1, 16); clk[fec_ahb_gate] = imx_clk_gate("fec_ahb_gate", "ahb", CCM_PCCR1, 17); @@ -221,17 +227,6 @@ int __init mx27_clocks_init(unsigned long fref) clk_register_clkdev(clk[per1_gate], "per", "imx21-uart.5"); clk_register_clkdev(clk[gpt1_ipg_gate], "ipg", "imx-gpt.0"); clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.0"); - clk_register_clkdev(clk[gpt2_ipg_gate], "ipg", "imx-gpt.1"); - clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.1"); - clk_register_clkdev(clk[gpt3_ipg_gate], "ipg", "imx-gpt.2"); - clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.2"); - clk_register_clkdev(clk[gpt4_ipg_gate], "ipg", "imx-gpt.3"); - clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.3"); - clk_register_clkdev(clk[gpt5_ipg_gate], "ipg", "imx-gpt.4"); - clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.4"); - clk_register_clkdev(clk[gpt6_ipg_gate], "ipg", "imx-gpt.5"); - clk_register_clkdev(clk[per1_gate], "per", "imx-gpt.5"); - clk_register_clkdev(clk[pwm_ipg_gate], NULL, "mxc_pwm.0"); clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.0"); clk_register_clkdev(clk[sdhc1_ipg_gate], "ipg", "imx21-mmc.0"); clk_register_clkdev(clk[per2_gate], "per", "imx21-mmc.1"); @@ -279,14 +274,7 @@ int __init mx27_clocks_init(unsigned long fref) clk_register_clkdev(clk[emma_ipg_gate], "emma-ipg", "imx27-camera.0"); clk_register_clkdev(clk[emma_ahb_gate], "ahb", "m2m-emmaprp.0"); clk_register_clkdev(clk[emma_ipg_gate], "ipg", "m2m-emmaprp.0"); - clk_register_clkdev(clk[iim_ipg_gate], "iim", NULL); - clk_register_clkdev(clk[gpio_ipg_gate], "gpio", NULL); - clk_register_clkdev(clk[brom_ahb_gate], "brom", NULL); - clk_register_clkdev(clk[ata_ahb_gate], "ata", NULL); - clk_register_clkdev(clk[rtc_ipg_gate], NULL, "imx21-rtc"); - clk_register_clkdev(clk[scc_ipg_gate], "scc", NULL); clk_register_clkdev(clk[cpu_div], NULL, "cpu0"); - clk_register_clkdev(clk[emi_ahb_gate], "emi_ahb" , NULL); mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1); @@ -297,7 +285,6 @@ int __init mx27_clocks_init(unsigned long fref) return 0; } -#ifdef CONFIG_OF int __init mx27_clocks_init_dt(void) { struct device_node *np; @@ -313,4 +300,3 @@ int __init mx27_clocks_init_dt(void) return mx27_clocks_init(fref); } -#endif diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c index b5b65f3efaf1..4a9de0835eb1 100644 --- a/arch/arm/mach-imx/clk-imx31.c +++ b/arch/arm/mach-imx/clk-imx31.c @@ -191,7 +191,6 @@ int __init mx31_clocks_init(unsigned long fref) return 0; } -#ifdef CONFIG_OF int __init mx31_clocks_init_dt(void) { struct device_node *np; @@ -207,4 +206,3 @@ int __init mx31_clocks_init_dt(void) return mx31_clocks_init(fref); } -#endif diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c index a4d5e425cd82..71c86a2f856d 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/arch/arm/mach-imx/clk-imx35.c @@ -289,14 +289,12 @@ int __init mx35_clocks_init(void) return 0; } -static int __init mx35_clocks_init_dt(struct device_node *ccm_node) +static void __init mx35_clocks_init_dt(struct device_node *ccm_node) { clk_data.clks = clk; clk_data.clk_num = ARRAY_SIZE(clk); of_clk_add_provider(ccm_node, of_clk_src_onecell_get, &clk_data); mx35_clocks_init(); - - return 0; } CLK_OF_DECLARE(imx35, "fsl,imx35-ccm", mx35_clocks_init_dt); diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index 19fca1fdc6fe..21d2b111c83d 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c @@ -266,8 +266,6 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, clk_register_clkdev(clk[IMX5_CLK_ECSPI2_PER_GATE], "per", "imx51-ecspi.1"); clk_register_clkdev(clk[IMX5_CLK_ECSPI2_IPG_GATE], "ipg", "imx51-ecspi.1"); clk_register_clkdev(clk[IMX5_CLK_CSPI_IPG_GATE], NULL, "imx35-cspi.2"); - clk_register_clkdev(clk[IMX5_CLK_PWM1_IPG_GATE], "pwm", "mxc_pwm.0"); - clk_register_clkdev(clk[IMX5_CLK_PWM2_IPG_GATE], "pwm", "mxc_pwm.1"); clk_register_clkdev(clk[IMX5_CLK_I2C1_GATE], NULL, "imx21-i2c.0"); clk_register_clkdev(clk[IMX5_CLK_I2C2_GATE], NULL, "imx21-i2c.1"); clk_register_clkdev(clk[IMX5_CLK_USBOH3_PER_GATE], "per", "mxc-ehci.0"); @@ -324,9 +322,8 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, static void __init mx50_clocks_init(struct device_node *np) { - void __iomem *base; unsigned long r; - int i, irq; + int i; clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE); clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE); @@ -374,11 +371,7 @@ static void __init mx50_clocks_init(struct device_node *np) r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000); clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r); - np = of_find_compatible_node(NULL, NULL, "fsl,imx50-gpt"); - base = of_iomap(np, 0); - WARN_ON(!base); - irq = irq_of_parse_and_map(np, 0); - mxc_timer_init(base, irq); + mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx50-gpt")); } CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init); @@ -438,7 +431,6 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc, clk_register_clkdev(clk[IMX5_CLK_HSI2C_GATE], NULL, "imx21-i2c.2"); clk_register_clkdev(clk[IMX5_CLK_MX51_MIPI], "mipi_hsp", NULL); - clk_register_clkdev(clk[IMX5_CLK_VPU_GATE], NULL, "imx51-vpu.0"); clk_register_clkdev(clk[IMX5_CLK_FEC_GATE], NULL, "imx27-fec.0"); clk_register_clkdev(clk[IMX5_CLK_USB_PHY_GATE], "phy", "mxc-ehci.0"); clk_register_clkdev(clk[IMX5_CLK_ESDHC1_IPG_GATE], "ipg", "sdhci-esdhc-imx51.0"); @@ -494,9 +486,8 @@ CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init_dt); static void __init mx53_clocks_init(struct device_node *np) { - int i, irq; + int i; unsigned long r; - void __iomem *base; clk[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE); clk[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE); @@ -563,7 +554,6 @@ static void __init mx53_clocks_init(struct device_node *np) mx5_clocks_common_init(0, 0, 0, 0); - clk_register_clkdev(clk[IMX5_CLK_VPU_GATE], NULL, "imx53-vpu.0"); clk_register_clkdev(clk[IMX5_CLK_I2C3_GATE], NULL, "imx21-i2c.2"); clk_register_clkdev(clk[IMX5_CLK_FEC_GATE], NULL, "imx25-fec.0"); clk_register_clkdev(clk[IMX5_CLK_USB_PHY1_GATE], "usb_phy1", "mxc-ehci.0"); @@ -594,10 +584,6 @@ static void __init mx53_clocks_init(struct device_node *np) r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000); clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r); - np = of_find_compatible_node(NULL, NULL, "fsl,imx53-gpt"); - base = of_iomap(np, 0); - WARN_ON(!base); - irq = irq_of_parse_and_map(np, 0); - mxc_timer_init(base, irq); + mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx53-gpt")); } CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init); diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 4d677f442539..8e795dea02ec 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -107,7 +107,7 @@ enum mx6q_clks { sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate, usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div, - lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, clk_max + lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, esai_ahb, clk_max }; static struct clk *clk[clk_max]; @@ -140,11 +140,13 @@ static struct clk_div_table video_div_table[] = { { /* sentinel */ } }; +static unsigned int share_count_esai; + static void __init imx6q_clocks_init(struct device_node *ccm_node) { struct device_node *np; void __iomem *base; - int i, irq; + int i; int ret; clk[dummy] = imx_clk_fixed("dummy", 0); @@ -208,8 +210,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) * the "output_enable" bit as a gate, even though it's really just * enabling clock output. */ - clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "dummy", base + 0x160, 10); - clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "dummy", base + 0x160, 11); + clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "lvds1_sel", base + 0x160, 10); + clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "lvds2_sel", base + 0x160, 11); /* name parent_name reg idx */ clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0); @@ -258,14 +260,14 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); - clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); - clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); - clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); - clk[ipu2_di1_pre_sel] = imx_clk_mux("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); - clk[ipu1_di0_sel] = imx_clk_mux("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels)); - clk[ipu1_di1_sel] = imx_clk_mux("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels)); - clk[ipu2_di0_sel] = imx_clk_mux("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels)); - clk[ipu2_di1_sel] = imx_clk_mux("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels)); + clk[ipu1_di0_pre_sel] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); + clk[ipu1_di1_pre_sel] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); + clk[ipu2_di0_pre_sel] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); + clk[ipu2_di1_pre_sel] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); + clk[ipu1_di0_sel] = imx_clk_mux_flags("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT); + clk[ipu1_di1_sel] = imx_clk_mux_flags("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT); + clk[ipu2_di0_sel] = imx_clk_mux_flags("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT); + clk[ipu2_di1_sel] = imx_clk_mux_flags("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT); clk[hsi_tx_sel] = imx_clk_mux("hsi_tx_sel", base + 0x30, 28, 1, hsi_tx_sels, ARRAY_SIZE(hsi_tx_sels)); clk[pcie_axi_sel] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels)); clk[ssi1_sel] = imx_clk_fixup_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); @@ -352,9 +354,14 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk[ecspi2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2); clk[ecspi3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4); clk[ecspi4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6); - clk[ecspi5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8); + if (cpu_is_imx6dl()) + /* ecspi5 is replaced with i2c4 on imx6dl & imx6s */ + clk[ecspi5] = imx_clk_gate2("i2c4", "ipg_per", base + 0x6c, 8); + else + clk[ecspi5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8); clk[enet] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10); - clk[esai] = imx_clk_gate2("esai", "esai_podf", base + 0x6c, 16); + clk[esai] = imx_clk_gate2_shared("esai", "esai_podf", base + 0x6c, 16, &share_count_esai); + clk[esai_ahb] = imx_clk_gate2_shared("esai_ahb", "ahb", base + 0x6c, 16, &share_count_esai); clk[gpt_ipg] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20); clk[gpt_ipg_per] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22); if (cpu_is_imx6dl()) @@ -437,12 +444,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0"); clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0"); - clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL); - clk_register_clkdev(clk[ahb], "ahb", NULL); - clk_register_clkdev(clk[cko1], "cko1", NULL); - clk_register_clkdev(clk[arm], NULL, "cpu0"); - clk_register_clkdev(clk[pll4_post_div], "pll4_post_div", NULL); - clk_register_clkdev(clk[pll4_audio], "pll4_audio", NULL); + clk_register_clkdev(clk[enet_ref], "enet_ref", NULL); if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) || cpu_is_imx6dl()) { @@ -450,6 +452,15 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]); } + clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]); + clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]); + clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]); + clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]); + clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]); + clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]); + clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]); + clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]); + /* * The gpmi needs 100MHz frequency in the EDO/Sync mode, * We can not get the 100MHz from the pll2_pfd0_352m. @@ -485,10 +496,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) /* Set initial power mode */ imx6q_set_lpm(WAIT_CLOCKED); - np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); - base = of_iomap(np, 0); - WARN_ON(!base); - irq = irq_of_parse_and_map(np, 0); - mxc_timer_init(base, irq); + mxc_timer_init_dt(of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt")); } CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init); diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c index 4c86f3035205..21cf06cebade 100644 --- a/arch/arm/mach-imx/clk-imx6sl.c +++ b/arch/arm/mach-imx/clk-imx6sl.c @@ -1,5 +1,5 @@ /* - * Copyright 2013 Freescale Semiconductor, Inc. + * Copyright 2013-2014 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,27 +18,43 @@ #include "clk.h" #include "common.h" -static const char const *step_sels[] = { "osc", "pll2_pfd2", }; -static const char const *pll1_sw_sels[] = { "pll1_sys", "step", }; -static const char const *ocram_alt_sels[] = { "pll2_pfd2", "pll3_pfd1", }; -static const char const *ocram_sels[] = { "periph", "ocram_alt_sels", }; -static const char const *pre_periph_sels[] = { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", }; -static const char const *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy", }; -static const char const *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", }; -static const char const *periph_sels[] = { "pre_periph_sel", "periph_clk2_podf", }; -static const char const *periph2_sels[] = { "pre_periph2_sel", "periph2_clk2_podf", }; -static const char const *csi_lcdif_sels[] = { "mmdc", "pll2_pfd2", "pll3_120m", "pll3_pfd1", }; -static const char const *usdhc_sels[] = { "pll2_pfd2", "pll2_pfd0", }; -static const char const *ssi_sels[] = { "pll3_pfd2", "pll3_pfd3", "pll4_audio_div", "dummy", }; -static const char const *perclk_sels[] = { "ipg", "osc", }; -static const char const *epdc_pxp_sels[] = { "mmdc", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd1", }; -static const char const *gpu2d_ovg_sels[] = { "pll3_pfd1", "pll3_usb_otg", "pll2_bus", "pll2_pfd2", }; -static const char const *gpu2d_sels[] = { "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", "pll2_bus", }; -static const char const *lcdif_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll3_pfd0", "pll3_pfd1", }; -static const char const *epdc_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", }; -static const char const *audio_sels[] = { "pll4_audio_div", "pll3_pfd2", "pll3_pfd3", "pll3_usb_otg", }; -static const char const *ecspi_sels[] = { "pll3_60m", "osc", }; -static const char const *uart_sels[] = { "pll3_80m", "osc", }; +#define CCSR 0xc +#define BM_CCSR_PLL1_SW_CLK_SEL (1 << 2) +#define CACRR 0x10 +#define CDHIPR 0x48 +#define BM_CDHIPR_ARM_PODF_BUSY (1 << 16) +#define ARM_WAIT_DIV_396M 2 +#define ARM_WAIT_DIV_792M 4 +#define ARM_WAIT_DIV_996M 6 + +#define PLL_ARM 0x0 +#define BM_PLL_ARM_DIV_SELECT (0x7f << 0) +#define BM_PLL_ARM_POWERDOWN (1 << 12) +#define BM_PLL_ARM_ENABLE (1 << 13) +#define BM_PLL_ARM_LOCK (1 << 31) +#define PLL_ARM_DIV_792M 66 + +static const char *step_sels[] = { "osc", "pll2_pfd2", }; +static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; +static const char *ocram_alt_sels[] = { "pll2_pfd2", "pll3_pfd1", }; +static const char *ocram_sels[] = { "periph", "ocram_alt_sels", }; +static const char *pre_periph_sels[] = { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", }; +static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy", }; +static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", }; +static const char *periph_sels[] = { "pre_periph_sel", "periph_clk2_podf", }; +static const char *periph2_sels[] = { "pre_periph2_sel", "periph2_clk2_podf", }; +static const char *csi_lcdif_sels[] = { "mmdc", "pll2_pfd2", "pll3_120m", "pll3_pfd1", }; +static const char *usdhc_sels[] = { "pll2_pfd2", "pll2_pfd0", }; +static const char *ssi_sels[] = { "pll3_pfd2", "pll3_pfd3", "pll4_audio_div", "dummy", }; +static const char *perclk_sels[] = { "ipg", "osc", }; +static const char *epdc_pxp_sels[] = { "mmdc", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd2", "pll3_pfd1", }; +static const char *gpu2d_ovg_sels[] = { "pll3_pfd1", "pll3_usb_otg", "pll2_bus", "pll2_pfd2", }; +static const char *gpu2d_sels[] = { "pll2_pfd2", "pll3_usb_otg", "pll3_pfd1", "pll2_bus", }; +static const char *lcdif_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll3_pfd0", "pll3_pfd1", }; +static const char *epdc_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", }; +static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2", "pll3_pfd3", "pll3_usb_otg", }; +static const char *ecspi_sels[] = { "pll3_60m", "osc", }; +static const char *uart_sels[] = { "pll3_80m", "osc", }; static struct clk_div_table clk_enet_ref_table[] = { { .val = 0, .div = 20, }, @@ -65,13 +81,96 @@ static struct clk_div_table video_div_table[] = { static struct clk *clks[IMX6SL_CLK_END]; static struct clk_onecell_data clk_data; +static void __iomem *ccm_base; +static void __iomem *anatop_base; + +static const u32 clks_init_on[] __initconst = { + IMX6SL_CLK_IPG, IMX6SL_CLK_ARM, IMX6SL_CLK_MMDC_ROOT, +}; + +/* + * ERR005311 CCM: After exit from WAIT mode, unwanted interrupt(s) taken + * during WAIT mode entry process could cause cache memory + * corruption. + * + * Software workaround: + * To prevent this issue from occurring, software should ensure that the + * ARM to IPG clock ratio is less than 12:5 (that is < 2.4x), before + * entering WAIT mode. + * + * This function will set the ARM clk to max value within the 12:5 limit. + * As IPG clock is fixed at 66MHz(so ARM freq must not exceed 158.4MHz), + * ARM freq are one of below setpoints: 396MHz, 792MHz and 996MHz, since + * the clk APIs can NOT be called in idle thread(may cause kernel schedule + * as there is sleep function in PLL wait function), so here we just slow + * down ARM to below freq according to previous freq: + * + * run mode wait mode + * 396MHz -> 132MHz; + * 792MHz -> 158.4MHz; + * 996MHz -> 142.3MHz; + */ +static int imx6sl_get_arm_divider_for_wait(void) +{ + if (readl_relaxed(ccm_base + CCSR) & BM_CCSR_PLL1_SW_CLK_SEL) { + return ARM_WAIT_DIV_396M; + } else { + if ((readl_relaxed(anatop_base + PLL_ARM) & + BM_PLL_ARM_DIV_SELECT) == PLL_ARM_DIV_792M) + return ARM_WAIT_DIV_792M; + else + return ARM_WAIT_DIV_996M; + } +} + +static void imx6sl_enable_pll_arm(bool enable) +{ + static u32 saved_pll_arm; + u32 val; + + if (enable) { + saved_pll_arm = val = readl_relaxed(anatop_base + PLL_ARM); + val |= BM_PLL_ARM_ENABLE; + val &= ~BM_PLL_ARM_POWERDOWN; + writel_relaxed(val, anatop_base + PLL_ARM); + while (!(__raw_readl(anatop_base + PLL_ARM) & BM_PLL_ARM_LOCK)) + ; + } else { + writel_relaxed(saved_pll_arm, anatop_base + PLL_ARM); + } +} + +void imx6sl_set_wait_clk(bool enter) +{ + static unsigned long saved_arm_div; + int arm_div_for_wait = imx6sl_get_arm_divider_for_wait(); + + /* + * According to hardware design, arm podf change need + * PLL1 clock enabled. + */ + if (arm_div_for_wait == ARM_WAIT_DIV_396M) + imx6sl_enable_pll_arm(true); + + if (enter) { + saved_arm_div = readl_relaxed(ccm_base + CACRR); + writel_relaxed(arm_div_for_wait, ccm_base + CACRR); + } else { + writel_relaxed(saved_arm_div, ccm_base + CACRR); + } + while (__raw_readl(ccm_base + CDHIPR) & BM_CDHIPR_ARM_PODF_BUSY) + ; + + if (arm_div_for_wait == ARM_WAIT_DIV_396M) + imx6sl_enable_pll_arm(false); +} static void __init imx6sl_clocks_init(struct device_node *ccm_node) { struct device_node *np; void __iomem *base; - int irq; int i; + int ret; clks[IMX6SL_CLK_DUMMY] = imx_clk_fixed("dummy", 0); clks[IMX6SL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0); @@ -80,6 +179,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-anatop"); base = of_iomap(np, 0); WARN_ON(!base); + anatop_base = base; /* type name parent base div_mask */ clks[IMX6SL_CLK_PLL1_SYS] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f); @@ -127,6 +227,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) np = ccm_node; base = of_iomap(np, 0); WARN_ON(!base); + ccm_base = base; /* Reuse imx6q pm code */ imx6q_pm_set_ccm_base(base); @@ -258,6 +359,19 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) clk_register_clkdev(clks[IMX6SL_CLK_GPT], "ipg", "imx-gpt.0"); clk_register_clkdev(clks[IMX6SL_CLK_GPT_SERIAL], "per", "imx-gpt.0"); + /* Ensure the AHB clk is at 132MHz. */ + ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000); + if (ret) + pr_warn("%s: failed to set AHB clock rate %d!\n", + __func__, ret); + + /* + * Make sure those always on clocks are enabled to maintain the correct + * usecount and enabling/disabling of parent PLLs. + */ + for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) + clk_prepare_enable(clks[clks_init_on[i]]); + if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { clk_prepare_enable(clks[IMX6SL_CLK_USBPHY1_GATE]); clk_prepare_enable(clks[IMX6SL_CLK_USBPHY2_GATE]); @@ -270,9 +384,6 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node) imx6q_set_lpm(WAIT_CLOCKED); np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpt"); - base = of_iomap(np, 0); - WARN_ON(!base); - irq = irq_of_parse_and_map(np, 0); - mxc_timer_init(base, irq); + mxc_timer_init_dt(np); } CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init); diff --git a/arch/arm/mach-imx/clk-imx6sx.c b/arch/arm/mach-imx/clk-imx6sx.c new file mode 100644 index 000000000000..72f8902235d1 --- /dev/null +++ b/arch/arm/mach-imx/clk-imx6sx.c @@ -0,0 +1,524 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <dt-bindings/clock/imx6sx-clock.h> +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/types.h> + +#include "clk.h" +#include "common.h" + +#define CCDR 0x4 +#define BM_CCM_CCDR_MMDC_CH0_MASK (0x2 << 16) + +static const char *step_sels[] = { "osc", "pll2_pfd2_396m", }; +static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; +static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", }; +static const char *periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll4_audio_div", }; +static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", }; +static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "osc", }; +static const char *periph_sels[] = { "periph_pre", "periph_clk2", }; +static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", }; +static const char *ocram_sels[] = { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", }; +static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", }; +static const char *gpu_axi_sels[] = { "pll2_pfd2_396m", "pll3_pfd0_720m", "pll3_pfd1_540m", "pll2_bus", }; +static const char *gpu_core_sels[] = { "pll3_pfd1_540m", "pll3_pfd0_720m", "pll2_bus", "pll2_pfd2_396m", }; +static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", }; +static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", }; +static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", }; +static const char *ldb_di1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", }; +static const char *pcie_axi_sels[] = { "axi", "ahb", }; +static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll5_video_div", "pll4_audio_div", }; +static const char *qspi1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", }; +static const char *perclk_sels[] = { "ipg", "osc", }; +static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; +static const char *vid_sels[] = { "pll3_pfd1_540m", "pll3_usb_otg", "pll3_pfd3_454m", "pll4_audio_div", "pll5_video_div", }; +static const char *can_sels[] = { "pll3_60m", "osc", "pll3_80m", "dummy", }; +static const char *uart_sels[] = { "pll3_80m", "osc", }; +static const char *qspi2_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", "pll3_pfd3_454m", "dummy", "dummy", "dummy", }; +static const char *enet_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", }; +static const char *enet_sels[] = { "enet_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; +static const char *m4_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "osc", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd3_454m", }; +static const char *m4_sels[] = { "m4_pre_sel", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; +static const char *eim_slow_sels[] = { "ocram", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", }; +static const char *ecspi_sels[] = { "pll3_60m", "osc", }; +static const char *lcdif1_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_540m", }; +static const char *lcdif1_sels[] = { "lcdif1_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; +static const char *lcdif2_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd3_594m", "pll3_pfd1_540m", }; +static const char *lcdif2_sels[] = { "lcdif2_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", }; +static const char *display_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll3_usb_otg", "pll3_pfd1_540m", }; +static const char *csi_sels[] = { "osc", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", }; +static const char *cko1_sels[] = { + "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div", + "dummy", "ocram", "dummy", "pxp_axi", "epdc_axi", "lcdif_pix", + "epdc_pix", "ahb", "ipg", "perclk", "ckil", "pll4_audio_div", +}; +static const char *cko2_sels[] = { + "dummy", "mmdc_p0_fast", "usdhc4", "usdhc1", "dummy", "wrck", + "ecspi_root", "dummy", "usdhc3", "pcie", "arm", "csi_core", + "lcdif_axi", "dummy", "osc", "dummy", "gpu2d_ovg_core", + "usdhc2", "ssi1", "ssi2", "ssi3", "gpu2d_core", "dummy", + "dummy", "dummy", "dummy", "esai_extal", "eim_slow", "uart_serial", + "spdif", "asrc", "dummy", +}; +static const char *cko_sels[] = { "cko1", "cko2", }; +static const char *lvds_sels[] = { + "arm", "pll1_sys", "dummy", "dummy", "dummy", "dummy", "dummy", "pll5_video_div", + "dummy", "dummy", "pcie_ref_125m", "dummy", "usbphy1", "usbphy2", +}; + +static struct clk *clks[IMX6SX_CLK_CLK_END]; +static struct clk_onecell_data clk_data; + +static int const clks_init_on[] __initconst = { + IMX6SX_CLK_AIPS_TZ1, IMX6SX_CLK_AIPS_TZ2, IMX6SX_CLK_AIPS_TZ3, + IMX6SX_CLK_IPMUX1, IMX6SX_CLK_IPMUX2, IMX6SX_CLK_IPMUX3, + IMX6SX_CLK_WAKEUP, IMX6SX_CLK_MMDC_P0_FAST, IMX6SX_CLK_MMDC_P0_IPG, + IMX6SX_CLK_ROM, IMX6SX_CLK_ARM, IMX6SX_CLK_IPG, IMX6SX_CLK_OCRAM, + IMX6SX_CLK_PER2_MAIN, IMX6SX_CLK_PERCLK, IMX6SX_CLK_M4, + IMX6SX_CLK_QSPI1, IMX6SX_CLK_QSPI2, IMX6SX_CLK_UART_IPG, + IMX6SX_CLK_UART_SERIAL, IMX6SX_CLK_I2C3, IMX6SX_CLK_ECSPI5, + IMX6SX_CLK_CAN1_IPG, IMX6SX_CLK_CAN1_SERIAL, IMX6SX_CLK_CAN2_IPG, + IMX6SX_CLK_CAN2_SERIAL, IMX6SX_CLK_CANFD, IMX6SX_CLK_EPIT1, + IMX6SX_CLK_EPIT2, +}; + +static struct clk_div_table clk_enet_ref_table[] = { + { .val = 0, .div = 20, }, + { .val = 1, .div = 10, }, + { .val = 2, .div = 5, }, + { .val = 3, .div = 4, }, + { } +}; + +static struct clk_div_table post_div_table[] = { + { .val = 2, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 0, .div = 4, }, + { } +}; + +static struct clk_div_table video_div_table[] = { + { .val = 0, .div = 1, }, + { .val = 1, .div = 2, }, + { .val = 2, .div = 1, }, + { .val = 3, .div = 4, }, + { } +}; + +static u32 share_count_asrc; +static u32 share_count_audio; +static u32 share_count_esai; + +static void __init imx6sx_clocks_init(struct device_node *ccm_node) +{ + struct device_node *np; + void __iomem *base; + int i; + + clks[IMX6SX_CLK_DUMMY] = imx_clk_fixed("dummy", 0); + + clks[IMX6SX_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil"); + clks[IMX6SX_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc"); + + /* ipp_di clock is external input */ + clks[IMX6SX_CLK_IPP_DI0] = of_clk_get_by_name(ccm_node, "ipp_di0"); + clks[IMX6SX_CLK_IPP_DI1] = of_clk_get_by_name(ccm_node, "ipp_di1"); + + np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-anatop"); + base = of_iomap(np, 0); + WARN_ON(!base); + + /* type name parent_name base div_mask */ + clks[IMX6SX_CLK_PLL1_SYS] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f); + clks[IMX6SX_CLK_PLL2_BUS] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1); + clks[IMX6SX_CLK_PLL3_USB_OTG] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3); + clks[IMX6SX_CLK_PLL4_AUDIO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f); + clks[IMX6SX_CLK_PLL5_VIDEO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f); + clks[IMX6SX_CLK_PLL6_ENET] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3); + clks[IMX6SX_CLK_PLL7_USB_HOST] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host", "osc", base + 0x20, 0x3); + + /* + * Bit 20 is the reserved and read-only bit, we do this only for: + * - Do nothing for usbphy clk_enable/disable + * - Keep refcount when do usbphy clk_enable/disable, in that case, + * the clk framework may need to enable/disable usbphy's parent + */ + clks[IMX6SX_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20); + clks[IMX6SX_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20); + + /* + * usbphy*_gate needs to be on after system boots up, and software + * never needs to control it anymore. + */ + clks[IMX6SX_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6); + clks[IMX6SX_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6); + + /* FIXME 100Mhz is used for pcie ref for all imx6 pcie, excepted imx6q */ + clks[IMX6SX_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 5); + clks[IMX6SX_CLK_PCIE_REF_125M] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19); + + clks[IMX6SX_CLK_LVDS1_OUT] = imx_clk_gate("lvds1_out", "lvds1_sel", base + 0x160, 10); + + clks[IMX6SX_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0, + base + 0xe0, 0, 2, 0, clk_enet_ref_table, + &imx_ccm_lock); + clks[IMX6SX_CLK_ENET2_REF] = clk_register_divider_table(NULL, "enet2_ref", "pll6_enet", 0, + base + 0xe0, 2, 2, 0, clk_enet_ref_table, + &imx_ccm_lock); + clks[IMX6SX_CLK_ENET2_REF_125M] = imx_clk_gate("enet2_ref_125m", "enet2_ref", base + 0xe0, 20); + + clks[IMX6SX_CLK_ENET_PTP_REF] = imx_clk_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20); + clks[IMX6SX_CLK_ENET_PTP] = imx_clk_gate("enet_ptp_25m", "enet_ptp_ref", base + 0xe0, 21); + + /* name parent_name reg idx */ + clks[IMX6SX_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0); + clks[IMX6SX_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1); + clks[IMX6SX_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2); + clks[IMX6SX_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus", base + 0x100, 3); + clks[IMX6SX_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0); + clks[IMX6SX_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1); + clks[IMX6SX_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2); + clks[IMX6SX_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3); + + /* name parent_name mult div */ + clks[IMX6SX_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2); + clks[IMX6SX_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4); + clks[IMX6SX_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); + clks[IMX6SX_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); + clks[IMX6SX_CLK_TWD] = imx_clk_fixed_factor("twd", "arm", 1, 2); + clks[IMX6SX_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); + + clks[IMX6SX_CLK_PLL4_POST_DIV] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", + CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock); + clks[IMX6SX_CLK_PLL4_AUDIO_DIV] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", + CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock); + clks[IMX6SX_CLK_PLL5_POST_DIV] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", + CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock); + clks[IMX6SX_CLK_PLL5_VIDEO_DIV] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", + CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock); + + /* name reg shift width parent_names num_parents */ + clks[IMX6SX_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); + + np = ccm_node; + base = of_iomap(np, 0); + WARN_ON(!base); + + imx6q_pm_set_ccm_base(base); + + /* name reg shift width parent_names num_parents */ + clks[IMX6SX_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels)); + clks[IMX6SX_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels)); + clks[IMX6SX_CLK_OCRAM_SEL] = imx_clk_mux("ocram_sel", base + 0x14, 6, 2, ocram_sels, ARRAY_SIZE(ocram_sels)); + clks[IMX6SX_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels)); + clks[IMX6SX_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels)); + clks[IMX6SX_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)); + clks[IMX6SX_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels)); + clks[IMX6SX_CLK_PCIE_AXI_SEL] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels)); + clks[IMX6SX_CLK_GPU_AXI_SEL] = imx_clk_mux("gpu_axi_sel", base + 0x18, 8, 2, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels)); + clks[IMX6SX_CLK_GPU_CORE_SEL] = imx_clk_mux("gpu_core_sel", base + 0x18, 4, 2, gpu_core_sels, ARRAY_SIZE(gpu_core_sels)); + clks[IMX6SX_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels)); + clks[IMX6SX_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SX_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SX_CLK_USDHC3_SEL] = imx_clk_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SX_CLK_USDHC4_SEL] = imx_clk_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels)); + clks[IMX6SX_CLK_SSI3_SEL] = imx_clk_mux("ssi3_sel", base + 0x1c, 14, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); + clks[IMX6SX_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", base + 0x1c, 12, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); + clks[IMX6SX_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels)); + clks[IMX6SX_CLK_QSPI1_SEL] = imx_clk_mux_flags("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT); + clks[IMX6SX_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels)); + clks[IMX6SX_CLK_VID_SEL] = imx_clk_mux("vid_sel", base + 0x20, 21, 3, vid_sels, ARRAY_SIZE(vid_sels)); + clks[IMX6SX_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels)); + clks[IMX6SX_CLK_CAN_SEL] = imx_clk_mux("can_sel", base + 0x20, 8, 2, can_sels, ARRAY_SIZE(can_sels)); + clks[IMX6SX_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels)); + clks[IMX6SX_CLK_QSPI2_SEL] = imx_clk_mux_flags("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT); + clks[IMX6SX_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels)); + clks[IMX6SX_CLK_AUDIO_SEL] = imx_clk_mux("audio_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels)); + clks[IMX6SX_CLK_ENET_PRE_SEL] = imx_clk_mux("enet_pre_sel", base + 0x34, 15, 3, enet_pre_sels, ARRAY_SIZE(enet_pre_sels)); + clks[IMX6SX_CLK_ENET_SEL] = imx_clk_mux("enet_sel", base + 0x34, 9, 3, enet_sels, ARRAY_SIZE(enet_sels)); + clks[IMX6SX_CLK_M4_PRE_SEL] = imx_clk_mux("m4_pre_sel", base + 0x34, 6, 3, m4_pre_sels, ARRAY_SIZE(m4_pre_sels)); + clks[IMX6SX_CLK_M4_SEL] = imx_clk_mux("m4_sel", base + 0x34, 0, 3, m4_sels, ARRAY_SIZE(m4_sels)); + clks[IMX6SX_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); + clks[IMX6SX_CLK_LCDIF2_PRE_SEL] = imx_clk_mux("lcdif2_pre_sel", base + 0x38, 6, 3, lcdif2_pre_sels, ARRAY_SIZE(lcdif2_pre_sels)); + clks[IMX6SX_CLK_LCDIF2_SEL] = imx_clk_mux("lcdif2_sel", base + 0x38, 0, 3, lcdif2_sels, ARRAY_SIZE(lcdif2_sels)); + clks[IMX6SX_CLK_DISPLAY_SEL] = imx_clk_mux("display_sel", base + 0x3c, 14, 2, display_sels, ARRAY_SIZE(display_sels)); + clks[IMX6SX_CLK_CSI_SEL] = imx_clk_mux("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels)); + clks[IMX6SX_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels)); + clks[IMX6SX_CLK_CKO2_SEL] = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels)); + clks[IMX6SX_CLK_CKO] = imx_clk_mux("cko", base + 0x60, 8, 1, cko_sels, ARRAY_SIZE(cko_sels)); + + clks[IMX6SX_CLK_LDB_DI1_DIV_SEL] = imx_clk_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT); + clks[IMX6SX_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT); + clks[IMX6SX_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di1_sels, ARRAY_SIZE(ldb_di1_sels), CLK_SET_RATE_PARENT); + clks[IMX6SX_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels), CLK_SET_RATE_PARENT); + clks[IMX6SX_CLK_LCDIF1_PRE_SEL] = imx_clk_mux_flags("lcdif1_pre_sel", base + 0x38, 15, 3, lcdif1_pre_sels, ARRAY_SIZE(lcdif1_pre_sels), CLK_SET_RATE_PARENT); + clks[IMX6SX_CLK_LCDIF1_SEL] = imx_clk_mux_flags("lcdif1_sel", base + 0x38, 9, 3, lcdif1_sels, ARRAY_SIZE(lcdif1_sels), CLK_SET_RATE_PARENT); + + /* name parent_name reg shift width */ + clks[IMX6SX_CLK_PERIPH_CLK2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3); + clks[IMX6SX_CLK_PERIPH2_CLK2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3); + clks[IMX6SX_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2); + clks[IMX6SX_CLK_GPU_CORE_PODF] = imx_clk_divider("gpu_core_podf", "gpu_core_sel", base + 0x18, 29, 3); + clks[IMX6SX_CLK_GPU_AXI_PODF] = imx_clk_divider("gpu_axi_podf", "gpu_axi_sel", base + 0x18, 26, 3); + clks[IMX6SX_CLK_LCDIF1_PODF] = imx_clk_divider("lcdif1_podf", "lcdif1_pred", base + 0x18, 23, 3); + clks[IMX6SX_CLK_QSPI1_PODF] = imx_clk_divider("qspi1_podf", "qspi1_sel", base + 0x1c, 26, 3); + clks[IMX6SX_CLK_EIM_SLOW_PODF] = imx_clk_divider("eim_slow_podf", "eim_slow_sel", base + 0x1c, 23, 3); + clks[IMX6SX_CLK_LCDIF2_PODF] = imx_clk_divider("lcdif2_podf", "lcdif2_pred", base + 0x1c, 20, 3); + clks[IMX6SX_CLK_PERCLK] = imx_clk_divider("perclk", "perclk_sel", base + 0x1c, 0, 6); + clks[IMX6SX_CLK_VID_PODF] = imx_clk_divider("vid_podf", "vid_sel", base + 0x20, 24, 2); + clks[IMX6SX_CLK_CAN_PODF] = imx_clk_divider("can_podf", "can_sel", base + 0x20, 2, 6); + clks[IMX6SX_CLK_USDHC4_PODF] = imx_clk_divider("usdhc4_podf", "usdhc4_sel", base + 0x24, 22, 3); + clks[IMX6SX_CLK_USDHC3_PODF] = imx_clk_divider("usdhc3_podf", "usdhc3_sel", base + 0x24, 19, 3); + clks[IMX6SX_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3); + clks[IMX6SX_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3); + clks[IMX6SX_CLK_UART_PODF] = imx_clk_divider("uart_podf", "uart_sel", base + 0x24, 0, 6); + clks[IMX6SX_CLK_ESAI_PRED] = imx_clk_divider("esai_pred", "esai_sel", base + 0x28, 9, 3); + clks[IMX6SX_CLK_ESAI_PODF] = imx_clk_divider("esai_podf", "esai_pred", base + 0x28, 25, 3); + clks[IMX6SX_CLK_SSI3_PRED] = imx_clk_divider("ssi3_pred", "ssi3_sel", base + 0x28, 22, 3); + clks[IMX6SX_CLK_SSI3_PODF] = imx_clk_divider("ssi3_podf", "ssi3_pred", base + 0x28, 16, 6); + clks[IMX6SX_CLK_SSI1_PRED] = imx_clk_divider("ssi1_pred", "ssi1_sel", base + 0x28, 6, 3); + clks[IMX6SX_CLK_SSI1_PODF] = imx_clk_divider("ssi1_podf", "ssi1_pred", base + 0x28, 0, 6); + clks[IMX6SX_CLK_QSPI2_PRED] = imx_clk_divider("qspi2_pred", "qspi2_sel", base + 0x2c, 18, 3); + clks[IMX6SX_CLK_QSPI2_PODF] = imx_clk_divider("qspi2_podf", "qspi2_pred", base + 0x2c, 21, 6); + clks[IMX6SX_CLK_SSI2_PRED] = imx_clk_divider("ssi2_pred", "ssi2_sel", base + 0x2c, 6, 3); + clks[IMX6SX_CLK_SSI2_PODF] = imx_clk_divider("ssi2_podf", "ssi2_pred", base + 0x2c, 0, 6); + clks[IMX6SX_CLK_SPDIF_PRED] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3); + clks[IMX6SX_CLK_SPDIF_PODF] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3); + clks[IMX6SX_CLK_AUDIO_PRED] = imx_clk_divider("audio_pred", "audio_sel", base + 0x30, 12, 3); + clks[IMX6SX_CLK_AUDIO_PODF] = imx_clk_divider("audio_podf", "audio_pred", base + 0x30, 9, 3); + clks[IMX6SX_CLK_ENET_PODF] = imx_clk_divider("enet_podf", "enet_pre_sel", base + 0x34, 12, 3); + clks[IMX6SX_CLK_M4_PODF] = imx_clk_divider("m4_podf", "m4_sel", base + 0x34, 3, 3); + clks[IMX6SX_CLK_ECSPI_PODF] = imx_clk_divider("ecspi_podf", "ecspi_sel", base + 0x38, 19, 6); + clks[IMX6SX_CLK_LCDIF1_PRED] = imx_clk_divider("lcdif1_pred", "lcdif1_pre_sel", base + 0x38, 12, 3); + clks[IMX6SX_CLK_LCDIF2_PRED] = imx_clk_divider("lcdif2_pred", "lcdif2_pre_sel", base + 0x38, 3, 3); + clks[IMX6SX_CLK_DISPLAY_PODF] = imx_clk_divider("display_podf", "display_sel", base + 0x3c, 16, 3); + clks[IMX6SX_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3); + clks[IMX6SX_CLK_CKO1_PODF] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3); + clks[IMX6SX_CLK_CKO2_PODF] = imx_clk_divider("cko2_podf", "cko2_sel", base + 0x60, 21, 3); + + clks[IMX6SX_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); + clks[IMX6SX_CLK_LDB_DI0_DIV_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7); + clks[IMX6SX_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); + clks[IMX6SX_CLK_LDB_DI1_DIV_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1_sel", 1, 7); + + /* name reg shift width busy: reg, shift parent_names num_parents */ + clks[IMX6SX_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels)); + clks[IMX6SX_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels)); + /* name parent_name reg shift width busy: reg, shift */ + clks[IMX6SX_CLK_OCRAM_PODF] = imx_clk_busy_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3, base + 0x48, 0); + clks[IMX6SX_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1); + clks[IMX6SX_CLK_MMDC_PODF] = imx_clk_busy_divider("mmdc_podf", "periph2", base + 0x14, 3, 3, base + 0x48, 2); + clks[IMX6SX_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16); + + /* name parent_name reg shift */ + /* CCGR0 */ + clks[IMX6SX_CLK_AIPS_TZ1] = imx_clk_gate2("aips_tz1", "ahb", base + 0x68, 0); + clks[IMX6SX_CLK_AIPS_TZ2] = imx_clk_gate2("aips_tz2", "ahb", base + 0x68, 2); + clks[IMX6SX_CLK_APBH_DMA] = imx_clk_gate2("apbh_dma", "usdhc3", base + 0x68, 4); + clks[IMX6SX_CLK_ASRC_MEM] = imx_clk_gate2_shared("asrc_mem", "ahb", base + 0x68, 6, &share_count_asrc); + clks[IMX6SX_CLK_ASRC_IPG] = imx_clk_gate2_shared("asrc_ipg", "ahb", base + 0x68, 6, &share_count_asrc); + clks[IMX6SX_CLK_CAAM_MEM] = imx_clk_gate2("caam_mem", "ahb", base + 0x68, 8); + clks[IMX6SX_CLK_CAAM_ACLK] = imx_clk_gate2("caam_aclk", "ahb", base + 0x68, 10); + clks[IMX6SX_CLK_CAAM_IPG] = imx_clk_gate2("caam_ipg", "ipg", base + 0x68, 12); + clks[IMX6SX_CLK_CAN1_IPG] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14); + clks[IMX6SX_CLK_CAN1_SERIAL] = imx_clk_gate2("can1_serial", "can_podf", base + 0x68, 16); + clks[IMX6SX_CLK_CAN2_IPG] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18); + clks[IMX6SX_CLK_CAN2_SERIAL] = imx_clk_gate2("can2_serial", "can_podf", base + 0x68, 20); + clks[IMX6SX_CLK_DCIC1] = imx_clk_gate2("dcic1", "display_podf", base + 0x68, 24); + clks[IMX6SX_CLK_DCIC2] = imx_clk_gate2("dcic2", "display_podf", base + 0x68, 26); + clks[IMX6SX_CLK_AIPS_TZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30); + + /* CCGR1 */ + clks[IMX6SX_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_podf", base + 0x6c, 0); + clks[IMX6SX_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_podf", base + 0x6c, 2); + clks[IMX6SX_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_podf", base + 0x6c, 4); + clks[IMX6SX_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_podf", base + 0x6c, 6); + clks[IMX6SX_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_podf", base + 0x6c, 8); + clks[IMX6SX_CLK_EPIT1] = imx_clk_gate2("epit1", "perclk", base + 0x6c, 12); + clks[IMX6SX_CLK_EPIT2] = imx_clk_gate2("epit2", "perclk", base + 0x6c, 14); + clks[IMX6SX_CLK_ESAI_EXTAL] = imx_clk_gate2_shared("esai_extal", "esai_podf", base + 0x6c, 16, &share_count_esai); + clks[IMX6SX_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ahb", base + 0x6c, 16, &share_count_esai); + clks[IMX6SX_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x6c, 16, &share_count_esai); + clks[IMX6SX_CLK_WAKEUP] = imx_clk_gate2("wakeup", "ipg", base + 0x6c, 18); + clks[IMX6SX_CLK_GPT_BUS] = imx_clk_gate2("gpt_bus", "perclk", base + 0x6c, 20); + clks[IMX6SX_CLK_GPT_SERIAL] = imx_clk_gate2("gpt_serial", "perclk", base + 0x6c, 22); + clks[IMX6SX_CLK_GPU] = imx_clk_gate2("gpu", "gpu_core_podf", base + 0x6c, 26); + clks[IMX6SX_CLK_CANFD] = imx_clk_gate2("canfd", "can_podf", base + 0x6c, 30); + + /* CCGR2 */ + clks[IMX6SX_CLK_CSI] = imx_clk_gate2("csi", "csi_podf", base + 0x70, 2); + clks[IMX6SX_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6); + clks[IMX6SX_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8); + clks[IMX6SX_CLK_I2C3] = imx_clk_gate2("i2c3", "perclk", base + 0x70, 10); + clks[IMX6SX_CLK_OCOTP] = imx_clk_gate2("ocotp", "ipg", base + 0x70, 12); + clks[IMX6SX_CLK_IOMUXC] = imx_clk_gate2("iomuxc", "lcdif1_podf", base + 0x70, 14); + clks[IMX6SX_CLK_IPMUX1] = imx_clk_gate2("ipmux1", "ahb", base + 0x70, 16); + clks[IMX6SX_CLK_IPMUX2] = imx_clk_gate2("ipmux2", "ahb", base + 0x70, 18); + clks[IMX6SX_CLK_IPMUX3] = imx_clk_gate2("ipmux3", "ahb", base + 0x70, 20); + clks[IMX6SX_CLK_TZASC1] = imx_clk_gate2("tzasc1", "mmdc_podf", base + 0x70, 22); + clks[IMX6SX_CLK_LCDIF_APB] = imx_clk_gate2("lcdif_apb", "display_podf", base + 0x70, 28); + clks[IMX6SX_CLK_PXP_AXI] = imx_clk_gate2("pxp_axi", "display_podf", base + 0x70, 30); + + /* CCGR3 */ + clks[IMX6SX_CLK_M4] = imx_clk_gate2("m4", "m4_podf", base + 0x74, 2); + clks[IMX6SX_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x74, 4); + clks[IMX6SX_CLK_ENET_AHB] = imx_clk_gate2("enet_ahb", "enet_sel", base + 0x74, 4); + clks[IMX6SX_CLK_DISPLAY_AXI] = imx_clk_gate2("display_axi", "display_podf", base + 0x74, 6); + clks[IMX6SX_CLK_LCDIF2_PIX] = imx_clk_gate2("lcdif2_pix", "lcdif2_sel", base + 0x74, 8); + clks[IMX6SX_CLK_LCDIF1_PIX] = imx_clk_gate2("lcdif1_pix", "lcdif1_sel", base + 0x74, 10); + clks[IMX6SX_CLK_LDB_DI0] = imx_clk_gate2("ldb_di0", "ldb_di0_div_sel", base + 0x74, 12); + clks[IMX6SX_CLK_QSPI1] = imx_clk_gate2("qspi1", "qspi1_podf", base + 0x74, 14); + clks[IMX6SX_CLK_MLB] = imx_clk_gate2("mlb", "ahb", base + 0x74, 18); + clks[IMX6SX_CLK_MMDC_P0_FAST] = imx_clk_gate2("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20); + clks[IMX6SX_CLK_MMDC_P0_IPG] = imx_clk_gate2("mmdc_p0_ipg", "ipg", base + 0x74, 24); + clks[IMX6SX_CLK_OCRAM] = imx_clk_gate2("ocram", "ocram_podf", base + 0x74, 28); + + /* CCGR4 */ + clks[IMX6SX_CLK_PCIE_AXI] = imx_clk_gate2("pcie_axi", "display_podf", base + 0x78, 0); + clks[IMX6SX_CLK_QSPI2] = imx_clk_gate2("qspi2", "qspi2_podf", base + 0x78, 10); + clks[IMX6SX_CLK_PER1_BCH] = imx_clk_gate2("per1_bch", "usdhc3", base + 0x78, 12); + clks[IMX6SX_CLK_PER2_MAIN] = imx_clk_gate2("per2_main", "ahb", base + 0x78, 14); + clks[IMX6SX_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16); + clks[IMX6SX_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18); + clks[IMX6SX_CLK_PWM3] = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20); + clks[IMX6SX_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22); + clks[IMX6SX_CLK_GPMI_BCH_APB] = imx_clk_gate2("gpmi_bch_apb", "usdhc3", base + 0x78, 24); + clks[IMX6SX_CLK_GPMI_BCH] = imx_clk_gate2("gpmi_bch", "usdhc4", base + 0x78, 26); + clks[IMX6SX_CLK_GPMI_IO] = imx_clk_gate2("gpmi_io", "qspi2_podf", base + 0x78, 28); + clks[IMX6SX_CLK_GPMI_APB] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30); + + /* CCGR5 */ + clks[IMX6SX_CLK_ROM] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0); + clks[IMX6SX_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6); + clks[IMX6SX_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); + clks[IMX6SX_CLK_AUDIO] = imx_clk_gate2_shared("audio", "audio_podf", base + 0x7c, 14, &share_count_audio); + clks[IMX6SX_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif_podf", base + 0x7c, 14, &share_count_audio); + clks[IMX6SX_CLK_SSI1_IPG] = imx_clk_gate2("ssi1_ipg", "ipg", base + 0x7c, 18); + clks[IMX6SX_CLK_SSI2_IPG] = imx_clk_gate2("ssi2_ipg", "ipg", base + 0x7c, 20); + clks[IMX6SX_CLK_SSI3_IPG] = imx_clk_gate2("ssi3_ipg", "ipg", base + 0x7c, 22); + clks[IMX6SX_CLK_SSI1] = imx_clk_gate2("ssi1", "ssi1_podf", base + 0x7c, 18); + clks[IMX6SX_CLK_SSI2] = imx_clk_gate2("ssi2", "ssi2_podf", base + 0x7c, 20); + clks[IMX6SX_CLK_SSI3] = imx_clk_gate2("ssi3", "ssi3_podf", base + 0x7c, 22); + clks[IMX6SX_CLK_UART_IPG] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24); + clks[IMX6SX_CLK_UART_SERIAL] = imx_clk_gate2("uart_serial", "uart_podf", base + 0x7c, 26); + clks[IMX6SX_CLK_SAI1_IPG] = imx_clk_gate2("sai1_ipg", "ipg", base + 0x7c, 28); + clks[IMX6SX_CLK_SAI2_IPG] = imx_clk_gate2("sai2_ipg", "ipg", base + 0x7c, 30); + clks[IMX6SX_CLK_SAI1] = imx_clk_gate2("sai1", "ssi1_podf", base + 0x7c, 28); + clks[IMX6SX_CLK_SAI2] = imx_clk_gate2("sai2", "ssi2_podf", base + 0x7c, 30); + + /* CCGR6 */ + clks[IMX6SX_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); + clks[IMX6SX_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2); + clks[IMX6SX_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4); + clks[IMX6SX_CLK_USDHC3] = imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6); + clks[IMX6SX_CLK_USDHC4] = imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8); + clks[IMX6SX_CLK_EIM_SLOW] = imx_clk_gate2("eim_slow", "eim_slow_podf", base + 0x80, 10); + clks[IMX6SX_CLK_PWM8] = imx_clk_gate2("pwm8", "perclk", base + 0x80, 16); + clks[IMX6SX_CLK_VADC] = imx_clk_gate2("vadc", "vid_podf", base + 0x80, 20); + clks[IMX6SX_CLK_GIS] = imx_clk_gate2("gis", "display_podf", base + 0x80, 22); + clks[IMX6SX_CLK_I2C4] = imx_clk_gate2("i2c4", "perclk", base + 0x80, 24); + clks[IMX6SX_CLK_PWM5] = imx_clk_gate2("pwm5", "perclk", base + 0x80, 26); + clks[IMX6SX_CLK_PWM6] = imx_clk_gate2("pwm6", "perclk", base + 0x80, 28); + clks[IMX6SX_CLK_PWM7] = imx_clk_gate2("pwm7", "perclk", base + 0x80, 30); + + clks[IMX6SX_CLK_CKO1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7); + clks[IMX6SX_CLK_CKO2] = imx_clk_gate("cko2", "cko2_podf", base + 0x60, 24); + + /* mask handshake of mmdc */ + writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR); + + for (i = 0; i < ARRAY_SIZE(clks); i++) + if (IS_ERR(clks[i])) + pr_err("i.MX6sx clk %d: register failed with %ld\n", i, PTR_ERR(clks[i])); + + clk_data.clks = clks; + clk_data.clk_num = ARRAY_SIZE(clks); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + + clk_register_clkdev(clks[IMX6SX_CLK_GPT_BUS], "ipg", "imx-gpt.0"); + clk_register_clkdev(clks[IMX6SX_CLK_GPT_SERIAL], "per", "imx-gpt.0"); + + for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) + clk_prepare_enable(clks[clks_init_on[i]]); + + if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { + clk_prepare_enable(clks[IMX6SX_CLK_USBPHY1_GATE]); + clk_prepare_enable(clks[IMX6SX_CLK_USBPHY2_GATE]); + } + + /* Set the default 132MHz for EIM module */ + clk_set_parent(clks[IMX6SX_CLK_EIM_SLOW_SEL], clks[IMX6SX_CLK_PLL2_PFD2]); + clk_set_rate(clks[IMX6SX_CLK_EIM_SLOW], 132000000); + + /* set parent clock for LCDIF1 pixel clock */ + clk_set_parent(clks[IMX6SX_CLK_LCDIF1_PRE_SEL], clks[IMX6SX_CLK_PLL5_VIDEO_DIV]); + clk_set_parent(clks[IMX6SX_CLK_LCDIF1_SEL], clks[IMX6SX_CLK_LCDIF1_PODF]); + + /* Set the parent clks of PCIe lvds1 and pcie_axi to be pcie ref, axi */ + if (clk_set_parent(clks[IMX6SX_CLK_LVDS1_SEL], clks[IMX6SX_CLK_PCIE_REF_125M])) + pr_err("Failed to set pcie bus parent clk.\n"); + if (clk_set_parent(clks[IMX6SX_CLK_PCIE_AXI_SEL], clks[IMX6SX_CLK_AXI])) + pr_err("Failed to set pcie parent clk.\n"); + + /* + * Init enet system AHB clock, set to 200Mhz + * pll2_pfd2_396m-> ENET_PODF-> ENET_AHB + */ + clk_set_parent(clks[IMX6SX_CLK_ENET_PRE_SEL], clks[IMX6SX_CLK_PLL2_PFD2]); + clk_set_parent(clks[IMX6SX_CLK_ENET_SEL], clks[IMX6SX_CLK_ENET_PODF]); + clk_set_rate(clks[IMX6SX_CLK_ENET_PODF], 200000000); + clk_set_rate(clks[IMX6SX_CLK_ENET_REF], 125000000); + clk_set_rate(clks[IMX6SX_CLK_ENET2_REF], 125000000); + + /* Audio clocks */ + clk_set_rate(clks[IMX6SX_CLK_PLL4_AUDIO_DIV], 393216000); + + clk_set_parent(clks[IMX6SX_CLK_SPDIF_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]); + clk_set_rate(clks[IMX6SX_CLK_SPDIF_PODF], 98304000); + + clk_set_parent(clks[IMX6SX_CLK_AUDIO_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]); + clk_set_rate(clks[IMX6SX_CLK_AUDIO_PODF], 24000000); + + clk_set_parent(clks[IMX6SX_CLK_SSI1_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]); + clk_set_parent(clks[IMX6SX_CLK_SSI2_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]); + clk_set_parent(clks[IMX6SX_CLK_SSI3_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]); + clk_set_rate(clks[IMX6SX_CLK_SSI1_PODF], 24576000); + clk_set_rate(clks[IMX6SX_CLK_SSI2_PODF], 24576000); + clk_set_rate(clks[IMX6SX_CLK_SSI3_PODF], 24576000); + + clk_set_parent(clks[IMX6SX_CLK_ESAI_SEL], clks[IMX6SX_CLK_PLL4_AUDIO_DIV]); + clk_set_rate(clks[IMX6SX_CLK_ESAI_PODF], 24576000); + + /* Set parent clock for vadc */ + clk_set_parent(clks[IMX6SX_CLK_VID_SEL], clks[IMX6SX_CLK_PLL3_USB_OTG]); + + /* default parent of can_sel clock is invalid, manually set it here */ + clk_set_parent(clks[IMX6SX_CLK_CAN_SEL], clks[IMX6SX_CLK_PLL3_60M]); + + /* Update gpu clock from default 528M to 720M */ + clk_set_parent(clks[IMX6SX_CLK_GPU_CORE_SEL], clks[IMX6SX_CLK_PLL3_PFD0]); + clk_set_parent(clks[IMX6SX_CLK_GPU_AXI_SEL], clks[IMX6SX_CLK_PLL3_PFD0]); + + /* Set initial power mode */ + imx6q_set_lpm(WAIT_CLOCKED); + + np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-gpt"); + mxc_timer_init_dt(np); +} +CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init); diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c index ecd66d8e20b6..22dc3ee21fd4 100644 --- a/arch/arm/mach-imx/clk-vf610.c +++ b/arch/arm/mach-imx/clk-vf610.c @@ -63,25 +63,25 @@ static void __iomem *anatop_base; static void __iomem *ccm_base; /* sources for multiplexer clocks, this is used multiple times */ -static const char const *fast_sels[] = { "firc", "fxosc", }; -static const char const *slow_sels[] = { "sirc_32k", "sxosc", }; -static const char const *pll1_sels[] = { "pll1_main", "pll1_pfd1", "pll1_pfd2", "pll1_pfd3", "pll1_pfd4", }; -static const char const *pll2_sels[] = { "pll2_main", "pll2_pfd1", "pll2_pfd2", "pll2_pfd3", "pll2_pfd4", }; -static const char const *sys_sels[] = { "fast_clk_sel", "slow_clk_sel", "pll2_pfd_sel", "pll2_main", "pll1_pfd_sel", "pll3_main", }; -static const char const *ddr_sels[] = { "pll2_pfd2", "sys_sel", }; -static const char const *rmii_sels[] = { "enet_ext", "audio_ext", "enet_50m", "enet_25m", }; -static const char const *enet_ts_sels[] = { "enet_ext", "fxosc", "audio_ext", "usb", "enet_ts", "enet_25m", "enet_50m", }; -static const char const *esai_sels[] = { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", }; -static const char const *sai_sels[] = { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", }; -static const char const *nfc_sels[] = { "platform_bus", "pll1_pfd1", "pll3_pfd1", "pll3_pfd3", }; -static const char const *qspi_sels[] = { "pll3_main", "pll3_pfd4", "pll2_pfd4", "pll1_pfd4", }; -static const char const *esdhc_sels[] = { "pll3_main", "pll3_pfd3", "pll1_pfd3", "platform_bus", }; -static const char const *dcu_sels[] = { "pll1_pfd2", "pll3_main", }; -static const char const *gpu_sels[] = { "pll2_pfd2", "pll3_pfd2", }; -static const char const *vadc_sels[] = { "pll6_main_div", "pll3_main_div", "pll3_main", }; +static const char *fast_sels[] = { "firc", "fxosc", }; +static const char *slow_sels[] = { "sirc_32k", "sxosc", }; +static const char *pll1_sels[] = { "pll1_main", "pll1_pfd1", "pll1_pfd2", "pll1_pfd3", "pll1_pfd4", }; +static const char *pll2_sels[] = { "pll2_main", "pll2_pfd1", "pll2_pfd2", "pll2_pfd3", "pll2_pfd4", }; +static const char *sys_sels[] = { "fast_clk_sel", "slow_clk_sel", "pll2_pfd_sel", "pll2_main", "pll1_pfd_sel", "pll3_main", }; +static const char *ddr_sels[] = { "pll2_pfd2", "sys_sel", }; +static const char *rmii_sels[] = { "enet_ext", "audio_ext", "enet_50m", "enet_25m", }; +static const char *enet_ts_sels[] = { "enet_ext", "fxosc", "audio_ext", "usb", "enet_ts", "enet_25m", "enet_50m", }; +static const char *esai_sels[] = { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", }; +static const char *sai_sels[] = { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", }; +static const char *nfc_sels[] = { "platform_bus", "pll1_pfd1", "pll3_pfd1", "pll3_pfd3", }; +static const char *qspi_sels[] = { "pll3_main", "pll3_pfd4", "pll2_pfd4", "pll1_pfd4", }; +static const char *esdhc_sels[] = { "pll3_main", "pll3_pfd3", "pll1_pfd3", "platform_bus", }; +static const char *dcu_sels[] = { "pll1_pfd2", "pll3_main", }; +static const char *gpu_sels[] = { "pll2_pfd2", "pll3_pfd2", }; +static const char *vadc_sels[] = { "pll6_main_div", "pll3_main_div", "pll3_main", }; /* FTM counter clock source, not module clock */ -static const char const *ftm_ext_sels[] = {"sirc_128k", "sxosc", "fxosc_half", "audio_ext", }; -static const char const *ftm_fix_sels[] = { "sxosc", "ipg_bus", }; +static const char *ftm_ext_sels[] = {"sirc_128k", "sxosc", "fxosc_half", "audio_ext", }; +static const char *ftm_fix_sels[] = { "sxosc", "ipg_bus", }; static struct clk_div_table pll4_main_div_table[] = { { .val = 0, .div = 1 }, diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 048c5ad8a80b..e29f6ebe9f39 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -28,7 +28,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, struct clk *clk_register_gate2(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx, - u8 clk_gate_flags, spinlock_t *lock); + u8 clk_gate_flags, spinlock_t *lock, + unsigned int *share_count); struct clk * imx_obtain_fixed_clock( const char *name, unsigned long rate); @@ -37,7 +38,15 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent, void __iomem *reg, u8 shift) { return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, - shift, 0, &imx_ccm_lock); + shift, 0, &imx_ccm_lock, NULL); +} + +static inline struct clk *imx_clk_gate2_shared(const char *name, + const char *parent, void __iomem *reg, u8 shift, + unsigned int *share_count) +{ + return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg, + shift, 0, &imx_ccm_lock, share_count); } struct clk *imx_clk_pfd(const char *name, const char *parent_name, diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index baf439dc22d8..9ab785ce13e8 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -17,6 +17,7 @@ struct irq_data; struct platform_device; struct pt_regs; struct clk; +struct device_node; enum mxc_cpu_pwr_mode; void mx1_map_io(void); @@ -56,6 +57,7 @@ void imx51_init_late(void); void imx53_init_late(void); void epit_timer_init(void __iomem *base, int irq); void mxc_timer_init(void __iomem *, int); +void mxc_timer_init_dt(struct device_node *); int mx1_clocks_init(unsigned long fref); int mx21_clocks_init(unsigned long lref, unsigned long fref); int mx25_clocks_init(void); @@ -99,24 +101,10 @@ enum mx3_cpu_pwr_mode { void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode); void imx_print_silicon_rev(const char *cpu, int srev); -void avic_handle_irq(struct pt_regs *); -void tzic_handle_irq(struct pt_regs *); - -#define imx1_handle_irq avic_handle_irq -#define imx21_handle_irq avic_handle_irq -#define imx25_handle_irq avic_handle_irq -#define imx27_handle_irq avic_handle_irq -#define imx31_handle_irq avic_handle_irq -#define imx35_handle_irq avic_handle_irq -#define imx50_handle_irq tzic_handle_irq -#define imx51_handle_irq tzic_handle_irq -#define imx53_handle_irq tzic_handle_irq - void imx_enable_cpu(int cpu, bool enable); void imx_set_cpu_jump(int cpu, void *jump_addr); u32 imx_get_cpu_arg(int cpu); void imx_set_cpu_arg(int cpu, u32 arg); -void v7_cpu_resume(void); #ifdef CONFIG_SMP void v7_secondary_startup(void); void imx_scu_map_io(void); @@ -139,13 +127,25 @@ void imx_anatop_init(void); void imx_anatop_pre_suspend(void); void imx_anatop_post_resume(void); int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); -void imx6q_set_chicken_bit(void); +void imx6q_set_int_mem_clk_lpm(void); +void imx6sl_set_wait_clk(bool enter); void imx_cpu_die(unsigned int cpu); int imx_cpu_kill(unsigned int cpu); +#ifdef CONFIG_SUSPEND +void v7_cpu_resume(void); +void imx6_suspend(void __iomem *ocram_vbase); +#else +static inline void v7_cpu_resume(void) {} +static inline void imx6_suspend(void __iomem *ocram_vbase) {} +#endif + void imx6q_pm_init(void); +void imx6dl_pm_init(void); +void imx6sl_pm_init(void); void imx6q_pm_set_ccm_base(void __iomem *base); + #ifdef CONFIG_PM void imx5_pm_init(void); #else diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c index ba3b498a67ec..bbe8ff1f0412 100644 --- a/arch/arm/mach-imx/cpu.c +++ b/arch/arm/mach-imx/cpu.c @@ -111,6 +111,9 @@ struct device * __init imx_soc_device_init(void) case MXC_CPU_IMX6DL: soc_id = "i.MX6DL"; break; + case MXC_CPU_IMX6SX: + soc_id = "i.MX6SX"; + break; case MXC_CPU_IMX6Q: soc_id = "i.MX6Q"; break; diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c index 23ddfb693b2d..6bcae0479049 100644 --- a/arch/arm/mach-imx/cpuidle-imx6q.c +++ b/arch/arm/mach-imx/cpuidle-imx6q.c @@ -68,8 +68,8 @@ int __init imx6q_cpuidle_init(void) /* Need to enable SCU standby for entering WAIT modes */ imx_scu_standby_enable(); - /* Set chicken bit to get a reliable WAIT mode support */ - imx6q_set_chicken_bit(); + /* Set INT_MEM_CLK_LPM bit to get a reliable WAIT mode support */ + imx6q_set_int_mem_clk_lpm(); return cpuidle_register(&imx6q_cpuidle_driver, NULL); } diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c new file mode 100644 index 000000000000..d4b6b8171fa9 --- /dev/null +++ b/arch/arm/mach-imx/cpuidle-imx6sl.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/cpuidle.h> +#include <linux/module.h> +#include <asm/cpuidle.h> +#include <asm/proc-fns.h> + +#include "common.h" +#include "cpuidle.h" + +static int imx6sl_enter_wait(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + imx6q_set_lpm(WAIT_UNCLOCKED); + /* + * Software workaround for ERR005311, see function + * description for details. + */ + imx6sl_set_wait_clk(true); + cpu_do_idle(); + imx6sl_set_wait_clk(false); + imx6q_set_lpm(WAIT_CLOCKED); + + return index; +} + +static struct cpuidle_driver imx6sl_cpuidle_driver = { + .name = "imx6sl_cpuidle", + .owner = THIS_MODULE, + .states = { + /* WFI */ + ARM_CPUIDLE_WFI_STATE, + /* WAIT */ + { + .exit_latency = 50, + .target_residency = 75, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_TIMER_STOP, + .enter = imx6sl_enter_wait, + .name = "WAIT", + .desc = "Clock off", + }, + }, + .state_count = 2, + .safe_state_index = 0, +}; + +int __init imx6sl_cpuidle_init(void) +{ + return cpuidle_register(&imx6sl_cpuidle_driver, NULL); +} diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h index 786f98ecc145..24e33670417c 100644 --- a/arch/arm/mach-imx/cpuidle.h +++ b/arch/arm/mach-imx/cpuidle.h @@ -13,6 +13,7 @@ #ifdef CONFIG_CPU_IDLE extern int imx5_cpuidle_init(void); extern int imx6q_cpuidle_init(void); +extern int imx6sl_cpuidle_init(void); #else static inline int imx5_cpuidle_init(void) { @@ -22,4 +23,8 @@ static inline int imx6q_cpuidle_init(void) { return 0; } +static inline int imx6sl_cpuidle_init(void) +{ + return 0; +} #endif diff --git a/arch/arm/mach-imx/devices-imx25.h b/arch/arm/mach-imx/devices-imx25.h index 769563fdeaa0..61a114cddc39 100644 --- a/arch/arm/mach-imx/devices-imx25.h +++ b/arch/arm/mach-imx/devices-imx25.h @@ -83,7 +83,3 @@ extern const struct imx_spi_imx_data imx25_cspi_data[]; #define imx25_add_spi_imx0(pdata) imx25_add_spi_imx(0, pdata) #define imx25_add_spi_imx1(pdata) imx25_add_spi_imx(1, pdata) #define imx25_add_spi_imx2(pdata) imx25_add_spi_imx(2, pdata) - -extern struct imx_mxc_pwm_data imx25_mxc_pwm_data[]; -#define imx25_add_mxc_pwm(id) \ - imx_add_mxc_pwm(&imx25_mxc_pwm_data[id]) diff --git a/arch/arm/mach-imx/devices-imx51.h b/arch/arm/mach-imx/devices-imx51.h index deee5baee88c..26389f35a2b2 100644 --- a/arch/arm/mach-imx/devices-imx51.h +++ b/arch/arm/mach-imx/devices-imx51.h @@ -57,10 +57,6 @@ extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[]; #define imx51_add_imx2_wdt(id) \ imx_add_imx2_wdt(&imx51_imx2_wdt_data[id]) -extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[]; -#define imx51_add_mxc_pwm(id) \ - imx_add_mxc_pwm(&imx51_mxc_pwm_data[id]) - extern const struct imx_imx_keypad_data imx51_imx_keypad_data; #define imx51_add_imx_keypad(pdata) \ imx_add_imx_keypad(&imx51_imx_keypad_data, pdata) diff --git a/arch/arm/mach-imx/devices/Kconfig b/arch/arm/mach-imx/devices/Kconfig index 68c74fb0373c..2d260a5a307c 100644 --- a/arch/arm/mach-imx/devices/Kconfig +++ b/arch/arm/mach-imx/devices/Kconfig @@ -67,9 +67,6 @@ config IMX_HAVE_PLATFORM_MXC_MMC config IMX_HAVE_PLATFORM_MXC_NAND bool -config IMX_HAVE_PLATFORM_MXC_PWM - bool - config IMX_HAVE_PLATFORM_MXC_RNGA bool select ARCH_HAS_RNGA diff --git a/arch/arm/mach-imx/devices/Makefile b/arch/arm/mach-imx/devices/Makefile index 67416fb1dc69..1cbc14cd80d1 100644 --- a/arch/arm/mach-imx/devices/Makefile +++ b/arch/arm/mach-imx/devices/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_MX2_CAMERA) += platform-mx2-camera.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_EHCI) += platform-mxc-ehci.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_MMC) += platform-mxc-mmc.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_NAND) += platform-mxc_nand.o -obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_PWM) += platform-mxc_pwm.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RNGA) += platform-mxc_rnga.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_RTC) += platform-mxc_rtc.o obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_W1) += platform-mxc_w1.o diff --git a/arch/arm/mach-imx/devices/devices-common.h b/arch/arm/mach-imx/devices/devices-common.h index c13b76b9f6b3..61352a80bb59 100644 --- a/arch/arm/mach-imx/devices/devices-common.h +++ b/arch/arm/mach-imx/devices/devices-common.h @@ -290,15 +290,6 @@ struct imx_pata_imx_data { struct platform_device *__init imx_add_pata_imx( const struct imx_pata_imx_data *data); -struct imx_mxc_pwm_data { - int id; - resource_size_t iobase; - resource_size_t iosize; - resource_size_t irq; -}; -struct platform_device *__init imx_add_mxc_pwm( - const struct imx_mxc_pwm_data *data); - /* mxc_rtc */ struct imx_mxc_rtc_data { const char *devid; diff --git a/arch/arm/mach-imx/devices/platform-ipu-core.c b/arch/arm/mach-imx/devices/platform-ipu-core.c index fc4dd7cedc11..6bd7c3f37ac0 100644 --- a/arch/arm/mach-imx/devices/platform-ipu-core.c +++ b/arch/arm/mach-imx/devices/platform-ipu-core.c @@ -77,7 +77,7 @@ struct platform_device *__init imx_alloc_mx3_camera( pdev = platform_device_alloc("mx3-camera", 0); if (!pdev) - goto err; + return ERR_PTR(-ENOMEM); pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); if (!pdev->dev.dma_mask) diff --git a/arch/arm/mach-imx/devices/platform-mx2-emma.c b/arch/arm/mach-imx/devices/platform-mx2-emma.c index 11bd01d402f2..0dc0651825b1 100644 --- a/arch/arm/mach-imx/devices/platform-mx2-emma.c +++ b/arch/arm/mach-imx/devices/platform-mx2-emma.c @@ -12,7 +12,7 @@ #define imx_mx2_emmaprp_data_entry_single(soc) \ { \ .iobase = soc ## _EMMAPRP_BASE_ADDR, \ - .iosize = SZ_32, \ + .iosize = SZ_256, \ .irq = soc ## _INT_EMMAPRP, \ } diff --git a/arch/arm/mach-imx/devices/platform-mxc_pwm.c b/arch/arm/mach-imx/devices/platform-mxc_pwm.c deleted file mode 100644 index dcd289777687..000000000000 --- a/arch/arm/mach-imx/devices/platform-mxc_pwm.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2009-2010 Pengutronix - * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License version 2 as published by the - * Free Software Foundation. - */ -#include "../hardware.h" -#include "devices-common.h" - -#define imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size) \ - { \ - .id = _id, \ - .iobase = soc ## _PWM ## _hwid ## _BASE_ADDR, \ - .iosize = _size, \ - .irq = soc ## _INT_PWM ## _hwid, \ - } -#define imx_mxc_pwm_data_entry(soc, _id, _hwid, _size) \ - [_id] = imx_mxc_pwm_data_entry_single(soc, _id, _hwid, _size) - -#ifdef CONFIG_SOC_IMX21 -const struct imx_mxc_pwm_data imx21_mxc_pwm_data __initconst = - imx_mxc_pwm_data_entry_single(MX21, 0, , SZ_4K); -#endif /* ifdef CONFIG_SOC_IMX21 */ - -#ifdef CONFIG_SOC_IMX25 -const struct imx_mxc_pwm_data imx25_mxc_pwm_data[] __initconst = { -#define imx25_mxc_pwm_data_entry(_id, _hwid) \ - imx_mxc_pwm_data_entry(MX25, _id, _hwid, SZ_16K) - imx25_mxc_pwm_data_entry(0, 1), - imx25_mxc_pwm_data_entry(1, 2), - imx25_mxc_pwm_data_entry(2, 3), - imx25_mxc_pwm_data_entry(3, 4), -}; -#endif /* ifdef CONFIG_SOC_IMX25 */ - -#ifdef CONFIG_SOC_IMX27 -const struct imx_mxc_pwm_data imx27_mxc_pwm_data __initconst = - imx_mxc_pwm_data_entry_single(MX27, 0, , SZ_4K); -#endif /* ifdef CONFIG_SOC_IMX27 */ - -#ifdef CONFIG_SOC_IMX51 -const struct imx_mxc_pwm_data imx51_mxc_pwm_data[] __initconst = { -#define imx51_mxc_pwm_data_entry(_id, _hwid) \ - imx_mxc_pwm_data_entry(MX51, _id, _hwid, SZ_16K) - imx51_mxc_pwm_data_entry(0, 1), - imx51_mxc_pwm_data_entry(1, 2), -}; -#endif /* ifdef CONFIG_SOC_IMX51 */ - -struct platform_device *__init imx_add_mxc_pwm( - const struct imx_mxc_pwm_data *data) -{ - struct resource res[] = { - { - .start = data->iobase, - .end = data->iobase + data->iosize - 1, - .flags = IORESOURCE_MEM, - }, { - .start = data->irq, - .end = data->irq, - .flags = IORESOURCE_IRQ, - }, - }; - - return imx_add_platform_device("mxc_pwm", data->id, - res, ARRAY_SIZE(res), NULL, 0); -} diff --git a/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c deleted file mode 100644 index 9be6c1e69d68..000000000000 --- a/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2010 Eric Benard - eric@eukrea.com - * - * Based on pcm970-baseboard.c which is : - * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include <linux/types.h> -#include <linux/init.h> - -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/leds.h> -#include <linux/platform_device.h> -#include <linux/input.h> -#include <linux/i2c.h> -#include <video/platform_lcd.h> -#include <linux/backlight.h> - -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/time.h> -#include <asm/mach/map.h> - -#include "common.h" -#include "devices-imx51.h" -#include "hardware.h" -#include "iomux-mx51.h" - -static iomux_v3_cfg_t eukrea_mbimxsd51_pads[] = { - /* LED */ - MX51_PAD_NANDF_D10__GPIO3_30, - /* SWITCH */ - NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP | - PAD_CTL_PKE | PAD_CTL_SRE_FAST | - PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), - /* UART2 */ - MX51_PAD_UART2_RXD__UART2_RXD, - MX51_PAD_UART2_TXD__UART2_TXD, - /* UART 3 */ - MX51_PAD_UART3_RXD__UART3_RXD, - MX51_PAD_UART3_TXD__UART3_TXD, - MX51_PAD_KEY_COL4__UART3_RTS, - MX51_PAD_KEY_COL5__UART3_CTS, - /* SD */ - MX51_PAD_SD1_CMD__SD1_CMD, - MX51_PAD_SD1_CLK__SD1_CLK, - MX51_PAD_SD1_DATA0__SD1_DATA0, - MX51_PAD_SD1_DATA1__SD1_DATA1, - MX51_PAD_SD1_DATA2__SD1_DATA2, - MX51_PAD_SD1_DATA3__SD1_DATA3, - /* SD1 CD */ - NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP | - PAD_CTL_PKE | PAD_CTL_SRE_FAST | - PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), - /* SSI */ - MX51_PAD_AUD3_BB_TXD__AUD3_TXD, - MX51_PAD_AUD3_BB_RXD__AUD3_RXD, - MX51_PAD_AUD3_BB_CK__AUD3_TXC, - MX51_PAD_AUD3_BB_FS__AUD3_TXFS, - /* LCD Backlight */ - MX51_PAD_DI1_D1_CS__GPIO3_4, - /* LCD RST */ - MX51_PAD_CSI1_D9__GPIO3_13, -}; - -#define GPIO_LED1 IMX_GPIO_NR(3, 30) -#define GPIO_SWITCH1 IMX_GPIO_NR(3, 31) -#define GPIO_LCDRST IMX_GPIO_NR(3, 13) -#define GPIO_LCDBL IMX_GPIO_NR(3, 4) - -static void eukrea_mbimxsd51_lcd_power_set(struct plat_lcd_data *pd, - unsigned int power) -{ - if (power) - gpio_direction_output(GPIO_LCDRST, 1); - else - gpio_direction_output(GPIO_LCDRST, 0); -} - -static struct plat_lcd_data eukrea_mbimxsd51_lcd_power_data = { - .set_power = eukrea_mbimxsd51_lcd_power_set, -}; - -static struct platform_device eukrea_mbimxsd51_lcd_powerdev = { - .name = "platform-lcd", - .dev.platform_data = &eukrea_mbimxsd51_lcd_power_data, -}; - -static void eukrea_mbimxsd51_bl_set_intensity(int intensity) -{ - if (intensity) - gpio_direction_output(GPIO_LCDBL, 1); - else - gpio_direction_output(GPIO_LCDBL, 0); -} - -static struct generic_bl_info eukrea_mbimxsd51_bl_info = { - .name = "eukrea_mbimxsd51-bl", - .max_intensity = 0xff, - .default_intensity = 0xff, - .set_bl_intensity = eukrea_mbimxsd51_bl_set_intensity, -}; - -static struct platform_device eukrea_mbimxsd51_bl_dev = { - .name = "generic-bl", - .id = 1, - .dev = { - .platform_data = &eukrea_mbimxsd51_bl_info, - }, -}; - -static const struct gpio_led eukrea_mbimxsd51_leds[] __initconst = { - { - .name = "led1", - .default_trigger = "heartbeat", - .active_low = 1, - .gpio = GPIO_LED1, - }, -}; - -static const struct gpio_led_platform_data - eukrea_mbimxsd51_led_info __initconst = { - .leds = eukrea_mbimxsd51_leds, - .num_leds = ARRAY_SIZE(eukrea_mbimxsd51_leds), -}; - -static struct gpio_keys_button eukrea_mbimxsd51_gpio_buttons[] = { - { - .gpio = GPIO_SWITCH1, - .code = BTN_0, - .desc = "BP1", - .active_low = 1, - .wakeup = 1, - }, -}; - -static const struct gpio_keys_platform_data - eukrea_mbimxsd51_button_data __initconst = { - .buttons = eukrea_mbimxsd51_gpio_buttons, - .nbuttons = ARRAY_SIZE(eukrea_mbimxsd51_gpio_buttons), -}; - -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static struct i2c_board_info eukrea_mbimxsd51_i2c_devices[] = { - { - I2C_BOARD_INFO("tlv320aic23", 0x1a), - }, -}; - -static const -struct imx_ssi_platform_data eukrea_mbimxsd51_ssi_pdata __initconst = { - .flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE, -}; - -static int screen_type; - -static int __init eukrea_mbimxsd51_screen_type(char *options) -{ - if (!strcmp(options, "dvi")) - screen_type = 1; - else if (!strcmp(options, "tft")) - screen_type = 0; - - return 0; -} -__setup("screen_type=", eukrea_mbimxsd51_screen_type); - -/* - * system init for baseboard usage. Will be called by cpuimx51sd init. - * - * Add platform devices present on this baseboard and init - * them from CPU side as far as required to use them later on - */ -void __init eukrea_mbimxsd51_baseboard_init(void) -{ - if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd51_pads, - ARRAY_SIZE(eukrea_mbimxsd51_pads))) - printk(KERN_ERR "error setting mbimxsd pads !\n"); - - imx51_add_imx_uart(1, NULL); - imx51_add_imx_uart(2, &uart_pdata); - - imx51_add_sdhci_esdhc_imx(0, NULL); - - imx51_add_imx_ssi(0, &eukrea_mbimxsd51_ssi_pdata); - - gpio_request(GPIO_LED1, "LED1"); - gpio_direction_output(GPIO_LED1, 1); - gpio_free(GPIO_LED1); - - gpio_request(GPIO_SWITCH1, "SWITCH1"); - gpio_direction_input(GPIO_SWITCH1); - gpio_free(GPIO_SWITCH1); - - gpio_request(GPIO_LCDRST, "LCDRST"); - gpio_direction_output(GPIO_LCDRST, 0); - gpio_request(GPIO_LCDBL, "LCDBL"); - gpio_direction_output(GPIO_LCDBL, 0); - if (!screen_type) { - platform_device_register(&eukrea_mbimxsd51_bl_dev); - platform_device_register(&eukrea_mbimxsd51_lcd_powerdev); - } else { - gpio_free(GPIO_LCDRST); - gpio_free(GPIO_LCDBL); - } - - i2c_register_board_info(0, eukrea_mbimxsd51_i2c_devices, - ARRAY_SIZE(eukrea_mbimxsd51_i2c_devices)); - - gpio_led_register_device(-1, &eukrea_mbimxsd51_led_info); - imx_add_gpio_keys(&eukrea_mbimxsd51_button_data); - imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0); -} diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h index a3b0b04b45c9..abf43bb47eca 100644 --- a/arch/arm/mach-imx/hardware.h +++ b/arch/arm/mach-imx/hardware.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2004-2007, 2014 Freescale Semiconductor, Inc. All Rights Reserved. * Copyright 2008 Juergen Beisert, kernel@pengutronix.de * * This program is free software; you can redistribute it and/or @@ -20,7 +20,9 @@ #ifndef __ASM_ARCH_MXC_HARDWARE_H__ #define __ASM_ARCH_MXC_HARDWARE_H__ +#ifndef __ASSEMBLY__ #include <asm/io.h> +#endif #include <asm/sizes.h> #define addr_in_module(addr, mod) \ diff --git a/arch/arm/mach-imx/headsmp.S b/arch/arm/mach-imx/headsmp.S index 627f16f0e9d1..de5047c8a6c8 100644 --- a/arch/arm/mach-imx/headsmp.S +++ b/arch/arm/mach-imx/headsmp.S @@ -12,12 +12,7 @@ #include <linux/linkage.h> #include <linux/init.h> -#include <asm/asm-offsets.h> -#include <asm/hardware/cache-l2x0.h> - .section ".text.head", "ax" - -#ifdef CONFIG_SMP diag_reg_offset: .word g_diag_reg - . @@ -34,38 +29,3 @@ ENTRY(v7_secondary_startup) set_diag_reg b secondary_startup ENDPROC(v7_secondary_startup) -#endif - -#ifdef CONFIG_ARM_CPU_SUSPEND -/* - * The following code must assume it is running from physical address - * where absolute virtual addresses to the data section have to be - * turned into relative ones. - */ - -#ifdef CONFIG_CACHE_L2X0 - .macro pl310_resume - adr r0, l2x0_saved_regs_offset - ldr r2, [r0] - add r2, r2, r0 - ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0 - ldr r1, [r2, #L2X0_R_AUX_CTRL] @ get aux_ctrl value - str r1, [r0, #L2X0_AUX_CTRL] @ restore aux_ctrl - mov r1, #0x1 - str r1, [r0, #L2X0_CTRL] @ re-enable L2 - .endm - -l2x0_saved_regs_offset: - .word l2x0_saved_regs - . - -#else - .macro pl310_resume - .endm -#endif - -ENTRY(v7_cpu_resume) - bl v7_invalidate_l1 - pl310_resume - b cpu_resume -ENDPROC(v7_cpu_resume) -#endif diff --git a/arch/arm/mach-imx/imx25-dt.c b/arch/arm/mach-imx/imx25-dt.c index 3e1ec5ffe630..42a65e067443 100644 --- a/arch/arm/mach-imx/imx25-dt.c +++ b/arch/arm/mach-imx/imx25-dt.c @@ -38,7 +38,6 @@ DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)") .map_io = mx25_map_io, .init_early = imx25_init_early, .init_irq = mx25_init_irq, - .handle_irq = imx25_handle_irq, .init_time = imx25_timer_init, .init_machine = imx25_dt_init, .dt_compat = imx25_dt_board_compat, diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c index 4e235ecb4021..17bd4058133d 100644 --- a/arch/arm/mach-imx/imx27-dt.c +++ b/arch/arm/mach-imx/imx27-dt.c @@ -43,7 +43,6 @@ DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .handle_irq = imx27_handle_irq, .init_time = imx27_timer_init, .init_machine = imx27_dt_init, .dt_compat = imx27_dt_board_compat, diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c index e1e70ef7bc2d..581f4d6c9b8a 100644 --- a/arch/arm/mach-imx/imx31-dt.c +++ b/arch/arm/mach-imx/imx31-dt.c @@ -39,7 +39,6 @@ DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .handle_irq = imx31_handle_irq, .init_time = imx31_dt_timer_init, .init_machine = imx31_dt_init, .dt_compat = imx31_dt_board_compat, diff --git a/arch/arm/mach-imx/imx35-dt.c b/arch/arm/mach-imx/imx35-dt.c index 9d48e0065a63..a62854c59240 100644 --- a/arch/arm/mach-imx/imx35-dt.c +++ b/arch/arm/mach-imx/imx35-dt.c @@ -43,7 +43,6 @@ DT_MACHINE_START(IMX35_DT, "Freescale i.MX35 (Device Tree Support)") .map_io = mx35_map_io, .init_early = imx35_init_early, .init_irq = imx35_irq_init, - .handle_irq = imx35_handle_irq, .init_machine = imx35_dt_init, .dt_compat = imx35_dt_board_compat, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c index 0230d78d1413..b8cd968faa52 100644 --- a/arch/arm/mach-imx/imx51-dt.c +++ b/arch/arm/mach-imx/imx51-dt.c @@ -38,7 +38,6 @@ DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)") .map_io = mx51_map_io, .init_early = imx51_init_early, .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, .init_machine = imx51_dt_init, .init_late = imx51_init_late, .dt_compat = imx51_dt_board_compat, diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c index 067580b2969b..ebbb5ab63529 100644 --- a/arch/arm/mach-imx/mach-apf9328.c +++ b/arch/arm/mach-imx/mach-apf9328.c @@ -142,7 +142,6 @@ MACHINE_START(APF9328, "Armadeus APF9328") .map_io = mx1_map_io, .init_early = imx1_init_early, .init_irq = mx1_init_irq, - .handle_irq = imx1_handle_irq, .init_time = apf9328_timer_init, .init_machine = apf9328_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c index 58b864a3fc20..39406b7e3228 100644 --- a/arch/arm/mach-imx/mach-armadillo5x0.c +++ b/arch/arm/mach-imx/mach-armadillo5x0.c @@ -562,7 +562,6 @@ MACHINE_START(ARMADILLO5X0, "Armadillo-500") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .handle_irq = imx31_handle_irq, .init_time = armadillo5x0_timer_init, .init_machine = armadillo5x0_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-bug.c b/arch/arm/mach-imx/mach-bug.c index 2d00476f7d2c..c97d7cb39135 100644 --- a/arch/arm/mach-imx/mach-bug.c +++ b/arch/arm/mach-imx/mach-bug.c @@ -57,7 +57,6 @@ MACHINE_START(BUG, "BugLabs BUGBase") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .handle_irq = imx31_handle_irq, .init_time = bug_timer_init, .init_machine = bug_board_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c index ea50870bda80..75b7b6aa2720 100644 --- a/arch/arm/mach-imx/mach-cpuimx27.c +++ b/arch/arm/mach-imx/mach-cpuimx27.c @@ -314,7 +314,6 @@ MACHINE_START(EUKREA_CPUIMX27, "EUKREA CPUIMX27") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .handle_irq = imx27_handle_irq, .init_time = eukrea_cpuimx27_timer_init, .init_machine = eukrea_cpuimx27_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c index 65e4c53e1554..1ffa27169045 100644 --- a/arch/arm/mach-imx/mach-cpuimx35.c +++ b/arch/arm/mach-imx/mach-cpuimx35.c @@ -199,7 +199,6 @@ MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35") .map_io = mx35_map_io, .init_early = imx35_init_early, .init_irq = mx35_init_irq, - .handle_irq = imx35_handle_irq, .init_time = eukrea_cpuimx35_timer_init, .init_machine = eukrea_cpuimx35_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c deleted file mode 100644 index 1fba2b8e983f..000000000000 --- a/arch/arm/mach-imx/mach-cpuimx51sd.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * - * Copyright (C) 2010 Eric Bénard <eric@eukrea.com> - * - * based on board-mx51_babbage.c which is - * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com> - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/i2c/tsc2007.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/interrupt.h> -#include <linux/i2c-gpio.h> -#include <linux/spi/spi.h> -#include <linux/can/platform/mcp251x.h> - -#include <asm/setup.h> -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/time.h> - -#include "common.h" -#include "devices-imx51.h" -#include "eukrea-baseboards.h" -#include "hardware.h" -#include "iomux-mx51.h" - -#define USBH1_RST IMX_GPIO_NR(2, 28) -#define ETH_RST IMX_GPIO_NR(2, 31) -#define TSC2007_IRQGPIO_REV2 IMX_GPIO_NR(3, 12) -#define TSC2007_IRQGPIO_REV3 IMX_GPIO_NR(4, 0) -#define CAN_IRQGPIO IMX_GPIO_NR(1, 1) -#define CAN_RST IMX_GPIO_NR(4, 15) -#define CAN_NCS IMX_GPIO_NR(4, 24) -#define CAN_RXOBF_REV2 IMX_GPIO_NR(1, 4) -#define CAN_RXOBF_REV3 IMX_GPIO_NR(3, 12) -#define CAN_RX1BF IMX_GPIO_NR(1, 6) -#define CAN_TXORTS IMX_GPIO_NR(1, 7) -#define CAN_TX1RTS IMX_GPIO_NR(1, 8) -#define CAN_TX2RTS IMX_GPIO_NR(1, 9) -#define I2C_SCL IMX_GPIO_NR(4, 16) -#define I2C_SDA IMX_GPIO_NR(4, 17) - -/* USB_CTRL_1 */ -#define MX51_USB_CTRL_1_OFFSET 0x10 -#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) - -#define MX51_USB_PLLDIV_12_MHZ 0x00 -#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 -#define MX51_USB_PLL_DIV_24_MHZ 0x02 - -static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = { - /* UART1 */ - MX51_PAD_UART1_RXD__UART1_RXD, - MX51_PAD_UART1_TXD__UART1_TXD, - MX51_PAD_UART1_RTS__UART1_RTS, - MX51_PAD_UART1_CTS__UART1_CTS, - - /* USB HOST1 */ - MX51_PAD_USBH1_CLK__USBH1_CLK, - MX51_PAD_USBH1_DIR__USBH1_DIR, - MX51_PAD_USBH1_NXT__USBH1_NXT, - MX51_PAD_USBH1_DATA0__USBH1_DATA0, - MX51_PAD_USBH1_DATA1__USBH1_DATA1, - MX51_PAD_USBH1_DATA2__USBH1_DATA2, - MX51_PAD_USBH1_DATA3__USBH1_DATA3, - MX51_PAD_USBH1_DATA4__USBH1_DATA4, - MX51_PAD_USBH1_DATA5__USBH1_DATA5, - MX51_PAD_USBH1_DATA6__USBH1_DATA6, - MX51_PAD_USBH1_DATA7__USBH1_DATA7, - MX51_PAD_USBH1_STP__USBH1_STP, - MX51_PAD_EIM_CS3__GPIO2_28, /* PHY nRESET */ - - /* FEC */ - MX51_PAD_EIM_DTACK__GPIO2_31, /* PHY nRESET */ - - /* HSI2C */ - MX51_PAD_I2C1_CLK__GPIO4_16, - MX51_PAD_I2C1_DAT__GPIO4_17, - - /* I2C1 */ - MX51_PAD_SD2_CMD__I2C1_SCL, - MX51_PAD_SD2_CLK__I2C1_SDA, - - /* CAN */ - MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI, - MX51_PAD_CSPI1_MISO__ECSPI1_MISO, - MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK, - MX51_PAD_CSPI1_SS0__GPIO4_24, /* nCS */ - MX51_PAD_CSI2_PIXCLK__GPIO4_15, /* nReset */ - MX51_PAD_GPIO1_1__GPIO1_1, /* IRQ */ - MX51_PAD_GPIO1_4__GPIO1_4, /* Control signals */ - MX51_PAD_GPIO1_6__GPIO1_6, - MX51_PAD_GPIO1_7__GPIO1_7, - MX51_PAD_GPIO1_8__GPIO1_8, - MX51_PAD_GPIO1_9__GPIO1_9, - - /* Touchscreen */ - /* IRQ */ - NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP | - PAD_CTL_PKE | PAD_CTL_SRE_FAST | - PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), - NEW_PAD_CTRL(MX51_PAD_NANDF_D8__GPIO4_0, PAD_CTL_PUS_22K_UP | - PAD_CTL_PKE | PAD_CTL_SRE_FAST | - PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS), -}; - -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static int tsc2007_get_pendown_state(struct device *dev) -{ - if (mx51_revision() < IMX_CHIP_REVISION_3_0) - return !gpio_get_value(TSC2007_IRQGPIO_REV2); - else - return !gpio_get_value(TSC2007_IRQGPIO_REV3); -} - -static struct tsc2007_platform_data tsc2007_info = { - .model = 2007, - .x_plate_ohms = 180, - .get_pendown_state = tsc2007_get_pendown_state, -}; - -static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = { - { - I2C_BOARD_INFO("pcf8563", 0x51), - }, { - I2C_BOARD_INFO("tsc2007", 0x49), - .platform_data = &tsc2007_info, - }, -}; - -static const struct mxc_nand_platform_data - eukrea_cpuimx51sd_nand_board_info __initconst = { - .width = 1, - .hw_ecc = 1, - .flash_bbt = 1, -}; - -/* This function is board specific as the bit mask for the plldiv will also -be different for other Freescale SoCs, thus a common bitmask is not -possible and cannot get place in /plat-mxc/ehci.c.*/ -static int initialize_otg_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - /* Set the PHY clock to 19.2MHz */ - v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; - v |= MX51_USB_PLL_DIV_19_2_MHZ; - __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY); -} - -static int initialize_usbh1_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - /* The clock for the USBH1 ULPI port will come from the PHY. */ - v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET); - __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, - usbother_base + MX51_USB_CTRL_1_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED | - MXC_EHCI_ITC_NO_THRESHOLD); -} - -static const struct mxc_usbh_platform_data dr_utmi_config __initconst = { - .init = initialize_otg_port, - .portsc = MXC_EHCI_UTMI_16BIT, -}; - -static const struct fsl_usb2_platform_data usb_pdata __initconst = { - .operating_mode = FSL_USB2_DR_DEVICE, - .phy_mode = FSL_USB2_PHY_UTMI_WIDE, -}; - -static const struct mxc_usbh_platform_data usbh1_config __initconst = { - .init = initialize_usbh1_port, - .portsc = MXC_EHCI_MODE_ULPI, -}; - -static bool otg_mode_host __initdata; - -static int __init eukrea_cpuimx51sd_otg_mode(char *options) -{ - if (!strcmp(options, "host")) - otg_mode_host = true; - else if (!strcmp(options, "device")) - otg_mode_host = false; - else - pr_info("otg_mode neither \"host\" nor \"device\". " - "Defaulting to device\n"); - return 1; -} -__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode); - -static struct i2c_gpio_platform_data pdata = { - .sda_pin = I2C_SDA, - .sda_is_open_drain = 0, - .scl_pin = I2C_SCL, - .scl_is_open_drain = 0, - .udelay = 2, -}; - -static struct platform_device hsi2c_gpio_device = { - .name = "i2c-gpio", - .id = 0, - .dev.platform_data = &pdata, -}; - -static struct mcp251x_platform_data mcp251x_info = { - .oscillator_frequency = 24E6, -}; - -static struct spi_board_info cpuimx51sd_spi_device[] = { - { - .modalias = "mcp2515", - .max_speed_hz = 10000000, - .bus_num = 0, - .mode = SPI_MODE_0, - .chip_select = 0, - .platform_data = &mcp251x_info, - /* irq number is run-time assigned */ - }, -}; - -static int cpuimx51sd_spi1_cs[] = { - CAN_NCS, -}; - -static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = { - .chipselect = cpuimx51sd_spi1_cs, - .num_chipselect = ARRAY_SIZE(cpuimx51sd_spi1_cs), -}; - -static struct platform_device *rev2_platform_devices[] __initdata = { - &hsi2c_gpio_device, -}; - -static const struct imxi2c_platform_data cpuimx51sd_i2c_data __initconst = { - .bitrate = 100000, -}; - -static void __init eukrea_cpuimx51sd_init(void) -{ - imx51_soc_init(); - - mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads, - ARRAY_SIZE(eukrea_cpuimx51sd_pads)); - - imx51_add_imx_uart(0, &uart_pdata); - imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info); - imx51_add_imx2_wdt(0); - - gpio_request(ETH_RST, "eth_rst"); - gpio_set_value(ETH_RST, 1); - imx51_add_fec(NULL); - - gpio_request(CAN_IRQGPIO, "can_irq"); - gpio_direction_input(CAN_IRQGPIO); - gpio_free(CAN_IRQGPIO); - gpio_request(CAN_NCS, "can_ncs"); - gpio_direction_output(CAN_NCS, 1); - gpio_free(CAN_NCS); - gpio_request(CAN_RST, "can_rst"); - gpio_direction_output(CAN_RST, 0); - msleep(20); - gpio_set_value(CAN_RST, 1); - imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata); - cpuimx51sd_spi_device[0].irq = gpio_to_irq(CAN_IRQGPIO); - spi_register_board_info(cpuimx51sd_spi_device, - ARRAY_SIZE(cpuimx51sd_spi_device)); - - if (mx51_revision() < IMX_CHIP_REVISION_3_0) { - eukrea_cpuimx51sd_i2c_devices[1].irq = - gpio_to_irq(TSC2007_IRQGPIO_REV2), - platform_add_devices(rev2_platform_devices, - ARRAY_SIZE(rev2_platform_devices)); - gpio_request(TSC2007_IRQGPIO_REV2, "tsc2007_irq"); - gpio_direction_input(TSC2007_IRQGPIO_REV2); - gpio_free(TSC2007_IRQGPIO_REV2); - } else { - eukrea_cpuimx51sd_i2c_devices[1].irq = - gpio_to_irq(TSC2007_IRQGPIO_REV3), - imx51_add_imx_i2c(0, &cpuimx51sd_i2c_data); - gpio_request(TSC2007_IRQGPIO_REV3, "tsc2007_irq"); - gpio_direction_input(TSC2007_IRQGPIO_REV3); - gpio_free(TSC2007_IRQGPIO_REV3); - } - - i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices, - ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices)); - - if (otg_mode_host) - imx51_add_mxc_ehci_otg(&dr_utmi_config); - else { - initialize_otg_port(NULL); - imx51_add_fsl_usb2_udc(&usb_pdata); - } - - gpio_request(USBH1_RST, "usb_rst"); - gpio_direction_output(USBH1_RST, 0); - msleep(20); - gpio_set_value(USBH1_RST, 1); - imx51_add_mxc_ehci_hs(1, &usbh1_config); - -#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD - eukrea_mbimxsd51_baseboard_init(); -#endif -} - -static void __init eukrea_cpuimx51sd_timer_init(void) -{ - mx51_clocks_init(32768, 24000000, 22579200, 0); -} - -MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD") - /* Maintainer: Eric Bénard <eric@eukrea.com> */ - .atag_offset = 0x100, - .map_io = mx51_map_io, - .init_early = imx51_init_early, - .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, - .init_time = eukrea_cpuimx51sd_timer_init, - .init_machine = eukrea_cpuimx51sd_init, - .init_late = imx51_init_late, - .restart = mxc_restart, -MACHINE_END diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c index 4bf454424249..e978dda1434c 100644 --- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c +++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c @@ -165,7 +165,6 @@ MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25") .map_io = mx25_map_io, .init_early = imx25_init_early, .init_irq = mx25_init_irq, - .handle_irq = imx25_handle_irq, .init_time = eukrea_cpuimx25_timer_init, .init_machine = eukrea_cpuimx25_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c index 97f9c6297fcf..b61bd8ed5568 100644 --- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c +++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c @@ -604,7 +604,6 @@ MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .handle_irq = imx27_handle_irq, .init_time = visstrim_m10_timer_init, .init_machine = visstrim_m10_board_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c index 1a851aea6832..bb3ca0429680 100644 --- a/arch/arm/mach-imx/mach-imx27ipcam.c +++ b/arch/arm/mach-imx/mach-imx27ipcam.c @@ -71,7 +71,6 @@ MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .handle_irq = imx27_handle_irq, .init_time = mx27ipcam_timer_init, .init_machine = mx27ipcam_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c index 3da2e3e44ce9..9992089d3ad1 100644 --- a/arch/arm/mach-imx/mach-imx27lite.c +++ b/arch/arm/mach-imx/mach-imx27lite.c @@ -77,7 +77,6 @@ MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .handle_irq = imx27_handle_irq, .init_time = mx27lite_timer_init, .init_machine = mx27lite_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-imx50.c b/arch/arm/mach-imx/mach-imx50.c index 77b77a92bb5d..b899c0b59afd 100644 --- a/arch/arm/mach-imx/mach-imx50.c +++ b/arch/arm/mach-imx/mach-imx50.c @@ -31,7 +31,6 @@ static const char *imx50_dt_board_compat[] __initconst = { DT_MACHINE_START(IMX50_DT, "Freescale i.MX50 (Device Tree Support)") .map_io = mx53_map_io, .init_irq = mx53_init_irq, - .handle_irq = imx50_handle_irq, .init_machine = imx50_dt_init, .dt_compat = imx50_dt_board_compat, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c index 65850908a4b4..2bad387956c0 100644 --- a/arch/arm/mach-imx/mach-imx53.c +++ b/arch/arm/mach-imx/mach-imx53.c @@ -40,7 +40,6 @@ DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)") .map_io = mx53_map_io, .init_early = imx53_init_early, .init_irq = mx53_init_irq, - .handle_irq = imx53_handle_irq, .init_machine = imx53_dt_init, .init_late = imx53_init_late, .dt_compat = imx53_dt_board_compat, diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 76e5db4fce35..e60456d85c9d 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -182,16 +182,83 @@ static void __init imx6q_enet_phy_init(void) static void __init imx6q_1588_init(void) { + struct device_node *np; + struct clk *ptp_clk; + struct clk *enet_ref; struct regmap *gpr; + u32 clksel; + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec"); + if (!np) { + pr_warn("%s: failed to find fec node\n", __func__); + return; + } + + ptp_clk = of_clk_get(np, 2); + if (IS_ERR(ptp_clk)) { + pr_warn("%s: failed to get ptp clock\n", __func__); + goto put_node; + } + + enet_ref = clk_get_sys(NULL, "enet_ref"); + if (IS_ERR(enet_ref)) { + pr_warn("%s: failed to get enet clock\n", __func__); + goto put_ptp_clk; + } + + /* + * If enet_ref from ANATOP/CCM is the PTP clock source, we need to + * set bit IOMUXC_GPR1[21]. Or the PTP clock must be from pad + * (external OSC), and we need to clear the bit. + */ + clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP : + IMX6Q_GPR1_ENET_CLK_SEL_PAD; gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); if (!IS_ERR(gpr)) regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_ENET_CLK_SEL_MASK, - IMX6Q_GPR1_ENET_CLK_SEL_ANATOP); + clksel); else pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n"); + clk_put(enet_ref); +put_ptp_clk: + clk_put(ptp_clk); +put_node: + of_node_put(np); +} + +static void __init imx6q_axi_init(void) +{ + struct regmap *gpr; + unsigned int mask; + + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); + if (!IS_ERR(gpr)) { + /* + * Enable the cacheable attribute of VPU and IPU + * AXI transactions. + */ + mask = IMX6Q_GPR4_VPU_WR_CACHE_SEL | + IMX6Q_GPR4_VPU_RD_CACHE_SEL | + IMX6Q_GPR4_VPU_P_WR_CACHE_VAL | + IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK | + IMX6Q_GPR4_IPU_WR_CACHE_CTL | + IMX6Q_GPR4_IPU_RD_CACHE_CTL; + regmap_update_bits(gpr, IOMUXC_GPR4, mask, mask); + + /* Increase IPU read QoS priority */ + regmap_update_bits(gpr, IOMUXC_GPR6, + IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK | + IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK, + (0xf << 16) | (0x7 << 20)); + regmap_update_bits(gpr, IOMUXC_GPR7, + IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK | + IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK, + (0xf << 16) | (0x7 << 20)); + } else { + pr_warn("failed to find fsl,imx6q-iomuxc-gpr regmap\n"); + } } static void __init imx6q_init_machine(void) @@ -212,15 +279,18 @@ static void __init imx6q_init_machine(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); imx_anatop_init(); - imx6q_pm_init(); + cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init(); imx6q_1588_init(); + imx6q_axi_init(); } #define OCOTP_CFG3 0x440 #define OCOTP_CFG3_SPEED_SHIFT 16 #define OCOTP_CFG3_SPEED_1P2GHZ 0x3 +#define OCOTP_CFG3_SPEED_996MHZ 0x2 +#define OCOTP_CFG3_SPEED_852MHZ 0x1 -static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev) +static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev) { struct device_node *np; void __iomem *base; @@ -238,11 +308,29 @@ static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev) goto put_node; } + /* + * SPEED_GRADING[1:0] defines the max speed of ARM: + * 2b'11: 1200000000Hz; + * 2b'10: 996000000Hz; + * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz. + * 2b'00: 792000000Hz; + * We need to set the max speed of ARM according to fuse map. + */ val = readl_relaxed(base + OCOTP_CFG3); val >>= OCOTP_CFG3_SPEED_SHIFT; - if ((val & 0x3) != OCOTP_CFG3_SPEED_1P2GHZ) + val &= 0x3; + + if (val != OCOTP_CFG3_SPEED_1P2GHZ) if (dev_pm_opp_disable(cpu_dev, 1200000000)) pr_warn("failed to disable 1.2 GHz OPP\n"); + if (val < OCOTP_CFG3_SPEED_996MHZ) + if (dev_pm_opp_disable(cpu_dev, 996000000)) + pr_warn("failed to disable 996 MHz OPP\n"); + if (cpu_is_imx6q()) { + if (val != OCOTP_CFG3_SPEED_852MHZ) + if (dev_pm_opp_disable(cpu_dev, 852000000)) + pr_warn("failed to disable 852 MHz OPP\n"); + } put_node: of_node_put(np); @@ -268,7 +356,7 @@ static void __init imx6q_opp_init(void) goto put_node; } - imx6q_opp_check_1p2ghz(cpu_dev); + imx6q_opp_check_speed_grading(cpu_dev); put_node: of_node_put(np); diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c index 0f4fd4c0ab8e..ad323385115c 100644 --- a/arch/arm/mach-imx/mach-imx6sl.c +++ b/arch/arm/mach-imx/mach-imx6sl.c @@ -17,6 +17,7 @@ #include <asm/mach/map.h> #include "common.h" +#include "cpuidle.h" static void __init imx6sl_fec_init(void) { @@ -39,6 +40,8 @@ static void __init imx6sl_init_late(void) /* imx6sl reuses imx6q cpufreq driver */ if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0); + + imx6sl_cpuidle_init(); } static void __init imx6sl_init_machine(void) @@ -55,8 +58,7 @@ static void __init imx6sl_init_machine(void) imx6sl_fec_init(); imx_anatop_init(); - /* Reuse imx6q pm code */ - imx6q_pm_init(); + imx6sl_pm_init(); } static void __init imx6sl_init_irq(void) diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c new file mode 100644 index 000000000000..02fccf6033ac --- /dev/null +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -0,0 +1,51 @@ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/irqchip.h> +#include <linux/of_platform.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include "common.h" + +static void __init imx6sx_init_machine(void) +{ + struct device *parent; + + mxc_arch_reset_init_dt(); + + parent = imx_soc_device_init(); + if (parent == NULL) + pr_warn("failed to initialize soc device\n"); + + of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); + + imx_anatop_init(); +} + +static void __init imx6sx_init_irq(void) +{ + imx_init_revision_from_anatop(); + imx_init_l2cache(); + imx_src_init(); + imx_gpc_init(); + irqchip_init(); +} + +static const char *imx6sx_dt_compat[] __initconst = { + "fsl,imx6sx", + NULL, +}; + +DT_MACHINE_START(IMX6SX, "Freescale i.MX6 SoloX (Device Tree)") + .map_io = debug_ll_io_init, + .init_irq = imx6sx_init_irq, + .init_machine = imx6sx_init_machine, + .dt_compat = imx6sx_dt_compat, + .restart = mxc_restart, +MACHINE_END diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c index c7bc41d6b468..31df4361996f 100644 --- a/arch/arm/mach-imx/mach-kzm_arm11_01.c +++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c @@ -289,7 +289,6 @@ MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01") .map_io = kzm_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .handle_irq = imx31_handle_irq, .init_time = kzm_timer_init, .init_machine = kzm_board_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c index 9f883e4d6fc9..77fda3de4290 100644 --- a/arch/arm/mach-imx/mach-mx1ads.c +++ b/arch/arm/mach-imx/mach-mx1ads.c @@ -138,7 +138,6 @@ MACHINE_START(MX1ADS, "Freescale MX1ADS") .map_io = mx1_map_io, .init_early = imx1_init_early, .init_irq = mx1_init_irq, - .handle_irq = imx1_handle_irq, .init_time = mx1ads_timer_init, .init_machine = mx1ads_init, .restart = mxc_restart, @@ -149,7 +148,6 @@ MACHINE_START(MXLADS, "Freescale MXLADS") .map_io = mx1_map_io, .init_early = imx1_init_early, .init_irq = mx1_init_irq, - .handle_irq = imx1_handle_irq, .init_time = mx1ads_timer_init, .init_machine = mx1ads_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c index a06aa4dc37fc..703ce31d7379 100644 --- a/arch/arm/mach-imx/mach-mx21ads.c +++ b/arch/arm/mach-imx/mach-mx21ads.c @@ -17,51 +17,46 @@ #include <linux/platform_device.h> #include <linux/mtd/mtd.h> #include <linux/mtd/physmap.h> +#include <linux/basic_mmio_gpio.h> #include <linux/gpio.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> -#include <asm/mach/time.h> -#include <asm/mach/map.h> #include "common.h" #include "devices-imx21.h" #include "hardware.h" #include "iomux-mx21.h" -/* - * Memory-mapped I/O on MX21ADS base board - */ -#define MX21ADS_MMIO_BASE_ADDR 0xf5000000 -#define MX21ADS_MMIO_SIZE 0xc00000 - -#define MX21ADS_REG_ADDR(offset) (void __force __iomem *) \ - (MX21ADS_MMIO_BASE_ADDR + (offset)) +#define MX21ADS_CS8900A_REG (MX21_CS1_BASE_ADDR + 0x000000) +#define MX21ADS_ST16C255_IOBASE_REG (MX21_CS1_BASE_ADDR + 0x200000) +#define MX21ADS_VERSION_REG (MX21_CS1_BASE_ADDR + 0x400000) +#define MX21ADS_IO_REG (MX21_CS1_BASE_ADDR + 0x800000) -#define MX21ADS_CS8900A_MMIO_SIZE 0x200000 -#define MX21ADS_CS8900A_IRQ_GPIO IMX_GPIO_NR(5, 11) -#define MX21ADS_ST16C255_IOBASE_REG MX21ADS_REG_ADDR(0x200000) -#define MX21ADS_VERSION_REG MX21ADS_REG_ADDR(0x400000) -#define MX21ADS_IO_REG MX21ADS_REG_ADDR(0x800000) +#define MX21ADS_MMC_CD IMX_GPIO_NR(4, 25) +#define MX21ADS_CS8900A_IRQ_GPIO IMX_GPIO_NR(5, 11) +#define MX21ADS_MMGPIO_BASE (6 * 32) /* MX21ADS_IO_REG bit definitions */ -#define MX21ADS_IO_SD_WP 0x0001 /* read */ -#define MX21ADS_IO_TP6 0x0001 /* write */ -#define MX21ADS_IO_SW_SEL 0x0002 /* read */ -#define MX21ADS_IO_TP7 0x0002 /* write */ -#define MX21ADS_IO_RESET_E_UART 0x0004 -#define MX21ADS_IO_RESET_BASE 0x0008 -#define MX21ADS_IO_CSI_CTL2 0x0010 -#define MX21ADS_IO_CSI_CTL1 0x0020 -#define MX21ADS_IO_CSI_CTL0 0x0040 -#define MX21ADS_IO_UART1_EN 0x0080 -#define MX21ADS_IO_UART4_EN 0x0100 -#define MX21ADS_IO_LCDON 0x0200 -#define MX21ADS_IO_IRDA_EN 0x0400 -#define MX21ADS_IO_IRDA_FIR_SEL 0x0800 -#define MX21ADS_IO_IRDA_MD0_B 0x1000 -#define MX21ADS_IO_IRDA_MD1 0x2000 -#define MX21ADS_IO_LED4_ON 0x4000 -#define MX21ADS_IO_LED3_ON 0x8000 +#define MX21ADS_IO_SD_WP (MX21ADS_MMGPIO_BASE + 0) +#define MX21ADS_IO_TP6 (MX21ADS_IO_SD_WP) +#define MX21ADS_IO_SW_SEL (MX21ADS_MMGPIO_BASE + 1) +#define MX21ADS_IO_TP7 (MX21ADS_IO_SW_SEL) +#define MX21ADS_IO_RESET_E_UART (MX21ADS_MMGPIO_BASE + 2) +#define MX21ADS_IO_RESET_BASE (MX21ADS_MMGPIO_BASE + 3) +#define MX21ADS_IO_CSI_CTL2 (MX21ADS_MMGPIO_BASE + 4) +#define MX21ADS_IO_CSI_CTL1 (MX21ADS_MMGPIO_BASE + 5) +#define MX21ADS_IO_CSI_CTL0 (MX21ADS_MMGPIO_BASE + 6) +#define MX21ADS_IO_UART1_EN (MX21ADS_MMGPIO_BASE + 7) +#define MX21ADS_IO_UART4_EN (MX21ADS_MMGPIO_BASE + 8) +#define MX21ADS_IO_LCDON (MX21ADS_MMGPIO_BASE + 9) +#define MX21ADS_IO_IRDA_EN (MX21ADS_MMGPIO_BASE + 10) +#define MX21ADS_IO_IRDA_FIR_SEL (MX21ADS_MMGPIO_BASE + 11) +#define MX21ADS_IO_IRDA_MD0_B (MX21ADS_MMGPIO_BASE + 12) +#define MX21ADS_IO_IRDA_MD1 (MX21ADS_MMGPIO_BASE + 13) +#define MX21ADS_IO_LED4_ON (MX21ADS_MMGPIO_BASE + 14) +#define MX21ADS_IO_LED3_ON (MX21ADS_MMGPIO_BASE + 15) static const int mx21ads_pins[] __initconst = { @@ -143,11 +138,8 @@ static struct physmap_flash_data mx21ads_flash_data = { .width = 4, }; -static struct resource mx21ads_flash_resource = { - .start = MX21_CS0_BASE_ADDR, - .end = MX21_CS0_BASE_ADDR + 0x02000000 - 1, - .flags = IORESOURCE_MEM, -}; +static struct resource mx21ads_flash_resource = + DEFINE_RES_MEM(MX21_CS0_BASE_ADDR, SZ_32M); static struct platform_device mx21ads_nor_mtd_device = { .name = "physmap-flash", @@ -160,7 +152,7 @@ static struct platform_device mx21ads_nor_mtd_device = { }; static struct resource mx21ads_cs8900_resources[] __initdata = { - DEFINE_RES_MEM(MX21_CS1_BASE_ADDR, MX21ADS_CS8900A_MMIO_SIZE), + DEFINE_RES_MEM(MX21ADS_CS8900A_REG, SZ_1K), /* irq number is run-time assigned */ DEFINE_RES_IRQ(-1), }; @@ -179,24 +171,50 @@ static const struct imxuart_platform_data uart_pdata_rts __initconst = { static const struct imxuart_platform_data uart_pdata_norts __initconst = { }; -static int mx21ads_fb_init(struct platform_device *pdev) -{ - u16 tmp; +static struct resource mx21ads_mmgpio_resource = + DEFINE_RES_MEM_NAMED(MX21ADS_IO_REG, SZ_2, "dat"); - tmp = __raw_readw(MX21ADS_IO_REG); - tmp |= MX21ADS_IO_LCDON; - __raw_writew(tmp, MX21ADS_IO_REG); - return 0; -} +static struct bgpio_pdata mx21ads_mmgpio_pdata = { + .base = MX21ADS_MMGPIO_BASE, + .ngpio = 16, +}; -static void mx21ads_fb_exit(struct platform_device *pdev) -{ - u16 tmp; +static struct platform_device mx21ads_mmgpio = { + .name = "basic-mmio-gpio", + .id = PLATFORM_DEVID_AUTO, + .resource = &mx21ads_mmgpio_resource, + .num_resources = 1, + .dev = { + .platform_data = &mx21ads_mmgpio_pdata, + }, +}; - tmp = __raw_readw(MX21ADS_IO_REG); - tmp &= ~MX21ADS_IO_LCDON; - __raw_writew(tmp, MX21ADS_IO_REG); -} +static struct regulator_consumer_supply mx21ads_lcd_regulator_consumer = + REGULATOR_SUPPLY("lcd", "imx-fb.0"); + +static struct regulator_init_data mx21ads_lcd_regulator_init_data = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .consumer_supplies = &mx21ads_lcd_regulator_consumer, + .num_consumer_supplies = 1, +}; + +static struct fixed_voltage_config mx21ads_lcd_regulator_pdata = { + .supply_name = "LCD", + .microvolts = 3300000, + .gpio = MX21ADS_IO_LCDON, + .enable_high = 1, + .init_data = &mx21ads_lcd_regulator_init_data, +}; + +static struct platform_device mx21ads_lcd_regulator = { + .name = "reg-fixed-voltage", + .id = PLATFORM_DEVID_AUTO, + .dev = { + .platform_data = &mx21ads_lcd_regulator_pdata, + }, +}; /* * Connected is a portrait Sharp-QVGA display @@ -229,26 +247,30 @@ static const struct imx_fb_platform_data mx21ads_fb_data __initconst = { .pwmr = 0x00a903ff, .lscr1 = 0x00120300, .dmacr = 0x00020008, - - .init = mx21ads_fb_init, - .exit = mx21ads_fb_exit, }; static int mx21ads_sdhc_get_ro(struct device *dev) { - return (__raw_readw(MX21ADS_IO_REG) & MX21ADS_IO_SD_WP) ? 1 : 0; + return gpio_get_value(MX21ADS_IO_SD_WP); } static int mx21ads_sdhc_init(struct device *dev, irq_handler_t detect_irq, void *data) { - return request_irq(gpio_to_irq(IMX_GPIO_NR(4, 25)), detect_irq, - IRQF_TRIGGER_FALLING, "mmc-detect", data); + int ret; + + ret = gpio_request(MX21ADS_IO_SD_WP, "mmc-ro"); + if (ret) + return ret; + + return request_irq(gpio_to_irq(MX21ADS_MMC_CD), detect_irq, + IRQF_TRIGGER_FALLING, "mmc-detect", data); } static void mx21ads_sdhc_exit(struct device *dev, void *data) { - free_irq(gpio_to_irq(IMX_GPIO_NR(4, 25)), data); + free_irq(gpio_to_irq(MX21ADS_MMC_CD), data); + gpio_free(MX21ADS_IO_SD_WP); } static const struct imxmmc_platform_data mx21ads_sdhc_pdata __initconst = { @@ -264,29 +286,9 @@ mx21ads_nand_board_info __initconst = { .hw_ecc = 1, }; -static struct map_desc mx21ads_io_desc[] __initdata = { - /* - * Memory-mapped I/O on MX21ADS Base board: - * - CS8900A Ethernet controller - * - ST16C2552CJ UART - * - CPU and Base board version - * - Base board I/O register - */ - { - .virtual = MX21ADS_MMIO_BASE_ADDR, - .pfn = __phys_to_pfn(MX21_CS1_BASE_ADDR), - .length = MX21ADS_MMIO_SIZE, - .type = MT_DEVICE, - }, -}; - -static void __init mx21ads_map_io(void) -{ - mx21_map_io(); - iotable_init(mx21ads_io_desc, ARRAY_SIZE(mx21ads_io_desc)); -} - static struct platform_device *platform_devices[] __initdata = { + &mx21ads_mmgpio, + &mx21ads_lcd_regulator, &mx21ads_nor_mtd_device, }; @@ -300,12 +302,13 @@ static void __init mx21ads_board_init(void) imx21_add_imx_uart0(&uart_pdata_rts); imx21_add_imx_uart2(&uart_pdata_norts); imx21_add_imx_uart3(&uart_pdata_rts); - imx21_add_imx_fb(&mx21ads_fb_data); imx21_add_mxc_mmc(0, &mx21ads_sdhc_pdata); imx21_add_mxc_nand(&mx21ads_nand_board_info); platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); + imx21_add_imx_fb(&mx21ads_fb_data); + mx21ads_cs8900_resources[1].start = gpio_to_irq(MX21ADS_CS8900A_IRQ_GPIO); mx21ads_cs8900_resources[1].end = @@ -321,10 +324,9 @@ static void __init mx21ads_timer_init(void) MACHINE_START(MX21ADS, "Freescale i.MX21ADS") /* maintainer: Freescale Semiconductor, Inc. */ .atag_offset = 0x100, - .map_io = mx21ads_map_io, + .map_io = mx21_map_io, .init_early = imx21_init_early, .init_irq = mx21_init_irq, - .handle_irq = imx21_handle_irq, .init_time = mx21ads_timer_init, .init_machine = mx21ads_board_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c index 13490c203050..ea1fa199c148 100644 --- a/arch/arm/mach-imx/mach-mx25_3ds.c +++ b/arch/arm/mach-imx/mach-mx25_3ds.c @@ -263,7 +263,6 @@ MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)") .map_io = mx25_map_io, .init_early = imx25_init_early, .init_irq = mx25_init_irq, - .handle_irq = imx25_handle_irq, .init_time = mx25pdk_timer_init, .init_machine = mx25pdk_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c index 25b3e4c9bc0a..435a5428a678 100644 --- a/arch/arm/mach-imx/mach-mx27_3ds.c +++ b/arch/arm/mach-imx/mach-mx27_3ds.c @@ -544,7 +544,6 @@ MACHINE_START(MX27_3DS, "Freescale MX27PDK") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .handle_irq = imx27_handle_irq, .init_time = mx27pdk_timer_init, .init_machine = mx27pdk_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c index 9821b824dcaf..2f834ce8f39c 100644 --- a/arch/arm/mach-imx/mach-mx27ads.c +++ b/arch/arm/mach-imx/mach-mx27ads.c @@ -21,6 +21,10 @@ #include <linux/mtd/physmap.h> #include <linux/i2c.h> #include <linux/irq.h> + +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> + #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> @@ -195,14 +199,58 @@ static const struct imxi2c_platform_data mx27ads_i2c1_data __initconst = { static struct i2c_board_info mx27ads_i2c_devices[] = { }; -void lcd_power(int on) +static void vgpio_set(struct gpio_chip *chip, unsigned offset, int value) { - if (on) + if (value) __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_SET_REG); else __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG); } +static int vgpio_dir_out(struct gpio_chip *chip, unsigned offset, int value) +{ + return 0; +} + +#define MX27ADS_LCD_GPIO (6 * 32) + +static struct regulator_consumer_supply mx27ads_lcd_regulator_consumer = + REGULATOR_SUPPLY("lcd", "imx-fb.0"); + +static struct regulator_init_data mx27ads_lcd_regulator_init_data = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, +}, + .consumer_supplies = &mx27ads_lcd_regulator_consumer, + .num_consumer_supplies = 1, +}; + +static struct fixed_voltage_config mx27ads_lcd_regulator_pdata = { + .supply_name = "LCD", + .microvolts = 3300000, + .gpio = MX27ADS_LCD_GPIO, + .init_data = &mx27ads_lcd_regulator_init_data, +}; + +static void __init mx27ads_regulator_init(void) +{ + struct gpio_chip *vchip; + + vchip = kzalloc(sizeof(*vchip), GFP_KERNEL); + vchip->owner = THIS_MODULE; + vchip->label = "LCD"; + vchip->base = MX27ADS_LCD_GPIO; + vchip->ngpio = 1; + vchip->direction_output = vgpio_dir_out; + vchip->set = vgpio_set; + gpiochip_add(vchip); + + platform_device_register_data(&platform_bus, "reg-fixed-voltage", + PLATFORM_DEVID_AUTO, + &mx27ads_lcd_regulator_pdata, + sizeof(mx27ads_lcd_regulator_pdata)); +} + static struct imx_fb_videomode mx27ads_modes[] = { { .mode = { @@ -239,8 +287,6 @@ static const struct imx_fb_platform_data mx27ads_fb_data __initconst = { .pwmr = 0x00A903FF, .lscr1 = 0x00120300, .dmacr = 0x00020010, - - .lcd_power = lcd_power, }; static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq, @@ -304,6 +350,7 @@ static void __init mx27ads_board_init(void) i2c_register_board_info(1, mx27ads_i2c_devices, ARRAY_SIZE(mx27ads_i2c_devices)); imx27_add_imx_i2c(1, &mx27ads_i2c1_data); + mx27ads_regulator_init(); imx27_add_imx_fb(&mx27ads_fb_data); imx27_add_mxc_mmc(0, &sdhc1_pdata); imx27_add_mxc_mmc(1, &sdhc2_pdata); @@ -344,7 +391,6 @@ MACHINE_START(MX27ADS, "Freescale i.MX27ADS") .map_io = mx27ads_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .handle_irq = imx27_handle_irq, .init_time = mx27ads_timer_init, .init_machine = mx27ads_board_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index 50044a21b388..4217871a9653 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -775,7 +775,6 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .handle_irq = imx31_handle_irq, .init_time = mx31_3ds_timer_init, .init_machine = mx31_3ds_init, .reserve = mx31_3ds_reserve, diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c index daf8889125cc..d08c37c696f6 100644 --- a/arch/arm/mach-imx/mach-mx31ads.c +++ b/arch/arm/mach-imx/mach-mx31ads.c @@ -582,7 +582,6 @@ MACHINE_START(MX31ADS, "Freescale MX31ADS") .map_io = mx31ads_map_io, .init_early = imx31_init_early, .init_irq = mx31ads_init_irq, - .handle_irq = imx31_handle_irq, .init_time = mx31ads_timer_init, .init_machine = mx31ads_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c index 832b1e2f964e..eee042fa2768 100644 --- a/arch/arm/mach-imx/mach-mx31lilly.c +++ b/arch/arm/mach-imx/mach-mx31lilly.c @@ -308,7 +308,6 @@ MACHINE_START(LILLY1131, "INCO startec LILLY-1131") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .handle_irq = imx31_handle_irq, .init_time = mx31lilly_timer_init, .init_machine = mx31lilly_board_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c index bea07299b61a..fa15d0b6118d 100644 --- a/arch/arm/mach-imx/mach-mx31lite.c +++ b/arch/arm/mach-imx/mach-mx31lite.c @@ -291,7 +291,6 @@ MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM") .map_io = mx31lite_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .handle_irq = imx31_handle_irq, .init_time = mx31lite_timer_init, .init_machine = mx31lite_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c index 8f45afe785f8..08730f238449 100644 --- a/arch/arm/mach-imx/mach-mx31moboard.c +++ b/arch/arm/mach-imx/mach-mx31moboard.c @@ -600,7 +600,6 @@ MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .handle_irq = imx31_handle_irq, .init_time = mx31moboard_timer_init, .init_machine = mx31moboard_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c index a42f4f07051f..4e8b184d773b 100644 --- a/arch/arm/mach-imx/mach-mx35_3ds.c +++ b/arch/arm/mach-imx/mach-mx35_3ds.c @@ -615,7 +615,6 @@ MACHINE_START(MX35_3DS, "Freescale MX35PDK") .map_io = mx35_map_io, .init_early = imx35_init_early, .init_irq = mx35_init_irq, - .handle_irq = imx35_handle_irq, .init_time = mx35pdk_timer_init, .init_machine = mx35_3ds_init, .reserve = mx35_3ds_reserve, diff --git a/arch/arm/mach-imx/mach-mx51_babbage.c b/arch/arm/mach-imx/mach-mx51_babbage.c deleted file mode 100644 index f3d264a636fa..000000000000 --- a/arch/arm/mach-imx/mach-mx51_babbage.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com> - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/input.h> -#include <linux/spi/flash.h> -#include <linux/spi/spi.h> - -#include <asm/setup.h> -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/time.h> - -#include "common.h" -#include "devices-imx51.h" -#include "hardware.h" -#include "iomux-mx51.h" - -#define BABBAGE_USB_HUB_RESET IMX_GPIO_NR(1, 7) -#define BABBAGE_USBH1_STP IMX_GPIO_NR(1, 27) -#define BABBAGE_USB_PHY_RESET IMX_GPIO_NR(2, 5) -#define BABBAGE_FEC_PHY_RESET IMX_GPIO_NR(2, 14) -#define BABBAGE_POWER_KEY IMX_GPIO_NR(2, 21) -#define BABBAGE_ECSPI1_CS0 IMX_GPIO_NR(4, 24) -#define BABBAGE_ECSPI1_CS1 IMX_GPIO_NR(4, 25) -#define BABBAGE_SD2_CD IMX_GPIO_NR(1, 6) -#define BABBAGE_SD2_WP IMX_GPIO_NR(1, 5) - -/* USB_CTRL_1 */ -#define MX51_USB_CTRL_1_OFFSET 0x10 -#define MX51_USB_CTRL_UH1_EXT_CLK_EN (1 << 25) - -#define MX51_USB_PLLDIV_12_MHZ 0x00 -#define MX51_USB_PLL_DIV_19_2_MHZ 0x01 -#define MX51_USB_PLL_DIV_24_MHZ 0x02 - -static struct gpio_keys_button babbage_buttons[] = { - { - .gpio = BABBAGE_POWER_KEY, - .code = BTN_0, - .desc = "PWR", - .active_low = 1, - .wakeup = 1, - }, -}; - -static const struct gpio_keys_platform_data imx_button_data __initconst = { - .buttons = babbage_buttons, - .nbuttons = ARRAY_SIZE(babbage_buttons), -}; - -static iomux_v3_cfg_t mx51babbage_pads[] = { - /* UART1 */ - MX51_PAD_UART1_RXD__UART1_RXD, - MX51_PAD_UART1_TXD__UART1_TXD, - MX51_PAD_UART1_RTS__UART1_RTS, - MX51_PAD_UART1_CTS__UART1_CTS, - - /* UART2 */ - MX51_PAD_UART2_RXD__UART2_RXD, - MX51_PAD_UART2_TXD__UART2_TXD, - - /* UART3 */ - MX51_PAD_EIM_D25__UART3_RXD, - MX51_PAD_EIM_D26__UART3_TXD, - MX51_PAD_EIM_D27__UART3_RTS, - MX51_PAD_EIM_D24__UART3_CTS, - - /* I2C1 */ - MX51_PAD_EIM_D16__I2C1_SDA, - MX51_PAD_EIM_D19__I2C1_SCL, - - /* I2C2 */ - MX51_PAD_KEY_COL4__I2C2_SCL, - MX51_PAD_KEY_COL5__I2C2_SDA, - - /* HSI2C */ - MX51_PAD_I2C1_CLK__I2C1_CLK, - MX51_PAD_I2C1_DAT__I2C1_DAT, - - /* USB HOST1 */ - MX51_PAD_USBH1_CLK__USBH1_CLK, - MX51_PAD_USBH1_DIR__USBH1_DIR, - MX51_PAD_USBH1_NXT__USBH1_NXT, - MX51_PAD_USBH1_DATA0__USBH1_DATA0, - MX51_PAD_USBH1_DATA1__USBH1_DATA1, - MX51_PAD_USBH1_DATA2__USBH1_DATA2, - MX51_PAD_USBH1_DATA3__USBH1_DATA3, - MX51_PAD_USBH1_DATA4__USBH1_DATA4, - MX51_PAD_USBH1_DATA5__USBH1_DATA5, - MX51_PAD_USBH1_DATA6__USBH1_DATA6, - MX51_PAD_USBH1_DATA7__USBH1_DATA7, - - /* USB HUB reset line*/ - MX51_PAD_GPIO1_7__GPIO1_7, - - /* USB PHY reset line */ - MX51_PAD_EIM_D21__GPIO2_5, - - /* FEC */ - MX51_PAD_EIM_EB2__FEC_MDIO, - MX51_PAD_EIM_EB3__FEC_RDATA1, - MX51_PAD_EIM_CS2__FEC_RDATA2, - MX51_PAD_EIM_CS3__FEC_RDATA3, - MX51_PAD_EIM_CS4__FEC_RX_ER, - MX51_PAD_EIM_CS5__FEC_CRS, - MX51_PAD_NANDF_RB2__FEC_COL, - MX51_PAD_NANDF_RB3__FEC_RX_CLK, - MX51_PAD_NANDF_D9__FEC_RDATA0, - MX51_PAD_NANDF_D8__FEC_TDATA0, - MX51_PAD_NANDF_CS2__FEC_TX_ER, - MX51_PAD_NANDF_CS3__FEC_MDC, - MX51_PAD_NANDF_CS4__FEC_TDATA1, - MX51_PAD_NANDF_CS5__FEC_TDATA2, - MX51_PAD_NANDF_CS6__FEC_TDATA3, - MX51_PAD_NANDF_CS7__FEC_TX_EN, - MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK, - - /* FEC PHY reset line */ - MX51_PAD_EIM_A20__GPIO2_14, - - /* SD 1 */ - MX51_PAD_SD1_CMD__SD1_CMD, - MX51_PAD_SD1_CLK__SD1_CLK, - MX51_PAD_SD1_DATA0__SD1_DATA0, - MX51_PAD_SD1_DATA1__SD1_DATA1, - MX51_PAD_SD1_DATA2__SD1_DATA2, - MX51_PAD_SD1_DATA3__SD1_DATA3, - /* CD/WP from controller */ - MX51_PAD_GPIO1_0__SD1_CD, - MX51_PAD_GPIO1_1__SD1_WP, - - /* SD 2 */ - MX51_PAD_SD2_CMD__SD2_CMD, - MX51_PAD_SD2_CLK__SD2_CLK, - MX51_PAD_SD2_DATA0__SD2_DATA0, - MX51_PAD_SD2_DATA1__SD2_DATA1, - MX51_PAD_SD2_DATA2__SD2_DATA2, - MX51_PAD_SD2_DATA3__SD2_DATA3, - /* CD/WP gpio */ - MX51_PAD_GPIO1_6__GPIO1_6, - MX51_PAD_GPIO1_5__GPIO1_5, - - /* eCSPI1 */ - MX51_PAD_CSPI1_MISO__ECSPI1_MISO, - MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI, - MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK, - MX51_PAD_CSPI1_SS0__GPIO4_24, - MX51_PAD_CSPI1_SS1__GPIO4_25, - - /* Audio */ - MX51_PAD_AUD3_BB_TXD__AUD3_TXD, - MX51_PAD_AUD3_BB_RXD__AUD3_RXD, - MX51_PAD_AUD3_BB_CK__AUD3_TXC, - MX51_PAD_AUD3_BB_FS__AUD3_TXFS, -}; - -/* Serial ports */ -static const struct imxuart_platform_data uart_pdata __initconst = { - .flags = IMXUART_HAVE_RTSCTS, -}; - -static const struct imxi2c_platform_data babbage_i2c_data __initconst = { - .bitrate = 100000, -}; - -static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = { - .bitrate = 400000, -}; - -static struct gpio mx51_babbage_usbh1_gpios[] = { - { BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" }, - { BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" }, -}; - -static int gpio_usbh1_active(void) -{ - iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27; - int ret; - - /* Set USBH1_STP to GPIO and toggle it */ - mxc_iomux_v3_setup_pad(usbh1stp_gpio); - ret = gpio_request_array(mx51_babbage_usbh1_gpios, - ARRAY_SIZE(mx51_babbage_usbh1_gpios)); - - if (ret) { - pr_debug("failed to get USBH1 pins: %d\n", ret); - return ret; - } - - msleep(100); - gpio_set_value(BABBAGE_USBH1_STP, 1); - gpio_set_value(BABBAGE_USB_PHY_RESET, 1); - gpio_free_array(mx51_babbage_usbh1_gpios, - ARRAY_SIZE(mx51_babbage_usbh1_gpios)); - return 0; -} - -static inline void babbage_usbhub_reset(void) -{ - int ret; - - /* Reset USB hub */ - ret = gpio_request_one(BABBAGE_USB_HUB_RESET, - GPIOF_OUT_INIT_LOW, "GPIO1_7"); - if (ret) { - printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret); - return; - } - - msleep(2); - /* Deassert reset */ - gpio_set_value(BABBAGE_USB_HUB_RESET, 1); -} - -static inline void babbage_fec_reset(void) -{ - int ret; - - /* reset FEC PHY */ - ret = gpio_request_one(BABBAGE_FEC_PHY_RESET, - GPIOF_OUT_INIT_LOW, "fec-phy-reset"); - if (ret) { - printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret); - return; - } - msleep(1); - gpio_set_value(BABBAGE_FEC_PHY_RESET, 1); -} - -/* This function is board specific as the bit mask for the plldiv will also -be different for other Freescale SoCs, thus a common bitmask is not -possible and cannot get place in /plat-mxc/ehci.c.*/ -static int initialize_otg_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - /* Set the PHY clock to 19.2MHz */ - v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK; - v |= MX51_USB_PLL_DIV_19_2_MHZ; - __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY); -} - -static int initialize_usbh1_port(struct platform_device *pdev) -{ - u32 v; - void __iomem *usb_base; - void __iomem *usbother_base; - - usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K); - if (!usb_base) - return -ENOMEM; - usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET; - - /* The clock for the USBH1 ULPI port will come externally from the PHY. */ - v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET); - __raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET); - iounmap(usb_base); - - mdelay(10); - - return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED | - MXC_EHCI_ITC_NO_THRESHOLD); -} - -static const struct mxc_usbh_platform_data dr_utmi_config __initconst = { - .init = initialize_otg_port, - .portsc = MXC_EHCI_UTMI_16BIT, -}; - -static const struct fsl_usb2_platform_data usb_pdata __initconst = { - .operating_mode = FSL_USB2_DR_DEVICE, - .phy_mode = FSL_USB2_PHY_UTMI_WIDE, -}; - -static const struct mxc_usbh_platform_data usbh1_config __initconst = { - .init = initialize_usbh1_port, - .portsc = MXC_EHCI_MODE_ULPI, -}; - -static bool otg_mode_host __initdata; - -static int __init babbage_otg_mode(char *options) -{ - if (!strcmp(options, "host")) - otg_mode_host = true; - else if (!strcmp(options, "device")) - otg_mode_host = false; - else - pr_info("otg_mode neither \"host\" nor \"device\". " - "Defaulting to device\n"); - return 1; -} -__setup("otg_mode=", babbage_otg_mode); - -static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = { - { - .modalias = "mtd_dataflash", - .max_speed_hz = 25000000, - .bus_num = 0, - .chip_select = 1, - .mode = SPI_MODE_0, - .platform_data = NULL, - }, -}; - -static int mx51_babbage_spi_cs[] = { - BABBAGE_ECSPI1_CS0, - BABBAGE_ECSPI1_CS1, -}; - -static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = { - .chipselect = mx51_babbage_spi_cs, - .num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs), -}; - -static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = { - .cd_type = ESDHC_CD_CONTROLLER, - .wp_type = ESDHC_WP_CONTROLLER, -}; - -static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = { - .cd_gpio = BABBAGE_SD2_CD, - .wp_gpio = BABBAGE_SD2_WP, - .cd_type = ESDHC_CD_GPIO, - .wp_type = ESDHC_WP_GPIO, -}; - -void __init imx51_babbage_common_init(void) -{ - mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads, - ARRAY_SIZE(mx51babbage_pads)); -} - -/* - * Board specific initialization. - */ -static void __init mx51_babbage_init(void) -{ - iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; - iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21, - PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH); - - imx51_soc_init(); - - imx51_babbage_common_init(); - - imx51_add_imx_uart(0, &uart_pdata); - imx51_add_imx_uart(1, NULL); - imx51_add_imx_uart(2, &uart_pdata); - - babbage_fec_reset(); - imx51_add_fec(NULL); - - /* Set the PAD settings for the pwr key. */ - mxc_iomux_v3_setup_pad(power_key); - imx_add_gpio_keys(&imx_button_data); - - imx51_add_imx_i2c(0, &babbage_i2c_data); - imx51_add_imx_i2c(1, &babbage_i2c_data); - imx51_add_hsi2c(&babbage_hsi2c_data); - - if (otg_mode_host) - imx51_add_mxc_ehci_otg(&dr_utmi_config); - else { - initialize_otg_port(NULL); - imx51_add_fsl_usb2_udc(&usb_pdata); - } - - gpio_usbh1_active(); - imx51_add_mxc_ehci_hs(1, &usbh1_config); - /* setback USBH1_STP to be function */ - mxc_iomux_v3_setup_pad(usbh1stp); - babbage_usbhub_reset(); - - imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data); - imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data); - - spi_register_board_info(mx51_babbage_spi_board_info, - ARRAY_SIZE(mx51_babbage_spi_board_info)); - imx51_add_ecspi(0, &mx51_babbage_spi_pdata); - imx51_add_imx2_wdt(0); -} - -static void __init mx51_babbage_timer_init(void) -{ - mx51_clocks_init(32768, 24000000, 22579200, 0); -} - -MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board") - /* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */ - .atag_offset = 0x100, - .map_io = mx51_map_io, - .init_early = imx51_init_early, - .init_irq = mx51_init_irq, - .handle_irq = imx51_handle_irq, - .init_time = mx51_babbage_timer_init, - .init_machine = mx51_babbage_init, - .init_late = imx51_init_late, - .restart = mxc_restart, -MACHINE_END diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c index c91894003da9..0b5d1ca31b9f 100644 --- a/arch/arm/mach-imx/mach-mxt_td60.c +++ b/arch/arm/mach-imx/mach-mxt_td60.c @@ -267,7 +267,6 @@ MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .handle_irq = imx27_handle_irq, .init_time = mxt_td60_timer_init, .init_machine = mxt_td60_board_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c index bf3ac51d5aca..12212378c672 100644 --- a/arch/arm/mach-imx/mach-pca100.c +++ b/arch/arm/mach-imx/mach-pca100.c @@ -245,8 +245,7 @@ static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq, int ret; ret = request_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), detect_irq, - IRQF_DISABLED | IRQF_TRIGGER_FALLING, - "imx-mmc-detect", data); + IRQF_TRIGGER_FALLING, "imx-mmc-detect", data); if (ret) printk(KERN_ERR "pca100: Failed to request irq for sd/mmc detection\n"); @@ -421,7 +420,6 @@ MACHINE_START(PCA100, "phyCARD-i.MX27") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .handle_irq = imx27_handle_irq, .init_machine = pca100_init, .init_time = pca100_timer_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c index 639a3dfb0092..81b8affb9448 100644 --- a/arch/arm/mach-imx/mach-pcm037.c +++ b/arch/arm/mach-imx/mach-pcm037.c @@ -703,7 +703,6 @@ MACHINE_START(PCM037, "Phytec Phycore pcm037") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .handle_irq = imx31_handle_irq, .init_time = pcm037_timer_init, .init_machine = pcm037_init, .init_late = pcm037_init_late, diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c index 592ddbe031ac..6c56fb5553c7 100644 --- a/arch/arm/mach-imx/mach-pcm038.c +++ b/arch/arm/mach-imx/mach-pcm038.c @@ -351,7 +351,6 @@ MACHINE_START(PCM038, "phyCORE-i.MX27") .map_io = mx27_map_io, .init_early = imx27_init_early, .init_irq = mx27_init_irq, - .handle_irq = imx27_handle_irq, .init_time = pcm038_timer_init, .init_machine = pcm038_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c index ac504b67326b..c62b5d261345 100644 --- a/arch/arm/mach-imx/mach-pcm043.c +++ b/arch/arm/mach-imx/mach-pcm043.c @@ -400,7 +400,6 @@ MACHINE_START(PCM043, "Phytec Phycore pcm043") .map_io = mx35_map_io, .init_early = imx35_init_early, .init_irq = mx35_init_irq, - .handle_irq = imx35_handle_irq, .init_time = pcm043_timer_init, .init_machine = pcm043_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c index 22af27ed457e..a213e7b9cb1c 100644 --- a/arch/arm/mach-imx/mach-qong.c +++ b/arch/arm/mach-imx/mach-qong.c @@ -266,7 +266,6 @@ MACHINE_START(QONG, "Dave/DENX QongEVB-LITE") .map_io = mx31_map_io, .init_early = imx31_init_early, .init_irq = mx31_init_irq, - .handle_irq = imx31_handle_irq, .init_time = qong_timer_init, .init_machine = qong_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c index b0fa10dd79fe..1f6bc3f7ae14 100644 --- a/arch/arm/mach-imx/mach-scb9328.c +++ b/arch/arm/mach-imx/mach-scb9328.c @@ -137,7 +137,6 @@ MACHINE_START(SCB9328, "Synertronixx scb9328") .map_io = mx1_map_io, .init_early = imx1_init_early, .init_irq = mx1_init_irq, - .handle_irq = imx1_handle_irq, .init_time = scb9328_timer_init, .init_machine = scb9328_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c index 2d8aef5a6efa..c44602758120 100644 --- a/arch/arm/mach-imx/mach-vf610.c +++ b/arch/arm/mach-imx/mach-vf610.c @@ -20,19 +20,14 @@ static void __init vf610_init_machine(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -static void __init vf610_init_irq(void) -{ - l2x0_of_init(0, ~0UL); - irqchip_init(); -} - static const char *vf610_dt_compat[] __initconst = { "fsl,vf610", NULL, }; DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)") - .init_irq = vf610_init_irq, + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .init_machine = vf610_init_machine, .dt_compat = vf610_dt_compat, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c index 8825d1217d18..872b3c6ba408 100644 --- a/arch/arm/mach-imx/mach-vpr200.c +++ b/arch/arm/mach-imx/mach-vpr200.c @@ -310,7 +310,6 @@ MACHINE_START(VPR200, "VPR200") .map_io = mx35_map_io, .init_early = imx35_init_early, .init_irq = mx35_init_irq, - .handle_irq = imx35_handle_irq, .init_time = vpr200_timer_init, .init_machine = vpr200_board_init, .restart = mxc_restart, diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h index b08ab3ad4a6d..75d6a37e1ae4 100644 --- a/arch/arm/mach-imx/mxc.h +++ b/arch/arm/mach-imx/mxc.h @@ -36,6 +36,7 @@ #define MXC_CPU_MX53 53 #define MXC_CPU_IMX6SL 0x60 #define MXC_CPU_IMX6DL 0x61 +#define MXC_CPU_IMX6SX 0x62 #define MXC_CPU_IMX6Q 0x63 #define IMX_CHIP_REVISION_1_0 0x10 @@ -163,6 +164,11 @@ static inline bool cpu_is_imx6dl(void) return __mxc_cpu_type == MXC_CPU_IMX6DL; } +static inline bool cpu_is_imx6sx(void) +{ + return __mxc_cpu_type == MXC_CPU_IMX6SX; +} + static inline bool cpu_is_imx6q(void) { return __mxc_cpu_type == MXC_CPU_IMX6Q; diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c new file mode 100644 index 000000000000..9392a8f4ef24 --- /dev/null +++ b/arch/arm/mach-imx/pm-imx6.c @@ -0,0 +1,551 @@ +/* + * Copyright 2011-2014 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/genalloc.h> +#include <linux/mfd/syscon.h> +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> +#include <linux/regmap.h> +#include <linux/suspend.h> +#include <asm/cacheflush.h> +#include <asm/fncpy.h> +#include <asm/proc-fns.h> +#include <asm/suspend.h> +#include <asm/tlb.h> + +#include "common.h" +#include "hardware.h" + +#define CCR 0x0 +#define BM_CCR_WB_COUNT (0x7 << 16) +#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21) +#define BM_CCR_RBC_EN (0x1 << 27) + +#define CLPCR 0x54 +#define BP_CLPCR_LPM 0 +#define BM_CLPCR_LPM (0x3 << 0) +#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2) +#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) +#define BM_CLPCR_SBYOS (0x1 << 6) +#define BM_CLPCR_DIS_REF_OSC (0x1 << 7) +#define BM_CLPCR_VSTBY (0x1 << 8) +#define BP_CLPCR_STBY_COUNT 9 +#define BM_CLPCR_STBY_COUNT (0x3 << 9) +#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11) +#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16) +#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17) +#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19) +#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21) +#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22) +#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23) +#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24) +#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25) +#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) +#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) + +#define CGPR 0x64 +#define BM_CGPR_INT_MEM_CLK_LPM (0x1 << 17) + +#define MX6Q_SUSPEND_OCRAM_SIZE 0x1000 +#define MX6_MAX_MMDC_IO_NUM 33 + +static void __iomem *ccm_base; +static void __iomem *suspend_ocram_base; +static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase); + +/* + * suspend ocram space layout: + * ======================== high address ====================== + * . + * . + * . + * ^ + * ^ + * ^ + * imx6_suspend code + * PM_INFO structure(imx6_cpu_pm_info) + * ======================== low address ======================= + */ + +struct imx6_pm_base { + phys_addr_t pbase; + void __iomem *vbase; +}; + +struct imx6_pm_socdata { + u32 cpu_type; + const char *mmdc_compat; + const char *src_compat; + const char *iomuxc_compat; + const char *gpc_compat; + const u32 mmdc_io_num; + const u32 *mmdc_io_offset; +}; + +static const u32 imx6q_mmdc_io_offset[] __initconst = { + 0x5ac, 0x5b4, 0x528, 0x520, /* DQM0 ~ DQM3 */ + 0x514, 0x510, 0x5bc, 0x5c4, /* DQM4 ~ DQM7 */ + 0x56c, 0x578, 0x588, 0x594, /* CAS, RAS, SDCLK_0, SDCLK_1 */ + 0x5a8, 0x5b0, 0x524, 0x51c, /* SDQS0 ~ SDQS3 */ + 0x518, 0x50c, 0x5b8, 0x5c0, /* SDQS4 ~ SDQS7 */ + 0x784, 0x788, 0x794, 0x79c, /* GPR_B0DS ~ GPR_B3DS */ + 0x7a0, 0x7a4, 0x7a8, 0x748, /* GPR_B4DS ~ GPR_B7DS */ + 0x59c, 0x5a0, 0x750, 0x774, /* SODT0, SODT1, MODE_CTL, MODE */ + 0x74c, /* GPR_ADDS */ +}; + +static const u32 imx6dl_mmdc_io_offset[] __initconst = { + 0x470, 0x474, 0x478, 0x47c, /* DQM0 ~ DQM3 */ + 0x480, 0x484, 0x488, 0x48c, /* DQM4 ~ DQM7 */ + 0x464, 0x490, 0x4ac, 0x4b0, /* CAS, RAS, SDCLK_0, SDCLK_1 */ + 0x4bc, 0x4c0, 0x4c4, 0x4c8, /* DRAM_SDQS0 ~ DRAM_SDQS3 */ + 0x4cc, 0x4d0, 0x4d4, 0x4d8, /* DRAM_SDQS4 ~ DRAM_SDQS7 */ + 0x764, 0x770, 0x778, 0x77c, /* GPR_B0DS ~ GPR_B3DS */ + 0x780, 0x784, 0x78c, 0x748, /* GPR_B4DS ~ GPR_B7DS */ + 0x4b4, 0x4b8, 0x750, 0x760, /* SODT0, SODT1, MODE_CTL, MODE */ + 0x74c, /* GPR_ADDS */ +}; + +static const u32 imx6sl_mmdc_io_offset[] __initconst = { + 0x30c, 0x310, 0x314, 0x318, /* DQM0 ~ DQM3 */ + 0x5c4, 0x5cc, 0x5d4, 0x5d8, /* GPR_B0DS ~ GPR_B3DS */ + 0x300, 0x31c, 0x338, 0x5ac, /* CAS, RAS, SDCLK_0, GPR_ADDS */ + 0x33c, 0x340, 0x5b0, 0x5c0, /* SODT0, SODT1, MODE_CTL, MODE */ + 0x330, 0x334, 0x320, /* SDCKE0, SDCKE1, RESET */ +}; + +static const struct imx6_pm_socdata imx6q_pm_data __initconst = { + .cpu_type = MXC_CPU_IMX6Q, + .mmdc_compat = "fsl,imx6q-mmdc", + .src_compat = "fsl,imx6q-src", + .iomuxc_compat = "fsl,imx6q-iomuxc", + .gpc_compat = "fsl,imx6q-gpc", + .mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset), + .mmdc_io_offset = imx6q_mmdc_io_offset, +}; + +static const struct imx6_pm_socdata imx6dl_pm_data __initconst = { + .cpu_type = MXC_CPU_IMX6DL, + .mmdc_compat = "fsl,imx6q-mmdc", + .src_compat = "fsl,imx6q-src", + .iomuxc_compat = "fsl,imx6dl-iomuxc", + .gpc_compat = "fsl,imx6q-gpc", + .mmdc_io_num = ARRAY_SIZE(imx6dl_mmdc_io_offset), + .mmdc_io_offset = imx6dl_mmdc_io_offset, +}; + +static const struct imx6_pm_socdata imx6sl_pm_data __initconst = { + .cpu_type = MXC_CPU_IMX6SL, + .mmdc_compat = "fsl,imx6sl-mmdc", + .src_compat = "fsl,imx6sl-src", + .iomuxc_compat = "fsl,imx6sl-iomuxc", + .gpc_compat = "fsl,imx6sl-gpc", + .mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset), + .mmdc_io_offset = imx6sl_mmdc_io_offset, +}; + +/* + * This structure is for passing necessary data for low level ocram + * suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct + * definition is changed, the offset definition in + * arch/arm/mach-imx/suspend-imx6.S must be also changed accordingly, + * otherwise, the suspend to ocram function will be broken! + */ +struct imx6_cpu_pm_info { + phys_addr_t pbase; /* The physical address of pm_info. */ + phys_addr_t resume_addr; /* The physical resume address for asm code */ + u32 cpu_type; + u32 pm_info_size; /* Size of pm_info. */ + struct imx6_pm_base mmdc_base; + struct imx6_pm_base src_base; + struct imx6_pm_base iomuxc_base; + struct imx6_pm_base ccm_base; + struct imx6_pm_base gpc_base; + struct imx6_pm_base l2_base; + u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */ + u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; /* To save offset and value */ +} __aligned(8); + +void imx6q_set_int_mem_clk_lpm(void) +{ + u32 val = readl_relaxed(ccm_base + CGPR); + + val |= BM_CGPR_INT_MEM_CLK_LPM; + writel_relaxed(val, ccm_base + CGPR); +} + +static void imx6q_enable_rbc(bool enable) +{ + u32 val; + + /* + * need to mask all interrupts in GPC before + * operating RBC configurations + */ + imx_gpc_mask_all(); + + /* configure RBC enable bit */ + val = readl_relaxed(ccm_base + CCR); + val &= ~BM_CCR_RBC_EN; + val |= enable ? BM_CCR_RBC_EN : 0; + writel_relaxed(val, ccm_base + CCR); + + /* configure RBC count */ + val = readl_relaxed(ccm_base + CCR); + val &= ~BM_CCR_RBC_BYPASS_COUNT; + val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0; + writel(val, ccm_base + CCR); + + /* + * need to delay at least 2 cycles of CKIL(32K) + * due to hardware design requirement, which is + * ~61us, here we use 65us for safe + */ + udelay(65); + + /* restore GPC interrupt mask settings */ + imx_gpc_restore_all(); +} + +static void imx6q_enable_wb(bool enable) +{ + u32 val; + + /* configure well bias enable bit */ + val = readl_relaxed(ccm_base + CLPCR); + val &= ~BM_CLPCR_WB_PER_AT_LPM; + val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0; + writel_relaxed(val, ccm_base + CLPCR); + + /* configure well bias count */ + val = readl_relaxed(ccm_base + CCR); + val &= ~BM_CCR_WB_COUNT; + val |= enable ? BM_CCR_WB_COUNT : 0; + writel_relaxed(val, ccm_base + CCR); +} + +int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) +{ + struct irq_data *iomuxc_irq_data = irq_get_irq_data(32); + u32 val = readl_relaxed(ccm_base + CLPCR); + + val &= ~BM_CLPCR_LPM; + switch (mode) { + case WAIT_CLOCKED: + break; + case WAIT_UNCLOCKED: + val |= 0x1 << BP_CLPCR_LPM; + val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM; + break; + case STOP_POWER_ON: + val |= 0x2 << BP_CLPCR_LPM; + break; + case WAIT_UNCLOCKED_POWER_OFF: + val |= 0x1 << BP_CLPCR_LPM; + val &= ~BM_CLPCR_VSTBY; + val &= ~BM_CLPCR_SBYOS; + break; + case STOP_POWER_OFF: + val |= 0x2 << BP_CLPCR_LPM; + val |= 0x3 << BP_CLPCR_STBY_COUNT; + val |= BM_CLPCR_VSTBY; + val |= BM_CLPCR_SBYOS; + if (cpu_is_imx6sl()) { + val |= BM_CLPCR_BYPASS_PMIC_READY; + val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS; + } else { + val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; + } + break; + default: + return -EINVAL; + } + + /* + * ERR007265: CCM: When improper low-power sequence is used, + * the SoC enters low power mode before the ARM core executes WFI. + * + * Software workaround: + * 1) Software should trigger IRQ #32 (IOMUX) to be always pending + * by setting IOMUX_GPR1_GINT. + * 2) Software should then unmask IRQ #32 in GPC before setting CCM + * Low-Power mode. + * 3) Software should mask IRQ #32 right after CCM Low-Power mode + * is set (set bits 0-1 of CCM_CLPCR). + */ + imx_gpc_irq_unmask(iomuxc_irq_data); + writel_relaxed(val, ccm_base + CLPCR); + imx_gpc_irq_mask(iomuxc_irq_data); + + return 0; +} + +static int imx6q_suspend_finish(unsigned long val) +{ + if (!imx6_suspend_in_ocram_fn) { + cpu_do_idle(); + } else { + /* + * call low level suspend function in ocram, + * as we need to float DDR IO. + */ + local_flush_tlb_all(); + imx6_suspend_in_ocram_fn(suspend_ocram_base); + } + + return 0; +} + +static int imx6q_pm_enter(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_MEM: + imx6q_set_lpm(STOP_POWER_OFF); + imx6q_enable_wb(true); + /* + * For suspend into ocram, asm code already take care of + * RBC setting, so we do NOT need to do that here. + */ + if (!imx6_suspend_in_ocram_fn) + imx6q_enable_rbc(true); + imx_gpc_pre_suspend(); + imx_anatop_pre_suspend(); + imx_set_cpu_jump(0, v7_cpu_resume); + /* Zzz ... */ + cpu_suspend(0, imx6q_suspend_finish); + if (cpu_is_imx6q() || cpu_is_imx6dl()) + imx_smp_prepare(); + imx_anatop_post_resume(); + imx_gpc_post_resume(); + imx6q_enable_rbc(false); + imx6q_enable_wb(false); + imx6q_set_lpm(WAIT_CLOCKED); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct platform_suspend_ops imx6q_pm_ops = { + .enter = imx6q_pm_enter, + .valid = suspend_valid_only_mem, +}; + +void __init imx6q_pm_set_ccm_base(void __iomem *base) +{ + ccm_base = base; +} + +static int __init imx6_pm_get_base(struct imx6_pm_base *base, + const char *compat) +{ + struct device_node *node; + struct resource res; + int ret = 0; + + node = of_find_compatible_node(NULL, NULL, compat); + if (!node) { + ret = -ENODEV; + goto out; + } + + ret = of_address_to_resource(node, 0, &res); + if (ret) + goto put_node; + + base->pbase = res.start; + base->vbase = ioremap(res.start, resource_size(&res)); + if (!base->vbase) + ret = -ENOMEM; + +put_node: + of_node_put(node); +out: + return ret; +} + +static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata) +{ + phys_addr_t ocram_pbase; + struct device_node *node; + struct platform_device *pdev; + struct imx6_cpu_pm_info *pm_info; + struct gen_pool *ocram_pool; + unsigned long ocram_base; + int i, ret = 0; + const u32 *mmdc_offset_array; + + suspend_set_ops(&imx6q_pm_ops); + + if (!socdata) { + pr_warn("%s: invalid argument!\n", __func__); + return -EINVAL; + } + + node = of_find_compatible_node(NULL, NULL, "mmio-sram"); + if (!node) { + pr_warn("%s: failed to find ocram node!\n", __func__); + return -ENODEV; + } + + pdev = of_find_device_by_node(node); + if (!pdev) { + pr_warn("%s: failed to find ocram device!\n", __func__); + ret = -ENODEV; + goto put_node; + } + + ocram_pool = dev_get_gen_pool(&pdev->dev); + if (!ocram_pool) { + pr_warn("%s: ocram pool unavailable!\n", __func__); + ret = -ENODEV; + goto put_node; + } + + ocram_base = gen_pool_alloc(ocram_pool, MX6Q_SUSPEND_OCRAM_SIZE); + if (!ocram_base) { + pr_warn("%s: unable to alloc ocram!\n", __func__); + ret = -ENOMEM; + goto put_node; + } + + ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base); + + suspend_ocram_base = __arm_ioremap_exec(ocram_pbase, + MX6Q_SUSPEND_OCRAM_SIZE, false); + + pm_info = suspend_ocram_base; + pm_info->pbase = ocram_pbase; + pm_info->resume_addr = virt_to_phys(v7_cpu_resume); + pm_info->pm_info_size = sizeof(*pm_info); + + /* + * ccm physical address is not used by asm code currently, + * so get ccm virtual address directly, as we already have + * it from ccm driver. + */ + pm_info->ccm_base.vbase = ccm_base; + + ret = imx6_pm_get_base(&pm_info->mmdc_base, socdata->mmdc_compat); + if (ret) { + pr_warn("%s: failed to get mmdc base %d!\n", __func__, ret); + goto put_node; + } + + ret = imx6_pm_get_base(&pm_info->src_base, socdata->src_compat); + if (ret) { + pr_warn("%s: failed to get src base %d!\n", __func__, ret); + goto src_map_failed; + } + + ret = imx6_pm_get_base(&pm_info->iomuxc_base, socdata->iomuxc_compat); + if (ret) { + pr_warn("%s: failed to get iomuxc base %d!\n", __func__, ret); + goto iomuxc_map_failed; + } + + ret = imx6_pm_get_base(&pm_info->gpc_base, socdata->gpc_compat); + if (ret) { + pr_warn("%s: failed to get gpc base %d!\n", __func__, ret); + goto gpc_map_failed; + } + + ret = imx6_pm_get_base(&pm_info->l2_base, "arm,pl310-cache"); + if (ret) { + pr_warn("%s: failed to get pl310-cache base %d!\n", + __func__, ret); + goto pl310_cache_map_failed; + } + + pm_info->cpu_type = socdata->cpu_type; + pm_info->mmdc_io_num = socdata->mmdc_io_num; + mmdc_offset_array = socdata->mmdc_io_offset; + + for (i = 0; i < pm_info->mmdc_io_num; i++) { + pm_info->mmdc_io_val[i][0] = + mmdc_offset_array[i]; + pm_info->mmdc_io_val[i][1] = + readl_relaxed(pm_info->iomuxc_base.vbase + + mmdc_offset_array[i]); + } + + imx6_suspend_in_ocram_fn = fncpy( + suspend_ocram_base + sizeof(*pm_info), + &imx6_suspend, + MX6Q_SUSPEND_OCRAM_SIZE - sizeof(*pm_info)); + + goto put_node; + +pl310_cache_map_failed: + iounmap(&pm_info->gpc_base.vbase); +gpc_map_failed: + iounmap(&pm_info->iomuxc_base.vbase); +iomuxc_map_failed: + iounmap(&pm_info->src_base.vbase); +src_map_failed: + iounmap(&pm_info->mmdc_base.vbase); +put_node: + of_node_put(node); + + return ret; +} + +static void __init imx6_pm_common_init(const struct imx6_pm_socdata + *socdata) +{ + struct regmap *gpr; + int ret; + + WARN_ON(!ccm_base); + + if (IS_ENABLED(CONFIG_SUSPEND)) { + ret = imx6q_suspend_init(socdata); + if (ret) + pr_warn("%s: No DDR LPM support with suspend %d!\n", + __func__, ret); + } + + /* + * This is for SW workaround step #1 of ERR007265, see comments + * in imx6q_set_lpm for details of this errata. + * Force IOMUXC irq pending, so that the interrupt to GPC can be + * used to deassert dsm_request signal when the signal gets + * asserted unexpectedly. + */ + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); + if (!IS_ERR(gpr)) + regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT, + IMX6Q_GPR1_GINT); +} + +void __init imx6q_pm_init(void) +{ + imx6_pm_common_init(&imx6q_pm_data); +} + +void __init imx6dl_pm_init(void) +{ + imx6_pm_common_init(&imx6dl_pm_data); +} + +void __init imx6sl_pm_init(void) +{ + imx6_pm_common_init(&imx6sl_pm_data); +} diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c deleted file mode 100644 index 29e3fe6a6669..000000000000 --- a/arch/arm/mach-imx/pm-imx6q.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2011-2013 Freescale Semiconductor, Inc. - * Copyright 2011 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/mfd/syscon.h> -#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/regmap.h> -#include <linux/suspend.h> -#include <asm/cacheflush.h> -#include <asm/proc-fns.h> -#include <asm/suspend.h> -#include <asm/hardware/cache-l2x0.h> - -#include "common.h" -#include "hardware.h" - -#define CCR 0x0 -#define BM_CCR_WB_COUNT (0x7 << 16) -#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21) -#define BM_CCR_RBC_EN (0x1 << 27) - -#define CLPCR 0x54 -#define BP_CLPCR_LPM 0 -#define BM_CLPCR_LPM (0x3 << 0) -#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2) -#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) -#define BM_CLPCR_SBYOS (0x1 << 6) -#define BM_CLPCR_DIS_REF_OSC (0x1 << 7) -#define BM_CLPCR_VSTBY (0x1 << 8) -#define BP_CLPCR_STBY_COUNT 9 -#define BM_CLPCR_STBY_COUNT (0x3 << 9) -#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11) -#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16) -#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17) -#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19) -#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21) -#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22) -#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23) -#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24) -#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25) -#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) -#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) - -#define CGPR 0x64 -#define BM_CGPR_CHICKEN_BIT (0x1 << 17) - -static void __iomem *ccm_base; - -void imx6q_set_chicken_bit(void) -{ - u32 val = readl_relaxed(ccm_base + CGPR); - - val |= BM_CGPR_CHICKEN_BIT; - writel_relaxed(val, ccm_base + CGPR); -} - -static void imx6q_enable_rbc(bool enable) -{ - u32 val; - - /* - * need to mask all interrupts in GPC before - * operating RBC configurations - */ - imx_gpc_mask_all(); - - /* configure RBC enable bit */ - val = readl_relaxed(ccm_base + CCR); - val &= ~BM_CCR_RBC_EN; - val |= enable ? BM_CCR_RBC_EN : 0; - writel_relaxed(val, ccm_base + CCR); - - /* configure RBC count */ - val = readl_relaxed(ccm_base + CCR); - val &= ~BM_CCR_RBC_BYPASS_COUNT; - val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0; - writel(val, ccm_base + CCR); - - /* - * need to delay at least 2 cycles of CKIL(32K) - * due to hardware design requirement, which is - * ~61us, here we use 65us for safe - */ - udelay(65); - - /* restore GPC interrupt mask settings */ - imx_gpc_restore_all(); -} - -static void imx6q_enable_wb(bool enable) -{ - u32 val; - - /* configure well bias enable bit */ - val = readl_relaxed(ccm_base + CLPCR); - val &= ~BM_CLPCR_WB_PER_AT_LPM; - val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0; - writel_relaxed(val, ccm_base + CLPCR); - - /* configure well bias count */ - val = readl_relaxed(ccm_base + CCR); - val &= ~BM_CCR_WB_COUNT; - val |= enable ? BM_CCR_WB_COUNT : 0; - writel_relaxed(val, ccm_base + CCR); -} - -int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) -{ - struct irq_data *iomuxc_irq_data = irq_get_irq_data(32); - u32 val = readl_relaxed(ccm_base + CLPCR); - - val &= ~BM_CLPCR_LPM; - switch (mode) { - case WAIT_CLOCKED: - break; - case WAIT_UNCLOCKED: - val |= 0x1 << BP_CLPCR_LPM; - val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM; - break; - case STOP_POWER_ON: - val |= 0x2 << BP_CLPCR_LPM; - break; - case WAIT_UNCLOCKED_POWER_OFF: - val |= 0x1 << BP_CLPCR_LPM; - val &= ~BM_CLPCR_VSTBY; - val &= ~BM_CLPCR_SBYOS; - break; - case STOP_POWER_OFF: - val |= 0x2 << BP_CLPCR_LPM; - val |= 0x3 << BP_CLPCR_STBY_COUNT; - val |= BM_CLPCR_VSTBY; - val |= BM_CLPCR_SBYOS; - if (cpu_is_imx6sl()) { - val |= BM_CLPCR_BYPASS_PMIC_READY; - val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS; - } else { - val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; - } - break; - default: - return -EINVAL; - } - - /* - * ERR007265: CCM: When improper low-power sequence is used, - * the SoC enters low power mode before the ARM core executes WFI. - * - * Software workaround: - * 1) Software should trigger IRQ #32 (IOMUX) to be always pending - * by setting IOMUX_GPR1_GINT. - * 2) Software should then unmask IRQ #32 in GPC before setting CCM - * Low-Power mode. - * 3) Software should mask IRQ #32 right after CCM Low-Power mode - * is set (set bits 0-1 of CCM_CLPCR). - */ - imx_gpc_irq_unmask(iomuxc_irq_data); - writel_relaxed(val, ccm_base + CLPCR); - imx_gpc_irq_mask(iomuxc_irq_data); - - return 0; -} - -static int imx6q_suspend_finish(unsigned long val) -{ - cpu_do_idle(); - return 0; -} - -static int imx6q_pm_enter(suspend_state_t state) -{ - switch (state) { - case PM_SUSPEND_MEM: - imx6q_set_lpm(STOP_POWER_OFF); - imx6q_enable_wb(true); - imx6q_enable_rbc(true); - imx_gpc_pre_suspend(); - imx_anatop_pre_suspend(); - imx_set_cpu_jump(0, v7_cpu_resume); - /* Zzz ... */ - cpu_suspend(0, imx6q_suspend_finish); - if (cpu_is_imx6q() || cpu_is_imx6dl()) - imx_smp_prepare(); - imx_anatop_post_resume(); - imx_gpc_post_resume(); - imx6q_enable_rbc(false); - imx6q_enable_wb(false); - imx6q_set_lpm(WAIT_CLOCKED); - break; - default: - return -EINVAL; - } - - return 0; -} - -static const struct platform_suspend_ops imx6q_pm_ops = { - .enter = imx6q_pm_enter, - .valid = suspend_valid_only_mem, -}; - -void __init imx6q_pm_set_ccm_base(void __iomem *base) -{ - ccm_base = base; -} - -void __init imx6q_pm_init(void) -{ - struct regmap *gpr; - - WARN_ON(!ccm_base); - - /* - * This is for SW workaround step #1 of ERR007265, see comments - * in imx6q_set_lpm for details of this errata. - * Force IOMUXC irq pending, so that the interrupt to GPC can be - * used to deassert dsm_request signal when the signal gets - * asserted unexpectedly. - */ - gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); - if (!IS_ERR(gpr)) - regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT, - IMX6Q_GPR1_GINT); - - - suspend_set_ops(&imx6q_pm_ops); -} diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S new file mode 100644 index 000000000000..fe123b079c05 --- /dev/null +++ b/arch/arm/mach-imx/suspend-imx6.S @@ -0,0 +1,343 @@ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/linkage.h> +#include <asm/asm-offsets.h> +#include <asm/hardware/cache-l2x0.h> +#include "hardware.h" + +/* + * ==================== low level suspend ==================== + * + * Better to follow below rules to use ARM registers: + * r0: pm_info structure address; + * r1 ~ r4: for saving pm_info members; + * r5 ~ r10: free registers; + * r11: io base address. + * + * suspend ocram space layout: + * ======================== high address ====================== + * . + * . + * . + * ^ + * ^ + * ^ + * imx6_suspend code + * PM_INFO structure(imx6_cpu_pm_info) + * ======================== low address ======================= + */ + +/* + * Below offsets are based on struct imx6_cpu_pm_info + * which defined in arch/arm/mach-imx/pm-imx6q.c, this + * structure contains necessary pm info for low level + * suspend related code. + */ +#define PM_INFO_PBASE_OFFSET 0x0 +#define PM_INFO_RESUME_ADDR_OFFSET 0x4 +#define PM_INFO_CPU_TYPE_OFFSET 0x8 +#define PM_INFO_PM_INFO_SIZE_OFFSET 0xC +#define PM_INFO_MX6Q_MMDC_P_OFFSET 0x10 +#define PM_INFO_MX6Q_MMDC_V_OFFSET 0x14 +#define PM_INFO_MX6Q_SRC_P_OFFSET 0x18 +#define PM_INFO_MX6Q_SRC_V_OFFSET 0x1C +#define PM_INFO_MX6Q_IOMUXC_P_OFFSET 0x20 +#define PM_INFO_MX6Q_IOMUXC_V_OFFSET 0x24 +#define PM_INFO_MX6Q_CCM_P_OFFSET 0x28 +#define PM_INFO_MX6Q_CCM_V_OFFSET 0x2C +#define PM_INFO_MX6Q_GPC_P_OFFSET 0x30 +#define PM_INFO_MX6Q_GPC_V_OFFSET 0x34 +#define PM_INFO_MX6Q_L2_P_OFFSET 0x38 +#define PM_INFO_MX6Q_L2_V_OFFSET 0x3C +#define PM_INFO_MMDC_IO_NUM_OFFSET 0x40 +#define PM_INFO_MMDC_IO_VAL_OFFSET 0x44 + +#define MX6Q_SRC_GPR1 0x20 +#define MX6Q_SRC_GPR2 0x24 +#define MX6Q_MMDC_MAPSR 0x404 +#define MX6Q_MMDC_MPDGCTRL0 0x83c +#define MX6Q_GPC_IMR1 0x08 +#define MX6Q_GPC_IMR2 0x0c +#define MX6Q_GPC_IMR3 0x10 +#define MX6Q_GPC_IMR4 0x14 +#define MX6Q_CCM_CCR 0x0 + + .align 3 + + .macro sync_l2_cache + + /* sync L2 cache to drain L2's buffers to DRAM. */ +#ifdef CONFIG_CACHE_L2X0 + ldr r11, [r0, #PM_INFO_MX6Q_L2_V_OFFSET] + mov r6, #0x0 + str r6, [r11, #L2X0_CACHE_SYNC] +1: + ldr r6, [r11, #L2X0_CACHE_SYNC] + ands r6, r6, #0x1 + bne 1b +#endif + + .endm + + .macro resume_mmdc + + /* restore MMDC IO */ + cmp r5, #0x0 + ldreq r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET] + ldrne r11, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET] + + ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET] + ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET + add r7, r7, r0 +1: + ldr r8, [r7], #0x4 + ldr r9, [r7], #0x4 + str r9, [r11, r8] + subs r6, r6, #0x1 + bne 1b + + cmp r5, #0x0 + ldreq r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET] + ldrne r11, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET] + + cmp r3, #MXC_CPU_IMX6SL + bne 4f + + /* reset read FIFO, RST_RD_FIFO */ + ldr r7, =MX6Q_MMDC_MPDGCTRL0 + ldr r6, [r11, r7] + orr r6, r6, #(1 << 31) + str r6, [r11, r7] +2: + ldr r6, [r11, r7] + ands r6, r6, #(1 << 31) + bne 2b + + /* reset FIFO a second time */ + ldr r6, [r11, r7] + orr r6, r6, #(1 << 31) + str r6, [r11, r7] +3: + ldr r6, [r11, r7] + ands r6, r6, #(1 << 31) + bne 3b +4: + /* let DDR out of self-refresh */ + ldr r7, [r11, #MX6Q_MMDC_MAPSR] + bic r7, r7, #(1 << 21) + str r7, [r11, #MX6Q_MMDC_MAPSR] +5: + ldr r7, [r11, #MX6Q_MMDC_MAPSR] + ands r7, r7, #(1 << 25) + bne 5b + + /* enable DDR auto power saving */ + ldr r7, [r11, #MX6Q_MMDC_MAPSR] + bic r7, r7, #0x1 + str r7, [r11, #MX6Q_MMDC_MAPSR] + + .endm + +ENTRY(imx6_suspend) + ldr r1, [r0, #PM_INFO_PBASE_OFFSET] + ldr r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET] + ldr r3, [r0, #PM_INFO_CPU_TYPE_OFFSET] + ldr r4, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET] + + /* + * counting the resume address in iram + * to set it in SRC register. + */ + ldr r6, =imx6_suspend + ldr r7, =resume + sub r7, r7, r6 + add r8, r1, r4 + add r9, r8, r7 + + /* + * make sure TLB contain the addr we want, + * as we will access them after MMDC IO floated. + */ + + ldr r11, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET] + ldr r6, [r11, #0x0] + ldr r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET] + ldr r6, [r11, #0x0] + + /* use r11 to store the IO address */ + ldr r11, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET] + /* store physical resume addr and pm_info address. */ + str r9, [r11, #MX6Q_SRC_GPR1] + str r1, [r11, #MX6Q_SRC_GPR2] + + /* need to sync L2 cache before DSM. */ + sync_l2_cache + + ldr r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET] + /* + * put DDR explicitly into self-refresh and + * disable automatic power savings. + */ + ldr r7, [r11, #MX6Q_MMDC_MAPSR] + orr r7, r7, #0x1 + str r7, [r11, #MX6Q_MMDC_MAPSR] + + /* make the DDR explicitly enter self-refresh. */ + ldr r7, [r11, #MX6Q_MMDC_MAPSR] + orr r7, r7, #(1 << 21) + str r7, [r11, #MX6Q_MMDC_MAPSR] + +poll_dvfs_set: + ldr r7, [r11, #MX6Q_MMDC_MAPSR] + ands r7, r7, #(1 << 25) + beq poll_dvfs_set + + ldr r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET] + ldr r6, =0x0 + ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET] + ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET + add r8, r8, r0 + /* i.MX6SL's last 3 IOs need special setting */ + cmp r3, #MXC_CPU_IMX6SL + subeq r7, r7, #0x3 +set_mmdc_io_lpm: + ldr r9, [r8], #0x8 + str r6, [r11, r9] + subs r7, r7, #0x1 + bne set_mmdc_io_lpm + + cmp r3, #MXC_CPU_IMX6SL + bne set_mmdc_io_lpm_done + ldr r6, =0x1000 + ldr r9, [r8], #0x8 + str r6, [r11, r9] + ldr r9, [r8], #0x8 + str r6, [r11, r9] + ldr r6, =0x80000 + ldr r9, [r8] + str r6, [r11, r9] +set_mmdc_io_lpm_done: + + /* + * mask all GPC interrupts before + * enabling the RBC counters to + * avoid the counter starting too + * early if an interupt is already + * pending. + */ + ldr r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET] + ldr r6, [r11, #MX6Q_GPC_IMR1] + ldr r7, [r11, #MX6Q_GPC_IMR2] + ldr r8, [r11, #MX6Q_GPC_IMR3] + ldr r9, [r11, #MX6Q_GPC_IMR4] + + ldr r10, =0xffffffff + str r10, [r11, #MX6Q_GPC_IMR1] + str r10, [r11, #MX6Q_GPC_IMR2] + str r10, [r11, #MX6Q_GPC_IMR3] + str r10, [r11, #MX6Q_GPC_IMR4] + + /* + * enable the RBC bypass counter here + * to hold off the interrupts. RBC counter + * = 32 (1ms), Minimum RBC delay should be + * 400us for the analog LDOs to power down. + */ + ldr r11, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET] + ldr r10, [r11, #MX6Q_CCM_CCR] + bic r10, r10, #(0x3f << 21) + orr r10, r10, #(0x20 << 21) + str r10, [r11, #MX6Q_CCM_CCR] + + /* enable the counter. */ + ldr r10, [r11, #MX6Q_CCM_CCR] + orr r10, r10, #(0x1 << 27) + str r10, [r11, #MX6Q_CCM_CCR] + + /* unmask all the GPC interrupts. */ + ldr r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET] + str r6, [r11, #MX6Q_GPC_IMR1] + str r7, [r11, #MX6Q_GPC_IMR2] + str r8, [r11, #MX6Q_GPC_IMR3] + str r9, [r11, #MX6Q_GPC_IMR4] + + /* + * now delay for a short while (3usec) + * ARM is at 1GHz at this point + * so a short loop should be enough. + * this delay is required to ensure that + * the RBC counter can start counting in + * case an interrupt is already pending + * or in case an interrupt arrives just + * as ARM is about to assert DSM_request. + */ + ldr r6, =2000 +rbc_loop: + subs r6, r6, #0x1 + bne rbc_loop + + /* Zzz, enter stop mode */ + wfi + nop + nop + nop + nop + + /* + * run to here means there is pending + * wakeup source, system should auto + * resume, we need to restore MMDC IO first + */ + mov r5, #0x0 + resume_mmdc + + /* return to suspend finish */ + mov pc, lr + +resume: + /* invalidate L1 I-cache first */ + mov r6, #0x0 + mcr p15, 0, r6, c7, c5, 0 + mcr p15, 0, r6, c7, c5, 6 + /* enable the Icache and branch prediction */ + mov r6, #0x1800 + mcr p15, 0, r6, c1, c0, 0 + isb + + /* get physical resume address from pm_info. */ + ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET] + /* clear core0's entry and parameter */ + ldr r11, [r0, #PM_INFO_MX6Q_SRC_P_OFFSET] + mov r7, #0x0 + str r7, [r11, #MX6Q_SRC_GPR1] + str r7, [r11, #MX6Q_SRC_GPR2] + + ldr r3, [r0, #PM_INFO_CPU_TYPE_OFFSET] + mov r5, #0x1 + resume_mmdc + + mov pc, lr +ENDPROC(imx6_suspend) + +/* + * The following code must assume it is running from physical address + * where absolute virtual addresses to the data section have to be + * turned into relative ones. + */ + +ENTRY(v7_cpu_resume) + bl v7_invalidate_l1 +#ifdef CONFIG_CACHE_L2X0 + bl l2c310_early_resume +#endif + b cpu_resume +ENDPROC(v7_cpu_resume) diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index 5e3027d3692f..3b0733edb68c 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c @@ -124,7 +124,7 @@ void __init imx_init_l2cache(void) } /* Configure the L2 PREFETCH and POWER registers */ - val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); + val = readl_relaxed(l2x0_base + L310_PREFETCH_CTRL); val |= 0x70800000; /* * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0 @@ -137,14 +137,12 @@ void __init imx_init_l2cache(void) */ if (cpu_is_imx6q()) val &= ~(1 << 30 | 1 << 23); - writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL); - val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN; - writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL); + writel_relaxed(val, l2x0_base + L310_PREFETCH_CTRL); iounmap(l2x0_base); of_node_put(np); out: - l2x0_of_init(0, ~0UL); + l2x0_of_init(0, ~0); } #endif diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index 1a3a5f615770..bed081e58262 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c @@ -25,8 +25,12 @@ #include <linux/irq.h> #include <linux/clockchips.h> #include <linux/clk.h> +#include <linux/delay.h> #include <linux/err.h> #include <linux/sched_clock.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <asm/mach/time.h> @@ -116,11 +120,22 @@ static u64 notrace mxc_read_sched_clock(void) return sched_clock_reg ? __raw_readl(sched_clock_reg) : 0; } +static struct delay_timer imx_delay_timer; + +static unsigned long imx_read_current_timer(void) +{ + return __raw_readl(sched_clock_reg); +} + static int __init mxc_clocksource_init(struct clk *timer_clk) { unsigned int c = clk_get_rate(timer_clk); void __iomem *reg = timer_base + (timer_is_v2() ? V2_TCN : MX1_2_TCN); + imx_delay_timer.read_current_timer = &imx_read_current_timer; + imx_delay_timer.freq = c; + register_current_timer_delay(&imx_delay_timer); + sched_clock_reg = reg; sched_clock_register(mxc_read_sched_clock, 32, c); @@ -316,3 +331,15 @@ void __init mxc_timer_init(void __iomem *base, int irq) /* Make irqs happen */ setup_irq(irq, &mxc_timer_irq); } + +void __init mxc_timer_init_dt(struct device_node *np) +{ + void __iomem *base; + int irq; + + base = of_iomap(np, 0); + WARN_ON(!base); + irq = irq_of_parse_and_map(np, 0); + + mxc_timer_init(base, irq); +} diff --git a/arch/arm/mach-imx/tzic.c b/arch/arm/mach-imx/tzic.c index 8183178d5aa3..7828af4b2022 100644 --- a/arch/arm/mach-imx/tzic.c +++ b/arch/arm/mach-imx/tzic.c @@ -125,7 +125,7 @@ static __init void tzic_init_gc(int idx, unsigned int irq_start) irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); } -asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs) +static void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs) { u32 stat; int i, irqofs, handled; @@ -189,6 +189,8 @@ void __init tzic_init_irq(void __iomem *irqbase) for (i = 0; i < 4; i++, irq_base += 32) tzic_init_gc(i, irq_base); + set_handle_irq(tzic_handle_irq); + #ifdef CONFIG_FIQ /* Initialize FIQ */ init_FIQ(FIQ_START); |