1/*
2 *  linux/arch/arm/mach-integrator/integrator_ap.c
3 *
4 *  Copyright (C) 2000-2003 Deep Blue Solutions Ltd
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, or
9 * (at your option) any later version.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20#include <linux/types.h>
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/list.h>
24#include <linux/platform_device.h>
25#include <linux/slab.h>
26#include <linux/string.h>
27#include <linux/sysdev.h>
28#include <linux/amba/bus.h>
29#include <linux/amba/kmi.h>
30
31#include <asm/hardware.h>
32#include <asm/io.h>
33#include <asm/irq.h>
34#include <asm/setup.h>
35#include <asm/param.h>		/* HZ */
36#include <asm/mach-types.h>
37
38#include <asm/arch/lm.h>
39
40#include <asm/mach/arch.h>
41#include <asm/mach/flash.h>
42#include <asm/mach/irq.h>
43#include <asm/mach/map.h>
44#include <asm/mach/time.h>
45
46#include "common.h"
47
48#define VA_IC_BASE	IO_ADDRESS(INTEGRATOR_IC_BASE)
49#define VA_SC_BASE	IO_ADDRESS(INTEGRATOR_SC_BASE)
50#define VA_EBI_BASE	IO_ADDRESS(INTEGRATOR_EBI_BASE)
51#define VA_CMIC_BASE	IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_IC_OFFSET
52
53/*
54 * Logical      Physical
55 * e8000000	40000000	PCI memory		PHYS_PCI_MEM_BASE	(max 512M)
56 * ec000000	61000000	PCI config space	PHYS_PCI_CONFIG_BASE	(max 16M)
57 * ed000000	62000000	PCI V3 regs		PHYS_PCI_V3_BASE	(max 64k)
58 * ee000000	60000000	PCI IO			PHYS_PCI_IO_BASE	(max 16M)
59 * ef000000			Cache flush
60 * f1000000	10000000	Core module registers
61 * f1100000	11000000	System controller registers
62 * f1200000	12000000	EBI registers
63 * f1300000	13000000	Counter/Timer
64 * f1400000	14000000	Interrupt controller
65 * f1600000	16000000	UART 0
66 * f1700000	17000000	UART 1
67 * f1a00000	1a000000	Debug LEDs
68 * f1b00000	1b000000	GPIO
69 */
70
71static struct map_desc ap_io_desc[] __initdata = {
72	{
73		.virtual	= IO_ADDRESS(INTEGRATOR_HDR_BASE),
74		.pfn		= __phys_to_pfn(INTEGRATOR_HDR_BASE),
75		.length		= SZ_4K,
76		.type		= MT_DEVICE
77	}, {
78		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE),
79		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE),
80		.length		= SZ_4K,
81		.type		= MT_DEVICE
82	}, {
83		.virtual	= IO_ADDRESS(INTEGRATOR_EBI_BASE),
84		.pfn		= __phys_to_pfn(INTEGRATOR_EBI_BASE),
85		.length		= SZ_4K,
86		.type		= MT_DEVICE
87	}, {
88		.virtual	= IO_ADDRESS(INTEGRATOR_CT_BASE),
89		.pfn		= __phys_to_pfn(INTEGRATOR_CT_BASE),
90		.length		= SZ_4K,
91		.type		= MT_DEVICE
92	}, {
93		.virtual	= IO_ADDRESS(INTEGRATOR_IC_BASE),
94		.pfn		= __phys_to_pfn(INTEGRATOR_IC_BASE),
95		.length		= SZ_4K,
96		.type		= MT_DEVICE
97	}, {
98		.virtual	= IO_ADDRESS(INTEGRATOR_UART0_BASE),
99		.pfn		= __phys_to_pfn(INTEGRATOR_UART0_BASE),
100		.length		= SZ_4K,
101		.type		= MT_DEVICE
102	}, {
103		.virtual	= IO_ADDRESS(INTEGRATOR_UART1_BASE),
104		.pfn		= __phys_to_pfn(INTEGRATOR_UART1_BASE),
105		.length		= SZ_4K,
106		.type		= MT_DEVICE
107	}, {
108		.virtual	= IO_ADDRESS(INTEGRATOR_DBG_BASE),
109		.pfn		= __phys_to_pfn(INTEGRATOR_DBG_BASE),
110		.length		= SZ_4K,
111		.type		= MT_DEVICE
112	}, {
113		.virtual	= IO_ADDRESS(INTEGRATOR_GPIO_BASE),
114		.pfn		= __phys_to_pfn(INTEGRATOR_GPIO_BASE),
115		.length		= SZ_4K,
116		.type		= MT_DEVICE
117	}, {
118		.virtual	= PCI_MEMORY_VADDR,
119		.pfn		= __phys_to_pfn(PHYS_PCI_MEM_BASE),
120		.length		= SZ_16M,
121		.type		= MT_DEVICE
122	}, {
123		.virtual	= PCI_CONFIG_VADDR,
124		.pfn		= __phys_to_pfn(PHYS_PCI_CONFIG_BASE),
125		.length		= SZ_16M,
126		.type		= MT_DEVICE
127	}, {
128		.virtual	= PCI_V3_VADDR,
129		.pfn		= __phys_to_pfn(PHYS_PCI_V3_BASE),
130		.length		= SZ_64K,
131		.type		= MT_DEVICE
132	}, {
133		.virtual	= PCI_IO_VADDR,
134		.pfn		= __phys_to_pfn(PHYS_PCI_IO_BASE),
135		.length		= SZ_64K,
136		.type		= MT_DEVICE
137	}
138};
139
140static void __init ap_map_io(void)
141{
142	iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
143}
144
145#define INTEGRATOR_SC_VALID_INT	0x003fffff
146
147static void sc_mask_irq(unsigned int irq)
148{
149	writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_CLEAR);
150}
151
152static void sc_unmask_irq(unsigned int irq)
153{
154	writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_SET);
155}
156
157static struct irq_chip sc_chip = {
158	.name	= "SC",
159	.ack	= sc_mask_irq,
160	.mask	= sc_mask_irq,
161	.unmask = sc_unmask_irq,
162};
163
164static void __init ap_init_irq(void)
165{
166	unsigned int i;
167
168	/* Disable all interrupts initially. */
169	/* Do the core module ones */
170	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
171
172	/* do the header card stuff next */
173	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
174	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
175
176	for (i = 0; i < NR_IRQS; i++) {
177		if (((1 << i) & INTEGRATOR_SC_VALID_INT) != 0) {
178			set_irq_chip(i, &sc_chip);
179			set_irq_handler(i, handle_level_irq);
180			set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
181		}
182	}
183}
184
185#ifdef CONFIG_PM
186static unsigned long ic_irq_enable;
187
188static int irq_suspend(struct sys_device *dev, pm_message_t state)
189{
190	ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
191	return 0;
192}
193
194static int irq_resume(struct sys_device *dev)
195{
196	/* disable all irq sources */
197	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
198	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
199	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
200
201	writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
202	return 0;
203}
204#else
205#define irq_suspend NULL
206#define irq_resume NULL
207#endif
208
209static struct sysdev_class irq_class = {
210	set_kset_name("irq"),
211	.suspend	= irq_suspend,
212	.resume		= irq_resume,
213};
214
215static struct sys_device irq_device = {
216	.id	= 0,
217	.cls	= &irq_class,
218};
219
220static int __init irq_init_sysfs(void)
221{
222	int ret = sysdev_class_register(&irq_class);
223	if (ret == 0)
224		ret = sysdev_register(&irq_device);
225	return ret;
226}
227
228device_initcall(irq_init_sysfs);
229
230/*
231 * Flash handling.
232 */
233#define SC_CTRLC (VA_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET)
234#define SC_CTRLS (VA_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET)
235#define EBI_CSR1 (VA_EBI_BASE + INTEGRATOR_EBI_CSR1_OFFSET)
236#define EBI_LOCK (VA_EBI_BASE + INTEGRATOR_EBI_LOCK_OFFSET)
237
238static int ap_flash_init(void)
239{
240	u32 tmp;
241
242	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
243
244	tmp = readl(EBI_CSR1) | INTEGRATOR_EBI_WRITE_ENABLE;
245	writel(tmp, EBI_CSR1);
246
247	if (!(readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE)) {
248		writel(0xa05f, EBI_LOCK);
249		writel(tmp, EBI_CSR1);
250		writel(0, EBI_LOCK);
251	}
252	return 0;
253}
254
255static void ap_flash_exit(void)
256{
257	u32 tmp;
258
259	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP, SC_CTRLC);
260
261	tmp = readl(EBI_CSR1) & ~INTEGRATOR_EBI_WRITE_ENABLE;
262	writel(tmp, EBI_CSR1);
263
264	if (readl(EBI_CSR1) & INTEGRATOR_EBI_WRITE_ENABLE) {
265		writel(0xa05f, EBI_LOCK);
266		writel(tmp, EBI_CSR1);
267		writel(0, EBI_LOCK);
268	}
269}
270
271static void ap_flash_set_vpp(int on)
272{
273	unsigned long reg = on ? SC_CTRLS : SC_CTRLC;
274
275	writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
276}
277
278static struct flash_platform_data ap_flash_data = {
279	.map_name	= "cfi_probe",
280	.width		= 4,
281	.init		= ap_flash_init,
282	.exit		= ap_flash_exit,
283	.set_vpp	= ap_flash_set_vpp,
284};
285
286static struct resource cfi_flash_resource = {
287	.start		= INTEGRATOR_FLASH_BASE,
288	.end		= INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
289	.flags		= IORESOURCE_MEM,
290};
291
292static struct platform_device cfi_flash_device = {
293	.name		= "armflash",
294	.id		= 0,
295	.dev		= {
296		.platform_data	= &ap_flash_data,
297	},
298	.num_resources	= 1,
299	.resource	= &cfi_flash_resource,
300};
301
302static void __init ap_init(void)
303{
304	unsigned long sc_dec;
305	int i;
306
307	platform_device_register(&cfi_flash_device);
308
309	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
310	for (i = 0; i < 4; i++) {
311		struct lm_device *lmdev;
312
313		if ((sc_dec & (16 << i)) == 0)
314			continue;
315
316		lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
317		if (!lmdev)
318			continue;
319
320		lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
321		lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
322		lmdev->resource.flags = IORESOURCE_MEM;
323		lmdev->irq = IRQ_AP_EXPINT0 + i;
324		lmdev->id = i;
325
326		lm_device_register(lmdev);
327	}
328}
329
330static void __init ap_init_timer(void)
331{
332	integrator_time_init(1000000 * TICKS_PER_uSEC / HZ, 0);
333}
334
335static struct sys_timer ap_timer = {
336	.init		= ap_init_timer,
337	.offset		= integrator_gettimeoffset,
338};
339
340MACHINE_START(INTEGRATOR, "ARM-Integrator")
341	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
342	.phys_io	= 0x16000000,
343	.io_pg_offst	= ((0xf1600000) >> 18) & 0xfffc,
344	.boot_params	= 0x00000100,
345	.map_io		= ap_map_io,
346	.init_irq	= ap_init_irq,
347	.timer		= &ap_timer,
348	.init_machine	= ap_init,
349MACHINE_END
350