aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-lh7a40x
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-lh7a40x')
-rw-r--r--arch/arm/mach-lh7a40x/Kconfig5
-rw-r--r--arch/arm/mach-lh7a40x/Makefile19
-rw-r--r--arch/arm/mach-lh7a40x/arch-lpd7a40x.c200
-rw-r--r--arch/arm/mach-lh7a40x/clcd.c241
-rw-r--r--arch/arm/mach-lh7a40x/clocks.c199
-rw-r--r--arch/arm/mach-lh7a40x/common.h1
-rw-r--r--arch/arm/mach-lh7a40x/irq-lh7a404.c17
-rw-r--r--arch/arm/mach-lh7a40x/lcd-panel.h346
-rw-r--r--arch/arm/mach-lh7a40x/ssp-cpld.c343
-rw-r--r--arch/arm/mach-lh7a40x/time.c4
10 files changed, 1303 insertions, 72 deletions
diff --git a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig
index 8a17867a6a24..558a34f53b1c 100644
--- a/arch/arm/mach-lh7a40x/Kconfig
+++ b/arch/arm/mach-lh7a40x/Kconfig
@@ -14,6 +14,7 @@ config MACH_LPD7A400
14 bool "LPD7A400 Card Engine" 14 bool "LPD7A400 Card Engine"
15 select ARCH_LH7A400 15 select ARCH_LH7A400
16# select IDE_POLL 16# select IDE_POLL
17 select HAS_TOUCHSCREEN_ADS7843_LH7
17 help 18 help
18 Say Y here if you are using Logic Product Development's 19 Say Y here if you are using Logic Product Development's
19 LPD7A400 CardEngine. For the time being, the LPD7A400 and 20 LPD7A400 CardEngine. For the time being, the LPD7A400 and
@@ -23,6 +24,7 @@ config MACH_LPD7A404
23 bool "LPD7A404 Card Engine" 24 bool "LPD7A404 Card Engine"
24 select ARCH_LH7A404 25 select ARCH_LH7A404
25# select IDE_POLL 26# select IDE_POLL
27 select HAS_TOUCHSCREEN_ADC_LH7
26 help 28 help
27 Say Y here if you are using Logic Product Development's 29 Say Y here if you are using Logic Product Development's
28 LPD7A404 CardEngine. For the time being, the LPD7A400 and 30 LPD7A404 CardEngine. For the time being, the LPD7A400 and
@@ -34,6 +36,9 @@ config ARCH_LH7A400
34config ARCH_LH7A404 36config ARCH_LH7A404
35 bool 37 bool
36 38
39config LPD7A40X_CPLD_SSP
40 bool
41
37config LH7A40X_CONTIGMEM 42config LH7A40X_CONTIGMEM
38 bool "Disable NUMA Support" 43 bool "Disable NUMA Support"
39 depends on ARCH_LH7A40X 44 depends on ARCH_LH7A40X
diff --git a/arch/arm/mach-lh7a40x/Makefile b/arch/arm/mach-lh7a40x/Makefile
index e90512dbc2d6..94b8615fb3c3 100644
--- a/arch/arm/mach-lh7a40x/Makefile
+++ b/arch/arm/mach-lh7a40x/Makefile
@@ -4,11 +4,14 @@
4 4
5# Object file lists. 5# Object file lists.
6 6
7obj-y := time.o 7obj-y := time.o clocks.o
8obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o 8obj-m :=
9obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o irq-lh7a400.o 9obj-n :=
10obj-$(CONFIG_MACH_LPD7A404) += arch-lpd7a40x.o irq-lh7a404.o 10obj- :=
11 11
12obj-m := 12obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o
13obj-n := 13obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o irq-lh7a400.o
14obj- := 14obj-$(CONFIG_MACH_LPD7A404) += arch-lpd7a40x.o irq-lh7a404.o
15obj-$(CONFIG_LPD7A40X_CPLD_SSP) += ssp-cpld.o
16obj-$(CONFIG_FB_ARMCLCD) += clcd.o
17
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index 12e23277c5ea..c0e6854289f1 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -23,6 +23,28 @@
23 23
24#include "common.h" 24#include "common.h"
25 25
26#define CPLD_INT_NETHERNET (1<<0)
27#define CPLD_INTMASK_ETHERNET (1<<2)
28#if defined (CONFIG_MACH_LPD7A400)
29# define CPLD_INT_NTOUCH (1<<1)
30# define CPLD_INTMASK_TOUCH (1<<3)
31# define CPLD_INT_PEN (1<<4)
32# define CPLD_INTMASK_PEN (1<<4)
33# define CPLD_INT_PIRQ (1<<4)
34#endif
35#define CPLD_INTMASK_CPLD (1<<7)
36#define CPLD_INT_CPLD (1<<6)
37
38#define CPLD_CONTROL_SWINT (1<<7) /* Disable all CPLD IRQs */
39#define CPLD_CONTROL_OCMSK (1<<6) /* Mask USB1 connect IRQ */
40#define CPLD_CONTROL_PDRV (1<<5) /* PCC_nDRV high */
41#define CPLD_CONTROL_USB1C (1<<4) /* USB1 connect IRQ active */
42#define CPLD_CONTROL_USB1P (1<<3) /* USB1 power disable */
43#define CPLD_CONTROL_AWKP (1<<2) /* Auto-wakeup disabled */
44#define CPLD_CONTROL_LCD_ENABLE (1<<1) /* LCD Vee enable */
45#define CPLD_CONTROL_WRLAN_NENABLE (1<<0) /* SMC91x power disable */
46
47
26static struct resource smc91x_resources[] = { 48static struct resource smc91x_resources[] = {
27 [0] = { 49 [0] = {
28 .start = CPLD00_PHYS, 50 .start = CPLD00_PHYS,
@@ -48,12 +70,12 @@ static struct platform_device smc91x_device = {
48static struct resource lh7a40x_usbclient_resources[] = { 70static struct resource lh7a40x_usbclient_resources[] = {
49 [0] = { 71 [0] = {
50 .start = USB_PHYS, 72 .start = USB_PHYS,
51 .end = (USB_PHYS + 0xFF), 73 .end = (USB_PHYS + PAGE_SIZE),
52 .flags = IORESOURCE_MEM, 74 .flags = IORESOURCE_MEM,
53 }, 75 },
54 [1] = { 76 [1] = {
55 .start = IRQ_USBINTR, 77 .start = IRQ_USB,
56 .end = IRQ_USBINTR, 78 .end = IRQ_USB,
57 .flags = IORESOURCE_IRQ, 79 .flags = IORESOURCE_IRQ,
58 }, 80 },
59}; 81};
@@ -61,7 +83,8 @@ static struct resource lh7a40x_usbclient_resources[] = {
61static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL; 83static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL;
62 84
63static struct platform_device lh7a40x_usbclient_device = { 85static struct platform_device lh7a40x_usbclient_device = {
64 .name = "lh7a40x_udc", 86// .name = "lh7a40x_udc",
87 .name = "lh7-udc",
65 .id = 0, 88 .id = 0,
66 .dev = { 89 .dev = {
67 .dma_mask = &lh7a40x_usbclient_dma_mask, 90 .dma_mask = &lh7a40x_usbclient_dma_mask,
@@ -101,7 +124,7 @@ static struct platform_device lh7a404_usbhost_device = {
101 124
102#endif 125#endif
103 126
104static struct platform_device *lpd7a40x_devs[] __initdata = { 127static struct platform_device* lpd7a40x_devs[] __initdata = {
105 &smc91x_device, 128 &smc91x_device,
106 &lh7a40x_usbclient_device, 129 &lh7a40x_usbclient_device,
107#if defined (CONFIG_ARCH_LH7A404) 130#if defined (CONFIG_ARCH_LH7A404)
@@ -113,29 +136,52 @@ extern void lpd7a400_map_io (void);
113 136
114static void __init lpd7a40x_init (void) 137static void __init lpd7a40x_init (void)
115{ 138{
116 CPLD_CONTROL |= (1<<6); /* Mask USB1 connection IRQ */ 139#if defined (CONFIG_MACH_LPD7A400)
140 CPLD_CONTROL |= 0
141 | CPLD_CONTROL_SWINT /* Disable software interrupt */
142 | CPLD_CONTROL_OCMSK; /* Mask USB1 connection IRQ */
117 CPLD_CONTROL &= ~(0 143 CPLD_CONTROL &= ~(0
118 | (1<<1) /* Disable LCD */ 144 | CPLD_CONTROL_LCD_ENABLE /* Disable LCD */
119 | (1<<0) /* Enable WLAN */ 145 | CPLD_CONTROL_WRLAN_NENABLE /* Enable SMC91x */
120 ); 146 );
147#endif
148
149#if defined (CONFIG_MACH_LPD7A404)
150 CPLD_CONTROL &= ~(0
151 | CPLD_CONTROL_WRLAN_NENABLE /* Enable SMC91x */
152 );
153#endif
121 154
122 platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs)); 155 platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs));
156#if defined (CONFIG_FB_ARMCLCD)
157 lh7a40x_clcd_init ();
158#endif
123} 159}
124 160
125static void lh7a40x_ack_cpld_irq (u32 irq) 161static void lh7a40x_ack_cpld_irq (u32 irq)
126{ 162{
127 /* CPLD doesn't have ack capability */ 163 /* CPLD doesn't have ack capability, but some devices may */
164
165#if defined (CPLD_INTMASK_TOUCH)
166 /* The touch control *must* mask the the interrupt because the
167 * interrupt bit is read by the driver to determine if the pen
168 * is still down. */
169 if (irq == IRQ_TOUCH)
170 CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
171#endif
128} 172}
129 173
130static void lh7a40x_mask_cpld_irq (u32 irq) 174static void lh7a40x_mask_cpld_irq (u32 irq)
131{ 175{
132 switch (irq) { 176 switch (irq) {
133 case IRQ_LPD7A40X_ETH_INT: 177 case IRQ_LPD7A40X_ETH_INT:
134 CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4; 178 CPLD_INTERRUPTS |= CPLD_INTMASK_ETHERNET;
135 break; 179 break;
136 case IRQ_LPD7A400_TS: 180#if defined (IRQ_TOUCH)
137 CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8; 181 case IRQ_TOUCH:
182 CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
138 break; 183 break;
184#endif
139 } 185 }
140} 186}
141 187
@@ -143,11 +189,13 @@ static void lh7a40x_unmask_cpld_irq (u32 irq)
143{ 189{
144 switch (irq) { 190 switch (irq) {
145 case IRQ_LPD7A40X_ETH_INT: 191 case IRQ_LPD7A40X_ETH_INT:
146 CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4; 192 CPLD_INTERRUPTS &= ~CPLD_INTMASK_ETHERNET;
147 break; 193 break;
148 case IRQ_LPD7A400_TS: 194#if defined (IRQ_TOUCH)
149 CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8; 195 case IRQ_TOUCH:
196 CPLD_INTERRUPTS &= ~CPLD_INTMASK_TOUCH;
150 break; 197 break;
198#endif
151 } 199 }
152} 200}
153 201
@@ -164,11 +212,13 @@ static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
164 212
165 desc->chip->ack (irq); 213 desc->chip->ack (irq);
166 214
167 if ((mask & 0x1) == 0) /* WLAN */ 215 if ((mask & (1<<0)) == 0) /* WLAN */
168 IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT); 216 IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT);
169 217
170 if ((mask & 0x2) == 0) /* Touch */ 218#if defined (IRQ_TOUCH)
171 IRQ_DISPATCH (IRQ_LPD7A400_TS); 219 if ((mask & (1<<1)) == 0) /* Touch */
220 IRQ_DISPATCH (IRQ_TOUCH);
221#endif
172 222
173 desc->chip->unmask (irq); /* Level-triggered need this */ 223 desc->chip->unmask (irq); /* Level-triggered need this */
174} 224}
@@ -204,9 +254,21 @@ void __init lh7a40x_init_board_irq (void)
204 254
205 /* Then, configure CPLD interrupt */ 255 /* Then, configure CPLD interrupt */
206 256
207 CPLD_INTERRUPTS = 0x9c; /* Disable all CPLD interrupts */ 257 /* Disable all CPLD interrupts */
258#if defined (CONFIG_MACH_LPD7A400)
259 CPLD_INTERRUPTS = CPLD_INTMASK_TOUCH | CPLD_INTMASK_PEN
260 | CPLD_INTMASK_ETHERNET;
261 /* *** FIXME: don't know why we need 7 and 4. 7 is way wrong
262 and 4 is uncefined. */
263 // (1<<7)|(1<<4)|(1<<3)|(1<<2);
264#endif
265#if defined (CONFIG_MACH_LPD7A404)
266 CPLD_INTERRUPTS = CPLD_INTMASK_ETHERNET;
267 /* *** FIXME: don't know why we need 6 and 5, neither is defined. */
268 // (1<<6)|(1<<5)|(1<<3);
269#endif
208 GPIO_PFDD &= ~(1 << pinCPLD); /* Make input */ 270 GPIO_PFDD &= ~(1 << pinCPLD); /* Make input */
209 GPIO_INTTYPE1 |= (1 << pinCPLD); /* Edge triggered */ 271 GPIO_INTTYPE1 &= ~(1 << pinCPLD); /* Level triggered */
210 GPIO_INTTYPE2 &= ~(1 << pinCPLD); /* Active low */ 272 GPIO_INTTYPE2 &= ~(1 << pinCPLD); /* Active low */
211 barrier (); 273 barrier ();
212 GPIO_GPIOFINTEN |= (1 << pinCPLD); /* Enable */ 274 GPIO_GPIOFINTEN |= (1 << pinCPLD); /* Enable */
@@ -216,7 +278,7 @@ void __init lh7a40x_init_board_irq (void)
216 for (irq = IRQ_BOARD_START; 278 for (irq = IRQ_BOARD_START;
217 irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) { 279 irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
218 set_irq_chip (irq, &lpd7a40x_cpld_chip); 280 set_irq_chip (irq, &lpd7a40x_cpld_chip);
219 set_irq_handler (irq, do_edge_IRQ); 281 set_irq_handler (irq, do_level_IRQ);
220 set_irq_flags (irq, IRQF_VALID); 282 set_irq_flags (irq, IRQF_VALID);
221 } 283 }
222 284
@@ -226,91 +288,109 @@ void __init lh7a40x_init_board_irq (void)
226 lpd7a40x_cpld_handler); 288 lpd7a40x_cpld_handler);
227} 289}
228 290
229static struct map_desc lpd7a400_io_desc[] __initdata = { 291static struct map_desc lpd7a40x_io_desc[] __initdata = {
230 { 292 {
231 .virtual = IO_VIRT, 293 .virtual = IO_VIRT,
232 .pfn = __phys_to_pfn(IO_PHYS), 294 .pfn = __phys_to_pfn(IO_PHYS),
233 .length = IO_SIZE, 295 .length = IO_SIZE,
234 .type = MT_DEVICE 296 .type = MT_DEVICE
235 }, { /* Mapping added to work around chip select problems */ 297 },
298 { /* Mapping added to work around chip select problems */
236 .virtual = IOBARRIER_VIRT, 299 .virtual = IOBARRIER_VIRT,
237 .pfn = __phys_to_pfn(IOBARRIER_PHYS), 300 .pfn = __phys_to_pfn(IOBARRIER_PHYS),
238 .length = IOBARRIER_SIZE, 301 .length = IOBARRIER_SIZE,
239 .type = MT_DEVICE 302 .type = MT_DEVICE
240 }, { 303 },
304 {
241 .virtual = CF_VIRT, 305 .virtual = CF_VIRT,
242 .pfn = __phys_to_pfn(CF_PHYS), 306 .pfn = __phys_to_pfn(CF_PHYS),
243 .length = CF_SIZE, 307 .length = CF_SIZE,
244 .type = MT_DEVICE 308 .type = MT_DEVICE
245 }, { 309 },
310 {
246 .virtual = CPLD02_VIRT, 311 .virtual = CPLD02_VIRT,
247 .pfn = __phys_to_pfn(CPLD02_PHYS), 312 .pfn = __phys_to_pfn(CPLD02_PHYS),
248 .length = CPLD02_SIZE, 313 .length = CPLD02_SIZE,
249 .type = MT_DEVICE 314 .type = MT_DEVICE
250 }, { 315 },
316 {
251 .virtual = CPLD06_VIRT, 317 .virtual = CPLD06_VIRT,
252 .pfn = __phys_to_pfn(CPLD06_PHYS), 318 .pfn = __phys_to_pfn(CPLD06_PHYS),
253 .length = CPLD06_SIZE, 319 .length = CPLD06_SIZE,
320 .type = MT_DEVICE
321 },
322 {
323 .virtual = CPLD08_VIRT,
324 .pfn = __phys_to_pfn(CPLD08_PHYS),
325 .length = CPLD08_SIZE,
254 .type = MT_DEVICE 326 .type = MT_DEVICE
255 }, { 327 },
328 {
256 .virtual = CPLD08_VIRT, 329 .virtual = CPLD08_VIRT,
257 .pfn = __phys_to_pfn(CPLD08_PHYS), 330 .pfn = __phys_to_pfn(CPLD08_PHYS),
258 .length = CPLD08_SIZE, 331 .length = CPLD08_SIZE,
259 .type = MT_DEVICE 332 .type = MT_DEVICE
260 }, { 333 },
334 {
335 .virtual = CPLD0A_VIRT,
336 .pfn = __phys_to_pfn(CPLD0A_PHYS),
337 .length = CPLD0A_SIZE,
338 .type = MT_DEVICE
339 },
340 {
261 .virtual = CPLD0C_VIRT, 341 .virtual = CPLD0C_VIRT,
262 .pfn = __phys_to_pfn(CPLD0C_PHYS), 342 .pfn = __phys_to_pfn(CPLD0C_PHYS),
263 .length = CPLD0C_SIZE, 343 .length = CPLD0C_SIZE,
264 .type = MT_DEVICE 344 .type = MT_DEVICE
265 }, { 345 },
346 {
266 .virtual = CPLD0E_VIRT, 347 .virtual = CPLD0E_VIRT,
267 .pfn = __phys_to_pfn(CPLD0E_PHYS), 348 .pfn = __phys_to_pfn(CPLD0E_PHYS),
268 .length = CPLD0E_SIZE, 349 .length = CPLD0E_SIZE,
269 .type = MT_DEVICE 350 .type = MT_DEVICE
270 }, { 351 },
352 {
271 .virtual = CPLD10_VIRT, 353 .virtual = CPLD10_VIRT,
272 .pfn = __phys_to_pfn(CPLD10_PHYS), 354 .pfn = __phys_to_pfn(CPLD10_PHYS),
273 .length = CPLD10_SIZE, 355 .length = CPLD10_SIZE,
274 .type = MT_DEVICE 356 .type = MT_DEVICE
275 }, { 357 },
358 {
276 .virtual = CPLD12_VIRT, 359 .virtual = CPLD12_VIRT,
277 .pfn = __phys_to_pfn(CPLD12_PHYS), 360 .pfn = __phys_to_pfn(CPLD12_PHYS),
278 .length = CPLD12_SIZE, 361 .length = CPLD12_SIZE,
279 .type = MT_DEVICE 362 .type = MT_DEVICE
280 }, { 363 },
364 {
281 .virtual = CPLD14_VIRT, 365 .virtual = CPLD14_VIRT,
282 .pfn = __phys_to_pfn(CPLD14_PHYS), 366 .pfn = __phys_to_pfn(CPLD14_PHYS),
283 .length = CPLD14_SIZE, 367 .length = CPLD14_SIZE,
284 .type = MT_DEVICE 368 .type = MT_DEVICE
285 }, { 369 },
370 {
286 .virtual = CPLD16_VIRT, 371 .virtual = CPLD16_VIRT,
287 .pfn = __phys_to_pfn(CPLD16_PHYS), 372 .pfn = __phys_to_pfn(CPLD16_PHYS),
288 .length = CPLD16_SIZE, 373 .length = CPLD16_SIZE,
289 .type = MT_DEVICE 374 .type = MT_DEVICE
290 }, { 375 },
376 {
291 .virtual = CPLD18_VIRT, 377 .virtual = CPLD18_VIRT,
292 .pfn = __phys_to_pfn(CPLD18_PHYS), 378 .pfn = __phys_to_pfn(CPLD18_PHYS),
293 .length = CPLD18_SIZE, 379 .length = CPLD18_SIZE,
294 .type = MT_DEVICE 380 .type = MT_DEVICE
295 }, { 381 },
382 {
296 .virtual = CPLD1A_VIRT, 383 .virtual = CPLD1A_VIRT,
297 .pfn = __phys_to_pfn(CPLD1A_PHYS), 384 .pfn = __phys_to_pfn(CPLD1A_PHYS),
298 .length = CPLD1A_SIZE, 385 .length = CPLD1A_SIZE,
299 .type = MT_DEVICE 386 .type = MT_DEVICE
300 }, 387 },
301 /* This mapping is redundant since the smc driver performs another. */
302/* { CPLD00_VIRT, CPLD00_PHYS, CPLD00_SIZE, MT_DEVICE }, */
303}; 388};
304 389
305void __init 390void __init
306lpd7a400_map_io(void) 391lpd7a40x_map_io(void)
307{ 392{
308 iotable_init (lpd7a400_io_desc, ARRAY_SIZE (lpd7a400_io_desc)); 393 iotable_init (lpd7a40x_io_desc, ARRAY_SIZE (lpd7a40x_io_desc));
309
310 /* Fixup (improve) Static Memory Controller settings */
311 SMC_BCR0 = 0x200039af; /* Boot Flash */
312 SMC_BCR6 = 0x1000fbe0; /* CPLD */
313 SMC_BCR7 = 0x1000b2c2; /* Compact Flash */
314} 394}
315 395
316#ifdef CONFIG_MACH_LPD7A400 396#ifdef CONFIG_MACH_LPD7A400
@@ -320,7 +400,7 @@ MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
320 .phys_io = 0x80000000, 400 .phys_io = 0x80000000,
321 .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, 401 .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
322 .boot_params = 0xc0000100, 402 .boot_params = 0xc0000100,
323 .map_io = lpd7a400_map_io, 403 .map_io = lpd7a40x_map_io,
324 .init_irq = lh7a400_init_irq, 404 .init_irq = lh7a400_init_irq,
325 .timer = &lh7a40x_timer, 405 .timer = &lh7a40x_timer,
326 .init_machine = lpd7a40x_init, 406 .init_machine = lpd7a40x_init,
@@ -335,7 +415,7 @@ MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
335 .phys_io = 0x80000000, 415 .phys_io = 0x80000000,
336 .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc, 416 .io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
337 .boot_params = 0xc0000100, 417 .boot_params = 0xc0000100,
338 .map_io = lpd7a400_map_io, 418 .map_io = lpd7a40x_map_io,
339 .init_irq = lh7a404_init_irq, 419 .init_irq = lh7a404_init_irq,
340 .timer = &lh7a40x_timer, 420 .timer = &lh7a40x_timer,
341 .init_machine = lpd7a40x_init, 421 .init_machine = lpd7a40x_init,
diff --git a/arch/arm/mach-lh7a40x/clcd.c b/arch/arm/mach-lh7a40x/clcd.c
new file mode 100644
index 000000000000..93751fee793d
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/clcd.c
@@ -0,0 +1,241 @@
1/*
2 * arch/arm/mach-lh7a40x/clcd.c
3 *
4 * Copyright (C) 2004 Marc Singer
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 */
11#include <linux/config.h>
12#include <linux/init.h>
13#include <linux/device.h>
14#include <linux/dma-mapping.h>
15#include <linux/sysdev.h>
16#include <linux/interrupt.h>
17
18//#include <linux/module.h>
19//#include <linux/time.h>
20//#include <asm/hardware.h>
21
22//#include <asm/mach/time.h>
23#include <asm/irq.h>
24#include <asm/mach/irq.h>
25
26#include <asm/system.h>
27#include <asm/hardware.h>
28#include <linux/amba/bus.h>
29#include <linux/amba/clcd.h>
30
31#define HRTFTC_HRSETUP __REG(HRTFTC_PHYS + 0x00)
32#define HRTFTC_HRCON __REG(HRTFTC_PHYS + 0x04)
33#define HRTFTC_HRTIMING1 __REG(HRTFTC_PHYS + 0x08)
34#define HRTFTC_HRTIMING2 __REG(HRTFTC_PHYS + 0x0c)
35
36#define ALI_SETUP __REG(ALI_PHYS + 0x00)
37#define ALI_CONTROL __REG(ALI_PHYS + 0x04)
38#define ALI_TIMING1 __REG(ALI_PHYS + 0x08)
39#define ALI_TIMING2 __REG(ALI_PHYS + 0x0c)
40
41#include "lcd-panel.h"
42
43static void lh7a40x_clcd_disable (struct clcd_fb *fb)
44{
45#if defined (CONFIG_MACH_LPD7A400)
46 CPLD_CONTROL &= ~(1<<1); /* Disable LCD Vee */
47#endif
48
49#if defined (CONFIG_MACH_LPD7A404)
50 GPIO_PCD &= ~(1<<3); /* Disable LCD Vee */
51#endif
52
53#if defined (CONFIG_ARCH_LH7A400)
54 HRTFTC_HRSETUP &= ~(1<<13); /* Disable HRTFT controller */
55#endif
56
57#if defined (CONFIG_ARCH_LH7A404)
58 ALI_SETUP &= ~(1<<13); /* Disable ALI */
59#endif
60}
61
62static void lh7a40x_clcd_enable (struct clcd_fb *fb)
63{
64 struct clcd_panel_extra* extra
65 = (struct clcd_panel_extra*) fb->board_data;
66
67#if defined (CONFIG_MACH_LPD7A400)
68 CPLD_CONTROL |= (1<<1); /* Enable LCD Vee */
69#endif
70
71#if defined (CONFIG_MACH_LPD7A404)
72 GPIO_PCDD &= ~(1<<3); /* Enable LCD Vee */
73 GPIO_PCD |= (1<<3);
74#endif
75
76#if defined (CONFIG_ARCH_LH7A400)
77
78 if (extra) {
79 HRTFTC_HRSETUP
80 = (1 << 13)
81 | ((fb->fb.var.xres - 1) << 4)
82 | 0xc
83 | (extra->hrmode ? 1 : 0);
84 HRTFTC_HRCON
85 = ((extra->clsen ? 1 : 0) << 1)
86 | ((extra->spsen ? 1 : 0) << 0);
87 HRTFTC_HRTIMING1
88 = (extra->pcdel << 8)
89 | (extra->revdel << 4)
90 | (extra->lpdel << 0);
91 HRTFTC_HRTIMING2
92 = (extra->spldel << 9)
93 | (extra->pc2del << 0);
94 }
95 else
96 HRTFTC_HRSETUP
97 = (1 << 13)
98 | 0xc;
99#endif
100
101#if defined (CONFIG_ARCH_LH7A404)
102
103 if (extra) {
104 ALI_SETUP
105 = (1 << 13)
106 | ((fb->fb.var.xres - 1) << 4)
107 | 0xc
108 | (extra->hrmode ? 1 : 0);
109 ALI_CONTROL
110 = ((extra->clsen ? 1 : 0) << 1)
111 | ((extra->spsen ? 1 : 0) << 0);
112 ALI_TIMING1
113 = (extra->pcdel << 8)
114 | (extra->revdel << 4)
115 | (extra->lpdel << 0);
116 ALI_TIMING2
117 = (extra->spldel << 9)
118 | (extra->pc2del << 0);
119 }
120 else
121 ALI_SETUP
122 = (1 << 13)
123 | 0xc;
124#endif
125
126}
127
128#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
129
130static int lh7a40x_clcd_setup (struct clcd_fb *fb)
131{
132 dma_addr_t dma;
133 u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
134 *(lcd_panel.bpp/8));
135
136 fb->panel = &lcd_panel;
137
138 /* Enforce the sync polarity defaults */
139 if (!(fb->panel->tim2 & TIM2_IHS))
140 fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
141 if (!(fb->panel->tim2 & TIM2_IVS))
142 fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
143
144#if defined (HAS_LCD_PANEL_EXTRA)
145 fb->board_data = &lcd_panel_extra;
146#endif
147
148 fb->fb.screen_base
149 = dma_alloc_writecombine (&fb->dev->dev, len,
150 &dma, GFP_KERNEL);
151 printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
152 fb->fb.screen_base, (void*) dma, len,
153 (void*) io_p2v (CLCDC_PHYS));
154 printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
155
156 if (!fb->fb.screen_base) {
157 printk(KERN_ERR "CLCD: unable to map framebuffer\n");
158 return -ENOMEM;
159 }
160
161#if defined (USE_RGB555)
162 fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
163#endif
164
165 fb->fb.fix.smem_start = dma;
166 fb->fb.fix.smem_len = len;
167
168 /* Drive PE4 high to prevent CPLD crash */
169 GPIO_PEDD |= (1<<4);
170 GPIO_PED |= (1<<4);
171
172 GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
173
174// fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
175// fb->fb.fbops->fb_set_par (&fb->fb);
176
177 return 0;
178}
179
180static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
181{
182 return dma_mmap_writecombine(&fb->dev->dev, vma,
183 fb->fb.screen_base,
184 fb->fb.fix.smem_start,
185 fb->fb.fix.smem_len);
186}
187
188static void lh7a40x_clcd_remove (struct clcd_fb *fb)
189{
190 dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
191 fb->fb.screen_base, fb->fb.fix.smem_start);
192}
193
194static struct clcd_board clcd_platform_data = {
195 .name = "lh7a40x FB",
196 .check = clcdfb_check,
197 .decode = clcdfb_decode,
198 .enable = lh7a40x_clcd_enable,
199 .setup = lh7a40x_clcd_setup,
200 .mmap = lh7a40x_clcd_mmap,
201 .remove = lh7a40x_clcd_remove,
202 .disable = lh7a40x_clcd_disable,
203};
204
205#define IRQ_CLCDC (IRQ_LCDINTR)
206
207#define AMBA_DEVICE(name,busid,base,plat,pid) \
208static struct amba_device name##_device = { \
209 .dev = { \
210 .coherent_dma_mask = ~0, \
211 .bus_id = busid, \
212 .platform_data = plat, \
213 }, \
214 .res = { \
215 .start = base##_PHYS, \
216 .end = (base##_PHYS) + (4*1024) - 1, \
217 .flags = IORESOURCE_MEM, \
218 }, \
219 .dma_mask = ~0, \
220 .irq = { IRQ_##base, }, \
221 /* .dma = base##_DMA,*/ \
222 .periphid = pid, \
223}
224
225AMBA_DEVICE(clcd, "cldc-lh7a40x", CLCDC, &clcd_platform_data, 0x41110);
226
227static struct amba_device *amba_devs[] __initdata = {
228 &clcd_device,
229};
230
231void __init lh7a40x_clcd_init (void)
232{
233 int i;
234 int result;
235 printk ("CLCD: registering amba devices\n");
236 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
237 struct amba_device *d = amba_devs[i];
238 result = amba_device_register(d, &iomem_resource);
239 printk (" %d -> %d\n", i ,result);
240 }
241}
diff --git a/arch/arm/mach-lh7a40x/clocks.c b/arch/arm/mach-lh7a40x/clocks.c
new file mode 100644
index 000000000000..2291afe9f23e
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/clocks.c
@@ -0,0 +1,199 @@
1/* arch/arm/mach-lh7a40x/clocks.c
2 *
3 * Copyright (C) 2004 Marc Singer
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/config.h>
12#include <linux/cpufreq.h>
13#include <asm/hardware.h>
14#include <asm/arch/clocks.h>
15#include <linux/err.h>
16
17struct module;
18struct icst525_params;
19
20struct clk {
21 struct list_head node;
22 unsigned long rate;
23 struct module *owner;
24 const char *name;
25// void *data;
26// const struct icst525_params *params;
27// void (*setvco)(struct clk *, struct icst525_vco vco);
28};
29
30int clk_register(struct clk *clk);
31void clk_unregister(struct clk *clk);
32
33/* ----- */
34
35#define MAINDIV1(c) (((c) >> 7) & 0x0f)
36#define MAINDIV2(c) (((c) >> 11) & 0x1f)
37#define PS(c) (((c) >> 18) & 0x03)
38#define PREDIV(c) (((c) >> 2) & 0x1f)
39#define HCLKDIV(c) (((c) >> 0) & 0x02)
40#define PCLKDIV(c) (((c) >> 16) & 0x03)
41
42unsigned int cpufreq_get (unsigned int cpu) /* in kHz */
43{
44 return fclkfreq_get ()/1000;
45}
46EXPORT_SYMBOL(cpufreq_get);
47
48unsigned int fclkfreq_get (void)
49{
50 unsigned int clkset = CSC_CLKSET;
51 unsigned int gclk
52 = XTAL_IN
53 / (1 << PS(clkset))
54 * (MAINDIV1(clkset) + 2)
55 / (PREDIV(clkset) + 2)
56 * (MAINDIV2(clkset) + 2)
57 ;
58 return gclk;
59}
60
61unsigned int hclkfreq_get (void)
62{
63 unsigned int clkset = CSC_CLKSET;
64 unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1);
65
66 return hclk;
67}
68
69unsigned int pclkfreq_get (void)
70{
71 unsigned int clkset = CSC_CLKSET;
72 int pclkdiv = PCLKDIV(clkset);
73 unsigned int pclk;
74 if (pclkdiv == 0x3)
75 pclkdiv = 0x2;
76 pclk = hclkfreq_get () / (1 << pclkdiv);
77
78 return pclk;
79}
80
81/* ----- */
82
83static LIST_HEAD(clocks);
84static DECLARE_MUTEX(clocks_sem);
85
86struct clk *clk_get (struct device *dev, const char *id)
87{
88 struct clk *p;
89 struct clk *clk = ERR_PTR(-ENOENT);
90
91 down (&clocks_sem);
92 list_for_each_entry (p, &clocks, node) {
93 if (strcmp (id, p->name) == 0
94 && try_module_get(p->owner)) {
95 clk = p;
96 break;
97 }
98 }
99 up (&clocks_sem);
100
101 return clk;
102}
103EXPORT_SYMBOL(clk_get);
104
105void clk_put (struct clk *clk)
106{
107 module_put(clk->owner);
108}
109EXPORT_SYMBOL(clk_put);
110
111int clk_enable (struct clk *clk)
112{
113 return 0;
114}
115EXPORT_SYMBOL(clk_enable);
116
117void clk_disable (struct clk *clk)
118{
119}
120EXPORT_SYMBOL(clk_disable);
121
122int clk_use (struct clk *clk)
123{
124 return 0;
125}
126EXPORT_SYMBOL(clk_use);
127
128void clk_unuse (struct clk *clk)
129{
130}
131EXPORT_SYMBOL(clk_unuse);
132
133unsigned long clk_get_rate (struct clk *clk)
134{
135 return clk->rate;
136}
137EXPORT_SYMBOL(clk_get_rate);
138
139long clk_round_rate (struct clk *clk, unsigned long rate)
140{
141 return rate;
142}
143EXPORT_SYMBOL(clk_round_rate);
144
145int clk_set_rate (struct clk *clk, unsigned long rate)
146{
147 int ret = -EIO;
148 return ret;
149}
150EXPORT_SYMBOL(clk_set_rate);
151
152#if 0
153/*
154 * These are fixed clocks.
155 */
156static struct clk kmi_clk = {
157 .name = "KMIREFCLK",
158 .rate = 24000000,
159};
160
161static struct clk uart_clk = {
162 .name = "UARTCLK",
163 .rate = 24000000,
164};
165
166static struct clk mmci_clk = {
167 .name = "MCLK",
168 .rate = 33000000,
169};
170#endif
171
172static struct clk clcd_clk = {
173 .name = "CLCDCLK",
174 .rate = 0,
175};
176
177int clk_register (struct clk *clk)
178{
179 down (&clocks_sem);
180 list_add (&clk->node, &clocks);
181 up (&clocks_sem);
182 return 0;
183}
184EXPORT_SYMBOL(clk_register);
185
186void clk_unregister (struct clk *clk)
187{
188 down (&clocks_sem);
189 list_del (&clk->node);
190 up (&clocks_sem);
191}
192EXPORT_SYMBOL(clk_unregister);
193
194static int __init clk_init (void)
195{
196 clk_register(&clcd_clk);
197 return 0;
198}
199arch_initcall(clk_init);
diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h
index ea8de7e3ab1b..18e8bb4eb202 100644
--- a/arch/arm/mach-lh7a40x/common.h
+++ b/arch/arm/mach-lh7a40x/common.h
@@ -12,6 +12,7 @@ extern struct sys_timer lh7a40x_timer;
12 12
13extern void lh7a400_init_irq (void); 13extern void lh7a400_init_irq (void);
14extern void lh7a404_init_irq (void); 14extern void lh7a404_init_irq (void);
15extern void lh7a40x_clcd_init (void);
15extern void lh7a40x_init_board_irq (void); 16extern void lh7a40x_init_board_irq (void);
16 17
17#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs) 18#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs)
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a404.c b/arch/arm/mach-lh7a40x/irq-lh7a404.c
index e902e3d87da4..2685a81454d2 100644
--- a/arch/arm/mach-lh7a40x/irq-lh7a404.c
+++ b/arch/arm/mach-lh7a40x/irq-lh7a404.c
@@ -28,13 +28,17 @@
28 28
29static unsigned char irq_pri_vic1[] = { 29static unsigned char irq_pri_vic1[] = {
30#if defined (USE_PRIORITIES) 30#if defined (USE_PRIORITIES)
31IRQ_GPIO3INTR, 31 IRQ_GPIO3INTR, /* CPLD */
32 IRQ_DMAM2P4, IRQ_DMAM2P5, /* AC97 */
32#endif 33#endif
33}; 34};
34static unsigned char irq_pri_vic2[] = { 35static unsigned char irq_pri_vic2[] = {
35#if defined (USE_PRIORITIES) 36#if defined (USE_PRIORITIES)
36 IRQ_T3UI, IRQ_GPIO7INTR, 37 IRQ_T3UI, /* Timer */
38 IRQ_GPIO7INTR, /* CPLD */
37 IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR, 39 IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR,
40 IRQ_LCDINTR, /* LCD */
41 IRQ_TSCINTR, /* ADC/Touchscreen */
38#endif 42#endif
39}; 43};
40 44
@@ -98,10 +102,19 @@ static struct irqchip lh7a404_gpio_vic2_chip = {
98 102
99 /* IRQ initialization */ 103 /* IRQ initialization */
100 104
105#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
106extern void* branch_irq_lh7a400;
107#endif
108
101void __init lh7a404_init_irq (void) 109void __init lh7a404_init_irq (void)
102{ 110{
103 int irq; 111 int irq;
104 112
113#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
114#define NOP 0xe1a00000 /* mov r0, r0 */
115 branch_irq_lh7a400 = NOP;
116#endif
117
105 VIC1_INTENCLR = 0xffffffff; 118 VIC1_INTENCLR = 0xffffffff;
106 VIC2_INTENCLR = 0xffffffff; 119 VIC2_INTENCLR = 0xffffffff;
107 VIC1_INTSEL = 0; /* All IRQs */ 120 VIC1_INTSEL = 0; /* All IRQs */
diff --git a/arch/arm/mach-lh7a40x/lcd-panel.h b/arch/arm/mach-lh7a40x/lcd-panel.h
new file mode 100644
index 000000000000..4fb2efc4950f
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/lcd-panel.h
@@ -0,0 +1,346 @@
1/* lcd-panel.h
2 $Id$
3
4 written by Marc Singer
5 18 Jul 2005
6
7 Copyright (C) 2005 Marc Singer
8
9 -----------
10 DESCRIPTION
11 -----------
12
13 Only one panel may be defined at a time.
14
15 The pixel clock is calculated to be no greater than the target.
16
17 Each timing value is accompanied by a specification comment.
18
19 UNITS/MIN/TYP/MAX
20
21 Most of the units will be in clocks.
22
23 USE_RGB555
24
25 Define this macro to configure the AMBA LCD controller to use an
26 RGB555 encoding for the pels instead of the normal RGB565.
27
28 LPD9520, LPD79524, LPD7A400, LPD7A404-10, LPD7A404-11
29
30 These boards are best approximated by 555 for all panels. Some
31 can use an extra low-order bit of blue in bit 16 of the color
32 value, but we don't have a way to communicate this non-linear
33 mapping to the kernel.
34
35*/
36
37#if !defined (__LCD_PANEL_H__)
38# define __LCD_PANEL_H__
39
40#if defined (MACH_LPD79520)\
41 || defined (MACH_LPD79524)\
42 || defined (MACH_LPD7A400)\
43 || defined (MACH_LPD7A404)
44# define USE_RGB555
45#endif
46
47struct clcd_panel_extra {
48 unsigned int hrmode;
49 unsigned int clsen;
50 unsigned int spsen;
51 unsigned int pcdel;
52 unsigned int revdel;
53 unsigned int lpdel;
54 unsigned int spldel;
55 unsigned int pc2del;
56};
57
58#define NS_TO_CLOCK(ns,c) ((((ns)*((c)/1000) + (1000000 - 1))/1000000))
59#define CLOCK_TO_DIV(e,c) (((c) + (e) - 1)/(e))
60
61#if defined CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
62
63 /* Logic Product Development LCD 3.5" QVGA HRTFT -10 */
64 /* Sharp PN LQ035Q7DB02 w/HRTFT controller chip */
65
66#define PIX_CLOCK_TARGET (6800000)
67#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
68#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
69
70static struct clcd_panel lcd_panel = {
71 .mode = {
72 .name = "3.5in QVGA (LQ035Q7DB02)",
73 .xres = 240,
74 .yres = 320,
75 .pixclock = PIX_CLOCK,
76 .left_margin = 16,
77 .right_margin = 21,
78 .upper_margin = 8, // line/8/8/8
79 .lower_margin = 5,
80 .hsync_len = 61,
81 .vsync_len = NS_TO_CLOCK (60, PIX_CLOCK),
82 .vmode = FB_VMODE_NONINTERLACED,
83 },
84 .width = -1,
85 .height = -1,
86 .tim2 = TIM2_IPC | (PIX_CLOCK_DIVIDER - 2),
87 .cntl = CNTL_LCDTFT | CNTL_WATERMARK,
88 .bpp = 16,
89};
90
91#define HAS_LCD_PANEL_EXTRA
92
93static struct clcd_panel_extra lcd_panel_extra = {
94 .hrmode = 1,
95 .clsen = 1,
96 .spsen = 1,
97 .pcdel = 8,
98 .revdel = 7,
99 .lpdel = 13,
100 .spldel = 77,
101 .pc2del = 208,
102};
103
104#endif
105
106#if defined CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02
107
108 /* Logic Product Development LCD 5.7" QVGA -10 */
109 /* Sharp PN LQ057Q3DC02 */
110 /* QVGA mode, V/Q=LOW */
111
112/* From Sharp on 2006.1.3. I believe some of the values are incorrect
113 * based on the datasheet.
114
115 Timing0 TIMING1 TIMING2 CONTROL
116 0x140A0C4C 0x080504EF 0x013F380D 0x00000829
117 HBP= 20 VBP= 8 BCD= 0
118 HFP= 10 VFP= 5 CPL=319
119 HSW= 12 VSW= 1 IOE= 0
120 PPL= 19 LPP=239 IPC= 1
121 IHS= 1
122 IVS= 1
123 ACB= 0
124 CSEL= 0
125 PCD= 13
126
127 */
128
129/* The full horozontal cycle (Th) is clock/360/400/450. */
130/* The full vertical cycle (Tv) is line/251/262/280. */
131
132#define PIX_CLOCK_TARGET (6300000) /* -/6.3/7 MHz */
133#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
134#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
135
136static struct clcd_panel lcd_panel = {
137 .mode = {
138 .name = "5.7in QVGA (LQ057Q3DC02)",
139 .xres = 320,
140 .yres = 240,
141 .pixclock = PIX_CLOCK,
142 .left_margin = 11,
143 .right_margin = 400-11-320-2,
144 .upper_margin = 7, // line/7/7/7
145 .lower_margin = 262-7-240-2,
146 .hsync_len = 2, // clk/2/96/200
147 .vsync_len = 2, // line/2/-/34
148 .vmode = FB_VMODE_NONINTERLACED,
149 },
150 .width = -1,
151 .height = -1,
152 .tim2 = TIM2_IHS | TIM2_IVS
153 | (PIX_CLOCK_DIVIDER - 2),
154 .cntl = CNTL_LCDTFT | CNTL_WATERMARK,
155 .bpp = 16,
156};
157
158#endif
159
160#if defined CONFIG_FB_ARMCLCD_SHARP_LQ64D343
161
162 /* Logic Product Development LCD 6.4" VGA -10 */
163 /* Sharp PN LQ64D343 */
164
165/* The full horozontal cycle (Th) is clock/750/800/900. */
166/* The full vertical cycle (Tv) is line/515/525/560. */
167
168#define PIX_CLOCK_TARGET (28330000)
169#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
170#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
171
172static struct clcd_panel lcd_panel = {
173 .mode = {
174 .name = "6.4in QVGA (LQ64D343)",
175 .xres = 640,
176 .yres = 480,
177 .pixclock = PIX_CLOCK,
178 .left_margin = 32,
179 .right_margin = 800-32-640-96,
180 .upper_margin = 32, // line/34/34/34
181 .lower_margin = 540-32-480-2,
182 .hsync_len = 96, // clk/2/96/200
183 .vsync_len = 2, // line/2/-/34
184 .vmode = FB_VMODE_NONINTERLACED,
185 },
186 .width = -1,
187 .height = -1,
188 .tim2 = TIM2_IHS | TIM2_IVS
189 | (PIX_CLOCK_DIVIDER - 2),
190 .cntl = CNTL_LCDTFT | CNTL_WATERMARK,
191 .bpp = 16,
192};
193
194#endif
195
196#if defined CONFIG_FB_ARMCLCD_SHARP_LQ10D368
197
198 /* Logic Product Development LCD 10.4" VGA -10 */
199 /* Sharp PN LQ10D368 */
200
201#define PIX_CLOCK_TARGET (28330000)
202#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
203#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
204
205static struct clcd_panel lcd_panel = {
206 .mode = {
207 .name = "10.4in VGA (LQ10D368)",
208 .xres = 640,
209 .yres = 480,
210 .pixclock = PIX_CLOCK,
211 .left_margin = 21,
212 .right_margin = 15,
213 .upper_margin = 34,
214 .lower_margin = 5,
215 .hsync_len = 96,
216 .vsync_len = 16,
217 .vmode = FB_VMODE_NONINTERLACED,
218 },
219 .width = -1,
220 .height = -1,
221 .tim2 = TIM2_IHS | TIM2_IVS
222 | (PIX_CLOCK_DIVIDER - 2),
223 .cntl = CNTL_LCDTFT | CNTL_WATERMARK,
224 .bpp = 16,
225};
226
227#endif
228
229#if defined CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41
230
231 /* Logic Product Development LCD 12.1" SVGA -10 */
232 /* Sharp PN LQ121S1DG41, was LQ121S1DG31 */
233
234/* Note that with a 99993900 Hz HCLK, it is not possible to hit the
235 * target clock frequency range of 35MHz to 42MHz. */
236
237/* If the target pixel clock is substantially lower than the panel
238 * spec, this is done to prevent the LCD display from glitching when
239 * the CPU is under load. A pixel clock higher than 25MHz
240 * (empirically determined) will compete with the CPU for bus cycles
241 * for the Ethernet chip. However, even a pixel clock of 10MHz
242 * competes with Compact Flash interface during some operations
243 * (fdisk, e2fsck). And, at that speed the display may have a visible
244 * flicker. */
245
246/* The full horozontal cycle (Th) is clock/832/1056/1395. */
247
248#define PIX_CLOCK_TARGET (20000000)
249#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
250#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
251
252static struct clcd_panel lcd_panel = {
253 .mode = {
254 .name = "12.1in SVGA (LQ121S1DG41)",
255 .xres = 800,
256 .yres = 600,
257 .pixclock = PIX_CLOCK,
258 .left_margin = 89, // ns/5/-/(1/PIX_CLOCK)-10
259 .right_margin = 1056-800-89-128,
260 .upper_margin = 23, // line/23/23/23
261 .lower_margin = 44,
262 .hsync_len = 128, // clk/2/128/200
263 .vsync_len = 4, // line/2/4/6
264 .vmode = FB_VMODE_NONINTERLACED,
265 },
266 .width = -1,
267 .height = -1,
268 .tim2 = TIM2_IHS | TIM2_IVS
269 | (PIX_CLOCK_DIVIDER - 2),
270 .cntl = CNTL_LCDTFT | CNTL_WATERMARK,
271 .bpp = 16,
272};
273
274#endif
275
276#if defined CONFIG_FB_ARMCLCD_HITACHI
277
278 /* Hitachi*/
279 /* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
280
281#define PIX_CLOCK_TARGET (49000000)
282#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
283#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
284
285static struct clcd_panel lcd_panel = {
286 .mode = {
287 .name = "Hitachi 800x480",
288 .xres = 800,
289 .yres = 480,
290 .pixclock = PIX_CLOCK,
291 .left_margin = 88,
292 .right_margin = 40,
293 .upper_margin = 32,
294 .lower_margin = 11,
295 .hsync_len = 128,
296 .vsync_len = 2,
297 .vmode = FB_VMODE_NONINTERLACED,
298 },
299 .width = -1,
300 .height = -1,
301 .tim2 = TIM2_IPC | TIM2_IHS | TIM2_IVS
302 | (PIX_CLOCK_DIVIDER - 2),
303 .cntl = CNTL_LCDTFT | CNTL_WATERMARK,
304 .bpp = 16,
305};
306
307#endif
308
309
310#if defined CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE
311
312 /* AU Optotronics A070VW01 7.0 Wide Screen color Display*/
313 /* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
314
315#define PIX_CLOCK_TARGET (10000000)
316#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
317#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER)
318
319static struct clcd_panel lcd_panel = {
320 .mode = {
321 .name = "7.0in Wide (A070VW01)",
322 .xres = 480,
323 .yres = 234,
324 .pixclock = PIX_CLOCK,
325 .left_margin = 30,
326 .right_margin = 25,
327 .upper_margin = 14,
328 .lower_margin = 12,
329 .hsync_len = 100,
330 .vsync_len = 1,
331 .vmode = FB_VMODE_NONINTERLACED,
332 },
333 .width = -1,
334 .height = -1,
335 .tim2 = TIM2_IPC | TIM2_IHS | TIM2_IVS
336 | (PIX_CLOCK_DIVIDER - 2),
337 .cntl = CNTL_LCDTFT | CNTL_WATERMARK,
338 .bpp = 16,
339};
340
341#endif
342
343#undef NS_TO_CLOCK
344#undef CLOCK_TO_DIV
345
346#endif /* __LCD_PANEL_H__ */
diff --git a/arch/arm/mach-lh7a40x/ssp-cpld.c b/arch/arm/mach-lh7a40x/ssp-cpld.c
new file mode 100644
index 000000000000..a10830186dac
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/ssp-cpld.c
@@ -0,0 +1,343 @@
1/* arch/arm/mach-lh7a40x/ssp-cpld.c
2 *
3 * Copyright (C) 2004,2005 Marc Singer
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * SSP/SPI driver for the CardEngine CPLD.
10 *
11 */
12
13/* NOTES
14 -----
15
16 o *** This driver is cribbed from the 7952x implementation.
17 Some comments may not apply.
18
19 o This driver contains sufficient logic to control either the
20 serial EEPROMs or the audio codec. It is included in the kernel
21 to support the codec. The EEPROMs are really the responsibility
22 of the boot loader and should probably be left alone.
23
24 o The code must be augmented to cope with multiple, simultaneous
25 clients.
26 o The audio codec writes to the codec chip whenever playback
27 starts.
28 o The touchscreen driver writes to the ads chip every time it
29 samples.
30 o The audio codec must write 16 bits, but the touch chip writes
31 are 8 bits long.
32 o We need to be able to keep these configurations separate while
33 simultaneously active.
34
35 */
36
37#include <linux/module.h>
38#include <linux/kernel.h>
39//#include <linux/sched.h>
40#include <linux/errno.h>
41#include <linux/interrupt.h>
42//#include <linux/ioport.h>
43#include <linux/init.h>
44#include <linux/delay.h>
45#include <linux/spinlock.h>
46
47#include <asm/io.h>
48#include <asm/irq.h>
49#include <asm/hardware.h>
50
51#include <asm/arch/ssp.h>
52
53//#define TALK
54
55#if defined (TALK)
56#define PRINTK(f...) printk (f)
57#else
58#define PRINTK(f...) do {} while (0)
59#endif
60
61#if defined (CONFIG_ARCH_LH7A400)
62# define CPLD_SPID __REGP16(CPLD06_VIRT) /* SPI data */
63# define CPLD_SPIC __REGP16(CPLD08_VIRT) /* SPI control */
64# define CPLD_SPIC_CS_CODEC (1<<0)
65# define CPLD_SPIC_CS_TOUCH (1<<1)
66# define CPLD_SPIC_WRITE (0<<2)
67# define CPLD_SPIC_READ (1<<2)
68# define CPLD_SPIC_DONE (1<<3) /* r/o */
69# define CPLD_SPIC_LOAD (1<<4)
70# define CPLD_SPIC_START (1<<4)
71# define CPLD_SPIC_LOADED (1<<5) /* r/o */
72#endif
73
74#define CPLD_SPI __REGP16(CPLD0A_VIRT) /* SPI operation */
75#define CPLD_SPI_CS_EEPROM (1<<3)
76#define CPLD_SPI_SCLK (1<<2)
77#define CPLD_SPI_TX_SHIFT (1)
78#define CPLD_SPI_TX (1<<CPLD_SPI_TX_SHIFT)
79#define CPLD_SPI_RX_SHIFT (0)
80#define CPLD_SPI_RX (1<<CPLD_SPI_RX_SHIFT)
81
82/* *** FIXME: these timing values are substantially larger than the
83 *** chip requires. We may implement an nsleep () function. */
84#define T_SKH 1 /* Clock time high (us) */
85#define T_SKL 1 /* Clock time low (us) */
86#define T_CS 1 /* Minimum chip select low time (us) */
87#define T_CSS 1 /* Minimum chip select setup time (us) */
88#define T_DIS 1 /* Data setup time (us) */
89
90 /* EEPROM SPI bits */
91#define P_START (1<<9)
92#define P_WRITE (1<<7)
93#define P_READ (2<<7)
94#define P_ERASE (3<<7)
95#define P_EWDS (0<<7)
96#define P_WRAL (0<<7)
97#define P_ERAL (0<<7)
98#define P_EWEN (0<<7)
99#define P_A_EWDS (0<<5)
100#define P_A_WRAL (1<<5)
101#define P_A_ERAL (2<<5)
102#define P_A_EWEN (3<<5)
103
104struct ssp_configuration {
105 int device;
106 int mode;
107 int speed;
108 int frame_size_write;
109 int frame_size_read;
110};
111
112static struct ssp_configuration ssp_configuration;
113static spinlock_t ssp_lock;
114
115static void enable_cs (void)
116{
117 switch (ssp_configuration.device) {
118 case DEVICE_EEPROM:
119 CPLD_SPI |= CPLD_SPI_CS_EEPROM;
120 break;
121 }
122 udelay (T_CSS);
123}
124
125static void disable_cs (void)
126{
127 switch (ssp_configuration.device) {
128 case DEVICE_EEPROM:
129 CPLD_SPI &= ~CPLD_SPI_CS_EEPROM;
130 break;
131 }
132 udelay (T_CS);
133}
134
135static void pulse_clock (void)
136{
137 CPLD_SPI |= CPLD_SPI_SCLK;
138 udelay (T_SKH);
139 CPLD_SPI &= ~CPLD_SPI_SCLK;
140 udelay (T_SKL);
141}
142
143
144/* execute_spi_command
145
146 sends an spi command to a device. It first sends cwrite bits from
147 v. If cread is greater than zero it will read cread bits
148 (discarding the leading 0 bit) and return them. If cread is less
149 than zero it will check for completetion status and return 0 on
150 success or -1 on timeout. If cread is zero it does nothing other
151 than sending the command.
152
153 On the LPD7A400, we can only read or write multiples of 8 bits on
154 the codec and the touch screen device. Here, we round up.
155
156*/
157
158static int execute_spi_command (int v, int cwrite, int cread)
159{
160 unsigned long l = 0;
161
162#if defined (CONFIG_MACH_LPD7A400)
163 /* The codec and touch devices cannot be bit-banged. Instead,
164 * the CPLD provides an eight-bit shift register and a crude
165 * interface. */
166 if ( ssp_configuration.device == DEVICE_CODEC
167 || ssp_configuration.device == DEVICE_TOUCH) {
168 int select = 0;
169
170 PRINTK ("spi(%d %d.%d) 0x%04x",
171 ssp_configuration.device, cwrite, cread,
172 v);
173#if defined (TALK)
174 if (ssp_configuration.device == DEVICE_CODEC)
175 PRINTK (" 0x%03x -> %2d", v & 0x1ff, (v >> 9) & 0x7f);
176#endif
177 PRINTK ("\n");
178
179 if (ssp_configuration.device == DEVICE_CODEC)
180 select = CPLD_SPIC_CS_CODEC;
181 if (ssp_configuration.device == DEVICE_TOUCH)
182 select = CPLD_SPIC_CS_TOUCH;
183 if (cwrite) {
184 for (cwrite = (cwrite + 7)/8; cwrite-- > 0; ) {
185 CPLD_SPID = (v >> (8*cwrite)) & 0xff;
186 CPLD_SPIC = select | CPLD_SPIC_LOAD;
187 while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
188 ;
189 CPLD_SPIC = select;
190 while (!(CPLD_SPIC & CPLD_SPIC_DONE))
191 ;
192 }
193 v = 0;
194 }
195 if (cread) {
196 mdelay (2); /* *** FIXME: required by ads7843? */
197 v = 0;
198 for (cread = (cread + 7)/8; cread-- > 0;) {
199 CPLD_SPID = 0;
200 CPLD_SPIC = select | CPLD_SPIC_READ
201 | CPLD_SPIC_START;
202 while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
203 ;
204 CPLD_SPIC = select | CPLD_SPIC_READ;
205 while (!(CPLD_SPIC & CPLD_SPIC_DONE))
206 ;
207 v = (v << 8) | CPLD_SPID;
208 }
209 }
210 return v;
211 }
212#endif
213
214 PRINTK ("spi(%d) 0x%04x -> 0x%x\r\n", ssp_configuration.device,
215 v & 0x1ff, (v >> 9) & 0x7f);
216
217 enable_cs ();
218
219 v <<= CPLD_SPI_TX_SHIFT; /* Correction for position of SPI_TX bit */
220 while (cwrite--) {
221 CPLD_SPI
222 = (CPLD_SPI & ~CPLD_SPI_TX)
223 | ((v >> cwrite) & CPLD_SPI_TX);
224 udelay (T_DIS);
225 pulse_clock ();
226 }
227
228 if (cread < 0) {
229 int delay = 10;
230 disable_cs ();
231 udelay (1);
232 enable_cs ();
233
234 l = -1;
235 do {
236 if (CPLD_SPI & CPLD_SPI_RX) {
237 l = 0;
238 break;
239 }
240 } while (udelay (1), --delay);
241 }
242 else
243 /* We pulse the clock before the data to skip the leading zero. */
244 while (cread-- > 0) {
245 pulse_clock ();
246 l = (l<<1)
247 | (((CPLD_SPI & CPLD_SPI_RX)
248 >> CPLD_SPI_RX_SHIFT) & 0x1);
249 }
250
251 disable_cs ();
252 return l;
253}
254
255static int ssp_init (void)
256{
257 spin_lock_init (&ssp_lock);
258 memset (&ssp_configuration, 0, sizeof (ssp_configuration));
259 return 0;
260}
261
262
263/* ssp_chip_select
264
265 drops the chip select line for the CPLD shift-register controlled
266 devices. It doesn't enable chip
267
268*/
269
270static void ssp_chip_select (int enable)
271{
272#if defined (CONFIG_MACH_LPD7A400)
273 int select;
274
275 if (ssp_configuration.device == DEVICE_CODEC)
276 select = CPLD_SPIC_CS_CODEC;
277 else if (ssp_configuration.device == DEVICE_TOUCH)
278 select = CPLD_SPIC_CS_TOUCH;
279 else
280 return;
281
282 if (enable)
283 CPLD_SPIC = select;
284 else
285 CPLD_SPIC = 0;
286#endif
287}
288
289static void ssp_acquire (void)
290{
291 spin_lock (&ssp_lock);
292}
293
294static void ssp_release (void)
295{
296 ssp_chip_select (0); /* just in case */
297 spin_unlock (&ssp_lock);
298}
299
300static int ssp_configure (int device, int mode, int speed,
301 int frame_size_write, int frame_size_read)
302{
303 ssp_configuration.device = device;
304 ssp_configuration.mode = mode;
305 ssp_configuration.speed = speed;
306 ssp_configuration.frame_size_write = frame_size_write;
307 ssp_configuration.frame_size_read = frame_size_read;
308
309 return 0;
310}
311
312static int ssp_read (void)
313{
314 return execute_spi_command (0, 0, ssp_configuration.frame_size_read);
315}
316
317static int ssp_write (u16 data)
318{
319 execute_spi_command (data, ssp_configuration.frame_size_write, 0);
320 return 0;
321}
322
323static int ssp_write_read (u16 data)
324{
325 return execute_spi_command (data, ssp_configuration.frame_size_write,
326 ssp_configuration.frame_size_read);
327}
328
329struct ssp_driver lh7a40x_cpld_ssp_driver = {
330 .init = ssp_init,
331 .acquire = ssp_acquire,
332 .release = ssp_release,
333 .configure = ssp_configure,
334 .chip_select = ssp_chip_select,
335 .read = ssp_read,
336 .write = ssp_write,
337 .write_read = ssp_write_read,
338};
339
340
341MODULE_AUTHOR("Marc Singer");
342MODULE_DESCRIPTION("LPD7A40X CPLD SPI driver");
343MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
index be377e331f25..ef9af375fcc4 100644
--- a/arch/arm/mach-lh7a40x/time.c
+++ b/arch/arm/mach-lh7a40x/time.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * arch/arm/mach-lh7a40x/time.c 2 * arch/arm/mach-lh7a40x/time.c
3 * 3 *
4 * Copyright (C) 2004 Logic Product Development 4 * Copyright (C) 2004 Logic Product Development
@@ -57,7 +57,7 @@ static struct irqaction lh7a40x_timer_irq = {
57 .handler = lh7a40x_timer_interrupt, 57 .handler = lh7a40x_timer_interrupt,
58}; 58};
59 59
60static void __init lh7a40x_timer_init(void) 60static void __init lh7a40x_timer_init (void)
61{ 61{
62 /* Stop/disable all timers */ 62 /* Stop/disable all timers */
63 TIMER_CONTROL1 = 0; 63 TIMER_CONTROL1 = 0;