[RFC][PATCH 03/10] arm: mxc: changes to common plat-mxc code to add support for i.MX5

From: Amit Kucheria
Date: Thu Dec 03 2009 - 21:47:37 EST


Changes separted to help in the review process

Signed-off-by: Amit Kucheria <amit.kucheria@xxxxxxxxxxxxx>
---
arch/arm/plat-mxc/include/mach/common.h | 3 +
arch/arm/plat-mxc/include/mach/debug-macro.S | 9 ++++
arch/arm/plat-mxc/include/mach/entry-macro.S | 34 ++++++++++++++++-
arch/arm/plat-mxc/include/mach/hardware.h | 4 ++
arch/arm/plat-mxc/include/mach/irqs.h | 9 ++++-
arch/arm/plat-mxc/include/mach/memory.h | 3 +
arch/arm/plat-mxc/include/mach/mxc.h | 13 ++++++
arch/arm/plat-mxc/include/mach/timex.h | 2 +
arch/arm/plat-mxc/time.c | 52 +++++++++++++++++++++++++-
9 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 286cb9b..b649382 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -20,6 +20,7 @@ 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 mxc91231_map_io(void);
extern void mxc_init_irq(void __iomem *);
extern void mx1_init_irq(void);
@@ -28,6 +29,7 @@ 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 mxc91231_init_irq(void);
extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
extern int mx1_clocks_init(unsigned long fref);
@@ -36,6 +38,7 @@ extern int mx25_clocks_init(unsigned long fref);
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, unsigned long ckih1, unsigned long ckih2);
extern int mxc91231_clocks_init(unsigned long fref);
extern int mxc_register_gpios(void);
extern int mxc_register_device(struct platform_device *pdev, void *data);
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index 15b2b14..9fe7300 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -44,6 +44,15 @@
#define UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
#endif

+#ifdef CONFIG_ARCH_MX5
+#ifdef UART_PADDR
+#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
+#endif
+#include <mach/mx51.h>
+#define UART_PADDR UART1_BASE_ADDR
+#define UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
+#endif
+
#ifdef CONFIG_ARCH_MXC91231
#ifdef UART_PADDR
#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S
index 7cf290e..e48948f 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Lennert Buytenhek <buytenh@xxxxxxxxxxxxxx>
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
*/

/*
@@ -18,11 +18,16 @@
.endm

.macro get_irqnr_preamble, base, tmp
+#ifndef CONFIG_MXC_TZIC
ldr \base, =avic_base
ldr \base, [\base]
#ifdef CONFIG_MXC_IRQ_PRIOR
ldr r4, [\base, #AVIC_NIMASK]
#endif
+#elif defined CONFIG_MXC_TZIC
+ ldr \base, =tzic_base
+ ldr \base, [\base]
+#endif /* CONFIG_MXC_TZIC */
.endm

