Commit 3e0d0b81 authored by Kevin Hilman's avatar Kevin Hilman

Merge tag 'imx-soc-4.2' of...

Merge tag 'imx-soc-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into next/soc

The i.MX SoC updates for 4.2:
 - Add new SoC i.MX7D support, which integrates two Cortex-A7 and one
   Cortex-M4 cores.
 - Support suspend from IRAM on i.MX53, so that DDR pins can be set to
   high impedance for more power saving during suspend.
 - Move i.MX clock drivers from arch/arm/mach-imx to drivers/clk/imx.
 - Move i.MX GPT timer driver from arch/arm/mach-imx into
   drivers/clocksource.
 - A couple of clock driver update for VF610 and i.MX6Q.
 - A few random code correction and improvement.

* tag 'imx-soc-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux: (44 commits)
  ARM: imx: imx7d requires anatop
  clocksource: timer-imx-gpt: remove include of <asm/mach/time.h>
  ARM: imx: move timer driver into drivers/clocksource
  ARM: imx: remove platform headers from timer driver
  ARM: imx: provide gpt device specific irq functions
  ARM: imx: get rid of variable timer_base
  ARM: imx: define gpt register offset per device type
  ARM: imx: move clock event variables into imx_timer
  ARM: imx: set up .set_next_event hook via imx_gpt_data
  ARM: imx: setup tctl register in device specific function
  ARM: imx: initialize gpt device type for DT boot
  ARM: imx: define an enum for gpt timer device type
  ARM: imx: move timer resources into a structure
  ARM: imx: use relaxed IO accessor in timer driver
  ARM: imx: make imx51/3 suspend optional
  ARM: clk-imx6q: refine sata's parent
  ARM: imx: clk-v610: Add clock for I2C2 and I2C3
  ARM: mach-imx: iomux-imx31: Use DECLARE_BITMAP
  ARM: imx: add imx7d clk tree support
  ARM: clk: imx: update pllv3 to support imx7
  ...

 Conflicts:
	arch/arm/mach-imx/Kconfig
