Commit b6fb5474 authored by Olof Johansson's avatar Olof Johansson

Merge tag 'imx-soc-3.13' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/soc

From Shawn Guo:
The imx/mxs soc changes for 3.13:

* Low-level debug support for Vybrid
* Support soc bus/device for imx6
* Suspend support for imx6dl and imx6sl
* The imx6q clock updates for PCIe and audio PLL support
* IOMUXC GPR update for fec support
* Some random cleanup
* A few defconfig updates

* tag 'imx-soc-3.13' of git://git.linaro.org/people/shawnguo/linux-2.6: (31 commits)
  ARM: imx: enable suspend for imx6sl
  ARM: imx: ensure dsm_request signal is not asserted when setting LPM
  ARM: imx6q: call WB and RBC configuration from imx6q_pm_enter()
  ARM: imx6q: move low-power code out of clock driver
  ARM: imx: drop extern with function prototypes in common.h
  ARM: imx: reset core along with enable/disable operation
  ARM: imx: do not return from imx_cpu_die() call
  ARM: imx_v6_v7_defconfig: Select CONFIG_PROVE_LOCKING
  ARM: imx_v6_v7_defconfig: Enable LEDS_GPIO related options
  ARM: mxs_defconfig: Turn off CONFIG_DEBUG_GPIO
  ARM: imx: replace imx6q_restart() with mxc_restart()
  ARM: mach-imx: mm-imx5: Retrieve iomuxc base address from dt
  ARM: mach-imx: mm-imx5: Retrieve tzic base address from dt
  ARM: mach-imx: clk-imx51-imx53: Retrieve base address and irq from dt
  ARM: mxs_defconfig: Add CHIPIDEA_UDC support
  ARM: imx: Include linux/err.h
  ARM: imx_v6_v7_defconfig: Add CHIPIDEA_UDC support
  ARM: imx_v6_v7_defconfig: Add SPDIF support
  ARM: imx6q: clock and Kconfig update for PCIe support
  ARM: imx: Add LVDS general-purpose clocks to i.MX6Q
  ...
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 826f57b4 9ba64fe3
......@@ -215,6 +215,11 @@ clocks and IDs.
cko2 200
cko 201
vdoa 202
pll4_audio_div 203
lvds1_sel 204
lvds2_sel 205
lvds1_gate 206
lvds2_gate 207
Examples:
......
......@@ -386,6 +386,13 @@ choice
when u-boot hands over to the kernel, the system
silently crashes, with no serial output at all.
config DEBUG_VF_UART
bool "Vybrid UART"
depends on SOC_VF610
help
Say Y here if you want kernel low-level debugging support
on Vybrid based platforms.
config DEBUG_NOMADIK_UART
bool "Kernel low-level debugging messages via NOMADIK UART"
depends on ARCH_NOMADIK
......@@ -906,6 +913,7 @@ config DEBUG_LL_INCLUDE
default "debug/tegra.S" if DEBUG_TEGRA_UART
default "debug/ux500.S" if DEBUG_UX500_UART
default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
default "debug/vf.S" if DEBUG_VF_UART
default "debug/vt8500.S" if DEBUG_VT8500_UART0
default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
default "mach/debug-macro.S"
......
......@@ -380,7 +380,9 @@ clks: ccm@020c4000 {
};
anatop: anatop@020c8000 {
compatible = "fsl,imx6sl-anatop", "syscon", "simple-bus";
compatible = "fsl,imx6sl-anatop",
"fsl,imx6q-anatop",
"syscon", "simple-bus";
reg = <0x020c8000 0x1000>;
interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
......
......@@ -132,7 +132,6 @@ CONFIG_TOUCHSCREEN_MC13783=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_MMA8450=y
CONFIG_SERIO_SERPORT=m
CONFIG_VT_HW_CONSOLE_BINDING=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_IMX=y
......@@ -188,22 +187,33 @@ CONFIG_SND_SOC_PHYCORE_AC97=y
CONFIG_SND_SOC_EUKREA_TLV320=y
CONFIG_SND_SOC_IMX_WM8962=y
CONFIG_SND_SOC_IMX_SGTL5000=y
CONFIG_SND_SOC_IMX_SPDIF=y
CONFIG_SND_SOC_IMX_MC13783=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_MXC=y
CONFIG_USB_STORAGE=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_PHY=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_MXS_PHY=y
CONFIG_USB_GADGET=y
CONFIG_USB_ETH=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
CONFIG_RTC_DRV_MC13XXX=y
......@@ -246,7 +256,6 @@ CONFIG_UDF_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_CONFIGFS_FS=m
CONFIG_JFFS2_FS=y
CONFIG_UBIFS_FS=y
CONFIG_NFS_FS=y
......@@ -261,6 +270,7 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_PROVE_LOCKING=y
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_FTRACE is not set
# CONFIG_ARM_UNWIND is not set
......
......@@ -76,7 +76,6 @@ CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_TSC2007=m
# CONFIG_SERIO is not set
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
......@@ -91,7 +90,6 @@ CONFIG_I2C_MXS=y
CONFIG_SPI=y
CONFIG_SPI_GPIO=m
CONFIG_SPI_MXS=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
......@@ -115,9 +113,12 @@ CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_PHY=y
CONFIG_USB_MXS_PHY=y
CONFIG_USB_GADGET=y
CONFIG_USB_ETH=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_MMC=y
CONFIG_MMC_UNSAFE_RESUME=y
CONFIG_MMC_MXS=y
......
/*
* Copyright 2013 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.
*
*/
.macro addruart, rp, rv, tmp
ldr \rp, =0x40028000 @ physical
ldr \rv, =0xfe028000 @ virtual
.endm
.macro senduart, rd, rx
strb \rd, [\rx, #0x7] @ Data Register
.endm
.macro busyuart, rd, rx
1001: ldrb \rd, [\rx, #0x4] @ Status Register 1
tst \rd, #1 << 6 @ TC
beq 1001b @ wait until transmit done
.endm
.macro waituart,rd,rx
.endm
......@@ -11,6 +11,7 @@ config ARCH_MXC
select GENERIC_IRQ_CHIP
select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7
select MULTI_IRQ_HANDLER
select SOC_BUS
select SPARSE_IRQ
select USE_OF
help
......@@ -24,7 +25,7 @@ config MXC_IRQ_PRIOR
help
Select this if you want to use prioritized IRQ handling.
This feature prevents higher priority ISR to be interrupted
by lower priority IRQ even IRQF_DISABLED flag is not set.
by lower priority IRQ.
This may be useful in embedded applications, where are strong
requirements for timing.
Say N here, unless you have a specialized requirement.
......@@ -801,6 +802,8 @@ config SOC_IMX6Q
select HAVE_IMX_SRC
select HAVE_SMP
select MFD_SYSCON
select MIGHT_HAVE_PCI
select PCI_DOMAINS if PCI
select PINCTRL
select PINCTRL_IMX6Q
select PL310_ERRATA_588369 if CACHE_PL310
......
......@@ -102,6 +102,8 @@ obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
ifeq ($(CONFIG_PM),y)
obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
# i.MX6SL reuses pm-imx6q.c
obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o
endif
# i.MX5 based machines
......
......@@ -16,6 +16,7 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "common.h"
#include "hardware.h"
#define REG_SET 0x4
#define REG_CLR 0x8
......@@ -26,6 +27,7 @@
#define ANADIG_USB1_CHRG_DETECT 0x1b0
#define ANADIG_USB2_CHRG_DETECT 0x210
#define ANADIG_DIGPROG 0x260
#define ANADIG_DIGPROG_IMX6SL 0x280
#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000
#define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000
......@@ -76,21 +78,38 @@ static void imx_anatop_usb_chrg_detect_disable(void)
BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
}
u32 imx_anatop_get_digprog(void)
void __init imx_init_revision_from_anatop(void)
{
struct device_node *np;
void __iomem *anatop_base;
static u32 digprog;
if (digprog)
return digprog;
unsigned int revision;
u32 digprog;
u16 offset = ANADIG_DIGPROG;
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
anatop_base = of_iomap(np, 0);
WARN_ON(!anatop_base);
digprog = readl_relaxed(anatop_base + ANADIG_DIGPROG);
if (of_device_is_compatible(np, "fsl,imx6sl-anatop"))
offset = ANADIG_DIGPROG_IMX6SL;
digprog = readl_relaxed(anatop_base + offset);
iounmap(anatop_base);
switch (digprog & 0xff) {
case 0:
revision = IMX_CHIP_REVISION_1_0;
break;
case 1:
revision = IMX_CHIP_REVISION_1_1;
break;
case 2:
revision = IMX_CHIP_REVISION_1_2;
break;
default:
revision = IMX_CHIP_REVISION_UNKNOWN;
}
return digprog;
mxc_set_cpu_type(digprog >> 16 & 0xff);
imx_set_soc_revision(revision);
}
void __init imx_anatop_init(void)
......
......@@ -14,6 +14,9 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include "crm-regs-imx5.h"
#include "clk.h"
......@@ -472,8 +475,9 @@ CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init_dt);
static void __init mx53_clocks_init(struct device_node *np)
{
int i;
int i, irq;
unsigned long r;
void __iomem *base;
clk[pll1_sw] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
clk[pll2_sw] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
......@@ -559,14 +563,17 @@ static void __init mx53_clocks_init(struct device_node *np)
clk_set_rate(clk[esdhc_a_podf], 200000000);
clk_set_rate(clk[esdhc_b_podf], 200000000);
/* System timer */
mxc_timer_init(MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR), MX53_INT_GPT);
clk_prepare_enable(clk[iim_gate]);
imx_print_silicon_rev("i.MX53", mx53_revision());
clk_disable_unprepare(clk[iim_gate]);
r = clk_round_rate(clk[usboh3_per_gate], 54000000);
clk_set_rate(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);
}
CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
This diff is collapsed.
......@@ -127,6 +127,9 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
base = of_iomap(np, 0);
WARN_ON(!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));
......
......@@ -13,70 +13,73 @@
#include <linux/reboot.h>
struct irq_data;
struct platform_device;
struct pt_regs;
struct clk;
enum mxc_cpu_pwr_mode;
extern void mx1_map_io(void);
extern void mx21_map_io(void);
extern void mx25_map_io(void);
extern void mx27_map_io(void);
extern void mx31_map_io(void);
extern void mx35_map_io(void);
extern void mx51_map_io(void);
extern void mx53_map_io(void);
extern void imx1_init_early(void);
extern void imx21_init_early(void);
extern void imx25_init_early(void);
extern void imx27_init_early(void);
extern void imx31_init_early(void);
extern void imx35_init_early(void);
extern void imx51_init_early(void);
extern void imx53_init_early(void);
extern void mxc_init_irq(void __iomem *);
extern void tzic_init_irq(void __iomem *);
extern void mx1_init_irq(void);
extern void mx21_init_irq(void);
extern void mx25_init_irq(void);
extern void mx27_init_irq(void);
extern void mx31_init_irq(void);
extern void mx35_init_irq(void);
extern void mx51_init_irq(void);
extern void mx53_init_irq(void);
extern void imx1_soc_init(void);
extern void imx21_soc_init(void);
extern void imx25_soc_init(void);
extern void imx27_soc_init(void);
extern void imx31_soc_init(void);
extern void imx35_soc_init(void);
extern void imx51_soc_init(void);
extern void imx51_init_late(void);
extern void imx53_init_late(void);
extern void epit_timer_init(void __iomem *base, int irq);
extern void mxc_timer_init(void __iomem *, int);
extern int mx1_clocks_init(unsigned long fref);
extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
extern int mx25_clocks_init(void);
extern int mx27_clocks_init(unsigned long fref);
extern int mx31_clocks_init(unsigned long fref);
extern int mx35_clocks_init(void);
extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,
void mx1_map_io(void);
void mx21_map_io(void);
void mx25_map_io(void);
void mx27_map_io(void);
void mx31_map_io(void);
void mx35_map_io(void);
void mx51_map_io(void);
void mx53_map_io(void);
void imx1_init_early(void);
void imx21_init_early(void);
void imx25_init_early(void);
void imx27_init_early(void);
void imx31_init_early(void);
void imx35_init_early(void);
void imx51_init_early(void);
void imx53_init_early(void);
void mxc_init_irq(void __iomem *);
void tzic_init_irq(void __iomem *);
void mx1_init_irq(void);
void mx21_init_irq(void);
void mx25_init_irq(void);
void mx27_init_irq(void);
void mx31_init_irq(void);
void mx35_init_irq(void);
void mx51_init_irq(void);
void mx53_init_irq(void);
void imx1_soc_init(void);
void imx21_soc_init(void);
void imx25_soc_init(void);
void imx27_soc_init(void);
void imx31_soc_init(void);
void imx35_soc_init(void);
void imx51_soc_init(void);
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);
int mx1_clocks_init(unsigned long fref);
int mx21_clocks_init(unsigned long lref, unsigned long fref);
int mx25_clocks_init(void);
int mx27_clocks_init(unsigned long fref);
int mx31_clocks_init(unsigned long fref);
int mx35_clocks_init(void);
int mx51_clocks_init(unsigned long ckil, unsigned long osc,
unsigned long ckih1, unsigned long ckih2);
extern int mx25_clocks_init_dt(void);
extern int mx27_clocks_init_dt(void);
extern int mx31_clocks_init_dt(void);
extern struct platform_device *mxc_register_gpio(char *name, int id,
int mx25_clocks_init_dt(void);
int mx27_clocks_init_dt(void);
int mx31_clocks_init_dt(void);
struct platform_device *mxc_register_gpio(char *name, int id,
resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
extern void mxc_set_cpu_type(unsigned int type);
extern void mxc_restart(enum reboot_mode, const char *);
extern void mxc_arch_reset_init(void __iomem *);
extern void mxc_arch_reset_init_dt(void);
extern int mx53_revision(void);
extern int imx6q_revision(void);
extern int mx53_display_revision(void);
extern void imx_set_aips(void __iomem *);
extern int mxc_device_init(void);
void mxc_set_cpu_type(unsigned int type);
void mxc_restart(enum reboot_mode, const char *);
void mxc_arch_reset_init(void __iomem *);
void mxc_arch_reset_init_dt(void);
int mx53_revision(void);
void imx_set_aips(void __iomem *);
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);
enum mxc_cpu_pwr_mode {
WAIT_CLOCKED, /* wfi only */
......@@ -93,8 +96,8 @@ enum mx3_cpu_pwr_mode {
MX3_SLEEP,
};
extern void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode);
extern void imx_print_silicon_rev(const char *cpu, int srev);
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 *);
......@@ -108,54 +111,61 @@ void tzic_handle_irq(struct pt_regs *);
#define imx51_handle_irq tzic_handle_irq
#define imx53_handle_irq tzic_handle_irq
extern void imx_enable_cpu(int cpu, bool enable);
extern void imx_set_cpu_jump(int cpu, void *jump_addr);
extern u32 imx_get_cpu_arg(int cpu);
extern void imx_set_cpu_arg(int cpu, u32 arg);
extern void v7_cpu_resume(void);
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
extern void v7_secondary_startup(void);
extern void imx_scu_map_io(void);
extern void imx_smp_prepare(void);
extern void imx_scu_standby_enable(void);
void v7_secondary_startup(void);
void imx_scu_map_io(void);
void imx_smp_prepare(void);
void imx_scu_standby_enable(void);
#else
static inline void imx_scu_map_io(void) {}
static inline void imx_smp_prepare(void) {}
static inline void imx_scu_standby_enable(void) {}
#endif
extern void imx_src_init(void);
extern void imx_src_prepare_restart(void);
extern void imx_gpc_init(void);
extern void imx_gpc_pre_suspend(void);
extern void imx_gpc_post_resume(void);
extern void imx_gpc_mask_all(void);
extern void imx_gpc_restore_all(void);
extern void imx_anatop_init(void);
extern void imx_anatop_pre_suspend(void);
extern void imx_anatop_post_resume(void);
extern u32 imx_anatop_get_digprog(void);
extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
extern void imx6q_set_chicken_bit(void);
extern void imx_cpu_die(unsigned int cpu);
extern int imx_cpu_kill(unsigned int cpu);
void imx_src_init(void);
#ifdef CONFIG_HAVE_IMX_SRC
void imx_src_prepare_restart(void);
#else
static inline void imx_src_prepare_restart(void) {}
#endif
void imx_gpc_init(void);
void imx_gpc_pre_suspend(void);
void imx_gpc_post_resume(void);
void imx_gpc_mask_all(void);
void imx_gpc_restore_all(void);
void imx_gpc_irq_mask(struct irq_data *d);
void imx_gpc_irq_unmask(struct irq_data *d);
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 imx_cpu_die(unsigned int cpu);
int imx_cpu_kill(unsigned int cpu);
#ifdef CONFIG_PM
extern void imx6q_pm_init(void);
extern void imx5_pm_init(void);
void imx6q_pm_init(void);
void imx6q_pm_set_ccm_base(void __iomem *base);
void imx5_pm_init(void);
#else
static inline void imx6q_pm_init(void) {}
static inline void imx6q_pm_set_ccm_base(void __iomem *base) {}
static inline void imx5_pm_init(void) {}
#endif
#ifdef CONFIG_NEON
extern int mx51_neon_fixup(void);
int mx51_neon_fixup(void);
#else
static inline int mx51_neon_fixup(void) { return 0; }
#endif
#ifdef CONFIG_CACHE_L2X0
extern void imx_init_l2cache(void);
void imx_init_l2cache(void);
#else
static inline void imx_init_l2cache(void) {}
#endif
......
#include <linux/err.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include "hardware.h"
#include "common.h"
......@@ -8,11 +11,23 @@
unsigned int __mxc_cpu_type;
EXPORT_SYMBOL(__mxc_cpu_type);
static unsigned int imx_soc_revision;
void mxc_set_cpu_type(unsigned int type)
{
__mxc_cpu_type = type;
}
void imx_set_soc_revision(unsigned int rev)
{
imx_soc_revision = rev;
}
unsigned int imx_get_soc_revision(void)
{
return imx_soc_revision;
}
void imx_print_silicon_rev(const char *cpu, int srev)
{
if (srev == IMX_CHIP_REVISION_UNKNOWN)
......@@ -44,3 +59,81 @@ void __init imx_set_aips(void __iomem *base)
reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
__raw_writel(reg, base + 0x50);
}
struct device * __init imx_soc_device_init(void)
{
struct soc_device_attribute *soc_dev_attr;
struct soc_device *soc_dev;
struct device_node *root;
const char *soc_id;
int ret;
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return NULL;
soc_dev_attr->family = "Freescale i.MX";
root = of_find_node_by_path("/");
ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
of_node_put(root);
if (ret)
goto free_soc;
switch (__mxc_cpu_type) {
case MXC_CPU_MX1:
soc_id = "i.MX1";
break;
case MXC_CPU_MX21:
soc_id = "i.MX21";
break;
case MXC_CPU_MX25:
soc_id = "i.MX25";
break;
case MXC_CPU_MX27:
soc_id = "i.MX27";
break;
case MXC_CPU_MX31:
soc_id = "i.MX31";
break;
case MXC_CPU_MX35:
soc_id = "i.MX35";
break;
case MXC_CPU_MX51:
soc_id = "i.MX51";
break;
case MXC_CPU_MX53:
soc_id = "i.MX53";
break;
case MXC_CPU_IMX6SL:
soc_id = "i.MX6SL";
break;
case MXC_CPU_IMX6DL:
soc_id = "i.MX6DL";
break;
case MXC_CPU_IMX6Q:
soc_id = "i.MX6Q";
break;
default:
soc_id = "Unknown";
}
soc_dev_attr->soc_id = soc_id;
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d.%d",
(imx_soc_revision >> 4) & 0xf,
imx_soc_revision & 0xf);
if (!soc_dev_attr->revision)
goto free_soc;
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev))
goto free_rev;
return soc_device_to_device(soc_dev);
free_rev:
kfree(soc_dev_attr->revision);
free_soc:
kfree(soc_dev_attr);
return NULL;
}
......@@ -171,7 +171,7 @@ static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
static struct irqaction epit_timer_irq = {
.name = "i.MX EPIT Timer Tick",
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = epit_timer_interrupt,
};
......
......@@ -90,7 +90,7 @@ void imx_gpc_restore_all(void)
writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
}
static void imx_gpc_irq_unmask(struct irq_data *d)
void imx_gpc_irq_unmask(struct irq_data *d)
{
void __iomem *reg;
u32 val;
......@@ -105,7 +105,7 @@ static void imx_gpc_irq_unmask(struct irq_data *d)
writel_relaxed(val, reg);
}
static void imx_gpc_irq_mask(struct irq_data *d)
void imx_gpc_irq_mask(struct irq_data *d)
{
void __iomem *reg;
u32 val;
......
......@@ -52,7 +52,9 @@ void imx_cpu_die(unsigned int cpu)
* the register being cleared to kill the cpu.
*/
imx_set_cpu_arg(cpu, ~0);
cpu_do_idle();
while (1)
cpu_do_idle();
}
int imx_cpu_kill(unsigned int cpu)
......
......@@ -404,8 +404,7 @@ static int armadillo5x0_sdhc1_init(struct device *dev,
/* When supported the trigger type have to be BOTH */
ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)),
detect_irq,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
detect_irq, IRQF_TRIGGER_FALLING,
"sdhc-detect", data);
if (ret)
......
......@@ -13,7 +13,6 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/cpu.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/io.h>
......@@ -38,64 +37,6 @@
#include "cpuidle.h"
#include "hardware.h"
static u32 chip_revision;
int imx6q_revision(void)
{
return chip_revision;
}
static void __init imx6q_init_revision(void)
{
u32 rev = imx_anatop_get_digprog();
switch (rev & 0xff) {
case 0:
chip_revision = IMX_CHIP_REVISION_1_0;
break;
case 1:
chip_revision = IMX_CHIP_REVISION_1_1;
break;
case 2:
chip_revision = IMX_CHIP_REVISION_1_2;
break;
default:
chip_revision = IMX_CHIP_REVISION_UNKNOWN;
}
mxc_set_cpu_type(rev >> 16 & 0xff);
}
static void imx6q_restart(enum reboot_mode mode, const char *cmd)
{
struct device_node *np;
void __iomem *wdog_base;
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-wdt");
wdog_base = of_iomap(np, 0);
if (!wdog_base)
goto soft;
imx_src_prepare_restart();
/* enable wdog */
writew_relaxed(1 << 2, wdog_base);
/* write twice to ensure the request will not get ignored */
writew_relaxed(1 << 2, wdog_base);
/* wait for reset to assert ... */
mdelay(500);
pr_err("Watchdog reset failed to assert reset\n");
/* delay to allow the serial port to show the message */
mdelay(50);
soft:
/* we'll take a jump through zero as a poor second */
soft_restart(0);
}
/* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
static int ksz9021rn_phy_fixup(struct phy_device *phydev)
{
......@@ -190,12 +131,20 @@ static void __init imx6q_1588_init(void)
static void __init imx6q_init_machine(void)
{
struct device *parent;
imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
imx6q_revision());
imx_get_soc_revision());
mxc_arch_reset_init_dt();
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn("failed to initialize soc device\n");
imx6q_enet_phy_init();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
imx_anatop_init();
imx6q_pm_init();
......@@ -270,7 +219,7 @@ static void __init imx6q_init_late(void)
* WAIT mode is broken on TO 1.0 and 1.1, so there is no point
* to run cpuidle on them.
*/
if (imx6q_revision() > IMX_CHIP_REVISION_1_1)
if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_1)
imx6q_cpuidle_init();
if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
......@@ -287,7 +236,7 @@ static void __init imx6q_map_io(void)
static void __init imx6q_init_irq(void)
{
imx6q_init_revision();
imx_init_revision_from_anatop();
imx_init_l2cache();
imx_src_init();
imx_gpc_init();
......@@ -307,5 +256,5 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
.init_machine = imx6q_init_machine,
.init_late = imx6q_init_late,
.dt_compat = imx6q_dt_compat,
.restart = imx6q_restart,
.restart = mxc_restart,
MACHINE_END
......@@ -10,20 +10,51 @@
#include <linux/irqchip.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <linux/regmap.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include "common.h"
static void __init imx6sl_fec_init(void)
{
struct regmap *gpr;
/* set FEC clock from internal PLL clock source */
gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sl-iomuxc-gpr");
if (!IS_ERR(gpr)) {
regmap_update_bits(gpr, IOMUXC_GPR1,
IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK, 0);
regmap_update_bits(gpr, IOMUXC_GPR1,
IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK, 0);
} else {
pr_err("failed to find fsl,imx6sl-iomux-gpr regmap\n");
}
}
static void __init imx6sl_init_machine(void)
{
struct device *parent;
mxc_arch_reset_init_dt();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
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);
imx6sl_fec_init();
imx_anatop_init();
/* Reuse imx6q pm code */
imx6q_pm_init();
}
static void __init imx6sl_init_irq(void)
{
imx_init_revision_from_anatop();
imx_init_l2cache();
imx_src_init();
imx_gpc_init();
......
......@@ -311,7 +311,7 @@ static int mx31_3ds_sdhc1_init(struct device *dev,
}
ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)),
detect_irq, IRQF_DISABLED |
detect_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"sdhc1-detect", data);
if (ret) {
......
......@@ -371,8 +371,7 @@ static int pcm970_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
#endif
ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), detect_irq,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"sdhc-detect", data);
IRQF_TRIGGER_FALLING, "sdhc-detect", data);
if (ret)
goto err_gpio_free_2;
......
......@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/pinctrl/machine.h>
#include <linux/of_address.h>
#include <asm/mach/map.h>
......@@ -88,8 +89,15 @@ void __init imx51_init_early(void)
void __init imx53_init_early(void)
{
struct device_node *np;
void __iomem *base;
mxc_set_cpu_type(MXC_CPU_MX53);
mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
np = of_find_compatible_node(NULL, NULL, "fsl,imx53-iomuxc");
base = of_iomap(np, 0);
WARN_ON(!base);
mxc_iomux_v3_init(base);
imx_src_init();
}
......@@ -100,7 +108,14 @@ void __init mx51_init_irq(void)
void __init mx53_init_irq(void)
{
tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
struct device_node *np;
void __iomem *base;
np = of_find_compatible_node(NULL, NULL, "fsl,imx53-tzic");
base = of_iomap(np, 0);
WARN_ON(!base);
tzic_init_irq(base);
}
static struct sdma_platform_data imx51_sdma_pdata __initdata = {
......
......@@ -130,8 +130,7 @@ static int mxc_mmc1_init(struct device *dev,
gpio_direction_input(gpio_wp);
ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)),
detect_irq,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
detect_irq, IRQF_TRIGGER_FALLING,
"MMC detect", data);
if (ret)
goto exit_free_wp;
......
......@@ -34,6 +34,7 @@
#define MXC_CPU_MX35 35
#define MXC_CPU_MX51 51
#define MXC_CPU_MX53 53
#define MXC_CPU_IMX6SL 0x60
#define MXC_CPU_IMX6DL 0x61
#define MXC_CPU_IMX6Q 0x63
......@@ -152,6 +153,11 @@ extern unsigned int __mxc_cpu_type;
#endif
#ifndef __ASSEMBLY__
static inline bool cpu_is_imx6sl(void)
{
return __mxc_cpu_type == MXC_CPU_IMX6SL;
}
static inline bool cpu_is_imx6dl(void)
{
return __mxc_cpu_type == MXC_CPU_IMX6DL;
......
......@@ -10,9 +10,15 @@
* 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>
......@@ -22,6 +28,147 @@
#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_desc *iomuxc_irq_desc;
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;
}
/*
* Unmask the always pending IOMUXC interrupt #32 as wakeup source to
* deassert dsm_request signal, so that we can ensure dsm_request
* is not asserted when we're going to write CLPCR register to set LPM.
* After setting up LPM bits, we need to mask this wakeup source.
*/
iomuxc_irq_desc = irq_to_desc(32);
imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data);
writel_relaxed(val, ccm_base + CLPCR);
imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data);
return 0;
}
static int imx6q_suspend_finish(unsigned long val)
{
cpu_do_idle();
......@@ -33,14 +180,19 @@ 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);
imx_smp_prepare();
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:
......@@ -55,7 +207,29 @@ static const struct platform_suspend_ops imx6q_pm_ops = {
.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);
/*
* 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);
/* Set initial power mode */
imx6q_set_lpm(WAIT_CLOCKED);
suspend_set_ops(&imx6q_pm_ops);
}
......@@ -91,6 +91,7 @@ void imx_enable_cpu(int cpu, bool enable)
spin_lock(&scr_lock);
val = readl_relaxed(src_base + SRC_SCR);
val = enable ? val | mask : val & ~mask;
val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
writel_relaxed(val, src_base + SRC_SCR);
spin_unlock(&scr_lock);
}
......
......@@ -42,6 +42,9 @@ void mxc_restart(enum reboot_mode mode, const char *cmd)
{
unsigned int wcr_enable;
if (cpu_is_imx6q() || cpu_is_imx6dl())
imx_src_prepare_restart();
if (wdog_clk)
clk_enable(wdog_clk);
......@@ -52,6 +55,8 @@ void mxc_restart(enum reboot_mode mode, const char *cmd)
/* Assert SRS signal */
__raw_writew(wcr_enable, wdog_base);
/* write twice to ensure the request will not get ignored */
__raw_writew(wcr_enable, wdog_base);
/* wait for reset to assert... */
mdelay(500);
......
......@@ -250,7 +250,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
static struct irqaction mxc_timer_irq = {
.name = "i.MX Timer Tick",
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = mxc_timer_interrupt,
};
......
......@@ -363,4 +363,9 @@
#define IMX6Q_GPR13_SATA_TX_LVL_1_240_V (0x1f << 2)
#define IMX6Q_GPR13_SATA_MPLL_CLK_EN BIT(1)
#define IMX6Q_GPR13_SATA_TX_EDGE_RATE BIT(0)
/* For imx6sl iomux gpr register field define */
#define IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK (0x3 << 17)
#define IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK (0x1 << 14)
#endif /* __LINUX_IMX6Q_IOMUXC_GPR_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