Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lpd270.c
Go to the documentation of this file.
1 /*
2  * linux/arch/arm/mach-pxa/lpd270.c
3  *
4  * Support for the LogicPD PXA270 Card Engine.
5  * Derived from the mainstone code, which carries these notices:
6  *
7  * Author: Nicolas Pitre
8  * Created: Nov 05, 2002
9  * Copyright: MontaVista Software Inc.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  */
15 #include <linux/gpio.h>
16 #include <linux/init.h>
17 #include <linux/platform_device.h>
18 #include <linux/syscore_ops.h>
19 #include <linux/interrupt.h>
20 #include <linux/sched.h>
21 #include <linux/bitops.h>
22 #include <linux/fb.h>
23 #include <linux/ioport.h>
24 #include <linux/mtd/mtd.h>
25 #include <linux/mtd/partitions.h>
26 #include <linux/pwm_backlight.h>
27 
28 #include <asm/types.h>
29 #include <asm/setup.h>
30 #include <asm/memory.h>
31 #include <asm/mach-types.h>
32 #include <mach/hardware.h>
33 #include <asm/irq.h>
34 #include <asm/sizes.h>
35 
36 #include <asm/mach/arch.h>
37 #include <asm/mach/map.h>
38 #include <asm/mach/irq.h>
39 #include <asm/mach/flash.h>
40 
41 #include <mach/pxa27x.h>
42 #include <mach/lpd270.h>
43 #include <mach/audio.h>
48 #include <mach/smemc.h>
49 
50 #include "generic.h"
51 #include "devices.h"
52 
53 static unsigned long lpd270_pin_config[] __initdata = {
54  /* Chip Selects */
55  GPIO15_nCS_1, /* Mainboard Flash */
56  GPIO78_nCS_2, /* CPLD + Ethernet */
57 
58  /* LCD - 16bpp Active TFT */
79  GPIO16_PWM0_OUT, /* Backlight */
80 
81  /* USB Host */
84 
85  /* AC97 */
91 
93 };
94 
95 static unsigned int lpd270_irq_enabled;
96 
97 static void lpd270_mask_irq(struct irq_data *d)
98 {
99  int lpd270_irq = d->irq - LPD270_IRQ(0);
100 
101  __raw_writew(~(1 << lpd270_irq), LPD270_INT_STATUS);
102 
103  lpd270_irq_enabled &= ~(1 << lpd270_irq);
104  __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
105 }
106 
107 static void lpd270_unmask_irq(struct irq_data *d)
108 {
109  int lpd270_irq = d->irq - LPD270_IRQ(0);
110 
111  lpd270_irq_enabled |= 1 << lpd270_irq;
112  __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
113 }
114 
115 static struct irq_chip lpd270_irq_chip = {
116  .name = "CPLD",
117  .irq_ack = lpd270_mask_irq,
118  .irq_mask = lpd270_mask_irq,
119  .irq_unmask = lpd270_unmask_irq,
120 };
121 
122 static void lpd270_irq_handler(unsigned int irq, struct irq_desc *desc)
123 {
124  unsigned long pending;
125 
126  pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled;
127  do {
128  /* clear useless edge notification */
129  desc->irq_data.chip->irq_ack(&desc->irq_data);
130  if (likely(pending)) {
131  irq = LPD270_IRQ(0) + __ffs(pending);
132  generic_handle_irq(irq);
133 
134  pending = __raw_readw(LPD270_INT_STATUS) &
135  lpd270_irq_enabled;
136  }
137  } while (pending);
138 }
139 
140 static void __init lpd270_init_irq(void)
141 {
142  int irq;
143 
144  pxa27x_init_irq();
145 
148 
149  /* setup extra LogicPD PXA270 irqs */
150  for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) {
151  irq_set_chip_and_handler(irq, &lpd270_irq_chip,
154  }
155  irq_set_chained_handler(PXA_GPIO_TO_IRQ(0), lpd270_irq_handler);
157 }
158 
159 
160 #ifdef CONFIG_PM
161 static void lpd270_irq_resume(void)
162 {
163  __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
164 }
165 
166 static struct syscore_ops lpd270_irq_syscore_ops = {
167  .resume = lpd270_irq_resume,
168 };
169 
170 static int __init lpd270_irq_device_init(void)
171 {
172  if (machine_is_logicpd_pxa270()) {
173  register_syscore_ops(&lpd270_irq_syscore_ops);
174  return 0;
175  }
176  return -ENODEV;
177 }
178 
179 device_initcall(lpd270_irq_device_init);
180 #endif
181 
182 
183 static struct resource smc91x_resources[] = {
184  [0] = {
185  .start = LPD270_ETH_PHYS,
186  .end = (LPD270_ETH_PHYS + 0xfffff),
188  },
189  [1] = {
190  .start = LPD270_ETHERNET_IRQ,
191  .end = LPD270_ETHERNET_IRQ,
192  .flags = IORESOURCE_IRQ,
193  },
194 };
195 
196 static struct platform_device smc91x_device = {
197  .name = "smc91x",
198  .id = 0,
199  .num_resources = ARRAY_SIZE(smc91x_resources),
200  .resource = smc91x_resources,
201 };
202 
203 static struct resource lpd270_flash_resources[] = {
204  [0] = {
205  .start = PXA_CS0_PHYS,
206  .end = PXA_CS0_PHYS + SZ_64M - 1,
207  .flags = IORESOURCE_MEM,
208  },
209  [1] = {
210  .start = PXA_CS1_PHYS,
211  .end = PXA_CS1_PHYS + SZ_64M - 1,
212  .flags = IORESOURCE_MEM,
213  },
214 };
215 
216 static struct mtd_partition lpd270_flash0_partitions[] = {
217  {
218  .name = "Bootloader",
219  .size = 0x00040000,
220  .offset = 0,
221  .mask_flags = MTD_WRITEABLE /* force read-only */
222  }, {
223  .name = "Kernel",
224  .size = 0x00400000,
225  .offset = 0x00040000,
226  }, {
227  .name = "Filesystem",
228  .size = MTDPART_SIZ_FULL,
229  .offset = 0x00440000
230  },
231 };
232 
233 static struct flash_platform_data lpd270_flash_data[2] = {
234  {
235  .name = "processor-flash",
236  .map_name = "cfi_probe",
237  .parts = lpd270_flash0_partitions,
238  .nr_parts = ARRAY_SIZE(lpd270_flash0_partitions),
239  }, {
240  .name = "mainboard-flash",
241  .map_name = "cfi_probe",
242  .parts = NULL,
243  .nr_parts = 0,
244  }
245 };
246 
247 static struct platform_device lpd270_flash_device[2] = {
248  {
249  .name = "pxa2xx-flash",
250  .id = 0,
251  .dev = {
252  .platform_data = &lpd270_flash_data[0],
253  },
254  .resource = &lpd270_flash_resources[0],
255  .num_resources = 1,
256  }, {
257  .name = "pxa2xx-flash",
258  .id = 1,
259  .dev = {
260  .platform_data = &lpd270_flash_data[1],
261  },
262  .resource = &lpd270_flash_resources[1],
263  .num_resources = 1,
264  },
265 };
266 
267 static struct platform_pwm_backlight_data lpd270_backlight_data = {
268  .pwm_id = 0,
269  .max_brightness = 1,
270  .dft_brightness = 1,
271  .pwm_period_ns = 78770,
272 };
273 
274 static struct platform_device lpd270_backlight_device = {
275  .name = "pwm-backlight",
276  .dev = {
277  .parent = &pxa27x_device_pwm0.dev,
278  .platform_data = &lpd270_backlight_data,
279  },
280 };
281 
282 /* 5.7" TFT QVGA (LoLo display number 1) */
283 static struct pxafb_mode_info sharp_lq057q3dc02_mode = {
284  .pixclock = 150000,
285  .xres = 320,
286  .yres = 240,
287  .bpp = 16,
288  .hsync_len = 0x14,
289  .left_margin = 0x28,
290  .right_margin = 0x0a,
291  .vsync_len = 0x02,
292  .upper_margin = 0x08,
293  .lower_margin = 0x14,
295 };
296 
297 static struct pxafb_mach_info sharp_lq057q3dc02 = {
298  .modes = &sharp_lq057q3dc02_mode,
299  .num_modes = 1,
302 };
303 
304 /* 12.1" TFT SVGA (LoLo display number 2) */
305 static struct pxafb_mode_info sharp_lq121s1dg31_mode = {
306  .pixclock = 50000,
307  .xres = 800,
308  .yres = 600,
309  .bpp = 16,
310  .hsync_len = 0x05,
311  .left_margin = 0x52,
312  .right_margin = 0x05,
313  .vsync_len = 0x04,
314  .upper_margin = 0x14,
315  .lower_margin = 0x0a,
317 };
318 
319 static struct pxafb_mach_info sharp_lq121s1dg31 = {
320  .modes = &sharp_lq121s1dg31_mode,
321  .num_modes = 1,
324 };
325 
326 /* 3.6" TFT QVGA (LoLo display number 3) */
327 static struct pxafb_mode_info sharp_lq036q1da01_mode = {
328  .pixclock = 150000,
329  .xres = 320,
330  .yres = 240,
331  .bpp = 16,
332  .hsync_len = 0x0e,
333  .left_margin = 0x04,
334  .right_margin = 0x0a,
335  .vsync_len = 0x03,
336  .upper_margin = 0x03,
337  .lower_margin = 0x03,
339 };
340 
341 static struct pxafb_mach_info sharp_lq036q1da01 = {
342  .modes = &sharp_lq036q1da01_mode,
343  .num_modes = 1,
346 };
347 
348 /* 6.4" TFT VGA (LoLo display number 5) */
349 static struct pxafb_mode_info sharp_lq64d343_mode = {
350  .pixclock = 25000,
351  .xres = 640,
352  .yres = 480,
353  .bpp = 16,
354  .hsync_len = 0x31,
355  .left_margin = 0x89,
356  .right_margin = 0x19,
357  .vsync_len = 0x12,
358  .upper_margin = 0x22,
359  .lower_margin = 0x00,
361 };
362 
363 static struct pxafb_mach_info sharp_lq64d343 = {
364  .modes = &sharp_lq64d343_mode,
365  .num_modes = 1,
368 };
369 
370 /* 10.4" TFT VGA (LoLo display number 7) */
371 static struct pxafb_mode_info sharp_lq10d368_mode = {
372  .pixclock = 25000,
373  .xres = 640,
374  .yres = 480,
375  .bpp = 16,
376  .hsync_len = 0x31,
377  .left_margin = 0x89,
378  .right_margin = 0x19,
379  .vsync_len = 0x12,
380  .upper_margin = 0x22,
381  .lower_margin = 0x00,
383 };
384 
385 static struct pxafb_mach_info sharp_lq10d368 = {
386  .modes = &sharp_lq10d368_mode,
387  .num_modes = 1,
390 };
391 
392 /* 3.5" TFT QVGA (LoLo display number 8) */
393 static struct pxafb_mode_info sharp_lq035q7db02_20_mode = {
394  .pixclock = 150000,
395  .xres = 240,
396  .yres = 320,
397  .bpp = 16,
398  .hsync_len = 0x0e,
399  .left_margin = 0x0a,
400  .right_margin = 0x0a,
401  .vsync_len = 0x03,
402  .upper_margin = 0x05,
403  .lower_margin = 0x14,
405 };
406 
407 static struct pxafb_mach_info sharp_lq035q7db02_20 = {
408  .modes = &sharp_lq035q7db02_20_mode,
409  .num_modes = 1,
412 };
413 
414 static struct pxafb_mach_info *lpd270_lcd_to_use;
415 
416 static int __init lpd270_set_lcd(char *str)
417 {
418  if (!strnicmp(str, "lq057q3dc02", 11)) {
419  lpd270_lcd_to_use = &sharp_lq057q3dc02;
420  } else if (!strnicmp(str, "lq121s1dg31", 11)) {
421  lpd270_lcd_to_use = &sharp_lq121s1dg31;
422  } else if (!strnicmp(str, "lq036q1da01", 11)) {
423  lpd270_lcd_to_use = &sharp_lq036q1da01;
424  } else if (!strnicmp(str, "lq64d343", 8)) {
425  lpd270_lcd_to_use = &sharp_lq64d343;
426  } else if (!strnicmp(str, "lq10d368", 8)) {
427  lpd270_lcd_to_use = &sharp_lq10d368;
428  } else if (!strnicmp(str, "lq035q7db02-20", 14)) {
429  lpd270_lcd_to_use = &sharp_lq035q7db02_20;
430  } else {
431  printk(KERN_INFO "lpd270: unknown lcd panel [%s]\n", str);
432  }
433 
434  return 1;
435 }
436 
437 __setup("lcd=", lpd270_set_lcd);
438 
439 static struct platform_device *platform_devices[] __initdata = {
440  &smc91x_device,
441  &lpd270_backlight_device,
442  &lpd270_flash_device[0],
443  &lpd270_flash_device[1],
444 };
445 
446 static struct pxaohci_platform_data lpd270_ohci_platform_data = {
447  .port_mode = PMM_PERPORT_MODE,
449 };
450 
451 static void __init lpd270_init(void)
452 {
453  pxa2xx_mfp_config(ARRAY_AND_SIZE(lpd270_pin_config));
454 
458 
459  lpd270_flash_data[0].width = (__raw_readl(BOOT_DEF) & 1) ? 2 : 4;
460  lpd270_flash_data[1].width = 4;
461 
462  /*
463  * System bus arbiter setting:
464  * - Core_Park
465  * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4
466  */
467  ARB_CNTRL = ARB_CORE_PARK | 0x234;
468 
469  platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
470 
472 
473  if (lpd270_lcd_to_use != NULL)
474  pxa_set_fb_info(NULL, lpd270_lcd_to_use);
475 
476  pxa_set_ohci_info(&lpd270_ohci_platform_data);
477 }
478 
479 
480 static struct map_desc lpd270_io_desc[] __initdata = {
481  {
482  .virtual = (unsigned long)LPD270_CPLD_VIRT,
484  .length = LPD270_CPLD_SIZE,
485  .type = MT_DEVICE,
486  },
487 };
488 
489 static void __init lpd270_map_io(void)
490 {
491  pxa27x_map_io();
492  iotable_init(lpd270_io_desc, ARRAY_SIZE(lpd270_io_desc));
493 
494  /* for use I SRAM as framebuffer. */
495  PSLR |= 0x00000F04;
496  PCFR = 0x00000066;
497 }
498 
499 MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine")
500  /* Maintainer: Peter Barada */
501  .atag_offset = 0x100,
502  .map_io = lpd270_map_io,
503  .nr_irqs = LPD270_NR_IRQS,
504  .init_irq = lpd270_init_irq,
505  .handle_irq = pxa27x_handle_irq,
506  .timer = &pxa_timer,
507  .init_machine = lpd270_init,
508  .restart = pxa_restart,