Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /***************************************************************************/ |
2 | ||
3 | /* | |
4 | * linux/arch/m68knommu/platform/528x/config.c | |
5 | * | |
6 | * Sub-architcture dependant initialization code for the Motorola | |
7 | * 5280 and 5282 CPUs. | |
8 | * | |
9 | * Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com) | |
10 | * Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com) | |
11 | */ | |
12 | ||
13 | /***************************************************************************/ | |
14 | ||
1da177e4 | 15 | #include <linux/kernel.h> |
1da177e4 LT |
16 | #include <linux/param.h> |
17 | #include <linux/init.h> | |
18 | #include <linux/interrupt.h> | |
eb49e907 GU |
19 | #include <linux/platform_device.h> |
20 | #include <linux/spi/spi.h> | |
21 | #include <linux/spi/flash.h> | |
22 | #include <linux/io.h> | |
1da177e4 LT |
23 | #include <asm/machdep.h> |
24 | #include <asm/coldfire.h> | |
25 | #include <asm/mcfsim.h> | |
eb49e907 GU |
26 | #include <asm/mcfuart.h> |
27 | #include <asm/mcfqspi.h> | |
1da177e4 | 28 | |
188a9a48 SB |
29 | #ifdef CONFIG_MTD_PARTITIONS |
30 | #include <linux/mtd/partitions.h> | |
31 | #endif | |
32 | ||
1da177e4 LT |
33 | /***************************************************************************/ |
34 | ||
1da177e4 | 35 | void coldfire_reset(void); |
188a9a48 SB |
36 | static void coldfire_qspi_cs_control(u8 cs, u8 command); |
37 | ||
38 | /***************************************************************************/ | |
39 | ||
40 | #if defined(CONFIG_SPI) | |
41 | ||
42 | #if defined(CONFIG_WILDFIRE) | |
43 | #define SPI_NUM_CHIPSELECTS 0x02 | |
44 | #define SPI_PAR_VAL 0x07 /* Enable DIN, DOUT, CLK */ | |
45 | #define SPI_CS_MASK 0x18 | |
46 | ||
47 | #define FLASH_BLOCKSIZE (1024*64) | |
48 | #define FLASH_NUMBLOCKS 16 | |
49 | #define FLASH_TYPE "m25p80" | |
50 | ||
51 | #define M25P80_CS 0 | |
52 | #define MMC_CS 1 | |
53 | ||
54 | #ifdef CONFIG_MTD_PARTITIONS | |
55 | static struct mtd_partition stm25p_partitions[] = { | |
56 | /* sflash */ | |
57 | [0] = { | |
58 | .name = "stm25p80", | |
59 | .offset = 0x00000000, | |
60 | .size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS, | |
61 | .mask_flags = 0 | |
62 | } | |
63 | }; | |
64 | ||
65 | #endif | |
66 | ||
67 | #elif defined(CONFIG_WILDFIREMOD) | |
68 | ||
69 | #define SPI_NUM_CHIPSELECTS 0x08 | |
70 | #define SPI_PAR_VAL 0x07 /* Enable DIN, DOUT, CLK */ | |
71 | #define SPI_CS_MASK 0x78 | |
72 | ||
73 | #define FLASH_BLOCKSIZE (1024*64) | |
74 | #define FLASH_NUMBLOCKS 64 | |
75 | #define FLASH_TYPE "m25p32" | |
76 | /* Reserve 1M for the kernel parition */ | |
77 | #define FLASH_KERNEL_SIZE (1024 * 1024) | |
78 | ||
79 | #define M25P80_CS 5 | |
80 | #define MMC_CS 6 | |
81 | ||
82 | #ifdef CONFIG_MTD_PARTITIONS | |
83 | static struct mtd_partition stm25p_partitions[] = { | |
84 | /* sflash */ | |
85 | [0] = { | |
86 | .name = "kernel", | |
87 | .offset = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS - FLASH_KERNEL_SIZE, | |
88 | .size = FLASH_KERNEL_SIZE, | |
89 | .mask_flags = 0 | |
90 | }, | |
91 | [1] = { | |
92 | .name = "image", | |
93 | .offset = 0x00000000, | |
94 | .size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS - FLASH_KERNEL_SIZE, | |
95 | .mask_flags = 0 | |
96 | }, | |
97 | [2] = { | |
98 | .name = "all", | |
99 | .offset = 0x00000000, | |
100 | .size = FLASH_BLOCKSIZE * FLASH_NUMBLOCKS, | |
101 | .mask_flags = 0 | |
102 | } | |
103 | }; | |
104 | #endif | |
105 | ||
106 | #else | |
107 | #define SPI_NUM_CHIPSELECTS 0x04 | |
108 | #define SPI_PAR_VAL 0x7F /* Enable DIN, DOUT, CLK, CS0 - CS4 */ | |
109 | #endif | |
110 | ||
111 | #ifdef MMC_CS | |
112 | static struct coldfire_spi_chip flash_chip_info = { | |
113 | .mode = SPI_MODE_0, | |
114 | .bits_per_word = 16, | |
115 | .del_cs_to_clk = 17, | |
116 | .del_after_trans = 1, | |
117 | .void_write_data = 0 | |
118 | }; | |
119 | ||
120 | static struct coldfire_spi_chip mmc_chip_info = { | |
121 | .mode = SPI_MODE_0, | |
122 | .bits_per_word = 16, | |
123 | .del_cs_to_clk = 17, | |
124 | .del_after_trans = 1, | |
125 | .void_write_data = 0xFFFF | |
126 | }; | |
127 | #endif | |
128 | ||
129 | #ifdef M25P80_CS | |
130 | static struct flash_platform_data stm25p80_platform_data = { | |
131 | .name = "ST M25P80 SPI Flash chip", | |
132 | #ifdef CONFIG_MTD_PARTITIONS | |
133 | .parts = stm25p_partitions, | |
134 | .nr_parts = sizeof(stm25p_partitions) / sizeof(*stm25p_partitions), | |
135 | #endif | |
136 | .type = FLASH_TYPE | |
137 | }; | |
138 | #endif | |
139 | ||
140 | static struct spi_board_info spi_board_info[] __initdata = { | |
141 | #ifdef M25P80_CS | |
142 | { | |
143 | .modalias = "m25p80", | |
144 | .max_speed_hz = 16000000, | |
145 | .bus_num = 1, | |
146 | .chip_select = M25P80_CS, | |
147 | .platform_data = &stm25p80_platform_data, | |
148 | .controller_data = &flash_chip_info | |
149 | }, | |
150 | #endif | |
151 | #ifdef MMC_CS | |
152 | { | |
153 | .modalias = "mmc_spi", | |
154 | .max_speed_hz = 16000000, | |
155 | .bus_num = 1, | |
156 | .chip_select = MMC_CS, | |
157 | .controller_data = &mmc_chip_info | |
158 | } | |
159 | #endif | |
160 | }; | |
161 | ||
162 | static struct coldfire_spi_master coldfire_master_info = { | |
163 | .bus_num = 1, | |
164 | .num_chipselect = SPI_NUM_CHIPSELECTS, | |
165 | .irq_source = MCF5282_QSPI_IRQ_SOURCE, | |
166 | .irq_vector = MCF5282_QSPI_IRQ_VECTOR, | |
167 | .irq_mask = ((0x01 << MCF5282_QSPI_IRQ_SOURCE) | 0x01), | |
168 | .irq_lp = 0x2B, /* Level 5 and Priority 3 */ | |
169 | .par_val = SPI_PAR_VAL, | |
170 | .cs_control = coldfire_qspi_cs_control, | |
171 | }; | |
172 | ||
173 | static struct resource coldfire_spi_resources[] = { | |
174 | [0] = { | |
175 | .name = "qspi-par", | |
176 | .start = MCF5282_QSPI_PAR, | |
177 | .end = MCF5282_QSPI_PAR, | |
178 | .flags = IORESOURCE_MEM | |
179 | }, | |
180 | ||
181 | [1] = { | |
182 | .name = "qspi-module", | |
183 | .start = MCF5282_QSPI_QMR, | |
184 | .end = MCF5282_QSPI_QMR + 0x18, | |
185 | .flags = IORESOURCE_MEM | |
186 | }, | |
187 | ||
188 | [2] = { | |
189 | .name = "qspi-int-level", | |
190 | .start = MCF5282_INTC0 + MCFINTC_ICR0 + MCF5282_QSPI_IRQ_SOURCE, | |
191 | .end = MCF5282_INTC0 + MCFINTC_ICR0 + MCF5282_QSPI_IRQ_SOURCE, | |
192 | .flags = IORESOURCE_MEM | |
193 | }, | |
194 | ||
195 | [3] = { | |
196 | .name = "qspi-int-mask", | |
197 | .start = MCF5282_INTC0 + MCFINTC_IMRL, | |
198 | .end = MCF5282_INTC0 + MCFINTC_IMRL, | |
199 | .flags = IORESOURCE_MEM | |
200 | } | |
201 | }; | |
202 | ||
203 | static struct platform_device coldfire_spi = { | |
204 | .name = "spi_coldfire", | |
205 | .id = -1, | |
206 | .resource = coldfire_spi_resources, | |
207 | .num_resources = ARRAY_SIZE(coldfire_spi_resources), | |
208 | .dev = { | |
209 | .platform_data = &coldfire_master_info, | |
210 | } | |
211 | }; | |
212 | ||
213 | static void coldfire_qspi_cs_control(u8 cs, u8 command) | |
214 | { | |
215 | u8 cs_bit = ((0x01 << cs) << 3) & SPI_CS_MASK; | |
216 | ||
217 | #if defined(CONFIG_WILDFIRE) | |
218 | u8 cs_mask = ~(((0x01 << cs) << 3) & SPI_CS_MASK); | |
219 | #endif | |
220 | #if defined(CONFIG_WILDFIREMOD) | |
221 | u8 cs_mask = (cs << 3) & SPI_CS_MASK; | |
222 | #endif | |
223 | ||
224 | /* | |
225 | * Don't do anything if the chip select is not | |
226 | * one of the port qs pins. | |
227 | */ | |
228 | if (command & QSPI_CS_INIT) { | |
229 | #if defined(CONFIG_WILDFIRE) | |
230 | MCF5282_GPIO_DDRQS |= cs_bit; | |
231 | MCF5282_GPIO_PQSPAR &= ~cs_bit; | |
232 | #endif | |
233 | ||
234 | #if defined(CONFIG_WILDFIREMOD) | |
235 | MCF5282_GPIO_DDRQS |= SPI_CS_MASK; | |
236 | MCF5282_GPIO_PQSPAR &= ~SPI_CS_MASK; | |
237 | #endif | |
238 | } | |
239 | ||
240 | if (command & QSPI_CS_ASSERT) { | |
241 | MCF5282_GPIO_PORTQS &= ~SPI_CS_MASK; | |
242 | MCF5282_GPIO_PORTQS |= cs_mask; | |
243 | } else if (command & QSPI_CS_DROP) { | |
244 | MCF5282_GPIO_PORTQS |= SPI_CS_MASK; | |
245 | } | |
246 | } | |
247 | ||
248 | static int __init spi_dev_init(void) | |
249 | { | |
250 | int retval; | |
251 | ||
252 | retval = platform_device_register(&coldfire_spi); | |
253 | if (retval < 0) | |
254 | return retval; | |
255 | ||
256 | if (ARRAY_SIZE(spi_board_info)) | |
257 | retval = spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); | |
258 | ||
259 | return retval; | |
260 | } | |
261 | ||
262 | #endif /* CONFIG_SPI */ | |
1da177e4 LT |
263 | |
264 | /***************************************************************************/ | |
265 | ||
eb49e907 GU |
266 | static struct mcf_platform_uart m528x_uart_platform[] = { |
267 | { | |
268 | .mapbase = MCF_MBAR + MCFUART_BASE1, | |
269 | .irq = MCFINT_VECBASE + MCFINT_UART0, | |
270 | }, | |
271 | { | |
272 | .mapbase = MCF_MBAR + MCFUART_BASE2, | |
273 | .irq = MCFINT_VECBASE + MCFINT_UART0 + 1, | |
274 | }, | |
275 | { | |
276 | .mapbase = MCF_MBAR + MCFUART_BASE3, | |
277 | .irq = MCFINT_VECBASE + MCFINT_UART0 + 2, | |
278 | }, | |
279 | { }, | |
1da177e4 LT |
280 | }; |
281 | ||
eb49e907 GU |
282 | static struct platform_device m528x_uart = { |
283 | .name = "mcfuart", | |
284 | .id = 0, | |
285 | .dev.platform_data = m528x_uart_platform, | |
286 | }; | |
287 | ||
288 | static struct platform_device *m528x_devices[] __initdata = { | |
289 | &m528x_uart, | |
290 | }; | |
291 | ||
292 | /***************************************************************************/ | |
293 | ||
294 | #define INTC0 (MCF_MBAR + MCFICM_INTC0) | |
295 | ||
296 | static void __init m528x_uart_init_line(int line, int irq) | |
297 | { | |
298 | u8 port; | |
299 | u32 imr; | |
300 | ||
301 | if ((line < 0) || (line > 2)) | |
302 | return; | |
303 | ||
304 | /* level 6, line based priority */ | |
305 | writeb(0x30+line, INTC0 + MCFINTC_ICR0 + MCFINT_UART0 + line); | |
306 | ||
307 | imr = readl(INTC0 + MCFINTC_IMRL); | |
308 | imr &= ~((1 << (irq - MCFINT_VECBASE)) | 1); | |
309 | writel(imr, INTC0 + MCFINTC_IMRL); | |
310 | ||
311 | /* make sure PUAPAR is set for UART0 and UART1 */ | |
312 | if (line < 2) { | |
313 | port = readb(MCF_MBAR + MCF5282_GPIO_PUAPAR); | |
314 | port |= (0x03 << (line * 2)); | |
315 | writeb(port, MCF_MBAR + MCF5282_GPIO_PUAPAR); | |
316 | } | |
317 | } | |
318 | ||
319 | static void __init m528x_uarts_init(void) | |
320 | { | |
321 | const int nrlines = ARRAY_SIZE(m528x_uart_platform); | |
322 | int line; | |
323 | ||
324 | for (line = 0; (line < nrlines); line++) | |
325 | m528x_uart_init_line(line, m528x_uart_platform[line].irq); | |
326 | } | |
1da177e4 LT |
327 | |
328 | /***************************************************************************/ | |
329 | ||
330 | void mcf_disableall(void) | |
331 | { | |
332 | *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff; | |
333 | *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff; | |
334 | } | |
335 | ||
336 | /***************************************************************************/ | |
337 | ||
338 | void mcf_autovector(unsigned int vec) | |
339 | { | |
340 | /* Everything is auto-vectored on the 5272 */ | |
341 | } | |
342 | ||
343 | /***************************************************************************/ | |
344 | ||
188a9a48 SB |
345 | #ifdef CONFIG_WILDFIRE |
346 | void wildfire_halt(void) | |
347 | { | |
348 | writeb(0, 0x30000007); | |
349 | writeb(0x2, 0x30000007); | |
350 | } | |
351 | #endif | |
352 | ||
353 | #ifdef CONFIG_WILDFIREMOD | |
354 | void wildfiremod_halt(void) | |
355 | { | |
356 | printk(KERN_INFO "WildFireMod hibernating...\n"); | |
357 | ||
358 | /* Set portE.5 to Digital IO */ | |
359 | MCF5282_GPIO_PEPAR &= ~(1 << (5 * 2)); | |
360 | ||
361 | /* Make portE.5 an output */ | |
362 | MCF5282_GPIO_DDRE |= (1 << 5); | |
363 | ||
364 | /* Now toggle portE.5 from low to high */ | |
365 | MCF5282_GPIO_PORTE &= ~(1 << 5); | |
366 | MCF5282_GPIO_PORTE |= (1 << 5); | |
367 | ||
368 | printk(KERN_EMERG "Failed to hibernate. Halting!\n"); | |
369 | } | |
370 | #endif | |
371 | ||
eb49e907 | 372 | void __init config_BSP(char *commandp, int size) |
1da177e4 LT |
373 | { |
374 | mcf_disableall(); | |
188a9a48 SB |
375 | |
376 | #ifdef CONFIG_WILDFIRE | |
377 | mach_halt = wildfire_halt; | |
378 | #endif | |
379 | #ifdef CONFIG_WILDFIREMOD | |
380 | mach_halt = wildfiremod_halt; | |
381 | #endif | |
1da177e4 LT |
382 | } |
383 | ||
384 | /***************************************************************************/ | |
eb49e907 GU |
385 | |
386 | static int __init init_BSP(void) | |
387 | { | |
388 | m528x_uarts_init(); | |
389 | platform_add_devices(m528x_devices, ARRAY_SIZE(m528x_devices)); | |
390 | return 0; | |
391 | } | |
392 | ||
393 | arch_initcall(init_BSP); | |
394 | ||
395 | /***************************************************************************/ |