kernel.org linux-2.6.10
[linux-2.6.git] / arch / arm / mach-pxa / mainstone.c
1 /*
2  *  linux/arch/arm/mach-pxa/mainstone.c
3  *
4  *  Support for the Intel HCDDBBVA0 Development Platform.
5  *  (go figure how they came up with such name...)
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
16 #include <linux/init.h>
17 #include <linux/device.h>
18 #include <linux/interrupt.h>
19 #include <linux/sched.h>
20 #include <linux/bitops.h>
21 #include <linux/fb.h>
22
23 #include <asm/types.h>
24 #include <asm/setup.h>
25 #include <asm/memory.h>
26 #include <asm/mach-types.h>
27 #include <asm/hardware.h>
28 #include <asm/irq.h>
29
30 #include <asm/mach/arch.h>
31 #include <asm/mach/map.h>
32 #include <asm/mach/irq.h>
33
34 #include <asm/arch/pxa-regs.h>
35 #include <asm/arch/mainstone.h>
36 #include <asm/arch/pxafb.h>
37 #include <asm/arch/mmc.h>
38
39 #include "generic.h"
40
41
42 static unsigned long mainstone_irq_enabled;
43
44 static void mainstone_mask_irq(unsigned int irq)
45 {
46         int mainstone_irq = (irq - MAINSTONE_IRQ(0));
47         MST_INTMSKENA = (mainstone_irq_enabled &= ~(1 << mainstone_irq));
48 }
49
50 static void mainstone_unmask_irq(unsigned int irq)
51 {
52         int mainstone_irq = (irq - MAINSTONE_IRQ(0));
53         /* the irq can be acknowledged only if deasserted, so it's done here */
54         MST_INTSETCLR &= ~(1 << mainstone_irq);
55         MST_INTMSKENA = (mainstone_irq_enabled |= (1 << mainstone_irq));
56 }
57
58 static struct irqchip mainstone_irq_chip = {
59         .ack            = mainstone_mask_irq,
60         .mask           = mainstone_mask_irq,
61         .unmask         = mainstone_unmask_irq,
62 };
63
64
65 static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
66                                   struct pt_regs *regs)
67 {
68         unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled;
69         do {
70                 GEDR(0) = GPIO_bit(0);  /* clear useless edge notification */
71                 if (likely(pending)) {
72                         irq = MAINSTONE_IRQ(0) + __ffs(pending);
73                         desc = irq_desc + irq;
74                         desc->handle(irq, desc, regs);
75                 }
76                 pending = MST_INTSETCLR & mainstone_irq_enabled;
77         } while (pending);
78 }
79
80 static void __init mainstone_init_irq(void)
81 {
82         int irq;
83
84         pxa_init_irq();
85
86         /* setup extra Mainstone irqs */
87         for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
88                 set_irq_chip(irq, &mainstone_irq_chip);
89                 set_irq_handler(irq, do_level_IRQ);
90                 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
91         }
92         set_irq_flags(MAINSTONE_IRQ(8), 0);
93         set_irq_flags(MAINSTONE_IRQ(12), 0);
94
95         MST_INTMSKENA = 0;
96         MST_INTSETCLR = 0;
97
98         set_irq_chained_handler(IRQ_GPIO(0), mainstone_irq_handler);
99         set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
100 }
101
102
103 static struct resource smc91x_resources[] = {
104         [0] = {
105                 .start  = (MST_ETH_PHYS + 0x300),
106                 .end    = (MST_ETH_PHYS + 0xfffff),
107                 .flags  = IORESOURCE_MEM,
108         },
109         [1] = {
110                 .start  = MAINSTONE_IRQ(3),
111                 .end    = MAINSTONE_IRQ(3),
112                 .flags  = IORESOURCE_IRQ,
113         }
114 };
115
116 static struct platform_device smc91x_device = {
117         .name           = "smc91x",
118         .id             = 0,
119         .num_resources  = ARRAY_SIZE(smc91x_resources),
120         .resource       = smc91x_resources,
121 };
122
123
124 static void mainstone_backlight_power(int on)
125 {
126         if (on) {
127                 pxa_gpio_mode(GPIO16_PWM0_MD);
128                 pxa_set_cken(CKEN0_PWM0, 1);
129                 PWM_CTRL0 = 0;
130                 PWM_PWDUTY0 = 0x3ff;
131                 PWM_PERVAL0 = 0x3ff;
132         } else {
133                 PWM_CTRL0 = 0;
134                 PWM_PWDUTY0 = 0x0;
135                 PWM_PERVAL0 = 0x3FF;
136                 pxa_set_cken(CKEN0_PWM0, 0);
137         }
138 }
139
140 static struct pxafb_mach_info toshiba_ltm04c380k __initdata = {
141         .pixclock               = 50000,
142         .xres                   = 640,
143         .yres                   = 480,
144         .bpp                    = 16,
145         .hsync_len              = 1,
146         .left_margin            = 0x9f,
147         .right_margin           = 1,
148         .vsync_len              = 44,
149         .upper_margin           = 0,
150         .lower_margin           = 0,
151         .sync                   = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
152         .lccr0                  = LCCR0_Act,
153         .lccr3                  = LCCR3_PCP,
154         .pxafb_backlight_power  = mainstone_backlight_power,
155 };
156
157 static struct pxafb_mach_info toshiba_ltm035a776c __initdata = {
158         .pixclock               = 110000,
159         .xres                   = 240,
160         .yres                   = 320,
161         .bpp                    = 16,
162         .hsync_len              = 4,
163         .left_margin            = 8,
164         .right_margin           = 20,
165         .vsync_len              = 3,
166         .upper_margin           = 1,
167         .lower_margin           = 10,
168         .sync                   = FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
169         .lccr0                  = LCCR0_Act,
170         .lccr3                  = LCCR3_PCP,
171         .pxafb_backlight_power  = mainstone_backlight_power,
172 };
173
174 static int mainstone_mci_init(struct device *dev, irqreturn_t (*mstone_detect_int)(int, void *, struct pt_regs *), void *data)
175 {
176         int err;
177
178         /*
179          * setup GPIO for PXA27x MMC controller
180          */
181         pxa_gpio_mode(GPIO32_MMCCLK_MD);
182         pxa_gpio_mode(GPIO112_MMCCMD_MD);
183         pxa_gpio_mode(GPIO92_MMCDAT0_MD);
184         pxa_gpio_mode(GPIO109_MMCDAT1_MD);
185         pxa_gpio_mode(GPIO110_MMCDAT2_MD);
186         pxa_gpio_mode(GPIO111_MMCDAT3_MD);
187
188         /* make sure SD/Memory Stick multiplexer's signals
189          * are routed to MMC controller
190          */
191         MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL;
192
193         err = request_irq(MAINSTONE_MMC_IRQ, mstone_detect_int, SA_INTERRUPT,
194                              "MMC card detect", data);
195         if (err) {
196                 printk(KERN_ERR "mainstone_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
197                 return -1;
198         }
199
200         return 0;
201 }
202
203 static void mainstone_mci_setpower(struct device *dev, unsigned int vdd)
204 {
205         struct pxamci_platform_data* p_d = dev->platform_data;
206
207         if (( 1 << vdd) & p_d->ocr_mask) {
208                 printk(KERN_DEBUG "%s: on\n", __FUNCTION__);
209                 MST_MSCWR1 |= MST_MSCWR1_MMC_ON;
210                 MST_MSCWR1 &= ~MST_MSCWR1_MS_SEL;
211         } else {
212                 printk(KERN_DEBUG "%s: off\n", __FUNCTION__);
213                 MST_MSCWR1 &= ~MST_MSCWR1_MMC_ON;
214         }
215 }
216
217 static void mainstone_mci_exit(struct device *dev, void *data)
218 {
219         free_irq(MAINSTONE_MMC_IRQ, data);
220 }
221
222 static struct pxamci_platform_data mainstone_mci_platform_data = {
223         .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
224         .init           = mainstone_mci_init,
225         .setpower       = mainstone_mci_setpower,
226         .exit           = mainstone_mci_exit,
227 };
228
229 static void __init mainstone_init(void)
230 {
231         platform_device_register(&smc91x_device);
232
233         /* reading Mainstone's "Virtual Configuration Register"
234            might be handy to select LCD type here */
235         if (0)
236                 set_pxa_fb_info(&toshiba_ltm04c380k);
237         else
238                 set_pxa_fb_info(&toshiba_ltm035a776c);
239
240         pxa_set_mci_info(&mainstone_mci_platform_data);
241 }
242
243
244 static struct map_desc mainstone_io_desc[] __initdata = {
245   { MST_FPGA_VIRT, MST_FPGA_PHYS, 0x00100000, MT_DEVICE }, /* CPLD */
246 };
247
248 static void __init mainstone_map_io(void)
249 {
250         pxa_map_io();
251         iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
252 }
253
254 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
255         MAINTAINER("MontaVista Software Inc.")
256         BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
257         MAPIO(mainstone_map_io)
258         INITIRQ(mainstone_init_irq)
259         .timer          = &pxa_timer,
260         INIT_MACHINE(mainstone_init)
261 MACHINE_END