• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * arch/arm/mach-ixp4xx/common.c
3  *
4  * Generic code shared across all IXP4XX platforms
5  *
6  * Maintainer: Deepak Saxena <dsaxena@plexity.net>
7  *
8  * Copyright 2002 (c) Intel Corporation
9  * Copyright 2003-2004 (c) MontaVista, Software, Inc.
10  *
11  * This file is licensed under  the terms of the GNU General Public
12  * License version 2. This program is licensed "as is" without any
13  * warranty of any kind, whether express or implied.
14  */
15 
16 #include <linux/kernel.h>
17 #include <linux/mm.h>
18 #include <linux/init.h>
19 #include <linux/serial.h>
20 #include <linux/tty.h>
21 #include <linux/platform_device.h>
22 #include <linux/serial_core.h>
23 #include <linux/interrupt.h>
24 #include <linux/bitops.h>
25 #include <linux/io.h>
26 #include <linux/export.h>
27 #include <linux/cpu.h>
28 #include <linux/pci.h>
29 #include <linux/sched_clock.h>
30 #include <linux/irqchip/irq-ixp4xx.h>
31 #include <linux/platform_data/timer-ixp4xx.h>
32 #include <linux/dma-map-ops.h>
33 #include <mach/udc.h>
34 #include <mach/hardware.h>
35 #include <mach/io.h>
36 #include <linux/uaccess.h>
37 #include <asm/page.h>
38 #include <asm/exception.h>
39 #include <asm/irq.h>
40 #include <asm/system_misc.h>
41 #include <asm/mach/map.h>
42 #include <asm/mach/irq.h>
43 #include <asm/mach/time.h>
44 
45 #include "irqs.h"
46 
47 #define IXP4XX_TIMER_FREQ 66666000
48 
49 /*************************************************************************
50  * IXP4xx chipset I/O mapping
51  *************************************************************************/
52 static struct map_desc ixp4xx_io_desc[] __initdata = {
53 	{	/* UART, Interrupt ctrl, GPIO, timers, NPEs, MACs, USB .... */
54 		.virtual	= (unsigned long)IXP4XX_PERIPHERAL_BASE_VIRT,
55 		.pfn		= __phys_to_pfn(IXP4XX_PERIPHERAL_BASE_PHYS),
56 		.length		= IXP4XX_PERIPHERAL_REGION_SIZE,
57 		.type		= MT_DEVICE
58 	}, {	/* Expansion Bus Config Registers */
59 		.virtual	= (unsigned long)IXP4XX_EXP_CFG_BASE_VIRT,
60 		.pfn		= __phys_to_pfn(IXP4XX_EXP_CFG_BASE_PHYS),
61 		.length		= IXP4XX_EXP_CFG_REGION_SIZE,
62 		.type		= MT_DEVICE
63 	}, {	/* PCI Registers */
64 		.virtual	= (unsigned long)IXP4XX_PCI_CFG_BASE_VIRT,
65 		.pfn		= __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS),
66 		.length		= IXP4XX_PCI_CFG_REGION_SIZE,
67 		.type		= MT_DEVICE
68 	},
69 };
70 
ixp4xx_map_io(void)71 void __init ixp4xx_map_io(void)
72 {
73   	iotable_init(ixp4xx_io_desc, ARRAY_SIZE(ixp4xx_io_desc));
74 }
75 
ixp4xx_init_irq(void)76 void __init ixp4xx_init_irq(void)
77 {
78 	/*
79 	 * ixp4xx does not implement the XScale PWRMODE register
80 	 * so it must not call cpu_do_idle().
81 	 */
82 	cpu_idle_poll_ctrl(true);
83 
84 	ixp4xx_irq_init(IXP4XX_INTC_BASE_PHYS,
85 			(cpu_is_ixp46x() || cpu_is_ixp43x()));
86 }
87 
ixp4xx_timer_init(void)88 void __init ixp4xx_timer_init(void)
89 {
90 	return ixp4xx_timer_setup(IXP4XX_TIMER_BASE_PHYS,
91 				  IRQ_IXP4XX_TIMER1,
92 				  IXP4XX_TIMER_FREQ);
93 }
94 
95 static struct pxa2xx_udc_mach_info ixp4xx_udc_info;
96 
ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info * info)97 void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info)
98 {
99 	memcpy(&ixp4xx_udc_info, info, sizeof *info);
100 }
101 
102 static struct resource ixp4xx_udc_resources[] = {
103 	[0] = {
104 		.start  = 0xc800b000,
105 		.end    = 0xc800bfff,
106 		.flags  = IORESOURCE_MEM,
107 	},
108 	[1] = {
109 		.start  = IRQ_IXP4XX_USB,
110 		.end    = IRQ_IXP4XX_USB,
111 		.flags  = IORESOURCE_IRQ,
112 	},
113 };
114 
115 static struct resource ixp4xx_gpio_resource[] = {
116 	{
117 		.start = IXP4XX_GPIO_BASE_PHYS,
118 		.end = IXP4XX_GPIO_BASE_PHYS + 0xfff,
119 		.flags = IORESOURCE_MEM,
120 	},
121 };
122 
123 static struct platform_device ixp4xx_gpio_device = {
124 	.name           = "ixp4xx-gpio",
125 	.id             = -1,
126 	.dev = {
127 		.coherent_dma_mask      = DMA_BIT_MASK(32),
128 	},
129 	.resource = ixp4xx_gpio_resource,
130 	.num_resources  = ARRAY_SIZE(ixp4xx_gpio_resource),
131 };
132 
133 /*
134  * USB device controller. The IXP4xx uses the same controller as PXA25X,
135  * so we just use the same device.
136  */
137 static struct platform_device ixp4xx_udc_device = {
138 	.name           = "pxa25x-udc",
139 	.id             = -1,
140 	.num_resources  = 2,
141 	.resource       = ixp4xx_udc_resources,
142 	.dev            = {
143 		.platform_data = &ixp4xx_udc_info,
144 	},
145 };
146 
147 static struct resource ixp4xx_npe_resources[] = {
148 	{
149 		.start = IXP4XX_NPEA_BASE_PHYS,
150 		.end = IXP4XX_NPEA_BASE_PHYS + 0xfff,
151 		.flags = IORESOURCE_MEM,
152 	},
153 	{
154 		.start = IXP4XX_NPEB_BASE_PHYS,
155 		.end = IXP4XX_NPEB_BASE_PHYS + 0xfff,
156 		.flags = IORESOURCE_MEM,
157 	},
158 	{
159 		.start = IXP4XX_NPEC_BASE_PHYS,
160 		.end = IXP4XX_NPEC_BASE_PHYS + 0xfff,
161 		.flags = IORESOURCE_MEM,
162 	},
163 
164 };
165 
166 static struct platform_device ixp4xx_npe_device = {
167 	.name           = "ixp4xx-npe",
168 	.id             = -1,
169 	.num_resources  = ARRAY_SIZE(ixp4xx_npe_resources),
170 	.resource       = ixp4xx_npe_resources,
171 };
172 
173 static struct resource ixp4xx_qmgr_resources[] = {
174 	{
175 		.start = IXP4XX_QMGR_BASE_PHYS,
176 		.end = IXP4XX_QMGR_BASE_PHYS + 0x3fff,
177 		.flags = IORESOURCE_MEM,
178 	},
179 	{
180 		.start = IRQ_IXP4XX_QM1,
181 		.end = IRQ_IXP4XX_QM1,
182 		.flags = IORESOURCE_IRQ,
183 	},
184 	{
185 		.start = IRQ_IXP4XX_QM2,
186 		.end = IRQ_IXP4XX_QM2,
187 		.flags = IORESOURCE_IRQ,
188 	},
189 };
190 
191 static struct platform_device ixp4xx_qmgr_device = {
192 	.name           = "ixp4xx-qmgr",
193 	.id             = -1,
194 	.num_resources  = ARRAY_SIZE(ixp4xx_qmgr_resources),
195 	.resource       = ixp4xx_qmgr_resources,
196 };
197 
198 static struct platform_device *ixp4xx_devices[] __initdata = {
199 	&ixp4xx_npe_device,
200 	&ixp4xx_qmgr_device,
201 	&ixp4xx_gpio_device,
202 	&ixp4xx_udc_device,
203 };
204 
205 static struct resource ixp46x_i2c_resources[] = {
206 	[0] = {
207 		.start 	= 0xc8011000,
208 		.end	= 0xc801101c,
209 		.flags	= IORESOURCE_MEM,
210 	},
211 	[1] = {
212 		.start 	= IRQ_IXP4XX_I2C,
213 		.end	= IRQ_IXP4XX_I2C,
214 		.flags	= IORESOURCE_IRQ
215 	}
216 };
217 
218 /*
219  * I2C controller. The IXP46x uses the same block as the IOP3xx, so
220  * we just use the same device name.
221  */
222 static struct platform_device ixp46x_i2c_controller = {
223 	.name		= "IOP3xx-I2C",
224 	.id		= 0,
225 	.num_resources	= 2,
226 	.resource	= ixp46x_i2c_resources
227 };
228 
229 static struct platform_device *ixp46x_devices[] __initdata = {
230 	&ixp46x_i2c_controller
231 };
232 
233 unsigned long ixp4xx_exp_bus_size;
234 EXPORT_SYMBOL(ixp4xx_exp_bus_size);
235 
ixp4xx_sys_init(void)236 void __init ixp4xx_sys_init(void)
237 {
238 	ixp4xx_exp_bus_size = SZ_16M;
239 
240 	platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices));
241 
242 	if (cpu_is_ixp46x()) {
243 		int region;
244 
245 		platform_add_devices(ixp46x_devices,
246 				ARRAY_SIZE(ixp46x_devices));
247 
248 		for (region = 0; region < 7; region++) {
249 			if((*(IXP4XX_EXP_REG(0x4 * region)) & 0x200)) {
250 				ixp4xx_exp_bus_size = SZ_32M;
251 				break;
252 			}
253 		}
254 	}
255 
256 	printk("IXP4xx: Using %luMiB expansion bus window size\n",
257 			ixp4xx_exp_bus_size >> 20);
258 }
259 
260 unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
261 EXPORT_SYMBOL(ixp4xx_timer_freq);
262 
ixp4xx_restart(enum reboot_mode mode,const char * cmd)263 void ixp4xx_restart(enum reboot_mode mode, const char *cmd)
264 {
265 	if (mode == REBOOT_SOFT) {
266 		/* Jump into ROM at address 0 */
267 		soft_restart(0);
268 	} else {
269 		/* Use on-chip reset capability */
270 
271 		/* set the "key" register to enable access to
272 		 * "timer" and "enable" registers
273 		 */
274 		*IXP4XX_OSWK = IXP4XX_WDT_KEY;
275 
276 		/* write 0 to the timer register for an immediate reset */
277 		*IXP4XX_OSWT = 0;
278 
279 		*IXP4XX_OSWE = IXP4XX_WDT_RESET_ENABLE | IXP4XX_WDT_COUNT_ENABLE;
280 	}
281 }
282 
283 #ifdef CONFIG_PCI
ixp4xx_needs_bounce(struct device * dev,dma_addr_t dma_addr,size_t size)284 static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
285 {
286 	return (dma_addr + size) > SZ_64M;
287 }
288 
ixp4xx_platform_notify_remove(struct device * dev)289 static int ixp4xx_platform_notify_remove(struct device *dev)
290 {
291 	if (dev_is_pci(dev))
292 		dmabounce_unregister_dev(dev);
293 
294 	return 0;
295 }
296 #endif
297 
298 /*
299  * Setup DMA mask to 64MB on PCI devices and 4 GB on all other things.
300  */
ixp4xx_platform_notify(struct device * dev)301 static int ixp4xx_platform_notify(struct device *dev)
302 {
303 	dev->dma_mask = &dev->coherent_dma_mask;
304 
305 #ifdef CONFIG_PCI
306 	if (dev_is_pci(dev)) {
307 		dev->coherent_dma_mask = DMA_BIT_MASK(28); /* 64 MB */
308 		dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce);
309 		return 0;
310 	}
311 #endif
312 
313 	dev->coherent_dma_mask = DMA_BIT_MASK(32);
314 	return 0;
315 }
316 
dma_set_coherent_mask(struct device * dev,u64 mask)317 int dma_set_coherent_mask(struct device *dev, u64 mask)
318 {
319 	if (dev_is_pci(dev))
320 		mask &= DMA_BIT_MASK(28); /* 64 MB */
321 
322 	if ((mask & DMA_BIT_MASK(28)) == DMA_BIT_MASK(28)) {
323 		dev->coherent_dma_mask = mask;
324 		return 0;
325 	}
326 
327 	return -EIO;		/* device wanted sub-64MB mask */
328 }
329 EXPORT_SYMBOL(dma_set_coherent_mask);
330 
331 #ifdef CONFIG_IXP4XX_INDIRECT_PCI
332 /*
333  * In the case of using indirect PCI, we simply return the actual PCI
334  * address and our read/write implementation use that to drive the
335  * access registers. If something outside of PCI is ioremap'd, we
336  * fallback to the default.
337  */
338 
ixp4xx_ioremap_caller(phys_addr_t addr,size_t size,unsigned int mtype,void * caller)339 static void __iomem *ixp4xx_ioremap_caller(phys_addr_t addr, size_t size,
340 					   unsigned int mtype, void *caller)
341 {
342 	if (!is_pci_memory(addr))
343 		return __arm_ioremap_caller(addr, size, mtype, caller);
344 
345 	return (void __iomem *)addr;
346 }
347 
ixp4xx_iounmap(volatile void __iomem * addr)348 static void ixp4xx_iounmap(volatile void __iomem *addr)
349 {
350 	if (!is_pci_memory((__force u32)addr))
351 		__iounmap(addr);
352 }
353 #endif
354 
ixp4xx_init_early(void)355 void __init ixp4xx_init_early(void)
356 {
357 	platform_notify = ixp4xx_platform_notify;
358 #ifdef CONFIG_PCI
359 	platform_notify_remove = ixp4xx_platform_notify_remove;
360 #endif
361 #ifdef CONFIG_IXP4XX_INDIRECT_PCI
362 	arch_ioremap_caller = ixp4xx_ioremap_caller;
363 	arch_iounmap = ixp4xx_iounmap;
364 #endif
365 }
366