aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-spear
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-04-19 16:30:31 -0400
committerArnd Bergmann <arnd@arndb.de>2013-04-19 16:50:01 -0400
commit1b361942b53c33f38d55065c13785aadb5103a18 (patch)
tree07b26d32b175f27f18f1fca3d5944a58f89cd17f /arch/arm/mach-spear
parent61b464aef0e306f141dbc0bb3f9c58049a987a7e (diff)
parentbcf3e72eff584136600a51a5b30ef7a794664d19 (diff)
Merge branch 'spear/multiplatform' into late/cleanup
This is a prerequisite for the spear/dwdma series. Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm/mach-spear')
-rw-r--r--arch/arm/mach-spear/Kconfig103
-rw-r--r--arch/arm/mach-spear/Makefile24
-rw-r--r--arch/arm/mach-spear/Makefile.boot3
-rw-r--r--arch/arm/mach-spear/generic.h59
-rw-r--r--arch/arm/mach-spear/headsmp.S47
-rw-r--r--arch/arm/mach-spear/hotplug.c103
-rw-r--r--arch/arm/mach-spear/include/mach/debug-macro.S36
-rw-r--r--arch/arm/mach-spear/include/mach/irqs.h35
-rw-r--r--arch/arm/mach-spear/include/mach/misc_regs.h22
-rw-r--r--arch/arm/mach-spear/include/mach/spear.h95
-rw-r--r--arch/arm/mach-spear/include/mach/timex.h19
-rw-r--r--arch/arm/mach-spear/include/mach/uncompress.h42
-rw-r--r--arch/arm/mach-spear/pl080.c78
-rw-r--r--arch/arm/mach-spear/pl080.h21
-rw-r--r--arch/arm/mach-spear/platsmp.c130
-rw-r--r--arch/arm/mach-spear/restart.c34
-rw-r--r--arch/arm/mach-spear/spear1310.c96
-rw-r--r--arch/arm/mach-spear/spear1340.c193
-rw-r--r--arch/arm/mach-spear/spear13xx-dma.h128
-rw-r--r--arch/arm/mach-spear/spear13xx.c184
-rw-r--r--arch/arm/mach-spear/spear300.c220
-rw-r--r--arch/arm/mach-spear/spear310.c262
-rw-r--r--arch/arm/mach-spear/spear320.c277
-rw-r--r--arch/arm/mach-spear/spear3xx.c116
-rw-r--r--arch/arm/mach-spear/spear6xx.c431
-rw-r--r--arch/arm/mach-spear/time.c245
26 files changed, 3003 insertions, 0 deletions
diff --git a/arch/arm/mach-spear/Kconfig b/arch/arm/mach-spear/Kconfig
new file mode 100644
index 000000000000..5412aeb377ac
--- /dev/null
+++ b/arch/arm/mach-spear/Kconfig
@@ -0,0 +1,103 @@
1#
2# SPEAr Platform configuration file
3#
4
5menuconfig PLAT_SPEAR
6 bool "ST SPEAr Family" if ARCH_MULTI_V7 || ARCH_MULTI_V5
7 default PLAT_SPEAR_SINGLE
8 select ARCH_REQUIRE_GPIOLIB
9 select ARM_AMBA
10 select CLKDEV_LOOKUP
11 select CLKSRC_MMIO
12 select COMMON_CLK
13 select GENERIC_CLOCKEVENTS
14 select HAVE_CLK
15
16if PLAT_SPEAR
17
18config ARCH_SPEAR13XX
19 bool "ST SPEAr13xx"
20 depends on ARCH_MULTI_V7 || PLAT_SPEAR_SINGLE
21 select ARCH_HAS_CPUFREQ
22 select ARM_GIC
23 select CPU_V7
24 select GPIO_SPEAR_SPICS
25 select HAVE_SMP
26 select MIGHT_HAVE_CACHE_L2X0
27 select PINCTRL
28 select USE_OF
29 help
30 Supports for ARM's SPEAR13XX family
31
32if ARCH_SPEAR13XX
33
34config MACH_SPEAR1310
35 bool "SPEAr1310 Machine support with Device Tree"
36 select PINCTRL_SPEAR1310
37 help
38 Supports ST SPEAr1310 machine configured via the device-tree
39
40config MACH_SPEAR1340
41 bool "SPEAr1340 Machine support with Device Tree"
42 select PINCTRL_SPEAR1340
43 help
44 Supports ST SPEAr1340 machine configured via the device-tree
45
46endif #ARCH_SPEAR13XX
47
48config ARCH_SPEAR3XX
49 bool "ST SPEAr3xx"
50 depends on ARCH_MULTI_V5 || PLAT_SPEAR_SINGLE
51 depends on !ARCH_SPEAR13XX
52 select ARM_VIC
53 select CPU_ARM926T
54 select PINCTRL
55 select USE_OF
56 help
57 Supports for ARM's SPEAR3XX family
58
59if ARCH_SPEAR3XX
60
61config MACH_SPEAR300
62 bool "SPEAr300 Machine support with Device Tree"
63 select PINCTRL_SPEAR300
64 help
65 Supports ST SPEAr300 machine configured via the device-tree
66
67config MACH_SPEAR310
68 bool "SPEAr310 Machine support with Device Tree"
69 select PINCTRL_SPEAR310
70 help
71 Supports ST SPEAr310 machine configured via the device-tree
72
73config MACH_SPEAR320
74 bool "SPEAr320 Machine support with Device Tree"
75 select PINCTRL_SPEAR320
76 help
77 Supports ST SPEAr320 machine configured via the device-tree
78
79endif
80
81config ARCH_SPEAR6XX
82 bool "ST SPEAr6XX"
83 depends on ARCH_MULTI_V5 || PLAT_SPEAR_SINGLE
84 depends on !ARCH_SPEAR13XX
85 select ARM_VIC
86 select CPU_ARM926T
87 help
88 Supports for ARM's SPEAR6XX family
89
90config MACH_SPEAR600
91 def_bool y
92 depends on ARCH_SPEAR6XX
93 select USE_OF
94 help
95 Supports ST SPEAr600 boards configured via the device-treesource "arch/arm/mach-spear6xx/Kconfig"
96
97config ARCH_SPEAR_AUTO
98 def_bool PLAT_SPEAR_SINGLE
99 depends on !ARCH_SPEAR13XX && !ARCH_SPEAR6XX
100 select ARCH_SPEAR3XX
101
102endif
103
diff --git a/arch/arm/mach-spear/Makefile b/arch/arm/mach-spear/Makefile
new file mode 100644
index 000000000000..dc9ce80508ad
--- /dev/null
+++ b/arch/arm/mach-spear/Makefile
@@ -0,0 +1,24 @@
1#
2# SPEAr Platform specific Makefile
3#
4
5ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
6
7# Common support
8obj-y := restart.o time.o
9
10obj-$(CONFIG_SMP) += headsmp.o platsmp.o
11obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
12
13obj-$(CONFIG_ARCH_SPEAR13XX) += spear13xx.o
14obj-$(CONFIG_MACH_SPEAR1310) += spear1310.o
15obj-$(CONFIG_MACH_SPEAR1340) += spear1340.o
16
17obj-$(CONFIG_ARCH_SPEAR3XX) += spear3xx.o
18obj-$(CONFIG_ARCH_SPEAR3XX) += pl080.o
19obj-$(CONFIG_MACH_SPEAR300) += spear300.o
20obj-$(CONFIG_MACH_SPEAR310) += spear310.o
21obj-$(CONFIG_MACH_SPEAR320) += spear320.o
22
23obj-$(CONFIG_ARCH_SPEAR6XX) += spear6xx.o
24obj-$(CONFIG_ARCH_SPEAR6XX) += pl080.o
diff --git a/arch/arm/mach-spear/Makefile.boot b/arch/arm/mach-spear/Makefile.boot
new file mode 100644
index 000000000000..4674a4c221db
--- /dev/null
+++ b/arch/arm/mach-spear/Makefile.boot
@@ -0,0 +1,3 @@
1zreladdr-y += 0x00008000
2params_phys-y := 0x00000100
3initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-spear/generic.h b/arch/arm/mach-spear/generic.h
new file mode 100644
index 000000000000..8ba7e75b648d
--- /dev/null
+++ b/arch/arm/mach-spear/generic.h
@@ -0,0 +1,59 @@
1/*
2 * spear machine family generic header file
3 *
4 * Copyright (C) 2009-2012 ST Microelectronics
5 * Rajeev Kumar <rajeev-dlh.kumar@st.com>
6 * Viresh Kumar <viresh.linux@gmail.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#ifndef __MACH_GENERIC_H
14#define __MACH_GENERIC_H
15
16#include <linux/dmaengine.h>
17#include <linux/amba/pl08x.h>
18#include <linux/init.h>
19#include <asm/mach/time.h>
20
21extern void spear13xx_timer_init(void);
22extern void spear3xx_timer_init(void);
23extern struct pl022_ssp_controller pl022_plat_data;
24extern struct pl08x_platform_data pl080_plat_data;
25extern struct dw_dma_platform_data dmac_plat_data;
26extern struct dw_dma_slave cf_dma_priv;
27extern struct dw_dma_slave nand_read_dma_priv;
28extern struct dw_dma_slave nand_write_dma_priv;
29bool dw_dma_filter(struct dma_chan *chan, void *slave);
30
31void __init spear_setup_of_timer(void);
32void __init spear3xx_clk_init(void __iomem *misc_base,
33 void __iomem *soc_config_base);
34void __init spear3xx_map_io(void);
35void __init spear3xx_dt_init_irq(void);
36void __init spear6xx_clk_init(void __iomem *misc_base);
37void __init spear13xx_map_io(void);
38void __init spear13xx_l2x0_init(void);
39
40void spear_restart(char, const char *);
41
42void spear13xx_secondary_startup(void);
43void __cpuinit spear13xx_cpu_die(unsigned int cpu);
44
45extern struct smp_operations spear13xx_smp_ops;
46
47#ifdef CONFIG_MACH_SPEAR1310
48void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base);
49#else
50static inline void spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base) {}
51#endif
52
53#ifdef CONFIG_MACH_SPEAR1340
54void __init spear1340_clk_init(void __iomem *misc_base);
55#else
56static inline void spear1340_clk_init(void __iomem *misc_base) {}
57#endif
58
59#endif /* __MACH_GENERIC_H */
diff --git a/arch/arm/mach-spear/headsmp.S b/arch/arm/mach-spear/headsmp.S
new file mode 100644
index 000000000000..ed85473a047f
--- /dev/null
+++ b/arch/arm/mach-spear/headsmp.S
@@ -0,0 +1,47 @@
1/*
2 * arch/arm/mach-spear13XX/headsmp.S
3 *
4 * Picked from realview
5 * Copyright (c) 2012 ST Microelectronics Limited
6 * Shiraz Hashim <shiraz.hashim@st.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/linkage.h>
14#include <linux/init.h>
15
16 __INIT
17
18/*
19 * spear13xx specific entry point for secondary CPUs. This provides
20 * a "holding pen" into which all secondary cores are held until we're
21 * ready for them to initialise.
22 */
23ENTRY(spear13xx_secondary_startup)
24 mrc p15, 0, r0, c0, c0, 5
25 and r0, r0, #15
26 adr r4, 1f
27 ldmia r4, {r5, r6}
28 sub r4, r4, r5
29 add r6, r6, r4
30pen: ldr r7, [r6]
31 cmp r7, r0
32 bne pen
33
34 /* re-enable coherency */
35 mrc p15, 0, r0, c1, c0, 1
36 orr r0, r0, #(1 << 6) | (1 << 0)
37 mcr p15, 0, r0, c1, c0, 1
38 /*
39 * we've been released from the holding pen: secondary_stack
40 * should now contain the SVC stack for this core
41 */
42 b secondary_startup
43
44 .align
451: .long .
46 .long pen_release
47ENDPROC(spear13xx_secondary_startup)
diff --git a/arch/arm/mach-spear/hotplug.c b/arch/arm/mach-spear/hotplug.c
new file mode 100644
index 000000000000..a7d2dd11a4f2
--- /dev/null
+++ b/arch/arm/mach-spear/hotplug.c
@@ -0,0 +1,103 @@
1/*
2 * linux/arch/arm/mach-spear13xx/hotplug.c
3 *
4 * Copyright (C) 2012 ST Microelectronics Ltd.
5 * Deepak Sikri <deepak.sikri@st.com>
6 *
7 * based upon linux/arch/arm/mach-realview/hotplug.c
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#include <linux/kernel.h>
14#include <linux/errno.h>
15#include <linux/smp.h>
16#include <asm/cacheflush.h>
17#include <asm/cp15.h>
18#include <asm/smp_plat.h>
19
20static inline void cpu_enter_lowpower(void)
21{
22 unsigned int v;
23
24 flush_cache_all();
25 asm volatile(
26 " mcr p15, 0, %1, c7, c5, 0\n"
27 " dsb\n"
28 /*
29 * Turn off coherency
30 */
31 " mrc p15, 0, %0, c1, c0, 1\n"
32 " bic %0, %0, #0x20\n"
33 " mcr p15, 0, %0, c1, c0, 1\n"
34 " mrc p15, 0, %0, c1, c0, 0\n"
35 " bic %0, %0, %2\n"
36 " mcr p15, 0, %0, c1, c0, 0\n"
37 : "=&r" (v)
38 : "r" (0), "Ir" (CR_C)
39 : "cc", "memory");
40}
41
42static inline void cpu_leave_lowpower(void)
43{
44 unsigned int v;
45
46 asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
47 " orr %0, %0, %1\n"
48 " mcr p15, 0, %0, c1, c0, 0\n"
49 " mrc p15, 0, %0, c1, c0, 1\n"
50 " orr %0, %0, #0x20\n"
51 " mcr p15, 0, %0, c1, c0, 1\n"
52 : "=&r" (v)
53 : "Ir" (CR_C)
54 : "cc");
55}
56
57static inline void spear13xx_do_lowpower(unsigned int cpu, int *spurious)
58{
59 for (;;) {
60 wfi();
61
62 if (pen_release == cpu) {
63 /*
64 * OK, proper wakeup, we're done
65 */
66 break;
67 }
68
69 /*
70 * Getting here, means that we have come out of WFI without
71 * having been woken up - this shouldn't happen
72 *
73 * Just note it happening - when we're woken, we can report
74 * its occurrence.
75 */
76 (*spurious)++;
77 }
78}
79
80/*
81 * platform-specific code to shutdown a CPU
82 *
83 * Called with IRQs disabled
84 */
85void __ref spear13xx_cpu_die(unsigned int cpu)
86{
87 int spurious = 0;
88
89 /*
90 * we're ready for shutdown now, so do it
91 */
92 cpu_enter_lowpower();
93 spear13xx_do_lowpower(cpu, &spurious);
94
95 /*
96 * bring this CPU back into the world of cache
97 * coherency, and then restore interrupts
98 */
99 cpu_leave_lowpower();
100
101 if (spurious)
102 pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
103}
diff --git a/arch/arm/mach-spear/include/mach/debug-macro.S b/arch/arm/mach-spear/include/mach/debug-macro.S
new file mode 100644
index 000000000000..75b05ad0fbad
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
1/*
2 * arch/arm/plat-spear/include/plat/debug-macro.S
3 *
4 * Debugging macro include header for spear platform
5 *
6 * Copyright (C) 2009 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#include <linux/amba/serial.h>
15#include <mach/spear.h>
16
17 .macro addruart, rp, rv, tmp
18 mov \rp, #SPEAR_DBG_UART_BASE @ Physical base
19 mov \rv, #VA_SPEAR_DBG_UART_BASE @ Virtual base
20 .endm
21
22 .macro senduart, rd, rx
23 strb \rd, [\rx, #UART01x_DR] @ ASC_TX_BUFFER
24 .endm
25
26 .macro waituart, rd, rx
271001: ldr \rd, [\rx, #UART01x_FR] @ FLAG REGISTER
28 tst \rd, #UART01x_FR_TXFF @ TX_FULL
29 bne 1001b
30 .endm
31
32 .macro busyuart, rd, rx
331002: ldr \rd, [\rx, #UART01x_FR] @ FLAG REGISTER
34 tst \rd, #UART011_FR_TXFE @ TX_EMPTY
35 beq 1002b
36 .endm
diff --git a/arch/arm/mach-spear/include/mach/irqs.h b/arch/arm/mach-spear/include/mach/irqs.h
new file mode 100644
index 000000000000..92da0a8c6bce
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/irqs.h
@@ -0,0 +1,35 @@
1/*
2 * IRQ helper macros for spear machine family
3 *
4 * Copyright (C) 2009-2012 ST Microelectronics
5 * Rajeev Kumar <rajeev-dlh.kumar@st.com>
6 * Viresh Kumar <viresh.linux@gmail.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#ifndef __MACH_IRQS_H
14#define __MACH_IRQS_H
15
16#ifdef CONFIG_ARCH_SPEAR3XX
17#define NR_IRQS 256
18#endif
19
20#ifdef CONFIG_ARCH_SPEAR6XX
21/* IRQ definitions */
22/* VIC 1 */
23#define IRQ_VIC_END 64
24
25/* GPIO pins virtual irqs */
26#define VIRTUAL_IRQS 24
27#define NR_IRQS (IRQ_VIC_END + VIRTUAL_IRQS)
28#endif
29
30#ifdef CONFIG_ARCH_SPEAR13XX
31#define IRQ_GIC_END 160
32#define NR_IRQS IRQ_GIC_END
33#endif
34
35#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear/include/mach/misc_regs.h b/arch/arm/mach-spear/include/mach/misc_regs.h
new file mode 100644
index 000000000000..935639ce59ba
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/misc_regs.h
@@ -0,0 +1,22 @@
1/*
2 * arch/arm/mach-spear3xx/include/mach/misc_regs.h
3 *
4 * Miscellaneous registers definitions for SPEAr3xx machine family
5 *
6 * Copyright (C) 2009 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#ifndef __MACH_MISC_REGS_H
15#define __MACH_MISC_REGS_H
16
17#include <mach/spear.h>
18
19#define MISC_BASE (VA_SPEAR_ICM3_MISC_REG_BASE)
20#define DMA_CHN_CFG (MISC_BASE + 0x0A0)
21
22#endif /* __MACH_MISC_REGS_H */
diff --git a/arch/arm/mach-spear/include/mach/spear.h b/arch/arm/mach-spear/include/mach/spear.h
new file mode 100644
index 000000000000..374ddc393df1
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/spear.h
@@ -0,0 +1,95 @@
1/*
2 * SPEAr3xx/6xx Machine family specific definition
3 *
4 * Copyright (C) 2009,2012 ST Microelectronics
5 * Rajeev Kumar<rajeev-dlh.kumar@st.com>
6 * Viresh Kumar <viresh.linux@gmail.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#ifndef __MACH_SPEAR_H
14#define __MACH_SPEAR_H
15
16#include <asm/memory.h>
17
18#if defined(CONFIG_ARCH_SPEAR3XX) || defined (CONFIG_ARCH_SPEAR6XX)
19
20/* ICM1 - Low speed connection */
21#define SPEAR_ICM1_2_BASE UL(0xD0000000)
22#define VA_SPEAR_ICM1_2_BASE IOMEM(0xFD000000)
23#define SPEAR_ICM1_UART_BASE UL(0xD0000000)
24#define VA_SPEAR_ICM1_UART_BASE (VA_SPEAR_ICM1_2_BASE - SPEAR_ICM1_2_BASE + SPEAR_ICM1_UART_BASE)
25#define SPEAR3XX_ICM1_SSP_BASE UL(0xD0100000)
26
27/* ML-1, 2 - Multi Layer CPU Subsystem */
28#define SPEAR_ICM3_ML1_2_BASE UL(0xF0000000)
29#define VA_SPEAR6XX_ML_CPU_BASE IOMEM(0xF0000000)
30
31/* ICM3 - Basic Subsystem */
32#define SPEAR_ICM3_SMI_CTRL_BASE UL(0xFC000000)
33#define VA_SPEAR_ICM3_SMI_CTRL_BASE IOMEM(0xFC000000)
34#define SPEAR_ICM3_DMA_BASE UL(0xFC400000)
35#define SPEAR_ICM3_SYS_CTRL_BASE UL(0xFCA00000)
36#define VA_SPEAR_ICM3_SYS_CTRL_BASE (VA_SPEAR_ICM3_SMI_CTRL_BASE - SPEAR_ICM3_SMI_CTRL_BASE + SPEAR_ICM3_SYS_CTRL_BASE)
37#define SPEAR_ICM3_MISC_REG_BASE UL(0xFCA80000)
38#define VA_SPEAR_ICM3_MISC_REG_BASE (VA_SPEAR_ICM3_SMI_CTRL_BASE - SPEAR_ICM3_SMI_CTRL_BASE + SPEAR_ICM3_MISC_REG_BASE)
39
40/* Debug uart for linux, will be used for debug and uncompress messages */
41#define SPEAR_DBG_UART_BASE SPEAR_ICM1_UART_BASE
42#define VA_SPEAR_DBG_UART_BASE VA_SPEAR_ICM1_UART_BASE
43
44/* Sysctl base for spear platform */
45#define SPEAR_SYS_CTRL_BASE SPEAR_ICM3_SYS_CTRL_BASE
46#define VA_SPEAR_SYS_CTRL_BASE VA_SPEAR_ICM3_SYS_CTRL_BASE
47#endif /* SPEAR3xx || SPEAR6XX */
48
49/* SPEAr320 Macros */
50#define SPEAR320_SOC_CONFIG_BASE UL(0xB3000000)
51#define VA_SPEAR320_SOC_CONFIG_BASE IOMEM(0xFE000000)
52
53#ifdef CONFIG_ARCH_SPEAR13XX
54
55#define PERIP_GRP2_BASE UL(0xB3000000)
56#define VA_PERIP_GRP2_BASE IOMEM(0xFE000000)
57#define MCIF_SDHCI_BASE UL(0xB3000000)
58#define SYSRAM0_BASE UL(0xB3800000)
59#define VA_SYSRAM0_BASE IOMEM(0xFE800000)
60#define SYS_LOCATION (VA_SYSRAM0_BASE + 0x600)
61
62#define PERIP_GRP1_BASE UL(0xE0000000)
63#define VA_PERIP_GRP1_BASE IOMEM(0xFD000000)
64#define UART_BASE UL(0xE0000000)
65#define VA_UART_BASE IOMEM(0xFD000000)
66#define SSP_BASE UL(0xE0100000)
67#define MISC_BASE UL(0xE0700000)
68#define VA_MISC_BASE IOMEM(0xFD700000)
69
70#define A9SM_AND_MPMC_BASE UL(0xEC000000)
71#define VA_A9SM_AND_MPMC_BASE IOMEM(0xFC000000)
72
73#define SPEAR1310_RAS_BASE UL(0xD8400000)
74#define VA_SPEAR1310_RAS_BASE IOMEM(UL(0xFA400000))
75
76/* A9SM peripheral offsets */
77#define A9SM_PERIP_BASE UL(0xEC800000)
78#define VA_A9SM_PERIP_BASE IOMEM(0xFC800000)
79#define VA_SCU_BASE (VA_A9SM_PERIP_BASE + 0x00)
80
81#define L2CC_BASE UL(0xED000000)
82#define VA_L2CC_BASE IOMEM(UL(0xFB000000))
83
84/* others */
85#define DMAC0_BASE UL(0xEA800000)
86#define DMAC1_BASE UL(0xEB000000)
87#define MCIF_CF_BASE UL(0xB2800000)
88
89/* Debug uart for linux, will be used for debug and uncompress messages */
90#define SPEAR_DBG_UART_BASE UART_BASE
91#define VA_SPEAR_DBG_UART_BASE VA_UART_BASE
92
93#endif /* SPEAR13XX */
94
95#endif /* __MACH_SPEAR_H */
diff --git a/arch/arm/mach-spear/include/mach/timex.h b/arch/arm/mach-spear/include/mach/timex.h
new file mode 100644
index 000000000000..ef95e5b780bd
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/timex.h
@@ -0,0 +1,19 @@
1/*
2 * arch/arm/plat-spear/include/plat/timex.h
3 *
4 * SPEAr platform specific timex definitions
5 *
6 * Copyright (C) 2009 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#ifndef __PLAT_TIMEX_H
15#define __PLAT_TIMEX_H
16
17#define CLOCK_TICK_RATE 48000000
18
19#endif /* __PLAT_TIMEX_H */
diff --git a/arch/arm/mach-spear/include/mach/uncompress.h b/arch/arm/mach-spear/include/mach/uncompress.h
new file mode 100644
index 000000000000..51b2dc93e4da
--- /dev/null
+++ b/arch/arm/mach-spear/include/mach/uncompress.h
@@ -0,0 +1,42 @@
1/*
2 * arch/arm/plat-spear/include/plat/uncompress.h
3 *
4 * Serial port stubs for kernel decompress status messages
5 *
6 * Copyright (C) 2009 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#include <linux/io.h>
15#include <linux/amba/serial.h>
16#include <mach/spear.h>
17
18#ifndef __PLAT_UNCOMPRESS_H
19#define __PLAT_UNCOMPRESS_H
20/*
21 * This does not append a newline
22 */
23static inline void putc(int c)
24{
25 void __iomem *base = (void __iomem *)SPEAR_DBG_UART_BASE;
26
27 while (readl_relaxed(base + UART01x_FR) & UART01x_FR_TXFF)
28 barrier();
29
30 writel_relaxed(c, base + UART01x_DR);
31}
32
33static inline void flush(void)
34{
35}
36
37/*
38 * nothing to do
39 */
40#define arch_decomp_setup()
41
42#endif /* __PLAT_UNCOMPRESS_H */
diff --git a/arch/arm/mach-spear/pl080.c b/arch/arm/mach-spear/pl080.c
new file mode 100644
index 000000000000..cfa1199d0f4a
--- /dev/null
+++ b/arch/arm/mach-spear/pl080.c
@@ -0,0 +1,78 @@
1/*
2 * arch/arm/plat-spear/pl080.c
3 *
4 * DMAC pl080 definitions for SPEAr platform
5 *
6 * Copyright (C) 2012 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#include <linux/amba/pl08x.h>
15#include <linux/amba/bus.h>
16#include <linux/bug.h>
17#include <linux/err.h>
18#include <linux/io.h>
19#include <linux/spinlock_types.h>
20#include <mach/spear.h>
21#include <mach/misc_regs.h>
22
23static spinlock_t lock = __SPIN_LOCK_UNLOCKED(x);
24
25struct {
26 unsigned char busy;
27 unsigned char val;
28} signals[16] = {{0, 0}, };
29
30int pl080_get_signal(const struct pl08x_channel_data *cd)
31{
32 unsigned int signal = cd->min_signal, val;
33 unsigned long flags;
34
35 spin_lock_irqsave(&lock, flags);
36
37 /* Return if signal is already acquired by somebody else */
38 if (signals[signal].busy &&
39 (signals[signal].val != cd->muxval)) {
40 spin_unlock_irqrestore(&lock, flags);
41 return -EBUSY;
42 }
43
44 /* If acquiring for the first time, configure it */
45 if (!signals[signal].busy) {
46 val = readl(DMA_CHN_CFG);
47
48 /*
49 * Each request line has two bits in DMA_CHN_CFG register. To
50 * goto the bits of current request line, do left shift of
51 * value by 2 * signal number.
52 */
53 val &= ~(0x3 << (signal * 2));
54 val |= cd->muxval << (signal * 2);
55 writel(val, DMA_CHN_CFG);
56 }
57
58 signals[signal].busy++;
59 signals[signal].val = cd->muxval;
60 spin_unlock_irqrestore(&lock, flags);
61
62 return signal;
63}
64
65void pl080_put_signal(const struct pl08x_channel_data *cd, int signal)
66{
67 unsigned long flags;
68
69 spin_lock_irqsave(&lock, flags);
70
71 /* if signal is not used */
72 if (!signals[signal].busy)
73 BUG();
74
75 signals[signal].busy--;
76
77 spin_unlock_irqrestore(&lock, flags);
78}
diff --git a/arch/arm/mach-spear/pl080.h b/arch/arm/mach-spear/pl080.h
new file mode 100644
index 000000000000..eb6590ded40d
--- /dev/null
+++ b/arch/arm/mach-spear/pl080.h
@@ -0,0 +1,21 @@
1/*
2 * arch/arm/plat-spear/include/plat/pl080.h
3 *
4 * DMAC pl080 definitions for SPEAr platform
5 *
6 * Copyright (C) 2012 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#ifndef __PLAT_PL080_H
15#define __PLAT_PL080_H
16
17struct pl08x_channel_data;
18int pl080_get_signal(const struct pl08x_channel_data *cd);
19void pl080_put_signal(const struct pl08x_channel_data *cd, int signal);
20
21#endif /* __PLAT_PL080_H */
diff --git a/arch/arm/mach-spear/platsmp.c b/arch/arm/mach-spear/platsmp.c
new file mode 100644
index 000000000000..927979e26b4d
--- /dev/null
+++ b/arch/arm/mach-spear/platsmp.c
@@ -0,0 +1,130 @@
1/*
2 * arch/arm/mach-spear13xx/platsmp.c
3 *
4 * based upon linux/arch/arm/mach-realview/platsmp.c
5 *
6 * Copyright (C) 2012 ST Microelectronics Ltd.
7 * Shiraz Hashim <shiraz.hashim@st.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/delay.h>
15#include <linux/jiffies.h>
16#include <linux/io.h>
17#include <linux/smp.h>
18#include <linux/irqchip/arm-gic.h>
19#include <asm/cacheflush.h>
20#include <asm/smp_scu.h>
21#include <mach/spear.h>
22#include "generic.h"
23
24static DEFINE_SPINLOCK(boot_lock);
25
26static void __iomem *scu_base = IOMEM(VA_SCU_BASE);
27
28static void __cpuinit spear13xx_secondary_init(unsigned int cpu)
29{
30 /*
31 * if any interrupts are already enabled for the primary
32 * core (e.g. timer irq), then they will not have been enabled
33 * for us: do so
34 */
35 gic_secondary_init(0);
36
37 /*
38 * let the primary processor know we're out of the
39 * pen, then head off into the C entry point
40 */
41 pen_release = -1;
42 smp_wmb();
43
44 /*
45 * Synchronise with the boot thread.
46 */
47 spin_lock(&boot_lock);
48 spin_unlock(&boot_lock);
49}
50
51static int __cpuinit spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle)
52{
53 unsigned long timeout;
54
55 /*
56 * set synchronisation state between this boot processor
57 * and the secondary one
58 */
59 spin_lock(&boot_lock);
60
61 /*
62 * The secondary processor is waiting to be released from
63 * the holding pen - release it, then wait for it to flag
64 * that it has been released by resetting pen_release.
65 *
66 * Note that "pen_release" is the hardware CPU ID, whereas
67 * "cpu" is Linux's internal ID.
68 */
69 pen_release = cpu;
70 flush_cache_all();
71 outer_flush_all();
72
73 timeout = jiffies + (1 * HZ);
74 while (time_before(jiffies, timeout)) {
75 smp_rmb();
76 if (pen_release == -1)
77 break;
78
79 udelay(10);
80 }
81
82 /*
83 * now the secondary core is starting up let it run its
84 * calibrations, then wait for it to finish
85 */
86 spin_unlock(&boot_lock);
87
88 return pen_release != -1 ? -ENOSYS : 0;
89}
90
91/*
92 * Initialise the CPU possible map early - this describes the CPUs
93 * which may be present or become present in the system.
94 */
95static void __init spear13xx_smp_init_cpus(void)
96{
97 unsigned int i, ncores = scu_get_core_count(scu_base);
98
99 if (ncores > nr_cpu_ids) {
100 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
101 ncores, nr_cpu_ids);
102 ncores = nr_cpu_ids;
103 }
104
105 for (i = 0; i < ncores; i++)
106 set_cpu_possible(i, true);
107}
108
109static void __init spear13xx_smp_prepare_cpus(unsigned int max_cpus)
110{
111
112 scu_enable(scu_base);
113
114 /*
115 * Write the address of secondary startup into the system-wide location
116 * (presently it is in SRAM). The BootMonitor waits until it receives a
117 * soft interrupt, and then the secondary CPU branches to this address.
118 */
119 __raw_writel(virt_to_phys(spear13xx_secondary_startup), SYS_LOCATION);
120}
121
122struct smp_operations spear13xx_smp_ops __initdata = {
123 .smp_init_cpus = spear13xx_smp_init_cpus,
124 .smp_prepare_cpus = spear13xx_smp_prepare_cpus,
125 .smp_secondary_init = spear13xx_secondary_init,
126 .smp_boot_secondary = spear13xx_boot_secondary,
127#ifdef CONFIG_HOTPLUG_CPU
128 .cpu_die = spear13xx_cpu_die,
129#endif
130};
diff --git a/arch/arm/mach-spear/restart.c b/arch/arm/mach-spear/restart.c
new file mode 100644
index 000000000000..2b44500bb718
--- /dev/null
+++ b/arch/arm/mach-spear/restart.c
@@ -0,0 +1,34 @@
1/*
2 * arch/arm/plat-spear/restart.c
3 *
4 * SPEAr platform specific restart functions
5 *
6 * Copyright (C) 2009 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13#include <linux/io.h>
14#include <linux/amba/sp810.h>
15#include <asm/system_misc.h>
16#include <mach/spear.h>
17#include "generic.h"
18
19#define SPEAR13XX_SYS_SW_RES (VA_MISC_BASE + 0x204)
20void spear_restart(char mode, const char *cmd)
21{
22 if (mode == 's') {
23 /* software reset, Jump into ROM at address 0 */
24 soft_restart(0);
25 } else {
26 /* hardware reset, Use on-chip reset capability */
27#ifdef CONFIG_ARCH_SPEAR13XX
28 writel_relaxed(0x01, SPEAR13XX_SYS_SW_RES);
29#endif
30#if defined(CONFIG_ARCH_SPEAR3XX) || defined(CONFIG_ARCH_SPEAR6XX)
31 sysctl_soft_reset((void __iomem *)VA_SPEAR_SYS_CTRL_BASE);
32#endif
33 }
34}
diff --git a/arch/arm/mach-spear/spear1310.c b/arch/arm/mach-spear/spear1310.c
new file mode 100644
index 000000000000..ed3b5c287a7b
--- /dev/null
+++ b/arch/arm/mach-spear/spear1310.c
@@ -0,0 +1,96 @@
1/*
2 * arch/arm/mach-spear13xx/spear1310.c
3 *
4 * SPEAr1310 machine source file
5 *
6 * Copyright (C) 2012 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#define pr_fmt(fmt) "SPEAr1310: " fmt
15
16#include <linux/amba/pl022.h>
17#include <linux/irqchip.h>
18#include <linux/of_platform.h>
19#include <linux/pata_arasan_cf_data.h>
20#include <asm/mach/arch.h>
21#include <asm/mach/map.h>
22#include "generic.h"
23#include <mach/spear.h>
24
25/* Base addresses */
26#define SPEAR1310_SSP1_BASE UL(0x5D400000)
27#define SPEAR1310_SATA0_BASE UL(0xB1000000)
28#define SPEAR1310_SATA1_BASE UL(0xB1800000)
29#define SPEAR1310_SATA2_BASE UL(0xB4000000)
30
31#define SPEAR1310_RAS_GRP1_BASE UL(0xD8000000)
32#define VA_SPEAR1310_RAS_GRP1_BASE UL(0xFA000000)
33
34static struct arasan_cf_pdata cf_pdata = {
35 .cf_if_clk = CF_IF_CLK_166M,
36 .quirk = CF_BROKEN_UDMA,
37 .dma_priv = &cf_dma_priv,
38};
39
40/* ssp device registration */
41static struct pl022_ssp_controller ssp1_plat_data = {
42 .enable_dma = 0,
43};
44
45/* Add SPEAr1310 auxdata to pass platform data */
46static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
47 OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata),
48 OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
49 OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
50 OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
51
52 OF_DEV_AUXDATA("arm,pl022", SPEAR1310_SSP1_BASE, NULL, &ssp1_plat_data),
53 {}
54};
55
56static void __init spear1310_dt_init(void)
57{
58 of_platform_populate(NULL, of_default_bus_match_table,
59 spear1310_auxdata_lookup, NULL);
60}
61
62static const char * const spear1310_dt_board_compat[] = {
63 "st,spear1310",
64 "st,spear1310-evb",
65 NULL,
66};
67
68/*
69 * Following will create 16MB static virtual/physical mappings
70 * PHYSICAL VIRTUAL
71 * 0xD8000000 0xFA000000
72 */
73struct map_desc spear1310_io_desc[] __initdata = {
74 {
75 .virtual = VA_SPEAR1310_RAS_GRP1_BASE,
76 .pfn = __phys_to_pfn(SPEAR1310_RAS_GRP1_BASE),
77 .length = SZ_16M,
78 .type = MT_DEVICE
79 },
80};
81
82static void __init spear1310_map_io(void)
83{
84 iotable_init(spear1310_io_desc, ARRAY_SIZE(spear1310_io_desc));
85 spear13xx_map_io();
86}
87
88DT_MACHINE_START(SPEAR1310_DT, "ST SPEAr1310 SoC with Flattened Device Tree")
89 .smp = smp_ops(spear13xx_smp_ops),
90 .map_io = spear1310_map_io,
91 .init_irq = irqchip_init,
92 .init_time = spear13xx_timer_init,
93 .init_machine = spear1310_dt_init,
94 .restart = spear_restart,
95 .dt_compat = spear1310_dt_board_compat,
96MACHINE_END
diff --git a/arch/arm/mach-spear/spear1340.c b/arch/arm/mach-spear/spear1340.c
new file mode 100644
index 000000000000..75e38644bbfb
--- /dev/null
+++ b/arch/arm/mach-spear/spear1340.c
@@ -0,0 +1,193 @@
1/*
2 * arch/arm/mach-spear13xx/spear1340.c
3 *
4 * SPEAr1340 machine source file
5 *
6 * Copyright (C) 2012 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#define pr_fmt(fmt) "SPEAr1340: " fmt
15
16#include <linux/ahci_platform.h>
17#include <linux/amba/serial.h>
18#include <linux/delay.h>
19#include <linux/dw_dmac.h>
20#include <linux/of_platform.h>
21#include <linux/irqchip.h>
22#include <asm/mach/arch.h>
23#include "generic.h"
24#include <mach/spear.h>
25
26#include "spear13xx-dma.h"
27
28/* Base addresses */
29#define SPEAR1340_SATA_BASE UL(0xB1000000)
30#define SPEAR1340_UART1_BASE UL(0xB4100000)
31
32/* Power Management Registers */
33#define SPEAR1340_PCM_CFG (VA_MISC_BASE + 0x100)
34#define SPEAR1340_PCM_WKUP_CFG (VA_MISC_BASE + 0x104)
35#define SPEAR1340_SWITCH_CTR (VA_MISC_BASE + 0x108)
36
37#define SPEAR1340_PERIP1_SW_RST (VA_MISC_BASE + 0x318)
38#define SPEAR1340_PERIP2_SW_RST (VA_MISC_BASE + 0x31C)
39#define SPEAR1340_PERIP3_SW_RST (VA_MISC_BASE + 0x320)
40
41/* PCIE - SATA configuration registers */
42#define SPEAR1340_PCIE_SATA_CFG (VA_MISC_BASE + 0x424)
43 /* PCIE CFG MASks */
44 #define SPEAR1340_PCIE_CFG_DEVICE_PRESENT (1 << 11)
45 #define SPEAR1340_PCIE_CFG_POWERUP_RESET (1 << 10)
46 #define SPEAR1340_PCIE_CFG_CORE_CLK_EN (1 << 9)
47 #define SPEAR1340_PCIE_CFG_AUX_CLK_EN (1 << 8)
48 #define SPEAR1340_SATA_CFG_TX_CLK_EN (1 << 4)
49 #define SPEAR1340_SATA_CFG_RX_CLK_EN (1 << 3)
50 #define SPEAR1340_SATA_CFG_POWERUP_RESET (1 << 2)
51 #define SPEAR1340_SATA_CFG_PM_CLK_EN (1 << 1)
52 #define SPEAR1340_PCIE_SATA_SEL_PCIE (0)
53 #define SPEAR1340_PCIE_SATA_SEL_SATA (1)
54 #define SPEAR1340_SATA_PCIE_CFG_MASK 0xF1F
55 #define SPEAR1340_PCIE_CFG_VAL (SPEAR1340_PCIE_SATA_SEL_PCIE | \
56 SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
57 SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
58 SPEAR1340_PCIE_CFG_POWERUP_RESET | \
59 SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
60 #define SPEAR1340_SATA_CFG_VAL (SPEAR1340_PCIE_SATA_SEL_SATA | \
61 SPEAR1340_SATA_CFG_PM_CLK_EN | \
62 SPEAR1340_SATA_CFG_POWERUP_RESET | \
63 SPEAR1340_SATA_CFG_RX_CLK_EN | \
64 SPEAR1340_SATA_CFG_TX_CLK_EN)
65
66#define SPEAR1340_PCIE_MIPHY_CFG (VA_MISC_BASE + 0x428)
67 #define SPEAR1340_MIPHY_OSC_BYPASS_EXT (1 << 31)
68 #define SPEAR1340_MIPHY_CLK_REF_DIV2 (1 << 27)
69 #define SPEAR1340_MIPHY_CLK_REF_DIV4 (2 << 27)
70 #define SPEAR1340_MIPHY_CLK_REF_DIV8 (3 << 27)
71 #define SPEAR1340_MIPHY_PLL_RATIO_TOP(x) (x << 0)
72 #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
73 (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
74 SPEAR1340_MIPHY_CLK_REF_DIV2 | \
75 SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
76 #define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
77 (SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
78 #define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
79 (SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
80 SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
81
82static struct dw_dma_slave uart1_dma_param[] = {
83 {
84 /* Tx */
85 .cfg_hi = DWC_CFGH_DST_PER(SPEAR1340_DMA_REQ_UART1_TX),
86 .cfg_lo = 0,
87 .src_master = DMA_MASTER_MEMORY,
88 .dst_master = SPEAR1340_DMA_MASTER_UART1,
89 }, {
90 /* Rx */
91 .cfg_hi = DWC_CFGH_SRC_PER(SPEAR1340_DMA_REQ_UART1_RX),
92 .cfg_lo = 0,
93 .src_master = SPEAR1340_DMA_MASTER_UART1,
94 .dst_master = DMA_MASTER_MEMORY,
95 }
96};
97
98static struct amba_pl011_data uart1_data = {
99 .dma_filter = dw_dma_filter,
100 .dma_tx_param = &uart1_dma_param[0],
101 .dma_rx_param = &uart1_dma_param[1],
102};
103
104/* SATA device registration */
105static int sata_miphy_init(struct device *dev, void __iomem *addr)
106{
107 writel(SPEAR1340_SATA_CFG_VAL, SPEAR1340_PCIE_SATA_CFG);
108 writel(SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK,
109 SPEAR1340_PCIE_MIPHY_CFG);
110 /* Switch on sata power domain */
111 writel((readl(SPEAR1340_PCM_CFG) | (0x800)), SPEAR1340_PCM_CFG);
112 msleep(20);
113 /* Disable PCIE SATA Controller reset */
114 writel((readl(SPEAR1340_PERIP1_SW_RST) & (~0x1000)),
115 SPEAR1340_PERIP1_SW_RST);
116 msleep(20);
117
118 return 0;
119}
120
121void sata_miphy_exit(struct device *dev)
122{
123 writel(0, SPEAR1340_PCIE_SATA_CFG);
124 writel(0, SPEAR1340_PCIE_MIPHY_CFG);
125
126 /* Enable PCIE SATA Controller reset */
127 writel((readl(SPEAR1340_PERIP1_SW_RST) | (0x1000)),
128 SPEAR1340_PERIP1_SW_RST);
129 msleep(20);
130 /* Switch off sata power domain */
131 writel((readl(SPEAR1340_PCM_CFG) & (~0x800)), SPEAR1340_PCM_CFG);
132 msleep(20);
133}
134
135int sata_suspend(struct device *dev)
136{
137 if (dev->power.power_state.event == PM_EVENT_FREEZE)
138 return 0;
139
140 sata_miphy_exit(dev);
141
142 return 0;
143}
144
145int sata_resume(struct device *dev)
146{
147 if (dev->power.power_state.event == PM_EVENT_THAW)
148 return 0;
149
150 return sata_miphy_init(dev, NULL);
151}
152
153static struct ahci_platform_data sata_pdata = {
154 .init = sata_miphy_init,
155 .exit = sata_miphy_exit,
156 .suspend = sata_suspend,
157 .resume = sata_resume,
158};
159
160/* Add SPEAr1340 auxdata to pass platform data */
161static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
162 OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
163 OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
164 OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
165 OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
166
167 OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
168 &sata_pdata),
169 OF_DEV_AUXDATA("arm,pl011", SPEAR1340_UART1_BASE, NULL, &uart1_data),
170 {}
171};
172
173static void __init spear1340_dt_init(void)
174{
175 of_platform_populate(NULL, of_default_bus_match_table,
176 spear1340_auxdata_lookup, NULL);
177}
178
179static const char * const spear1340_dt_board_compat[] = {
180 "st,spear1340",
181 "st,spear1340-evb",
182 NULL,
183};
184
185DT_MACHINE_START(SPEAR1340_DT, "ST SPEAr1340 SoC with Flattened Device Tree")
186 .smp = smp_ops(spear13xx_smp_ops),
187 .map_io = spear13xx_map_io,
188 .init_irq = irqchip_init,
189 .init_time = spear13xx_timer_init,
190 .init_machine = spear1340_dt_init,
191 .restart = spear_restart,
192 .dt_compat = spear1340_dt_board_compat,
193MACHINE_END
diff --git a/arch/arm/mach-spear/spear13xx-dma.h b/arch/arm/mach-spear/spear13xx-dma.h
new file mode 100644
index 000000000000..d50bdb605925
--- /dev/null
+++ b/arch/arm/mach-spear/spear13xx-dma.h
@@ -0,0 +1,128 @@
1/*
2 * arch/arm/mach-spear13xx/include/mach/dma.h
3 *
4 * DMA information for SPEAr13xx machine family
5 *
6 * Copyright (C) 2012 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#ifndef __MACH_DMA_H
15#define __MACH_DMA_H
16
17/* request id of all the peripherals */
18enum dma_master_info {
19 /* Accessible from only one master */
20 DMA_MASTER_MCIF = 0,
21 DMA_MASTER_FSMC = 1,
22 /* Accessible from both 0 & 1 */
23 DMA_MASTER_MEMORY = 0,
24 DMA_MASTER_ADC = 0,
25 DMA_MASTER_UART0 = 0,
26 DMA_MASTER_SSP0 = 0,
27 DMA_MASTER_I2C0 = 0,
28
29#ifdef CONFIG_MACH_SPEAR1310
30 /* Accessible from only one master */
31 SPEAR1310_DMA_MASTER_JPEG = 1,
32
33 /* Accessible from both 0 & 1 */
34 SPEAR1310_DMA_MASTER_I2S = 0,
35 SPEAR1310_DMA_MASTER_UART1 = 0,
36 SPEAR1310_DMA_MASTER_UART2 = 0,
37 SPEAR1310_DMA_MASTER_UART3 = 0,
38 SPEAR1310_DMA_MASTER_UART4 = 0,
39 SPEAR1310_DMA_MASTER_UART5 = 0,
40 SPEAR1310_DMA_MASTER_I2C1 = 0,
41 SPEAR1310_DMA_MASTER_I2C2 = 0,
42 SPEAR1310_DMA_MASTER_I2C3 = 0,
43 SPEAR1310_DMA_MASTER_I2C4 = 0,
44 SPEAR1310_DMA_MASTER_I2C5 = 0,
45 SPEAR1310_DMA_MASTER_I2C6 = 0,
46 SPEAR1310_DMA_MASTER_I2C7 = 0,
47 SPEAR1310_DMA_MASTER_SSP1 = 0,
48#endif
49
50#ifdef CONFIG_MACH_SPEAR1340
51 /* Accessible from only one master */
52 SPEAR1340_DMA_MASTER_I2S_PLAY = 1,
53 SPEAR1340_DMA_MASTER_I2S_REC = 1,
54 SPEAR1340_DMA_MASTER_I2C1 = 1,
55 SPEAR1340_DMA_MASTER_UART1 = 1,
56
57 /* following are accessible from both master 0 & 1 */
58 SPEAR1340_DMA_MASTER_SPDIF = 0,
59 SPEAR1340_DMA_MASTER_CAM = 1,
60 SPEAR1340_DMA_MASTER_VIDEO_IN = 0,
61 SPEAR1340_DMA_MASTER_MALI = 0,
62#endif
63};
64
65enum request_id {
66 DMA_REQ_ADC = 0,
67 DMA_REQ_SSP0_TX = 4,
68 DMA_REQ_SSP0_RX = 5,
69 DMA_REQ_UART0_TX = 6,
70 DMA_REQ_UART0_RX = 7,
71 DMA_REQ_I2C0_TX = 8,
72 DMA_REQ_I2C0_RX = 9,
73
74#ifdef CONFIG_MACH_SPEAR1310
75 SPEAR1310_DMA_REQ_FROM_JPEG = 2,
76 SPEAR1310_DMA_REQ_TO_JPEG = 3,
77 SPEAR1310_DMA_REQ_I2S_TX = 10,
78 SPEAR1310_DMA_REQ_I2S_RX = 11,
79
80 SPEAR1310_DMA_REQ_I2C1_RX = 0,
81 SPEAR1310_DMA_REQ_I2C1_TX = 1,
82 SPEAR1310_DMA_REQ_I2C2_RX = 2,
83 SPEAR1310_DMA_REQ_I2C2_TX = 3,
84 SPEAR1310_DMA_REQ_I2C3_RX = 4,
85 SPEAR1310_DMA_REQ_I2C3_TX = 5,
86 SPEAR1310_DMA_REQ_I2C4_RX = 6,
87 SPEAR1310_DMA_REQ_I2C4_TX = 7,
88 SPEAR1310_DMA_REQ_I2C5_RX = 8,
89 SPEAR1310_DMA_REQ_I2C5_TX = 9,
90 SPEAR1310_DMA_REQ_I2C6_RX = 10,
91 SPEAR1310_DMA_REQ_I2C6_TX = 11,
92 SPEAR1310_DMA_REQ_UART1_RX = 12,
93 SPEAR1310_DMA_REQ_UART1_TX = 13,
94 SPEAR1310_DMA_REQ_UART2_RX = 14,
95 SPEAR1310_DMA_REQ_UART2_TX = 15,
96 SPEAR1310_DMA_REQ_UART5_RX = 16,
97 SPEAR1310_DMA_REQ_UART5_TX = 17,
98 SPEAR1310_DMA_REQ_SSP1_RX = 18,
99 SPEAR1310_DMA_REQ_SSP1_TX = 19,
100 SPEAR1310_DMA_REQ_I2C7_RX = 20,
101 SPEAR1310_DMA_REQ_I2C7_TX = 21,
102 SPEAR1310_DMA_REQ_UART3_RX = 28,
103 SPEAR1310_DMA_REQ_UART3_TX = 29,
104 SPEAR1310_DMA_REQ_UART4_RX = 30,
105 SPEAR1310_DMA_REQ_UART4_TX = 31,
106#endif
107
108#ifdef CONFIG_MACH_SPEAR1340
109 SPEAR1340_DMA_REQ_SPDIF_TX = 2,
110 SPEAR1340_DMA_REQ_SPDIF_RX = 3,
111 SPEAR1340_DMA_REQ_I2S_TX = 10,
112 SPEAR1340_DMA_REQ_I2S_RX = 11,
113 SPEAR1340_DMA_REQ_UART1_TX = 12,
114 SPEAR1340_DMA_REQ_UART1_RX = 13,
115 SPEAR1340_DMA_REQ_I2C1_TX = 14,
116 SPEAR1340_DMA_REQ_I2C1_RX = 15,
117 SPEAR1340_DMA_REQ_CAM0_EVEN = 0,
118 SPEAR1340_DMA_REQ_CAM0_ODD = 1,
119 SPEAR1340_DMA_REQ_CAM1_EVEN = 2,
120 SPEAR1340_DMA_REQ_CAM1_ODD = 3,
121 SPEAR1340_DMA_REQ_CAM2_EVEN = 4,
122 SPEAR1340_DMA_REQ_CAM2_ODD = 5,
123 SPEAR1340_DMA_REQ_CAM3_EVEN = 6,
124 SPEAR1340_DMA_REQ_CAM3_ODD = 7,
125#endif
126};
127
128#endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-spear/spear13xx.c b/arch/arm/mach-spear/spear13xx.c
new file mode 100644
index 000000000000..1b97e8623472
--- /dev/null
+++ b/arch/arm/mach-spear/spear13xx.c
@@ -0,0 +1,184 @@
1/*
2 * arch/arm/mach-spear13xx/spear13xx.c
3 *
4 * SPEAr13XX machines common source file
5 *
6 * Copyright (C) 2012 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#define pr_fmt(fmt) "SPEAr13xx: " fmt
15
16#include <linux/amba/pl022.h>
17#include <linux/clk.h>
18#include <linux/dw_dmac.h>
19#include <linux/err.h>
20#include <linux/of.h>
21#include <asm/hardware/cache-l2x0.h>
22#include <asm/mach/map.h>
23#include <asm/smp_twd.h>
24#include "generic.h"
25#include <mach/spear.h>
26
27#include "spear13xx-dma.h"
28
29/* common dw_dma filter routine to be used by peripherals */
30bool dw_dma_filter(struct dma_chan *chan, void *slave)
31{
32 struct dw_dma_slave *dws = (struct dw_dma_slave *)slave;
33
34 if (chan->device->dev == dws->dma_dev) {
35 chan->private = slave;
36 return true;
37 } else {
38 return false;
39 }
40}
41
42/* ssp device registration */
43static struct dw_dma_slave ssp_dma_param[] = {
44 {
45 /* Tx */
46 .cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX),
47 .cfg_lo = 0,
48 .src_master = DMA_MASTER_MEMORY,
49 .dst_master = DMA_MASTER_SSP0,
50 }, {
51 /* Rx */
52 .cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX),
53 .cfg_lo = 0,
54 .src_master = DMA_MASTER_SSP0,
55 .dst_master = DMA_MASTER_MEMORY,
56 }
57};
58
59struct pl022_ssp_controller pl022_plat_data = {
60 .enable_dma = 1,
61 .dma_filter = dw_dma_filter,
62 .dma_rx_param = &ssp_dma_param[1],
63 .dma_tx_param = &ssp_dma_param[0],
64};
65
66/* CF device registration */
67struct dw_dma_slave cf_dma_priv = {
68 .cfg_hi = 0,
69 .cfg_lo = 0,
70 .src_master = 0,
71 .dst_master = 0,
72};
73
74/* dmac device registeration */
75struct dw_dma_platform_data dmac_plat_data = {
76 .nr_channels = 8,
77 .chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
78 .chan_priority = CHAN_PRIORITY_DESCENDING,
79 .block_size = 4095U,
80 .nr_masters = 2,
81 .data_width = { 3, 3, 0, 0 },
82};
83
84void __init spear13xx_l2x0_init(void)
85{
86 /*
87 * 512KB (64KB/way), 8-way associativity, parity supported
88 *
89 * FIXME: 9th bit, of Auxillary Controller register must be set
90 * for some spear13xx devices for stable L2 operation.
91 *
92 * Enable Early BRESP, L2 prefetch for Instruction and Data,
93 * write alloc and 'Full line of zero' options
94 *
95 */
96
97 writel_relaxed(0x06, VA_L2CC_BASE + L2X0_PREFETCH_CTRL);
98
99 /*
100 * Program following latencies in order to make
101 * SPEAr1340 work at 600 MHz
102 */
103 writel_relaxed(0x221, VA_L2CC_BASE + L2X0_TAG_LATENCY_CTRL);
104 writel_relaxed(0x441, VA_L2CC_BASE + L2X0_DATA_LATENCY_CTRL);
105 l2x0_init(VA_L2CC_BASE, 0x70A60001, 0xfe00ffff);
106}
107
108/*
109 * Following will create 16MB static virtual/physical mappings
110 * PHYSICAL VIRTUAL
111 * 0xB3000000 0xFE000000
112 * 0xE0000000 0xFD000000
113 * 0xEC000000 0xFC000000
114 * 0xED000000 0xFB000000
115 */
116struct map_desc spear13xx_io_desc[] __initdata = {
117 {
118 .virtual = (unsigned long)VA_PERIP_GRP2_BASE,
119 .pfn = __phys_to_pfn(PERIP_GRP2_BASE),
120 .length = SZ_16M,
121 .type = MT_DEVICE
122 }, {
123 .virtual = (unsigned long)VA_PERIP_GRP1_BASE,
124 .pfn = __phys_to_pfn(PERIP_GRP1_BASE),
125 .length = SZ_16M,
126 .type = MT_DEVICE
127 }, {
128 .virtual = (unsigned long)VA_A9SM_AND_MPMC_BASE,
129 .pfn = __phys_to_pfn(A9SM_AND_MPMC_BASE),
130 .length = SZ_16M,
131 .type = MT_DEVICE
132 }, {
133 .virtual = (unsigned long)VA_L2CC_BASE,
134 .pfn = __phys_to_pfn(L2CC_BASE),
135 .length = SZ_4K,
136 .type = MT_DEVICE
137 },
138};
139
140/* This will create static memory mapping for selected devices */
141void __init spear13xx_map_io(void)
142{
143 iotable_init(spear13xx_io_desc, ARRAY_SIZE(spear13xx_io_desc));
144}
145
146static void __init spear13xx_clk_init(void)
147{
148 if (of_machine_is_compatible("st,spear1310"))
149 spear1310_clk_init(VA_MISC_BASE, VA_SPEAR1310_RAS_BASE);
150 else if (of_machine_is_compatible("st,spear1340"))
151 spear1340_clk_init(VA_MISC_BASE);
152 else
153 pr_err("%s: Unknown machine\n", __func__);
154}
155
156void __init spear13xx_timer_init(void)
157{
158 char pclk_name[] = "osc_24m_clk";
159 struct clk *gpt_clk, *pclk;
160
161 spear13xx_clk_init();
162
163 /* get the system timer clock */
164 gpt_clk = clk_get_sys("gpt0", NULL);
165 if (IS_ERR(gpt_clk)) {
166 pr_err("%s:couldn't get clk for gpt\n", __func__);
167 BUG();
168 }
169
170 /* get the suitable parent clock for timer*/
171 pclk = clk_get(NULL, pclk_name);
172 if (IS_ERR(pclk)) {
173 pr_err("%s:couldn't get %s as parent for gpt\n", __func__,
174 pclk_name);
175 BUG();
176 }
177
178 clk_set_parent(gpt_clk, pclk);
179 clk_put(gpt_clk);
180 clk_put(pclk);
181
182 spear_setup_of_timer();
183 twd_local_timer_of_register();
184}
diff --git a/arch/arm/mach-spear/spear300.c b/arch/arm/mach-spear/spear300.c
new file mode 100644
index 000000000000..bac56e845f7a
--- /dev/null
+++ b/arch/arm/mach-spear/spear300.c
@@ -0,0 +1,220 @@
1/*
2 * arch/arm/mach-spear3xx/spear300.c
3 *
4 * SPEAr300 machine source file
5 *
6 * Copyright (C) 2009-2012 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#define pr_fmt(fmt) "SPEAr300: " fmt
15
16#include <linux/amba/pl08x.h>
17#include <linux/irqchip.h>
18#include <linux/of_platform.h>
19#include <asm/mach/arch.h>
20#include "generic.h"
21#include <mach/spear.h>
22
23/* DMAC platform data's slave info */
24struct pl08x_channel_data spear300_dma_info[] = {
25 {
26 .bus_id = "uart0_rx",
27 .min_signal = 2,
28 .max_signal = 2,
29 .muxval = 0,
30 .periph_buses = PL08X_AHB1,
31 }, {
32 .bus_id = "uart0_tx",
33 .min_signal = 3,
34 .max_signal = 3,
35 .muxval = 0,
36 .periph_buses = PL08X_AHB1,
37 }, {
38 .bus_id = "ssp0_rx",
39 .min_signal = 8,
40 .max_signal = 8,
41 .muxval = 0,
42 .periph_buses = PL08X_AHB1,
43 }, {
44 .bus_id = "ssp0_tx",
45 .min_signal = 9,
46 .max_signal = 9,
47 .muxval = 0,
48 .periph_buses = PL08X_AHB1,
49 }, {
50 .bus_id = "i2c_rx",
51 .min_signal = 10,
52 .max_signal = 10,
53 .muxval = 0,
54 .periph_buses = PL08X_AHB1,
55 }, {
56 .bus_id = "i2c_tx",
57 .min_signal = 11,
58 .max_signal = 11,
59 .muxval = 0,
60 .periph_buses = PL08X_AHB1,
61 }, {
62 .bus_id = "irda",
63 .min_signal = 12,
64 .max_signal = 12,
65 .muxval = 0,
66 .periph_buses = PL08X_AHB1,
67 }, {
68 .bus_id = "adc",
69 .min_signal = 13,
70 .max_signal = 13,
71 .muxval = 0,
72 .periph_buses = PL08X_AHB1,
73 }, {
74 .bus_id = "to_jpeg",
75 .min_signal = 14,
76 .max_signal = 14,
77 .muxval = 0,
78 .periph_buses = PL08X_AHB1,
79 }, {
80 .bus_id = "from_jpeg",
81 .min_signal = 15,
82 .max_signal = 15,
83 .muxval = 0,
84 .periph_buses = PL08X_AHB1,
85 }, {
86 .bus_id = "ras0_rx",
87 .min_signal = 0,
88 .max_signal = 0,
89 .muxval = 1,
90 .periph_buses = PL08X_AHB1,
91 }, {
92 .bus_id = "ras0_tx",
93 .min_signal = 1,
94 .max_signal = 1,
95 .muxval = 1,
96 .periph_buses = PL08X_AHB1,
97 }, {
98 .bus_id = "ras1_rx",
99 .min_signal = 2,
100 .max_signal = 2,
101 .muxval = 1,
102 .periph_buses = PL08X_AHB1,
103 }, {
104 .bus_id = "ras1_tx",
105 .min_signal = 3,
106 .max_signal = 3,
107 .muxval = 1,
108 .periph_buses = PL08X_AHB1,
109 }, {
110 .bus_id = "ras2_rx",
111 .min_signal = 4,
112 .max_signal = 4,
113 .muxval = 1,
114 .periph_buses = PL08X_AHB1,
115 }, {
116 .bus_id = "ras2_tx",
117 .min_signal = 5,
118 .max_signal = 5,
119 .muxval = 1,
120 .periph_buses = PL08X_AHB1,
121 }, {
122 .bus_id = "ras3_rx",
123 .min_signal = 6,
124 .max_signal = 6,
125 .muxval = 1,
126 .periph_buses = PL08X_AHB1,
127 }, {
128 .bus_id = "ras3_tx",
129 .min_signal = 7,
130 .max_signal = 7,
131 .muxval = 1,
132 .periph_buses = PL08X_AHB1,
133 }, {
134 .bus_id = "ras4_rx",
135 .min_signal = 8,
136 .max_signal = 8,
137 .muxval = 1,
138 .periph_buses = PL08X_AHB1,
139 }, {
140 .bus_id = "ras4_tx",
141 .min_signal = 9,
142 .max_signal = 9,
143 .muxval = 1,
144 .periph_buses = PL08X_AHB1,
145 }, {
146 .bus_id = "ras5_rx",
147 .min_signal = 10,
148 .max_signal = 10,
149 .muxval = 1,
150 .periph_buses = PL08X_AHB1,
151 }, {
152 .bus_id = "ras5_tx",
153 .min_signal = 11,
154 .max_signal = 11,
155 .muxval = 1,
156 .periph_buses = PL08X_AHB1,
157 }, {
158 .bus_id = "ras6_rx",
159 .min_signal = 12,
160 .max_signal = 12,
161 .muxval = 1,
162 .periph_buses = PL08X_AHB1,
163 }, {
164 .bus_id = "ras6_tx",
165 .min_signal = 13,
166 .max_signal = 13,
167 .muxval = 1,
168 .periph_buses = PL08X_AHB1,
169 }, {
170 .bus_id = "ras7_rx",
171 .min_signal = 14,
172 .max_signal = 14,
173 .muxval = 1,
174 .periph_buses = PL08X_AHB1,
175 }, {
176 .bus_id = "ras7_tx",
177 .min_signal = 15,
178 .max_signal = 15,
179 .muxval = 1,
180 .periph_buses = PL08X_AHB1,
181 },
182};
183
184/* Add SPEAr300 auxdata to pass platform data */
185static struct of_dev_auxdata spear300_auxdata_lookup[] __initdata = {
186 OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
187 &pl022_plat_data),
188 OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL,
189 &pl080_plat_data),
190 {}
191};
192
193static void __init spear300_dt_init(void)
194{
195 pl080_plat_data.slave_channels = spear300_dma_info;
196 pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
197
198 of_platform_populate(NULL, of_default_bus_match_table,
199 spear300_auxdata_lookup, NULL);
200}
201
202static const char * const spear300_dt_board_compat[] = {
203 "st,spear300",
204 "st,spear300-evb",
205 NULL,
206};
207
208static void __init spear300_map_io(void)
209{
210 spear3xx_map_io();
211}
212
213DT_MACHINE_START(SPEAR300_DT, "ST SPEAr300 SoC with Flattened Device Tree")
214 .map_io = spear300_map_io,
215 .init_irq = irqchip_init,
216 .init_time = spear3xx_timer_init,
217 .init_machine = spear300_dt_init,
218 .restart = spear_restart,
219 .dt_compat = spear300_dt_board_compat,
220MACHINE_END
diff --git a/arch/arm/mach-spear/spear310.c b/arch/arm/mach-spear/spear310.c
new file mode 100644
index 000000000000..6ffbc63d516d
--- /dev/null
+++ b/arch/arm/mach-spear/spear310.c
@@ -0,0 +1,262 @@
1/*
2 * arch/arm/mach-spear3xx/spear310.c
3 *
4 * SPEAr310 machine source file
5 *
6 * Copyright (C) 2009-2012 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#define pr_fmt(fmt) "SPEAr310: " fmt
15
16#include <linux/amba/pl08x.h>
17#include <linux/amba/serial.h>
18#include <linux/irqchip.h>
19#include <linux/of_platform.h>
20#include <asm/mach/arch.h>
21#include "generic.h"
22#include <mach/spear.h>
23
24#define SPEAR310_UART1_BASE UL(0xB2000000)
25#define SPEAR310_UART2_BASE UL(0xB2080000)
26#define SPEAR310_UART3_BASE UL(0xB2100000)
27#define SPEAR310_UART4_BASE UL(0xB2180000)
28#define SPEAR310_UART5_BASE UL(0xB2200000)
29
30/* DMAC platform data's slave info */
31struct pl08x_channel_data spear310_dma_info[] = {
32 {
33 .bus_id = "uart0_rx",
34 .min_signal = 2,
35 .max_signal = 2,
36 .muxval = 0,
37 .periph_buses = PL08X_AHB1,
38 }, {
39 .bus_id = "uart0_tx",
40 .min_signal = 3,
41 .max_signal = 3,
42 .muxval = 0,
43 .periph_buses = PL08X_AHB1,
44 }, {
45 .bus_id = "ssp0_rx",
46 .min_signal = 8,
47 .max_signal = 8,
48 .muxval = 0,
49 .periph_buses = PL08X_AHB1,
50 }, {
51 .bus_id = "ssp0_tx",
52 .min_signal = 9,
53 .max_signal = 9,
54 .muxval = 0,
55 .periph_buses = PL08X_AHB1,
56 }, {
57 .bus_id = "i2c_rx",
58 .min_signal = 10,
59 .max_signal = 10,
60 .muxval = 0,
61 .periph_buses = PL08X_AHB1,
62 }, {
63 .bus_id = "i2c_tx",
64 .min_signal = 11,
65 .max_signal = 11,
66 .muxval = 0,
67 .periph_buses = PL08X_AHB1,
68 }, {
69 .bus_id = "irda",
70 .min_signal = 12,
71 .max_signal = 12,
72 .muxval = 0,
73 .periph_buses = PL08X_AHB1,
74 }, {
75 .bus_id = "adc",
76 .min_signal = 13,
77 .max_signal = 13,
78 .muxval = 0,
79 .periph_buses = PL08X_AHB1,
80 }, {
81 .bus_id = "to_jpeg",
82 .min_signal = 14,
83 .max_signal = 14,
84 .muxval = 0,
85 .periph_buses = PL08X_AHB1,
86 }, {
87 .bus_id = "from_jpeg",
88 .min_signal = 15,
89 .max_signal = 15,
90 .muxval = 0,
91 .periph_buses = PL08X_AHB1,
92 }, {
93 .bus_id = "uart1_rx",
94 .min_signal = 0,
95 .max_signal = 0,
96 .muxval = 1,
97 .periph_buses = PL08X_AHB1,
98 }, {
99 .bus_id = "uart1_tx",
100 .min_signal = 1,
101 .max_signal = 1,
102 .muxval = 1,
103 .periph_buses = PL08X_AHB1,
104 }, {
105 .bus_id = "uart2_rx",
106 .min_signal = 2,
107 .max_signal = 2,
108 .muxval = 1,
109 .periph_buses = PL08X_AHB1,
110 }, {
111 .bus_id = "uart2_tx",
112 .min_signal = 3,
113 .max_signal = 3,
114 .muxval = 1,
115 .periph_buses = PL08X_AHB1,
116 }, {
117 .bus_id = "uart3_rx",
118 .min_signal = 4,
119 .max_signal = 4,
120 .muxval = 1,
121 .periph_buses = PL08X_AHB1,
122 }, {
123 .bus_id = "uart3_tx",
124 .min_signal = 5,
125 .max_signal = 5,
126 .muxval = 1,
127 .periph_buses = PL08X_AHB1,
128 }, {
129 .bus_id = "uart4_rx",
130 .min_signal = 6,
131 .max_signal = 6,
132 .muxval = 1,
133 .periph_buses = PL08X_AHB1,
134 }, {
135 .bus_id = "uart4_tx",
136 .min_signal = 7,
137 .max_signal = 7,
138 .muxval = 1,
139 .periph_buses = PL08X_AHB1,
140 }, {
141 .bus_id = "uart5_rx",
142 .min_signal = 8,
143 .max_signal = 8,
144 .muxval = 1,
145 .periph_buses = PL08X_AHB1,
146 }, {
147 .bus_id = "uart5_tx",
148 .min_signal = 9,
149 .max_signal = 9,
150 .muxval = 1,
151 .periph_buses = PL08X_AHB1,
152 }, {
153 .bus_id = "ras5_rx",
154 .min_signal = 10,
155 .max_signal = 10,
156 .muxval = 1,
157 .periph_buses = PL08X_AHB1,
158 }, {
159 .bus_id = "ras5_tx",
160 .min_signal = 11,
161 .max_signal = 11,
162 .muxval = 1,
163 .periph_buses = PL08X_AHB1,
164 }, {
165 .bus_id = "ras6_rx",
166 .min_signal = 12,
167 .max_signal = 12,
168 .muxval = 1,
169 .periph_buses = PL08X_AHB1,
170 }, {
171 .bus_id = "ras6_tx",
172 .min_signal = 13,
173 .max_signal = 13,
174 .muxval = 1,
175 .periph_buses = PL08X_AHB1,
176 }, {
177 .bus_id = "ras7_rx",
178 .min_signal = 14,
179 .max_signal = 14,
180 .muxval = 1,
181 .periph_buses = PL08X_AHB1,
182 }, {
183 .bus_id = "ras7_tx",
184 .min_signal = 15,
185 .max_signal = 15,
186 .muxval = 1,
187 .periph_buses = PL08X_AHB1,
188 },
189};
190
191/* uart devices plat data */
192static struct amba_pl011_data spear310_uart_data[] = {
193 {
194 .dma_filter = pl08x_filter_id,
195 .dma_tx_param = "uart1_tx",
196 .dma_rx_param = "uart1_rx",
197 }, {
198 .dma_filter = pl08x_filter_id,
199 .dma_tx_param = "uart2_tx",
200 .dma_rx_param = "uart2_rx",
201 }, {
202 .dma_filter = pl08x_filter_id,
203 .dma_tx_param = "uart3_tx",
204 .dma_rx_param = "uart3_rx",
205 }, {
206 .dma_filter = pl08x_filter_id,
207 .dma_tx_param = "uart4_tx",
208 .dma_rx_param = "uart4_rx",
209 }, {
210 .dma_filter = pl08x_filter_id,
211 .dma_tx_param = "uart5_tx",
212 .dma_rx_param = "uart5_rx",
213 },
214};
215
216/* Add SPEAr310 auxdata to pass platform data */
217static struct of_dev_auxdata spear310_auxdata_lookup[] __initdata = {
218 OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
219 &pl022_plat_data),
220 OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL,
221 &pl080_plat_data),
222 OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART1_BASE, NULL,
223 &spear310_uart_data[0]),
224 OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART2_BASE, NULL,
225 &spear310_uart_data[1]),
226 OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART3_BASE, NULL,
227 &spear310_uart_data[2]),
228 OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART4_BASE, NULL,
229 &spear310_uart_data[3]),
230 OF_DEV_AUXDATA("arm,pl011", SPEAR310_UART5_BASE, NULL,
231 &spear310_uart_data[4]),
232 {}
233};
234
235static void __init spear310_dt_init(void)
236{
237 pl080_plat_data.slave_channels = spear310_dma_info;
238 pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
239
240 of_platform_populate(NULL, of_default_bus_match_table,
241 spear310_auxdata_lookup, NULL);
242}
243
244static const char * const spear310_dt_board_compat[] = {
245 "st,spear310",
246 "st,spear310-evb",
247 NULL,
248};
249
250static void __init spear310_map_io(void)
251{
252 spear3xx_map_io();
253}
254
255DT_MACHINE_START(SPEAR310_DT, "ST SPEAr310 SoC with Flattened Device Tree")
256 .map_io = spear310_map_io,
257 .init_irq = irqchip_init,
258 .init_time = spear3xx_timer_init,
259 .init_machine = spear310_dt_init,
260 .restart = spear_restart,
261 .dt_compat = spear310_dt_board_compat,
262MACHINE_END
diff --git a/arch/arm/mach-spear/spear320.c b/arch/arm/mach-spear/spear320.c
new file mode 100644
index 000000000000..6eb3eec65f96
--- /dev/null
+++ b/arch/arm/mach-spear/spear320.c
@@ -0,0 +1,277 @@
1/*
2 * arch/arm/mach-spear3xx/spear320.c
3 *
4 * SPEAr320 machine source file
5 *
6 * Copyright (C) 2009-2012 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#define pr_fmt(fmt) "SPEAr320: " fmt
15
16#include <linux/amba/pl022.h>
17#include <linux/amba/pl08x.h>
18#include <linux/amba/serial.h>
19#include <linux/irqchip.h>
20#include <linux/of_platform.h>
21#include <asm/mach/arch.h>
22#include <asm/mach/map.h>
23#include "generic.h"
24#include <mach/spear.h>
25
26#define SPEAR320_UART1_BASE UL(0xA3000000)
27#define SPEAR320_UART2_BASE UL(0xA4000000)
28#define SPEAR320_SSP0_BASE UL(0xA5000000)
29#define SPEAR320_SSP1_BASE UL(0xA6000000)
30
31/* DMAC platform data's slave info */
32struct pl08x_channel_data spear320_dma_info[] = {
33 {
34 .bus_id = "uart0_rx",
35 .min_signal = 2,
36 .max_signal = 2,
37 .muxval = 0,
38 .periph_buses = PL08X_AHB1,
39 }, {
40 .bus_id = "uart0_tx",
41 .min_signal = 3,
42 .max_signal = 3,
43 .muxval = 0,
44 .periph_buses = PL08X_AHB1,
45 }, {
46 .bus_id = "ssp0_rx",
47 .min_signal = 8,
48 .max_signal = 8,
49 .muxval = 0,
50 .periph_buses = PL08X_AHB1,
51 }, {
52 .bus_id = "ssp0_tx",
53 .min_signal = 9,
54 .max_signal = 9,
55 .muxval = 0,
56 .periph_buses = PL08X_AHB1,
57 }, {
58 .bus_id = "i2c0_rx",
59 .min_signal = 10,
60 .max_signal = 10,
61 .muxval = 0,
62 .periph_buses = PL08X_AHB1,
63 }, {
64 .bus_id = "i2c0_tx",
65 .min_signal = 11,
66 .max_signal = 11,
67 .muxval = 0,
68 .periph_buses = PL08X_AHB1,
69 }, {
70 .bus_id = "irda",
71 .min_signal = 12,
72 .max_signal = 12,
73 .muxval = 0,
74 .periph_buses = PL08X_AHB1,
75 }, {
76 .bus_id = "adc",
77 .min_signal = 13,
78 .max_signal = 13,
79 .muxval = 0,
80 .periph_buses = PL08X_AHB1,
81 }, {
82 .bus_id = "to_jpeg",
83 .min_signal = 14,
84 .max_signal = 14,
85 .muxval = 0,
86 .periph_buses = PL08X_AHB1,
87 }, {
88 .bus_id = "from_jpeg",
89 .min_signal = 15,
90 .max_signal = 15,
91 .muxval = 0,
92 .periph_buses = PL08X_AHB1,
93 }, {
94 .bus_id = "ssp1_rx",
95 .min_signal = 0,
96 .max_signal = 0,
97 .muxval = 1,
98 .periph_buses = PL08X_AHB2,
99 }, {
100 .bus_id = "ssp1_tx",
101 .min_signal = 1,
102 .max_signal = 1,
103 .muxval = 1,
104 .periph_buses = PL08X_AHB2,
105 }, {
106 .bus_id = "ssp2_rx",
107 .min_signal = 2,
108 .max_signal = 2,
109 .muxval = 1,
110 .periph_buses = PL08X_AHB2,
111 }, {
112 .bus_id = "ssp2_tx",
113 .min_signal = 3,
114 .max_signal = 3,
115 .muxval = 1,
116 .periph_buses = PL08X_AHB2,
117 }, {
118 .bus_id = "uart1_rx",
119 .min_signal = 4,
120 .max_signal = 4,
121 .muxval = 1,
122 .periph_buses = PL08X_AHB2,
123 }, {
124 .bus_id = "uart1_tx",
125 .min_signal = 5,
126 .max_signal = 5,
127 .muxval = 1,
128 .periph_buses = PL08X_AHB2,
129 }, {
130 .bus_id = "uart2_rx",
131 .min_signal = 6,
132 .max_signal = 6,
133 .muxval = 1,
134 .periph_buses = PL08X_AHB2,
135 }, {
136 .bus_id = "uart2_tx",
137 .min_signal = 7,
138 .max_signal = 7,
139 .muxval = 1,
140 .periph_buses = PL08X_AHB2,
141 }, {
142 .bus_id = "i2c1_rx",
143 .min_signal = 8,
144 .max_signal = 8,
145 .muxval = 1,
146 .periph_buses = PL08X_AHB2,
147 }, {
148 .bus_id = "i2c1_tx",
149 .min_signal = 9,
150 .max_signal = 9,
151 .muxval = 1,
152 .periph_buses = PL08X_AHB2,
153 }, {
154 .bus_id = "i2c2_rx",
155 .min_signal = 10,
156 .max_signal = 10,
157 .muxval = 1,
158 .periph_buses = PL08X_AHB2,
159 }, {
160 .bus_id = "i2c2_tx",
161 .min_signal = 11,
162 .max_signal = 11,
163 .muxval = 1,
164 .periph_buses = PL08X_AHB2,
165 }, {
166 .bus_id = "i2s_rx",
167 .min_signal = 12,
168 .max_signal = 12,
169 .muxval = 1,
170 .periph_buses = PL08X_AHB2,
171 }, {
172 .bus_id = "i2s_tx",
173 .min_signal = 13,
174 .max_signal = 13,
175 .muxval = 1,
176 .periph_buses = PL08X_AHB2,
177 }, {
178 .bus_id = "rs485_rx",
179 .min_signal = 14,
180 .max_signal = 14,
181 .muxval = 1,
182 .periph_buses = PL08X_AHB2,
183 }, {
184 .bus_id = "rs485_tx",
185 .min_signal = 15,
186 .max_signal = 15,
187 .muxval = 1,
188 .periph_buses = PL08X_AHB2,
189 },
190};
191
192static struct pl022_ssp_controller spear320_ssp_data[] = {
193 {
194 .bus_id = 1,
195 .enable_dma = 1,
196 .dma_filter = pl08x_filter_id,
197 .dma_tx_param = "ssp1_tx",
198 .dma_rx_param = "ssp1_rx",
199 .num_chipselect = 2,
200 }, {
201 .bus_id = 2,
202 .enable_dma = 1,
203 .dma_filter = pl08x_filter_id,
204 .dma_tx_param = "ssp2_tx",
205 .dma_rx_param = "ssp2_rx",
206 .num_chipselect = 2,
207 }
208};
209
210static struct amba_pl011_data spear320_uart_data[] = {
211 {
212 .dma_filter = pl08x_filter_id,
213 .dma_tx_param = "uart1_tx",
214 .dma_rx_param = "uart1_rx",
215 }, {
216 .dma_filter = pl08x_filter_id,
217 .dma_tx_param = "uart2_tx",
218 .dma_rx_param = "uart2_rx",
219 },
220};
221
222/* Add SPEAr310 auxdata to pass platform data */
223static struct of_dev_auxdata spear320_auxdata_lookup[] __initdata = {
224 OF_DEV_AUXDATA("arm,pl022", SPEAR3XX_ICM1_SSP_BASE, NULL,
225 &pl022_plat_data),
226 OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL,
227 &pl080_plat_data),
228 OF_DEV_AUXDATA("arm,pl022", SPEAR320_SSP0_BASE, NULL,
229 &spear320_ssp_data[0]),
230 OF_DEV_AUXDATA("arm,pl022", SPEAR320_SSP1_BASE, NULL,
231 &spear320_ssp_data[1]),
232 OF_DEV_AUXDATA("arm,pl011", SPEAR320_UART1_BASE, NULL,
233 &spear320_uart_data[0]),
234 OF_DEV_AUXDATA("arm,pl011", SPEAR320_UART2_BASE, NULL,
235 &spear320_uart_data[1]),
236 {}
237};
238
239static void __init spear320_dt_init(void)
240{
241 pl080_plat_data.slave_channels = spear320_dma_info;
242 pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
243
244 of_platform_populate(NULL, of_default_bus_match_table,
245 spear320_auxdata_lookup, NULL);
246}
247
248static const char * const spear320_dt_board_compat[] = {
249 "st,spear320",
250 "st,spear320-evb",
251 "st,spear320-hmi",
252 NULL,
253};
254
255struct map_desc spear320_io_desc[] __initdata = {
256 {
257 .virtual = (unsigned long)VA_SPEAR320_SOC_CONFIG_BASE,
258 .pfn = __phys_to_pfn(SPEAR320_SOC_CONFIG_BASE),
259 .length = SZ_16M,
260 .type = MT_DEVICE
261 },
262};
263
264static void __init spear320_map_io(void)
265{
266 iotable_init(spear320_io_desc, ARRAY_SIZE(spear320_io_desc));
267 spear3xx_map_io();
268}
269
270DT_MACHINE_START(SPEAR320_DT, "ST SPEAr320 SoC with Flattened Device Tree")
271 .map_io = spear320_map_io,
272 .init_irq = irqchip_init,
273 .init_time = spear3xx_timer_init,
274 .init_machine = spear320_dt_init,
275 .restart = spear_restart,
276 .dt_compat = spear320_dt_board_compat,
277MACHINE_END
diff --git a/arch/arm/mach-spear/spear3xx.c b/arch/arm/mach-spear/spear3xx.c
new file mode 100644
index 000000000000..0227c97797cd
--- /dev/null
+++ b/arch/arm/mach-spear/spear3xx.c
@@ -0,0 +1,116 @@
1/*
2 * arch/arm/mach-spear3xx/spear3xx.c
3 *
4 * SPEAr3XX machines common source file
5 *
6 * Copyright (C) 2009-2012 ST Microelectronics
7 * Viresh Kumar <viresh.linux@gmail.com>
8 *
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
12 */
13
14#define pr_fmt(fmt) "SPEAr3xx: " fmt
15
16#include <linux/amba/pl022.h>
17#include <linux/amba/pl080.h>
18#include <linux/clk.h>
19#include <linux/io.h>
20#include <asm/mach/map.h>
21#include "pl080.h"
22#include "generic.h"
23#include <mach/spear.h>
24#include <mach/misc_regs.h>
25
26/* ssp device registration */
27struct pl022_ssp_controller pl022_plat_data = {
28 .bus_id = 0,
29 .enable_dma = 1,
30 .dma_filter = pl08x_filter_id,
31 .dma_tx_param = "ssp0_tx",
32 .dma_rx_param = "ssp0_rx",
33 /*
34 * This is number of spi devices that can be connected to spi. There are
35 * two type of chipselects on which slave devices can work. One is chip
36 * select provided by spi masters other is controlled through external
37 * gpio's. We can't use chipselect provided from spi master (because as
38 * soon as FIFO becomes empty, CS is disabled and transfer ends). So
39 * this number now depends on number of gpios available for spi. each
40 * slave on each master requires a separate gpio pin.
41 */
42 .num_chipselect = 2,
43};
44
45/* dmac device registration */
46struct pl08x_platform_data pl080_plat_data = {
47 .memcpy_channel = {
48 .bus_id = "memcpy",
49 .cctl_memcpy =
50 (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
51 PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
52 PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
53 PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
54 PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
55 PL080_CONTROL_PROT_SYS),
56 },
57 .lli_buses = PL08X_AHB1,
58 .mem_buses = PL08X_AHB1,
59 .get_signal = pl080_get_signal,
60 .put_signal = pl080_put_signal,
61};
62
63/*
64 * Following will create 16MB static virtual/physical mappings
65 * PHYSICAL VIRTUAL
66 * 0xD0000000 0xFD000000
67 * 0xFC000000 0xFC000000
68 */
69struct map_desc spear3xx_io_desc[] __initdata = {
70 {
71 .virtual = (unsigned long)VA_SPEAR_ICM1_2_BASE,
72 .pfn = __phys_to_pfn(SPEAR_ICM1_2_BASE),
73 .length = SZ_16M,
74 .type = MT_DEVICE
75 }, {
76 .virtual = (unsigned long)VA_SPEAR_ICM3_SMI_CTRL_BASE,
77 .pfn = __phys_to_pfn(SPEAR_ICM3_SMI_CTRL_BASE),
78 .length = SZ_16M,
79 .type = MT_DEVICE
80 },
81};
82
83/* This will create static memory mapping for selected devices */
84void __init spear3xx_map_io(void)
85{
86 iotable_init(spear3xx_io_desc, ARRAY_SIZE(spear3xx_io_desc));
87}
88
89void __init spear3xx_timer_init(void)
90{
91 char pclk_name[] = "pll3_clk";
92 struct clk *gpt_clk, *pclk;
93
94 spear3xx_clk_init(MISC_BASE, VA_SPEAR320_SOC_CONFIG_BASE);
95
96 /* get the system timer clock */
97 gpt_clk = clk_get_sys("gpt0", NULL);
98 if (IS_ERR(gpt_clk)) {
99 pr_err("%s:couldn't get clk for gpt\n", __func__);
100 BUG();
101 }
102
103 /* get the suitable parent clock for timer*/
104 pclk = clk_get(NULL, pclk_name);
105 if (IS_ERR(pclk)) {
106 pr_err("%s:couldn't get %s as parent for gpt\n",
107 __func__, pclk_name);
108 BUG();
109 }
110
111 clk_set_parent(gpt_clk, pclk);
112 clk_put(gpt_clk);
113 clk_put(pclk);
114
115 spear_setup_of_timer();
116}
diff --git a/arch/arm/mach-spear/spear6xx.c b/arch/arm/mach-spear/spear6xx.c
new file mode 100644
index 000000000000..ec8eefbbdfad
--- /dev/null
+++ b/arch/arm/mach-spear/spear6xx.c
@@ -0,0 +1,431 @@
1/*
2 * arch/arm/mach-spear6xx/spear6xx.c
3 *
4 * SPEAr6XX machines common source file
5 *
6 * Copyright (C) 2009 ST Microelectronics
7 * Rajeev Kumar<rajeev-dlh.kumar@st.com>
8 *
9 * Copyright 2012 Stefan Roese <sr@denx.de>
10 *
11 * This file is licensed under the terms of the GNU General Public
12 * License version 2. This program is licensed "as is" without any
13 * warranty of any kind, whether express or implied.
14 */
15
16#include <linux/amba/pl08x.h>
17#include <linux/clk.h>
18#include <linux/err.h>
19#include <linux/irqchip.h>
20#include <linux/of.h>
21#include <linux/of_address.h>
22#include <linux/of_platform.h>
23#include <linux/amba/pl080.h>
24#include <asm/mach/arch.h>
25#include <asm/mach/time.h>
26#include <asm/mach/map.h>
27#include "pl080.h"
28#include "generic.h"
29#include <mach/spear.h>
30#include <mach/misc_regs.h>
31
32/* dmac device registration */
33static struct pl08x_channel_data spear600_dma_info[] = {
34 {
35 .bus_id = "ssp1_rx",
36 .min_signal = 0,
37 .max_signal = 0,
38 .muxval = 0,
39 .periph_buses = PL08X_AHB1,
40 }, {
41 .bus_id = "ssp1_tx",
42 .min_signal = 1,
43 .max_signal = 1,
44 .muxval = 0,
45 .periph_buses = PL08X_AHB1,
46 }, {
47 .bus_id = "uart0_rx",
48 .min_signal = 2,
49 .max_signal = 2,
50 .muxval = 0,
51 .periph_buses = PL08X_AHB1,
52 }, {
53 .bus_id = "uart0_tx",
54 .min_signal = 3,
55 .max_signal = 3,
56 .muxval = 0,
57 .periph_buses = PL08X_AHB1,
58 }, {
59 .bus_id = "uart1_rx",
60 .min_signal = 4,
61 .max_signal = 4,
62 .muxval = 0,
63 .periph_buses = PL08X_AHB1,
64 }, {
65 .bus_id = "uart1_tx",
66 .min_signal = 5,
67 .max_signal = 5,
68 .muxval = 0,
69 .periph_buses = PL08X_AHB1,
70 }, {
71 .bus_id = "ssp2_rx",
72 .min_signal = 6,
73 .max_signal = 6,
74 .muxval = 0,
75 .periph_buses = PL08X_AHB2,
76 }, {
77 .bus_id = "ssp2_tx",
78 .min_signal = 7,
79 .max_signal = 7,
80 .muxval = 0,
81 .periph_buses = PL08X_AHB2,
82 }, {
83 .bus_id = "ssp0_rx",
84 .min_signal = 8,
85 .max_signal = 8,
86 .muxval = 0,
87 .periph_buses = PL08X_AHB1,
88 }, {
89 .bus_id = "ssp0_tx",
90 .min_signal = 9,
91 .max_signal = 9,
92 .muxval = 0,
93 .periph_buses = PL08X_AHB1,
94 }, {
95 .bus_id = "i2c_rx",
96 .min_signal = 10,
97 .max_signal = 10,
98 .muxval = 0,
99 .periph_buses = PL08X_AHB1,
100 }, {
101 .bus_id = "i2c_tx",
102 .min_signal = 11,
103 .max_signal = 11,
104 .muxval = 0,
105 .periph_buses = PL08X_AHB1,
106 }, {
107 .bus_id = "irda",
108 .min_signal = 12,
109 .max_signal = 12,
110 .muxval = 0,
111 .periph_buses = PL08X_AHB1,
112 }, {
113 .bus_id = "adc",
114 .min_signal = 13,
115 .max_signal = 13,
116 .muxval = 0,
117 .periph_buses = PL08X_AHB2,
118 }, {
119 .bus_id = "to_jpeg",
120 .min_signal = 14,
121 .max_signal = 14,
122 .muxval = 0,
123 .periph_buses = PL08X_AHB1,
124 }, {
125 .bus_id = "from_jpeg",
126 .min_signal = 15,
127 .max_signal = 15,
128 .muxval = 0,
129 .periph_buses = PL08X_AHB1,
130 }, {
131 .bus_id = "ras0_rx",
132 .min_signal = 0,
133 .max_signal = 0,
134 .muxval = 1,
135 .periph_buses = PL08X_AHB1,
136 }, {
137 .bus_id = "ras0_tx",
138 .min_signal = 1,
139 .max_signal = 1,
140 .muxval = 1,
141 .periph_buses = PL08X_AHB1,
142 }, {
143 .bus_id = "ras1_rx",
144 .min_signal = 2,
145 .max_signal = 2,
146 .muxval = 1,
147 .periph_buses = PL08X_AHB1,
148 }, {
149 .bus_id = "ras1_tx",
150 .min_signal = 3,
151 .max_signal = 3,
152 .muxval = 1,
153 .periph_buses = PL08X_AHB1,
154 }, {
155 .bus_id = "ras2_rx",
156 .min_signal = 4,
157 .max_signal = 4,
158 .muxval = 1,
159 .periph_buses = PL08X_AHB1,
160 }, {
161 .bus_id = "ras2_tx",
162 .min_signal = 5,
163 .max_signal = 5,
164 .muxval = 1,
165 .periph_buses = PL08X_AHB1,
166 }, {
167 .bus_id = "ras3_rx",
168 .min_signal = 6,
169 .max_signal = 6,
170 .muxval = 1,
171 .periph_buses = PL08X_AHB1,
172 }, {
173 .bus_id = "ras3_tx",
174 .min_signal = 7,
175 .max_signal = 7,
176 .muxval = 1,
177 .periph_buses = PL08X_AHB1,
178 }, {
179 .bus_id = "ras4_rx",
180 .min_signal = 8,
181 .max_signal = 8,
182 .muxval = 1,
183 .periph_buses = PL08X_AHB1,
184 }, {
185 .bus_id = "ras4_tx",
186 .min_signal = 9,
187 .max_signal = 9,
188 .muxval = 1,
189 .periph_buses = PL08X_AHB1,
190 }, {
191 .bus_id = "ras5_rx",
192 .min_signal = 10,
193 .max_signal = 10,
194 .muxval = 1,
195 .periph_buses = PL08X_AHB1,
196 }, {
197 .bus_id = "ras5_tx",
198 .min_signal = 11,
199 .max_signal = 11,
200 .muxval = 1,
201 .periph_buses = PL08X_AHB1,
202 }, {
203 .bus_id = "ras6_rx",
204 .min_signal = 12,
205 .max_signal = 12,
206 .muxval = 1,
207 .periph_buses = PL08X_AHB1,
208 }, {
209 .bus_id = "ras6_tx",
210 .min_signal = 13,
211 .max_signal = 13,
212 .muxval = 1,
213 .periph_buses = PL08X_AHB1,
214 }, {
215 .bus_id = "ras7_rx",
216 .min_signal = 14,
217 .max_signal = 14,
218 .muxval = 1,
219 .periph_buses = PL08X_AHB1,
220 }, {
221 .bus_id = "ras7_tx",
222 .min_signal = 15,
223 .max_signal = 15,
224 .muxval = 1,
225 .periph_buses = PL08X_AHB1,
226 }, {
227 .bus_id = "ext0_rx",
228 .min_signal = 0,
229 .max_signal = 0,
230 .muxval = 2,
231 .periph_buses = PL08X_AHB2,
232 }, {
233 .bus_id = "ext0_tx",
234 .min_signal = 1,
235 .max_signal = 1,
236 .muxval = 2,
237 .periph_buses = PL08X_AHB2,
238 }, {
239 .bus_id = "ext1_rx",
240 .min_signal = 2,
241 .max_signal = 2,
242 .muxval = 2,
243 .periph_buses = PL08X_AHB2,
244 }, {
245 .bus_id = "ext1_tx",
246 .min_signal = 3,
247 .max_signal = 3,
248 .muxval = 2,
249 .periph_buses = PL08X_AHB2,
250 }, {
251 .bus_id = "ext2_rx",
252 .min_signal = 4,
253 .max_signal = 4,
254 .muxval = 2,
255 .periph_buses = PL08X_AHB2,
256 }, {
257 .bus_id = "ext2_tx",
258 .min_signal = 5,
259 .max_signal = 5,
260 .muxval = 2,
261 .periph_buses = PL08X_AHB2,
262 }, {
263 .bus_id = "ext3_rx",
264 .min_signal = 6,
265 .max_signal = 6,
266 .muxval = 2,
267 .periph_buses = PL08X_AHB2,
268 }, {
269 .bus_id = "ext3_tx",
270 .min_signal = 7,
271 .max_signal = 7,
272 .muxval = 2,
273 .periph_buses = PL08X_AHB2,
274 }, {
275 .bus_id = "ext4_rx",
276 .min_signal = 8,
277 .max_signal = 8,
278 .muxval = 2,
279 .periph_buses = PL08X_AHB2,
280 }, {
281 .bus_id = "ext4_tx",
282 .min_signal = 9,
283 .max_signal = 9,
284 .muxval = 2,
285 .periph_buses = PL08X_AHB2,
286 }, {
287 .bus_id = "ext5_rx",
288 .min_signal = 10,
289 .max_signal = 10,
290 .muxval = 2,
291 .periph_buses = PL08X_AHB2,
292 }, {
293 .bus_id = "ext5_tx",
294 .min_signal = 11,
295 .max_signal = 11,
296 .muxval = 2,
297 .periph_buses = PL08X_AHB2,
298 }, {
299 .bus_id = "ext6_rx",
300 .min_signal = 12,
301 .max_signal = 12,
302 .muxval = 2,
303 .periph_buses = PL08X_AHB2,
304 }, {
305 .bus_id = "ext6_tx",
306 .min_signal = 13,
307 .max_signal = 13,
308 .muxval = 2,
309 .periph_buses = PL08X_AHB2,
310 }, {
311 .bus_id = "ext7_rx",
312 .min_signal = 14,
313 .max_signal = 14,
314 .muxval = 2,
315 .periph_buses = PL08X_AHB2,
316 }, {
317 .bus_id = "ext7_tx",
318 .min_signal = 15,
319 .max_signal = 15,
320 .muxval = 2,
321 .periph_buses = PL08X_AHB2,
322 },
323};
324
325static struct pl08x_platform_data spear6xx_pl080_plat_data = {
326 .memcpy_channel = {
327 .bus_id = "memcpy",
328 .cctl_memcpy =
329 (PL080_BSIZE_16 << PL080_CONTROL_SB_SIZE_SHIFT | \
330 PL080_BSIZE_16 << PL080_CONTROL_DB_SIZE_SHIFT | \
331 PL080_WIDTH_32BIT << PL080_CONTROL_SWIDTH_SHIFT | \
332 PL080_WIDTH_32BIT << PL080_CONTROL_DWIDTH_SHIFT | \
333 PL080_CONTROL_PROT_BUFF | PL080_CONTROL_PROT_CACHE | \
334 PL080_CONTROL_PROT_SYS),
335 },
336 .lli_buses = PL08X_AHB1,
337 .mem_buses = PL08X_AHB1,
338 .get_signal = pl080_get_signal,
339 .put_signal = pl080_put_signal,
340 .slave_channels = spear600_dma_info,
341 .num_slave_channels = ARRAY_SIZE(spear600_dma_info),
342};
343
344/*
345 * Following will create 16MB static virtual/physical mappings
346 * PHYSICAL VIRTUAL
347 * 0xF0000000 0xF0000000
348 * 0xF1000000 0xF1000000
349 * 0xD0000000 0xFD000000
350 * 0xFC000000 0xFC000000
351 */
352struct map_desc spear6xx_io_desc[] __initdata = {
353 {
354 .virtual = (unsigned long)VA_SPEAR6XX_ML_CPU_BASE,
355 .pfn = __phys_to_pfn(SPEAR_ICM3_ML1_2_BASE),
356 .length = 2 * SZ_16M,
357 .type = MT_DEVICE
358 }, {
359 .virtual = (unsigned long)VA_SPEAR_ICM1_2_BASE,
360 .pfn = __phys_to_pfn(SPEAR_ICM1_2_BASE),
361 .length = SZ_16M,
362 .type = MT_DEVICE
363 }, {
364 .virtual = (unsigned long)VA_SPEAR_ICM3_SMI_CTRL_BASE,
365 .pfn = __phys_to_pfn(SPEAR_ICM3_SMI_CTRL_BASE),
366 .length = SZ_16M,
367 .type = MT_DEVICE
368 },
369};
370
371/* This will create static memory mapping for selected devices */
372void __init spear6xx_map_io(void)
373{
374 iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
375}
376
377void __init spear6xx_timer_init(void)
378{
379 char pclk_name[] = "pll3_clk";
380 struct clk *gpt_clk, *pclk;
381
382 spear6xx_clk_init(MISC_BASE);
383
384 /* get the system timer clock */
385 gpt_clk = clk_get_sys("gpt0", NULL);
386 if (IS_ERR(gpt_clk)) {
387 pr_err("%s:couldn't get clk for gpt\n", __func__);
388 BUG();
389 }
390
391 /* get the suitable parent clock for timer*/
392 pclk = clk_get(NULL, pclk_name);
393 if (IS_ERR(pclk)) {
394 pr_err("%s:couldn't get %s as parent for gpt\n",
395 __func__, pclk_name);
396 BUG();
397 }
398
399 clk_set_parent(gpt_clk, pclk);
400 clk_put(gpt_clk);
401 clk_put(pclk);
402
403 spear_setup_of_timer();
404}
405
406/* Add auxdata to pass platform data */
407struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
408 OF_DEV_AUXDATA("arm,pl080", SPEAR_ICM3_DMA_BASE, NULL,
409 &spear6xx_pl080_plat_data),
410 {}
411};
412
413static void __init spear600_dt_init(void)
414{
415 of_platform_populate(NULL, of_default_bus_match_table,
416 spear6xx_auxdata_lookup, NULL);
417}
418
419static const char *spear600_dt_board_compat[] = {
420 "st,spear600",
421 NULL
422};
423
424DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)")
425 .map_io = spear6xx_map_io,
426 .init_irq = irqchip_init,
427 .init_time = spear6xx_timer_init,
428 .init_machine = spear600_dt_init,
429 .restart = spear_restart,
430 .dt_compat = spear600_dt_board_compat,
431MACHINE_END
diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c
new file mode 100644
index 000000000000..d449673e40f7
--- /dev/null
+++ b/arch/arm/mach-spear/time.c
@@ -0,0 +1,245 @@
1/*
2 * arch/arm/plat-spear/time.c
3 *
4 * Copyright (C) 2010 ST Microelectronics
5 * Shiraz Hashim<shiraz.hashim@st.com>
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10 */
11
12#include <linux/clk.h>
13#include <linux/clockchips.h>
14#include <linux/clocksource.h>
15#include <linux/err.h>
16#include <linux/init.h>
17#include <linux/interrupt.h>
18#include <linux/ioport.h>
19#include <linux/io.h>
20#include <linux/kernel.h>
21#include <linux/of_irq.h>
22#include <linux/of_address.h>
23#include <linux/time.h>
24#include <linux/irq.h>
25#include <asm/mach/time.h>
26#include "generic.h"
27
28/*
29 * We would use TIMER0 and TIMER1 as clockevent and clocksource.
30 * Timer0 and Timer1 both belong to same gpt block in cpu subbsystem. Further
31 * they share same functional clock. Any change in one's functional clock will
32 * also affect other timer.
33 */
34
35#define CLKEVT 0 /* gpt0, channel0 as clockevent */
36#define CLKSRC 1 /* gpt0, channel1 as clocksource */
37
38/* Register offsets, x is channel number */
39#define CR(x) ((x) * 0x80 + 0x80)
40#define IR(x) ((x) * 0x80 + 0x84)
41#define LOAD(x) ((x) * 0x80 + 0x88)
42#define COUNT(x) ((x) * 0x80 + 0x8C)
43
44/* Reg bit definitions */
45#define CTRL_INT_ENABLE 0x0100
46#define CTRL_ENABLE 0x0020
47#define CTRL_ONE_SHOT 0x0010
48
49#define CTRL_PRESCALER1 0x0
50#define CTRL_PRESCALER2 0x1
51#define CTRL_PRESCALER4 0x2
52#define CTRL_PRESCALER8 0x3
53#define CTRL_PRESCALER16 0x4
54#define CTRL_PRESCALER32 0x5
55#define CTRL_PRESCALER64 0x6
56#define CTRL_PRESCALER128 0x7
57#define CTRL_PRESCALER256 0x8
58
59#define INT_STATUS 0x1
60
61/*
62 * Minimum clocksource/clockevent timer range in seconds
63 */
64#define SPEAR_MIN_RANGE 4
65
66static __iomem void *gpt_base;
67static struct clk *gpt_clk;
68
69static void clockevent_set_mode(enum clock_event_mode mode,
70 struct clock_event_device *clk_event_dev);
71static int clockevent_next_event(unsigned long evt,
72 struct clock_event_device *clk_event_dev);
73
74static void spear_clocksource_init(void)
75{
76 u32 tick_rate;
77 u16 val;
78
79 /* program the prescaler (/256)*/
80 writew(CTRL_PRESCALER256, gpt_base + CR(CLKSRC));
81
82 /* find out actual clock driving Timer */
83 tick_rate = clk_get_rate(gpt_clk);
84 tick_rate >>= CTRL_PRESCALER256;
85
86 writew(0xFFFF, gpt_base + LOAD(CLKSRC));
87
88 val = readw(gpt_base + CR(CLKSRC));
89 val &= ~CTRL_ONE_SHOT; /* autoreload mode */
90 val |= CTRL_ENABLE ;
91 writew(val, gpt_base + CR(CLKSRC));
92
93 /* register the clocksource */
94 clocksource_mmio_init(gpt_base + COUNT(CLKSRC), "tmr1", tick_rate,
95 200, 16, clocksource_mmio_readw_up);
96}
97
98static struct clock_event_device clkevt = {
99 .name = "tmr0",
100 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
101 .set_mode = clockevent_set_mode,
102 .set_next_event = clockevent_next_event,
103 .shift = 0, /* to be computed */
104};
105
106static void clockevent_set_mode(enum clock_event_mode mode,
107 struct clock_event_device *clk_event_dev)
108{
109 u32 period;
110 u16 val;
111
112 /* stop the timer */
113 val = readw(gpt_base + CR(CLKEVT));
114 val &= ~CTRL_ENABLE;
115 writew(val, gpt_base + CR(CLKEVT));
116
117 switch (mode) {
118 case CLOCK_EVT_MODE_PERIODIC:
119 period = clk_get_rate(gpt_clk) / HZ;
120 period >>= CTRL_PRESCALER16;
121 writew(period, gpt_base + LOAD(CLKEVT));
122
123 val = readw(gpt_base + CR(CLKEVT));
124 val &= ~CTRL_ONE_SHOT;
125 val |= CTRL_ENABLE | CTRL_INT_ENABLE;
126 writew(val, gpt_base + CR(CLKEVT));
127
128 break;
129 case CLOCK_EVT_MODE_ONESHOT:
130 val = readw(gpt_base + CR(CLKEVT));
131 val |= CTRL_ONE_SHOT;
132 writew(val, gpt_base + CR(CLKEVT));
133
134 break;
135 case CLOCK_EVT_MODE_UNUSED:
136 case CLOCK_EVT_MODE_SHUTDOWN:
137 case CLOCK_EVT_MODE_RESUME:
138
139 break;
140 default:
141 pr_err("Invalid mode requested\n");
142 break;
143 }
144}
145
146static int clockevent_next_event(unsigned long cycles,
147 struct clock_event_device *clk_event_dev)
148{
149 u16 val = readw(gpt_base + CR(CLKEVT));
150
151 if (val & CTRL_ENABLE)
152 writew(val & ~CTRL_ENABLE, gpt_base + CR(CLKEVT));
153
154 writew(cycles, gpt_base + LOAD(CLKEVT));
155
156 val |= CTRL_ENABLE | CTRL_INT_ENABLE;
157 writew(val, gpt_base + CR(CLKEVT));
158
159 return 0;
160}
161
162static irqreturn_t spear_timer_interrupt(int irq, void *dev_id)
163{
164 struct clock_event_device *evt = &clkevt;
165
166 writew(INT_STATUS, gpt_base + IR(CLKEVT));
167
168 evt->event_handler(evt);
169
170 return IRQ_HANDLED;
171}
172
173static struct irqaction spear_timer_irq = {
174 .name = "timer",
175 .flags = IRQF_DISABLED | IRQF_TIMER,
176 .handler = spear_timer_interrupt
177};
178
179static void __init spear_clockevent_init(int irq)
180{
181 u32 tick_rate;
182
183 /* program the prescaler */
184 writew(CTRL_PRESCALER16, gpt_base + CR(CLKEVT));
185
186 tick_rate = clk_get_rate(gpt_clk);
187 tick_rate >>= CTRL_PRESCALER16;
188
189 clkevt.cpumask = cpumask_of(0);
190
191 clockevents_config_and_register(&clkevt, tick_rate, 3, 0xfff0);
192
193 setup_irq(irq, &spear_timer_irq);
194}
195
196const static struct of_device_id timer_of_match[] __initconst = {
197 { .compatible = "st,spear-timer", },
198 { },
199};
200
201void __init spear_setup_of_timer(void)
202{
203 struct device_node *np;
204 int irq, ret;
205
206 np = of_find_matching_node(NULL, timer_of_match);
207 if (!np) {
208 pr_err("%s: No timer passed via DT\n", __func__);
209 return;
210 }
211
212 irq = irq_of_parse_and_map(np, 0);
213 if (!irq) {
214 pr_err("%s: No irq passed for timer via DT\n", __func__);
215 return;
216 }
217
218 gpt_base = of_iomap(np, 0);
219 if (!gpt_base) {
220 pr_err("%s: of iomap failed\n", __func__);
221 return;
222 }
223
224 gpt_clk = clk_get_sys("gpt0", NULL);
225 if (!gpt_clk) {
226 pr_err("%s:couldn't get clk for gpt\n", __func__);
227 goto err_iomap;
228 }
229
230 ret = clk_prepare_enable(gpt_clk);
231 if (ret < 0) {
232 pr_err("%s:couldn't prepare-enable gpt clock\n", __func__);
233 goto err_prepare_enable_clk;
234 }
235
236 spear_clockevent_init(irq);
237 spear_clocksource_init();
238
239 return;
240
241err_prepare_enable_clk:
242 clk_put(gpt_clk);
243err_iomap:
244 iounmap(gpt_base);
245}