diff options
47 files changed, 2439 insertions, 36 deletions
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi new file mode 100644 index 000000000000..cb84de791b5a --- /dev/null +++ b/arch/arm/boot/dts/at91sam9n12.dtsi | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * at91sam9n12.dtsi - Device Tree include file for AT91SAM9N12 SoC | ||
3 | * | ||
4 | * Copyright (C) 2012 Atmel, | ||
5 | * 2012 Hong Xu <hong.xu@atmel.com> | ||
6 | * | ||
7 | * Licensed under GPLv2 or later. | ||
8 | */ | ||
9 | |||
10 | /include/ "skeleton.dtsi" | ||
11 | |||
12 | / { | ||
13 | model = "Atmel AT91SAM9N12 SoC"; | ||
14 | compatible = "atmel,at91sam9n12"; | ||
15 | interrupt-parent = <&aic>; | ||
16 | |||
17 | aliases { | ||
18 | serial0 = &dbgu; | ||
19 | serial1 = &usart0; | ||
20 | serial2 = &usart1; | ||
21 | serial3 = &usart2; | ||
22 | serial4 = &usart3; | ||
23 | gpio0 = &pioA; | ||
24 | gpio1 = &pioB; | ||
25 | gpio2 = &pioC; | ||
26 | gpio3 = &pioD; | ||
27 | tcb0 = &tcb0; | ||
28 | tcb1 = &tcb1; | ||
29 | }; | ||
30 | cpus { | ||
31 | cpu@0 { | ||
32 | compatible = "arm,arm926ejs"; | ||
33 | }; | ||
34 | }; | ||
35 | |||
36 | memory { | ||
37 | reg = <0x20000000 0x10000000>; | ||
38 | }; | ||
39 | |||
40 | ahb { | ||
41 | compatible = "simple-bus"; | ||
42 | #address-cells = <1>; | ||
43 | #size-cells = <1>; | ||
44 | ranges; | ||
45 | |||
46 | apb { | ||
47 | compatible = "simple-bus"; | ||
48 | #address-cells = <1>; | ||
49 | #size-cells = <1>; | ||
50 | ranges; | ||
51 | |||
52 | aic: interrupt-controller@fffff000 { | ||
53 | #interrupt-cells = <2>; | ||
54 | compatible = "atmel,at91rm9200-aic"; | ||
55 | interrupt-controller; | ||
56 | reg = <0xfffff000 0x200>; | ||
57 | }; | ||
58 | |||
59 | ramc0: ramc@ffffe800 { | ||
60 | compatible = "atmel,at91sam9g45-ddramc"; | ||
61 | reg = <0xffffe800 0x200>; | ||
62 | }; | ||
63 | |||
64 | pmc: pmc@fffffc00 { | ||
65 | compatible = "atmel,at91rm9200-pmc"; | ||
66 | reg = <0xfffffc00 0x100>; | ||
67 | }; | ||
68 | |||
69 | rstc@fffffe00 { | ||
70 | compatible = "atmel,at91sam9g45-rstc"; | ||
71 | reg = <0xfffffe00 0x10>; | ||
72 | }; | ||
73 | |||
74 | pit: timer@fffffe30 { | ||
75 | compatible = "atmel,at91sam9260-pit"; | ||
76 | reg = <0xfffffe30 0xf>; | ||
77 | interrupts = <1 4>; | ||
78 | }; | ||
79 | |||
80 | shdwc@fffffe10 { | ||
81 | compatible = "atmel,at91sam9x5-shdwc"; | ||
82 | reg = <0xfffffe10 0x10>; | ||
83 | }; | ||
84 | |||
85 | tcb0: timer@f8008000 { | ||
86 | compatible = "atmel,at91sam9x5-tcb"; | ||
87 | reg = <0xf8008000 0x100>; | ||
88 | interrupts = <17 4>; | ||
89 | }; | ||
90 | |||
91 | tcb1: timer@f800c000 { | ||
92 | compatible = "atmel,at91sam9x5-tcb"; | ||
93 | reg = <0xf800c000 0x100>; | ||
94 | interrupts = <17 4>; | ||
95 | }; | ||
96 | |||
97 | dma: dma-controller@ffffec00 { | ||
98 | compatible = "atmel,at91sam9g45-dma"; | ||
99 | reg = <0xffffec00 0x200>; | ||
100 | interrupts = <20 4>; | ||
101 | }; | ||
102 | |||
103 | pioA: gpio@fffff400 { | ||
104 | compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; | ||
105 | reg = <0xfffff400 0x100>; | ||
106 | interrupts = <2 4>; | ||
107 | #gpio-cells = <2>; | ||
108 | gpio-controller; | ||
109 | interrupt-controller; | ||
110 | }; | ||
111 | |||
112 | pioB: gpio@fffff600 { | ||
113 | compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; | ||
114 | reg = <0xfffff600 0x100>; | ||
115 | interrupts = <2 4>; | ||
116 | #gpio-cells = <2>; | ||
117 | gpio-controller; | ||
118 | interrupt-controller; | ||
119 | }; | ||
120 | |||
121 | pioC: gpio@fffff800 { | ||
122 | compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; | ||
123 | reg = <0xfffff800 0x100>; | ||
124 | interrupts = <3 4>; | ||
125 | #gpio-cells = <2>; | ||
126 | gpio-controller; | ||
127 | interrupt-controller; | ||
128 | }; | ||
129 | |||
130 | pioD: gpio@fffffa00 { | ||
131 | compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio"; | ||
132 | reg = <0xfffffa00 0x100>; | ||
133 | interrupts = <3 4>; | ||
134 | #gpio-cells = <2>; | ||
135 | gpio-controller; | ||
136 | interrupt-controller; | ||
137 | }; | ||
138 | |||
139 | dbgu: serial@fffff200 { | ||
140 | compatible = "atmel,at91sam9260-usart"; | ||
141 | reg = <0xfffff200 0x200>; | ||
142 | interrupts = <1 4>; | ||
143 | status = "disabled"; | ||
144 | }; | ||
145 | |||
146 | usart0: serial@f801c000 { | ||
147 | compatible = "atmel,at91sam9260-usart"; | ||
148 | reg = <0xf801c000 0x4000>; | ||
149 | interrupts = <5 4>; | ||
150 | atmel,use-dma-rx; | ||
151 | atmel,use-dma-tx; | ||
152 | status = "disabled"; | ||
153 | }; | ||
154 | |||
155 | usart1: serial@f8020000 { | ||
156 | compatible = "atmel,at91sam9260-usart"; | ||
157 | reg = <0xf8020000 0x4000>; | ||
158 | interrupts = <6 4>; | ||
159 | atmel,use-dma-rx; | ||
160 | atmel,use-dma-tx; | ||
161 | status = "disabled"; | ||
162 | }; | ||
163 | |||
164 | usart2: serial@f8024000 { | ||
165 | compatible = "atmel,at91sam9260-usart"; | ||
166 | reg = <0xf8024000 0x4000>; | ||
167 | interrupts = <7 4>; | ||
168 | atmel,use-dma-rx; | ||
169 | atmel,use-dma-tx; | ||
170 | status = "disabled"; | ||
171 | }; | ||
172 | |||
173 | usart3: serial@f8028000 { | ||
174 | compatible = "atmel,at91sam9260-usart"; | ||
175 | reg = <0xf8028000 0x4000>; | ||
176 | interrupts = <8 4>; | ||
177 | atmel,use-dma-rx; | ||
178 | atmel,use-dma-tx; | ||
179 | status = "disabled"; | ||
180 | }; | ||
181 | }; | ||
182 | |||
183 | nand0: nand@40000000 { | ||
184 | compatible = "atmel,at91rm9200-nand"; | ||
185 | #address-cells = <1>; | ||
186 | #size-cells = <1>; | ||
187 | reg = < 0x40000000 0x10000000 | ||
188 | 0xffffe000 0x00000600 | ||
189 | 0xffffe600 0x00000200 | ||
190 | 0x00100000 0x00100000 | ||
191 | >; | ||
192 | atmel,nand-addr-offset = <21>; | ||
193 | atmel,nand-cmd-offset = <22>; | ||
194 | gpios = <&pioD 5 0 | ||
195 | &pioD 4 0 | ||
196 | 0 | ||
197 | >; | ||
198 | status = "disabled"; | ||
199 | }; | ||
200 | |||
201 | usb0: ohci@00500000 { | ||
202 | compatible = "atmel,at91rm9200-ohci", "usb-ohci"; | ||
203 | reg = <0x00500000 0x00100000>; | ||
204 | interrupts = <22 4>; | ||
205 | status = "disabled"; | ||
206 | }; | ||
207 | }; | ||
208 | |||
209 | i2c@0 { | ||
210 | compatible = "i2c-gpio"; | ||
211 | gpios = <&pioA 30 0 /* sda */ | ||
212 | &pioA 31 0 /* scl */ | ||
213 | >; | ||
214 | i2c-gpio,sda-open-drain; | ||
215 | i2c-gpio,scl-open-drain; | ||
216 | i2c-gpio,delay-us = <2>; /* ~100 kHz */ | ||
217 | #address-cells = <1>; | ||
218 | #size-cells = <0>; | ||
219 | status = "disabled"; | ||
220 | }; | ||
221 | }; | ||
diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts new file mode 100644 index 000000000000..f4e43e38f3a1 --- /dev/null +++ b/arch/arm/boot/dts/at91sam9n12ek.dts | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * at91sam9n12ek.dts - Device Tree file for AT91SAM9N12-EK board | ||
3 | * | ||
4 | * Copyright (C) 2012 Atmel, | ||
5 | * 2012 Hong Xu <hong.xu@atmel.com> | ||
6 | * | ||
7 | * Licensed under GPLv2 or later. | ||
8 | */ | ||
9 | /dts-v1/; | ||
10 | /include/ "at91sam9n12.dtsi" | ||
11 | |||
12 | / { | ||
13 | model = "Atmel AT91SAM9N12-EK"; | ||
14 | compatible = "atmel,at91sam9n12ek", "atmel,at91sam9n12", "atmel,at91sam9"; | ||
15 | |||
16 | chosen { | ||
17 | bootargs = "mem=128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2"; | ||
18 | }; | ||
19 | |||
20 | memory { | ||
21 | reg = <0x20000000 0x10000000>; | ||
22 | }; | ||
23 | |||
24 | clocks { | ||
25 | #address-cells = <1>; | ||
26 | #size-cells = <1>; | ||
27 | ranges; | ||
28 | |||
29 | main_clock: clock@0 { | ||
30 | compatible = "atmel,osc", "fixed-clock"; | ||
31 | clock-frequency = <16000000>; | ||
32 | }; | ||
33 | }; | ||
34 | |||
35 | ahb { | ||
36 | apb { | ||
37 | dbgu: serial@fffff200 { | ||
38 | status = "okay"; | ||
39 | }; | ||
40 | }; | ||
41 | |||
42 | nand0: nand@40000000 { | ||
43 | nand-bus-width = <8>; | ||
44 | nand-ecc-mode = "soft"; | ||
45 | nand-on-flash-bbt; | ||
46 | status = "okay"; | ||
47 | }; | ||
48 | }; | ||
49 | |||
50 | leds { | ||
51 | compatible = "gpio-leds"; | ||
52 | |||
53 | d8 { | ||
54 | label = "d8"; | ||
55 | gpios = <&pioB 4 1>; | ||
56 | linux,default-trigger = "mmc0"; | ||
57 | }; | ||
58 | |||
59 | d9 { | ||
60 | label = "d6"; | ||
61 | gpios = <&pioB 5 1>; | ||
62 | linux,default-trigger = "nand-disk"; | ||
63 | }; | ||
64 | |||
65 | d10 { | ||
66 | label = "d7"; | ||
67 | gpios = <&pioB 6 0>; | ||
68 | linux,default-trigger = "heartbeat"; | ||
69 | }; | ||
70 | }; | ||
71 | |||
72 | gpio_keys { | ||
73 | compatible = "gpio-keys"; | ||
74 | #address-cells = <1>; | ||
75 | #size-cells = <0>; | ||
76 | |||
77 | enter { | ||
78 | label = "Enter"; | ||
79 | gpios = <&pioB 4 1>; | ||
80 | linux,code = <28>; | ||
81 | gpio-key,wakeup; | ||
82 | }; | ||
83 | }; | ||
84 | }; | ||
diff --git a/arch/arm/boot/dts/emev2-kzm9d.dts b/arch/arm/boot/dts/emev2-kzm9d.dts new file mode 100644 index 000000000000..297e3baba71c --- /dev/null +++ b/arch/arm/boot/dts/emev2-kzm9d.dts | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * Device Tree Source for the KZM9D board | ||
3 | * | ||
4 | * Copyright (C) 2012 Renesas Solutions Corp. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | */ | ||
10 | /dts-v1/; | ||
11 | |||
12 | /include/ "emev2.dtsi" | ||
13 | |||
14 | / { | ||
15 | model = "EMEV2 KZM9D Board"; | ||
16 | compatible = "renesas,kzm9d", "renesas,emev2"; | ||
17 | |||
18 | memory { | ||
19 | device_type = "memory"; | ||
20 | reg = <0x40000000 0x8000000>; | ||
21 | }; | ||
22 | |||
23 | chosen { | ||
24 | bootargs = "console=ttyS1,115200n81"; | ||
25 | }; | ||
26 | }; | ||
diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/emev2.dtsi new file mode 100644 index 000000000000..eb504a6c0f4a --- /dev/null +++ b/arch/arm/boot/dts/emev2.dtsi | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Device Tree Source for the EMEV2 SoC | ||
3 | * | ||
4 | * Copyright (C) 2012 Renesas Solutions Corp. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | /include/ "skeleton.dtsi" | ||
12 | |||
13 | / { | ||
14 | compatible = "renesas,emev2"; | ||
15 | interrupt-parent = <&gic>; | ||
16 | |||
17 | cpus { | ||
18 | cpu@0 { | ||
19 | compatible = "arm,cortex-a9"; | ||
20 | }; | ||
21 | cpu@1 { | ||
22 | compatible = "arm,cortex-a9"; | ||
23 | }; | ||
24 | }; | ||
25 | |||
26 | gic: interrupt-controller@e0020000 { | ||
27 | compatible = "arm,cortex-a9-gic"; | ||
28 | interrupt-controller; | ||
29 | #interrupt-cells = <3>; | ||
30 | reg = <0xe0028000 0x1000>, | ||
31 | <0xe0020000 0x0100>; | ||
32 | }; | ||
33 | |||
34 | sti@e0180000 { | ||
35 | compatible = "renesas,em-sti"; | ||
36 | reg = <0xe0180000 0x54>; | ||
37 | interrupts = <0 125 0>; | ||
38 | }; | ||
39 | |||
40 | uart@e1020000 { | ||
41 | compatible = "renesas,em-uart"; | ||
42 | reg = <0xe1020000 0x38>; | ||
43 | interrupts = <0 8 0>; | ||
44 | }; | ||
45 | |||
46 | uart@e1030000 { | ||
47 | compatible = "renesas,em-uart"; | ||
48 | reg = <0xe1030000 0x38>; | ||
49 | interrupts = <0 9 0>; | ||
50 | }; | ||
51 | |||
52 | uart@e1040000 { | ||
53 | compatible = "renesas,em-uart"; | ||
54 | reg = <0xe1040000 0x38>; | ||
55 | interrupts = <0 10 0>; | ||
56 | }; | ||
57 | |||
58 | uart@e1050000 { | ||
59 | compatible = "renesas,em-uart"; | ||
60 | reg = <0xe1050000 0x38>; | ||
61 | interrupts = <0 11 0>; | ||
62 | }; | ||
63 | }; | ||
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 98a42f3472d5..19505c0a3f01 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig | |||
@@ -91,6 +91,14 @@ config SOC_AT91SAM9X5 | |||
91 | This support covers AT91SAM9G15, AT91SAM9G25, AT91SAM9X25, AT91SAM9G35 | 91 | This support covers AT91SAM9G15, AT91SAM9G25, AT91SAM9X25, AT91SAM9G35 |
92 | and AT91SAM9X35. | 92 | and AT91SAM9X35. |
93 | 93 | ||
94 | config SOC_AT91SAM9N12 | ||
95 | bool "AT91SAM9N12 family" | ||
96 | select SOC_AT91SAM9 | ||
97 | select HAVE_AT91_DBGU0 | ||
98 | select HAVE_FB_ATMEL | ||
99 | help | ||
100 | Select this if you are using Atmel's AT91SAM9N12 SoC. | ||
101 | |||
94 | choice | 102 | choice |
95 | prompt "Atmel AT91 Processor Devices for non DT boards" | 103 | prompt "Atmel AT91 Processor Devices for non DT boards" |
96 | 104 | ||
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 79d0f60af0b2..3bb7a51efc9d 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_SOC_AT91SAM9260) += at91sam9260.o | |||
18 | obj-$(CONFIG_SOC_AT91SAM9261) += at91sam9261.o | 18 | obj-$(CONFIG_SOC_AT91SAM9261) += at91sam9261.o |
19 | obj-$(CONFIG_SOC_AT91SAM9263) += at91sam9263.o | 19 | obj-$(CONFIG_SOC_AT91SAM9263) += at91sam9263.o |
20 | obj-$(CONFIG_SOC_AT91SAM9G45) += at91sam9g45.o | 20 | obj-$(CONFIG_SOC_AT91SAM9G45) += at91sam9g45.o |
21 | obj-$(CONFIG_SOC_AT91SAM9N12) += at91sam9n12.o | ||
21 | obj-$(CONFIG_SOC_AT91SAM9X5) += at91sam9x5.o | 22 | obj-$(CONFIG_SOC_AT91SAM9X5) += at91sam9x5.o |
22 | obj-$(CONFIG_SOC_AT91SAM9RL) += at91sam9rl.o | 23 | obj-$(CONFIG_SOC_AT91SAM9RL) += at91sam9rl.o |
23 | 24 | ||
diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot index c03417ddbf0c..9e84fe4f2aaa 100644 --- a/arch/arm/mach-at91/Makefile.boot +++ b/arch/arm/mach-at91/Makefile.boot | |||
@@ -30,5 +30,7 @@ dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9g20.dtb | |||
30 | dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9g20.dtb | 30 | dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9g20.dtb |
31 | # sam9g45 | 31 | # sam9g45 |
32 | dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb | 32 | dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb |
33 | # sam9n12 | ||
34 | dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9n12ek.dtb | ||
33 | # sam9x5 | 35 | # sam9x5 |
34 | dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g25ek.dtb | 36 | dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g25ek.dtb |
diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c new file mode 100644 index 000000000000..08494664ab78 --- /dev/null +++ b/arch/arm/mach-at91/at91sam9n12.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * SoC specific setup code for the AT91SAM9N12 | ||
3 | * | ||
4 | * Copyright (C) 2012 Atmel Corporation. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/dma-mapping.h> | ||
11 | |||
12 | #include <asm/irq.h> | ||
13 | #include <asm/mach/arch.h> | ||
14 | #include <asm/mach/map.h> | ||
15 | #include <mach/at91sam9n12.h> | ||
16 | #include <mach/at91_pmc.h> | ||
17 | #include <mach/cpu.h> | ||
18 | #include <mach/board.h> | ||
19 | |||
20 | #include "soc.h" | ||
21 | #include "generic.h" | ||
22 | #include "clock.h" | ||
23 | #include "sam9_smc.h" | ||
24 | |||
25 | /* -------------------------------------------------------------------- | ||
26 | * Clocks | ||
27 | * -------------------------------------------------------------------- */ | ||
28 | |||
29 | /* | ||
30 | * The peripheral clocks. | ||
31 | */ | ||
32 | static struct clk pioAB_clk = { | ||
33 | .name = "pioAB_clk", | ||
34 | .pmc_mask = 1 << AT91SAM9N12_ID_PIOAB, | ||
35 | .type = CLK_TYPE_PERIPHERAL, | ||
36 | }; | ||
37 | static struct clk pioCD_clk = { | ||
38 | .name = "pioCD_clk", | ||
39 | .pmc_mask = 1 << AT91SAM9N12_ID_PIOCD, | ||
40 | .type = CLK_TYPE_PERIPHERAL, | ||
41 | }; | ||
42 | static struct clk usart0_clk = { | ||
43 | .name = "usart0_clk", | ||
44 | .pmc_mask = 1 << AT91SAM9N12_ID_USART0, | ||
45 | .type = CLK_TYPE_PERIPHERAL, | ||
46 | }; | ||
47 | static struct clk usart1_clk = { | ||
48 | .name = "usart1_clk", | ||
49 | .pmc_mask = 1 << AT91SAM9N12_ID_USART1, | ||
50 | .type = CLK_TYPE_PERIPHERAL, | ||
51 | }; | ||
52 | static struct clk usart2_clk = { | ||
53 | .name = "usart2_clk", | ||
54 | .pmc_mask = 1 << AT91SAM9N12_ID_USART2, | ||
55 | .type = CLK_TYPE_PERIPHERAL, | ||
56 | }; | ||
57 | static struct clk usart3_clk = { | ||
58 | .name = "usart3_clk", | ||
59 | .pmc_mask = 1 << AT91SAM9N12_ID_USART3, | ||
60 | .type = CLK_TYPE_PERIPHERAL, | ||
61 | }; | ||
62 | static struct clk twi0_clk = { | ||
63 | .name = "twi0_clk", | ||
64 | .pmc_mask = 1 << AT91SAM9N12_ID_TWI0, | ||
65 | .type = CLK_TYPE_PERIPHERAL, | ||
66 | }; | ||
67 | static struct clk twi1_clk = { | ||
68 | .name = "twi1_clk", | ||
69 | .pmc_mask = 1 << AT91SAM9N12_ID_TWI1, | ||
70 | .type = CLK_TYPE_PERIPHERAL, | ||
71 | }; | ||
72 | static struct clk mmc_clk = { | ||
73 | .name = "mci_clk", | ||
74 | .pmc_mask = 1 << AT91SAM9N12_ID_MCI, | ||
75 | .type = CLK_TYPE_PERIPHERAL, | ||
76 | }; | ||
77 | static struct clk spi0_clk = { | ||
78 | .name = "spi0_clk", | ||
79 | .pmc_mask = 1 << AT91SAM9N12_ID_SPI0, | ||
80 | .type = CLK_TYPE_PERIPHERAL, | ||
81 | }; | ||
82 | static struct clk spi1_clk = { | ||
83 | .name = "spi1_clk", | ||
84 | .pmc_mask = 1 << AT91SAM9N12_ID_SPI1, | ||
85 | .type = CLK_TYPE_PERIPHERAL, | ||
86 | }; | ||
87 | static struct clk uart0_clk = { | ||
88 | .name = "uart0_clk", | ||
89 | .pmc_mask = 1 << AT91SAM9N12_ID_UART0, | ||
90 | .type = CLK_TYPE_PERIPHERAL, | ||
91 | }; | ||
92 | static struct clk uart1_clk = { | ||
93 | .name = "uart1_clk", | ||
94 | .pmc_mask = 1 << AT91SAM9N12_ID_UART1, | ||
95 | .type = CLK_TYPE_PERIPHERAL, | ||
96 | }; | ||
97 | static struct clk tcb_clk = { | ||
98 | .name = "tcb_clk", | ||
99 | .pmc_mask = 1 << AT91SAM9N12_ID_TCB, | ||
100 | .type = CLK_TYPE_PERIPHERAL, | ||
101 | }; | ||
102 | static struct clk pwm_clk = { | ||
103 | .name = "pwm_clk", | ||
104 | .pmc_mask = 1 << AT91SAM9N12_ID_PWM, | ||
105 | .type = CLK_TYPE_PERIPHERAL, | ||
106 | }; | ||
107 | static struct clk adc_clk = { | ||
108 | .name = "adc_clk", | ||
109 | .pmc_mask = 1 << AT91SAM9N12_ID_ADC, | ||
110 | .type = CLK_TYPE_PERIPHERAL, | ||
111 | }; | ||
112 | static struct clk dma_clk = { | ||
113 | .name = "dma_clk", | ||
114 | .pmc_mask = 1 << AT91SAM9N12_ID_DMA, | ||
115 | .type = CLK_TYPE_PERIPHERAL, | ||
116 | }; | ||
117 | static struct clk uhp_clk = { | ||
118 | .name = "uhp", | ||
119 | .pmc_mask = 1 << AT91SAM9N12_ID_UHP, | ||
120 | .type = CLK_TYPE_PERIPHERAL, | ||
121 | }; | ||
122 | static struct clk udp_clk = { | ||
123 | .name = "udp_clk", | ||
124 | .pmc_mask = 1 << AT91SAM9N12_ID_UDP, | ||
125 | .type = CLK_TYPE_PERIPHERAL, | ||
126 | }; | ||
127 | static struct clk lcdc_clk = { | ||
128 | .name = "lcdc_clk", | ||
129 | .pmc_mask = 1 << AT91SAM9N12_ID_LCDC, | ||
130 | .type = CLK_TYPE_PERIPHERAL, | ||
131 | }; | ||
132 | static struct clk ssc_clk = { | ||
133 | .name = "ssc_clk", | ||
134 | .pmc_mask = 1 << AT91SAM9N12_ID_SSC, | ||
135 | .type = CLK_TYPE_PERIPHERAL, | ||
136 | }; | ||
137 | |||
138 | static struct clk *periph_clocks[] __initdata = { | ||
139 | &pioAB_clk, | ||
140 | &pioCD_clk, | ||
141 | &usart0_clk, | ||
142 | &usart1_clk, | ||
143 | &usart2_clk, | ||
144 | &usart3_clk, | ||
145 | &twi0_clk, | ||
146 | &twi1_clk, | ||
147 | &mmc_clk, | ||
148 | &spi0_clk, | ||
149 | &spi1_clk, | ||
150 | &lcdc_clk, | ||
151 | &uart0_clk, | ||
152 | &uart1_clk, | ||
153 | &tcb_clk, | ||
154 | &pwm_clk, | ||
155 | &adc_clk, | ||
156 | &dma_clk, | ||
157 | &uhp_clk, | ||
158 | &udp_clk, | ||
159 | &ssc_clk, | ||
160 | }; | ||
161 | |||
162 | static struct clk_lookup periph_clocks_lookups[] = { | ||
163 | /* lookup table for DT entries */ | ||
164 | CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck), | ||
165 | CLKDEV_CON_DEV_ID("usart", "f801c000.serial", &usart0_clk), | ||
166 | CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart1_clk), | ||
167 | CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart2_clk), | ||
168 | CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk), | ||
169 | CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb_clk), | ||
170 | CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk), | ||
171 | CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk), | ||
172 | CLKDEV_CON_ID("pioA", &pioAB_clk), | ||
173 | CLKDEV_CON_ID("pioB", &pioAB_clk), | ||
174 | CLKDEV_CON_ID("pioC", &pioCD_clk), | ||
175 | CLKDEV_CON_ID("pioD", &pioCD_clk), | ||
176 | /* additional fake clock for macb_hclk */ | ||
177 | CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &uhp_clk), | ||
178 | CLKDEV_CON_DEV_ID("ohci_clk", "500000.ohci", &uhp_clk), | ||
179 | }; | ||
180 | |||
181 | /* | ||
182 | * The two programmable clocks. | ||
183 | * You must configure pin multiplexing to bring these signals out. | ||
184 | */ | ||
185 | static struct clk pck0 = { | ||
186 | .name = "pck0", | ||
187 | .pmc_mask = AT91_PMC_PCK0, | ||
188 | .type = CLK_TYPE_PROGRAMMABLE, | ||
189 | .id = 0, | ||
190 | }; | ||
191 | static struct clk pck1 = { | ||
192 | .name = "pck1", | ||
193 | .pmc_mask = AT91_PMC_PCK1, | ||
194 | .type = CLK_TYPE_PROGRAMMABLE, | ||
195 | .id = 1, | ||
196 | }; | ||
197 | |||
198 | static void __init at91sam9n12_register_clocks(void) | ||
199 | { | ||
200 | int i; | ||
201 | |||
202 | for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) | ||
203 | clk_register(periph_clocks[i]); | ||
204 | clk_register(&pck0); | ||
205 | clk_register(&pck1); | ||
206 | |||
207 | clkdev_add_table(periph_clocks_lookups, | ||
208 | ARRAY_SIZE(periph_clocks_lookups)); | ||
209 | |||
210 | } | ||
211 | |||
212 | /* -------------------------------------------------------------------- | ||
213 | * AT91SAM9N12 processor initialization | ||
214 | * -------------------------------------------------------------------- */ | ||
215 | |||
216 | static void __init at91sam9n12_map_io(void) | ||
217 | { | ||
218 | at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE); | ||
219 | } | ||
220 | |||
221 | void __init at91sam9n12_initialize(void) | ||
222 | { | ||
223 | at91_extern_irq = (1 << AT91SAM9N12_ID_IRQ0); | ||
224 | |||
225 | /* Register GPIO subsystem (using DT) */ | ||
226 | at91_gpio_init(NULL, 0); | ||
227 | } | ||
228 | |||
229 | struct at91_init_soc __initdata at91sam9n12_soc = { | ||
230 | .map_io = at91sam9n12_map_io, | ||
231 | .register_clocks = at91sam9n12_register_clocks, | ||
232 | .init = at91sam9n12_initialize, | ||
233 | }; | ||
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 6b692824c988..de2ec6b8fea7 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c | |||
@@ -58,13 +58,15 @@ EXPORT_SYMBOL_GPL(at91_pmc_base); | |||
58 | 58 | ||
59 | #define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \ | 59 | #define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \ |
60 | || cpu_is_at91sam9g45() \ | 60 | || cpu_is_at91sam9g45() \ |
61 | || cpu_is_at91sam9x5()) | 61 | || cpu_is_at91sam9x5() \ |
62 | || cpu_is_at91sam9n12()) | ||
62 | 63 | ||
63 | #define cpu_has_300M_plla() (cpu_is_at91sam9g10()) | 64 | #define cpu_has_300M_plla() (cpu_is_at91sam9g10()) |
64 | 65 | ||
65 | #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ | 66 | #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ |
66 | || cpu_is_at91sam9g45() \ | 67 | || cpu_is_at91sam9g45() \ |
67 | || cpu_is_at91sam9x5())) | 68 | || cpu_is_at91sam9x5() \ |
69 | || cpu_is_at91sam9n12())) | ||
68 | 70 | ||
69 | #define cpu_has_upll() (cpu_is_at91sam9g45() \ | 71 | #define cpu_has_upll() (cpu_is_at91sam9g45() \ |
70 | || cpu_is_at91sam9x5()) | 72 | || cpu_is_at91sam9x5()) |
@@ -78,12 +80,15 @@ EXPORT_SYMBOL_GPL(at91_pmc_base); | |||
78 | || cpu_is_at91sam9x5())) | 80 | || cpu_is_at91sam9x5())) |
79 | 81 | ||
80 | #define cpu_has_plladiv2() (cpu_is_at91sam9g45() \ | 82 | #define cpu_has_plladiv2() (cpu_is_at91sam9g45() \ |
81 | || cpu_is_at91sam9x5()) | 83 | || cpu_is_at91sam9x5() \ |
84 | || cpu_is_at91sam9n12()) | ||
82 | 85 | ||
83 | #define cpu_has_mdiv3() (cpu_is_at91sam9g45() \ | 86 | #define cpu_has_mdiv3() (cpu_is_at91sam9g45() \ |
84 | || cpu_is_at91sam9x5()) | 87 | || cpu_is_at91sam9x5() \ |
88 | || cpu_is_at91sam9n12()) | ||
85 | 89 | ||
86 | #define cpu_has_alt_prescaler() (cpu_is_at91sam9x5()) | 90 | #define cpu_has_alt_prescaler() (cpu_is_at91sam9x5() \ |
91 | || cpu_is_at91sam9n12()) | ||
87 | 92 | ||
88 | static LIST_HEAD(clocks); | 93 | static LIST_HEAD(clocks); |
89 | static DEFINE_SPINLOCK(clk_lock); | 94 | static DEFINE_SPINLOCK(clk_lock); |
diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12.h b/arch/arm/mach-at91/include/mach/at91sam9n12.h new file mode 100644 index 000000000000..d374b87c0459 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at91sam9n12.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * SoC specific header file for the AT91SAM9N12 | ||
3 | * | ||
4 | * Copyright (C) 2012 Atmel Corporation | ||
5 | * | ||
6 | * Common definitions, based on AT91SAM9N12 SoC datasheet | ||
7 | * | ||
8 | * Licensed under GPLv2 or later | ||
9 | */ | ||
10 | |||
11 | #ifndef _AT91SAM9N12_H_ | ||
12 | #define _AT91SAM9N12_H_ | ||
13 | |||
14 | /* | ||
15 | * Peripheral identifiers/interrupts. | ||
16 | */ | ||
17 | #define AT91SAM9N12_ID_PIOAB 2 /* Parallel I/O Controller A and B */ | ||
18 | #define AT91SAM9N12_ID_PIOCD 3 /* Parallel I/O Controller C and D */ | ||
19 | #define AT91SAM9N12_ID_FUSE 4 /* FUSE Controller */ | ||
20 | #define AT91SAM9N12_ID_USART0 5 /* USART 0 */ | ||
21 | #define AT91SAM9N12_ID_USART1 6 /* USART 1 */ | ||
22 | #define AT91SAM9N12_ID_USART2 7 /* USART 2 */ | ||
23 | #define AT91SAM9N12_ID_USART3 8 /* USART 3 */ | ||
24 | #define AT91SAM9N12_ID_TWI0 9 /* Two-Wire Interface 0 */ | ||
25 | #define AT91SAM9N12_ID_TWI1 10 /* Two-Wire Interface 1 */ | ||
26 | #define AT91SAM9N12_ID_MCI 12 /* High Speed Multimedia Card Interface */ | ||
27 | #define AT91SAM9N12_ID_SPI0 13 /* Serial Peripheral Interface 0 */ | ||
28 | #define AT91SAM9N12_ID_SPI1 14 /* Serial Peripheral Interface 1 */ | ||
29 | #define AT91SAM9N12_ID_UART0 15 /* UART 0 */ | ||
30 | #define AT91SAM9N12_ID_UART1 16 /* UART 1 */ | ||
31 | #define AT91SAM9N12_ID_TCB 17 /* Timer Counter 0, 1, 2, 3, 4 and 5 */ | ||
32 | #define AT91SAM9N12_ID_PWM 18 /* Pulse Width Modulation Controller */ | ||
33 | #define AT91SAM9N12_ID_ADC 19 /* ADC Controller */ | ||
34 | #define AT91SAM9N12_ID_DMA 20 /* DMA Controller */ | ||
35 | #define AT91SAM9N12_ID_UHP 22 /* USB Host High Speed */ | ||
36 | #define AT91SAM9N12_ID_UDP 23 /* USB Device High Speed */ | ||
37 | #define AT91SAM9N12_ID_LCDC 25 /* LCD Controller */ | ||
38 | #define AT91SAM9N12_ID_ISI 25 /* Image Sensor Interface */ | ||
39 | #define AT91SAM9N12_ID_SSC 28 /* Synchronous Serial Controller */ | ||
40 | #define AT91SAM9N12_ID_TRNG 30 /* TRNG */ | ||
41 | #define AT91SAM9N12_ID_IRQ0 31 /* Advanced Interrupt Controller */ | ||
42 | |||
43 | /* | ||
44 | * User Peripheral physical base addresses. | ||
45 | */ | ||
46 | #define AT91SAM9N12_BASE_USART0 0xf801c000 | ||
47 | #define AT91SAM9N12_BASE_USART1 0xf8020000 | ||
48 | #define AT91SAM9N12_BASE_USART2 0xf8024000 | ||
49 | #define AT91SAM9N12_BASE_USART3 0xf8028000 | ||
50 | |||
51 | /* | ||
52 | * Internal Memory. | ||
53 | */ | ||
54 | #define AT91SAM9N12_SRAM_BASE 0x00300000 /* Internal SRAM base address */ | ||
55 | #define AT91SAM9N12_SRAM_SIZE SZ_32K /* Internal SRAM size (32Kb) */ | ||
56 | |||
57 | #define AT91SAM9N12_ROM_BASE 0x00100000 /* Internal ROM base address */ | ||
58 | #define AT91SAM9N12_ROM_SIZE SZ_128K /* Internal ROM size (128Kb) */ | ||
59 | |||
60 | #endif | ||
diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h new file mode 100644 index 000000000000..40060cd62fa9 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Matrix-centric header file for the AT91SAM9N12 | ||
3 | * | ||
4 | * Copyright (C) 2012 Atmel Corporation. | ||
5 | * | ||
6 | * Only EBI related registers. | ||
7 | * Write Protect register definitions may be useful. | ||
8 | * | ||
9 | * Licensed under GPLv2 or later. | ||
10 | */ | ||
11 | |||
12 | #ifndef _AT91SAM9N12_MATRIX_H_ | ||
13 | #define _AT91SAM9N12_MATRIX_H_ | ||
14 | |||
15 | #define AT91_MATRIX_EBICSA (AT91_MATRIX + 0x118) /* EBI Chip Select Assignment Register */ | ||
16 | #define AT91_MATRIX_EBI_CS1A (1 << 1) /* Chip Select 1 Assignment */ | ||
17 | #define AT91_MATRIX_EBI_CS1A_SMC (0 << 1) | ||
18 | #define AT91_MATRIX_EBI_CS1A_SDRAMC (1 << 1) | ||
19 | #define AT91_MATRIX_EBI_CS3A (1 << 3) /* Chip Select 3 Assignment */ | ||
20 | #define AT91_MATRIX_EBI_CS3A_SMC (0 << 3) | ||
21 | #define AT91_MATRIX_EBI_CS3A_SMC_NANDFLASH (1 << 3) | ||
22 | #define AT91_MATRIX_EBI_DBPUC (1 << 8) /* Data Bus Pull-up Configuration */ | ||
23 | #define AT91_MATRIX_EBI_DBPU_ON (0 << 8) | ||
24 | #define AT91_MATRIX_EBI_DBPU_OFF (1 << 8) | ||
25 | #define AT91_MATRIX_EBI_VDDIOMSEL (1 << 16) /* Memory voltage selection */ | ||
26 | #define AT91_MATRIX_EBI_VDDIOMSEL_1_8V (0 << 16) | ||
27 | #define AT91_MATRIX_EBI_VDDIOMSEL_3_3V (1 << 16) | ||
28 | #define AT91_MATRIX_EBI_EBI_IOSR (1 << 17) /* EBI I/O slew rate selection */ | ||
29 | #define AT91_MATRIX_EBI_EBI_IOSR_REDUCED (0 << 17) | ||
30 | #define AT91_MATRIX_EBI_EBI_IOSR_NORMAL (1 << 17) | ||
31 | #define AT91_MATRIX_EBI_DDR_IOSR (1 << 18) /* DDR2 dedicated port I/O slew rate selection */ | ||
32 | #define AT91_MATRIX_EBI_DDR_IOSR_REDUCED (0 << 18) | ||
33 | #define AT91_MATRIX_EBI_DDR_IOSR_NORMAL (1 << 18) | ||
34 | #define AT91_MATRIX_NFD0_SELECT (1 << 24) /* NAND Flash Data Bus Selection */ | ||
35 | #define AT91_MATRIX_NFD0_ON_D0 (0 << 24) | ||
36 | #define AT91_MATRIX_NFD0_ON_D16 (1 << 24) | ||
37 | #define AT91_MATRIX_DDR_MP_EN (1 << 25) /* DDR Multi-port Enable */ | ||
38 | #define AT91_MATRIX_MP_OFF (0 << 25) | ||
39 | #define AT91_MATRIX_MP_ON (1 << 25) | ||
40 | |||
41 | #define AT91_MATRIX_WPMR (AT91_MATRIX + 0x1E4) /* Write Protect Mode Register */ | ||
42 | #define AT91_MATRIX_WPMR_WPEN (1 << 0) /* Write Protect ENable */ | ||
43 | #define AT91_MATRIX_WPMR_WP_WPDIS (0 << 0) | ||
44 | #define AT91_MATRIX_WPMR_WP_WPEN (1 << 0) | ||
45 | #define AT91_MATRIX_WPMR_WPKEY (0xFFFFFF << 8) /* Write Protect KEY */ | ||
46 | |||
47 | #define AT91_MATRIX_WPSR (AT91_MATRIX + 0x1E8) /* Write Protect Status Register */ | ||
48 | #define AT91_MATRIX_WPSR_WPVS (1 << 0) /* Write Protect Violation Status */ | ||
49 | #define AT91_MATRIX_WPSR_NO_WPV (0 << 0) | ||
50 | #define AT91_MATRIX_WPSR_WPV (1 << 0) | ||
51 | #define AT91_MATRIX_WPSR_WPVSRC (0xFFFF << 8) /* Write Protect Violation Source */ | ||
52 | |||
53 | #endif | ||
diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index 73d2fd209ce4..b6504c19d55c 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define ARCH_ID_AT91SAM9G45MRL 0x819b05a2 /* aka 9G45-ES2 & non ES lots */ | 25 | #define ARCH_ID_AT91SAM9G45MRL 0x819b05a2 /* aka 9G45-ES2 & non ES lots */ |
26 | #define ARCH_ID_AT91SAM9G45ES 0x819b05a1 /* 9G45-ES (Engineering Sample) */ | 26 | #define ARCH_ID_AT91SAM9G45ES 0x819b05a1 /* 9G45-ES (Engineering Sample) */ |
27 | #define ARCH_ID_AT91SAM9X5 0x819a05a0 | 27 | #define ARCH_ID_AT91SAM9X5 0x819a05a0 |
28 | #define ARCH_ID_AT91SAM9N12 0x819a07a0 | ||
28 | 29 | ||
29 | #define ARCH_ID_AT91SAM9XE128 0x329973a0 | 30 | #define ARCH_ID_AT91SAM9XE128 0x329973a0 |
30 | #define ARCH_ID_AT91SAM9XE256 0x329a93a0 | 31 | #define ARCH_ID_AT91SAM9XE256 0x329a93a0 |
@@ -71,6 +72,9 @@ enum at91_soc_type { | |||
71 | /* SAM9X5 */ | 72 | /* SAM9X5 */ |
72 | AT91_SOC_SAM9X5, | 73 | AT91_SOC_SAM9X5, |
73 | 74 | ||
75 | /* SAM9N12 */ | ||
76 | AT91_SOC_SAM9N12, | ||
77 | |||
74 | /* Unknown type */ | 78 | /* Unknown type */ |
75 | AT91_SOC_NONE | 79 | AT91_SOC_NONE |
76 | }; | 80 | }; |
@@ -177,6 +181,12 @@ static inline int at91_soc_is_detected(void) | |||
177 | #define cpu_is_at91sam9x25() (0) | 181 | #define cpu_is_at91sam9x25() (0) |
178 | #endif | 182 | #endif |
179 | 183 | ||
184 | #ifdef CONFIG_SOC_AT91SAM9N12 | ||
185 | #define cpu_is_at91sam9n12() (at91_soc_initdata.type == AT91_SOC_SAM9N12) | ||
186 | #else | ||
187 | #define cpu_is_at91sam9n12() (0) | ||
188 | #endif | ||
189 | |||
180 | /* | 190 | /* |
181 | * Since this is ARM, we will never run on any AVR32 CPU. But these | 191 | * Since this is ARM, we will never run on any AVR32 CPU. But these |
182 | * definitions may reduce clutter in common drivers. | 192 | * definitions may reduce clutter in common drivers. |
diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h index ef5786299c60..09242b67d277 100644 --- a/arch/arm/mach-at91/include/mach/hardware.h +++ b/arch/arm/mach-at91/include/mach/hardware.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <mach/at91sam9rl.h> | 32 | #include <mach/at91sam9rl.h> |
33 | #include <mach/at91sam9g45.h> | 33 | #include <mach/at91sam9g45.h> |
34 | #include <mach/at91sam9x5.h> | 34 | #include <mach/at91sam9x5.h> |
35 | #include <mach/at91sam9n12.h> | ||
35 | 36 | ||
36 | /* | 37 | /* |
37 | * On all at91 except rm9200 and x40 have the System Controller starts | 38 | * On all at91 except rm9200 and x40 have the System Controller starts |
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index f44a2e7272e3..944bffb08991 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c | |||
@@ -143,6 +143,11 @@ static void __init soc_detect(u32 dbgu_base) | |||
143 | at91_soc_initdata.type = AT91_SOC_SAM9X5; | 143 | at91_soc_initdata.type = AT91_SOC_SAM9X5; |
144 | at91_boot_soc = at91sam9x5_soc; | 144 | at91_boot_soc = at91sam9x5_soc; |
145 | break; | 145 | break; |
146 | |||
147 | case ARCH_ID_AT91SAM9N12: | ||
148 | at91_soc_initdata.type = AT91_SOC_SAM9N12; | ||
149 | at91_boot_soc = at91sam9n12_soc; | ||
150 | break; | ||
146 | } | 151 | } |
147 | 152 | ||
148 | /* at91sam9g10 */ | 153 | /* at91sam9g10 */ |
@@ -210,6 +215,7 @@ static const char *soc_name[] = { | |||
210 | [AT91_SOC_SAM9G45] = "at91sam9g45", | 215 | [AT91_SOC_SAM9G45] = "at91sam9g45", |
211 | [AT91_SOC_SAM9RL] = "at91sam9rl", | 216 | [AT91_SOC_SAM9RL] = "at91sam9rl", |
212 | [AT91_SOC_SAM9X5] = "at91sam9x5", | 217 | [AT91_SOC_SAM9X5] = "at91sam9x5", |
218 | [AT91_SOC_SAM9N12] = "at91sam9n12", | ||
213 | [AT91_SOC_NONE] = "Unknown" | 219 | [AT91_SOC_NONE] = "Unknown" |
214 | }; | 220 | }; |
215 | 221 | ||
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h index 683dddfd8b13..a9cfeb153719 100644 --- a/arch/arm/mach-at91/soc.h +++ b/arch/arm/mach-at91/soc.h | |||
@@ -20,6 +20,7 @@ extern struct at91_init_soc at91sam9263_soc; | |||
20 | extern struct at91_init_soc at91sam9g45_soc; | 20 | extern struct at91_init_soc at91sam9g45_soc; |
21 | extern struct at91_init_soc at91sam9rl_soc; | 21 | extern struct at91_init_soc at91sam9rl_soc; |
22 | extern struct at91_init_soc at91sam9x5_soc; | 22 | extern struct at91_init_soc at91sam9x5_soc; |
23 | extern struct at91_init_soc at91sam9n12_soc; | ||
23 | 24 | ||
24 | static inline int at91_soc_is_enabled(void) | 25 | static inline int at91_soc_is_enabled(void) |
25 | { | 26 | { |
@@ -53,3 +54,7 @@ static inline int at91_soc_is_enabled(void) | |||
53 | #if !defined(CONFIG_SOC_AT91SAM9X5) | 54 | #if !defined(CONFIG_SOC_AT91SAM9X5) |
54 | #define at91sam9x5_soc at91_boot_soc | 55 | #define at91sam9x5_soc at91_boot_soc |
55 | #endif | 56 | #endif |
57 | |||
58 | #if !defined(CONFIG_SOC_AT91SAM9N12) | ||
59 | #define at91sam9n12_soc at91_boot_soc | ||
60 | #endif | ||
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 34560cab45d9..7dcf08ee979d 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig | |||
@@ -41,6 +41,12 @@ config ARCH_R8A7779 | |||
41 | select ARM_GIC | 41 | select ARM_GIC |
42 | select ARCH_WANT_OPTIONAL_GPIOLIB | 42 | select ARCH_WANT_OPTIONAL_GPIOLIB |
43 | 43 | ||
44 | config ARCH_EMEV2 | ||
45 | bool "Emma Mobile EV2" | ||
46 | select CPU_V7 | ||
47 | select ARM_GIC | ||
48 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
49 | |||
44 | comment "SH-Mobile Board Type" | 50 | comment "SH-Mobile Board Type" |
45 | 51 | ||
46 | config MACH_G3EVM | 52 | config MACH_G3EVM |
@@ -98,6 +104,11 @@ config MACH_MARZEN | |||
98 | depends on ARCH_R8A7779 | 104 | depends on ARCH_R8A7779 |
99 | select ARCH_REQUIRE_GPIOLIB | 105 | select ARCH_REQUIRE_GPIOLIB |
100 | 106 | ||
107 | config MACH_KZM9D | ||
108 | bool "KZM9D board" | ||
109 | depends on ARCH_EMEV2 | ||
110 | select USE_OF | ||
111 | |||
101 | comment "SH-Mobile System Configuration" | 112 | comment "SH-Mobile System Configuration" |
102 | 113 | ||
103 | config CPU_HAS_INTEVT | 114 | config CPU_HAS_INTEVT |
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index e7c2590b75d9..c795335931c9 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile | |||
@@ -12,12 +12,14 @@ obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o | |||
12 | obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o | 12 | obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o |
13 | obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o | 13 | obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o |
14 | obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o | 14 | obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o |
15 | obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o | ||
15 | 16 | ||
16 | # SMP objects | 17 | # SMP objects |
17 | smp-y := platsmp.o headsmp.o | 18 | smp-y := platsmp.o headsmp.o |
18 | smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 19 | smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
19 | smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o | 20 | smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o |
20 | smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o | 21 | smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o |
22 | smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o | ||
21 | 23 | ||
22 | # Pinmux setup | 24 | # Pinmux setup |
23 | pfc-y := | 25 | pfc-y := |
@@ -49,6 +51,7 @@ obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o | |||
49 | obj-$(CONFIG_MACH_KOTA2) += board-kota2.o | 51 | obj-$(CONFIG_MACH_KOTA2) += board-kota2.o |
50 | obj-$(CONFIG_MACH_BONITO) += board-bonito.o | 52 | obj-$(CONFIG_MACH_BONITO) += board-bonito.o |
51 | obj-$(CONFIG_MACH_MARZEN) += board-marzen.o | 53 | obj-$(CONFIG_MACH_MARZEN) += board-marzen.o |
54 | obj-$(CONFIG_MACH_KZM9D) += board-kzm9d.o | ||
52 | 55 | ||
53 | # Framework support | 56 | # Framework support |
54 | obj-$(CONFIG_SMP) += $(smp-y) | 57 | obj-$(CONFIG_SMP) += $(smp-y) |
diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c new file mode 100644 index 000000000000..7bc5e7d39f9b --- /dev/null +++ b/arch/arm/mach-shmobile/board-kzm9d.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * kzm9d board support | ||
3 | * | ||
4 | * Copyright (C) 2012 Renesas Solutions Corp. | ||
5 | * Copyright (C) 2012 Magnus Damm | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/smsc911x.h> | ||
25 | #include <mach/common.h> | ||
26 | #include <mach/emev2.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | #include <asm/mach/arch.h> | ||
29 | #include <asm/hardware/gic.h> | ||
30 | |||
31 | /* Ether */ | ||
32 | static struct resource smsc911x_resources[] = { | ||
33 | [0] = { | ||
34 | .start = 0x20000000, | ||
35 | .end = 0x2000ffff, | ||
36 | .flags = IORESOURCE_MEM, | ||
37 | }, | ||
38 | [1] = { | ||
39 | .start = EMEV2_GPIO_IRQ(1), | ||
40 | .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, | ||
41 | }, | ||
42 | }; | ||
43 | |||
44 | static struct smsc911x_platform_config smsc911x_platdata = { | ||
45 | .flags = SMSC911X_USE_32BIT, | ||
46 | .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, | ||
47 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH, | ||
48 | }; | ||
49 | |||
50 | static struct platform_device smsc91x_device = { | ||
51 | .name = "smsc911x", | ||
52 | .id = 0, | ||
53 | .dev = { | ||
54 | .platform_data = &smsc911x_platdata, | ||
55 | }, | ||
56 | .num_resources = ARRAY_SIZE(smsc911x_resources), | ||
57 | .resource = smsc911x_resources, | ||
58 | }; | ||
59 | |||
60 | static struct platform_device *kzm9d_devices[] __initdata = { | ||
61 | &smsc91x_device, | ||
62 | }; | ||
63 | |||
64 | void __init kzm9d_add_standard_devices(void) | ||
65 | { | ||
66 | emev2_add_standard_devices(); | ||
67 | |||
68 | platform_add_devices(kzm9d_devices, ARRAY_SIZE(kzm9d_devices)); | ||
69 | } | ||
70 | |||
71 | static const char *kzm9d_boards_compat_dt[] __initdata = { | ||
72 | "renesas,kzm9d", | ||
73 | NULL, | ||
74 | }; | ||
75 | |||
76 | DT_MACHINE_START(KZM9D_DT, "kzm9d") | ||
77 | .map_io = emev2_map_io, | ||
78 | .init_early = emev2_add_early_devices, | ||
79 | .nr_irqs = NR_IRQS_LEGACY, | ||
80 | .init_irq = emev2_init_irq, | ||
81 | .handle_irq = gic_handle_irq, | ||
82 | .init_machine = kzm9d_add_standard_devices, | ||
83 | .timer = &shmobile_timer, | ||
84 | .dt_compat = kzm9d_boards_compat_dt, | ||
85 | MACHINE_END | ||
diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c new file mode 100644 index 000000000000..4710f1847bb7 --- /dev/null +++ b/arch/arm/mach-shmobile/clock-emev2.c | |||
@@ -0,0 +1,249 @@ | |||
1 | /* | ||
2 | * Emma Mobile EV2 clock framework support | ||
3 | * | ||
4 | * Copyright (C) 2012 Magnus Damm | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/sh_clk.h> | ||
23 | #include <linux/clkdev.h> | ||
24 | #include <mach/common.h> | ||
25 | |||
26 | #define EMEV2_SMU_BASE 0xe0110000 | ||
27 | |||
28 | /* EMEV2 SMU registers */ | ||
29 | #define USIAU0_RSTCTRL 0x094 | ||
30 | #define USIBU1_RSTCTRL 0x0ac | ||
31 | #define USIBU2_RSTCTRL 0x0b0 | ||
32 | #define USIBU3_RSTCTRL 0x0b4 | ||
33 | #define STI_RSTCTRL 0x124 | ||
34 | #define USIAU0GCLKCTRL 0x4a0 | ||
35 | #define USIBU1GCLKCTRL 0x4b8 | ||
36 | #define USIBU2GCLKCTRL 0x4bc | ||
37 | #define USIBU3GCLKCTRL 0x04c0 | ||
38 | #define STIGCLKCTRL 0x528 | ||
39 | #define USIAU0SCLKDIV 0x61c | ||
40 | #define USIB2SCLKDIV 0x65c | ||
41 | #define USIB3SCLKDIV 0x660 | ||
42 | #define STI_CLKSEL 0x688 | ||
43 | #define SMU_GENERAL_REG0 0x7c0 | ||
44 | |||
45 | /* not pretty, but hey */ | ||
46 | static void __iomem *smu_base; | ||
47 | |||
48 | static void emev2_smu_write(unsigned long value, int offs) | ||
49 | { | ||
50 | BUG_ON(!smu_base || (offs >= PAGE_SIZE)); | ||
51 | iowrite32(value, smu_base + offs); | ||
52 | } | ||
53 | |||
54 | void emev2_set_boot_vector(unsigned long value) | ||
55 | { | ||
56 | emev2_smu_write(value, SMU_GENERAL_REG0); | ||
57 | } | ||
58 | |||
59 | static struct clk_mapping smu_mapping = { | ||
60 | .phys = EMEV2_SMU_BASE, | ||
61 | .len = PAGE_SIZE, | ||
62 | }; | ||
63 | |||
64 | /* Fixed 32 KHz root clock from C32K pin */ | ||
65 | static struct clk c32k_clk = { | ||
66 | .rate = 32768, | ||
67 | .mapping = &smu_mapping, | ||
68 | }; | ||
69 | |||
70 | /* PLL3 multiplies C32K with 7000 */ | ||
71 | static unsigned long pll3_recalc(struct clk *clk) | ||
72 | { | ||
73 | return clk->parent->rate * 7000; | ||
74 | } | ||
75 | |||
76 | static struct sh_clk_ops pll3_clk_ops = { | ||
77 | .recalc = pll3_recalc, | ||
78 | }; | ||
79 | |||
80 | static struct clk pll3_clk = { | ||
81 | .ops = &pll3_clk_ops, | ||
82 | .parent = &c32k_clk, | ||
83 | }; | ||
84 | |||
85 | static struct clk *main_clks[] = { | ||
86 | &c32k_clk, | ||
87 | &pll3_clk, | ||
88 | }; | ||
89 | |||
90 | enum { SCLKDIV_USIAU0, SCLKDIV_USIBU2, SCLKDIV_USIBU1, SCLKDIV_USIBU3, | ||
91 | SCLKDIV_NR }; | ||
92 | |||
93 | #define SCLKDIV(_reg, _shift) \ | ||
94 | { \ | ||
95 | .parent = &pll3_clk, \ | ||
96 | .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \ | ||
97 | .enable_bit = _shift, \ | ||
98 | } | ||
99 | |||
100 | static struct clk sclkdiv_clks[SCLKDIV_NR] = { | ||
101 | [SCLKDIV_USIAU0] = SCLKDIV(USIAU0SCLKDIV, 0), | ||
102 | [SCLKDIV_USIBU2] = SCLKDIV(USIB2SCLKDIV, 16), | ||
103 | [SCLKDIV_USIBU1] = SCLKDIV(USIB2SCLKDIV, 0), | ||
104 | [SCLKDIV_USIBU3] = SCLKDIV(USIB3SCLKDIV, 0), | ||
105 | }; | ||
106 | |||
107 | enum { GCLK_USIAU0_SCLK, GCLK_USIBU1_SCLK, GCLK_USIBU2_SCLK, GCLK_USIBU3_SCLK, | ||
108 | GCLK_STI_SCLK, | ||
109 | GCLK_NR }; | ||
110 | |||
111 | #define GCLK_SCLK(_parent, _reg) \ | ||
112 | { \ | ||
113 | .parent = _parent, \ | ||
114 | .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \ | ||
115 | .enable_bit = 1, /* SCLK_GCC */ \ | ||
116 | } | ||
117 | |||
118 | static struct clk gclk_clks[GCLK_NR] = { | ||
119 | [GCLK_USIAU0_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIAU0], | ||
120 | USIAU0GCLKCTRL), | ||
121 | [GCLK_USIBU1_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU1], | ||
122 | USIBU1GCLKCTRL), | ||
123 | [GCLK_USIBU2_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU2], | ||
124 | USIBU2GCLKCTRL), | ||
125 | [GCLK_USIBU3_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU3], | ||
126 | USIBU3GCLKCTRL), | ||
127 | [GCLK_STI_SCLK] = GCLK_SCLK(&c32k_clk, STIGCLKCTRL), | ||
128 | }; | ||
129 | |||
130 | static int emev2_gclk_enable(struct clk *clk) | ||
131 | { | ||
132 | iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit), | ||
133 | clk->mapped_reg); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static void emev2_gclk_disable(struct clk *clk) | ||
138 | { | ||
139 | iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit), | ||
140 | clk->mapped_reg); | ||
141 | } | ||
142 | |||
143 | static struct sh_clk_ops emev2_gclk_clk_ops = { | ||
144 | .enable = emev2_gclk_enable, | ||
145 | .disable = emev2_gclk_disable, | ||
146 | .recalc = followparent_recalc, | ||
147 | }; | ||
148 | |||
149 | static int __init emev2_gclk_register(struct clk *clks, int nr) | ||
150 | { | ||
151 | struct clk *clkp; | ||
152 | int ret = 0; | ||
153 | int k; | ||
154 | |||
155 | for (k = 0; !ret && (k < nr); k++) { | ||
156 | clkp = clks + k; | ||
157 | clkp->ops = &emev2_gclk_clk_ops; | ||
158 | ret |= clk_register(clkp); | ||
159 | } | ||
160 | |||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | static unsigned long emev2_sclkdiv_recalc(struct clk *clk) | ||
165 | { | ||
166 | unsigned int sclk_div; | ||
167 | |||
168 | sclk_div = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0xff; | ||
169 | |||
170 | return clk->parent->rate / (sclk_div + 1); | ||
171 | } | ||
172 | |||
173 | static struct sh_clk_ops emev2_sclkdiv_clk_ops = { | ||
174 | .recalc = emev2_sclkdiv_recalc, | ||
175 | }; | ||
176 | |||
177 | static int __init emev2_sclkdiv_register(struct clk *clks, int nr) | ||
178 | { | ||
179 | struct clk *clkp; | ||
180 | int ret = 0; | ||
181 | int k; | ||
182 | |||
183 | for (k = 0; !ret && (k < nr); k++) { | ||
184 | clkp = clks + k; | ||
185 | clkp->ops = &emev2_sclkdiv_clk_ops; | ||
186 | ret |= clk_register(clkp); | ||
187 | } | ||
188 | |||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static struct clk_lookup lookups[] = { | ||
193 | CLKDEV_DEV_ID("serial8250-em.0", &gclk_clks[GCLK_USIAU0_SCLK]), | ||
194 | CLKDEV_DEV_ID("e1020000.uart", &gclk_clks[GCLK_USIAU0_SCLK]), | ||
195 | CLKDEV_DEV_ID("serial8250-em.1", &gclk_clks[GCLK_USIBU1_SCLK]), | ||
196 | CLKDEV_DEV_ID("e1030000.uart", &gclk_clks[GCLK_USIBU1_SCLK]), | ||
197 | CLKDEV_DEV_ID("serial8250-em.2", &gclk_clks[GCLK_USIBU2_SCLK]), | ||
198 | CLKDEV_DEV_ID("e1040000.uart", &gclk_clks[GCLK_USIBU2_SCLK]), | ||
199 | CLKDEV_DEV_ID("serial8250-em.3", &gclk_clks[GCLK_USIBU3_SCLK]), | ||
200 | CLKDEV_DEV_ID("e1050000.uart", &gclk_clks[GCLK_USIBU3_SCLK]), | ||
201 | CLKDEV_DEV_ID("em_sti.0", &gclk_clks[GCLK_STI_SCLK]), | ||
202 | CLKDEV_DEV_ID("e0180000.sti", &gclk_clks[GCLK_STI_SCLK]), | ||
203 | }; | ||
204 | |||
205 | void __init emev2_clock_init(void) | ||
206 | { | ||
207 | int k, ret = 0; | ||
208 | static int is_setup; | ||
209 | |||
210 | /* yuck, this is ugly as hell, but the non-smp case of clocks | ||
211 | * code is now designed to rely on ioremap() instead of static | ||
212 | * entity maps. in the case of smp we need access to the SMU | ||
213 | * register earlier than ioremap() is actually working without | ||
214 | * any static maps. to enable SMP in ugly but with dynamic | ||
215 | * mappings we have to call emev2_clock_init() from different | ||
216 | * places depending on UP and SMP... | ||
217 | */ | ||
218 | if (is_setup++) | ||
219 | return; | ||
220 | |||
221 | smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE); | ||
222 | BUG_ON(!smu_base); | ||
223 | |||
224 | /* setup STI timer to run on 37.768 kHz and deassert reset */ | ||
225 | emev2_smu_write(0, STI_CLKSEL); | ||
226 | emev2_smu_write(1, STI_RSTCTRL); | ||
227 | |||
228 | /* deassert reset for UART0->UART3 */ | ||
229 | emev2_smu_write(2, USIAU0_RSTCTRL); | ||
230 | emev2_smu_write(2, USIBU1_RSTCTRL); | ||
231 | emev2_smu_write(2, USIBU2_RSTCTRL); | ||
232 | emev2_smu_write(2, USIBU3_RSTCTRL); | ||
233 | |||
234 | for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) | ||
235 | ret = clk_register(main_clks[k]); | ||
236 | |||
237 | if (!ret) | ||
238 | ret = emev2_sclkdiv_register(sclkdiv_clks, SCLKDIV_NR); | ||
239 | |||
240 | if (!ret) | ||
241 | ret = emev2_gclk_register(gclk_clks, GCLK_NR); | ||
242 | |||
243 | clkdev_add_table(lookups, ARRAY_SIZE(lookups)); | ||
244 | |||
245 | if (!ret) | ||
246 | shmobile_clk_init(); | ||
247 | else | ||
248 | panic("failed to setup emev2 clocks\n"); | ||
249 | } | ||
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index 99c4d743a99c..81b54a6af20f 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #define PLLC01CR 0xe6150028 | 47 | #define PLLC01CR 0xe6150028 |
48 | 48 | ||
49 | #define SUBCKCR 0xe6150080 | 49 | #define SUBCKCR 0xe6150080 |
50 | #define USBCKCR 0xe615008c | ||
50 | 51 | ||
51 | #define MSTPSR0 0xe6150030 | 52 | #define MSTPSR0 0xe6150030 |
52 | #define MSTPSR1 0xe6150038 | 53 | #define MSTPSR1 0xe6150038 |
@@ -181,6 +182,95 @@ static struct clk pllc1_div2_clk = { | |||
181 | .parent = &pllc1_clk, | 182 | .parent = &pllc1_clk, |
182 | }; | 183 | }; |
183 | 184 | ||
185 | /* USB clock */ | ||
186 | static struct clk *usb24s_parents[] = { | ||
187 | [0] = &system_clk, | ||
188 | [1] = &extal2_clk | ||
189 | }; | ||
190 | |||
191 | static int usb24s_enable(struct clk *clk) | ||
192 | { | ||
193 | __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static void usb24s_disable(struct clk *clk) | ||
199 | { | ||
200 | __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR); | ||
201 | } | ||
202 | |||
203 | static int usb24s_set_parent(struct clk *clk, struct clk *parent) | ||
204 | { | ||
205 | int i, ret; | ||
206 | u32 val; | ||
207 | |||
208 | if (!clk->parent_table || !clk->parent_num) | ||
209 | return -EINVAL; | ||
210 | |||
211 | /* Search the parent */ | ||
212 | for (i = 0; i < clk->parent_num; i++) | ||
213 | if (clk->parent_table[i] == parent) | ||
214 | break; | ||
215 | |||
216 | if (i == clk->parent_num) | ||
217 | return -ENODEV; | ||
218 | |||
219 | ret = clk_reparent(clk, parent); | ||
220 | if (ret < 0) | ||
221 | return ret; | ||
222 | |||
223 | val = __raw_readl(USBCKCR); | ||
224 | val &= ~(1 << 7); | ||
225 | val |= i << 7; | ||
226 | __raw_writel(val, USBCKCR); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static struct sh_clk_ops usb24s_clk_ops = { | ||
232 | .recalc = followparent_recalc, | ||
233 | .enable = usb24s_enable, | ||
234 | .disable = usb24s_disable, | ||
235 | .set_parent = usb24s_set_parent, | ||
236 | }; | ||
237 | |||
238 | static struct clk usb24s_clk = { | ||
239 | .ops = &usb24s_clk_ops, | ||
240 | .parent_table = usb24s_parents, | ||
241 | .parent_num = ARRAY_SIZE(usb24s_parents), | ||
242 | .parent = &system_clk, | ||
243 | }; | ||
244 | |||
245 | static unsigned long usb24_recalc(struct clk *clk) | ||
246 | { | ||
247 | return clk->parent->rate / | ||
248 | ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2); | ||
249 | }; | ||
250 | |||
251 | static int usb24_set_rate(struct clk *clk, unsigned long rate) | ||
252 | { | ||
253 | u32 val; | ||
254 | |||
255 | /* closer to which ? parent->rate or parent->rate/2 */ | ||
256 | val = __raw_readl(USBCKCR); | ||
257 | val &= ~(1 << 6); | ||
258 | val |= (rate > (clk->parent->rate / 4) * 3) << 6; | ||
259 | __raw_writel(val, USBCKCR); | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static struct sh_clk_ops usb24_clk_ops = { | ||
265 | .recalc = usb24_recalc, | ||
266 | .set_rate = usb24_set_rate, | ||
267 | }; | ||
268 | |||
269 | static struct clk usb24_clk = { | ||
270 | .ops = &usb24_clk_ops, | ||
271 | .parent = &usb24s_clk, | ||
272 | }; | ||
273 | |||
184 | struct clk *main_clks[] = { | 274 | struct clk *main_clks[] = { |
185 | &extalr_clk, | 275 | &extalr_clk, |
186 | &extal1_clk, | 276 | &extal1_clk, |
@@ -196,6 +286,8 @@ struct clk *main_clks[] = { | |||
196 | &pllc0_clk, | 286 | &pllc0_clk, |
197 | &pllc1_clk, | 287 | &pllc1_clk, |
198 | &pllc1_div2_clk, | 288 | &pllc1_div2_clk, |
289 | &usb24s_clk, | ||
290 | &usb24_clk, | ||
199 | }; | 291 | }; |
200 | 292 | ||
201 | static void div4_kick(struct clk *clk) | 293 | static void div4_kick(struct clk *clk) |
@@ -223,7 +315,7 @@ static struct clk_div4_table div4_table = { | |||
223 | 315 | ||
224 | enum { | 316 | enum { |
225 | DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, | 317 | DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, |
226 | DIV4_HPP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, | 318 | DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, |
227 | DIV4_NR | 319 | DIV4_NR |
228 | }; | 320 | }; |
229 | 321 | ||
@@ -234,6 +326,7 @@ struct clk div4_clks[DIV4_NR] = { | |||
234 | [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), | 326 | [DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT), |
235 | [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0), | 327 | [DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0), |
236 | [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0), | 328 | [DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0), |
329 | [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0), | ||
237 | [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0), | 330 | [DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0), |
238 | [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0), | 331 | [DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0), |
239 | [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0), | 332 | [DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0), |
@@ -257,7 +350,10 @@ enum { | |||
257 | MSTP222, | 350 | MSTP222, |
258 | MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, | 351 | MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, |
259 | 352 | ||
260 | MSTP329, MSTP323, | 353 | MSTP329, MSTP328, MSTP323, MSTP320, |
354 | MSTP314, MSTP313, MSTP312, | ||
355 | |||
356 | MSTP416, MSTP415, MSTP407, MSTP406, | ||
261 | 357 | ||
262 | MSTP_NR | 358 | MSTP_NR |
263 | }; | 359 | }; |
@@ -280,7 +376,17 @@ static struct clk mstp_clks[MSTP_NR] = { | |||
280 | [MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ | 376 | [MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ |
281 | 377 | ||
282 | [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ | 378 | [MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ |
379 | [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */ | ||
283 | [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ | 380 | [MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ |
381 | [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */ | ||
382 | [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ | ||
383 | [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */ | ||
384 | [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */ | ||
385 | |||
386 | [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */ | ||
387 | [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */ | ||
388 | [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */ | ||
389 | [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */ | ||
284 | }; | 390 | }; |
285 | 391 | ||
286 | static struct clk_lookup lookups[] = { | 392 | static struct clk_lookup lookups[] = { |
@@ -299,6 +405,7 @@ static struct clk_lookup lookups[] = { | |||
299 | CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), | 405 | CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), |
300 | CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), | 406 | CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), |
301 | CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), | 407 | CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), |
408 | CLKDEV_CON_ID("usb24s", &usb24s_clk), | ||
302 | 409 | ||
303 | /* DIV4 clocks */ | 410 | /* DIV4 clocks */ |
304 | CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), | 411 | CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), |
@@ -334,7 +441,21 @@ static struct clk_lookup lookups[] = { | |||
334 | CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]), | 441 | CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]), |
335 | 442 | ||
336 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), | 443 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), |
444 | CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), | ||
337 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), | 445 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), |
446 | CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]), | ||
447 | CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), | ||
448 | CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), | ||
449 | CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]), | ||
450 | |||
451 | CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), | ||
452 | |||
453 | /* ICK */ | ||
454 | CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]), | ||
455 | CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]), | ||
456 | CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), | ||
457 | CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), | ||
458 | CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), | ||
338 | }; | 459 | }; |
339 | 460 | ||
340 | void __init r8a7740_clock_init(u8 md_ck) | 461 | void __init r8a7740_clock_init(u8 md_ck) |
diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h new file mode 100644 index 000000000000..e6b0c1bf4b7e --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/emev2.h | |||
@@ -0,0 +1,19 @@ | |||
1 | #ifndef __ASM_EMEV2_H__ | ||
2 | #define __ASM_EMEV2_H__ | ||
3 | |||
4 | extern void emev2_map_io(void); | ||
5 | extern void emev2_init_irq(void); | ||
6 | extern void emev2_add_early_devices(void); | ||
7 | extern void emev2_add_standard_devices(void); | ||
8 | extern void emev2_clock_init(void); | ||
9 | extern void emev2_set_boot_vector(unsigned long value); | ||
10 | extern unsigned int emev2_get_core_count(void); | ||
11 | extern int emev2_platform_cpu_kill(unsigned int cpu); | ||
12 | extern void emev2_secondary_init(unsigned int cpu); | ||
13 | extern int emev2_boot_secondary(unsigned int cpu); | ||
14 | extern void emev2_smp_prepare_cpus(void); | ||
15 | |||
16 | #define EMEV2_GPIO_BASE 200 | ||
17 | #define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n)) | ||
18 | |||
19 | #endif /* __ASM_EMEV2_H__ */ | ||
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index 8254ab86f6cd..915d0093da08 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h | |||
@@ -457,6 +457,8 @@ enum { | |||
457 | SHDMA_SLAVE_SDHI1_TX, | 457 | SHDMA_SLAVE_SDHI1_TX, |
458 | SHDMA_SLAVE_SDHI2_RX, | 458 | SHDMA_SLAVE_SDHI2_RX, |
459 | SHDMA_SLAVE_SDHI2_TX, | 459 | SHDMA_SLAVE_SDHI2_TX, |
460 | SHDMA_SLAVE_FSIA_RX, | ||
461 | SHDMA_SLAVE_FSIA_TX, | ||
460 | SHDMA_SLAVE_MMCIF_RX, | 462 | SHDMA_SLAVE_MMCIF_RX, |
461 | SHDMA_SLAVE_MMCIF_TX, | 463 | SHDMA_SLAVE_MMCIF_TX, |
462 | SHDMA_SLAVE_USB0_TX, | 464 | SHDMA_SLAVE_USB0_TX, |
diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h index cad57578ceed..9b3598e4f105 100644 --- a/arch/arm/mach-shmobile/include/mach/sh73a0.h +++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h | |||
@@ -515,8 +515,36 @@ enum { | |||
515 | SHDMA_SLAVE_MMCIF_RX, | 515 | SHDMA_SLAVE_MMCIF_RX, |
516 | }; | 516 | }; |
517 | 517 | ||
518 | /* PINT interrupts are located at Linux IRQ 800 and up */ | 518 | /* |
519 | #define SH73A0_PINT0_IRQ(irq) ((irq) + 800) | 519 | * SH73A0 IRQ LOCATION TABLE |
520 | #define SH73A0_PINT1_IRQ(irq) ((irq) + 832) | 520 | * |
521 | * 416 ----------------------------------------- | ||
522 | * IRQ0-IRQ15 | ||
523 | * 431 ----------------------------------------- | ||
524 | * ... | ||
525 | * 448 ----------------------------------------- | ||
526 | * sh73a0-intcs | ||
527 | * sh73a0-intca-irq-pins | ||
528 | * 680 ----------------------------------------- | ||
529 | * ... | ||
530 | * 700 ----------------------------------------- | ||
531 | * sh73a0-pint0 | ||
532 | * 731 ----------------------------------------- | ||
533 | * 732 ----------------------------------------- | ||
534 | * sh73a0-pint1 | ||
535 | * 739 ----------------------------------------- | ||
536 | * ... | ||
537 | * 800 ----------------------------------------- | ||
538 | * IRQ16-IRQ31 | ||
539 | * 815 ----------------------------------------- | ||
540 | * ... | ||
541 | * 928 ----------------------------------------- | ||
542 | * sh73a0-intca-irq-pins | ||
543 | * 943 ----------------------------------------- | ||
544 | */ | ||
545 | |||
546 | /* PINT interrupts are located at Linux IRQ 700 and up */ | ||
547 | #define SH73A0_PINT0_IRQ(irq) ((irq) + 700) | ||
548 | #define SH73A0_PINT1_IRQ(irq) ((irq) + 732) | ||
521 | 549 | ||
522 | #endif /* __ASM_SH73A0_H__ */ | 550 | #endif /* __ASM_SH73A0_H__ */ |
diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c index a4fff6950b03..670fe1869dbc 100644 --- a/arch/arm/mach-shmobile/pfc-r8a7740.c +++ b/arch/arm/mach-shmobile/pfc-r8a7740.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
24 | #include <mach/r8a7740.h> | 24 | #include <mach/r8a7740.h> |
25 | #include <mach/irqs.h> | ||
25 | 26 | ||
26 | #define CPU_ALL_PORT(fn, pfx, sfx) \ | 27 | #define CPU_ALL_PORT(fn, pfx, sfx) \ |
27 | PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx), \ | 28 | PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx), \ |
@@ -2527,6 +2528,41 @@ static struct pinmux_data_reg pinmux_data_regs[] = { | |||
2527 | { }, | 2528 | { }, |
2528 | }; | 2529 | }; |
2529 | 2530 | ||
2531 | static struct pinmux_irq pinmux_irqs[] = { | ||
2532 | PINMUX_IRQ(evt2irq(0x0200), PORT2_FN0, PORT13_FN0), /* IRQ0A */ | ||
2533 | PINMUX_IRQ(evt2irq(0x0220), PORT20_FN0), /* IRQ1A */ | ||
2534 | PINMUX_IRQ(evt2irq(0x0240), PORT11_FN0, PORT12_FN0), /* IRQ2A */ | ||
2535 | PINMUX_IRQ(evt2irq(0x0260), PORT10_FN0, PORT14_FN0), /* IRQ3A */ | ||
2536 | PINMUX_IRQ(evt2irq(0x0280), PORT15_FN0, PORT172_FN0), /* IRQ4A */ | ||
2537 | PINMUX_IRQ(evt2irq(0x02A0), PORT0_FN0, PORT1_FN0), /* IRQ5A */ | ||
2538 | PINMUX_IRQ(evt2irq(0x02C0), PORT121_FN0, PORT173_FN0), /* IRQ6A */ | ||
2539 | PINMUX_IRQ(evt2irq(0x02E0), PORT120_FN0, PORT209_FN0), /* IRQ7A */ | ||
2540 | PINMUX_IRQ(evt2irq(0x0300), PORT119_FN0), /* IRQ8A */ | ||
2541 | PINMUX_IRQ(evt2irq(0x0320), PORT118_FN0, PORT210_FN0), /* IRQ9A */ | ||
2542 | PINMUX_IRQ(evt2irq(0x0340), PORT19_FN0), /* IRQ10A */ | ||
2543 | PINMUX_IRQ(evt2irq(0x0360), PORT104_FN0), /* IRQ11A */ | ||
2544 | PINMUX_IRQ(evt2irq(0x0380), PORT42_FN0, PORT97_FN0), /* IRQ12A */ | ||
2545 | PINMUX_IRQ(evt2irq(0x03A0), PORT64_FN0, PORT98_FN0), /* IRQ13A */ | ||
2546 | PINMUX_IRQ(evt2irq(0x03C0), PORT63_FN0, PORT99_FN0), /* IRQ14A */ | ||
2547 | PINMUX_IRQ(evt2irq(0x03E0), PORT62_FN0, PORT100_FN0), /* IRQ15A */ | ||
2548 | PINMUX_IRQ(evt2irq(0x3200), PORT68_FN0, PORT211_FN0), /* IRQ16A */ | ||
2549 | PINMUX_IRQ(evt2irq(0x3220), PORT69_FN0), /* IRQ17A */ | ||
2550 | PINMUX_IRQ(evt2irq(0x3240), PORT70_FN0), /* IRQ18A */ | ||
2551 | PINMUX_IRQ(evt2irq(0x3260), PORT71_FN0), /* IRQ19A */ | ||
2552 | PINMUX_IRQ(evt2irq(0x3280), PORT67_FN0), /* IRQ20A */ | ||
2553 | PINMUX_IRQ(evt2irq(0x32A0), PORT202_FN0), /* IRQ21A */ | ||
2554 | PINMUX_IRQ(evt2irq(0x32C0), PORT95_FN0), /* IRQ22A */ | ||
2555 | PINMUX_IRQ(evt2irq(0x32E0), PORT96_FN0), /* IRQ23A */ | ||
2556 | PINMUX_IRQ(evt2irq(0x3300), PORT180_FN0), /* IRQ24A */ | ||
2557 | PINMUX_IRQ(evt2irq(0x3320), PORT38_FN0), /* IRQ25A */ | ||
2558 | PINMUX_IRQ(evt2irq(0x3340), PORT58_FN0, PORT81_FN0), /* IRQ26A */ | ||
2559 | PINMUX_IRQ(evt2irq(0x3360), PORT57_FN0, PORT168_FN0), /* IRQ27A */ | ||
2560 | PINMUX_IRQ(evt2irq(0x3380), PORT56_FN0, PORT169_FN0), /* IRQ28A */ | ||
2561 | PINMUX_IRQ(evt2irq(0x33A0), PORT50_FN0, PORT170_FN0), /* IRQ29A */ | ||
2562 | PINMUX_IRQ(evt2irq(0x33C0), PORT49_FN0, PORT171_FN0), /* IRQ30A */ | ||
2563 | PINMUX_IRQ(evt2irq(0x33E0), PORT41_FN0, PORT167_FN0), /* IRQ31A */ | ||
2564 | }; | ||
2565 | |||
2530 | static struct pinmux_info r8a7740_pinmux_info = { | 2566 | static struct pinmux_info r8a7740_pinmux_info = { |
2531 | .name = "r8a7740_pfc", | 2567 | .name = "r8a7740_pfc", |
2532 | .reserved_id = PINMUX_RESERVED, | 2568 | .reserved_id = PINMUX_RESERVED, |
@@ -2554,6 +2590,9 @@ static struct pinmux_info r8a7740_pinmux_info = { | |||
2554 | 2590 | ||
2555 | .gpio_data = pinmux_data, | 2591 | .gpio_data = pinmux_data, |
2556 | .gpio_data_size = ARRAY_SIZE(pinmux_data), | 2592 | .gpio_data_size = ARRAY_SIZE(pinmux_data), |
2593 | |||
2594 | .gpio_irq = pinmux_irqs, | ||
2595 | .gpio_irq_size = ARRAY_SIZE(pinmux_irqs), | ||
2557 | }; | 2596 | }; |
2558 | 2597 | ||
2559 | void r8a7740_pinmux_init(void) | 2598 | void r8a7740_pinmux_init(void) |
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index 45fa3924c6a1..7006cdc8b8ca 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c | |||
@@ -16,12 +16,15 @@ | |||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/of.h> | ||
19 | #include <asm/hardware/gic.h> | 20 | #include <asm/hardware/gic.h> |
20 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
21 | #include <mach/common.h> | 22 | #include <mach/common.h> |
23 | #include <mach/emev2.h> | ||
22 | 24 | ||
23 | #define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2()) | 25 | #define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2()) |
24 | #define is_r8a7779() machine_is_marzen() | 26 | #define is_r8a7779() machine_is_marzen() |
27 | #define is_emev2() of_machine_is_compatible("renesas,emev2") | ||
25 | 28 | ||
26 | static unsigned int __init shmobile_smp_get_core_count(void) | 29 | static unsigned int __init shmobile_smp_get_core_count(void) |
27 | { | 30 | { |
@@ -31,6 +34,9 @@ static unsigned int __init shmobile_smp_get_core_count(void) | |||
31 | if (is_r8a7779()) | 34 | if (is_r8a7779()) |
32 | return r8a7779_get_core_count(); | 35 | return r8a7779_get_core_count(); |
33 | 36 | ||
37 | if (is_emev2()) | ||
38 | return emev2_get_core_count(); | ||
39 | |||
34 | return 1; | 40 | return 1; |
35 | } | 41 | } |
36 | 42 | ||
@@ -41,6 +47,9 @@ static void __init shmobile_smp_prepare_cpus(void) | |||
41 | 47 | ||
42 | if (is_r8a7779()) | 48 | if (is_r8a7779()) |
43 | r8a7779_smp_prepare_cpus(); | 49 | r8a7779_smp_prepare_cpus(); |
50 | |||
51 | if (is_emev2()) | ||
52 | emev2_smp_prepare_cpus(); | ||
44 | } | 53 | } |
45 | 54 | ||
46 | int shmobile_platform_cpu_kill(unsigned int cpu) | 55 | int shmobile_platform_cpu_kill(unsigned int cpu) |
@@ -48,6 +57,9 @@ int shmobile_platform_cpu_kill(unsigned int cpu) | |||
48 | if (is_r8a7779()) | 57 | if (is_r8a7779()) |
49 | return r8a7779_platform_cpu_kill(cpu); | 58 | return r8a7779_platform_cpu_kill(cpu); |
50 | 59 | ||
60 | if (is_emev2()) | ||
61 | return emev2_platform_cpu_kill(cpu); | ||
62 | |||
51 | return 1; | 63 | return 1; |
52 | } | 64 | } |
53 | 65 | ||
@@ -60,6 +72,9 @@ void __cpuinit platform_secondary_init(unsigned int cpu) | |||
60 | 72 | ||
61 | if (is_r8a7779()) | 73 | if (is_r8a7779()) |
62 | r8a7779_secondary_init(cpu); | 74 | r8a7779_secondary_init(cpu); |
75 | |||
76 | if (is_emev2()) | ||
77 | emev2_secondary_init(cpu); | ||
63 | } | 78 | } |
64 | 79 | ||
65 | int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | 80 | int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) |
@@ -70,6 +85,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
70 | if (is_r8a7779()) | 85 | if (is_r8a7779()) |
71 | return r8a7779_boot_secondary(cpu); | 86 | return r8a7779_boot_secondary(cpu); |
72 | 87 | ||
88 | if (is_emev2()) | ||
89 | return emev2_boot_secondary(cpu); | ||
90 | |||
73 | return -ENOSYS; | 91 | return -ENOSYS; |
74 | } | 92 | } |
75 | 93 | ||
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c new file mode 100644 index 000000000000..dae9aa68bb09 --- /dev/null +++ b/arch/arm/mach-shmobile/setup-emev2.c | |||
@@ -0,0 +1,452 @@ | |||
1 | /* | ||
2 | * Emma Mobile EV2 processor support | ||
3 | * | ||
4 | * Copyright (C) 2012 Magnus Damm | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/platform_data/gpio-em.h> | ||
25 | #include <linux/of_platform.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/input.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/of_irq.h> | ||
30 | #include <mach/hardware.h> | ||
31 | #include <mach/common.h> | ||
32 | #include <mach/emev2.h> | ||
33 | #include <mach/irqs.h> | ||
34 | #include <asm/mach-types.h> | ||
35 | #include <asm/mach/arch.h> | ||
36 | #include <asm/mach/map.h> | ||
37 | #include <asm/mach/time.h> | ||
38 | #include <asm/hardware/gic.h> | ||
39 | |||
40 | static struct map_desc emev2_io_desc[] __initdata = { | ||
41 | #ifdef CONFIG_SMP | ||
42 | /* 128K entity map for 0xe0100000 (SMU) */ | ||
43 | { | ||
44 | .virtual = 0xe0100000, | ||
45 | .pfn = __phys_to_pfn(0xe0100000), | ||
46 | .length = SZ_128K, | ||
47 | .type = MT_DEVICE | ||
48 | }, | ||
49 | /* 2M mapping for SCU + L2 controller */ | ||
50 | { | ||
51 | .virtual = 0xf0000000, | ||
52 | .pfn = __phys_to_pfn(0x1e000000), | ||
53 | .length = SZ_2M, | ||
54 | .type = MT_DEVICE | ||
55 | }, | ||
56 | #endif | ||
57 | }; | ||
58 | |||
59 | void __init emev2_map_io(void) | ||
60 | { | ||
61 | iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc)); | ||
62 | } | ||
63 | |||
64 | /* UART */ | ||
65 | static struct resource uart0_resources[] = { | ||
66 | [0] = { | ||
67 | .start = 0xe1020000, | ||
68 | .end = 0xe1020037, | ||
69 | .flags = IORESOURCE_MEM, | ||
70 | }, | ||
71 | [1] = { | ||
72 | .start = 40, | ||
73 | .flags = IORESOURCE_IRQ, | ||
74 | } | ||
75 | }; | ||
76 | |||
77 | static struct platform_device uart0_device = { | ||
78 | .name = "serial8250-em", | ||
79 | .id = 0, | ||
80 | .num_resources = ARRAY_SIZE(uart0_resources), | ||
81 | .resource = uart0_resources, | ||
82 | }; | ||
83 | |||
84 | static struct resource uart1_resources[] = { | ||
85 | [0] = { | ||
86 | .start = 0xe1030000, | ||
87 | .end = 0xe1030037, | ||
88 | .flags = IORESOURCE_MEM, | ||
89 | }, | ||
90 | [1] = { | ||
91 | .start = 41, | ||
92 | .flags = IORESOURCE_IRQ, | ||
93 | } | ||
94 | }; | ||
95 | |||
96 | static struct platform_device uart1_device = { | ||
97 | .name = "serial8250-em", | ||
98 | .id = 1, | ||
99 | .num_resources = ARRAY_SIZE(uart1_resources), | ||
100 | .resource = uart1_resources, | ||
101 | }; | ||
102 | |||
103 | static struct resource uart2_resources[] = { | ||
104 | [0] = { | ||
105 | .start = 0xe1040000, | ||
106 | .end = 0xe1040037, | ||
107 | .flags = IORESOURCE_MEM, | ||
108 | }, | ||
109 | [1] = { | ||
110 | .start = 42, | ||
111 | .flags = IORESOURCE_IRQ, | ||
112 | } | ||
113 | }; | ||
114 | |||
115 | static struct platform_device uart2_device = { | ||
116 | .name = "serial8250-em", | ||
117 | .id = 2, | ||
118 | .num_resources = ARRAY_SIZE(uart2_resources), | ||
119 | .resource = uart2_resources, | ||
120 | }; | ||
121 | |||
122 | static struct resource uart3_resources[] = { | ||
123 | [0] = { | ||
124 | .start = 0xe1050000, | ||
125 | .end = 0xe1050037, | ||
126 | .flags = IORESOURCE_MEM, | ||
127 | }, | ||
128 | [1] = { | ||
129 | .start = 43, | ||
130 | .flags = IORESOURCE_IRQ, | ||
131 | } | ||
132 | }; | ||
133 | |||
134 | static struct platform_device uart3_device = { | ||
135 | .name = "serial8250-em", | ||
136 | .id = 3, | ||
137 | .num_resources = ARRAY_SIZE(uart3_resources), | ||
138 | .resource = uart3_resources, | ||
139 | }; | ||
140 | |||
141 | /* STI */ | ||
142 | static struct resource sti_resources[] = { | ||
143 | [0] = { | ||
144 | .name = "STI", | ||
145 | .start = 0xe0180000, | ||
146 | .end = 0xe0180053, | ||
147 | .flags = IORESOURCE_MEM, | ||
148 | }, | ||
149 | [1] = { | ||
150 | .start = 157, | ||
151 | .flags = IORESOURCE_IRQ, | ||
152 | }, | ||
153 | }; | ||
154 | |||
155 | static struct platform_device sti_device = { | ||
156 | .name = "em_sti", | ||
157 | .id = 0, | ||
158 | .resource = sti_resources, | ||
159 | .num_resources = ARRAY_SIZE(sti_resources), | ||
160 | }; | ||
161 | |||
162 | |||
163 | /* GIO */ | ||
164 | static struct gpio_em_config gio0_config = { | ||
165 | .gpio_base = 0, | ||
166 | .irq_base = EMEV2_GPIO_IRQ(0), | ||
167 | .number_of_pins = 32, | ||
168 | }; | ||
169 | |||
170 | static struct resource gio0_resources[] = { | ||
171 | [0] = { | ||
172 | .name = "GIO_000", | ||
173 | .start = 0xe0050000, | ||
174 | .end = 0xe005002b, | ||
175 | .flags = IORESOURCE_MEM, | ||
176 | }, | ||
177 | [1] = { | ||
178 | .name = "GIO_000", | ||
179 | .start = 0xe0050040, | ||
180 | .end = 0xe005005f, | ||
181 | .flags = IORESOURCE_MEM, | ||
182 | }, | ||
183 | [2] = { | ||
184 | .start = 99, | ||
185 | .flags = IORESOURCE_IRQ, | ||
186 | }, | ||
187 | [3] = { | ||
188 | .start = 100, | ||
189 | .flags = IORESOURCE_IRQ, | ||
190 | }, | ||
191 | }; | ||
192 | |||
193 | static struct platform_device gio0_device = { | ||
194 | .name = "em_gio", | ||
195 | .id = 0, | ||
196 | .resource = gio0_resources, | ||
197 | .num_resources = ARRAY_SIZE(gio0_resources), | ||
198 | .dev = { | ||
199 | .platform_data = &gio0_config, | ||
200 | }, | ||
201 | }; | ||
202 | |||
203 | static struct gpio_em_config gio1_config = { | ||
204 | .gpio_base = 32, | ||
205 | .irq_base = EMEV2_GPIO_IRQ(32), | ||
206 | .number_of_pins = 32, | ||
207 | }; | ||
208 | |||
209 | static struct resource gio1_resources[] = { | ||
210 | [0] = { | ||
211 | .name = "GIO_032", | ||
212 | .start = 0xe0050080, | ||
213 | .end = 0xe00500ab, | ||
214 | .flags = IORESOURCE_MEM, | ||
215 | }, | ||
216 | [1] = { | ||
217 | .name = "GIO_032", | ||
218 | .start = 0xe00500c0, | ||
219 | .end = 0xe00500df, | ||
220 | .flags = IORESOURCE_MEM, | ||
221 | }, | ||
222 | [2] = { | ||
223 | .start = 101, | ||
224 | .flags = IORESOURCE_IRQ, | ||
225 | }, | ||
226 | [3] = { | ||
227 | .start = 102, | ||
228 | .flags = IORESOURCE_IRQ, | ||
229 | }, | ||
230 | }; | ||
231 | |||
232 | static struct platform_device gio1_device = { | ||
233 | .name = "em_gio", | ||
234 | .id = 1, | ||
235 | .resource = gio1_resources, | ||
236 | .num_resources = ARRAY_SIZE(gio1_resources), | ||
237 | .dev = { | ||
238 | .platform_data = &gio1_config, | ||
239 | }, | ||
240 | }; | ||
241 | |||
242 | static struct gpio_em_config gio2_config = { | ||
243 | .gpio_base = 64, | ||
244 | .irq_base = EMEV2_GPIO_IRQ(64), | ||
245 | .number_of_pins = 32, | ||
246 | }; | ||
247 | |||
248 | static struct resource gio2_resources[] = { | ||
249 | [0] = { | ||
250 | .name = "GIO_064", | ||
251 | .start = 0xe0050100, | ||
252 | .end = 0xe005012b, | ||
253 | .flags = IORESOURCE_MEM, | ||
254 | }, | ||
255 | [1] = { | ||
256 | .name = "GIO_064", | ||
257 | .start = 0xe0050140, | ||
258 | .end = 0xe005015f, | ||
259 | .flags = IORESOURCE_MEM, | ||
260 | }, | ||
261 | [2] = { | ||
262 | .start = 103, | ||
263 | .flags = IORESOURCE_IRQ, | ||
264 | }, | ||
265 | [3] = { | ||
266 | .start = 104, | ||
267 | .flags = IORESOURCE_IRQ, | ||
268 | }, | ||
269 | }; | ||
270 | |||
271 | static struct platform_device gio2_device = { | ||
272 | .name = "em_gio", | ||
273 | .id = 2, | ||
274 | .resource = gio2_resources, | ||
275 | .num_resources = ARRAY_SIZE(gio2_resources), | ||
276 | .dev = { | ||
277 | .platform_data = &gio2_config, | ||
278 | }, | ||
279 | }; | ||
280 | |||
281 | static struct gpio_em_config gio3_config = { | ||
282 | .gpio_base = 96, | ||
283 | .irq_base = EMEV2_GPIO_IRQ(96), | ||
284 | .number_of_pins = 32, | ||
285 | }; | ||
286 | |||
287 | static struct resource gio3_resources[] = { | ||
288 | [0] = { | ||
289 | .name = "GIO_096", | ||
290 | .start = 0xe0050100, | ||
291 | .end = 0xe005012b, | ||
292 | .flags = IORESOURCE_MEM, | ||
293 | }, | ||
294 | [1] = { | ||
295 | .name = "GIO_096", | ||
296 | .start = 0xe0050140, | ||
297 | .end = 0xe005015f, | ||
298 | .flags = IORESOURCE_MEM, | ||
299 | }, | ||
300 | [2] = { | ||
301 | .start = 105, | ||
302 | .flags = IORESOURCE_IRQ, | ||
303 | }, | ||
304 | [3] = { | ||
305 | .start = 106, | ||
306 | .flags = IORESOURCE_IRQ, | ||
307 | }, | ||
308 | }; | ||
309 | |||
310 | static struct platform_device gio3_device = { | ||
311 | .name = "em_gio", | ||
312 | .id = 3, | ||
313 | .resource = gio3_resources, | ||
314 | .num_resources = ARRAY_SIZE(gio3_resources), | ||
315 | .dev = { | ||
316 | .platform_data = &gio3_config, | ||
317 | }, | ||
318 | }; | ||
319 | |||
320 | static struct gpio_em_config gio4_config = { | ||
321 | .gpio_base = 128, | ||
322 | .irq_base = EMEV2_GPIO_IRQ(128), | ||
323 | .number_of_pins = 31, | ||
324 | }; | ||
325 | |||
326 | static struct resource gio4_resources[] = { | ||
327 | [0] = { | ||
328 | .name = "GIO_128", | ||
329 | .start = 0xe0050200, | ||
330 | .end = 0xe005022b, | ||
331 | .flags = IORESOURCE_MEM, | ||
332 | }, | ||
333 | [1] = { | ||
334 | .name = "GIO_128", | ||
335 | .start = 0xe0050240, | ||
336 | .end = 0xe005025f, | ||
337 | .flags = IORESOURCE_MEM, | ||
338 | }, | ||
339 | [2] = { | ||
340 | .start = 107, | ||
341 | .flags = IORESOURCE_IRQ, | ||
342 | }, | ||
343 | [3] = { | ||
344 | .start = 108, | ||
345 | .flags = IORESOURCE_IRQ, | ||
346 | }, | ||
347 | }; | ||
348 | |||
349 | static struct platform_device gio4_device = { | ||
350 | .name = "em_gio", | ||
351 | .id = 4, | ||
352 | .resource = gio4_resources, | ||
353 | .num_resources = ARRAY_SIZE(gio4_resources), | ||
354 | .dev = { | ||
355 | .platform_data = &gio4_config, | ||
356 | }, | ||
357 | }; | ||
358 | |||
359 | static struct platform_device *emev2_early_devices[] __initdata = { | ||
360 | &uart0_device, | ||
361 | &uart1_device, | ||
362 | &uart2_device, | ||
363 | &uart3_device, | ||
364 | }; | ||
365 | |||
366 | static struct platform_device *emev2_late_devices[] __initdata = { | ||
367 | &sti_device, | ||
368 | &gio0_device, | ||
369 | &gio1_device, | ||
370 | &gio2_device, | ||
371 | &gio3_device, | ||
372 | &gio4_device, | ||
373 | }; | ||
374 | |||
375 | void __init emev2_add_standard_devices(void) | ||
376 | { | ||
377 | emev2_clock_init(); | ||
378 | |||
379 | platform_add_devices(emev2_early_devices, | ||
380 | ARRAY_SIZE(emev2_early_devices)); | ||
381 | |||
382 | platform_add_devices(emev2_late_devices, | ||
383 | ARRAY_SIZE(emev2_late_devices)); | ||
384 | } | ||
385 | |||
386 | void __init emev2_init_delay(void) | ||
387 | { | ||
388 | shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */ | ||
389 | } | ||
390 | |||
391 | void __init emev2_add_early_devices(void) | ||
392 | { | ||
393 | emev2_init_delay(); | ||
394 | |||
395 | early_platform_add_devices(emev2_early_devices, | ||
396 | ARRAY_SIZE(emev2_early_devices)); | ||
397 | |||
398 | /* setup early console here as well */ | ||
399 | shmobile_setup_console(); | ||
400 | } | ||
401 | |||
402 | void __init emev2_init_irq(void) | ||
403 | { | ||
404 | void __iomem *gic_dist_base; | ||
405 | void __iomem *gic_cpu_base; | ||
406 | |||
407 | /* Static mappings, never released */ | ||
408 | gic_dist_base = ioremap(0xe0028000, PAGE_SIZE); | ||
409 | gic_cpu_base = ioremap(0xe0020000, PAGE_SIZE); | ||
410 | BUG_ON(!gic_dist_base || !gic_cpu_base); | ||
411 | |||
412 | /* Use GIC to handle interrupts */ | ||
413 | gic_init(0, 29, gic_dist_base, gic_cpu_base); | ||
414 | } | ||
415 | |||
416 | #ifdef CONFIG_USE_OF | ||
417 | static const struct of_dev_auxdata emev2_auxdata_lookup[] __initconst = { | ||
418 | { } | ||
419 | }; | ||
420 | |||
421 | void __init emev2_add_standard_devices_dt(void) | ||
422 | { | ||
423 | of_platform_populate(NULL, of_default_bus_match_table, | ||
424 | emev2_auxdata_lookup, NULL); | ||
425 | } | ||
426 | |||
427 | static const struct of_device_id emev2_dt_irq_match[] = { | ||
428 | { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, | ||
429 | {}, | ||
430 | }; | ||
431 | |||
432 | static const char *emev2_boards_compat_dt[] __initdata = { | ||
433 | "renesas,emev2", | ||
434 | NULL, | ||
435 | }; | ||
436 | |||
437 | void __init emev2_init_irq_dt(void) | ||
438 | { | ||
439 | of_irq_init(emev2_dt_irq_match); | ||
440 | } | ||
441 | |||
442 | DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)") | ||
443 | .init_early = emev2_init_delay, | ||
444 | .nr_irqs = NR_IRQS_LEGACY, | ||
445 | .init_irq = emev2_init_irq_dt, | ||
446 | .handle_irq = gic_handle_irq, | ||
447 | .init_machine = emev2_add_standard_devices_dt, | ||
448 | .timer = &shmobile_timer, | ||
449 | .dt_compat = emev2_boards_compat_dt, | ||
450 | MACHINE_END | ||
451 | |||
452 | #endif /* CONFIG_USE_OF */ | ||
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 14edb5cffa7f..34a1548dbda6 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c | |||
@@ -350,19 +350,19 @@ static void r8a7740_i2c_workaround(struct platform_device *pdev) | |||
350 | i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10); | 350 | i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10); |
351 | i2c_read(reg, ICSTART); /* dummy read */ | 351 | i2c_read(reg, ICSTART); /* dummy read */ |
352 | 352 | ||
353 | mdelay(100); | 353 | udelay(10); |
354 | 354 | ||
355 | i2c_write(reg, ICCR, 0x01); | 355 | i2c_write(reg, ICCR, 0x01); |
356 | i2c_read(reg, ICCR); | ||
357 | i2c_write(reg, ICSTART, 0x00); | 356 | i2c_write(reg, ICSTART, 0x00); |
358 | i2c_read(reg, ICSTART); | 357 | |
358 | udelay(10); | ||
359 | 359 | ||
360 | i2c_write(reg, ICCR, 0x10); | 360 | i2c_write(reg, ICCR, 0x10); |
361 | mdelay(100); | 361 | udelay(10); |
362 | i2c_write(reg, ICCR, 0x00); | 362 | i2c_write(reg, ICCR, 0x00); |
363 | mdelay(100); | 363 | udelay(10); |
364 | i2c_write(reg, ICCR, 0x10); | 364 | i2c_write(reg, ICCR, 0x10); |
365 | mdelay(100); | 365 | udelay(10); |
366 | 366 | ||
367 | iounmap(reg); | 367 | iounmap(reg); |
368 | } | 368 | } |
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 4c7fece5ef92..6a4bd582c028 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c | |||
@@ -462,6 +462,16 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = { | |||
462 | .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), | 462 | .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), |
463 | .mid_rid = 0xce, | 463 | .mid_rid = 0xce, |
464 | }, { | 464 | }, { |
465 | .slave_id = SHDMA_SLAVE_FSIA_TX, | ||
466 | .addr = 0xfe1f0024, | ||
467 | .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), | ||
468 | .mid_rid = 0xb1, | ||
469 | }, { | ||
470 | .slave_id = SHDMA_SLAVE_FSIA_RX, | ||
471 | .addr = 0xfe1f0020, | ||
472 | .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), | ||
473 | .mid_rid = 0xb2, | ||
474 | }, { | ||
465 | .slave_id = SHDMA_SLAVE_MMCIF_TX, | 475 | .slave_id = SHDMA_SLAVE_MMCIF_TX, |
466 | .addr = 0xe6bd0034, | 476 | .addr = 0xe6bd0034, |
467 | .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), | 477 | .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), |
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c new file mode 100644 index 000000000000..6a35c4a31e6c --- /dev/null +++ b/arch/arm/mach-shmobile/smp-emev2.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * SMP support for Emma Mobile EV2 | ||
3 | * | ||
4 | * Copyright (C) 2012 Renesas Solutions Corp. | ||
5 | * Copyright (C) 2012 Magnus Damm | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/smp.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <mach/common.h> | ||
27 | #include <mach/emev2.h> | ||
28 | #include <asm/smp_plat.h> | ||
29 | #include <asm/smp_scu.h> | ||
30 | #include <asm/hardware/gic.h> | ||
31 | #include <asm/cacheflush.h> | ||
32 | |||
33 | #define EMEV2_SCU_BASE 0x1e000000 | ||
34 | |||
35 | static DEFINE_SPINLOCK(scu_lock); | ||
36 | static void __iomem *scu_base; | ||
37 | |||
38 | static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) | ||
39 | { | ||
40 | unsigned long tmp; | ||
41 | |||
42 | /* we assume this code is running on a different cpu | ||
43 | * than the one that is changing coherency setting */ | ||
44 | spin_lock(&scu_lock); | ||
45 | tmp = readl(scu_base + 8); | ||
46 | tmp &= ~clr; | ||
47 | tmp |= set; | ||
48 | writel(tmp, scu_base + 8); | ||
49 | spin_unlock(&scu_lock); | ||
50 | |||
51 | } | ||
52 | |||
53 | unsigned int __init emev2_get_core_count(void) | ||
54 | { | ||
55 | if (!scu_base) { | ||
56 | scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE); | ||
57 | emev2_clock_init(); /* need ioremapped SMU */ | ||
58 | } | ||
59 | |||
60 | WARN_ON_ONCE(!scu_base); | ||
61 | |||
62 | return scu_base ? scu_get_core_count(scu_base) : 1; | ||
63 | } | ||
64 | |||
65 | int emev2_platform_cpu_kill(unsigned int cpu) | ||
66 | { | ||
67 | return 0; /* not supported yet */ | ||
68 | } | ||
69 | |||
70 | void __cpuinit emev2_secondary_init(unsigned int cpu) | ||
71 | { | ||
72 | gic_secondary_init(0); | ||
73 | } | ||
74 | |||
75 | int __cpuinit emev2_boot_secondary(unsigned int cpu) | ||
76 | { | ||
77 | cpu = cpu_logical_map(cpu); | ||
78 | |||
79 | /* enable cache coherency */ | ||
80 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); | ||
81 | |||
82 | /* Tell ROM loader about our vector (in headsmp.S) */ | ||
83 | emev2_set_boot_vector(__pa(shmobile_secondary_vector)); | ||
84 | |||
85 | gic_raise_softirq(cpumask_of(cpu), 1); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | void __init emev2_smp_prepare_cpus(void) | ||
90 | { | ||
91 | int cpu = cpu_logical_map(0); | ||
92 | |||
93 | scu_enable(scu_base); | ||
94 | |||
95 | /* enable cache coherency on CPU0 */ | ||
96 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); | ||
97 | } | ||
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c index cba39d866687..a68919727e24 100644 --- a/arch/arm/mach-shmobile/timer.c +++ b/arch/arm/mach-shmobile/timer.c | |||
@@ -36,7 +36,8 @@ void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz, | |||
36 | 36 | ||
37 | unsigned int value = (1000000 * mult) / (HZ * div); | 37 | unsigned int value = (1000000 * mult) / (HZ * div); |
38 | 38 | ||
39 | lpj_fine = max_cpu_core_mhz * value; | 39 | if (!preset_lpj) |
40 | preset_lpj = max_cpu_core_mhz * value; | ||
40 | } | 41 | } |
41 | 42 | ||
42 | static void __init shmobile_late_time_init(void) | 43 | static void __init shmobile_late_time_init(void) |
diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c index 5af36aa56c08..b29a788f498c 100644 --- a/arch/arm/mach-ux500/board-mop500-uib.c +++ b/arch/arm/mach-ux500/board-mop500-uib.c | |||
@@ -102,7 +102,7 @@ static int __init mop500_uib_init(void) | |||
102 | struct i2c_adapter *i2c0; | 102 | struct i2c_adapter *i2c0; |
103 | int ret; | 103 | int ret; |
104 | 104 | ||
105 | if (!cpu_is_u8500()) | 105 | if (!cpu_is_u8500_family()) |
106 | return -ENODEV; | 106 | return -ENODEV; |
107 | 107 | ||
108 | if (uib) { | 108 | if (uib) { |
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c index df91344aa2db..dc12394295d5 100644 --- a/arch/arm/mach-ux500/cache-l2x0.c +++ b/arch/arm/mach-ux500/cache-l2x0.c | |||
@@ -36,7 +36,9 @@ static int __init ux500_l2x0_unlock(void) | |||
36 | 36 | ||
37 | static int __init ux500_l2x0_init(void) | 37 | static int __init ux500_l2x0_init(void) |
38 | { | 38 | { |
39 | if (cpu_is_u8500()) | 39 | u32 aux_val = 0x3e000000; |
40 | |||
41 | if (cpu_is_u8500_family()) | ||
40 | l2x0_base = __io_address(U8500_L2CC_BASE); | 42 | l2x0_base = __io_address(U8500_L2CC_BASE); |
41 | else | 43 | else |
42 | ux500_unknown_soc(); | 44 | ux500_unknown_soc(); |
@@ -44,11 +46,19 @@ static int __init ux500_l2x0_init(void) | |||
44 | /* Unlock before init */ | 46 | /* Unlock before init */ |
45 | ux500_l2x0_unlock(); | 47 | ux500_l2x0_unlock(); |
46 | 48 | ||
49 | /* DB9540's L2 has 128KB way size */ | ||
50 | if (cpu_is_u9540()) | ||
51 | /* 128KB way size */ | ||
52 | aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); | ||
53 | else | ||
54 | /* 64KB way size */ | ||
55 | aux_val |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); | ||
56 | |||
47 | /* 64KB way size, 8 way associativity, force WA */ | 57 | /* 64KB way size, 8 way associativity, force WA */ |
48 | if (of_have_populated_dt()) | 58 | if (of_have_populated_dt()) |
49 | l2x0_of_init(0x3e060000, 0xc0000fff); | 59 | l2x0_of_init(aux_val, 0xc0000fff); |
50 | else | 60 | else |
51 | l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); | 61 | l2x0_init(l2x0_base, aux_val, 0xc0000fff); |
52 | 62 | ||
53 | /* | 63 | /* |
54 | * We can't disable l2 as we are in non secure mode, currently | 64 | * We can't disable l2 as we are in non secure mode, currently |
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 9feb6bc7f20e..063f3dbd45a9 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c | |||
@@ -149,7 +149,7 @@ static unsigned long clk_mtu_get_rate(struct clk *clk) | |||
149 | unsigned long mturate; | 149 | unsigned long mturate; |
150 | unsigned long retclk; | 150 | unsigned long retclk; |
151 | 151 | ||
152 | if (cpu_is_u8500()) | 152 | if (cpu_is_u8500_family()) |
153 | addr = __io_address(U8500_PRCMU_BASE); | 153 | addr = __io_address(U8500_PRCMU_BASE); |
154 | else | 154 | else |
155 | ux500_unknown_soc(); | 155 | ux500_unknown_soc(); |
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index f44a12ccddf3..76a7503a11a2 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c | |||
@@ -34,8 +34,8 @@ static struct map_desc u8500_uart_io_desc[] __initdata = { | |||
34 | __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K), | 34 | __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K), |
35 | __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K), | 35 | __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K), |
36 | }; | 36 | }; |
37 | 37 | /* U8500 and U9540 common io_desc */ | |
38 | static struct map_desc u8500_io_desc[] __initdata = { | 38 | static struct map_desc u8500_common_io_desc[] __initdata = { |
39 | /* SCU base also covers GIC CPU BASE and TWD with its 4K page */ | 39 | /* SCU base also covers GIC CPU BASE and TWD with its 4K page */ |
40 | __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), | 40 | __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), |
41 | __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), | 41 | __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), |
@@ -49,12 +49,23 @@ static struct map_desc u8500_io_desc[] __initdata = { | |||
49 | __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), | 49 | __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), |
50 | __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), | 50 | __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), |
51 | 51 | ||
52 | __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), | ||
53 | __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), | 52 | __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), |
54 | __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), | 53 | __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), |
55 | __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), | 54 | __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), |
56 | __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), | 55 | __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), |
56 | }; | ||
57 | |||
58 | /* U8500 IO map specific description */ | ||
59 | static struct map_desc u8500_io_desc[] __initdata = { | ||
60 | __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), | ||
57 | __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), | 61 | __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), |
62 | |||
63 | }; | ||
64 | |||
65 | /* U9540 IO map specific description */ | ||
66 | static struct map_desc u9540_io_desc[] __initdata = { | ||
67 | __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K + SZ_8K), | ||
68 | __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K + SZ_8K), | ||
58 | }; | 69 | }; |
59 | 70 | ||
60 | void __init u8500_map_io(void) | 71 | void __init u8500_map_io(void) |
@@ -66,7 +77,12 @@ void __init u8500_map_io(void) | |||
66 | 77 | ||
67 | ux500_map_io(); | 78 | ux500_map_io(); |
68 | 79 | ||
69 | iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); | 80 | iotable_init(u8500_common_io_desc, ARRAY_SIZE(u8500_common_io_desc)); |
81 | |||
82 | if (cpu_is_u9540()) | ||
83 | iotable_init(u9540_io_desc, ARRAY_SIZE(u9540_io_desc)); | ||
84 | else | ||
85 | iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); | ||
70 | 86 | ||
71 | _PRCMU_BASE = __io_address(U8500_PRCMU_BASE); | 87 | _PRCMU_BASE = __io_address(U8500_PRCMU_BASE); |
72 | } | 88 | } |
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 4b4e59b30d81..0982279f51f3 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c | |||
@@ -39,7 +39,7 @@ void __init ux500_init_irq(void) | |||
39 | void __iomem *dist_base; | 39 | void __iomem *dist_base; |
40 | void __iomem *cpu_base; | 40 | void __iomem *cpu_base; |
41 | 41 | ||
42 | if (cpu_is_u8500()) { | 42 | if (cpu_is_u8500_family()) { |
43 | dist_base = __io_address(U8500_GIC_DIST_BASE); | 43 | dist_base = __io_address(U8500_GIC_DIST_BASE); |
44 | cpu_base = __io_address(U8500_GIC_CPU_BASE); | 44 | cpu_base = __io_address(U8500_GIC_CPU_BASE); |
45 | } else | 45 | } else |
@@ -56,7 +56,7 @@ void __init ux500_init_irq(void) | |||
56 | * Init clocks here so that they are available for system timer | 56 | * Init clocks here so that they are available for system timer |
57 | * initialization. | 57 | * initialization. |
58 | */ | 58 | */ |
59 | if (cpu_is_u8500()) | 59 | if (cpu_is_u8500_family()) |
60 | db8500_prcmu_early_init(); | 60 | db8500_prcmu_early_init(); |
61 | clk_init(); | 61 | clk_init(); |
62 | } | 62 | } |
diff --git a/arch/arm/mach-ux500/id.c b/arch/arm/mach-ux500/id.c index 15a0f63b2e2b..d1579920139f 100644 --- a/arch/arm/mach-ux500/id.c +++ b/arch/arm/mach-ux500/id.c | |||
@@ -23,7 +23,7 @@ static unsigned int ux500_read_asicid(phys_addr_t addr) | |||
23 | { | 23 | { |
24 | phys_addr_t base = addr & ~0xfff; | 24 | phys_addr_t base = addr & ~0xfff; |
25 | struct map_desc desc = { | 25 | struct map_desc desc = { |
26 | .virtual = IO_ADDRESS(base), | 26 | .virtual = UX500_VIRT_ROM, |
27 | .pfn = __phys_to_pfn(base), | 27 | .pfn = __phys_to_pfn(base), |
28 | .length = SZ_16K, | 28 | .length = SZ_16K, |
29 | .type = MT_DEVICE, | 29 | .type = MT_DEVICE, |
@@ -35,7 +35,7 @@ static unsigned int ux500_read_asicid(phys_addr_t addr) | |||
35 | local_flush_tlb_all(); | 35 | local_flush_tlb_all(); |
36 | flush_cache_all(); | 36 | flush_cache_all(); |
37 | 37 | ||
38 | return readl(__io_address(addr)); | 38 | return readl(IOMEM(UX500_VIRT_ROM + (addr & 0xfff))); |
39 | } | 39 | } |
40 | 40 | ||
41 | static void ux500_print_soc_info(unsigned int asicid) | 41 | static void ux500_print_soc_info(unsigned int asicid) |
@@ -67,6 +67,7 @@ static unsigned int partnumber(unsigned int asicid) | |||
67 | * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0 | 67 | * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0 |
68 | * DB8520v2.2 0x412fc091 0x9001DBF4 0x008500B2 | 68 | * DB8520v2.2 0x412fc091 0x9001DBF4 0x008500B2 |
69 | * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0 | 69 | * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0 |
70 | * DB9540 0x413fc090 0xFFFFDBF4 0x009540xx | ||
70 | */ | 71 | */ |
71 | 72 | ||
72 | void __init ux500_map_io(void) | 73 | void __init ux500_map_io(void) |
@@ -91,6 +92,10 @@ void __init ux500_map_io(void) | |||
91 | /* DB5500v1 */ | 92 | /* DB5500v1 */ |
92 | addr = 0x9001FFF4; | 93 | addr = 0x9001FFF4; |
93 | break; | 94 | break; |
95 | |||
96 | case 0x413fc090: /* DB9540 */ | ||
97 | addr = 0xFFFFDBF4; | ||
98 | break; | ||
94 | } | 99 | } |
95 | 100 | ||
96 | if (addr) | 101 | if (addr) |
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index 9ec20b96d8f2..1530d493879d 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h | |||
@@ -41,6 +41,10 @@ | |||
41 | /* ASIC ID is at 0xbf4 offset within this region */ | 41 | /* ASIC ID is at 0xbf4 offset within this region */ |
42 | #define U8500_ASIC_ID_BASE 0x9001D000 | 42 | #define U8500_ASIC_ID_BASE 0x9001D000 |
43 | 43 | ||
44 | #define U9540_BOOT_ROM_BASE 0xFFFE0000 | ||
45 | /* ASIC ID is at 0xbf4 offset within this region */ | ||
46 | #define U9540_ASIC_ID_BASE 0xFFFFD000 | ||
47 | |||
44 | #define U8500_PER6_BASE 0xa03c0000 | 48 | #define U8500_PER6_BASE 0xa03c0000 |
45 | #define U8500_PER7_BASE 0xa03d0000 | 49 | #define U8500_PER7_BASE 0xa03d0000 |
46 | #define U8500_PER5_BASE 0xa03e0000 | 50 | #define U8500_PER5_BASE 0xa03e0000 |
@@ -96,7 +100,9 @@ | |||
96 | #define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) | 100 | #define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) |
97 | #define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) | 101 | #define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) |
98 | #define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) | 102 | #define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) |
103 | #define U9540_DMC1_BASE (U8500_PER4_BASE + 0x0A000) | ||
99 | #define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000) | 104 | #define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000) |
105 | #define U9540_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x6A000) | ||
100 | #define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000) | 106 | #define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000) |
101 | #define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338) | 107 | #define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338) |
102 | #define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450) | 108 | #define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450) |
diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index cf6fac3d1eeb..808c1d6601c5 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h | |||
@@ -17,6 +17,8 @@ | |||
17 | */ | 17 | */ |
18 | #define U8500_IO_VIRTUAL 0xf0000000 | 18 | #define U8500_IO_VIRTUAL 0xf0000000 |
19 | #define U8500_IO_PHYSICAL 0xa0000000 | 19 | #define U8500_IO_PHYSICAL 0xa0000000 |
20 | /* This is where we map in the ROM to check ASIC IDs */ | ||
21 | #define UX500_VIRT_ROM 0xf0000000 | ||
20 | 22 | ||
21 | /* This macro is used in assembly, so no cast */ | 23 | /* This macro is used in assembly, so no cast */ |
22 | #define IO_ADDRESS(x) \ | 24 | #define IO_ADDRESS(x) \ |
@@ -24,6 +26,7 @@ | |||
24 | 26 | ||
25 | /* typesafe io address */ | 27 | /* typesafe io address */ |
26 | #define __io_address(n) IOMEM(IO_ADDRESS(n)) | 28 | #define __io_address(n) IOMEM(IO_ADDRESS(n)) |
29 | |||
27 | /* Used by some plat-nomadik code */ | 30 | /* Used by some plat-nomadik code */ |
28 | #define io_p2v(n) __io_address(n) | 31 | #define io_p2v(n) __io_address(n) |
29 | 32 | ||
diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/include/mach/id.h index 833d6a6edc9b..c6e2db9e9e51 100644 --- a/arch/arm/mach-ux500/include/mach/id.h +++ b/arch/arm/mach-ux500/include/mach/id.h | |||
@@ -41,6 +41,16 @@ static inline bool __attribute_const__ cpu_is_u8500(void) | |||
41 | return dbx500_partnumber() == 0x8500; | 41 | return dbx500_partnumber() == 0x8500; |
42 | } | 42 | } |
43 | 43 | ||
44 | static inline bool __attribute_const__ cpu_is_u9540(void) | ||
45 | { | ||
46 | return dbx500_partnumber() == 0x9540; | ||
47 | } | ||
48 | |||
49 | static inline bool cpu_is_u8500_family(void) | ||
50 | { | ||
51 | return cpu_is_u8500() || cpu_is_u9540(); | ||
52 | } | ||
53 | |||
44 | static inline bool __attribute_const__ cpu_is_u5500(void) | 54 | static inline bool __attribute_const__ cpu_is_u5500(void) |
45 | { | 55 | { |
46 | return dbx500_partnumber() == 0x5500; | 56 | return dbx500_partnumber() == 0x5500; |
@@ -111,7 +121,12 @@ static inline bool cpu_is_u8500v21(void) | |||
111 | 121 | ||
112 | static inline bool cpu_is_u8500v20_or_later(void) | 122 | static inline bool cpu_is_u8500v20_or_later(void) |
113 | { | 123 | { |
114 | return cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11(); | 124 | /* |
125 | * U9540 has so much in common with U8500 that is is considered a | ||
126 | * U8500 variant. | ||
127 | */ | ||
128 | return cpu_is_u9540() || | ||
129 | (cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11()); | ||
115 | } | 130 | } |
116 | 131 | ||
117 | static inline bool ux500_is_svp(void) | 132 | static inline bool ux500_is_svp(void) |
diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index d06dcf6208fa..e8928548b6a3 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h | |||
@@ -24,7 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | #define IRQ_MTU0 (IRQ_SHPI_START + 4) | 25 | #define IRQ_MTU0 (IRQ_SHPI_START + 4) |
26 | 26 | ||
27 | #define DBX500_NR_INTERNAL_IRQS 160 | 27 | #define DBX500_NR_INTERNAL_IRQS 166 |
28 | 28 | ||
29 | /* After chip-specific IRQ numbers we have the GPIO ones */ | 29 | /* After chip-specific IRQ numbers we have the GPIO ones */ |
30 | #define NOMADIK_NR_GPIO 288 | 30 | #define NOMADIK_NR_GPIO 288 |
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index e8cd51aa61e4..da1d5ad5bd45 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c | |||
@@ -48,7 +48,7 @@ static void write_pen_release(int val) | |||
48 | 48 | ||
49 | static void __iomem *scu_base_addr(void) | 49 | static void __iomem *scu_base_addr(void) |
50 | { | 50 | { |
51 | if (cpu_is_u8500()) | 51 | if (cpu_is_u8500_family()) |
52 | return __io_address(U8500_SCU_BASE); | 52 | return __io_address(U8500_SCU_BASE); |
53 | else | 53 | else |
54 | ux500_unknown_soc(); | 54 | ux500_unknown_soc(); |
@@ -118,7 +118,7 @@ static void __init wakeup_secondary(void) | |||
118 | { | 118 | { |
119 | void __iomem *backupram; | 119 | void __iomem *backupram; |
120 | 120 | ||
121 | if (cpu_is_u8500()) | 121 | if (cpu_is_u8500_family()) |
122 | backupram = __io_address(U8500_BACKUPRAM0_BASE); | 122 | backupram = __io_address(U8500_BACKUPRAM0_BASE); |
123 | else | 123 | else |
124 | ux500_unknown_soc(); | 124 | ux500_unknown_soc(); |
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c index bd8e110cbcc2..741e71feca78 100644 --- a/arch/arm/mach-ux500/timer.c +++ b/arch/arm/mach-ux500/timer.c | |||
@@ -54,7 +54,7 @@ static void __init ux500_timer_init(void) | |||
54 | void __iomem *tmp_base; | 54 | void __iomem *tmp_base; |
55 | struct device_node *np; | 55 | struct device_node *np; |
56 | 56 | ||
57 | if (cpu_is_u8500()) { | 57 | if (cpu_is_u8500_family()) { |
58 | mtu_timer_base = __io_address(U8500_MTU0_BASE); | 58 | mtu_timer_base = __io_address(U8500_MTU0_BASE); |
59 | prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE); | 59 | prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE); |
60 | } else { | 60 | } else { |
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c index 0bf1b8910eeb..74b830b635a6 100644 --- a/drivers/cpufreq/db8500-cpufreq.c +++ b/drivers/cpufreq/db8500-cpufreq.c | |||
@@ -161,7 +161,7 @@ static struct cpufreq_driver db8500_cpufreq_driver = { | |||
161 | 161 | ||
162 | static int __init db8500_cpufreq_register(void) | 162 | static int __init db8500_cpufreq_register(void) |
163 | { | 163 | { |
164 | if (!cpu_is_u8500v20_or_later()) | 164 | if (!cpu_is_u8500_family()) |
165 | return -ENODEV; | 165 | return -ENODEV; |
166 | 166 | ||
167 | pr_info("cpufreq for DB8500 started\n"); | 167 | pr_info("cpufreq for DB8500 started\n"); |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e03653d69357..eb80ba300452 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -91,6 +91,12 @@ config GPIO_IT8761E | |||
91 | help | 91 | help |
92 | Say yes here to support GPIO functionality of IT8761E super I/O chip. | 92 | Say yes here to support GPIO functionality of IT8761E super I/O chip. |
93 | 93 | ||
94 | config GPIO_EM | ||
95 | tristate "Emma Mobile GPIO" | ||
96 | depends on ARM | ||
97 | help | ||
98 | Say yes here to support GPIO on Renesas Emma Mobile SoCs. | ||
99 | |||
94 | config GPIO_EP93XX | 100 | config GPIO_EP93XX |
95 | def_bool y | 101 | def_bool y |
96 | depends on ARCH_EP93XX | 102 | depends on ARCH_EP93XX |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 007f54bd0081..3f1f829260bb 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o | |||
15 | obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o | 15 | obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o |
16 | obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o | 16 | obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o |
17 | obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o | 17 | obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o |
18 | obj-$(CONFIG_GPIO_EM) += gpio-em.o | ||
18 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o | 19 | obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o |
19 | obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o | 20 | obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o |
20 | obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o | 21 | obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o |
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c new file mode 100644 index 000000000000..150d9768811d --- /dev/null +++ b/drivers/gpio/gpio-em.c | |||
@@ -0,0 +1,418 @@ | |||
1 | /* | ||
2 | * Emma Mobile GPIO Support - GIO | ||
3 | * | ||
4 | * Copyright (C) 2012 Magnus Damm | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/irqdomain.h> | ||
28 | #include <linux/bitops.h> | ||
29 | #include <linux/err.h> | ||
30 | #include <linux/gpio.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/platform_data/gpio-em.h> | ||
34 | |||
35 | struct em_gio_priv { | ||
36 | void __iomem *base0; | ||
37 | void __iomem *base1; | ||
38 | unsigned int irq_base; | ||
39 | spinlock_t sense_lock; | ||
40 | struct platform_device *pdev; | ||
41 | struct gpio_chip gpio_chip; | ||
42 | struct irq_chip irq_chip; | ||
43 | struct irq_domain *irq_domain; | ||
44 | }; | ||
45 | |||
46 | #define GIO_E1 0x00 | ||
47 | #define GIO_E0 0x04 | ||
48 | #define GIO_EM 0x04 | ||
49 | #define GIO_OL 0x08 | ||
50 | #define GIO_OH 0x0c | ||
51 | #define GIO_I 0x10 | ||
52 | #define GIO_IIA 0x14 | ||
53 | #define GIO_IEN 0x18 | ||
54 | #define GIO_IDS 0x1c | ||
55 | #define GIO_IIM 0x1c | ||
56 | #define GIO_RAW 0x20 | ||
57 | #define GIO_MST 0x24 | ||
58 | #define GIO_IIR 0x28 | ||
59 | |||
60 | #define GIO_IDT0 0x40 | ||
61 | #define GIO_IDT1 0x44 | ||
62 | #define GIO_IDT2 0x48 | ||
63 | #define GIO_IDT3 0x4c | ||
64 | #define GIO_RAWBL 0x50 | ||
65 | #define GIO_RAWBH 0x54 | ||
66 | #define GIO_IRBL 0x58 | ||
67 | #define GIO_IRBH 0x5c | ||
68 | |||
69 | #define GIO_IDT(n) (GIO_IDT0 + ((n) * 4)) | ||
70 | |||
71 | static inline unsigned long em_gio_read(struct em_gio_priv *p, int offs) | ||
72 | { | ||
73 | if (offs < GIO_IDT0) | ||
74 | return ioread32(p->base0 + offs); | ||
75 | else | ||
76 | return ioread32(p->base1 + (offs - GIO_IDT0)); | ||
77 | } | ||
78 | |||
79 | static inline void em_gio_write(struct em_gio_priv *p, int offs, | ||
80 | unsigned long value) | ||
81 | { | ||
82 | if (offs < GIO_IDT0) | ||
83 | iowrite32(value, p->base0 + offs); | ||
84 | else | ||
85 | iowrite32(value, p->base1 + (offs - GIO_IDT0)); | ||
86 | } | ||
87 | |||
88 | static inline struct em_gio_priv *irq_to_priv(struct irq_data *d) | ||
89 | { | ||
90 | struct irq_chip *chip = irq_data_get_irq_chip(d); | ||
91 | return container_of(chip, struct em_gio_priv, irq_chip); | ||
92 | } | ||
93 | |||
94 | static void em_gio_irq_disable(struct irq_data *d) | ||
95 | { | ||
96 | struct em_gio_priv *p = irq_to_priv(d); | ||
97 | |||
98 | em_gio_write(p, GIO_IDS, BIT(irqd_to_hwirq(d))); | ||
99 | } | ||
100 | |||
101 | static void em_gio_irq_enable(struct irq_data *d) | ||
102 | { | ||
103 | struct em_gio_priv *p = irq_to_priv(d); | ||
104 | |||
105 | em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d))); | ||
106 | } | ||
107 | |||
108 | #define GIO_ASYNC(x) (x + 8) | ||
109 | |||
110 | static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { | ||
111 | [IRQ_TYPE_EDGE_RISING] = GIO_ASYNC(0x00), | ||
112 | [IRQ_TYPE_EDGE_FALLING] = GIO_ASYNC(0x01), | ||
113 | [IRQ_TYPE_LEVEL_HIGH] = GIO_ASYNC(0x02), | ||
114 | [IRQ_TYPE_LEVEL_LOW] = GIO_ASYNC(0x03), | ||
115 | [IRQ_TYPE_EDGE_BOTH] = GIO_ASYNC(0x04), | ||
116 | }; | ||
117 | |||
118 | static int em_gio_irq_set_type(struct irq_data *d, unsigned int type) | ||
119 | { | ||
120 | unsigned char value = em_gio_sense_table[type & IRQ_TYPE_SENSE_MASK]; | ||
121 | struct em_gio_priv *p = irq_to_priv(d); | ||
122 | unsigned int reg, offset, shift; | ||
123 | unsigned long flags; | ||
124 | unsigned long tmp; | ||
125 | |||
126 | if (!value) | ||
127 | return -EINVAL; | ||
128 | |||
129 | offset = irqd_to_hwirq(d); | ||
130 | |||
131 | pr_debug("gio: sense irq = %d, mode = %d\n", offset, value); | ||
132 | |||
133 | /* 8 x 4 bit fields in 4 IDT registers */ | ||
134 | reg = GIO_IDT(offset >> 3); | ||
135 | shift = (offset & 0x07) << 4; | ||
136 | |||
137 | spin_lock_irqsave(&p->sense_lock, flags); | ||
138 | |||
139 | /* disable the interrupt in IIA */ | ||
140 | tmp = em_gio_read(p, GIO_IIA); | ||
141 | tmp &= ~BIT(offset); | ||
142 | em_gio_write(p, GIO_IIA, tmp); | ||
143 | |||
144 | /* change the sense setting in IDT */ | ||
145 | tmp = em_gio_read(p, reg); | ||
146 | tmp &= ~(0xf << shift); | ||
147 | tmp |= value << shift; | ||
148 | em_gio_write(p, reg, tmp); | ||
149 | |||
150 | /* clear pending interrupts */ | ||
151 | em_gio_write(p, GIO_IIR, BIT(offset)); | ||
152 | |||
153 | /* enable the interrupt in IIA */ | ||
154 | tmp = em_gio_read(p, GIO_IIA); | ||
155 | tmp |= BIT(offset); | ||
156 | em_gio_write(p, GIO_IIA, tmp); | ||
157 | |||
158 | spin_unlock_irqrestore(&p->sense_lock, flags); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static irqreturn_t em_gio_irq_handler(int irq, void *dev_id) | ||
164 | { | ||
165 | struct em_gio_priv *p = dev_id; | ||
166 | unsigned long pending; | ||
167 | unsigned int offset, irqs_handled = 0; | ||
168 | |||
169 | while ((pending = em_gio_read(p, GIO_MST))) { | ||
170 | offset = __ffs(pending); | ||
171 | em_gio_write(p, GIO_IIR, BIT(offset)); | ||
172 | generic_handle_irq(irq_find_mapping(p->irq_domain, offset)); | ||
173 | irqs_handled++; | ||
174 | } | ||
175 | |||
176 | return irqs_handled ? IRQ_HANDLED : IRQ_NONE; | ||
177 | } | ||
178 | |||
179 | static inline struct em_gio_priv *gpio_to_priv(struct gpio_chip *chip) | ||
180 | { | ||
181 | return container_of(chip, struct em_gio_priv, gpio_chip); | ||
182 | } | ||
183 | |||
184 | static int em_gio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
185 | { | ||
186 | em_gio_write(gpio_to_priv(chip), GIO_E0, BIT(offset)); | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int em_gio_get(struct gpio_chip *chip, unsigned offset) | ||
191 | { | ||
192 | return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) & BIT(offset)); | ||
193 | } | ||
194 | |||
195 | static void __em_gio_set(struct gpio_chip *chip, unsigned int reg, | ||
196 | unsigned shift, int value) | ||
197 | { | ||
198 | /* upper 16 bits contains mask and lower 16 actual value */ | ||
199 | em_gio_write(gpio_to_priv(chip), reg, | ||
200 | (1 << (shift + 16)) | (value << shift)); | ||
201 | } | ||
202 | |||
203 | static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
204 | { | ||
205 | /* output is split into two registers */ | ||
206 | if (offset < 16) | ||
207 | __em_gio_set(chip, GIO_OL, offset, value); | ||
208 | else | ||
209 | __em_gio_set(chip, GIO_OH, offset - 16, value); | ||
210 | } | ||
211 | |||
212 | static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
213 | int value) | ||
214 | { | ||
215 | /* write GPIO value to output before selecting output mode of pin */ | ||
216 | em_gio_set(chip, offset, value); | ||
217 | em_gio_write(gpio_to_priv(chip), GIO_E1, BIT(offset)); | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
222 | { | ||
223 | return irq_find_mapping(gpio_to_priv(chip)->irq_domain, offset); | ||
224 | } | ||
225 | |||
226 | static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq, | ||
227 | irq_hw_number_t hw) | ||
228 | { | ||
229 | struct em_gio_priv *p = h->host_data; | ||
230 | |||
231 | pr_debug("gio: map hw irq = %d, virq = %d\n", (int)hw, virq); | ||
232 | |||
233 | irq_set_chip_data(virq, h->host_data); | ||
234 | irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq); | ||
235 | set_irq_flags(virq, IRQF_VALID); /* kill me now */ | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static struct irq_domain_ops em_gio_irq_domain_ops = { | ||
240 | .map = em_gio_irq_domain_map, | ||
241 | }; | ||
242 | |||
243 | static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p) | ||
244 | { | ||
245 | struct platform_device *pdev = p->pdev; | ||
246 | struct gpio_em_config *pdata = pdev->dev.platform_data; | ||
247 | |||
248 | p->irq_base = irq_alloc_descs(pdata->irq_base, 0, | ||
249 | pdata->number_of_pins, numa_node_id()); | ||
250 | if (IS_ERR_VALUE(p->irq_base)) { | ||
251 | dev_err(&pdev->dev, "cannot get irq_desc\n"); | ||
252 | return -ENXIO; | ||
253 | } | ||
254 | pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n", | ||
255 | pdata->gpio_base, pdata->number_of_pins, p->irq_base); | ||
256 | |||
257 | p->irq_domain = irq_domain_add_legacy(pdev->dev.of_node, | ||
258 | pdata->number_of_pins, | ||
259 | p->irq_base, 0, | ||
260 | &em_gio_irq_domain_ops, p); | ||
261 | if (!p->irq_domain) { | ||
262 | irq_free_descs(p->irq_base, pdata->number_of_pins); | ||
263 | return -ENXIO; | ||
264 | } | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static void __devexit em_gio_irq_domain_cleanup(struct em_gio_priv *p) | ||
270 | { | ||
271 | struct gpio_em_config *pdata = p->pdev->dev.platform_data; | ||
272 | |||
273 | irq_free_descs(p->irq_base, pdata->number_of_pins); | ||
274 | /* FIXME: irq domain wants to be freed! */ | ||
275 | } | ||
276 | |||
277 | static int __devinit em_gio_probe(struct platform_device *pdev) | ||
278 | { | ||
279 | struct gpio_em_config *pdata = pdev->dev.platform_data; | ||
280 | struct em_gio_priv *p; | ||
281 | struct resource *io[2], *irq[2]; | ||
282 | struct gpio_chip *gpio_chip; | ||
283 | struct irq_chip *irq_chip; | ||
284 | const char *name = dev_name(&pdev->dev); | ||
285 | int ret; | ||
286 | |||
287 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
288 | if (!p) { | ||
289 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
290 | ret = -ENOMEM; | ||
291 | goto err0; | ||
292 | } | ||
293 | |||
294 | p->pdev = pdev; | ||
295 | platform_set_drvdata(pdev, p); | ||
296 | spin_lock_init(&p->sense_lock); | ||
297 | |||
298 | io[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
299 | io[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
300 | irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
301 | irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||
302 | |||
303 | if (!io[0] || !io[1] || !irq[0] || !irq[1] || !pdata) { | ||
304 | dev_err(&pdev->dev, "missing IRQ, IOMEM or configuration\n"); | ||
305 | ret = -EINVAL; | ||
306 | goto err1; | ||
307 | } | ||
308 | |||
309 | p->base0 = ioremap_nocache(io[0]->start, resource_size(io[0])); | ||
310 | if (!p->base0) { | ||
311 | dev_err(&pdev->dev, "failed to remap low I/O memory\n"); | ||
312 | ret = -ENXIO; | ||
313 | goto err1; | ||
314 | } | ||
315 | |||
316 | p->base1 = ioremap_nocache(io[1]->start, resource_size(io[1])); | ||
317 | if (!p->base1) { | ||
318 | dev_err(&pdev->dev, "failed to remap high I/O memory\n"); | ||
319 | ret = -ENXIO; | ||
320 | goto err2; | ||
321 | } | ||
322 | |||
323 | gpio_chip = &p->gpio_chip; | ||
324 | gpio_chip->direction_input = em_gio_direction_input; | ||
325 | gpio_chip->get = em_gio_get; | ||
326 | gpio_chip->direction_output = em_gio_direction_output; | ||
327 | gpio_chip->set = em_gio_set; | ||
328 | gpio_chip->to_irq = em_gio_to_irq; | ||
329 | gpio_chip->label = name; | ||
330 | gpio_chip->owner = THIS_MODULE; | ||
331 | gpio_chip->base = pdata->gpio_base; | ||
332 | gpio_chip->ngpio = pdata->number_of_pins; | ||
333 | |||
334 | irq_chip = &p->irq_chip; | ||
335 | irq_chip->name = name; | ||
336 | irq_chip->irq_mask = em_gio_irq_disable; | ||
337 | irq_chip->irq_unmask = em_gio_irq_enable; | ||
338 | irq_chip->irq_enable = em_gio_irq_enable; | ||
339 | irq_chip->irq_disable = em_gio_irq_disable; | ||
340 | irq_chip->irq_set_type = em_gio_irq_set_type; | ||
341 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; | ||
342 | |||
343 | ret = em_gio_irq_domain_init(p); | ||
344 | if (ret) { | ||
345 | dev_err(&pdev->dev, "cannot initialize irq domain\n"); | ||
346 | goto err3; | ||
347 | } | ||
348 | |||
349 | if (request_irq(irq[0]->start, em_gio_irq_handler, 0, name, p)) { | ||
350 | dev_err(&pdev->dev, "failed to request low IRQ\n"); | ||
351 | ret = -ENOENT; | ||
352 | goto err4; | ||
353 | } | ||
354 | |||
355 | if (request_irq(irq[1]->start, em_gio_irq_handler, 0, name, p)) { | ||
356 | dev_err(&pdev->dev, "failed to request high IRQ\n"); | ||
357 | ret = -ENOENT; | ||
358 | goto err5; | ||
359 | } | ||
360 | |||
361 | ret = gpiochip_add(gpio_chip); | ||
362 | if (ret) { | ||
363 | dev_err(&pdev->dev, "failed to add GPIO controller\n"); | ||
364 | goto err6; | ||
365 | } | ||
366 | return 0; | ||
367 | |||
368 | err6: | ||
369 | free_irq(irq[1]->start, pdev); | ||
370 | err5: | ||
371 | free_irq(irq[0]->start, pdev); | ||
372 | err4: | ||
373 | em_gio_irq_domain_cleanup(p); | ||
374 | err3: | ||
375 | iounmap(p->base1); | ||
376 | err2: | ||
377 | iounmap(p->base0); | ||
378 | err1: | ||
379 | kfree(p); | ||
380 | err0: | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int __devexit em_gio_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | struct em_gio_priv *p = platform_get_drvdata(pdev); | ||
387 | struct resource *irq[2]; | ||
388 | int ret; | ||
389 | |||
390 | ret = gpiochip_remove(&p->gpio_chip); | ||
391 | if (ret) | ||
392 | return ret; | ||
393 | |||
394 | irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
395 | irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||
396 | |||
397 | free_irq(irq[1]->start, pdev); | ||
398 | free_irq(irq[0]->start, pdev); | ||
399 | em_gio_irq_domain_cleanup(p); | ||
400 | iounmap(p->base1); | ||
401 | iounmap(p->base0); | ||
402 | kfree(p); | ||
403 | return 0; | ||
404 | } | ||
405 | |||
406 | static struct platform_driver em_gio_device_driver = { | ||
407 | .probe = em_gio_probe, | ||
408 | .remove = __devexit_p(em_gio_remove), | ||
409 | .driver = { | ||
410 | .name = "em_gio", | ||
411 | } | ||
412 | }; | ||
413 | |||
414 | module_platform_driver(em_gio_device_driver); | ||
415 | |||
416 | MODULE_AUTHOR("Magnus Damm"); | ||
417 | MODULE_DESCRIPTION("Renesas Emma Mobile GIO Driver"); | ||
418 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/include/linux/platform_data/gpio-em.h b/include/linux/platform_data/gpio-em.h new file mode 100644 index 000000000000..573edfb046c4 --- /dev/null +++ b/include/linux/platform_data/gpio-em.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __GPIO_EM_H__ | ||
2 | #define __GPIO_EM_H__ | ||
3 | |||
4 | struct gpio_em_config { | ||
5 | unsigned int gpio_base; | ||
6 | unsigned int irq_base; | ||
7 | unsigned int number_of_pins; | ||
8 | }; | ||
9 | |||
10 | #endif /* __GPIO_EM_H__ */ | ||