.macro arch_ret_to_user, tmp1, tmp2
@@ -32,6 +37,7 @@
@ and returns its number in irqnr
@ and returns if an interrupt occured in irqstat
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+#ifndef CONFIG_MXC_TZIC
@ Load offset & priority of the highest priority
@ interrupt pending from AVIC_NIVECSR
ldr \irqstat, [\base, #0x40]
@@ -45,6 +51,32 @@
strne \tmp, [\base, #AVIC_NIMASK]
streq r4, [\base, #AVIC_NIMASK]
#endif
+#elif defined CONFIG_MXC_TZIC
+ @ Load offset & priority of the highest priority
+ @ interrupt pending.
+ @ 0xD80 is HIPND0 register
+ ldr \irqnr, =0
+ ldr \irqstat, =0x0D80
+1000:
+ ldr \tmp, [\irqstat, \base]
+ cmp \tmp, #0
+ bne 1001f
+ addeq \irqnr, \irqnr, #32
+ addeq \irqstat, \irqstat, #4
+ cmp \irqnr, #128
+ blo 1000b
+ b 2001f
+1001: ldr \irqstat, =1
+1002: tst \tmp, \irqstat
+ bne 2002f
+ movs \tmp, \tmp, lsr #1
+ addne \irqnr, \irqnr, #1
+ bne 1002b
+2001:
+ ldr \irqnr, =0
+2002:
+ movs \irqnr, \irqnr
+#endif
.endm

@ irq priority table (not used)
diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
index 78db754..55ebe88 100644
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ b/arch/arm/plat-mxc/include/mach/hardware.h
@@ -22,6 +22,10 @@

#include <asm/sizes.h>

+#ifdef CONFIG_ARCH_MX5
+#include <mach/mx51.h>
+#endif
+
#ifdef CONFIG_ARCH_MX3
#include <mach/mx3x.h>
#include <mach/mx31.h>
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index ead9d59..8740514 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -12,9 +12,13 @@
#define __ASM_ARCH_MXC_IRQS_H__

/*
- * So far all i.MX SoCs have 64 internal interrupts
+ * All i.MX SoCs have 64 internal interrupts, except IMX51 which has 128
*/
+#ifndef CONFIG_ARCH_MX5
#define MXC_INTERNAL_IRQS 64
+#else
+#define MXC_INTERNAL_IRQS 128
+#endif

#define MXC_GPIO_IRQ_START MXC_INTERNAL_IRQS

@@ -26,6 +30,8 @@
#define MXC_GPIO_IRQS (32 * 3)
#elif defined CONFIG_ARCH_MX25
#define MXC_GPIO_IRQS (32 * 4)
+#elif defined CONFIG_ARCH_MX5
+#define MXC_GPIO_IRQS (32 * 4)
#elif defined CONFIG_ARCH_MXC91231
#define MXC_GPIO_IRQS (32 * 4)
#endif
@@ -46,6 +52,7 @@
#else
#define MX3_IPU_IRQS 0
#endif
+/* REVISIT: Add IPU irqs on IMX51 */

#define NR_IRQS (MXC_IPU_IRQ_START + MX3_IPU_IRQS)

diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h
index d3afafd..e46626e 100644
--- a/arch/arm/plat-mxc/include/mach/memory.h
+++ b/arch/arm/plat-mxc/include/mach/memory.h
@@ -27,6 +27,9 @@
#elif defined CONFIG_ARCH_MXC91231
#define PHYS_OFFSET UL(0x90000000)
#endif
+#ifdef CONFIG_ARCH_MX5
+#define PHYS_OFFSET UL(0x90000000)
+#endif

#if defined(CONFIG_MX1_VIDEO)
/*
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 5199053..555e5f8 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -30,6 +30,7 @@
#define MXC_CPU_MX27 27
#define MXC_CPU_MX31 31
#define MXC_CPU_MX35 35
+#define MXC_CPU_MX51 51
#define MXC_CPU_MXC91231 91231

#ifndef __ASSEMBLY__
@@ -108,6 +109,18 @@ extern unsigned int __mxc_cpu_type;
# define cpu_is_mx35() (0)
#endif

+#ifdef CONFIG_ARCH_MX5
+# ifdef mxc_cpu_type
+# undef mxc_cpu_type
+# define mxc_cpu_type __mxc_cpu_type
+# else
+# define mxc_cpu_type MXC_CPU_MX51
+# endif
+# define cpu_is_mx51() (mxc_cpu_type == MXC_CPU_MX51)
+#else
+# define cpu_is_mx51() (0)
+#endif
+
#ifdef CONFIG_ARCH_MXC91231
# ifdef mxc_cpu_type
# undef mxc_cpu_type
diff --git a/arch/arm/plat-mxc/include/mach/timex.h b/arch/arm/plat-mxc/include/mach/timex.h
index 527a6c2..024416e 100644
--- a/arch/arm/plat-mxc/include/mach/timex.h
+++ b/arch/arm/plat-mxc/include/mach/timex.h
@@ -28,6 +28,8 @@
#define CLOCK_TICK_RATE 16625000
#elif defined CONFIG_ARCH_MX25
#define CLOCK_TICK_RATE 16000000
+#elif defined CONFIG_ARCH_MX5
+#define CLOCK_TICK_RATE 8000000
#elif defined CONFIG_ARCH_MXC91231
#define CLOCK_TICK_RATE 13000000
#endif
diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c
index 844567e..97fb590 100644
--- a/arch/arm/plat-mxc/time.c
+++ b/arch/arm/plat-mxc/time.c
@@ -25,6 +25,7 @@
#include <linux/irq.h>
#include <linux/clockchips.h>
#include <linux/clk.h>
+#include <linux/delay.h>

#include <mach/hardware.h>
#include <asm/mach/time.h>
@@ -57,6 +58,19 @@
#define MX3_TCN 0x24
#define MX3_TCMP 0x10

+/* MX51 */
+#define MX51_TCTL_FRR (1 << 9)
+#define MX51_TCTL_VAL (2 << 6) /* ipg_clk_highfreq is source */
+#define MX51_TCTL_TEN (1 << 0) /* Enable module */
+#define MX51_TCTL_TEN_MODE (1 << 1) /* Reset counter when module disabled */
+#define MX51_TCTL_WAITEN (1 << 3) /* Wait enable mode */
+#define MX51_TCTL_INT_ENABLE (1 << 0) /* Output compare 1 */
+#define MX51_IR 0x0c
+#define MX51_TSTAT 0x08
+#define MX51_TSTAT_OF1 (1 << 0)
+#define MX51_TCN 0x24
+#define MX51_TCMP 0x10
+
static struct clock_event_device clockevent_mxc;
static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;

@@ -68,6 +82,8 @@ static inline void gpt_irq_disable(void)

if (cpu_is_mx3() || cpu_is_mx25())
__raw_writel(0, timer_base + MX3_IR);
+ else if (cpu_is_mx51())
+ __raw_writel(0, timer_base + MX51_IR);
else {
tmp = __raw_readl(timer_base + MXC_TCTL);
__raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
@@ -78,6 +94,8 @@ static inline void gpt_irq_enable(void)
{
if (cpu_is_mx3() || cpu_is_mx25())
__raw_writel(1<<0, timer_base + MX3_IR);
+ else if (cpu_is_mx51())
+ __raw_writel(1<<0, timer_base + MX51_IR);
else {
__raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
timer_base + MXC_TCTL);
@@ -92,6 +110,8 @@ static void gpt_irq_acknowledge(void)
__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, timer_base + MX1_2_TSTAT);
if (cpu_is_mx3() || cpu_is_mx25())
__raw_writel(MX3_TSTAT_OF1, timer_base + MX3_TSTAT);
+ if (cpu_is_mx51())
+ __raw_writel(MX51_TSTAT_OF1, timer_base + MX51_TSTAT);
}

static cycle_t mx1_2_get_cycles(struct clocksource *cs)
@@ -104,6 +124,11 @@ static cycle_t mx3_get_cycles(struct clocksource *cs)
return __raw_readl(timer_base + MX3_TCN);
}

+static cycle_t mx51_get_cycles(struct clocksource *cs)
+{
+ return __raw_readl(timer_base + MX51_TCN);
+}
+
static struct clocksource clocksource_mxc = {
.name = "mxc_timer1",
.rating = 200,
@@ -119,6 +144,8 @@ static int __init mxc_clocksource_init(struct clk *timer_clk)

if (cpu_is_mx3() || cpu_is_mx25())
clocksource_mxc.read = mx3_get_cycles;
+ if (cpu_is_mx51())
+ clocksource_mxc.read = mx51_get_cycles;

clocksource_mxc.mult = clocksource_hz2mult(c,
clocksource_mxc.shift);
@@ -155,6 +182,19 @@ static int mx3_set_next_event(unsigned long evt,
-ETIME : 0;
}

+static int mx51_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+{
+ unsigned long tcmp;
+
+ tcmp = __raw_readl(timer_base + MX51_TCN) + evt;
+
+ __raw_writel(tcmp, timer_base + MX51_TCMP);
+
+ return (int)(tcmp - __raw_readl(timer_base + MX51_TCN)) < 0 ?
+ -ETIME : 0;
+}
+
#ifdef DEBUG
static const char *clock_event_mode_label[] = {
[CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
@@ -183,6 +223,9 @@ static void mxc_set_mode(enum clock_event_mode mode,
if (cpu_is_mx3() || cpu_is_mx25())
__raw_writel(__raw_readl(timer_base + MX3_TCN) - 3,
timer_base + MX3_TCMP);
+ else if (cpu_is_mx51())
+ __raw_writel(__raw_readl(timer_base + MX51_TCN) - 3,
+ timer_base + MX51_TCMP);
else
__raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
timer_base + MX1_2_TCMP);
@@ -235,6 +278,8 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)

if (cpu_is_mx3() || cpu_is_mx25())
tstat = __raw_readl(timer_base + MX3_TSTAT);
+ if (cpu_is_mx51())
+ tstat = __raw_readl(timer_base + MX51_TSTAT);
else
tstat = __raw_readl(timer_base + MX1_2_TSTAT);

@@ -266,6 +311,8 @@ static int __init mxc_clockevent_init(struct clk *timer_clk)

if (cpu_is_mx3() || cpu_is_mx25())
clockevent_mxc.set_next_event = mx3_set_next_event;
+ if (cpu_is_mx51())
+ clockevent_mxc.set_next_event = mx51_set_next_event;

clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
clockevent_mxc.shift);
@@ -298,7 +345,10 @@ void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq)

if (cpu_is_mx3() || cpu_is_mx25())
tctl_val = MX3_TCTL_CLK_IPG | MX3_TCTL_FRR | MX3_TCTL_WAITEN | MXC_TCTL_TEN;
- else
+ else if (cpu_is_mx51()) {
+ tctl_val = MX51_TCTL_FRR | MX51_TCTL_VAL | MX51_TCTL_WAITEN | MX51_TCTL_TEN;
+ __raw_writel(MX51_TCTL_INT_ENABLE, timer_base + MX51_IR);
+ } else
tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;

__raw_writel(tctl_val, timer_base + MXC_TCTL);
--
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/