1/*
2 * arch/arm/mach-pnx4008/core.c
3 *
4 * PNX4008 core startup code
5 *
6 * Authors: Vitaly Wool, Dmitry Chigirev,
7 * Grigory Tolstolytkin, Dmitry Pervushin <source@mvista.com>
8 *
9 * Based on reference code received from Philips:
10 * Copyright (C) 2003 Philips Semiconductors
11 *
12 * 2005 (c) MontaVista Software, Inc. This file is licensed under
13 * the terms of the GNU General Public License version 2. This program
14 * is licensed "as is" without any warranty of any kind, whether express
15 * or implied.
16 */
17
18#include <linux/kernel.h>
19#include <linux/types.h>
20#include <linux/mm.h>
21#include <linux/interrupt.h>
22#include <linux/list.h>
23#include <linux/init.h>
24#include <linux/ioport.h>
25#include <linux/serial_8250.h>
26#include <linux/device.h>
27#include <linux/spi/spi.h>
28
29#include <asm/hardware.h>
30#include <asm/io.h>
31#include <asm/setup.h>
32#include <asm/mach-types.h>
33#include <asm/pgtable.h>
34#include <asm/page.h>
35#include <asm/system.h>
36
37#include <asm/mach/arch.h>
38#include <asm/mach/map.h>
39#include <asm/mach/time.h>
40
41#include <asm/arch/irq.h>
42#include <asm/arch/clock.h>
43#include <asm/arch/dma.h>
44
45struct resource spipnx_0_resources[] = {
46	{
47		.start = PNX4008_SPI1_BASE,
48		.end = PNX4008_SPI1_BASE + SZ_4K,
49		.flags = IORESOURCE_MEM,
50	}, {
51		.start = PER_SPI1_REC_XMIT,
52		.flags = IORESOURCE_DMA,
53	}, {
54		.start = SPI1_INT,
55		.flags = IORESOURCE_IRQ,
56	}, {
57		.flags = 0,
58	},
59};
60
61struct resource spipnx_1_resources[] = {
62	{
63		.start = PNX4008_SPI2_BASE,
64		.end = PNX4008_SPI2_BASE + SZ_4K,
65		.flags = IORESOURCE_MEM,
66	}, {
67		.start = PER_SPI2_REC_XMIT,
68		.flags = IORESOURCE_DMA,
69	}, {
70		.start = SPI2_INT,
71		.flags = IORESOURCE_IRQ,
72	}, {
73		.flags = 0,
74	}
75};
76
77static struct spi_board_info spi_board_info[] __initdata = {
78	{
79		.modalias	= "m25p80",
80		.max_speed_hz	= 1000000,
81		.bus_num	= 1,
82		.chip_select	= 0,
83	},
84};
85
86static struct platform_device spipnx_1 = {
87	.name = "spipnx",
88	.id = 1,
89	.num_resources = ARRAY_SIZE(spipnx_0_resources),
90	.resource = spipnx_0_resources,
91	.dev = {
92		.coherent_dma_mask = 0xFFFFFFFF,
93		},
94};
95
96static struct platform_device spipnx_2 = {
97	.name = "spipnx",
98	.id = 2,
99	.num_resources = ARRAY_SIZE(spipnx_1_resources),
100	.resource = spipnx_1_resources,
101	.dev = {
102		.coherent_dma_mask = 0xFFFFFFFF,
103		},
104};
105
106static struct plat_serial8250_port platform_serial_ports[] = {
107	{
108		.membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART5_BASE)),
109		.mapbase = (unsigned long)PNX4008_UART5_BASE,
110		.irq = IIR5_INT,
111		.uartclk = PNX4008_UART_CLK,
112		.regshift = 2,
113		.iotype = UPIO_MEM,
114		.flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
115	},
116	{
117		.membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART3_BASE)),
118		.mapbase = (unsigned long)PNX4008_UART3_BASE,
119		.irq = IIR3_INT,
120		.uartclk = PNX4008_UART_CLK,
121		.regshift = 2,
122		.iotype = UPIO_MEM,
123		.flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
124	 },
125	{}
126};
127
128static struct platform_device serial_device = {
129	.name = "serial8250",
130	.id = PLAT8250_DEV_PLATFORM,
131	.dev = {
132		.platform_data = &platform_serial_ports,
133	},
134};
135
136static struct platform_device nand_flash_device = {
137	.name = "pnx4008-flash",
138	.id = -1,
139	.dev = {
140		.coherent_dma_mask = 0xFFFFFFFF,
141	},
142};
143
144/* The dmamask must be set for OHCI to work */
145static u64 ohci_dmamask = ~(u32) 0;
146
147static struct resource ohci_resources[] = {
148	{
149		.start = IO_ADDRESS(PNX4008_USB_CONFIG_BASE),
150		.end = IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x100),
151		.flags = IORESOURCE_MEM,
152	}, {
153		.start = USB_HOST_INT,
154		.flags = IORESOURCE_IRQ,
155	},
156};
157
158static struct platform_device ohci_device = {
159	.name = "pnx4008-usb-ohci",
160	.id = -1,
161	.dev = {
162		.dma_mask = &ohci_dmamask,
163		.coherent_dma_mask = 0xffffffff,
164		},
165	.num_resources = ARRAY_SIZE(ohci_resources),
166	.resource = ohci_resources,
167};
168
169static struct platform_device sdum_device = {
170	.name = "pnx4008-sdum",
171	.id = 0,
172	.dev = {
173		.coherent_dma_mask = 0xffffffff,
174	},
175};
176
177static struct platform_device rgbfb_device = {
178	.name = "pnx4008-rgbfb",
179	.id = 0,
180	.dev = {
181		.coherent_dma_mask = 0xffffffff,
182	}
183};
184
185struct resource watchdog_resources[] = {
186	{
187		.start = PNX4008_WDOG_BASE,
188		.end = PNX4008_WDOG_BASE + SZ_4K - 1,
189		.flags = IORESOURCE_MEM,
190	},
191};
192
193static struct platform_device watchdog_device = {
194	.name = "pnx4008-watchdog",
195	.id = -1,
196	.num_resources = ARRAY_SIZE(watchdog_resources),
197	.resource = watchdog_resources,
198};
199
200static struct platform_device *devices[] __initdata = {
201	&spipnx_1,
202	&spipnx_2,
203	&serial_device,
204	&ohci_device,
205	&nand_flash_device,
206	&sdum_device,
207	&rgbfb_device,
208	&watchdog_device,
209};
210
211
212extern void pnx4008_uart_init(void);
213
214static void __init pnx4008_init(void)
215{
216	/*disable all START interrupt sources,
217	   and clear all START interrupt flags */
218	__raw_writel(0, START_INT_ER_REG(SE_PIN_BASE_INT));
219	__raw_writel(0, START_INT_ER_REG(SE_INT_BASE_INT));
220	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
221	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
222
223	platform_add_devices(devices, ARRAY_SIZE(devices));
224	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
225	/* Switch on the UART clocks */
226	pnx4008_uart_init();
227}
228
229static struct map_desc pnx4008_io_desc[] __initdata = {
230	{
231		.virtual 	= IO_ADDRESS(PNX4008_IRAM_BASE),
232		.pfn 		= __phys_to_pfn(PNX4008_IRAM_BASE),
233		.length		= SZ_64K,
234		.type 		= MT_DEVICE,
235	}, {
236		.virtual 	= IO_ADDRESS(PNX4008_NDF_FLASH_BASE),
237		.pfn 		= __phys_to_pfn(PNX4008_NDF_FLASH_BASE),
238		.length		= SZ_1M - SZ_128K,
239		.type 		= MT_DEVICE,
240	}, {
241		.virtual 	= IO_ADDRESS(PNX4008_JPEG_CONFIG_BASE),
242		.pfn 		= __phys_to_pfn(PNX4008_JPEG_CONFIG_BASE),
243		.length		= SZ_128K * 3,
244		.type 		= MT_DEVICE,
245	}, {
246		.virtual 	= IO_ADDRESS(PNX4008_DMA_CONFIG_BASE),
247		.pfn 		= __phys_to_pfn(PNX4008_DMA_CONFIG_BASE),
248		.length		= SZ_1M,
249		.type 		= MT_DEVICE,
250	}, {
251		.virtual 	= IO_ADDRESS(PNX4008_AHB2FAB_BASE),
252		.pfn 		= __phys_to_pfn(PNX4008_AHB2FAB_BASE),
253		.length		= SZ_1M,
254		.type 		= MT_DEVICE,
255	},
256};
257
258void __init pnx4008_map_io(void)
259{
260	iotable_init(pnx4008_io_desc, ARRAY_SIZE(pnx4008_io_desc));
261}
262
263extern struct sys_timer pnx4008_timer;
264
265MACHINE_START(PNX4008, "Philips PNX4008")
266	/* Maintainer: MontaVista Software Inc. */
267	.phys_io 		= 0x40090000,
268	.io_pg_offst 		= (0xf4090000 >> 18) & 0xfffc,
269	.boot_params		= 0x80000100,
270	.map_io 		= pnx4008_map_io,
271	.init_irq 		= pnx4008_init_irq,
272	.init_machine 		= pnx4008_init,
273	.timer 			= &pnx4008_timer,
274MACHINE_END
275