add support for the AVR32 platform, namely the ATNGW100 board - joint work with wigyori
[openwrt/svn-archive/archive.git] / target / linux / avr32-2.6 / patches / 100-git_sync.patch
1 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atngw100/flash.c avr32-git/arch/avr32/boards/atngw100/flash.c
2 --- linux-2.6.21.3/arch/avr32/boards/atngw100/flash.c 1970-01-01 01:00:00.000000000 +0100
3 +++ avr32-git/arch/avr32/boards/atngw100/flash.c 2007-06-06 11:33:46.000000000 +0200
4 @@ -0,0 +1,95 @@
5 +/*
6 + * ATNGW100 board-specific flash initialization
7 + *
8 + * Copyright (C) 2005-2006 Atmel Corporation
9 + *
10 + * This program is free software; you can redistribute it and/or modify
11 + * it under the terms of the GNU General Public License version 2 as
12 + * published by the Free Software Foundation.
13 + */
14 +#include <linux/init.h>
15 +#include <linux/platform_device.h>
16 +#include <linux/mtd/mtd.h>
17 +#include <linux/mtd/partitions.h>
18 +#include <linux/mtd/physmap.h>
19 +
20 +#include <asm/arch/smc.h>
21 +
22 +static struct smc_config flash_config __initdata = {
23 + .ncs_read_setup = 0,
24 + .nrd_setup = 40,
25 + .ncs_write_setup = 0,
26 + .nwe_setup = 10,
27 +
28 + .ncs_read_pulse = 80,
29 + .nrd_pulse = 40,
30 + .ncs_write_pulse = 65,
31 + .nwe_pulse = 55,
32 +
33 + .read_cycle = 120,
34 + .write_cycle = 120,
35 +
36 + .bus_width = 2,
37 + .nrd_controlled = 1,
38 + .nwe_controlled = 1,
39 + .byte_write = 1,
40 +};
41 +
42 +static struct mtd_partition flash_parts[] = {
43 + {
44 + .name = "u-boot",
45 + .offset = 0x00000000,
46 + .size = 0x00020000, /* 128 KiB */
47 + .mask_flags = MTD_WRITEABLE,
48 + },
49 + {
50 + .name = "root",
51 + .offset = 0x00020000,
52 + .size = 0x007d0000,
53 + },
54 + {
55 + .name = "env",
56 + .offset = 0x007f0000,
57 + .size = 0x00010000,
58 + .mask_flags = MTD_WRITEABLE,
59 + },
60 +};
61 +
62 +static struct physmap_flash_data flash_data = {
63 + .width = 2,
64 + .nr_parts = ARRAY_SIZE(flash_parts),
65 + .parts = flash_parts,
66 +};
67 +
68 +static struct resource flash_resource = {
69 + .start = 0x00000000,
70 + .end = 0x007fffff,
71 + .flags = IORESOURCE_MEM,
72 +};
73 +
74 +static struct platform_device flash_device = {
75 + .name = "physmap-flash",
76 + .id = 0,
77 + .resource = &flash_resource,
78 + .num_resources = 1,
79 + .dev = {
80 + .platform_data = &flash_data,
81 + },
82 +};
83 +
84 +/* This needs to be called after the SMC has been initialized */
85 +static int __init atngw100_flash_init(void)
86 +{
87 + int ret;
88 +
89 + ret = smc_set_configuration(0, &flash_config);
90 + if (ret < 0) {
91 + printk(KERN_ERR "atngw100: failed to set NOR flash timing\n");
92 + return ret;
93 + }
94 +
95 + platform_device_register(&flash_device);
96 +
97 + return 0;
98 +}
99 +device_initcall(atngw100_flash_init);
100 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atngw100/Makefile avr32-git/arch/avr32/boards/atngw100/Makefile
101 --- linux-2.6.21.3/arch/avr32/boards/atngw100/Makefile 1970-01-01 01:00:00.000000000 +0100
102 +++ avr32-git/arch/avr32/boards/atngw100/Makefile 2007-06-06 11:33:46.000000000 +0200
103 @@ -0,0 +1 @@
104 +obj-y += setup.o flash.o
105 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atngw100/setup.c avr32-git/arch/avr32/boards/atngw100/setup.c
106 --- linux-2.6.21.3/arch/avr32/boards/atngw100/setup.c 1970-01-01 01:00:00.000000000 +0100
107 +++ avr32-git/arch/avr32/boards/atngw100/setup.c 2007-06-06 11:33:46.000000000 +0200
108 @@ -0,0 +1,131 @@
109 +/*
110 + * Board-specific setup code for the ATNGW100 Network Gateway
111 + *
112 + * Copyright (C) 2005-2006 Atmel Corporation
113 + *
114 + * This program is free software; you can redistribute it and/or modify
115 + * it under the terms of the GNU General Public License version 2 as
116 + * published by the Free Software Foundation.
117 + */
118 +#include <linux/clk.h>
119 +#include <linux/etherdevice.h>
120 +#include <linux/init.h>
121 +#include <linux/linkage.h>
122 +#include <linux/platform_device.h>
123 +#include <linux/types.h>
124 +#include <linux/spi/spi.h>
125 +
126 +#include <asm/io.h>
127 +#include <asm/setup.h>
128 +
129 +#include <asm/arch/at32ap7000.h>
130 +#include <asm/arch/board.h>
131 +#include <asm/arch/init.h>
132 +
133 +/* Initialized by bootloader-specific startup code. */
134 +struct tag *bootloader_tags __initdata;
135 +
136 +struct eth_addr {
137 + u8 addr[6];
138 +};
139 +static struct eth_addr __initdata hw_addr[2];
140 +static struct eth_platform_data __initdata eth_data[2];
141 +
142 +static struct spi_board_info spi0_board_info[] __initdata = {
143 + {
144 + .modalias = "mtd_dataflash",
145 + .max_speed_hz = 10000000,
146 + .chip_select = 0,
147 + },
148 +};
149 +
150 +static struct mci_platform_data __initdata mci0_data = {
151 + .detect_pin = GPIO_PIN_PC(25),
152 + .wp_pin = GPIO_PIN_PE(0),
153 +};
154 +
155 +/*
156 + * The next two functions should go away as the boot loader is
157 + * supposed to initialize the macb address registers with a valid
158 + * ethernet address. But we need to keep it around for a while until
159 + * we can be reasonably sure the boot loader does this.
160 + *
161 + * The phy_id is ignored as the driver will probe for it.
162 + */
163 +static int __init parse_tag_ethernet(struct tag *tag)
164 +{
165 + int i;
166 +
167 + i = tag->u.ethernet.mac_index;
168 + if (i < ARRAY_SIZE(hw_addr))
169 + memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
170 + sizeof(hw_addr[i].addr));
171 +
172 + return 0;
173 +}
174 +__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
175 +
176 +static void __init set_hw_addr(struct platform_device *pdev)
177 +{
178 + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
179 + const u8 *addr;
180 + void __iomem *regs;
181 + struct clk *pclk;
182 +
183 + if (!res)
184 + return;
185 + if (pdev->id >= ARRAY_SIZE(hw_addr))
186 + return;
187 +
188 + addr = hw_addr[pdev->id].addr;
189 + if (!is_valid_ether_addr(addr))
190 + return;
191 +
192 + /*
193 + * Since this is board-specific code, we'll cheat and use the
194 + * physical address directly as we happen to know that it's
195 + * the same as the virtual address.
196 + */
197 + regs = (void __iomem __force *)res->start;
198 + pclk = clk_get(&pdev->dev, "pclk");
199 + if (!pclk)
200 + return;
201 +
202 + clk_enable(pclk);
203 + __raw_writel((addr[3] << 24) | (addr[2] << 16)
204 + | (addr[1] << 8) | addr[0], regs + 0x98);
205 + __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c);
206 + clk_disable(pclk);
207 + clk_put(pclk);
208 +}
209 +
210 +struct platform_device *at32_usart_map[1];
211 +unsigned int at32_nr_usarts = 1;
212 +
213 +void __init setup_board(void)
214 +{
215 + at32_map_usart(1, 0); /* USART 1: /dev/ttyS0, DB9 */
216 + at32_setup_serial_console(0);
217 +}
218 +
219 +static int __init atngw100_init(void)
220 +{
221 + /*
222 + * ATNGW100 uses 16-bit SDRAM interface, so we don't need to
223 + * reserve any pins for it.
224 + */
225 +
226 + at32_add_system_devices();
227 +
228 + at32_add_device_usart(0);
229 +
230 + set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
231 + set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
232 +
233 + at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
234 + at32_add_device_mci(0, &mci0_data);
235 + at32_add_device_usba(0);
236 +
237 + return 0;
238 +}
239 +postcore_initcall(atngw100_init);
240 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atstk1000/atstk1000.h avr32-git/arch/avr32/boards/atstk1000/atstk1000.h
241 --- linux-2.6.21.3/arch/avr32/boards/atstk1000/atstk1000.h 1970-01-01 01:00:00.000000000 +0100
242 +++ avr32-git/arch/avr32/boards/atstk1000/atstk1000.h 2007-06-06 11:33:46.000000000 +0200
243 @@ -0,0 +1,15 @@
244 +/*
245 + * ATSTK1000 setup code: Daughterboard interface
246 + *
247 + * Copyright (C) 2007 Atmel Corporation
248 + *
249 + * This program is free software; you can redistribute it and/or modify
250 + * it under the terms of the GNU General Public License version 2 as
251 + * published by the Free Software Foundation.
252 + */
253 +#ifndef __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H
254 +#define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H
255 +
256 +extern struct atmel_lcdfb_info atstk1000_lcdc_data;
257 +
258 +#endif /* __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H */
259 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atstk1000/atstk1002.c avr32-git/arch/avr32/boards/atstk1000/atstk1002.c
260 --- linux-2.6.21.3/arch/avr32/boards/atstk1000/atstk1002.c 2007-05-24 23:22:47.000000000 +0200
261 +++ avr32-git/arch/avr32/boards/atstk1000/atstk1002.c 2007-06-06 11:33:46.000000000 +0200
262 @@ -16,6 +16,8 @@
263 #include <linux/types.h>
264 #include <linux/spi/spi.h>
265
266 +#include <video/atmel_lcdc.h>
267 +
268 #include <asm/io.h>
269 #include <asm/setup.h>
270 #include <asm/arch/at32ap7000.h>
271 @@ -23,6 +25,7 @@
272 #include <asm/arch/init.h>
273 #include <asm/arch/portmux.h>
274
275 +#include "atstk1000.h"
276
277 #define SW2_DEFAULT /* MMCI and UART_A available */
278
279 @@ -31,9 +34,7 @@
280 };
281
282 static struct eth_addr __initdata hw_addr[2];
283 -
284 static struct eth_platform_data __initdata eth_data[2];
285 -extern struct lcdc_platform_data atstk1000_fb0_data;
286
287 static struct spi_board_info spi0_board_info[] __initdata = {
288 {
289 @@ -41,9 +42,15 @@
290 .modalias = "ltv350qv",
291 .max_speed_hz = 16000000,
292 .chip_select = 1,
293 + .mode = SPI_MODE_3,
294 },
295 };
296
297 +static struct mci_platform_data __initdata mci0_data = {
298 + .detect_pin = GPIO_PIN_NONE,
299 + .wp_pin = GPIO_PIN_NONE,
300 +};
301 +
302 /*
303 * The next two functions should go away as the boot loader is
304 * supposed to initialize the macb address registers with a valid
305 @@ -148,7 +155,12 @@
306 set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
307
308 at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info));
309 - at32_add_device_lcdc(0, &atstk1000_fb0_data);
310 + at32_add_device_twi(0);
311 + at32_add_device_mci(0, &mci0_data);
312 + at32_add_device_lcdc(0, &atstk1000_lcdc_data,
313 + fbmem_start, fbmem_size);
314 + at32_add_device_usba(0);
315 + at32_add_device_abdac(0);
316
317 return 0;
318 }
319 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/boards/atstk1000/setup.c avr32-git/arch/avr32/boards/atstk1000/setup.c
320 --- linux-2.6.21.3/arch/avr32/boards/atstk1000/setup.c 2007-05-24 23:22:47.000000000 +0200
321 +++ avr32-git/arch/avr32/boards/atstk1000/setup.c 2007-06-06 11:33:46.000000000 +0200
322 @@ -8,43 +8,56 @@
323 * published by the Free Software Foundation.
324 */
325 #include <linux/bootmem.h>
326 +#include <linux/fb.h>
327 #include <linux/init.h>
328 #include <linux/types.h>
329 #include <linux/linkage.h>
330
331 -#include <asm/setup.h>
332 +#include <video/atmel_lcdc.h>
333
334 +#include <asm/setup.h>
335 #include <asm/arch/board.h>
336
337 +#include "atstk1000.h"
338 +
339 /* Initialized by bootloader-specific startup code. */
340 struct tag *bootloader_tags __initdata;
341
342 -struct lcdc_platform_data __initdata atstk1000_fb0_data;
343 -
344 -void __init board_setup_fbmem(unsigned long fbmem_start,
345 - unsigned long fbmem_size)
346 -{
347 - if (!fbmem_size)
348 - return;
349 -
350 - if (!fbmem_start) {
351 - void *fbmem;
352 -
353 - fbmem = alloc_bootmem_low_pages(fbmem_size);
354 - fbmem_start = __pa(fbmem);
355 - } else {
356 - pg_data_t *pgdat;
357 -
358 - for_each_online_pgdat(pgdat) {
359 - if (fbmem_start >= pgdat->bdata->node_boot_start
360 - && fbmem_start <= pgdat->bdata->node_low_pfn)
361 - reserve_bootmem_node(pgdat, fbmem_start,
362 - fbmem_size);
363 - }
364 - }
365 -
366 - printk("%luKiB framebuffer memory at address 0x%08lx\n",
367 - fbmem_size >> 10, fbmem_start);
368 - atstk1000_fb0_data.fbmem_start = fbmem_start;
369 - atstk1000_fb0_data.fbmem_size = fbmem_size;
370 -}
371 +static struct fb_videomode __initdata ltv350qv_modes[] = {
372 + {
373 + .name = "320x240 @ 75",
374 + .refresh = 75,
375 + .xres = 320, .yres = 240,
376 + .pixclock = KHZ2PICOS(6891),
377 +
378 + .left_margin = 17, .right_margin = 33,
379 + .upper_margin = 10, .lower_margin = 10,
380 + .hsync_len = 16, .vsync_len = 1,
381 +
382 + .sync = 0,
383 + .vmode = FB_VMODE_NONINTERLACED,
384 + },
385 +};
386 +
387 +static struct fb_monspecs __initdata atstk1000_default_monspecs = {
388 + .manufacturer = "SNG",
389 + .monitor = "LTV350QV",
390 + .modedb = ltv350qv_modes,
391 + .modedb_len = ARRAY_SIZE(ltv350qv_modes),
392 + .hfmin = 14820,
393 + .hfmax = 22230,
394 + .vfmin = 60,
395 + .vfmax = 90,
396 + .dclkmax = 30000000,
397 +};
398 +
399 +struct atmel_lcdfb_info __initdata atstk1000_lcdc_data = {
400 + .default_bpp = 24,
401 + .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
402 + .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
403 + | ATMEL_LCDC_INVCLK
404 + | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
405 + | ATMEL_LCDC_MEMOR_BIG),
406 + .default_monspecs = &atstk1000_default_monspecs,
407 + .guard_time = 2,
408 +};
409 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/drivers/dw-dmac.c avr32-git/arch/avr32/drivers/dw-dmac.c
410 --- linux-2.6.21.3/arch/avr32/drivers/dw-dmac.c 1970-01-01 01:00:00.000000000 +0100
411 +++ avr32-git/arch/avr32/drivers/dw-dmac.c 2007-06-06 11:33:46.000000000 +0200
412 @@ -0,0 +1,761 @@
413 +/*
414 + * Driver for the Synopsys DesignWare DMA Controller
415 + *
416 + * Copyright (C) 2005-2006 Atmel Corporation
417 + *
418 + * This program is free software; you can redistribute it and/or modify
419 + * it under the terms of the GNU General Public License version 2 as
420 + * published by the Free Software Foundation.
421 + */
422 +#include <linux/clk.h>
423 +#include <linux/device.h>
424 +#include <linux/dma-mapping.h>
425 +#include <linux/dmapool.h>
426 +#include <linux/init.h>
427 +#include <linux/interrupt.h>
428 +#include <linux/module.h>
429 +#include <linux/platform_device.h>
430 +
431 +#include <asm/dma-controller.h>
432 +#include <asm/io.h>
433 +
434 +#include "dw-dmac.h"
435 +
436 +#define DMAC_NR_CHANNELS 3
437 +#define DMAC_MAX_BLOCKSIZE 4095
438 +
439 +enum {
440 + CH_STATE_FREE = 0,
441 + CH_STATE_ALLOCATED,
442 + CH_STATE_BUSY,
443 +};
444 +
445 +struct dw_dma_lli {
446 + dma_addr_t sar;
447 + dma_addr_t dar;
448 + dma_addr_t llp;
449 + u32 ctllo;
450 + u32 ctlhi;
451 + u32 sstat;
452 + u32 dstat;
453 +};
454 +
455 +struct dw_dma_block {
456 + struct dw_dma_lli *lli_vaddr;
457 + dma_addr_t lli_dma_addr;
458 +};
459 +
460 +struct dw_dma_channel {
461 + unsigned int state;
462 + int is_cyclic;
463 + struct dma_request_sg *req_sg;
464 + struct dma_request_cyclic *req_cyclic;
465 + unsigned int nr_blocks;
466 + int direction;
467 + struct dw_dma_block *block;
468 +};
469 +
470 +struct dw_dma_controller {
471 + spinlock_t lock;
472 + void * __iomem regs;
473 + struct dma_pool *lli_pool;
474 + struct clk *hclk;
475 + struct dma_controller dma;
476 + struct dw_dma_channel channel[DMAC_NR_CHANNELS];
477 +};
478 +#define to_dw_dmac(dmac) container_of(dmac, struct dw_dma_controller, dma)
479 +
480 +#define dmac_writel_hi(dmac, reg, value) \
481 + __raw_writel((value), (dmac)->regs + DW_DMAC_##reg + 4)
482 +#define dmac_readl_hi(dmac, reg) \
483 + __raw_readl((dmac)->regs + DW_DMAC_##reg + 4)
484 +#define dmac_writel_lo(dmac, reg, value) \
485 + __raw_writel((value), (dmac)->regs + DW_DMAC_##reg)
486 +#define dmac_readl_lo(dmac, reg) \
487 + __raw_readl((dmac)->regs + DW_DMAC_##reg)
488 +#define dmac_chan_writel_hi(dmac, chan, reg, value) \
489 + __raw_writel((value), ((dmac)->regs + 0x58 * (chan) \
490 + + DW_DMAC_CHAN_##reg + 4))
491 +#define dmac_chan_readl_hi(dmac, chan, reg) \
492 + __raw_readl((dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg + 4)
493 +#define dmac_chan_writel_lo(dmac, chan, reg, value) \
494 + __raw_writel((value), (dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg)
495 +#define dmac_chan_readl_lo(dmac, chan, reg) \
496 + __raw_readl((dmac)->regs + 0x58 * (chan) + DW_DMAC_CHAN_##reg)
497 +#define set_channel_bit(dmac, reg, chan) \
498 + dmac_writel_lo(dmac, reg, (1 << (chan)) | (1 << ((chan) + 8)))
499 +#define clear_channel_bit(dmac, reg, chan) \
500 + dmac_writel_lo(dmac, reg, (0 << (chan)) | (1 << ((chan) + 8)))
501 +
502 +static int dmac_alloc_channel(struct dma_controller *_dmac)
503 +{
504 + struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
505 + struct dw_dma_channel *chan;
506 + unsigned long flags;
507 + int i;
508 +
509 + spin_lock_irqsave(&dmac->lock, flags);
510 + for (i = 0; i < DMAC_NR_CHANNELS; i++)
511 + if (dmac->channel[i].state == CH_STATE_FREE)
512 + break;
513 +
514 + if (i < DMAC_NR_CHANNELS) {
515 + chan = &dmac->channel[i];
516 + chan->state = CH_STATE_ALLOCATED;
517 + } else {
518 + i = -EBUSY;
519 + }
520 +
521 + spin_unlock_irqrestore(&dmac->lock, flags);
522 +
523 + return i;
524 +}
525 +
526 +static void dmac_release_channel(struct dma_controller *_dmac, int channel)
527 +{
528 + struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
529 +
530 + BUG_ON(channel >= DMAC_NR_CHANNELS
531 + || dmac->channel[channel].state != CH_STATE_ALLOCATED);
532 +
533 + dmac->channel[channel].state = CH_STATE_FREE;
534 +}
535 +
536 +static struct dw_dma_block *allocate_blocks(struct dw_dma_controller *dmac,
537 + unsigned int nr_blocks)
538 +{
539 + struct dw_dma_block *block;
540 + void *p;
541 + unsigned int i;
542 +
543 + block = kmalloc(nr_blocks * sizeof(*block),
544 + GFP_KERNEL);
545 + if (unlikely(!block))
546 + return NULL;
547 +
548 + for (i = 0; i < nr_blocks; i++) {
549 + p = dma_pool_alloc(dmac->lli_pool, GFP_KERNEL,
550 + &block[i].lli_dma_addr);
551 + block[i].lli_vaddr = p;
552 + if (unlikely(!p))
553 + goto fail;
554 + }
555 +
556 + return block;
557 +
558 +fail:
559 + for (i = 0; i < nr_blocks; i++) {
560 + if (!block[i].lli_vaddr)
561 + break;
562 + dma_pool_free(dmac->lli_pool, block[i].lli_vaddr,
563 + block[i].lli_dma_addr);
564 + }
565 + kfree(block);
566 + return NULL;
567 +}
568 +
569 +static void cleanup_channel(struct dw_dma_controller *dmac,
570 + struct dw_dma_channel *chan)
571 +{
572 + unsigned int i;
573 +
574 + if (chan->nr_blocks > 1) {
575 + for (i = 0; i < chan->nr_blocks; i++)
576 + dma_pool_free(dmac->lli_pool, chan->block[i].lli_vaddr,
577 + chan->block[i].lli_dma_addr);
578 + kfree(chan->block);
579 + }
580 +
581 + chan->state = CH_STATE_ALLOCATED;
582 +}
583 +
584 +static int dmac_prepare_request_sg(struct dma_controller *_dmac,
585 + struct dma_request_sg *req)
586 +{
587 + struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
588 + struct dw_dma_channel *chan;
589 + unsigned long ctlhi, ctllo, cfghi, cfglo;
590 + unsigned long block_size;
591 + unsigned int nr_blocks;
592 + int ret, i, direction;
593 + unsigned long flags;
594 +
595 + spin_lock_irqsave(&dmac->lock, flags);
596 +
597 + ret = -EINVAL;
598 + if (req->req.channel >= DMAC_NR_CHANNELS
599 + || dmac->channel[req->req.channel].state != CH_STATE_ALLOCATED
600 + || req->block_size > DMAC_MAX_BLOCKSIZE) {
601 + spin_unlock_irqrestore(&dmac->lock, flags);
602 + return -EINVAL;
603 + }
604 +
605 + chan = &dmac->channel[req->req.channel];
606 + chan->state = CH_STATE_BUSY;
607 + chan->req_sg = req;
608 + chan->is_cyclic = 0;
609 +
610 + /*
611 + * We have marked the channel as busy, so no need to keep the
612 + * lock as long as we only touch the channel-specific
613 + * registers
614 + */
615 + spin_unlock_irqrestore(&dmac->lock, flags);
616 +
617 + /*
618 + * There may be limitations in the driver and/or the DMA
619 + * controller that prevents us from sending a whole
620 + * scatterlist item in one go. Taking this into account,
621 + * calculate the number of block transfers we need to set up.
622 + *
623 + * FIXME: Let the peripheral driver know about the maximum
624 + * block size we support. We really don't want to use a
625 + * different block size than what was suggested by the
626 + * peripheral.
627 + *
628 + * Each block will get its own Linked List Item (LLI) below.
629 + */
630 + block_size = req->block_size;
631 + nr_blocks = req->nr_blocks;
632 + pr_debug("block_size %lu, nr_blocks %u nr_sg = %u\n",
633 + block_size, nr_blocks, req->nr_sg);
634 +
635 + BUG_ON(nr_blocks == 0);
636 + chan->nr_blocks = nr_blocks;
637 +
638 + ret = -EINVAL;
639 + cfglo = cfghi = 0;
640 + switch (req->direction) {
641 + case DMA_DIR_MEM_TO_PERIPH:
642 + direction = DMA_TO_DEVICE;
643 + cfghi = req->periph_id << (43 - 32);
644 + break;
645 +
646 + case DMA_DIR_PERIPH_TO_MEM:
647 + direction = DMA_FROM_DEVICE;
648 + cfghi = req->periph_id << (39 - 32);
649 + break;
650 + default:
651 + goto out_unclaim_channel;
652 + }
653 +
654 + chan->direction = direction;
655 +
656 + dmac_chan_writel_hi(dmac, req->req.channel, CFG, cfghi);
657 + dmac_chan_writel_lo(dmac, req->req.channel, CFG, cfglo);
658 +
659 + ctlhi = block_size >> req->width;
660 + ctllo = ((req->direction << 20)
661 + // | (1 << 14) | (1 << 11) // source/dest burst trans len
662 + | (req->width << 4) | (req->width << 1)
663 + | (1 << 0)); // interrupt enable
664 +
665 + if (nr_blocks == 1) {
666 + /* Only one block: No need to use block chaining */
667 + if (direction == DMA_TO_DEVICE) {
668 + dmac_chan_writel_lo(dmac, req->req.channel, SAR,
669 + req->sg->dma_address);
670 + dmac_chan_writel_lo(dmac, req->req.channel, DAR,
671 + req->data_reg);
672 + ctllo |= 2 << 7; // no dst increment
673 + } else {
674 + dmac_chan_writel_lo(dmac, req->req.channel, SAR,
675 + req->data_reg);
676 + dmac_chan_writel_lo(dmac, req->req.channel, DAR,
677 + req->sg->dma_address);
678 + ctllo |= 2 << 9; // no src increment
679 + }
680 + dmac_chan_writel_lo(dmac, req->req.channel, CTL, ctllo);
681 + dmac_chan_writel_hi(dmac, req->req.channel, CTL, ctlhi);
682 + pr_debug("ctl hi:lo 0x%lx:%lx\n", ctlhi, ctllo);
683 + } else {
684 + struct dw_dma_lli *lli, *lli_prev = NULL;
685 + int j = 0, offset = 0;
686 +
687 + ret = -ENOMEM;
688 + chan->block = allocate_blocks(dmac, nr_blocks);
689 + if (!chan->block)
690 + goto out_unclaim_channel;
691 +
692 + if (direction == DMA_TO_DEVICE)
693 + ctllo |= 1 << 28 | 1 << 27 | 2 << 7;
694 + else
695 + ctllo |= 1 << 28 | 1 << 27 | 2 << 9;
696 +
697 + /*
698 + * Map scatterlist items to blocks. One scatterlist
699 + * item may need more than one block for the reasons
700 + * mentioned above.
701 + */
702 + for (i = 0; i < nr_blocks; i++) {
703 + lli = chan->block[i].lli_vaddr;
704 + if (lli_prev) {
705 + lli_prev->llp = chan->block[i].lli_dma_addr;
706 + pr_debug("lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n",
707 + i - 1, chan->block[i - 1].lli_vaddr,
708 + chan->block[i - 1].lli_dma_addr,
709 + lli_prev->sar, lli_prev->dar, lli_prev->llp,
710 + lli_prev->ctllo, lli_prev->ctlhi);
711 + }
712 + lli->llp = 0;
713 + lli->ctllo = ctllo;
714 + lli->ctlhi = ctlhi;
715 + if (direction == DMA_TO_DEVICE) {
716 + lli->sar = req->sg[j].dma_address + offset;
717 + lli->dar = req->data_reg;
718 + } else {
719 + lli->sar = req->data_reg;
720 + lli->dar = req->sg[j].dma_address + offset;
721 + }
722 + lli_prev = lli;
723 +
724 + offset += block_size;
725 + if (offset > req->sg[j].length) {
726 + j++;
727 + offset = 0;
728 + }
729 + }
730 +
731 + pr_debug("lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n",
732 + i - 1, chan->block[i - 1].lli_vaddr,
733 + chan->block[i - 1].lli_dma_addr, lli_prev->sar,
734 + lli_prev->dar, lli_prev->llp,
735 + lli_prev->ctllo, lli_prev->ctlhi);
736 +
737 + /*
738 + * SAR, DAR and CTL are initialized from the LLI. We
739 + * only have to enable the LLI bits in CTL.
740 + */
741 + dmac_chan_writel_hi(dmac, req->req.channel, CTL, 0);
742 + dmac_chan_writel_lo(dmac, req->req.channel, LLP,
743 + chan->block[0].lli_dma_addr);
744 + dmac_chan_writel_lo(dmac, req->req.channel, CTL, 1 << 28 | 1 << 27);
745 + }
746 +
747 + set_channel_bit(dmac, MASK_XFER, req->req.channel);
748 + set_channel_bit(dmac, MASK_ERROR, req->req.channel);
749 + if (req->req.block_complete)
750 + set_channel_bit(dmac, MASK_BLOCK, req->req.channel);
751 + else
752 + clear_channel_bit(dmac, MASK_BLOCK, req->req.channel);
753 +
754 + return 0;
755 +
756 +out_unclaim_channel:
757 + chan->state = CH_STATE_ALLOCATED;
758 + return ret;
759 +}
760 +
761 +static int dmac_prepare_request_cyclic(struct dma_controller *_dmac,
762 + struct dma_request_cyclic *req)
763 +{
764 + struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
765 + struct dw_dma_channel *chan;
766 + unsigned long ctlhi, ctllo, cfghi, cfglo;
767 + unsigned long block_size;
768 + int ret, i, direction;
769 + unsigned long flags;
770 +
771 + spin_lock_irqsave(&dmac->lock, flags);
772 +
773 + block_size = (req->buffer_size/req->periods) >> req->width;
774 +
775 + ret = -EINVAL;
776 + if (req->req.channel >= DMAC_NR_CHANNELS
777 + || dmac->channel[req->req.channel].state != CH_STATE_ALLOCATED
778 + || (req->periods == 0)
779 + || block_size > DMAC_MAX_BLOCKSIZE) {
780 + spin_unlock_irqrestore(&dmac->lock, flags);
781 + return -EINVAL;
782 + }
783 +
784 + chan = &dmac->channel[req->req.channel];
785 + chan->state = CH_STATE_BUSY;
786 + chan->is_cyclic = 1;
787 + chan->req_cyclic = req;
788 +
789 + /*
790 + * We have marked the channel as busy, so no need to keep the
791 + * lock as long as we only touch the channel-specific
792 + * registers
793 + */
794 + spin_unlock_irqrestore(&dmac->lock, flags);
795 +
796 + /*
797 + Setup
798 + */
799 + BUG_ON(req->buffer_size % req->periods);
800 + /* printk(KERN_INFO "block_size = %lu, periods = %u\n", block_size, req->periods); */
801 +
802 + chan->nr_blocks = req->periods;
803 +
804 + ret = -EINVAL;
805 + cfglo = cfghi = 0;
806 + switch (req->direction) {
807 + case DMA_DIR_MEM_TO_PERIPH:
808 + direction = DMA_TO_DEVICE;
809 + cfghi = req->periph_id << (43 - 32);
810 + break;
811 +
812 + case DMA_DIR_PERIPH_TO_MEM:
813 + direction = DMA_FROM_DEVICE;
814 + cfghi = req->periph_id << (39 - 32);
815 + break;
816 + default:
817 + goto out_unclaim_channel;
818 + }
819 +
820 + chan->direction = direction;
821 +
822 + dmac_chan_writel_hi(dmac, req->req.channel, CFG, cfghi);
823 + dmac_chan_writel_lo(dmac, req->req.channel, CFG, cfglo);
824 +
825 + ctlhi = block_size;
826 + ctllo = ((req->direction << 20)
827 + | (req->width << 4) | (req->width << 1)
828 + | (1 << 0)); // interrupt enable
829 +
830 + {
831 + struct dw_dma_lli *lli = NULL, *lli_prev = NULL;
832 +
833 + ret = -ENOMEM;
834 + chan->block = allocate_blocks(dmac, req->periods);
835 + if (!chan->block)
836 + goto out_unclaim_channel;
837 +
838 + if (direction == DMA_TO_DEVICE)
839 + ctllo |= 1 << 28 | 1 << 27 | 2 << 7;
840 + else
841 + ctllo |= 1 << 28 | 1 << 27 | 2 << 9;
842 +
843 + /*
844 + * Set up a linked list items where each period gets
845 + * an item. The linked list item for the last period
846 + * points back to the star of the buffer making a
847 + * cyclic buffer.
848 + */
849 + for (i = 0; i < req->periods; i++) {
850 + lli = chan->block[i].lli_vaddr;
851 + if (lli_prev) {
852 + lli_prev->llp = chan->block[i].lli_dma_addr;
853 + /* printk(KERN_INFO "lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n",
854 + i - 1, chan->block[i - 1].lli_vaddr,
855 + chan->block[i - 1].lli_dma_addr,
856 + lli_prev->sar, lli_prev->dar, lli_prev->llp,
857 + lli_prev->ctllo, lli_prev->ctlhi);*/
858 + }
859 + lli->llp = 0;
860 + lli->ctllo = ctllo;
861 + lli->ctlhi = ctlhi;
862 + if (direction == DMA_TO_DEVICE) {
863 + lli->sar = req->buffer_start + i*(block_size << req->width);
864 + lli->dar = req->data_reg;
865 + } else {
866 + lli->sar = req->data_reg;
867 + lli->dar = req->buffer_start + i*(block_size << req->width);
868 + }
869 + lli_prev = lli;
870 + }
871 + lli->llp = chan->block[0].lli_dma_addr;
872 +
873 + /*printk(KERN_INFO "lli[%d] (0x%p/0x%x): 0x%x 0x%x 0x%x 0x%x 0x%x\n",
874 + i - 1, chan->block[i - 1].lli_vaddr,
875 + chan->block[i - 1].lli_dma_addr, lli_prev->sar,
876 + lli_prev->dar, lli_prev->llp,
877 + lli_prev->ctllo, lli_prev->ctlhi); */
878 +
879 + /*
880 + * SAR, DAR and CTL are initialized from the LLI. We
881 + * only have to enable the LLI bits in CTL.
882 + */
883 + dmac_chan_writel_lo(dmac, req->req.channel, LLP,
884 + chan->block[0].lli_dma_addr);
885 + dmac_chan_writel_lo(dmac, req->req.channel, CTL, 1 << 28 | 1 << 27);
886 + }
887 +
888 + clear_channel_bit(dmac, MASK_XFER, req->req.channel);
889 + set_channel_bit(dmac, MASK_ERROR, req->req.channel);
890 + if (req->req.block_complete)
891 + set_channel_bit(dmac, MASK_BLOCK, req->req.channel);
892 + else
893 + clear_channel_bit(dmac, MASK_BLOCK, req->req.channel);
894 +
895 + return 0;
896 +
897 +out_unclaim_channel:
898 + chan->state = CH_STATE_ALLOCATED;
899 + return ret;
900 +}
901 +
902 +static int dmac_start_request(struct dma_controller *_dmac,
903 + unsigned int channel)
904 +{
905 + struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
906 +
907 + BUG_ON(channel >= DMAC_NR_CHANNELS);
908 +
909 + set_channel_bit(dmac, CH_EN, channel);
910 +
911 + return 0;
912 +}
913 +
914 +static dma_addr_t dmac_get_current_pos(struct dma_controller *_dmac,
915 + unsigned int channel)
916 +{
917 + struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
918 + struct dw_dma_channel *chan;
919 + dma_addr_t current_pos;
920 +
921 + BUG_ON(channel >= DMAC_NR_CHANNELS);
922 +
923 + chan = &dmac->channel[channel];
924 +
925 + switch (chan->direction) {
926 + case DMA_TO_DEVICE:
927 + current_pos = dmac_chan_readl_lo(dmac, channel, SAR);
928 + break;
929 + case DMA_FROM_DEVICE:
930 + current_pos = dmac_chan_readl_lo(dmac, channel, DAR);
931 + break;
932 + default:
933 + return 0;
934 + }
935 +
936 +
937 + if (!current_pos) {
938 + if (chan->is_cyclic) {
939 + current_pos = chan->req_cyclic->buffer_start;
940 + } else {
941 + current_pos = chan->req_sg->sg->dma_address;
942 + }
943 + }
944 +
945 + return current_pos;
946 +}
947 +
948 +
949 +static int dmac_stop_request(struct dma_controller *_dmac,
950 + unsigned int channel)
951 +{
952 + struct dw_dma_controller *dmac = to_dw_dmac(_dmac);
953 + struct dw_dma_channel *chan;
954 +
955 + BUG_ON(channel >= DMAC_NR_CHANNELS);
956 +
957 + chan = &dmac->channel[channel];
958 + pr_debug("stop: st%u s%08x d%08x l%08x ctl0x%08x:0x%08x\n",
959 + chan->state, dmac_chan_readl_lo(dmac, channel, SAR),
960 + dmac_chan_readl_lo(dmac, channel, DAR),
961 + dmac_chan_readl_lo(dmac, channel, LLP),
962 + dmac_chan_readl_hi(dmac, channel, CTL),
963 + dmac_chan_readl_lo(dmac, channel, CTL));
964 +
965 + if (chan->state == CH_STATE_BUSY) {
966 + clear_channel_bit(dmac, CH_EN, channel);
967 + cleanup_channel(dmac, &dmac->channel[channel]);
968 + }
969 +
970 + return 0;
971 +}
972 +
973 +
974 +static void dmac_block_complete(struct dw_dma_controller *dmac)
975 +{
976 + struct dw_dma_channel *chan;
977 + unsigned long status, chanid;
978 +
979 + status = dmac_readl_lo(dmac, STATUS_BLOCK);
980 +
981 + while (status) {
982 + struct dma_request *req;
983 + chanid = __ffs(status);
984 + chan = &dmac->channel[chanid];
985 +
986 + if (chan->is_cyclic) {
987 + BUG_ON(!chan->req_cyclic
988 + || !chan->req_cyclic->req.block_complete);
989 + req = &chan->req_cyclic->req;
990 + } else {
991 + BUG_ON(!chan->req_sg || !chan->req_sg->req.block_complete);
992 + req = &chan->req_sg->req;
993 + }
994 + dmac_writel_lo(dmac, CLEAR_BLOCK, 1 << chanid);
995 + req->block_complete(req);
996 + status = dmac_readl_lo(dmac, STATUS_BLOCK);
997 + }
998 +}
999 +
1000 +static void dmac_xfer_complete(struct dw_dma_controller *dmac)
1001 +{
1002 + struct dw_dma_channel *chan;
1003 + struct dma_request *req;
1004 + unsigned long status, chanid;
1005 +
1006 + status = dmac_readl_lo(dmac, STATUS_XFER);
1007 +
1008 + while (status) {
1009 + chanid = __ffs(status);
1010 + chan = &dmac->channel[chanid];
1011 +
1012 + dmac_writel_lo(dmac, CLEAR_XFER, 1 << chanid);
1013 +
1014 + req = &chan->req_sg->req;
1015 + BUG_ON(!req);
1016 + cleanup_channel(dmac, chan);
1017 + if (req->xfer_complete)
1018 + req->xfer_complete(req);
1019 +
1020 + status = dmac_readl_lo(dmac, STATUS_XFER);
1021 + }
1022 +}
1023 +
1024 +static void dmac_error(struct dw_dma_controller *dmac)
1025 +{
1026 + struct dw_dma_channel *chan;
1027 + unsigned long status, chanid;
1028 +
1029 + status = dmac_readl_lo(dmac, STATUS_ERROR);
1030 +
1031 + while (status) {
1032 + struct dma_request *req;
1033 +
1034 + chanid = __ffs(status);
1035 + chan = &dmac->channel[chanid];
1036 +
1037 + dmac_writel_lo(dmac, CLEAR_ERROR, 1 << chanid);
1038 + clear_channel_bit(dmac, CH_EN, chanid);
1039 +
1040 + if (chan->is_cyclic) {
1041 + BUG_ON(!chan->req_cyclic);
1042 + req = &chan->req_cyclic->req;
1043 + } else {
1044 + BUG_ON(!chan->req_sg);
1045 + req = &chan->req_sg->req;
1046 + }
1047 +
1048 + cleanup_channel(dmac, chan);
1049 + if (req->error)
1050 + req->error(req);
1051 +
1052 + status = dmac_readl_lo(dmac, STATUS_XFER);
1053 + }
1054 +}
1055 +
1056 +static irqreturn_t dmac_interrupt(int irq, void *dev_id)
1057 +{
1058 + struct dw_dma_controller *dmac = dev_id;
1059 + unsigned long status;
1060 + int ret = IRQ_NONE;
1061 +
1062 + spin_lock(&dmac->lock);
1063 +
1064 + status = dmac_readl_lo(dmac, STATUS_INT);
1065 +
1066 + while (status) {
1067 + ret = IRQ_HANDLED;
1068 + if (status & 0x10)
1069 + dmac_error(dmac);
1070 + if (status & 0x02)
1071 + dmac_block_complete(dmac);
1072 + if (status & 0x01)
1073 + dmac_xfer_complete(dmac);
1074 +
1075 + status = dmac_readl_lo(dmac, STATUS_INT);
1076 + }
1077 +
1078 + spin_unlock(&dmac->lock);
1079 + return ret;
1080 +}
1081 +
1082 +static int __devinit dmac_probe(struct platform_device *pdev)
1083 +{
1084 + struct dw_dma_controller *dmac;
1085 + struct resource *regs;
1086 + int ret;
1087 +
1088 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1089 + if (!regs)
1090 + return -ENXIO;
1091 +
1092 + dmac = kmalloc(sizeof(*dmac), GFP_KERNEL);
1093 + if (!dmac)
1094 + return -ENOMEM;
1095 + memset(dmac, 0, sizeof(*dmac));
1096 +
1097 + dmac->hclk = clk_get(&pdev->dev, "hclk");
1098 + if (IS_ERR(dmac->hclk)) {
1099 + ret = PTR_ERR(dmac->hclk);
1100 + goto out_free_dmac;
1101 + }
1102 + clk_enable(dmac->hclk);
1103 +
1104 + ret = -ENOMEM;
1105 + dmac->lli_pool = dma_pool_create("dmac", &pdev->dev,
1106 + sizeof(struct dw_dma_lli), 4, 0);
1107 + if (!dmac->lli_pool)
1108 + goto out_disable_clk;
1109 +
1110 + spin_lock_init(&dmac->lock);
1111 + dmac->dma.dev = &pdev->dev;
1112 + dmac->dma.alloc_channel = dmac_alloc_channel;
1113 + dmac->dma.release_channel = dmac_release_channel;
1114 + dmac->dma.prepare_request_sg = dmac_prepare_request_sg;
1115 + dmac->dma.prepare_request_cyclic = dmac_prepare_request_cyclic;
1116 + dmac->dma.start_request = dmac_start_request;
1117 + dmac->dma.stop_request = dmac_stop_request;
1118 + dmac->dma.get_current_pos = dmac_get_current_pos;
1119 +
1120 + dmac->regs = ioremap(regs->start, regs->end - regs->start + 1);
1121 + if (!dmac->regs)
1122 + goto out_free_pool;
1123 +
1124 + ret = request_irq(platform_get_irq(pdev, 0), dmac_interrupt,
1125 + SA_SAMPLE_RANDOM, pdev->name, dmac);
1126 + if (ret)
1127 + goto out_unmap_regs;
1128 +
1129 + /* Enable the DMA controller */
1130 + dmac_writel_lo(dmac, CFG, 1);
1131 +
1132 + register_dma_controller(&dmac->dma);
1133 +
1134 + printk(KERN_INFO
1135 + "dmac%d: DesignWare DMA controller at 0x%p irq %d\n",
1136 + dmac->dma.id, dmac->regs, platform_get_irq(pdev, 0));
1137 +
1138 + return 0;
1139 +
1140 +out_unmap_regs:
1141 + iounmap(dmac->regs);
1142 +out_free_pool:
1143 + dma_pool_destroy(dmac->lli_pool);
1144 +out_disable_clk:
1145 + clk_disable(dmac->hclk);
1146 + clk_put(dmac->hclk);
1147 +out_free_dmac:
1148 + kfree(dmac);
1149 + return ret;
1150 +}
1151 +
1152 +static struct platform_driver dmac_driver = {
1153 + .probe = dmac_probe,
1154 + .driver = {
1155 + .name = "dmaca",
1156 + },
1157 +};
1158 +
1159 +static int __init dmac_init(void)
1160 +{
1161 + return platform_driver_register(&dmac_driver);
1162 +}
1163 +subsys_initcall(dmac_init);
1164 +
1165 +static void __exit dmac_exit(void)
1166 +{
1167 + platform_driver_unregister(&dmac_driver);
1168 +}
1169 +module_exit(dmac_exit);
1170 +
1171 +MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver");
1172 +MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
1173 +MODULE_LICENSE("GPL");
1174 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/drivers/dw-dmac.h avr32-git/arch/avr32/drivers/dw-dmac.h
1175 --- linux-2.6.21.3/arch/avr32/drivers/dw-dmac.h 1970-01-01 01:00:00.000000000 +0100
1176 +++ avr32-git/arch/avr32/drivers/dw-dmac.h 2007-06-06 11:33:46.000000000 +0200
1177 @@ -0,0 +1,42 @@
1178 +/*
1179 + * Driver for the Synopsys DesignWare DMA Controller
1180 + *
1181 + * Copyright (C) 2005-2006 Atmel Corporation
1182 + *
1183 + * This program is free software; you can redistribute it and/or modify
1184 + * it under the terms of the GNU General Public License version 2 as
1185 + * published by the Free Software Foundation.
1186 + */
1187 +#ifndef __AVR32_DW_DMAC_H__
1188 +#define __AVR32_DW_DMAC_H__
1189 +
1190 +#define DW_DMAC_CFG 0x398
1191 +#define DW_DMAC_CH_EN 0x3a0
1192 +
1193 +#define DW_DMAC_STATUS_XFER 0x2e8
1194 +#define DW_DMAC_STATUS_BLOCK 0x2f0
1195 +#define DW_DMAC_STATUS_ERROR 0x308
1196 +
1197 +#define DW_DMAC_MASK_XFER 0x310
1198 +#define DW_DMAC_MASK_BLOCK 0x318
1199 +#define DW_DMAC_MASK_ERROR 0x330
1200 +
1201 +#define DW_DMAC_CLEAR_XFER 0x338
1202 +#define DW_DMAC_CLEAR_BLOCK 0x340
1203 +#define DW_DMAC_CLEAR_ERROR 0x358
1204 +
1205 +#define DW_DMAC_STATUS_INT 0x360
1206 +
1207 +#define DW_DMAC_CHAN_SAR 0x000
1208 +#define DW_DMAC_CHAN_DAR 0x008
1209 +#define DW_DMAC_CHAN_LLP 0x010
1210 +#define DW_DMAC_CHAN_CTL 0x018
1211 +#define DW_DMAC_CHAN_SSTAT 0x020
1212 +#define DW_DMAC_CHAN_DSTAT 0x028
1213 +#define DW_DMAC_CHAN_SSTATAR 0x030
1214 +#define DW_DMAC_CHAN_DSTATAR 0x038
1215 +#define DW_DMAC_CHAN_CFG 0x040
1216 +#define DW_DMAC_CHAN_SGR 0x048
1217 +#define DW_DMAC_CHAN_DSR 0x050
1218 +
1219 +#endif /* __AVR32_DW_DMAC_H__ */
1220 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/drivers/Makefile avr32-git/arch/avr32/drivers/Makefile
1221 --- linux-2.6.21.3/arch/avr32/drivers/Makefile 1970-01-01 01:00:00.000000000 +0100
1222 +++ avr32-git/arch/avr32/drivers/Makefile 2007-06-06 11:33:46.000000000 +0200
1223 @@ -0,0 +1 @@
1224 +obj-$(CONFIG_DW_DMAC) += dw-dmac.o
1225 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/Kconfig avr32-git/arch/avr32/Kconfig
1226 --- linux-2.6.21.3/arch/avr32/Kconfig 2007-05-24 23:22:47.000000000 +0200
1227 +++ avr32-git/arch/avr32/Kconfig 2007-06-06 11:33:46.000000000 +0200
1228 @@ -57,9 +57,6 @@
1229 bool
1230 default n
1231
1232 -config GENERIC_BUST_SPINLOCK
1233 - bool
1234 -
1235 config GENERIC_HWEIGHT
1236 bool
1237 default y
1238 @@ -68,6 +65,11 @@
1239 bool
1240 default y
1241
1242 +config GENERIC_BUG
1243 + bool
1244 + default y
1245 + depends on BUG
1246 +
1247 source "init/Kconfig"
1248
1249 menu "System Type and features"
1250 @@ -106,6 +108,9 @@
1251 config BOARD_ATSTK1000
1252 bool "ATSTK1000 evaluation board"
1253 select BOARD_ATSTK1002 if CPU_AT32AP7000
1254 +
1255 +config BOARD_ATNGW100
1256 + bool "ATNGW100 Network Gateway"
1257 endchoice
1258
1259 choice
1260 @@ -116,6 +121,8 @@
1261 bool "U-Boot (or similar) bootloader"
1262 endchoice
1263
1264 +source "arch/avr32/mach-at32ap/Kconfig"
1265 +
1266 config LOAD_ADDRESS
1267 hex
1268 default 0x10000000 if LOADER_U_BOOT=y && CPU_AT32AP7000=y
1269 @@ -164,6 +171,10 @@
1270 enabling Nexus-compliant debuggers to keep track of the PID of the
1271 currently executing task.
1272
1273 +config DW_DMAC
1274 + tristate "Synopsys DesignWare DMA Controller support"
1275 + default y if CPU_AT32AP7000
1276 +
1277 # FPU emulation goes here
1278
1279 source "kernel/Kconfig.hz"
1280 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/cpu.c avr32-git/arch/avr32/kernel/cpu.c
1281 --- linux-2.6.21.3/arch/avr32/kernel/cpu.c 2007-05-24 23:22:47.000000000 +0200
1282 +++ avr32-git/arch/avr32/kernel/cpu.c 2007-06-06 11:33:46.000000000 +0200
1283 @@ -209,16 +209,17 @@
1284 void __init setup_processor(void)
1285 {
1286 unsigned long config0, config1;
1287 + unsigned long features;
1288 unsigned cpu_id, cpu_rev, arch_id, arch_rev, mmu_type;
1289 unsigned tmp;
1290
1291 - config0 = sysreg_read(CONFIG0); /* 0x0000013e; */
1292 - config1 = sysreg_read(CONFIG1); /* 0x01f689a2; */
1293 - cpu_id = config0 >> 24;
1294 - cpu_rev = (config0 >> 16) & 0xff;
1295 - arch_id = (config0 >> 13) & 0x07;
1296 - arch_rev = (config0 >> 10) & 0x07;
1297 - mmu_type = (config0 >> 7) & 0x03;
1298 + config0 = sysreg_read(CONFIG0);
1299 + config1 = sysreg_read(CONFIG1);
1300 + cpu_id = SYSREG_BFEXT(PROCESSORID, config0);
1301 + cpu_rev = SYSREG_BFEXT(PROCESSORREVISION, config0);
1302 + arch_id = SYSREG_BFEXT(AT, config0);
1303 + arch_rev = SYSREG_BFEXT(AR, config0);
1304 + mmu_type = SYSREG_BFEXT(MMUT, config0);
1305
1306 boot_cpu_data.arch_type = arch_id;
1307 boot_cpu_data.cpu_type = cpu_id;
1308 @@ -226,16 +227,16 @@
1309 boot_cpu_data.cpu_revision = cpu_rev;
1310 boot_cpu_data.tlb_config = mmu_type;
1311
1312 - tmp = (config1 >> 13) & 0x07;
1313 + tmp = SYSREG_BFEXT(ILSZ, config1);
1314 if (tmp) {
1315 - boot_cpu_data.icache.ways = 1 << ((config1 >> 10) & 0x07);
1316 - boot_cpu_data.icache.sets = 1 << ((config1 >> 16) & 0x0f);
1317 + boot_cpu_data.icache.ways = 1 << SYSREG_BFEXT(IASS, config1);
1318 + boot_cpu_data.icache.sets = 1 << SYSREG_BFEXT(ISET, config1);
1319 boot_cpu_data.icache.linesz = 1 << (tmp + 1);
1320 }
1321 - tmp = (config1 >> 3) & 0x07;
1322 + tmp = SYSREG_BFEXT(DLSZ, config1);
1323 if (tmp) {
1324 - boot_cpu_data.dcache.ways = 1 << (config1 & 0x07);
1325 - boot_cpu_data.dcache.sets = 1 << ((config1 >> 6) & 0x0f);
1326 + boot_cpu_data.dcache.ways = 1 << SYSREG_BFEXT(DASS, config1);
1327 + boot_cpu_data.dcache.sets = 1 << SYSREG_BFEXT(DSET, config1);
1328 boot_cpu_data.dcache.linesz = 1 << (tmp + 1);
1329 }
1330
1331 @@ -250,16 +251,39 @@
1332 cpu_names[cpu_id], cpu_id, cpu_rev,
1333 arch_names[arch_id], arch_rev);
1334 printk ("CPU: MMU configuration: %s\n", mmu_types[mmu_type]);
1335 +
1336 printk ("CPU: features:");
1337 - if (config0 & (1 << 6))
1338 - printk(" fpu");
1339 - if (config0 & (1 << 5))
1340 - printk(" java");
1341 - if (config0 & (1 << 4))
1342 - printk(" perfctr");
1343 - if (config0 & (1 << 3))
1344 + features = 0;
1345 + if (config0 & SYSREG_BIT(CONFIG0_R)) {
1346 + features |= AVR32_FEATURE_RMW;
1347 + printk(" rmw");
1348 + }
1349 + if (config0 & SYSREG_BIT(CONFIG0_D)) {
1350 + features |= AVR32_FEATURE_DSP;
1351 + printk(" dsp");
1352 + }
1353 + if (config0 & SYSREG_BIT(CONFIG0_S)) {
1354 + features |= AVR32_FEATURE_SIMD;
1355 + printk(" simd");
1356 + }
1357 + if (config0 & SYSREG_BIT(CONFIG0_O)) {
1358 + features |= AVR32_FEATURE_OCD;
1359 printk(" ocd");
1360 + }
1361 + if (config0 & SYSREG_BIT(CONFIG0_P)) {
1362 + features |= AVR32_FEATURE_PCTR;
1363 + printk(" perfctr");
1364 + }
1365 + if (config0 & SYSREG_BIT(CONFIG0_J)) {
1366 + features |= AVR32_FEATURE_JAVA;
1367 + printk(" java");
1368 + }
1369 + if (config0 & SYSREG_BIT(CONFIG0_F)) {
1370 + features |= AVR32_FEATURE_FPU;
1371 + printk(" fpu");
1372 + }
1373 printk("\n");
1374 + boot_cpu_data.features = features;
1375 }
1376
1377 #ifdef CONFIG_PROC_FS
1378 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/dma-controller.c avr32-git/arch/avr32/kernel/dma-controller.c
1379 --- linux-2.6.21.3/arch/avr32/kernel/dma-controller.c 1970-01-01 01:00:00.000000000 +0100
1380 +++ avr32-git/arch/avr32/kernel/dma-controller.c 2007-06-06 11:33:46.000000000 +0200
1381 @@ -0,0 +1,34 @@
1382 +/*
1383 + * Preliminary DMA controller framework for AVR32
1384 + *
1385 + * Copyright (C) 2005-2006 Atmel Corporation
1386 + *
1387 + * This program is free software; you can redistribute it and/or modify
1388 + * it under the terms of the GNU General Public License version 2 as
1389 + * published by the Free Software Foundation.
1390 + */
1391 +#include <asm/dma-controller.h>
1392 +
1393 +static LIST_HEAD(controllers);
1394 +
1395 +int register_dma_controller(struct dma_controller *dmac)
1396 +{
1397 + static int next_id;
1398 +
1399 + dmac->id = next_id++;
1400 + list_add_tail(&dmac->list, &controllers);
1401 +
1402 + return 0;
1403 +}
1404 +EXPORT_SYMBOL(register_dma_controller);
1405 +
1406 +struct dma_controller *find_dma_controller(int id)
1407 +{
1408 + struct dma_controller *dmac;
1409 +
1410 + list_for_each_entry(dmac, &controllers, list)
1411 + if (dmac->id == id)
1412 + return dmac;
1413 + return NULL;
1414 +}
1415 +EXPORT_SYMBOL(find_dma_controller);
1416 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/entry-avr32b.S avr32-git/arch/avr32/kernel/entry-avr32b.S
1417 --- linux-2.6.21.3/arch/avr32/kernel/entry-avr32b.S 2007-05-24 23:22:47.000000000 +0200
1418 +++ avr32-git/arch/avr32/kernel/entry-avr32b.S 2007-06-06 11:33:46.000000000 +0200
1419 @@ -100,55 +100,49 @@
1420
1421 .global tlb_miss_common
1422 tlb_miss_common:
1423 - mfsr r0, SYSREG_PTBR
1424 - mfsr r1, SYSREG_TLBEAR
1425 + mfsr r0, SYSREG_TLBEAR
1426 + mfsr r1, SYSREG_PTBR
1427
1428 /* Is it the vmalloc space? */
1429 - bld r1, 31
1430 + bld r0, 31
1431 brcs handle_vmalloc_miss
1432
1433 /* First level lookup */
1434 pgtbl_lookup:
1435 - lsr r2, r1, PGDIR_SHIFT
1436 - ld.w r0, r0[r2 << 2]
1437 - bld r0, _PAGE_BIT_PRESENT
1438 + lsr r2, r0, PGDIR_SHIFT
1439 + ld.w r3, r1[r2 << 2]
1440 + bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT
1441 + bld r3, _PAGE_BIT_PRESENT
1442 brcc page_table_not_present
1443
1444 - /* TODO: Check access rights on page table if necessary */
1445 -
1446 /* Translate to virtual address in P1. */
1447 - andl r0, 0xf000
1448 - sbr r0, 31
1449 + andl r3, 0xf000
1450 + sbr r3, 31
1451
1452 /* Second level lookup */
1453 - lsl r1, (32 - PGDIR_SHIFT)
1454 - lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
1455 - add r2, r0, r1 << 2
1456 - ld.w r1, r2[0]
1457 - bld r1, _PAGE_BIT_PRESENT
1458 + ld.w r2, r3[r1 << 2]
1459 + mfsr r0, SYSREG_TLBARLO
1460 + bld r2, _PAGE_BIT_PRESENT
1461 brcc page_not_present
1462
1463 /* Mark the page as accessed */
1464 - sbr r1, _PAGE_BIT_ACCESSED
1465 - st.w r2[0], r1
1466 + sbr r2, _PAGE_BIT_ACCESSED
1467 + st.w r3[r1 << 2], r2
1468
1469 /* Drop software flags */
1470 - andl r1, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
1471 - mtsr SYSREG_TLBELO, r1
1472 + andl r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
1473 + mtsr SYSREG_TLBELO, r2
1474
1475 /* Figure out which entry we want to replace */
1476 - mfsr r0, SYSREG_TLBARLO
1477 + mfsr r1, SYSREG_MMUCR
1478 clz r2, r0
1479 brcc 1f
1480 - mov r1, -1 /* All entries have been accessed, */
1481 - mtsr SYSREG_TLBARLO, r1 /* so reset TLBAR */
1482 - mov r2, 0 /* and start at 0 */
1483 -1: mfsr r1, SYSREG_MMUCR
1484 - lsl r2, 14
1485 - andl r1, 0x3fff, COH
1486 - or r1, r2
1487 - mtsr SYSREG_MMUCR, r1
1488 + mov r3, -1 /* All entries have been accessed, */
1489 + mov r2, 0 /* so start at 0 */
1490 + mtsr SYSREG_TLBARLO, r3 /* and reset TLBAR */
1491
1492 +1: bfins r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE
1493 + mtsr SYSREG_MMUCR, r1
1494 tlbw
1495
1496 tlbmiss_restore
1497 @@ -156,8 +150,8 @@
1498
1499 handle_vmalloc_miss:
1500 /* Simply do the lookup in init's page table */
1501 - mov r0, lo(swapper_pg_dir)
1502 - orh r0, hi(swapper_pg_dir)
1503 + mov r1, lo(swapper_pg_dir)
1504 + orh r1, hi(swapper_pg_dir)
1505 rjmp pgtbl_lookup
1506
1507
1508 @@ -340,12 +334,34 @@
1509 do_nmi_ll:
1510 sub sp, 4
1511 stmts --sp, r0-lr
1512 - /* FIXME: Make sure RAR_NMI and RSR_NMI are pushed instead of *_EX */
1513 - rcall save_full_context_ex
1514 + mfsr r9, SYSREG_RSR_NMI
1515 + mfsr r8, SYSREG_RAR_NMI
1516 + bfextu r0, r9, MODE_SHIFT, 3
1517 + brne 2f
1518 +
1519 +1: pushm r8, r9 /* PC and SR */
1520 mfsr r12, SYSREG_ECR
1521 mov r11, sp
1522 rcall do_nmi
1523 - rjmp bad_return
1524 + popm r8-r9
1525 + mtsr SYSREG_RAR_NMI, r8
1526 + tst r0, r0
1527 + mtsr SYSREG_RSR_NMI, r9
1528 + brne 3f
1529 +
1530 + ldmts sp++, r0-lr
1531 + sub sp, -4 /* skip r12_orig */
1532 + rete
1533 +
1534 +2: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
1535 + stdsp sp[4], r10 /* replace saved SP */
1536 + rjmp 1b
1537 +
1538 +3: popm lr
1539 + sub sp, -4 /* skip sp */
1540 + popm r0-r12
1541 + sub sp, -4 /* skip r12_orig */
1542 + rete
1543
1544 handle_address_fault:
1545 sub sp, 4
1546 @@ -630,9 +646,12 @@
1547 rcall do_IRQ
1548
1549 lddsp r4, sp[REG_SR]
1550 - andh r4, (MODE_MASK >> 16), COH
1551 + bfextu r4, r4, SYSREG_M0_OFFSET, 3
1552 + cp.w r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET
1553 + breq 2f
1554 + cp.w r4, MODE_USER >> SYSREG_M0_OFFSET
1555 #ifdef CONFIG_PREEMPT
1556 - brne 2f
1557 + brne 3f
1558 #else
1559 brne 1f
1560 #endif
1561 @@ -649,9 +668,18 @@
1562 sub sp, -4 /* ignore r12_orig */
1563 rete
1564
1565 +2: get_thread_info r0
1566 + ld.w r1, r0[TI_flags]
1567 + bld r1, TIF_CPU_GOING_TO_SLEEP
1568 #ifdef CONFIG_PREEMPT
1569 -2:
1570 - get_thread_info r0
1571 + brcc 3f
1572 +#else
1573 + brcc 1b
1574 +#endif
1575 + sub r1, pc, . - cpu_idle_skip_sleep
1576 + stdsp sp[REG_PC], r1
1577 +#ifdef CONFIG_PREEMPT
1578 +3: get_thread_info r0
1579 ld.w r2, r0[TI_preempt_count]
1580 cp.w r2, 0
1581 brne 1b
1582 @@ -662,12 +690,32 @@
1583 bld r4, SYSREG_GM_OFFSET
1584 brcs 1b
1585 rcall preempt_schedule_irq
1586 - rjmp 1b
1587 #endif
1588 + rjmp 1b
1589 .endm
1590
1591 .section .irq.text,"ax",@progbits
1592
1593 +.global cpu_idle_sleep
1594 +cpu_idle_sleep:
1595 + mask_interrupts
1596 + get_thread_info r8
1597 + ld.w r9, r8[TI_flags]
1598 + bld r9, TIF_NEED_RESCHED
1599 + brcs cpu_idle_enable_int_and_exit
1600 + sbr r9, TIF_CPU_GOING_TO_SLEEP
1601 + st.w r8[TI_flags], r9
1602 + unmask_interrupts
1603 + sleep 0
1604 +cpu_idle_skip_sleep:
1605 + mask_interrupts
1606 + ld.w r9, r8[TI_flags]
1607 + cbr r9, TIF_CPU_GOING_TO_SLEEP
1608 + st.w r8[TI_flags], r9
1609 +cpu_idle_enable_int_and_exit:
1610 + unmask_interrupts
1611 + retal r12
1612 +
1613 .global irq_level0
1614 .global irq_level1
1615 .global irq_level2
1616 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/irq.c avr32-git/arch/avr32/kernel/irq.c
1617 --- linux-2.6.21.3/arch/avr32/kernel/irq.c 2007-05-24 23:22:47.000000000 +0200
1618 +++ avr32-git/arch/avr32/kernel/irq.c 2007-06-06 11:33:46.000000000 +0200
1619 @@ -7,15 +7,6 @@
1620 * This program is free software; you can redistribute it and/or modify
1621 * it under the terms of the GNU General Public License version 2 as
1622 * published by the Free Software Foundation.
1623 - *
1624 - * This file contains the code used by various IRQ handling routines:
1625 - * asking for different IRQ's should be done through these routines
1626 - * instead of just grabbing them. Thus setups with different IRQ numbers
1627 - * shouldn't result in any weird surprises, and installing new handlers
1628 - * should be easier.
1629 - *
1630 - * IRQ's are in fact implemented a bit like signal handlers for the kernel.
1631 - * Naturally it's not a 1:1 relation, but there are similarities.
1632 */
1633
1634 #include <linux/interrupt.h>
1635 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/kprobes.c avr32-git/arch/avr32/kernel/kprobes.c
1636 --- linux-2.6.21.3/arch/avr32/kernel/kprobes.c 2007-05-24 23:22:47.000000000 +0200
1637 +++ avr32-git/arch/avr32/kernel/kprobes.c 2007-06-06 11:33:46.000000000 +0200
1638 @@ -179,7 +179,7 @@
1639 return 1;
1640 }
1641
1642 -static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
1643 +int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
1644 {
1645 struct kprobe *cur = kprobe_running();
1646
1647 @@ -216,11 +216,6 @@
1648 if (post_kprobe_handler(args->regs))
1649 ret = NOTIFY_STOP;
1650 break;
1651 - case DIE_FAULT:
1652 - if (kprobe_running()
1653 - && kprobe_fault_handler(args->regs, args->trapnr))
1654 - ret = NOTIFY_STOP;
1655 - break;
1656 default:
1657 break;
1658 }
1659 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/Makefile avr32-git/arch/avr32/kernel/Makefile
1660 --- linux-2.6.21.3/arch/avr32/kernel/Makefile 2007-05-24 23:22:47.000000000 +0200
1661 +++ avr32-git/arch/avr32/kernel/Makefile 2007-06-06 11:33:46.000000000 +0200
1662 @@ -9,6 +9,7 @@
1663 obj-y += setup.o traps.o semaphore.o ptrace.o
1664 obj-y += signal.o sys_avr32.o process.o time.o
1665 obj-y += init_task.o switch_to.o cpu.o
1666 +obj-y += dma-controller.o
1667 obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o
1668 obj-$(CONFIG_KPROBES) += kprobes.o
1669
1670 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/module.c avr32-git/arch/avr32/kernel/module.c
1671 --- linux-2.6.21.3/arch/avr32/kernel/module.c 2007-05-24 23:22:47.000000000 +0200
1672 +++ avr32-git/arch/avr32/kernel/module.c 2007-06-06 11:33:46.000000000 +0200
1673 @@ -12,10 +12,11 @@
1674 * published by the Free Software Foundation.
1675 */
1676
1677 -#include <linux/moduleloader.h>
1678 -#include <linux/module.h>
1679 -#include <linux/kernel.h>
1680 +#include <linux/bug.h>
1681 #include <linux/elf.h>
1682 +#include <linux/kernel.h>
1683 +#include <linux/module.h>
1684 +#include <linux/moduleloader.h>
1685 #include <linux/vmalloc.h>
1686
1687 void *module_alloc(unsigned long size)
1688 @@ -315,10 +316,10 @@
1689 vfree(module->arch.syminfo);
1690 module->arch.syminfo = NULL;
1691
1692 - return 0;
1693 + return module_bug_finalize(hdr, sechdrs, module);
1694 }
1695
1696 void module_arch_cleanup(struct module *module)
1697 {
1698 -
1699 + module_bug_cleanup(module);
1700 }
1701 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/process.c avr32-git/arch/avr32/kernel/process.c
1702 --- linux-2.6.21.3/arch/avr32/kernel/process.c 2007-05-24 23:22:47.000000000 +0200
1703 +++ avr32-git/arch/avr32/kernel/process.c 2007-06-06 11:33:46.000000000 +0200
1704 @@ -11,6 +11,7 @@
1705 #include <linux/fs.h>
1706 #include <linux/ptrace.h>
1707 #include <linux/reboot.h>
1708 +#include <linux/uaccess.h>
1709 #include <linux/unistd.h>
1710
1711 #include <asm/sysreg.h>
1712 @@ -19,6 +20,8 @@
1713 void (*pm_power_off)(void) = NULL;
1714 EXPORT_SYMBOL(pm_power_off);
1715
1716 +extern void cpu_idle_sleep(void);
1717 +
1718 /*
1719 * This file handles the architecture-dependent parts of process handling..
1720 */
1721 @@ -27,9 +30,8 @@
1722 {
1723 /* endless idle loop with no priority at all */
1724 while (1) {
1725 - /* TODO: Enter sleep mode */
1726 while (!need_resched())
1727 - cpu_relax();
1728 + cpu_idle_sleep();
1729 preempt_enable_no_resched();
1730 schedule();
1731 preempt_disable();
1732 @@ -114,39 +116,178 @@
1733 /* do nothing */
1734 }
1735
1736 +static void dump_mem(const char *str, const char *log_lvl,
1737 + unsigned long bottom, unsigned long top)
1738 +{
1739 + unsigned long p;
1740 + int i;
1741 +
1742 + printk("%s%s(0x%08lx to 0x%08lx)\n", log_lvl, str, bottom, top);
1743 +
1744 + for (p = bottom & ~31; p < top; ) {
1745 + printk("%s%04lx: ", log_lvl, p & 0xffff);
1746 +
1747 + for (i = 0; i < 8; i++, p += 4) {
1748 + unsigned int val;
1749 +
1750 + if (p < bottom || p >= top)
1751 + printk(" ");
1752 + else {
1753 + if (__get_user(val, (unsigned int __user *)p)) {
1754 + printk("\n");
1755 + goto out;
1756 + }
1757 + printk("%08x ", val);
1758 + }
1759 + }
1760 + printk("\n");
1761 + }
1762 +
1763 +out:
1764 + return;
1765 +}
1766 +
1767 +static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p)
1768 +{
1769 + return (p > (unsigned long)tinfo)
1770 + && (p < (unsigned long)tinfo + THREAD_SIZE - 3);
1771 +}
1772 +
1773 +#ifdef CONFIG_FRAME_POINTER
1774 +static void show_trace_log_lvl(struct task_struct *tsk, unsigned long *sp,
1775 + struct pt_regs *regs, const char *log_lvl)
1776 +{
1777 + unsigned long lr, fp;
1778 + struct thread_info *tinfo;
1779 +
1780 + if (regs)
1781 + fp = regs->r7;
1782 + else if (tsk == current)
1783 + asm("mov %0, r7" : "=r"(fp));
1784 + else
1785 + fp = tsk->thread.cpu_context.r7;
1786 +
1787 + /*
1788 + * Walk the stack as long as the frame pointer (a) is within
1789 + * the kernel stack of the task, and (b) it doesn't move
1790 + * downwards.
1791 + */
1792 + tinfo = task_thread_info(tsk);
1793 + printk("%sCall trace:\n", log_lvl);
1794 + while (valid_stack_ptr(tinfo, fp)) {
1795 + unsigned long new_fp;
1796 +
1797 + lr = *(unsigned long *)fp;
1798 +#ifdef CONFIG_KALLSYMS
1799 + printk("%s [<%08lx>] ", log_lvl, lr);
1800 +#else
1801 + printk(" [<%08lx>] ", lr);
1802 +#endif
1803 + print_symbol("%s\n", lr);
1804 +
1805 + new_fp = *(unsigned long *)(fp + 4);
1806 + if (new_fp <= fp)
1807 + break;
1808 + fp = new_fp;
1809 + }
1810 + printk("\n");
1811 +}
1812 +#else
1813 +static void show_trace_log_lvl(struct task_struct *tsk, unsigned long *sp,
1814 + struct pt_regs *regs, const char *log_lvl)
1815 +{
1816 + unsigned long addr;
1817 +
1818 + printk("%sCall trace:\n", log_lvl);
1819 +
1820 + while (!kstack_end(sp)) {
1821 + addr = *sp++;
1822 + if (kernel_text_address(addr)) {
1823 +#ifdef CONFIG_KALLSYMS
1824 + printk("%s [<%08lx>] ", log_lvl, addr);
1825 +#else
1826 + printk(" [<%08lx>] ", addr);
1827 +#endif
1828 + print_symbol("%s\n", addr);
1829 + }
1830 + }
1831 + printk("\n");
1832 +}
1833 +#endif
1834 +
1835 +void show_stack_log_lvl(struct task_struct *tsk, unsigned long sp,
1836 + struct pt_regs *regs, const char *log_lvl)
1837 +{
1838 + struct thread_info *tinfo;
1839 +
1840 + if (sp == 0) {
1841 + if (tsk)
1842 + sp = tsk->thread.cpu_context.ksp;
1843 + else
1844 + sp = (unsigned long)&tinfo;
1845 + }
1846 + if (!tsk)
1847 + tsk = current;
1848 +
1849 + tinfo = task_thread_info(tsk);
1850 +
1851 + if (valid_stack_ptr(tinfo, sp)) {
1852 + dump_mem("Stack: ", log_lvl, sp,
1853 + THREAD_SIZE + (unsigned long)tinfo);
1854 + show_trace_log_lvl(tsk, (unsigned long *)sp, regs, log_lvl);
1855 + }
1856 +}
1857 +
1858 +void show_stack(struct task_struct *tsk, unsigned long *stack)
1859 +{
1860 + show_stack_log_lvl(tsk, (unsigned long)stack, NULL, "");
1861 +}
1862 +
1863 +void dump_stack(void)
1864 +{
1865 + unsigned long stack;
1866 +
1867 + show_trace_log_lvl(current, &stack, NULL, "");
1868 +}
1869 +EXPORT_SYMBOL(dump_stack);
1870 +
1871 static const char *cpu_modes[] = {
1872 "Application", "Supervisor", "Interrupt level 0", "Interrupt level 1",
1873 "Interrupt level 2", "Interrupt level 3", "Exception", "NMI"
1874 };
1875
1876 -void show_regs(struct pt_regs *regs)
1877 +void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl)
1878 {
1879 unsigned long sp = regs->sp;
1880 unsigned long lr = regs->lr;
1881 unsigned long mode = (regs->sr & MODE_MASK) >> MODE_SHIFT;
1882
1883 - if (!user_mode(regs))
1884 + if (!user_mode(regs)) {
1885 sp = (unsigned long)regs + FRAME_SIZE_FULL;
1886
1887 - print_symbol("PC is at %s\n", instruction_pointer(regs));
1888 - print_symbol("LR is at %s\n", lr);
1889 - printk("pc : [<%08lx>] lr : [<%08lx>] %s\n"
1890 - "sp : %08lx r12: %08lx r11: %08lx\n",
1891 - instruction_pointer(regs),
1892 - lr, print_tainted(), sp, regs->r12, regs->r11);
1893 - printk("r10: %08lx r9 : %08lx r8 : %08lx\n",
1894 - regs->r10, regs->r9, regs->r8);
1895 - printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
1896 - regs->r7, regs->r6, regs->r5, regs->r4);
1897 - printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
1898 - regs->r3, regs->r2, regs->r1, regs->r0);
1899 - printk("Flags: %c%c%c%c%c\n",
1900 + printk("%s", log_lvl);
1901 + print_symbol("PC is at %s\n", instruction_pointer(regs));
1902 + printk("%s", log_lvl);
1903 + print_symbol("LR is at %s\n", lr);
1904 + }
1905 +
1906 + printk("%spc : [<%08lx>] lr : [<%08lx>] %s\n"
1907 + "%ssp : %08lx r12: %08lx r11: %08lx\n",
1908 + log_lvl, instruction_pointer(regs), lr, print_tainted(),
1909 + log_lvl, sp, regs->r12, regs->r11);
1910 + printk("%sr10: %08lx r9 : %08lx r8 : %08lx\n",
1911 + log_lvl, regs->r10, regs->r9, regs->r8);
1912 + printk("%sr7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
1913 + log_lvl, regs->r7, regs->r6, regs->r5, regs->r4);
1914 + printk("%sr3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
1915 + log_lvl, regs->r3, regs->r2, regs->r1, regs->r0);
1916 + printk("%sFlags: %c%c%c%c%c\n", log_lvl,
1917 regs->sr & SR_Q ? 'Q' : 'q',
1918 regs->sr & SR_V ? 'V' : 'v',
1919 regs->sr & SR_N ? 'N' : 'n',
1920 regs->sr & SR_Z ? 'Z' : 'z',
1921 regs->sr & SR_C ? 'C' : 'c');
1922 - printk("Mode bits: %c%c%c%c%c%c%c%c%c\n",
1923 + printk("%sMode bits: %c%c%c%c%c%c%c%c%c\n", log_lvl,
1924 regs->sr & SR_H ? 'H' : 'h',
1925 regs->sr & SR_R ? 'R' : 'r',
1926 regs->sr & SR_J ? 'J' : 'j',
1927 @@ -156,9 +297,21 @@
1928 regs->sr & SR_I1M ? '1' : '.',
1929 regs->sr & SR_I0M ? '0' : '.',
1930 regs->sr & SR_GM ? 'G' : 'g');
1931 - printk("CPU Mode: %s\n", cpu_modes[mode]);
1932 + printk("%sCPU Mode: %s\n", log_lvl, cpu_modes[mode]);
1933 + printk("%sProcess: %s [%d] (task: %p thread: %p)\n",
1934 + log_lvl, current->comm, current->pid, current,
1935 + task_thread_info(current));
1936 +}
1937 +
1938 +void show_regs(struct pt_regs *regs)
1939 +{
1940 + unsigned long sp = regs->sp;
1941 +
1942 + if (!user_mode(regs))
1943 + sp = (unsigned long)regs + FRAME_SIZE_FULL;
1944
1945 - show_trace(NULL, (unsigned long *)sp, regs);
1946 + show_regs_log_lvl(regs, "");
1947 + show_trace_log_lvl(current, (unsigned long *)sp, regs, "");
1948 }
1949 EXPORT_SYMBOL(show_regs);
1950
1951 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/setup.c avr32-git/arch/avr32/kernel/setup.c
1952 --- linux-2.6.21.3/arch/avr32/kernel/setup.c 2007-05-24 23:22:47.000000000 +0200
1953 +++ avr32-git/arch/avr32/kernel/setup.c 2007-06-06 11:33:46.000000000 +0200
1954 @@ -8,12 +8,14 @@
1955
1956 #include <linux/clk.h>
1957 #include <linux/init.h>
1958 +#include <linux/initrd.h>
1959 #include <linux/sched.h>
1960 #include <linux/console.h>
1961 #include <linux/ioport.h>
1962 #include <linux/bootmem.h>
1963 #include <linux/fs.h>
1964 #include <linux/module.h>
1965 +#include <linux/pfn.h>
1966 #include <linux/root_dev.h>
1967 #include <linux/cpu.h>
1968 #include <linux/kernel.h>
1969 @@ -30,13 +32,6 @@
1970 extern int root_mountflags;
1971
1972 /*
1973 - * Bootloader-provided information about physical memory
1974 - */
1975 -struct tag_mem_range *mem_phys;
1976 -struct tag_mem_range *mem_reserved;
1977 -struct tag_mem_range *mem_ramdisk;
1978 -
1979 -/*
1980 * Initialize loops_per_jiffy as 5000000 (500MIPS).
1981 * Better make it too large than too small...
1982 */
1983 @@ -48,48 +43,193 @@
1984 static char __initdata command_line[COMMAND_LINE_SIZE];
1985
1986 /*
1987 - * Should be more than enough, but if you have a _really_ complex
1988 - * setup, you might need to increase the size of this...
1989 + * Standard memory resources
1990 */
1991 -static struct tag_mem_range __initdata mem_range_cache[32];
1992 -static unsigned mem_range_next_free;
1993 +static struct resource __initdata kernel_data = {
1994 + .name = "Kernel data",
1995 + .start = 0,
1996 + .end = 0,
1997 + .flags = IORESOURCE_MEM,
1998 +};
1999 +static struct resource __initdata kernel_code = {
2000 + .name = "Kernel code",
2001 + .start = 0,
2002 + .end = 0,
2003 + .flags = IORESOURCE_MEM,
2004 + .sibling = &kernel_data,
2005 +};
2006
2007 /*
2008 - * Standard memory resources
2009 + * Available system RAM and reserved regions as singly linked
2010 + * lists. These lists are traversed using the sibling pointer in
2011 + * struct resource and are kept sorted at all times.
2012 */
2013 -static struct resource mem_res[] = {
2014 - {
2015 - .name = "Kernel code",
2016 - .start = 0,
2017 - .end = 0,
2018 - .flags = IORESOURCE_MEM
2019 - },
2020 - {
2021 - .name = "Kernel data",
2022 - .start = 0,
2023 - .end = 0,
2024 - .flags = IORESOURCE_MEM,
2025 - },
2026 -};
2027 +static struct resource *__initdata system_ram;
2028 +static struct resource *__initdata reserved = &kernel_code;
2029 +
2030 +/*
2031 + * We need to allocate these before the bootmem allocator is up and
2032 + * running, so we need this "cache". 32 entries are probably enough
2033 + * for all but the most insanely complex systems.
2034 + */
2035 +static struct resource __initdata res_cache[32];
2036 +static unsigned int __initdata res_cache_next_free;
2037 +
2038 +static void __init resource_init(void)
2039 +{
2040 + struct resource *mem, *res;
2041 + struct resource *new;
2042 +
2043 + kernel_code.start = __pa(init_mm.start_code);
2044 +
2045 + for (mem = system_ram; mem; mem = mem->sibling) {
2046 + new = alloc_bootmem_low(sizeof(struct resource));
2047 + memcpy(new, mem, sizeof(struct resource));
2048 +
2049 + new->sibling = NULL;
2050 + if (request_resource(&iomem_resource, new))
2051 + printk(KERN_WARNING "Bad RAM resource %08x-%08x\n",
2052 + mem->start, mem->end);
2053 + }
2054 +
2055 + for (res = reserved; res; res = res->sibling) {
2056 + new = alloc_bootmem_low(sizeof(struct resource));
2057 + memcpy(new, res, sizeof(struct resource));
2058 +
2059 + new->sibling = NULL;
2060 + if (insert_resource(&iomem_resource, new))
2061 + printk(KERN_WARNING
2062 + "Bad reserved resource %s (%08x-%08x)\n",
2063 + res->name, res->start, res->end);
2064 + }
2065 +}
2066 +
2067 +static void __init
2068 +add_physical_memory(resource_size_t start, resource_size_t end)
2069 +{
2070 + struct resource *new, *next, **pprev;
2071 +
2072 + for (pprev = &system_ram, next = system_ram; next;
2073 + pprev = &next->sibling, next = next->sibling) {
2074 + if (end < next->start)
2075 + break;
2076 + if (start <= next->end) {
2077 + printk(KERN_WARNING
2078 + "Warning: Physical memory map is broken\n");
2079 + printk(KERN_WARNING
2080 + "Warning: %08x-%08x overlaps %08x-%08x\n",
2081 + start, end, next->start, next->end);
2082 + return;
2083 + }
2084 + }
2085 +
2086 + if (res_cache_next_free >= ARRAY_SIZE(res_cache)) {
2087 + printk(KERN_WARNING
2088 + "Warning: Failed to add physical memory %08x-%08x\n",
2089 + start, end);
2090 + return;
2091 + }
2092 +
2093 + new = &res_cache[res_cache_next_free++];
2094 + new->start = start;
2095 + new->end = end;
2096 + new->name = "System RAM";
2097 + new->flags = IORESOURCE_MEM;
2098 +
2099 + *pprev = new;
2100 +}
2101 +
2102 +static int __init
2103 +add_reserved_region(resource_size_t start, resource_size_t end,
2104 + const char *name)
2105 +{
2106 + struct resource *new, *next, **pprev;
2107 +
2108 + if (end < start)
2109 + return -EINVAL;
2110 +
2111 + if (res_cache_next_free >= ARRAY_SIZE(res_cache))
2112 + return -ENOMEM;
2113 +
2114 + for (pprev = &reserved, next = reserved; next;
2115 + pprev = &next->sibling, next = next->sibling) {
2116 + if (end < next->start)
2117 + break;
2118 + if (start <= next->end)
2119 + return -EBUSY;
2120 + }
2121 +
2122 + new = &res_cache[res_cache_next_free++];
2123 + new->start = start;
2124 + new->end = end;
2125 + new->name = name;
2126 + new->flags = IORESOURCE_MEM;
2127
2128 -#define kernel_code mem_res[0]
2129 -#define kernel_data mem_res[1]
2130 + *pprev = new;
2131 +
2132 + return 0;
2133 +}
2134 +
2135 +static unsigned long __init
2136 +find_free_region(const struct resource *mem, resource_size_t size,
2137 + resource_size_t align)
2138 +{
2139 + struct resource *res;
2140 + unsigned long target;
2141 +
2142 + target = ALIGN(mem->start, align);
2143 + for (res = reserved; res; res = res->sibling) {
2144 + if ((target + size) <= res->start)
2145 + break;
2146 + if (target <= res->end)
2147 + target = ALIGN(res->end + 1, align);
2148 + }
2149 +
2150 + if ((target + size) > (mem->end + 1))
2151 + return mem->end + 1;
2152 +
2153 + return target;
2154 +}
2155 +
2156 +static int __init
2157 +alloc_reserved_region(resource_size_t *start, resource_size_t size,
2158 + resource_size_t align, const char *name)
2159 +{
2160 + struct resource *mem;
2161 + resource_size_t target;
2162 + int ret;
2163 +
2164 + for (mem = system_ram; mem; mem = mem->sibling) {
2165 + target = find_free_region(mem, size, align);
2166 + if (target <= mem->end) {
2167 + ret = add_reserved_region(target, target + size - 1,
2168 + name);
2169 + if (!ret)
2170 + *start = target;
2171 + return ret;
2172 + }
2173 + }
2174 +
2175 + return -ENOMEM;
2176 +}
2177
2178 /*
2179 * Early framebuffer allocation. Works as follows:
2180 * - If fbmem_size is zero, nothing will be allocated or reserved.
2181 * - If fbmem_start is zero when setup_bootmem() is called,
2182 - * fbmem_size bytes will be allocated from the bootmem allocator.
2183 + * a block of fbmem_size bytes will be reserved before bootmem
2184 + * initialization. It will be aligned to the largest page size
2185 + * that fbmem_size is a multiple of.
2186 * - If fbmem_start is nonzero, an area of size fbmem_size will be
2187 - * reserved at the physical address fbmem_start if necessary. If
2188 - * the area isn't in a memory region known to the kernel, it will
2189 - * be left alone.
2190 + * reserved at the physical address fbmem_start if possible. If
2191 + * it collides with other reserved memory, a different block of
2192 + * same size will be allocated, just as if fbmem_start was zero.
2193 *
2194 * Board-specific code may use these variables to set up platform data
2195 * for the framebuffer driver if fbmem_size is nonzero.
2196 */
2197 -static unsigned long __initdata fbmem_start;
2198 -static unsigned long __initdata fbmem_size;
2199 +resource_size_t __initdata fbmem_start;
2200 +resource_size_t __initdata fbmem_size;
2201
2202 /*
2203 * "fbmem=xxx[kKmM]" allocates the specified amount of boot memory for
2204 @@ -103,48 +243,42 @@
2205 */
2206 static int __init early_parse_fbmem(char *p)
2207 {
2208 + int ret;
2209 + unsigned long align;
2210 +
2211 fbmem_size = memparse(p, &p);
2212 - if (*p == '@')
2213 + if (*p == '@') {
2214 fbmem_start = memparse(p, &p);
2215 - return 0;
2216 -}
2217 -early_param("fbmem", early_parse_fbmem);
2218 -
2219 -static inline void __init resource_init(void)
2220 -{
2221 - struct tag_mem_range *region;
2222 -
2223 - kernel_code.start = __pa(init_mm.start_code);
2224 - kernel_code.end = __pa(init_mm.end_code - 1);
2225 - kernel_data.start = __pa(init_mm.end_code);
2226 - kernel_data.end = __pa(init_mm.brk - 1);
2227 + ret = add_reserved_region(fbmem_start,
2228 + fbmem_start + fbmem_size - 1,
2229 + "Framebuffer");
2230 + if (ret) {
2231 + printk(KERN_WARNING
2232 + "Failed to reserve framebuffer memory\n");
2233 + fbmem_start = 0;
2234 + }
2235 + }
2236
2237 - for (region = mem_phys; region; region = region->next) {
2238 - struct resource *res;
2239 - unsigned long phys_start, phys_end;
2240 -
2241 - if (region->size == 0)
2242 - continue;
2243 -
2244 - phys_start = region->addr;
2245 - phys_end = phys_start + region->size - 1;
2246 -
2247 - res = alloc_bootmem_low(sizeof(*res));
2248 - res->name = "System RAM";
2249 - res->start = phys_start;
2250 - res->end = phys_end;
2251 - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
2252 -
2253 - request_resource (&iomem_resource, res);
2254 -
2255 - if (kernel_code.start >= res->start &&
2256 - kernel_code.end <= res->end)
2257 - request_resource (res, &kernel_code);
2258 - if (kernel_data.start >= res->start &&
2259 - kernel_data.end <= res->end)
2260 - request_resource (res, &kernel_data);
2261 + if (!fbmem_start) {
2262 + if ((fbmem_size & 0x000fffffUL) == 0)
2263 + align = 0x100000; /* 1 MiB */
2264 + else if ((fbmem_size & 0x0000ffffUL) == 0)
2265 + align = 0x10000; /* 64 KiB */
2266 + else
2267 + align = 0x1000; /* 4 KiB */
2268 +
2269 + ret = alloc_reserved_region(&fbmem_start, fbmem_size,
2270 + align, "Framebuffer");
2271 + if (ret) {
2272 + printk(KERN_WARNING
2273 + "Failed to allocate framebuffer memory\n");
2274 + fbmem_size = 0;
2275 + }
2276 }
2277 +
2278 + return 0;
2279 }
2280 +early_param("fbmem", early_parse_fbmem);
2281
2282 static int __init parse_tag_core(struct tag *tag)
2283 {
2284 @@ -157,11 +291,9 @@
2285 }
2286 __tagtable(ATAG_CORE, parse_tag_core);
2287
2288 -static int __init parse_tag_mem_range(struct tag *tag,
2289 - struct tag_mem_range **root)
2290 +static int __init parse_tag_mem(struct tag *tag)
2291 {
2292 - struct tag_mem_range *cur, **pprev;
2293 - struct tag_mem_range *new;
2294 + unsigned long start, end;
2295
2296 /*
2297 * Ignore zero-sized entries. If we're running standalone, the
2298 @@ -171,34 +303,53 @@
2299 if (tag->u.mem_range.size == 0)
2300 return 0;
2301
2302 - /*
2303 - * Copy the data so the bootmem init code doesn't need to care
2304 - * about it.
2305 - */
2306 - if (mem_range_next_free >= ARRAY_SIZE(mem_range_cache))
2307 - panic("Physical memory map too complex!\n");
2308 + start = tag->u.mem_range.addr;
2309 + end = tag->u.mem_range.addr + tag->u.mem_range.size - 1;
2310
2311 - new = &mem_range_cache[mem_range_next_free++];
2312 - *new = tag->u.mem_range;
2313 + add_physical_memory(start, end);
2314 + return 0;
2315 +}
2316 +__tagtable(ATAG_MEM, parse_tag_mem);
2317
2318 - pprev = root;
2319 - cur = *root;
2320 - while (cur) {
2321 - pprev = &cur->next;
2322 - cur = cur->next;
2323 +static int __init parse_tag_rdimg(struct tag *tag)
2324 +{
2325 +#ifdef CONFIG_INITRD
2326 + struct tag_mem_range *mem = &tag->u.mem_range;
2327 + int ret;
2328 +
2329 + if (initrd_start) {
2330 + printk(KERN_WARNING
2331 + "Warning: Only the first initrd image will be used\n");
2332 + return 0;
2333 }
2334
2335 - *pprev = new;
2336 - new->next = NULL;
2337 + ret = add_reserved_region(mem->start, mem->start + mem->size - 1,
2338 + "initrd");
2339 + if (ret) {
2340 + printk(KERN_WARNING
2341 + "Warning: Failed to reserve initrd memory\n");
2342 + return ret;
2343 + }
2344 +
2345 + initrd_start = (unsigned long)__va(mem->addr);
2346 + initrd_end = initrd_start + mem->size;
2347 +#else
2348 + printk(KERN_WARNING "RAM disk image present, but "
2349 + "no initrd support in kernel, ignoring\n");
2350 +#endif
2351
2352 return 0;
2353 }
2354 +__tagtable(ATAG_RDIMG, parse_tag_rdimg);
2355
2356 -static int __init parse_tag_mem(struct tag *tag)
2357 +static int __init parse_tag_rsvd_mem(struct tag *tag)
2358 {
2359 - return parse_tag_mem_range(tag, &mem_phys);
2360 + struct tag_mem_range *mem = &tag->u.mem_range;
2361 +
2362 + return add_reserved_region(mem->addr, mem->addr + mem->size - 1,
2363 + "Reserved");
2364 }
2365 -__tagtable(ATAG_MEM, parse_tag_mem);
2366 +__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
2367
2368 static int __init parse_tag_cmdline(struct tag *tag)
2369 {
2370 @@ -207,12 +358,6 @@
2371 }
2372 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
2373
2374 -static int __init parse_tag_rdimg(struct tag *tag)
2375 -{
2376 - return parse_tag_mem_range(tag, &mem_ramdisk);
2377 -}
2378 -__tagtable(ATAG_RDIMG, parse_tag_rdimg);
2379 -
2380 static int __init parse_tag_clock(struct tag *tag)
2381 {
2382 /*
2383 @@ -223,12 +368,6 @@
2384 }
2385 __tagtable(ATAG_CLOCK, parse_tag_clock);
2386
2387 -static int __init parse_tag_rsvd_mem(struct tag *tag)
2388 -{
2389 - return parse_tag_mem_range(tag, &mem_reserved);
2390 -}
2391 -__tagtable(ATAG_RSVD_MEM, parse_tag_rsvd_mem);
2392 -
2393 /*
2394 * Scan the tag table for this tag, and call its parse function. The
2395 * tag table is built by the linker from all the __tagtable
2396 @@ -260,10 +399,137 @@
2397 t->hdr.tag);
2398 }
2399
2400 +/*
2401 + * Find a free memory region large enough for storing the
2402 + * bootmem bitmap.
2403 + */
2404 +static unsigned long __init
2405 +find_bootmap_pfn(const struct resource *mem)
2406 +{
2407 + unsigned long bootmap_pages, bootmap_len;
2408 + unsigned long node_pages = PFN_UP(mem->end - mem->start + 1);
2409 + unsigned long bootmap_start;
2410 +
2411 + bootmap_pages = bootmem_bootmap_pages(node_pages);
2412 + bootmap_len = bootmap_pages << PAGE_SHIFT;
2413 +
2414 + /*
2415 + * Find a large enough region without reserved pages for
2416 + * storing the bootmem bitmap. We can take advantage of the
2417 + * fact that all lists have been sorted.
2418 + *
2419 + * We have to check that we don't collide with any reserved
2420 + * regions, which includes the kernel image and any RAMDISK
2421 + * images.
2422 + */
2423 + bootmap_start = find_free_region(mem, bootmap_len, PAGE_SIZE);
2424 +
2425 + return bootmap_start >> PAGE_SHIFT;
2426 +}
2427 +
2428 +#define MAX_LOWMEM HIGHMEM_START
2429 +#define MAX_LOWMEM_PFN PFN_DOWN(MAX_LOWMEM)
2430 +
2431 +static void __init setup_bootmem(void)
2432 +{
2433 + unsigned bootmap_size;
2434 + unsigned long first_pfn, bootmap_pfn, pages;
2435 + unsigned long max_pfn, max_low_pfn;
2436 + unsigned node = 0;
2437 + struct resource *res;
2438 +
2439 + printk(KERN_INFO "Physical memory:\n");
2440 + for (res = system_ram; res; res = res->sibling)
2441 + printk(" %08x-%08x\n", res->start, res->end);
2442 + printk(KERN_INFO "Reserved memory:\n");
2443 + for (res = reserved; res; res = res->sibling)
2444 + printk(" %08x-%08x: %s\n",
2445 + res->start, res->end, res->name);
2446 +
2447 + nodes_clear(node_online_map);
2448 +
2449 + if (system_ram->sibling)
2450 + printk(KERN_WARNING "Only using first memory bank\n");
2451 +
2452 + for (res = system_ram; res; res = NULL) {
2453 + first_pfn = PFN_UP(res->start);
2454 + max_low_pfn = max_pfn = PFN_DOWN(res->end + 1);
2455 + bootmap_pfn = find_bootmap_pfn(res);
2456 + if (bootmap_pfn > max_pfn)
2457 + panic("No space for bootmem bitmap!\n");
2458 +
2459 + if (max_low_pfn > MAX_LOWMEM_PFN) {
2460 + max_low_pfn = MAX_LOWMEM_PFN;
2461 +#ifndef CONFIG_HIGHMEM
2462 + /*
2463 + * Lowmem is memory that can be addressed
2464 + * directly through P1/P2
2465 + */
2466 + printk(KERN_WARNING
2467 + "Node %u: Only %ld MiB of memory will be used.\n",
2468 + node, MAX_LOWMEM >> 20);
2469 + printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
2470 +#else
2471 +#error HIGHMEM is not supported by AVR32 yet
2472 +#endif
2473 + }
2474 +
2475 + /* Initialize the boot-time allocator with low memory only. */
2476 + bootmap_size = init_bootmem_node(NODE_DATA(node), bootmap_pfn,
2477 + first_pfn, max_low_pfn);
2478 +
2479 + /*
2480 + * Register fully available RAM pages with the bootmem
2481 + * allocator.
2482 + */
2483 + pages = max_low_pfn - first_pfn;
2484 + free_bootmem_node (NODE_DATA(node), PFN_PHYS(first_pfn),
2485 + PFN_PHYS(pages));
2486 +
2487 + /* Reserve space for the bootmem bitmap... */
2488 + reserve_bootmem_node(NODE_DATA(node),
2489 + PFN_PHYS(bootmap_pfn),
2490 + bootmap_size);
2491 +
2492 + /* ...and any other reserved regions. */
2493 + for (res = reserved; res; res = res->sibling) {
2494 + if (res->start > PFN_PHYS(max_pfn))
2495 + break;
2496 +
2497 + /*
2498 + * resource_init will complain about partial
2499 + * overlaps, so we'll just ignore such
2500 + * resources for now.
2501 + */
2502 + if (res->start >= PFN_PHYS(first_pfn)
2503 + && res->end < PFN_PHYS(max_pfn))
2504 + reserve_bootmem_node(
2505 + NODE_DATA(node), res->start,
2506 + res->end - res->start + 1);
2507 + }
2508 +
2509 + node_set_online(node);
2510 + }
2511 +}
2512 +
2513 void __init setup_arch (char **cmdline_p)
2514 {
2515 struct clk *cpu_clk;
2516
2517 + init_mm.start_code = (unsigned long)_text;
2518 + init_mm.end_code = (unsigned long)_etext;
2519 + init_mm.end_data = (unsigned long)_edata;
2520 + init_mm.brk = (unsigned long)_end;
2521 +
2522 + /*
2523 + * Include .init section to make allocations easier. It will
2524 + * be removed before the resource is actually requested.
2525 + */
2526 + kernel_code.start = __pa(__init_begin);
2527 + kernel_code.end = __pa(init_mm.end_code - 1);
2528 + kernel_data.start = __pa(init_mm.end_code);
2529 + kernel_data.end = __pa(init_mm.brk - 1);
2530 +
2531 parse_tags(bootloader_tags);
2532
2533 setup_processor();
2534 @@ -289,24 +555,16 @@
2535 ((cpu_hz + 500) / 1000) % 1000);
2536 }
2537
2538 - init_mm.start_code = (unsigned long) &_text;
2539 - init_mm.end_code = (unsigned long) &_etext;
2540 - init_mm.end_data = (unsigned long) &_edata;
2541 - init_mm.brk = (unsigned long) &_end;
2542 -
2543 strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
2544 *cmdline_p = command_line;
2545 parse_early_param();
2546
2547 setup_bootmem();
2548
2549 - board_setup_fbmem(fbmem_start, fbmem_size);
2550 -
2551 #ifdef CONFIG_VT
2552 conswitchp = &dummy_con;
2553 #endif
2554
2555 paging_init();
2556 -
2557 resource_init();
2558 }
2559 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/time.c avr32-git/arch/avr32/kernel/time.c
2560 --- linux-2.6.21.3/arch/avr32/kernel/time.c 2007-05-24 23:22:47.000000000 +0200
2561 +++ avr32-git/arch/avr32/kernel/time.c 2007-06-06 11:33:46.000000000 +0200
2562 @@ -1,5 +1,5 @@
2563 /*
2564 - * Copyright (C) 2004-2006 Atmel Corporation
2565 + * Copyright (C) 2004-2007 Atmel Corporation
2566 *
2567 * Based on MIPS implementation arch/mips/kernel/time.c
2568 * Copyright 2001 MontaVista Software Inc.
2569 @@ -20,18 +20,25 @@
2570 #include <linux/init.h>
2571 #include <linux/profile.h>
2572 #include <linux/sysdev.h>
2573 +#include <linux/err.h>
2574
2575 #include <asm/div64.h>
2576 #include <asm/sysreg.h>
2577 #include <asm/io.h>
2578 #include <asm/sections.h>
2579
2580 -static cycle_t read_cycle_count(void)
2581 +/* how many counter cycles in a jiffy? */
2582 +static u32 cycles_per_jiffy;
2583 +
2584 +/* the count value for the next timer interrupt */
2585 +static u32 expirelo;
2586 +
2587 +cycle_t __weak read_cycle_count(void)
2588 {
2589 return (cycle_t)sysreg_read(COUNT);
2590 }
2591
2592 -static struct clocksource clocksource_avr32 = {
2593 +struct clocksource __weak clocksource_avr32 = {
2594 .name = "avr32",
2595 .rating = 350,
2596 .read = read_cycle_count,
2597 @@ -40,12 +47,20 @@
2598 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
2599 };
2600
2601 +irqreturn_t __weak timer_interrupt(int irq, void *dev_id);
2602 +
2603 +struct irqaction timer_irqaction = {
2604 + .handler = timer_interrupt,
2605 + .flags = IRQF_DISABLED,
2606 + .name = "timer",
2607 +};
2608 +
2609 /*
2610 * By default we provide the null RTC ops
2611 */
2612 static unsigned long null_rtc_get_time(void)
2613 {
2614 - return mktime(2004, 1, 1, 0, 0, 0);
2615 + return mktime(2007, 1, 1, 0, 0, 0);
2616 }
2617
2618 static int null_rtc_set_time(unsigned long sec)
2619 @@ -56,23 +71,14 @@
2620 static unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
2621 static int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
2622
2623 -/* how many counter cycles in a jiffy? */
2624 -static unsigned long cycles_per_jiffy;
2625 -
2626 -/* cycle counter value at the previous timer interrupt */
2627 -static unsigned int timerhi, timerlo;
2628 -
2629 -/* the count value for the next timer interrupt */
2630 -static unsigned int expirelo;
2631 -
2632 static void avr32_timer_ack(void)
2633 {
2634 - unsigned int count;
2635 + u32 count;
2636
2637 /* Ack this timer interrupt and set the next one */
2638 expirelo += cycles_per_jiffy;
2639 + /* setting COMPARE to 0 stops the COUNT-COMPARE */
2640 if (expirelo == 0) {
2641 - printk(KERN_DEBUG "expirelo == 0\n");
2642 sysreg_write(COMPARE, expirelo + 1);
2643 } else {
2644 sysreg_write(COMPARE, expirelo);
2645 @@ -86,27 +92,56 @@
2646 }
2647 }
2648
2649 -static unsigned int avr32_hpt_read(void)
2650 +int __weak avr32_hpt_init(void)
2651 {
2652 - return sysreg_read(COUNT);
2653 + int ret;
2654 + unsigned long mult, shift, count_hz;
2655 +
2656 + count_hz = clk_get_rate(boot_cpu_data.clk);
2657 + shift = clocksource_avr32.shift;
2658 + mult = clocksource_hz2mult(count_hz, shift);
2659 + clocksource_avr32.mult = mult;
2660 +
2661 + {
2662 + u64 tmp;
2663 +
2664 + tmp = TICK_NSEC;
2665 + tmp <<= shift;
2666 + tmp += mult / 2;
2667 + do_div(tmp, mult);
2668 +
2669 + cycles_per_jiffy = tmp;
2670 + }
2671 +
2672 + ret = setup_irq(0, &timer_irqaction);
2673 + if (ret) {
2674 + pr_debug("timer: could not request IRQ 0: %d\n", ret);
2675 + return -ENODEV;
2676 + }
2677 +
2678 + printk(KERN_INFO "timer: AT32AP COUNT-COMPARE at irq 0, "
2679 + "%lu.%03lu MHz\n",
2680 + ((count_hz + 500) / 1000) / 1000,
2681 + ((count_hz + 500) / 1000) % 1000);
2682 +
2683 + return 0;
2684 }
2685
2686 /*
2687 * Taken from MIPS c0_hpt_timer_init().
2688 *
2689 - * Why is it so complicated, and what is "count"? My assumption is
2690 - * that `count' specifies the "reference cycle", i.e. the cycle since
2691 - * reset that should mean "zero". The reason COUNT is written twice is
2692 - * probably to make sure we don't get any timer interrupts while we
2693 - * are messing with the counter.
2694 + * The reason COUNT is written twice is probably to make sure we don't get any
2695 + * timer interrupts while we are messing with the counter.
2696 */
2697 -static void avr32_hpt_init(unsigned int count)
2698 +int __weak avr32_hpt_start(void)
2699 {
2700 - count = sysreg_read(COUNT) - count;
2701 + u32 count = sysreg_read(COUNT);
2702 expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy;
2703 sysreg_write(COUNT, expirelo - cycles_per_jiffy);
2704 sysreg_write(COMPARE, expirelo);
2705 sysreg_write(COUNT, count);
2706 +
2707 + return 0;
2708 }
2709
2710 /*
2711 @@ -115,26 +150,18 @@
2712 *
2713 * In UP mode, it is invoked from the (global) timer_interrupt.
2714 */
2715 -static void local_timer_interrupt(int irq, void *dev_id)
2716 +void local_timer_interrupt(int irq, void *dev_id)
2717 {
2718 if (current->pid)
2719 profile_tick(CPU_PROFILING);
2720 update_process_times(user_mode(get_irq_regs()));
2721 }
2722
2723 -static irqreturn_t
2724 -timer_interrupt(int irq, void *dev_id)
2725 +irqreturn_t __weak timer_interrupt(int irq, void *dev_id)
2726 {
2727 - unsigned int count;
2728 -
2729 /* ack timer interrupt and try to set next interrupt */
2730 - count = avr32_hpt_read();
2731 avr32_timer_ack();
2732
2733 - /* Update timerhi/timerlo for intra-jiffy calibration */
2734 - timerhi += count < timerlo; /* Wrap around */
2735 - timerlo = count;
2736 -
2737 /*
2738 * Call the generic timer interrupt handler
2739 */
2740 @@ -153,60 +180,37 @@
2741 return IRQ_HANDLED;
2742 }
2743
2744 -static struct irqaction timer_irqaction = {
2745 - .handler = timer_interrupt,
2746 - .flags = IRQF_DISABLED,
2747 - .name = "timer",
2748 -};
2749 -
2750 void __init time_init(void)
2751 {
2752 - unsigned long mult, shift, count_hz;
2753 int ret;
2754
2755 + /*
2756 + * Make sure we don't get any COMPARE interrupts before we can
2757 + * handle them.
2758 + */
2759 + sysreg_write(COMPARE, 0);
2760 +
2761 xtime.tv_sec = rtc_get_time();
2762 xtime.tv_nsec = 0;
2763
2764 set_normalized_timespec(&wall_to_monotonic,
2765 -xtime.tv_sec, -xtime.tv_nsec);
2766
2767 - printk("Before time_init: count=%08lx, compare=%08lx\n",
2768 - (unsigned long)sysreg_read(COUNT),
2769 - (unsigned long)sysreg_read(COMPARE));
2770 -
2771 - count_hz = clk_get_rate(boot_cpu_data.clk);
2772 - shift = clocksource_avr32.shift;
2773 - mult = clocksource_hz2mult(count_hz, shift);
2774 - clocksource_avr32.mult = mult;
2775 -
2776 - printk("Cycle counter: mult=%lu, shift=%lu\n", mult, shift);
2777 -
2778 - {
2779 - u64 tmp;
2780 -
2781 - tmp = TICK_NSEC;
2782 - tmp <<= shift;
2783 - tmp += mult / 2;
2784 - do_div(tmp, mult);
2785 -
2786 - cycles_per_jiffy = tmp;
2787 + ret = avr32_hpt_init();
2788 + if (ret) {
2789 + pr_debug("timer: failed setup: %d\n", ret);
2790 + return;
2791 }
2792
2793 - /* This sets up the high precision timer for the first interrupt. */
2794 - avr32_hpt_init(avr32_hpt_read());
2795 -
2796 - printk("After time_init: count=%08lx, compare=%08lx\n",
2797 - (unsigned long)sysreg_read(COUNT),
2798 - (unsigned long)sysreg_read(COMPARE));
2799 -
2800 ret = clocksource_register(&clocksource_avr32);
2801 if (ret)
2802 - printk(KERN_ERR
2803 - "timer: could not register clocksource: %d\n", ret);
2804 + pr_debug("timer: could not register clocksource: %d\n", ret);
2805
2806 - ret = setup_irq(0, &timer_irqaction);
2807 - if (ret)
2808 - printk("timer: could not request IRQ 0: %d\n", ret);
2809 + ret = avr32_hpt_start();
2810 + if (ret) {
2811 + pr_debug("timer: failed starting: %d\n", ret);
2812 + return;
2813 + }
2814 }
2815
2816 static struct sysdev_class timer_class = {
2817 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/traps.c avr32-git/arch/avr32/kernel/traps.c
2818 --- linux-2.6.21.3/arch/avr32/kernel/traps.c 2007-05-24 23:22:47.000000000 +0200
2819 +++ avr32-git/arch/avr32/kernel/traps.c 2007-06-06 11:33:46.000000000 +0200
2820 @@ -5,158 +5,25 @@
2821 * it under the terms of the GNU General Public License version 2 as
2822 * published by the Free Software Foundation.
2823 */
2824 -#undef DEBUG
2825 -#include <linux/sched.h>
2826 +
2827 +#include <linux/bug.h>
2828 #include <linux/init.h>
2829 -#include <linux/module.h>
2830 #include <linux/kallsyms.h>
2831 +#include <linux/module.h>
2832 #include <linux/notifier.h>
2833 +#include <linux/sched.h>
2834 +#include <linux/uaccess.h>
2835
2836 -#include <asm/traps.h>
2837 -#include <asm/sysreg.h>
2838 #include <asm/addrspace.h>
2839 -#include <asm/ocd.h>
2840 #include <asm/mmu_context.h>
2841 -#include <asm/uaccess.h>
2842 -
2843 -static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
2844 -{
2845 - unsigned long p;
2846 - int i;
2847 -
2848 - printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
2849 -
2850 - for (p = bottom & ~31; p < top; ) {
2851 - printk("%04lx: ", p & 0xffff);
2852 -
2853 - for (i = 0; i < 8; i++, p += 4) {
2854 - unsigned int val;
2855 -
2856 - if (p < bottom || p >= top)
2857 - printk(" ");
2858 - else {
2859 - if (__get_user(val, (unsigned int __user *)p)) {
2860 - printk("\n");
2861 - goto out;
2862 - }
2863 - printk("%08x ", val);
2864 - }
2865 - }
2866 - printk("\n");
2867 - }
2868 -
2869 -out:
2870 - return;
2871 -}
2872 -
2873 -static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p)
2874 -{
2875 - return (p > (unsigned long)tinfo)
2876 - && (p < (unsigned long)tinfo + THREAD_SIZE - 3);
2877 -}
2878 -
2879 -#ifdef CONFIG_FRAME_POINTER
2880 -static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
2881 - struct pt_regs *regs)
2882 -{
2883 - unsigned long lr, fp;
2884 - struct thread_info *tinfo;
2885 -
2886 - tinfo = (struct thread_info *)
2887 - ((unsigned long)sp & ~(THREAD_SIZE - 1));
2888 -
2889 - if (regs)
2890 - fp = regs->r7;
2891 - else if (tsk == current)
2892 - asm("mov %0, r7" : "=r"(fp));
2893 - else
2894 - fp = tsk->thread.cpu_context.r7;
2895 -
2896 - /*
2897 - * Walk the stack as long as the frame pointer (a) is within
2898 - * the kernel stack of the task, and (b) it doesn't move
2899 - * downwards.
2900 - */
2901 - while (valid_stack_ptr(tinfo, fp)) {
2902 - unsigned long new_fp;
2903 -
2904 - lr = *(unsigned long *)fp;
2905 - printk(" [<%08lx>] ", lr);
2906 - print_symbol("%s\n", lr);
2907 -
2908 - new_fp = *(unsigned long *)(fp + 4);
2909 - if (new_fp <= fp)
2910 - break;
2911 - fp = new_fp;
2912 - }
2913 - printk("\n");
2914 -}
2915 -#else
2916 -static inline void __show_trace(struct task_struct *tsk, unsigned long *sp,
2917 - struct pt_regs *regs)
2918 -{
2919 - unsigned long addr;
2920 -
2921 - while (!kstack_end(sp)) {
2922 - addr = *sp++;
2923 - if (kernel_text_address(addr)) {
2924 - printk(" [<%08lx>] ", addr);
2925 - print_symbol("%s\n", addr);
2926 - }
2927 - }
2928 -}
2929 -#endif
2930 -
2931 -void show_trace(struct task_struct *tsk, unsigned long *sp,
2932 - struct pt_regs *regs)
2933 -{
2934 - if (regs &&
2935 - (((regs->sr & MODE_MASK) == MODE_EXCEPTION) ||
2936 - ((regs->sr & MODE_MASK) == MODE_USER)))
2937 - return;
2938 -
2939 - printk ("Call trace:");
2940 -#ifdef CONFIG_KALLSYMS
2941 - printk("\n");
2942 -#endif
2943 -
2944 - __show_trace(tsk, sp, regs);
2945 - printk("\n");
2946 -}
2947 -
2948 -void show_stack(struct task_struct *tsk, unsigned long *sp)
2949 -{
2950 - unsigned long stack;
2951 -
2952 - if (!tsk)
2953 - tsk = current;
2954 - if (sp == 0) {
2955 - if (tsk == current) {
2956 - register unsigned long *real_sp __asm__("sp");
2957 - sp = real_sp;
2958 - } else {
2959 - sp = (unsigned long *)tsk->thread.cpu_context.ksp;
2960 - }
2961 - }
2962 -
2963 - stack = (unsigned long)sp;
2964 - dump_mem("Stack: ", stack,
2965 - THREAD_SIZE + (unsigned long)tsk->thread_info);
2966 - show_trace(tsk, sp, NULL);
2967 -}
2968 -
2969 -void dump_stack(void)
2970 -{
2971 - show_stack(NULL, NULL);
2972 -}
2973 -EXPORT_SYMBOL(dump_stack);
2974 +#include <asm/ocd.h>
2975 +#include <asm/sysreg.h>
2976 +#include <asm/traps.h>
2977
2978 ATOMIC_NOTIFIER_HEAD(avr32_die_chain);
2979
2980 int register_die_notifier(struct notifier_block *nb)
2981 {
2982 - pr_debug("register_die_notifier: %p\n", nb);
2983 -
2984 return atomic_notifier_chain_register(&avr32_die_chain, nb);
2985 }
2986 EXPORT_SYMBOL(register_die_notifier);
2987 @@ -169,98 +36,108 @@
2988
2989 static DEFINE_SPINLOCK(die_lock);
2990
2991 -void __die(const char *str, struct pt_regs *regs, unsigned long err,
2992 - const char *file, const char *func, unsigned long line)
2993 +void NORET_TYPE die(const char *str, struct pt_regs *regs, long err)
2994 {
2995 - struct task_struct *tsk = current;
2996 static int die_counter;
2997
2998 console_verbose();
2999 spin_lock_irq(&die_lock);
3000 bust_spinlocks(1);
3001
3002 - printk(KERN_ALERT "%s", str);
3003 - if (file && func)
3004 - printk(" in %s:%s, line %ld", file, func, line);
3005 - printk("[#%d]:\n", ++die_counter);
3006 - print_modules();
3007 - show_regs(regs);
3008 - printk("Process %s (pid: %d, stack limit = 0x%p)\n",
3009 - tsk->comm, tsk->pid, tsk->thread_info + 1);
3010 -
3011 - if (!user_mode(regs) || in_interrupt()) {
3012 - dump_mem("Stack: ", regs->sp,
3013 - THREAD_SIZE + (unsigned long)tsk->thread_info);
3014 + printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n" KERN_EMERG,
3015 + str, err, ++die_counter);
3016 +#ifdef CONFIG_PREEMPT
3017 + printk("PREEMPT ");
3018 +#endif
3019 +#ifdef CONFIG_FRAME_POINTER
3020 + printk("FRAME_POINTER ");
3021 +#endif
3022 + if (current_cpu_data.features & AVR32_FEATURE_OCD) {
3023 + unsigned long did = __mfdr(DBGREG_DID);
3024 + printk("chip: 0x%03lx:0x%04lx rev %lu\n",
3025 + (did >> 1) & 0x7ff,
3026 + (did >> 12) & 0x7fff,
3027 + (did >> 28) & 0xf);
3028 + } else {
3029 + printk("cpu: arch %u r%u / core %u r%u\n",
3030 + current_cpu_data.arch_type,
3031 + current_cpu_data.arch_revision,
3032 + current_cpu_data.cpu_type,
3033 + current_cpu_data.cpu_revision);
3034 }
3035
3036 + print_modules();
3037 + show_regs_log_lvl(regs, KERN_EMERG);
3038 + show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG);
3039 bust_spinlocks(0);
3040 spin_unlock_irq(&die_lock);
3041 - do_exit(SIGSEGV);
3042 +
3043 + if (in_interrupt())
3044 + panic("Fatal exception in interrupt");
3045 +
3046 + if (panic_on_oops)
3047 + panic("Fatal exception");
3048 +
3049 + do_exit(err);
3050 }
3051
3052 -void __die_if_kernel(const char *str, struct pt_regs *regs, unsigned long err,
3053 - const char *file, const char *func, unsigned long line)
3054 +void _exception(long signr, struct pt_regs *regs, int code,
3055 + unsigned long addr)
3056 {
3057 + siginfo_t info;
3058 +
3059 if (!user_mode(regs))
3060 - __die(str, regs, err, file, func, line);
3061 -}
3062 + die("Unhandled exception in kernel mode", regs, signr);
3063 +
3064 + memset(&info, 0, sizeof(info));
3065 + info.si_signo = signr;
3066 + info.si_code = code;
3067 + info.si_addr = (void __user *)addr;
3068 + force_sig_info(signr, &info, current);
3069
3070 -asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
3071 -{
3072 -#ifdef CONFIG_SUBARCH_AVR32B
3073 /*
3074 - * The exception entry always saves RSR_EX. For NMI, this is
3075 - * wrong; it should be RSR_NMI
3076 + * Init gets no signals that it doesn't have a handler for.
3077 + * That's all very well, but if it has caused a synchronous
3078 + * exception and we ignore the resulting signal, it will just
3079 + * generate the same exception over and over again and we get
3080 + * nowhere. Better to kill it and let the kernel panic.
3081 */
3082 - regs->sr = sysreg_read(RSR_NMI);
3083 -#endif
3084 + if (is_init(current)) {
3085 + __sighandler_t handler;
3086
3087 - printk("NMI taken!!!!\n");
3088 - die("NMI", regs, ecr);
3089 - BUG();
3090 + spin_lock_irq(&current->sighand->siglock);
3091 + handler = current->sighand->action[signr-1].sa.sa_handler;
3092 + spin_unlock_irq(&current->sighand->siglock);
3093 + if (handler == SIG_DFL) {
3094 + /* init has generated a synchronous exception
3095 + and it doesn't have a handler for the signal */
3096 + printk(KERN_CRIT "init has generated signal %ld "
3097 + "but has no handler for it\n", signr);
3098 + do_exit(signr);
3099 + }
3100 + }
3101 +}
3102 +
3103 +asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
3104 +{
3105 + printk(KERN_ALERT "Got Non-Maskable Interrupt, dumping regs\n");
3106 + show_regs_log_lvl(regs, KERN_ALERT);
3107 + show_stack_log_lvl(current, regs->sp, regs, KERN_ALERT);
3108 }
3109
3110 asmlinkage void do_critical_exception(unsigned long ecr, struct pt_regs *regs)
3111 {
3112 - printk("Unable to handle critical exception %lu at pc = %08lx!\n",
3113 - ecr, regs->pc);
3114 - die("Oops", regs, ecr);
3115 - BUG();
3116 + die("Critical exception", regs, SIGKILL);
3117 }
3118
3119 asmlinkage void do_address_exception(unsigned long ecr, struct pt_regs *regs)
3120 {
3121 - siginfo_t info;
3122 -
3123 - die_if_kernel("Oops: Address exception in kernel mode", regs, ecr);
3124 -
3125 -#ifdef DEBUG
3126 - if (ecr == ECR_ADDR_ALIGN_X)
3127 - pr_debug("Instruction Address Exception at pc = %08lx\n",
3128 - regs->pc);
3129 - else if (ecr == ECR_ADDR_ALIGN_R)
3130 - pr_debug("Data Address Exception (Read) at pc = %08lx\n",
3131 - regs->pc);
3132 - else if (ecr == ECR_ADDR_ALIGN_W)
3133 - pr_debug("Data Address Exception (Write) at pc = %08lx\n",
3134 - regs->pc);
3135 - else
3136 - BUG();
3137 -
3138 - show_regs(regs);
3139 -#endif
3140 -
3141 - info.si_signo = SIGBUS;
3142 - info.si_errno = 0;
3143 - info.si_code = BUS_ADRALN;
3144 - info.si_addr = (void __user *)regs->pc;
3145 -
3146 - force_sig_info(SIGBUS, &info, current);
3147 + _exception(SIGBUS, regs, BUS_ADRALN, regs->pc);
3148 }
3149
3150 /* This way of handling undefined instructions is stolen from ARM */
3151 static LIST_HEAD(undef_hook);
3152 -static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED;
3153 +static DEFINE_SPINLOCK(undef_lock);
3154
3155 void register_undef_hook(struct undef_hook *hook)
3156 {
3157 @@ -280,7 +157,8 @@
3158 {
3159 int cop_nr;
3160 u32 cpucr;
3161 - if ( (insn & 0xfdf00000) == 0xf1900000 )
3162 +
3163 + if ((insn & 0xfdf00000) == 0xf1900000)
3164 /* LDC0 */
3165 cop_nr = 0;
3166 else
3167 @@ -292,136 +170,91 @@
3168 sysreg_write(CPUCR, cpucr);
3169
3170 cpucr = sysreg_read(CPUCR);
3171 - if ( !(cpucr & (1 << (24 + cop_nr))) ){
3172 - printk("Coprocessor #%i not found!\n", cop_nr);
3173 - return -1;
3174 - }
3175 + if (!(cpucr & (1 << (24 + cop_nr))))
3176 + return -ENODEV;
3177
3178 return 0;
3179 }
3180
3181 -#ifdef CONFIG_BUG
3182 -#ifdef CONFIG_DEBUG_BUGVERBOSE
3183 -static inline void do_bug_verbose(struct pt_regs *regs, u32 insn)
3184 -{
3185 - char *file;
3186 - u16 line;
3187 - char c;
3188 -
3189 - if (__get_user(line, (u16 __user *)(regs->pc + 2)))
3190 - return;
3191 - if (__get_user(file, (char * __user *)(regs->pc + 4))
3192 - || (unsigned long)file < PAGE_OFFSET
3193 - || __get_user(c, file))
3194 - file = "<bad filename>";
3195 -
3196 - printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line);
3197 -}
3198 -#else
3199 -static inline void do_bug_verbose(struct pt_regs *regs, u32 insn)
3200 +int is_valid_bugaddr(unsigned long pc)
3201 {
3202 + unsigned short opcode;
3203 +
3204 + if (pc < PAGE_OFFSET)
3205 + return 0;
3206 + if (probe_kernel_address((u16 *)pc, opcode))
3207 + return 0;
3208
3209 + return opcode == AVR32_BUG_OPCODE;
3210 }
3211 -#endif
3212 -#endif
3213
3214 asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs)
3215 {
3216 u32 insn;
3217 struct undef_hook *hook;
3218 - siginfo_t info;
3219 void __user *pc;
3220 + long code;
3221
3222 - if (!user_mode(regs))
3223 - goto kernel_trap;
3224 + if (!user_mode(regs) && (ecr == ECR_ILLEGAL_OPCODE)) {
3225 + enum bug_trap_type type;
3226 +
3227 + type = report_bug(regs->pc);
3228 + switch (type) {
3229 + case BUG_TRAP_TYPE_NONE:
3230 + break;
3231 + case BUG_TRAP_TYPE_WARN:
3232 + regs->pc += 2;
3233 + return;
3234 + case BUG_TRAP_TYPE_BUG:
3235 + die("Kernel BUG", regs, SIGKILL);
3236 + }
3237 + }
3238
3239 local_irq_enable();
3240
3241 - pc = (void __user *)instruction_pointer(regs);
3242 - if (__get_user(insn, (u32 __user *)pc))
3243 - goto invalid_area;
3244 + if (user_mode(regs)) {
3245 + pc = (void __user *)instruction_pointer(regs);
3246 + if (get_user(insn, (u32 __user *)pc))
3247 + goto invalid_area;
3248
3249 - if (ecr == ECR_COPROC_ABSENT) {
3250 - if (do_cop_absent(insn) == 0)
3251 + if (ecr == ECR_COPROC_ABSENT && !do_cop_absent(insn))
3252 return;
3253 - }
3254
3255 - spin_lock_irq(&undef_lock);
3256 - list_for_each_entry(hook, &undef_hook, node) {
3257 - if ((insn & hook->insn_mask) == hook->insn_val) {
3258 - if (hook->fn(regs, insn) == 0) {
3259 - spin_unlock_irq(&undef_lock);
3260 - return;
3261 + spin_lock_irq(&undef_lock);
3262 + list_for_each_entry(hook, &undef_hook, node) {
3263 + if ((insn & hook->insn_mask) == hook->insn_val) {
3264 + if (hook->fn(regs, insn) == 0) {
3265 + spin_unlock_irq(&undef_lock);
3266 + return;
3267 + }
3268 }
3269 }
3270 + spin_unlock_irq(&undef_lock);
3271 }
3272 - spin_unlock_irq(&undef_lock);
3273 -
3274 -invalid_area:
3275
3276 -#ifdef DEBUG
3277 - printk("Illegal instruction at pc = %08lx\n", regs->pc);
3278 - if (regs->pc < TASK_SIZE) {
3279 - unsigned long ptbr, pgd, pte, *p;
3280 -
3281 - ptbr = sysreg_read(PTBR);
3282 - p = (unsigned long *)ptbr;
3283 - pgd = p[regs->pc >> 22];
3284 - p = (unsigned long *)((pgd & 0x1ffff000) | 0x80000000);
3285 - pte = p[(regs->pc >> 12) & 0x3ff];
3286 - printk("page table: 0x%08lx -> 0x%08lx -> 0x%08lx\n", ptbr, pgd, pte);
3287 - }
3288 -#endif
3289 -
3290 - info.si_signo = SIGILL;
3291 - info.si_errno = 0;
3292 - info.si_addr = (void __user *)regs->pc;
3293 switch (ecr) {
3294 - case ECR_ILLEGAL_OPCODE:
3295 - case ECR_UNIMPL_INSTRUCTION:
3296 - info.si_code = ILL_ILLOPC;
3297 - break;
3298 case ECR_PRIVILEGE_VIOLATION:
3299 - info.si_code = ILL_PRVOPC;
3300 + code = ILL_PRVOPC;
3301 break;
3302 case ECR_COPROC_ABSENT:
3303 - info.si_code = ILL_COPROC;
3304 + code = ILL_COPROC;
3305 break;
3306 default:
3307 - BUG();
3308 + code = ILL_ILLOPC;
3309 + break;
3310 }
3311
3312 - force_sig_info(SIGILL, &info, current);
3313 + _exception(SIGILL, regs, code, regs->pc);
3314 return;
3315
3316 -kernel_trap:
3317 -#ifdef CONFIG_BUG
3318 - if (__kernel_text_address(instruction_pointer(regs))) {
3319 - insn = *(u16 *)instruction_pointer(regs);
3320 - if (insn == AVR32_BUG_OPCODE) {
3321 - do_bug_verbose(regs, insn);
3322 - die("Kernel BUG", regs, 0);
3323 - return;
3324 - }
3325 - }
3326 -#endif
3327 -
3328 - die("Oops: Illegal instruction in kernel code", regs, ecr);
3329 +invalid_area:
3330 + _exception(SIGSEGV, regs, SEGV_MAPERR, regs->pc);
3331 }
3332
3333 asmlinkage void do_fpe(unsigned long ecr, struct pt_regs *regs)
3334 {
3335 - siginfo_t info;
3336 -
3337 - printk("Floating-point exception at pc = %08lx\n", regs->pc);
3338 -
3339 - /* We have no FPU... */
3340 - info.si_signo = SIGILL;
3341 - info.si_errno = 0;
3342 - info.si_addr = (void __user *)regs->pc;
3343 - info.si_code = ILL_COPROC;
3344 -
3345 - force_sig_info(SIGILL, &info, current);
3346 + /* We have no FPU yet */
3347 + _exception(SIGILL, regs, ILL_COPROC, regs->pc);
3348 }
3349
3350
3351 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/kernel/vmlinux.lds.c avr32-git/arch/avr32/kernel/vmlinux.lds.c
3352 --- linux-2.6.21.3/arch/avr32/kernel/vmlinux.lds.c 2007-05-24 23:22:47.000000000 +0200
3353 +++ avr32-git/arch/avr32/kernel/vmlinux.lds.c 2007-06-06 11:33:46.000000000 +0200
3354 @@ -26,10 +26,16 @@
3355 _sinittext = .;
3356 *(.text.reset)
3357 *(.init.text)
3358 + /*
3359 + * .exit.text is discarded at runtime, not
3360 + * link time, to deal with references from
3361 + * __bug_table
3362 + */
3363 + *(.exit.text)
3364 _einittext = .;
3365 . = ALIGN(4);
3366 __tagtable_begin = .;
3367 - *(.taglist)
3368 + *(.taglist.init)
3369 __tagtable_end = .;
3370 *(.init.data)
3371 . = ALIGN(16);
3372 @@ -86,6 +92,8 @@
3373 __stop___ex_table = .;
3374 }
3375
3376 + BUG_TABLE
3377 +
3378 RODATA
3379
3380 . = ALIGN(8192);
3381 @@ -126,7 +134,6 @@
3382 * thrown away, as cleanup code is never called unless it's a module.
3383 */
3384 /DISCARD/ : {
3385 - *(.exit.text)
3386 *(.exit.data)
3387 *(.exitcall.exit)
3388 }
3389 diff -Nur -x .gitignore -x .git linux-2.6.21.3/arch/avr32/mach-at32ap/at32ap7000.c avr32-git/arch/avr32/mach-at32ap/at32ap7000.c
3390 --- linux-2.6.21.3/arch/avr32/mach-at32ap/at32ap7000.c 2007-05-24 23:22:47.000000000 +0200
3391 +++ avr32-git/arch/avr32/mach-at32ap/at32ap7000.c 2007-06-06 11:33:46.000000000 +0200
3392 @@ -6,6 +6,7 @@
3393 * published by the Free Software Foundation.
3394 */
3395 #include <linux/clk.h>
3396 +#include <linux/fb.h>
3397 #include <linux/init.h>
3398 #include <linux/platform_device.h>
3399 #include <linux/spi/spi.h>
3400 @@ -17,7 +18,10 @@
3401 #include <asm/arch/portmux.h>
3402 #include <asm/arch/sm.h>
3403
3404 +#include <video/atmel_lcdc.h>
3405 +
3406 #include "clock.h"
3407 +#include "hmatrix.h"
3408 #include "pio.h"
3409 #include "sm.h"
3410
3411 @@ -416,7 +420,15 @@
3412 .resource = sm_resource,
3413 .num_resources = ARRAY_SIZE(sm_resource),
3414 };
3415 -DEV_CLK(pclk, at32_sm, pbb, 0);
3416 +static struct clk at32_sm_pclk = {
3417 + .name = "pclk",
3418 + .dev = &at32_sm_device.dev,
3419 + .parent = &pbb_clk,
3420 + .mode = pbb_clk_mode,
3421 + .get_rate = pbb_clk_get_rate,
3422 + .users = 1,
3423 + .index = 0,
3424 +};
3425
3426 static struct resource intc0_resource[] = {
3427 PBMEM(0xfff00400),
3428 @@ -442,6 +454,7 @@
3429 .mode = hsb_clk_mode,
3430 .get_rate = hsb_clk_get_rate,
3431 .users = 1,
3432 + .index = 3,
3433 };
3434
3435 static struct resource smc0_resource[] = {
3436 @@ -466,6 +479,68 @@
3437 .users = 1,
3438 };
3439
3440 +static struct resource dmaca0_resource[] = {
3441 + {
3442 + .start = 0xff200000,
3443 + .end = 0xff20ffff,
3444 + .flags = IORESOURCE_MEM,
3445 + },
3446 + IRQ(2),
3447 +};
3448 +DEFINE_DEV(dmaca, 0);
3449 +DEV_CLK(hclk, dmaca0, hsb, 10);
3450 +
3451 +/* --------------------------------------------------------------------
3452 + * HMATRIX
3453 + * -------------------------------------------------------------------- */
3454 +
3455 +static struct clk hmatrix_clk = {
3456 + .name = "hmatrix_clk",
3457 + .parent = &pbb_clk,
3458 + .mode = pbb_clk_mode,
3459 + .get_rate = pbb_clk_get_rate,
3460 + .index = 2,
3461 + .users = 1,
3462 +};
3463 +#define HMATRIX_BASE ((void __iomem *)0xfff00800)
3464 +
3465 +#define hmatrix_readl(reg) \
3466 + __raw_readl((HMATRIX_BASE) + HMATRIX_##reg)
3467 +#define hmatrix_writel(reg,value) \
3468 + __raw_writel((value), (HMATRIX_BASE) + HMATRIX_##reg)
3469 +
3470 +/*
3471 + * Set bits in the HMATRIX Special Function Register (SFR) used by the
3472 + * External Bus Interface (EBI). This can be used to enable special
3473 + * features like CompactFlash support, NAND Flash support, etc. on
3474 + * certain chipselects.
3475 + */
3476 +static inline void set_ebi_sfr_bits(u32 mask)
3477 +{
3478 + u32 sfr;
3479 +
3480 + clk_enable(&hmatrix_clk);
3481 + sfr = hmatrix_readl(SFR4);
3482 + sfr |= mask;
3483 + hmatrix_writel(SFR4, sfr);
3484 + clk_disable(&hmatrix_clk);
3485 +}
3486 +
3487 +/* --------------------------------------------------------------------
3488 + * System Timer/Counter (TC)
3489 + * -------------------------------------------------------------------- */
3490 +static struct resource at32_systc0_resource[] = {
3491 + PBMEM(0xfff00c00),
3492 + IRQ(22),
3493 +};
3494 +struct platform_device at32_systc0_device = {
3495 + .name = "systc",
3496 + .id = 0,
3497 + .resource = at32_systc0_resource,
3498 + .num_resources = ARRAY_SIZE(at32_systc0_resource),
3499 +};
3500 +DEV_CLK(pclk, at32_systc0, pbb, 3);
3501 +
3502 /* --------------------------------------------------------------------
3503 * PIO
3504 * -------------------------------------------------------------------- */
3505 @@ -513,6 +588,9 @@
3506 platform_device_register(&at32_intc0_device);
3507 platform_device_register(&smc0_device);
3508 platform_device_register(&pdc_device);
3509 + platform_device_register(&dmaca0_device);
3510 +
3511 + platform_device_register(&at32_systc0_device);
3512
3513 platform_device_register(&pio0_device);
3514 platform_device_register(&pio1_device);
3515 @@ -816,22 +894,105 @@
3516 }
3517
3518 /* --------------------------------------------------------------------
3519 + * TWI
3520 + * -------------------------------------------------------------------- */
3521 +
3522 +static struct resource atmel_twi0_resource[] = {
3523 + PBMEM(0xffe00800),
3524 + IRQ(5),
3525 +};
3526 +DEFINE_DEV(atmel_twi, 0);
3527 +DEV_CLK(pclk,atmel_twi0,pba,2);
3528 +
3529 +struct platform_device *__init
3530 +at32_add_device_twi(unsigned int id)
3531 +{
3532 + struct platform_device *pdev;
3533 +
3534 + switch (id) {
3535 + case 0:
3536 + pdev = &atmel_twi0_device;
3537 + select_peripheral(PA(6), PERIPH_A, 0); /* SDA */
3538 + select_peripheral(PA(7), PERIPH_A, 0); /* SCL */
3539 + break;
3540 +
3541 + default:
3542 + return NULL;
3543 + }
3544 +
3545 + platform_device_register(pdev);
3546 + return pdev;
3547 +}
3548 +
3549 +/* --------------------------------------------------------------------
3550 + * MMC
3551 + * -------------------------------------------------------------------- */
3552 +static struct mci_platform_data atmel_mci0_data = {
3553 + .detect_pin = GPIO_PIN_NONE,
3554 + .wp_pin = GPIO_PIN_NONE,
3555 +};
3556 +static struct resource atmel_mci0_resource[] = {
3557 + PBMEM(0xfff02400),
3558 + IRQ(28),
3559 +};
3560 +DEFINE_DEV_DATA(atmel_mci, 0);
3561 +DEV_CLK(mci_clk, atmel_mci0, pbb, 9);
3562 +
3563 +struct platform_device *__init
3564 +at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
3565 +{
3566 + struct platform_device *pdev;
3567 +
3568 + switch (id) {
3569 + case 0:
3570 + pdev = &atmel_mci0_device;
3571 + select_peripheral(PA(10), PERIPH_A, 0); /* CLK */
3572 + select_peripheral(PA(11), PERIPH_A, 0); /* CMD */
3573 + select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */
3574 + select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */
3575 + select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */
3576 + select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */
3577 + break;
3578 + default:
3579 + return NULL;
3580 + }
3581 +
3582 + if (data) {
3583 + if (data->detect_pin != GPIO_PIN_NONE)
3584 + at32_select_gpio(data->detect_pin, 0);
3585 + if (data->wp_pin != GPIO_PIN_NONE)
3586 + at32_select_gpio(data->wp_pin, 0);
3587 + memcpy(pdev->dev.platform_data, data,
3588 + sizeof(struct mci_platform_data));
3589 + }
3590 +
3591 + platform_device_register(pdev);
3592 + return pdev;
3593 +}
3594 +
3595 +/* --------------------------------------------------------------------
3596 * LCDC
3597 * -------------------------------------------------------------------- */
3598 -static struct lcdc_platform_data lcdc0_data;
3599 -static struct resource lcdc0_resource[] = {
3600 +static struct atmel_lcdfb_info atmel_lcdfb0_data;
3601 +static struct resource atmel_lcdfb0_resource[] = {