parents 2f69b1a4 0be5da9d
......@@ -1044,6 +1044,8 @@ F: arch/arm/mach-imx/
F: arch/arm/mach-mxs/
F: arch/arm/boot/dts/imx*
F: arch/arm/configs/imx*_defconfig
F: drivers/clk/imx/
F: include/soc/imx/
ARM/FREESCALE VYBRID ARM ARCHITECTURE
M: Shawn Guo <shawn.guo@linaro.org>
......
......@@ -410,6 +410,13 @@ choice
Say Y here if you want kernel low-level debugging support
on i.MX6SX.
config DEBUG_IMX7D_UART
bool "i.MX7D Debug UART"
depends on SOC_IMX7D
help
Say Y here if you want kernel low-level debugging support
on i.MX7D.
config DEBUG_KEYSTONE_UART0
bool "Kernel low-level debugging on KEYSTONE2 using UART0"
depends on ARCH_KEYSTONE
......@@ -1260,7 +1267,8 @@ config DEBUG_IMX_UART_PORT
DEBUG_IMX53_UART || \
DEBUG_IMX6Q_UART || \
DEBUG_IMX6SL_UART || \
DEBUG_IMX6SX_UART
DEBUG_IMX6SX_UART || \
DEBUG_IMX7D_UART
default 1
depends on ARCH_MXC
help
......@@ -1310,7 +1318,8 @@ config DEBUG_LL_INCLUDE
DEBUG_IMX53_UART ||\
DEBUG_IMX6Q_UART || \
DEBUG_IMX6SL_UART || \
DEBUG_IMX6SX_UART
DEBUG_IMX6SX_UART || \
DEBUG_IMX7D_UART
default "debug/ks8695.S" if DEBUG_KS8695_UART
default "debug/msm.S" if DEBUG_QCOM_UARTDM
default "debug/netx.S" if DEBUG_NETX_UART
......
/*
* Copyright (C) 2012 Freescale Semiconductor, Inc.
* Copyright (C) 2012-2015 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
......@@ -90,6 +90,16 @@
#define IMX6SX_UART_BASE_ADDR(n) IMX6SX_UART##n##_BASE_ADDR
#define IMX6SX_UART_BASE(n) IMX6SX_UART_BASE_ADDR(n)
#define IMX7D_UART1_BASE_ADDR 0x30860000
#define IMX7D_UART2_BASE_ADDR 0x30890000
#define IMX7D_UART3_BASE_ADDR 0x30880000
#define IMX7D_UART4_BASE_ADDR 0x30a60000
#define IMX7D_UART5_BASE_ADDR 0x30a70000
#define IMX7D_UART6_BASE_ADDR 0x30a80000
#define IMX7D_UART7_BASE_ADDR 0x30a90000
#define IMX7D_UART_BASE_ADDR(n) IMX7D_UART##n##_BASE_ADDR
#define IMX7D_UART_BASE(n) IMX7D_UART_BASE_ADDR(n)
#define IMX_DEBUG_UART_BASE(soc) soc##_UART_BASE(CONFIG_DEBUG_IMX_UART_PORT)
#ifdef CONFIG_DEBUG_IMX1_UART
......@@ -114,6 +124,9 @@
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SL)
#elif defined(CONFIG_DEBUG_IMX6SX_UART)
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX6SX)
#elif defined(CONFIG_DEBUG_IMX7D_UART)
#define UART_PADDR IMX_DEBUG_UART_BASE(IMX7D)
#endif
#endif /* __DEBUG_IMX_UART_H */
......@@ -2,7 +2,7 @@ menuconfig ARCH_MXC
bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7 || ARM_SINGLE_ARMV7M
select ARCH_REQUIRE_GPIOLIB
select ARM_CPU_SUSPEND if PM
select CLKSRC_MMIO
select CLKSRC_IMX_GPT
select GENERIC_IRQ_CHIP
select PINCTRL
select PM_OPP if PM
......@@ -582,6 +582,15 @@ config SOC_IMX6SX
help
This enables support for Freescale i.MX6 SoloX processor.
config SOC_IMX7D
bool "i.MX7 Dual support"
select PINCTRL_IMX7D
select ARM_GIC
select HAVE_IMX_ANATOP
select HAVE_IMX_MMDC
help
This enables support for Freescale i.MX7 Dual processor.
config SOC_LS1021A
bool "Freescale LS1021A support"
select ARM_GIC
......
obj-y := time.o cpu.o system.o irq-common.o
obj-y := cpu.o system.o irq-common.o
obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
obj-$(CONFIG_SOC_IMX1) += mm-imx1.o
obj-$(CONFIG_SOC_IMX21) += mm-imx21.o
obj-$(CONFIG_SOC_IMX25) += clk-imx25.o cpu-imx25.o mach-imx25.o
obj-$(CONFIG_SOC_IMX25) += cpu-imx25.o mach-imx25.o
obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
obj-$(CONFIG_SOC_IMX27) += mm-imx27.o ehci-imx27.o
obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o ehci-imx35.o pm-imx3.o
imx5-pm-$(CONFIG_PM) += pm-imx5.o
obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o clk-cpu.o $(imx5-pm-y)
obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
clk-pfd.o clk-busy.o clk.o \
clk-fixup-div.o clk-fixup-mux.o \
clk-gate-exclusive.o
obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o $(imx5-pm-y)
obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
......@@ -87,13 +82,15 @@ AFLAGS_headsmp.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
endif
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) += mach-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o
obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o
obj-$(CONFIG_SOC_IMX7D) += mach-imx7d.o
ifeq ($(CONFIG_SUSPEND),y)
AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o
endif
obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
......@@ -101,7 +98,7 @@ obj-$(CONFIG_SOC_IMX50) += mach-imx50.o
obj-$(CONFIG_SOC_IMX51) += mach-imx51.o
obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o
obj-$(CONFIG_SOC_VF610) += mach-vf610.o
obj-$(CONFIG_SOC_LS1021A) += mach-ls1021a.o
......
/*
* Copyright (C) 2013 Freescale Semiconductor, Inc.
* Copyright (C) 2013-2015 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
......@@ -28,6 +28,7 @@
#define ANADIG_USB2_CHRG_DETECT 0x210
#define ANADIG_DIGPROG 0x260
#define ANADIG_DIGPROG_IMX6SL 0x280
#define ANADIG_DIGPROG_IMX7D 0x800
#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000
#define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN 0x8
......@@ -121,6 +122,8 @@ void __init imx_init_revision_from_anatop(void)
WARN_ON(!anatop_base);
if (of_device_is_compatible(np, "fsl,imx6sl-anatop"))
offset = ANADIG_DIGPROG_IMX6SL;
if (of_device_is_compatible(np, "fsl,imx7d-anatop"))
offset = ANADIG_DIGPROG_IMX7D;
digprog = readl_relaxed(anatop_base + offset);
iounmap(anatop_base);
......
......@@ -44,7 +44,6 @@ void imx27_soc_init(void);
void imx31_soc_init(void);
void imx35_soc_init(void);
void epit_timer_init(void __iomem *base, int irq);
void mxc_timer_init(void __iomem *, int);
int mx1_clocks_init(unsigned long fref);
int mx21_clocks_init(unsigned long lref, unsigned long fref);
int mx27_clocks_init(unsigned long fref);
......@@ -56,13 +55,10 @@ struct platform_device *mxc_register_gpio(char *name, int id,
void mxc_set_cpu_type(unsigned int type);
void mxc_restart(enum reboot_mode, const char *);
void mxc_arch_reset_init(void __iomem *);
int mx51_revision(void);
int mx53_revision(void);
void imx_set_aips(void __iomem *);
void imx_aips_allow_unprivileged_access(const char *compat);
int mxc_device_init(void);
void imx_set_soc_revision(unsigned int rev);
unsigned int imx_get_soc_revision(void);
void imx_init_revision_from_anatop(void);
struct device *imx_soc_device_init(void);
void imx6_enable_rbc(bool enable);
......@@ -87,7 +83,6 @@ 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 imx_enable_cpu(int cpu, bool enable);
void imx_set_cpu_jump(int cpu, void *jump_addr);
......@@ -111,7 +106,7 @@ void imx_gpc_hwirq_unmask(unsigned int hwirq);
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);
int imx6_set_lpm(enum mxc_cpu_pwr_mode mode);
void imx6q_set_int_mem_clk_lpm(bool enable);
void imx6sl_set_wait_clk(bool enter);
int imx_mmdc_get_ddr_type(void);
......@@ -121,26 +116,28 @@ int imx_cpu_kill(unsigned int cpu);
#ifdef CONFIG_SUSPEND
void v7_cpu_resume(void);
void imx53_suspend(void __iomem *ocram_vbase);
extern const u32 imx53_suspend_sz;
void imx6_suspend(void __iomem *ocram_vbase);
#else
static inline void v7_cpu_resume(void) {}
static inline void imx53_suspend(void __iomem *ocram_vbase) {}
static const u32 imx53_suspend_sz;
static inline void imx6_suspend(void __iomem *ocram_vbase) {}
#endif
void imx6_pm_ccm_init(const char *ccm_compat);
void imx6q_pm_init(void);
void imx6dl_pm_init(void);
void imx6sl_pm_init(void);
void imx6sx_pm_init(void);
void imx6q_pm_set_ccm_base(void __iomem *base);
#ifdef CONFIG_PM
void imx51_pm_init(void);
void imx53_pm_init(void);
void imx5_pm_set_ccm_base(void __iomem *base);
#else
static inline void imx51_pm_init(void) {}
static inline void imx53_pm_init(void) {}
static inline void imx5_pm_set_ccm_base(void __iomem *base) {}
#endif
#ifdef CONFIG_NEON
......
......@@ -130,6 +130,9 @@ struct device * __init imx_soc_device_init(void)
case MXC_CPU_IMX6Q:
soc_id = "i.MX6Q";
break;
case MXC_CPU_IMX7D:
soc_id = "i.MX7D";
break;
default:
soc_id = "Unknown";
}
......
......@@ -27,9 +27,9 @@ static int imx6q_enter_wait(struct cpuidle_device *dev,
*/
if (!spin_trylock(&master_lock))
goto idle;
imx6q_set_lpm(WAIT_UNCLOCKED);
imx6_set_lpm(WAIT_UNCLOCKED);
cpu_do_idle();
imx6q_set_lpm(WAIT_CLOCKED);
imx6_set_lpm(WAIT_CLOCKED);
spin_unlock(&master_lock);
goto done;
}
......
......@@ -16,7 +16,7 @@
static int imx6sl_enter_wait(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
imx6q_set_lpm(WAIT_UNCLOCKED);
imx6_set_lpm(WAIT_UNCLOCKED);
/*
* Software workaround for ERR005311, see function
* description for details.
......@@ -24,7 +24,7 @@ static int imx6sl_enter_wait(struct cpuidle_device *dev,
imx6sl_set_wait_clk(true);
cpu_do_idle();
imx6sl_set_wait_clk(false);
imx6q_set_lpm(WAIT_CLOCKED);
imx6_set_lpm(WAIT_CLOCKED);
return index;
}
......
......@@ -25,7 +25,7 @@ static int imx6sx_idle_finish(unsigned long val)
static int imx6sx_enter_wait(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
imx6q_set_lpm(WAIT_UNCLOCKED);
imx6_set_lpm(WAIT_UNCLOCKED);
switch (index) {
case 1:
......@@ -50,7 +50,7 @@ static int imx6sx_enter_wait(struct cpuidle_device *dev,
break;
}
imx6q_set_lpm(WAIT_CLOCKED);
imx6_set_lpm(WAIT_CLOCKED);
return index;
}
......
......@@ -227,7 +227,7 @@ static int imx_gpc_domain_alloc(struct irq_domain *domain,
return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
}
static struct irq_domain_ops imx_gpc_domain_ops = {
static const struct irq_domain_ops imx_gpc_domain_ops = {
.xlate = imx_gpc_domain_xlate,
.alloc = imx_gpc_domain_alloc,
.free = irq_domain_free_irqs_common,
......
......@@ -22,6 +22,7 @@
#ifndef __ASSEMBLY__
#include <asm/io.h>
#include <soc/imx/revision.h>
#endif
#include <asm/sizes.h>
......
......@@ -40,7 +40,7 @@ static DEFINE_SPINLOCK(gpio_mux_lock);
#define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
static unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
static DECLARE_BITMAP(mxc_pin_alloc_map, NB_PORTS * 32);
/*
* set the mode for a IOMUX pin.
*/
......
......@@ -393,6 +393,7 @@ static void __init imx6q_init_irq(void)
imx_init_l2cache();
imx_src_init();
irqchip_init();
imx6_pm_ccm_init("fsl,imx6q-ccm");
}
static const char * const imx6q_dt_compat[] __initconst = {
......
......@@ -66,6 +66,7 @@ static void __init imx6sl_init_irq(void)
imx_init_l2cache();
imx_src_init();
irqchip_init();
imx6_pm_ccm_init("fsl,imx6sl-ccm");
}
static const char * const imx6sl_dt_compat[] __initconst = {
......
......@@ -86,6 +86,7 @@ static void __init imx6sx_init_irq(void)
imx_init_l2cache();
imx_src_init();
irqchip_init();
imx6_pm_ccm_init("fsl,imx6sx-ccm");
}
static void __init imx6sx_init_late(void)
......
/*
* Copyright (C) 2015 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 imx7d_init_machine(void)
{
struct device *parent;
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, NULL);
imx_anatop_init();
}
static void __init imx7d_init_irq(void)
{
imx_init_revision_from_anatop();
imx_src_init();
irqchip_init();
}
static const char *imx7d_dt_compat[] __initconst = {
"fsl,imx7d",
NULL,
};
DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual (Device Tree)")
.init_irq = imx7d_init_irq,
.init_machine = imx7d_init_machine,
.dt_compat = imx7d_dt_compat,
MACHINE_END
......@@ -17,6 +17,8 @@
#include <linux/of_address.h>
#include <linux/of_device.h>
#include "common.h"
#define MMDC_MAPSR 0x404
#define BP_MMDC_MAPSR_PSD 0
#define BP_MMDC_MAPSR_PSS 4
......
......@@ -231,8 +231,4 @@
#define MX27_DMA_REQ_SDHC3 36
#define MX27_DMA_REQ_NFC 37
#ifndef __ASSEMBLY__
extern int mx27_revision(void);
#endif
#endif /* ifndef __MACH_MX27_H__ */
......@@ -185,11 +185,4 @@
#define MX3x_PROD_SIGNATURE 0x1 /* For MX31 */
/* Mandatory defines used globally */
#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
extern int mx35_revision(void);
extern int mx31_revision(void);
#endif
#endif /* ifndef __MACH_MX3x_H__ */
/*
* Copyright 2004-2007, 2010 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2004-2007, 2010-2015 Freescale Semiconductor, Inc.
* Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
*
* This program is free software; you can redistribute it and/or
......@@ -38,22 +38,7 @@
#define MXC_CPU_IMX6DL 0x61
#define MXC_CPU_IMX6SX 0x62
#define MXC_CPU_IMX6Q 0x63
#define IMX_CHIP_REVISION_1_0 0x10
#define IMX_CHIP_REVISION_1_1 0x11
#define IMX_CHIP_REVISION_1_2 0x12
#define IMX_CHIP_REVISION_1_3 0x13
#define IMX_CHIP_REVISION_1_4 0x14
#define IMX_CHIP_REVISION_1_5 0x15
#define IMX_CHIP_REVISION_2_0 0x20
#define IMX_CHIP_REVISION_2_1 0x21
#define IMX_CHIP_REVISION_2_2 0x22
#define IMX_CHIP_REVISION_2_3 0x23
#define IMX_CHIP_REVISION_3_0 0x30
#define IMX_CHIP_REVISION_3_1 0x31
#define IMX_CHIP_REVISION_3_2 0x32
#define IMX_CHIP_REVISION_3_3 0x33
#define IMX_CHIP_REVISION_UNKNOWN 0xff
#define MXC_CPU_IMX7D 0x72
#define IMX_DDR_TYPE_LPDDR2 1
......@@ -185,6 +170,11 @@ static inline bool cpu_is_imx6q(void)
return __mxc_cpu_type == MXC_CPU_IMX6Q;
}
static inline bool cpu_is_imx7d(void)
{
return __mxc_cpu_type == MXC_CPU_IMX7D;
}
struct cpu_op {
u32 cpu_rate;
};
......
......@@ -13,7 +13,14 @@
#include <linux/io.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/genalloc.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <asm/cacheflush.h>
#include <asm/fncpy.h>
#include <asm/system_misc.h>
#include <asm/tlbflush.h>
......@@ -49,29 +56,91 @@
*/
#define IMX5_DEFAULT_CPU_IDLE_STATE WAIT_UNCLOCKED_POWER_OFF
struct imx5_suspend_io_state {
u32 offset;
u32 clear;
u32 set;
u32 saved_value;
};
struct imx5_pm_data {
phys_addr_t ccm_addr;
phys_addr_t cortex_addr;
phys_addr_t gpc_addr;
phys_addr_t m4if_addr;
phys_addr_t iomuxc_addr;
void (*suspend_asm)(void __iomem *ocram_vbase);
const u32 *suspend_asm_sz;
const struct imx5_suspend_io_state *suspend_io_config;
int suspend_io_count;
};
static const struct imx5_suspend_io_state imx53_suspend_io_config[] = {
#define MX53_DSE_HIGHZ_MASK (0x7 << 19)
{.offset = 0x584, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM0 */
{.offset = 0x594, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM1 */
{.offset = 0x560, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM2 */
{.offset = 0x554, .clear = MX53_DSE_HIGHZ_MASK}, /* DQM3 */
{.offset = 0x574, .clear = MX53_DSE_HIGHZ_MASK}, /* CAS */
{.offset = 0x588, .clear = MX53_DSE_HIGHZ_MASK}, /* RAS */
{.offset = 0x578, .clear = MX53_DSE_HIGHZ_MASK}, /* SDCLK_0 */
{.offset = 0x570, .clear = MX53_DSE_HIGHZ_MASK}, /* SDCLK_1 */
{.offset = 0x580, .clear = MX53_DSE_HIGHZ_MASK}, /* SDODT0 */
{.offset = 0x564, .clear = MX53_DSE_HIGHZ_MASK}, /* SDODT1 */
{.offset = 0x57c, .clear = MX53_DSE_HIGHZ_MASK}, /* SDQS0 */
{.offset = 0x590, .clear = MX53_DSE_HIGHZ_MASK}, /* SDQS1 */
{.offset = 0x568, .clear = MX53_DSE_HIGHZ_MASK}, /* SDQS2 */
{.offset = 0x558, .clear = MX53_DSE_HIGHZ_MASK}, /* SDSQ3 */
{.offset = 0x6f0, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_ADDS */
{.offset = 0x718, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_BODS */
{.offset = 0x71c, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_B1DS */
{.offset = 0x728, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_B2DS */
{.offset = 0x72c, .clear = MX53_DSE_HIGHZ_MASK}, /* GRP_B3DS */
/* Controls the CKE signal which is required to leave self refresh */
{.offset = 0x720, .clear = MX53_DSE_HIGHZ_MASK, .set = 1 << 19}, /* CTLDS */
};
static const struct imx5_pm_data imx51_pm_data __initconst = {
.ccm_addr = 0x73fd4000,
.cortex_addr = 0x83fa0000,
.gpc_addr = 0x73fd8000,
};
static const struct imx5_pm_data imx53_pm_data __initconst = {
.ccm_addr = 0x53fd4000,
.cortex_addr = 0x63fa0000,
.gpc_addr = 0x53fd8000,
.m4if_addr = 0x63fd8000,
.iomuxc_addr = 0x53fa8000,
.suspend_asm = &imx53_suspend,
.suspend_asm_sz = &imx53_suspend_sz,
.suspend_io_config = imx53_suspend_io_config,
.suspend_io_count = ARRAY_SIZE(imx53_suspend_io_config),
};
#define MX5_MAX_SUSPEND_IOSTATE ARRAY_SIZE(imx53_suspend_io_config)
/*
* This structure is for passing necessary data for low level ocram
* suspend code(arch/arm/mach-imx/suspend-imx53.S), if this struct
* definition is changed, the offset definition in that file
* must be also changed accordingly otherwise, the suspend to ocram
* function will be broken!
*/
struct imx5_cpu_suspend_info {
void __iomem *m4if_base;
void __iomem *iomuxc_base;
u32 io_count;
struct imx5_suspend_io_state io_state[MX5_MAX_SUSPEND_IOSTATE];
} __aligned(8);
static void __iomem *ccm_base;
static void __iomem *cortex_base;
static void __iomem *gpc_base;
void __init imx5_pm_set_ccm_base(void __iomem *base)
{
ccm_base = base;
}
static void __iomem *suspend_ocram_base;
static void (*imx5_suspend_in_ocram_fn)(void __iomem *ocram_vbase);
/*
* set cpu low power mode before WFI instruction. This function is called
......@@ -161,8 +230,15 @@ static int mx5_suspend_enter(suspend_state_t state)
/*clear the EMPGC0/1 bits */
__raw_writel(0, gpc_base + MXC_SRPG_EMPGC0_SRPGCR);
__raw_writel(0, gpc_base + MXC_SRPG_EMPGC1_SRPGCR);
if (imx5_suspend_in_ocram_fn)
imx5_suspend_in_ocram_fn(suspend_ocram_base);
else
cpu_do_idle();
} else {
cpu_do_idle();
}
cpu_do_idle();
/* return registers to default idle state */
mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
......@@ -194,6 +270,111 @@ static void imx5_pm_idle(void)
imx5_cpu_do_idle();
}
static int __init imx_suspend_alloc_ocram(
size_t size,
void __iomem **virt_out,
phys_addr_t *phys_out)
{
struct device_node *node;
struct platform_device *pdev;
struct gen_pool *ocram_pool;
unsigned long ocram_base;
void __iomem *virt;
phys_addr_t phys;
int ret = 0;
/* Copied from imx6: TODO factorize */
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, size);
if (!ocram_base) {
pr_warn("%s: unable to alloc ocram!\n", __func__);
ret = -ENOMEM;
goto put_node;
}
phys = gen_pool_virt_to_phys(ocram_pool, ocram_base);
virt = __arm_ioremap_exec(phys, size, false);
if (phys_out)
*phys_out = phys;
if (virt_out)
*virt_out = virt;
put_node:
of_node_put(node);
return ret;
}
static int __init imx5_suspend_init(const struct imx5_pm_data *soc_data)
{
struct imx5_cpu_suspend_info *suspend_info;
int ret;
/* Need this to avoid compile error due to const typeof in fncpy.h */
void (*suspend_asm)(void __iomem *) = soc_data->suspend_asm;
if (!suspend_asm)
return 0;
if (!soc_data->suspend_asm_sz || !*soc_data->suspend_asm_sz)
return -EINVAL;
ret = imx_suspend_alloc_ocram(
*soc_data->suspend_asm_sz + sizeof(*suspend_info),
&suspend_ocram_base, NULL);
if (ret)
return ret;
suspend_info = suspend_ocram_base;
suspend_info->io_count = soc_data->suspend_io_count;
memcpy(suspend_info->io_state, soc_data->suspend_io_config,
sizeof(*suspend_info->io_state) * soc_data->suspend_io_count);
suspend_info->m4if_base = ioremap(soc_data->m4if_addr, SZ_16K);
if (!suspend_info->m4if_base) {
ret = -ENOMEM;
goto failed_map_m4if;
}
suspend_info->iomuxc_base = ioremap(soc_data->iomuxc_addr, SZ_16K);
if (!suspend_info->iomuxc_base) {
ret = -ENOMEM;
goto failed_map_iomuxc;
}
imx5_suspend_in_ocram_fn = fncpy(
suspend_ocram_base + sizeof(*suspend_info),
suspend_asm,
*soc_data->suspend_asm_sz);
return 0;
failed_map_iomuxc:
iounmap(suspend_info->m4if_base);
failed_map_m4if:
return ret;
}
static int __init imx5_pm_common_init(const struct imx5_pm_data *data)
{
int ret;
......@@ -208,6 +389,7 @@ static int __init imx5_pm_common_init(const struct imx5_pm_data *data)
arm_pm_idle = imx5_pm_idle;
ccm_base = ioremap(data->ccm_addr, SZ_16K);
cortex_base = ioremap(data->cortex_addr, SZ_16K);
gpc_base = ioremap(data->gpc_addr, SZ_16K);
WARN_ON(!ccm_base || !cortex_base || !gpc_base);
......@@ -219,6 +401,11 @@ static int __init imx5_pm_common_init(const struct imx5_pm_data *data)
if (ret)
pr_warn("%s: cpuidle init failed %d\n", __func__, ret);
ret = imx5_suspend_init(data);
if (ret)
pr_warn("%s: No DDR LPM support with suspend %d!\n",
__func__, ret);
suspend_set_ops(&mx5_suspend_ops);
return 0;
......@@ -226,10 +413,12 @@ static int __init imx5_pm_common_init(const struct imx5_pm_data *data)
void __init imx51_pm_init(void)
{
imx5_pm_common_init(&imx51_pm_data);
if (IS_ENABLED(CONFIG_SOC_IMX51))
imx5_pm_common_init(&imx51_pm_data);
}
void __init imx53_pm_init(void)
{
imx5_pm_common_init(&imx53_pm_data);
if (IS_ENABLED(CONFIG_SOC_IMX53))
imx5_pm_common_init(&imx53_pm_data);
}
......@@ -255,7 +255,7 @@ static void imx6q_enable_wb(bool enable)
writel_relaxed(val, ccm_base + CCR);
}
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
{
u32 val = readl_relaxed(ccm_base + CLPCR);
......@@ -340,7 +340,7 @@ static int imx6q_pm_enter(suspend_state_t state)
{
switch (state) {
case PM_SUSPEND_STANDBY:
imx6q_set_lpm(STOP_POWER_ON);
imx6_set_lpm(STOP_POWER_ON);
imx6q_set_int_mem_clk_lpm(true);
imx_gpc_pre_suspend(false);
if (cpu_is_imx6sl())
......@@ -350,10 +350,10 @@ static int imx6q_pm_enter(suspend_state_t state)
if (cpu_is_imx6sl())
imx6sl_set_wait_clk(false);
imx_gpc_post_resume();
imx6q_set_lpm(WAIT_CLOCKED);
imx6_set_lpm(WAIT_CLOCKED);
break;
case PM_SUSPEND_MEM:
imx6q_set_lpm(STOP_POWER_OFF);
imx6_set_lpm(STOP_POWER_OFF);
imx6q_set_int_mem_clk_lpm(false);
imx6q_enable_wb(true);
/*
......@@ -373,7 +373,7 @@ static int imx6q_pm_enter(suspend_state_t state)
imx6_enable_rbc(false);
imx6q_enable_wb(false);
imx6q_set_int_mem_clk_lpm(true);
imx6q_set_lpm(WAIT_CLOCKED);
imx6_set_lpm(WAIT_CLOCKED);
break;
default:
return -EINVAL;
......@@ -392,11 +392,6 @@ static const struct platform_suspend_ops imx6q_pm_ops = {
.valid = imx6q_pm_valid,
};
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)
{
......@@ -482,8 +477,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
/*
* ccm physical address is not used by asm code currently,
* so get ccm virtual address directly, as we already have
* it from ccm driver.
* so get ccm virtual address directly.
*/
pm_info->ccm_base.vbase = ccm_base;
......@@ -568,7 +562,7 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata
/*
* This is for SW workaround step #1 of ERR007265, see comments
* in imx6q_set_lpm for details of this errata.
* in imx6_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.
......@@ -579,6 +573,24 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata
IMX6Q_GPR1_GINT);
}
void __init imx6_pm_ccm_init(const char *ccm_compat)
{
struct device_node *np;
u32 val;
np = of_find_compatible_node(NULL, NULL, ccm_compat);
ccm_base = of_iomap(np, 0);
BUG_ON(!ccm_base);
/*
* Initialize CCM_CLPCR_LPM into RUN mode to avoid ARM core
* clock being shut down unexpectedly by WAIT mode.
*/
val = readl_relaxed(ccm_base + CLPCR);
val &= ~BM_CLPCR_LPM;
writel_relaxed(val, ccm_base + CLPCR);
}
void __init imx6q_pm_init(void)
{
imx6_pm_common_init(&imx6q_pm_data);
......
/*
* Copyright (C) 2008-2011 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>
#define M4IF_MCR0_OFFSET (0x008C)
#define M4IF_MCR0_FDVFS (0x1 << 11)
#define M4IF_MCR0_FDVACK (0x1 << 27)
.align 3
/*
* ==================== low level suspend ====================
*
* On entry
* r0: pm_info structure address;
*
* suspend ocram space layout:
* ======================== high address ======================
* .
* .
* .
* ^
* ^
* ^
* imx53_suspend code
* PM_INFO structure(imx53_suspend_info)
* ======================== low address =======================
*/
/* Offsets of members of struct imx53_suspend_info */
#define SUSPEND_INFO_MX53_M4IF_V_OFFSET 0x0
#define SUSPEND_INFO_MX53_IOMUXC_V_OFFSET 0x4
#define SUSPEND_INFO_MX53_IO_COUNT_OFFSET 0x8
#define SUSPEND_INFO_MX53_IO_STATE_OFFSET 0xc
ENTRY(imx53_suspend)
stmfd sp!, {r4,r5,r6,r7}
/* Save pad config */
ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
cmp r1, #0
beq skip_pad_conf_1
add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
1:
ldr r5, [r2], #12 /* IOMUXC register offset */
ldr r6, [r3, r5] /* current value */
str r6, [r2], #4 /* save area */
subs r1, r1, #1
bne 1b
skip_pad_conf_1:
/* Set FDVFS bit of M4IF_MCR0 to request DDR to enter self-refresh */
ldr r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
ldr r2,[r1, #M4IF_MCR0_OFFSET]
orr r2, r2, #M4IF_MCR0_FDVFS
str r2,[r1, #M4IF_MCR0_OFFSET]
/* Poll FDVACK bit of M4IF_MCR to wait for DDR to enter self-refresh */
wait_sr_ack:
ldr r2,[r1, #M4IF_MCR0_OFFSET]
ands r2, r2, #M4IF_MCR0_FDVACK
beq wait_sr_ack
/* Set pad config */
ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
cmp r1, #0
beq skip_pad_conf_2
add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
2:
ldr r5, [r2], #4 /* IOMUXC register offset */
ldr r6, [r2], #4 /* clear */
ldr r7, [r3, r5]
bic r7, r7, r6
ldr r6, [r2], #8 /* set */
orr r7, r7, r6
str r7, [r3, r5]
subs r1, r1, #1
bne 2b
skip_pad_conf_2:
/* Zzz, enter stop mode */
wfi
nop
nop
nop
nop
/* Restore pad config */
ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
cmp r1, #0
beq skip_pad_conf_3
add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
3:
ldr r5, [r2], #12 /* IOMUXC register offset */
ldr r6, [r2], #4 /* saved value */
str r6, [r3, r5]
subs r1, r1, #1
bne 3b
skip_pad_conf_3:
/* Clear FDVFS bit of M4IF_MCR0 to request DDR to exit self-refresh */
ldr r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
ldr r2,[r1, #M4IF_MCR0_OFFSET]
bic r2, r2, #M4IF_MCR0_FDVFS
str r2,[r1, #M4IF_MCR0_OFFSET]
/* Poll FDVACK bit of M4IF_MCR to wait for DDR to exit self-refresh */
wait_ar_ack:
ldr r2,[r1, #M4IF_MCR0_OFFSET]
ands r2, r2, #M4IF_MCR0_FDVACK
bne wait_ar_ack
/* Restore registers */
ldmfd sp!, {r4,r5,r6,r7}
mov pc, lr
ENDPROC(imx53_suspend)
ENTRY(imx53_suspend_sz)
.word . - imx53_suspend
......@@ -50,6 +50,7 @@ obj-$(CONFIG_ARCH_BERLIN) += berlin/
obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/
obj-$(CONFIG_ARCH_HIP04) += hisilicon/
obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/
obj-$(CONFIG_ARCH_MXC) += imx/
obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/
ifeq ($(CONFIG_COMMON_CLK), y)
obj-$(CONFIG_ARCH_MMP) += mmp/
......
obj-y += \
clk.o \
clk-busy.o \
clk-cpu.o \
clk-fixup-div.o \
clk-fixup-mux.o \
clk-gate-exclusive.o \
clk-gate2.o \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
clk-pfd.o
obj-$(CONFIG_SOC_IMX1) += clk-imx1.o
obj-$(CONFIG_SOC_IMX21) += clk-imx21.o
obj-$(CONFIG_SOC_IMX25) += clk-imx25.o
obj-$(CONFIG_SOC_IMX27) += clk-imx27.o
obj-$(CONFIG_SOC_IMX31) += clk-imx31.o
obj-$(CONFIG_SOC_IMX35) += clk-imx35.o
obj-$(CONFIG_SOC_IMX5) += clk-imx51-imx53.o
obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o
obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
obj-$(CONFIG_SOC_IMX7D) += clk-imx7d.o
obj-$(CONFIG_SOC_VF610) += clk-vf610.o
......@@ -12,6 +12,7 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include "clk.h"
struct clk_cpu {
struct clk_hw hw;
......
......@@ -23,10 +23,14 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/imx1-clock.h>
#include <soc/imx/timer.h>
#include <asm/irq.h>
#include "clk.h"
#include "common.h"
#include "hardware.h"
#define MX1_CCM_BASE_ADDR 0x0021b000
#define MX1_TIM1_BASE_ADDR 0x00220000
#define MX1_TIM1_INT (NR_IRQS_LEGACY + 59)
static const char *prem_sel_clks[] = { "clk32_premult", "clk16m", };
static const char *clko_sel_clks[] = { "per1", "hclk", "clk48m", "clk16m",
......@@ -50,9 +54,9 @@ static void __init _mx1_clocks_init(unsigned long fref)
clk[IMX1_CLK_CLK16M] = imx_clk_gate("clk16m", "clk16m_ext", CCM_CSCR, 17);
clk[IMX1_CLK_CLK32_PREMULT] = imx_clk_fixed_factor("clk32_premult", "clk32", 512, 1);
clk[IMX1_CLK_PREM] = imx_clk_mux("prem", CCM_CSCR, 16, 1, prem_sel_clks, ARRAY_SIZE(prem_sel_clks));
clk[IMX1_CLK_MPLL] = imx_clk_pllv1("mpll", "clk32_premult", CCM_MPCTL0);
clk[IMX1_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX1, "mpll", "clk32_premult", CCM_MPCTL0);
clk[IMX1_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0);
clk[IMX1_CLK_SPLL] = imx_clk_pllv1("spll", "prem", CCM_SPCTL0);
clk[IMX1_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX1, "spll", "prem", CCM_SPCTL0);
clk[IMX1_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
clk[IMX1_CLK_MCU] = imx_clk_divider("mcu", "clk32_premult", CCM_CSCR, 15, 1);
clk[IMX1_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 15, 1);
......@@ -75,7 +79,8 @@ static void __init _mx1_clocks_init(unsigned long fref)
int __init mx1_clocks_init(unsigned long fref)
{
ccm = MX1_IO_ADDRESS(MX1_CCM_BASE_ADDR);
ccm = ioremap(MX1_CCM_BASE_ADDR, SZ_4K);
BUG_ON(!ccm);
_mx1_clocks_init(fref);
......@@ -98,7 +103,7 @@ int __init mx1_clocks_init(unsigned long fref)
clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ipg", "imx1-fb.0");
clk_register_clkdev(clk[IMX1_CLK_DUMMY], "ahb", "imx1-fb.0");
mxc_timer_init(MX1_IO_ADDRESS(MX1_TIM1_BASE_ADDR), MX1_TIM1_INT);
mxc_timer_init(MX1_TIM1_BASE_ADDR, MX1_TIM1_INT, GPT_TYPE_IMX1);
return 0;
}
......
......@@ -15,10 +15,14 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/imx21-clock.h>
#include <soc/imx/timer.h>
#include <asm/irq.h>
#include "clk.h"
#include "common.h"
#include "hardware.h"
#define MX21_CCM_BASE_ADDR 0x10027000
#define MX21_GPT1_BASE_ADDR 0x10003000
#define MX21_INT_GPT1 (NR_IRQS_LEGACY + 26)
static void __iomem *ccm __initdata;
......@@ -63,9 +67,9 @@ static void __init _mx21_clocks_init(unsigned long lref, unsigned long href)
clk[IMX21_CLK_USB_DIV] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 26, 3);
clk[IMX21_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 29, 3);
clk[IMX21_CLK_MPLL] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
clk[IMX21_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX21, "mpll", "mpll_sel", CCM_MPCTL0);
clk[IMX21_CLK_SPLL] = imx_clk_pllv1("spll", "spll_sel", CCM_SPCTL0);
clk[IMX21_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX21, "spll", "spll_sel", CCM_SPCTL0);
clk[IMX21_CLK_NFC_DIV] = imx_clk_divider("nfc_div", "fclk", CCM_PCDR0, 12, 4);
clk[IMX21_CLK_SSI1_DIV] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
......@@ -153,7 +157,7 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href)
clk_register_clkdev(clk[IMX21_CLK_I2C_GATE], NULL, "imx21-i2c.0");
clk_register_clkdev(clk[IMX21_CLK_OWIRE_GATE], NULL, "mxc_w1.0");
mxc_timer_init(MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR), MX21_INT_GPT1);
mxc_timer_init(MX21_GPT1_BASE_ADDR, MX21_INT_GPT1, GPT_TYPE_IMX21);
return 0;
}
......
......@@ -28,8 +28,6 @@
#include <linux/of_irq.h>
#include "clk.h"
#include "common.h"
#include "hardware.h"
#define CCM_MPCTL 0x00
#define CCM_UPCTL 0x04
......@@ -95,8 +93,8 @@ static int __init __mx25_clocks_init(unsigned long osc_rate,
clk[dummy] = imx_clk_fixed("dummy", 0);
clk[osc] = imx_clk_fixed("osc", osc_rate);
clk[mpll] = imx_clk_pllv1("mpll", "osc", ccm(CCM_MPCTL));
clk[upll] = imx_clk_pllv1("upll", "osc", ccm(CCM_UPCTL));
clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "mpll", "osc", ccm(CCM_MPCTL));
clk[upll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "upll", "osc", ccm(CCM_UPCTL));
clk[mpll_cpu_3_4] = imx_clk_fixed_factor("mpll_cpu_3_4", "mpll", 3, 4);
clk[cpu_sel] = imx_clk_mux("cpu_sel", ccm(CCM_CCTL), 14, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
clk[cpu] = imx_clk_divider("cpu", "cpu_sel", ccm(CCM_CCTL), 30, 2);
......
......@@ -5,10 +5,15 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/imx27-clock.h>
#include <soc/imx/revision.h>
#include <soc/imx/timer.h>
#include <asm/irq.h>
#include "clk.h"
#include "common.h"
#include "hardware.h"
#define MX27_CCM_BASE_ADDR 0x10027000
#define MX27_GPT1_BASE_ADDR 0x10003000
#define MX27_INT_GPT1 (NR_IRQS_LEGACY + 26)
static void __iomem *ccm __initdata;
......@@ -54,8 +59,8 @@ static void __init _mx27_clocks_init(unsigned long fref)
clk[IMX27_CLK_CKIH_GATE] = imx_clk_gate_dis("ckih_gate", "ckih", CCM_CSCR, 3);
clk[IMX27_CLK_MPLL_OSC_SEL] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1, mpll_osc_sel_clks, ARRAY_SIZE(mpll_osc_sel_clks));
clk[IMX27_CLK_MPLL_SEL] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks, ARRAY_SIZE(mpll_sel_clks));
clk[IMX27_CLK_MPLL] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
clk[IMX27_CLK_SPLL] = imx_clk_pllv1("spll", "ckih_gate", CCM_SPCTL0);
clk[IMX27_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX27, "mpll", "mpll_sel", CCM_MPCTL0);
clk[IMX27_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX27, "spll", "ckih_gate", CCM_SPCTL0);
clk[IMX27_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
clk[IMX27_CLK_MPLL_MAIN2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
......@@ -229,7 +234,7 @@ int __init mx27_clocks_init(unsigned long fref)
clk_register_clkdev(clk[IMX27_CLK_EMMA_AHB_GATE], "ahb", "m2m-emmaprp.0");
clk_register_clkdev(clk[IMX27_CLK_EMMA_IPG_GATE], "ipg", "m2m-emmaprp.0");
mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1);
mxc_timer_init(MX27_GPT1_BASE_ADDR, MX27_INT_GPT1, GPT_TYPE_IMX21);
return 0;
}
......
......@@ -21,12 +21,26 @@
#include <linux/io.h>
#include <linux/err.h>
#include <linux/of.h>
#include <soc/imx/revision.h>
#include <soc/imx/timer.h>
#include <asm/irq.h>
#include "clk.h"
#include "common.h"
#include "crmregs-imx3.h"
#include "hardware.h"
#include "mx31.h"
#define MX31_CCM_BASE_ADDR 0x53f80000
#define MX31_GPT1_BASE_ADDR 0x53f90000
#define MX31_INT_GPT (NR_IRQS_LEGACY + 29)
#define MXC_CCM_CCMR 0x00
#define MXC_CCM_PDR0 0x04
#define MXC_CCM_PDR1 0x08
#define MXC_CCM_MPCTL 0x10
#define MXC_CCM_UPCTL 0x14
#define MXC_CCM_SRPCTL 0x18
#define MXC_CCM_CGR0 0x20
#define MXC_CCM_CGR1 0x24
#define MXC_CCM_CGR2 0x28
#define MXC_CCM_PMCR0 0x5c
static const char *mcu_main_sel[] = { "spll", "mpll", };
static const char *per_sel[] = { "per_div", "ipg", };
......@@ -50,15 +64,18 @@ static struct clk_onecell_data clk_data;
int __init mx31_clocks_init(unsigned long fref)
{
void __iomem *base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR);
void __iomem *base;
struct device_node *np;
base = ioremap(MX31_CCM_BASE_ADDR, SZ_4K);
BUG_ON(!base);
clk[dummy] = imx_clk_fixed("dummy", 0);
clk[ckih] = imx_clk_fixed("ckih", fref);
clk[ckil] = imx_clk_fixed("ckil", 32768);
clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MXC_CCM_MPCTL);
clk[spll] = imx_clk_pllv1("spll", "ckih", base + MXC_CCM_SRPCTL);
clk[upll] = imx_clk_pllv1("upll", "ckih", base + MXC_CCM_UPCTL);
clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX31, "mpll", "ckih", base + MXC_CCM_MPCTL);
clk[spll] = imx_clk_pllv1(IMX_PLLV1_IMX31, "spll", "ckih", base + MXC_CCM_SRPCTL);
clk[upll] = imx_clk_pllv1(IMX_PLLV1_IMX31, "upll", "ckih", base + MXC_CCM_UPCTL);
clk[mcu_main] = imx_clk_mux("mcu_main", base + MXC_CCM_PMCR0, 31, 1, mcu_main_sel, ARRAY_SIZE(mcu_main_sel));
clk[hsp] = imx_clk_divider("hsp", "mcu_main", base + MXC_CCM_PDR0, 11, 3);
clk[ahb] = imx_clk_divider("ahb", "mcu_main", base + MXC_CCM_PDR0, 3, 3);
......@@ -182,7 +199,7 @@ int __init mx31_clocks_init(unsigned long fref)
mx31_revision();
clk_disable_unprepare(clk[iim_gate]);
mxc_timer_init(MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR), MX31_INT_GPT);
mxc_timer_init(MX31_GPT1_BASE_ADDR, MX31_INT_GPT, GPT_TYPE_IMX31);
return 0;
}
......
......@@ -13,11 +13,26 @@
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/err.h>
#include <soc/imx/revision.h>
#include <soc/imx/timer.h>
#include <asm/irq.h>
#include "crmregs-imx3.h"
#include "clk.h"
#include "common.h"
#include "hardware.h"
#define MX35_CCM_BASE_ADDR 0x53f80000
#define MX35_GPT1_BASE_ADDR 0x53f90000
#define MX35_INT_GPT (NR_IRQS_LEGACY + 29)
#define MXC_CCM_PDR0 0x04
#define MX35_CCM_PDR2 0x0c
#define MX35_CCM_PDR3 0x10
#define MX35_CCM_PDR4 0x14
#define MX35_CCM_MPCTL 0x1c
#define MX35_CCM_PPCTL 0x20
#define MX35_CCM_CGR0 0x2c
#define MX35_CCM_CGR1 0x30
#define MX35_CCM_CGR2 0x34
#define MX35_CCM_CGR3 0x38
struct arm_ahb_div {
unsigned char arm, ahb, sel;
......@@ -71,11 +86,14 @@ static struct clk *clk[clk_max];
int __init mx35_clocks_init(void)
{
void __iomem *base = MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR);
void __iomem *base;
u32 pdr0, consumer_sel, hsp_sel;
struct arm_ahb_div *aad;
unsigned char *hsp_div;
base = ioremap(MX35_CCM_BASE_ADDR, SZ_4K);
BUG_ON(!base);
pdr0 = __raw_readl(base + MXC_CCM_PDR0);
consumer_sel = (pdr0 >> 16) & 0xf;
aad = &clk_consumer[consumer_sel];
......@@ -89,8 +107,8 @@ int __init mx35_clocks_init(void)
}
clk[ckih] = imx_clk_fixed("ckih", 24000000);
clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MX35_CCM_MPCTL);
clk[ppll] = imx_clk_pllv1("ppll", "ckih", base + MX35_CCM_PPCTL);
clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "mpll", "ckih", base + MX35_CCM_MPCTL);
clk[ppll] = imx_clk_pllv1(IMX_PLLV1_IMX35, "ppll", "ckih", base + MX35_CCM_PPCTL);
clk[mpll] = imx_clk_fixed_factor("mpll_075", "mpll", 3, 4);
......@@ -276,11 +294,7 @@ int __init mx35_clocks_init(void)
imx_print_silicon_rev("i.MX35", mx35_revision());
#ifdef CONFIG_MXC_USE_EPIT
epit_timer_init(MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1);
#else
mxc_timer_init(MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT);
#endif
mxc_timer_init(MX35_GPT1_BASE_ADDR, MX35_INT_GPT, GPT_TYPE_IMX31);
return 0;
}
......
......@@ -16,11 +16,10 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <soc/imx/revision.h>
#include <dt-bindings/clock/imx5-clock.h>
#include "clk.h"
#include "common.h"
#include "hardware.h"
#define MX51_DPLL1_BASE 0x83f80000
#define MX51_DPLL2_BASE 0x83f84000
......@@ -133,8 +132,6 @@ static struct clk_onecell_data clk_data;
static void __init mx5_clocks_common_init(void __iomem *ccm_base)
{
imx5_pm_set_ccm_base(ccm_base);
clk[IMX5_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
clk[IMX5_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
clk[IMX5_CLK_OSC] = imx_obtain_fixed_clock("osc", 0);
......
......@@ -19,11 +19,10 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <soc/imx/revision.h>
#include <dt-bindings/clock/imx6qdl-clock.h>
#include "clk.h"
#include "common.h"
#include "hardware.h"
static const char *step_sels[] = { "osc", "pll2_pfd2_396m", };
static const char *pll1_sw_sels[] = { "pll1_sys", "step", };
......@@ -121,6 +120,16 @@ static unsigned int share_count_ssi2;
static unsigned int share_count_ssi3;
static unsigned int share_count_mipi_core_cfg;
static inline int clk_on_imx6q(void)
{
return of_machine_is_compatible("fsl,imx6q");
}
static inline int clk_on_imx6dl(void)
{
return of_machine_is_compatible("fsl,imx6dl");
}
static void __init imx6q_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
......@@ -141,7 +150,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
WARN_ON(!base);
/* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) {
if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) {
post_div_table[1].div = 1;
post_div_table[2].div = 1;
video_div_table[1].div = 1;
......@@ -248,7 +257,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_TWD] = imx_clk_fixed_factor("twd", "arm", 1, 2);
clk[IMX6QDL_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
clk[IMX6QDL_CLK_VIDEO_27M] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20);
if (cpu_is_imx6dl()) {
if (clk_on_imx6dl()) {
clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_fixed_factor("gpu2d_axi", "mmdc_ch0_axi_podf", 1, 1);
clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_fixed_factor("gpu3d_axi", "mmdc_ch0_axi_podf", 1, 1);
}
......@@ -262,8 +271,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
base = of_iomap(np, 0);
WARN_ON(!base);
imx6q_pm_set_ccm_base(base);
/* name reg shift width parent_names num_parents */
clk[IMX6QDL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
clk[IMX6QDL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
......@@ -275,7 +282,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels));
clk[IMX6QDL_CLK_ASRC_SEL] = imx_clk_mux("asrc_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels));
clk[IMX6QDL_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels));
if (cpu_is_imx6q()) {
if (clk_on_imx6q()) {
clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_mux("gpu2d_axi", base + 0x18, 0, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels));
clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_mux("gpu3d_axi", base + 0x18, 1, 1, gpu_axi_sels, ARRAY_SIZE(gpu_axi_sels));
}
......@@ -382,7 +389,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2);
clk[IMX6QDL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4);
clk[IMX6QDL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6);
if (cpu_is_imx6dl())
if (clk_on_imx6dl())
clk[IMX6DL_CLK_I2C4] = imx_clk_gate2("i2c4", "ipg_per", base + 0x6c, 8);
else
clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8);
......@@ -392,7 +399,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x6c, 16, &share_count_esai);
clk[IMX6QDL_CLK_GPT_IPG] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20);
clk[IMX6QDL_CLK_GPT_IPG_PER] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22);
if (cpu_is_imx6dl())
if (clk_on_imx6dl())
/*
* The multiplexer and divider of imx6q clock gpu3d_shader get
* redefined/reused as gpu2d_core_sel and gpu2d_core_podf on imx6dl.
......@@ -420,7 +427,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_HSI_TX] = imx_clk_gate2_shared("hsi_tx", "hsi_tx_podf", base + 0x74, 16, &share_count_mipi_core_cfg);
clk[IMX6QDL_CLK_MIPI_CORE_CFG] = imx_clk_gate2_shared("mipi_core_cfg", "video_27m", base + 0x74, 16, &share_count_mipi_core_cfg);
clk[IMX6QDL_CLK_MIPI_IPG] = imx_clk_gate2_shared("mipi_ipg", "ipg", base + 0x74, 16, &share_count_mipi_core_cfg);
if (cpu_is_imx6dl())
if (clk_on_imx6dl())
/*
* The multiplexer and divider of the imx6q clock gpu2d get
* redefined/reused as mlb_sys_sel and mlb_sys_clk_podf on imx6dl.
......@@ -443,7 +450,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_GPMI_IO] = imx_clk_gate2("gpmi_io", "enfc", base + 0x78, 28);
clk[IMX6QDL_CLK_GPMI_APB] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30);
clk[IMX6QDL_CLK_ROM] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0);
clk[IMX6QDL_CLK_SATA] = imx_clk_gate2("sata", "ipg", base + 0x7c, 4);
clk[IMX6QDL_CLK_SATA] = imx_clk_gate2("sata", "ahb", base + 0x7c, 4);
clk[IMX6QDL_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6);
clk[IMX6QDL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
clk[IMX6QDL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif_podf", base + 0x7c, 14);
......@@ -470,7 +477,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
* The gpt_3m clock is not available on i.MX6Q TO1.0. Let's point it
* to clock gpt_ipg_per to ease the gpt driver code.
*/
if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0)
if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0)
clk[IMX6QDL_CLK_GPT_3M] = clk[IMX6QDL_CLK_GPT_IPG_PER];
imx_check_clocks(clk, ARRAY_SIZE(clk));
......@@ -482,7 +489,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL);
if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
cpu_is_imx6dl()) {
clk_on_imx6dl()) {
clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
}
......@@ -527,8 +534,5 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
/* All existing boards with PCIe use LVDS1 */
if (IS_ENABLED(CONFIG_PCI_IMX6))
clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]);
/* Set initial power mode */
imx6q_set_lpm(WAIT_CLOCKED);
}
CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
......@@ -16,7 +16,6 @@
#include <dt-bindings/clock/imx6sl-clock.h>
#include "clk.h"
#include "common.h"
#define CCSR 0xc
#define BM_CCSR_PLL1_SW_CLK_SEL (1 << 2)
......@@ -288,9 +287,6 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
WARN_ON(!base);
ccm_base = base;
/* Reuse imx6q pm code */
imx6q_pm_set_ccm_base(base);
/* name reg shift width parent_names num_parents */
clks[IMX6SL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
clks[IMX6SL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
......@@ -443,8 +439,5 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clk_set_parent(clks[IMX6SL_CLK_LCDIF_AXI_SEL],
clks[IMX6SL_CLK_PLL2_PFD2]);
/* Set initial power mode */
imx6q_set_lpm(WAIT_CLOCKED);
}
CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
......@@ -21,7 +21,6 @@
#include <linux/types.h>
#include "clk.h"
#include "common.h"
#define CCDR 0x4
#define BM_CCM_CCDR_MMDC_CH0_MASK (0x2 << 16)
......@@ -268,8 +267,6 @@ static void __init imx6sx_clocks_init(struct device_node *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));
......@@ -560,8 +557,5 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clk_set_parent(clks[IMX6SX_CLK_QSPI1_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
clk_set_parent(clks[IMX6SX_CLK_QSPI2_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
/* Set initial power mode */
imx6q_set_lpm(WAIT_CLOCKED);
}
CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init);
This diff is collapsed.
......@@ -6,8 +6,6 @@
#include <linux/err.h>
#include "clk.h"
#include "common.h"
#include "hardware.h"
/**
* pll v1
......@@ -26,13 +24,29 @@
struct clk_pllv1 {
struct clk_hw hw;
void __iomem *base;
enum imx_pllv1_type type;
};
#define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk))
static inline bool mfn_is_negative(unsigned int mfn)
static inline bool is_imx1_pllv1(struct clk_pllv1 *pll)
{
return !cpu_is_mx1() && !cpu_is_mx21() && (mfn & MFN_SIGN);
return pll->type == IMX_PLLV1_IMX1;
}
static inline bool is_imx21_pllv1(struct clk_pllv1 *pll)
{
return pll->type == IMX_PLLV1_IMX21;
}
static inline bool is_imx27_pllv1(struct clk_pllv1 *pll)
{
return pll->type == IMX_PLLV1_IMX27;
}
static inline bool mfn_is_negative(struct clk_pllv1 *pll, unsigned int mfn)
{
return !is_imx1_pllv1(pll) && !is_imx21_pllv1(pll) && (mfn & MFN_SIGN);
}
static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
......@@ -71,8 +85,8 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
* 2's complements number.
* On i.MX27 the bit 9 is the sign bit.
*/
if (mfn_is_negative(mfn)) {
if (cpu_is_mx27())
if (mfn_is_negative(pll, mfn)) {
if (is_imx27_pllv1(pll))
mfn_abs = mfn & MFN_MASK;
else
mfn_abs = BIT(MFN_BITS) - mfn;
......@@ -85,7 +99,7 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
do_div(ll, mfd + 1);
if (mfn_is_negative(mfn))
if (mfn_is_negative(pll, mfn))
ll = -ll;
ll = (rate * mfi) + ll;
......@@ -97,8 +111,8 @@ static struct clk_ops clk_pllv1_ops = {
.recalc_rate = clk_pllv1_recalc_rate,
};
struct clk *imx_clk_pllv1(const char *name, const char *parent,
void __iomem *base)
struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name,
const char *parent, void __iomem *base)
{
struct clk_pllv1 *pll;
struct clk *clk;
......@@ -109,6 +123,7 @@ struct clk *imx_clk_pllv1(const char *name, const char *parent,
return ERR_PTR(-ENOMEM);
pll->base = base;
pll->type = type;
init.name = name;
init.ops = &clk_pllv1_ops;
......
......@@ -24,12 +24,14 @@
#define BM_PLL_POWER (0x1 << 12)
#define BM_PLL_LOCK (0x1 << 31)
#define IMX7_ENET_PLL_POWER (0x1 << 5)
/**
* struct clk_pllv3 - IMX PLL clock version 3
* @clk_hw: clock source
* @base: base address of PLL registers
* @powerup_set: set POWER bit to power up the PLL
* @powerdown: pll powerdown offset bit
* @div_mask: mask of divider bits
* @div_shift: shift of divider bits
*
......@@ -40,6 +42,7 @@ struct clk_pllv3 {
struct clk_hw hw;
void __iomem *base;
bool powerup_set;
u32 powerdown;
u32 div_mask;
u32 div_shift;
};
......@@ -49,7 +52,7 @@ struct clk_pllv3 {
static int clk_pllv3_wait_lock(struct clk_pllv3 *pll)
{
unsigned long timeout = jiffies + msecs_to_jiffies(10);
u32 val = readl_relaxed(pll->base) & BM_PLL_POWER;
u32 val = readl_relaxed(pll->base) & pll->powerdown;
/* No need to wait for lock when pll is not powered up */
if ((pll->powerup_set && !val) || (!pll->powerup_set && val))
......@@ -215,7 +218,7 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long max_rate = parent_rate * 54;
u32 div;
u32 mfn, mfd = 1000000;
s64 temp64;
u64 temp64;
if (rate > max_rate)
rate = max_rate;
......@@ -239,7 +242,7 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long max_rate = parent_rate * 54;
u32 val, div;
u32 mfn, mfd = 1000000;
s64 temp64;
u64 temp64;
if (rate < min_rate || rate > max_rate)
return -EINVAL;
......@@ -293,6 +296,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
if (!pll)
return ERR_PTR(-ENOMEM);
pll->powerdown = BM_PLL_POWER;
switch (type) {
case IMX_PLLV3_SYS:
ops = &clk_pllv3_sys_ops;
......@@ -306,6 +311,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
case IMX_PLLV3_AV:
ops = &clk_pllv3_av_ops;
break;
case IMX_PLLV3_ENET_IMX7:
pll->powerdown = IMX7_ENET_PLL_POWER;
case IMX_PLLV3_ENET:
ops = &clk_pllv3_enet_ops;
break;
......
......@@ -118,6 +118,7 @@ static struct clk_onecell_data clk_data;
static unsigned int const clks_init_on[] __initconst = {
VF610_CLK_SYS_BUS,
VF610_CLK_DDR_SEL,
VF610_CLK_DAP,
};
static struct clk * __init vf610_get_fixed_clock(
......@@ -272,6 +273,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6));
clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7));
clk[VF610_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(6));
clk[VF610_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_bus", CCM_CCGR10, CCM_CCGRx_CGn(7));
clk[VF610_CLK_DSPI0] = imx_clk_gate2("dspi0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(12));
clk[VF610_CLK_DSPI1] = imx_clk_gate2("dspi1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(13));
......@@ -383,6 +386,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2));
clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7));
clk[VF610_CLK_DAP] = imx_clk_gate("dap", "platform_bus", CCM_CCSR, 24);
imx_check_clocks(clk, ARRAY_SIZE(clk));
......
......@@ -10,8 +10,17 @@ void imx_check_clocks(struct clk *clks[], unsigned int count);
extern void imx_cscmr1_fixup(u32 *val);
struct clk *imx_clk_pllv1(const char *name, const char *parent,
void __iomem *base);
enum imx_pllv1_type {
IMX_PLLV1_IMX1,
IMX_PLLV1_IMX21,
IMX_PLLV1_IMX25,
IMX_PLLV1_IMX27,
IMX_PLLV1_IMX31,
IMX_PLLV1_IMX35,
};
struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name,
const char *parent, void __iomem *base);
struct clk *imx_clk_pllv2(const char *name, const char *parent,
void __iomem *base);
......@@ -23,6 +32,7 @@ enum imx_pllv3_type {
IMX_PLLV3_USB_VF610,
IMX_PLLV3_AV,
IMX_PLLV3_ENET,
IMX_PLLV3_ENET_IMX7,
};
struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
......
......@@ -258,4 +258,10 @@ config CLKSRC_PXA
help
This enables OST0 support available on PXA and SA-11x0
platforms.
config CLKSRC_IMX_GPT
bool "Clocksource using i.MX GPT" if COMPILE_TEST
depends on ARM && CLKDEV_LOOKUP
select CLKSRC_MMIO
endmenu
......@@ -51,4 +51,5 @@ obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o
obj-$(CONFIG_ARCH_INTEGRATOR_AP) += timer-integrator-ap.o
obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o
obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o
obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o
obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
This diff is collapsed.
......@@ -193,6 +193,7 @@
#define VF610_PLL6_BYPASS 180
#define VF610_PLL7_BYPASS 181
#define VF610_CLK_SNVS 182
#define VF610_CLK_END 183
#define VF610_CLK_DAP 183
#define VF610_CLK_END 184
#endif /* __DT_BINDINGS_CLOCK_VF610_H */
/*
* Copyright 2015 Linaro Ltd.
*
* 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.
*/
#ifndef __SOC_IMX_REVISION_H__
#define __SOC_IMX_REVISION_H__
#define IMX_CHIP_REVISION_1_0 0x10
#define IMX_CHIP_REVISION_1_1 0x11
#define IMX_CHIP_REVISION_1_2 0x12
#define IMX_CHIP_REVISION_1_3 0x13
#define IMX_CHIP_REVISION_1_4 0x14
#define IMX_CHIP_REVISION_1_5 0x15
#define IMX_CHIP_REVISION_2_0 0x20
#define IMX_CHIP_REVISION_2_1 0x21
#define IMX_CHIP_REVISION_2_2 0x22
#define IMX_CHIP_REVISION_2_3 0x23
#define IMX_CHIP_REVISION_3_0 0x30
#define IMX_CHIP_REVISION_3_1 0x31
#define IMX_CHIP_REVISION_3_2 0x32
#define IMX_CHIP_REVISION_3_3 0x33
#define IMX_CHIP_REVISION_UNKNOWN 0xff
int mx27_revision(void);
int mx31_revision(void);
int mx35_revision(void);
int mx51_revision(void);
int mx53_revision(void);
unsigned int imx_get_soc_revision(void);
void imx_print_silicon_rev(const char *cpu, int srev);
#endif /* __SOC_IMX_REVISION_H__ */
/*
* Copyright 2015 Linaro Ltd.
*
* 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.
*/
#ifndef __SOC_IMX_TIMER_H__
#define __SOC_IMX_TIMER_H__
enum imx_gpt_type {
GPT_TYPE_IMX1, /* i.MX1 */
GPT_TYPE_IMX21, /* i.MX21/27 */
GPT_TYPE_IMX31, /* i.MX31/35/25/37/51/6Q */
GPT_TYPE_IMX6DL, /* i.MX6DL/SX/SL */
};
/*
* This is a stop-gap solution for clock drivers like imx1/imx21 which call
* mxc_timer_init() to initialize timer for non-DT boot. It can be removed
* when these legacy non-DT support is converted or dropped.
*/
void mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type);
#endif /* __SOC_IMX_TIMER_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment