Commit | Line | Data |
---|---|---|
4adc5fb6 MR |
1 | /* |
2 | * linux/arch/arm/mach-pxa/cm-x270.c | |
3 | * | |
4 | * Copyright (C) 2007, 2008 CompuLab, Ltd. | |
5 | * Mike Rapoport <mike@compulab.co.il> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License version 2 as | |
9 | * published by the Free Software Foundation. | |
10 | */ | |
11 | ||
12 | #include <linux/platform_device.h> | |
13 | #include <linux/sysdev.h> | |
14 | #include <linux/irq.h> | |
15 | #include <linux/gpio.h> | |
16 | ||
17 | #include <linux/rtc-v3020.h> | |
18 | #include <video/mbxfb.h> | |
19 | ||
20 | #include <mach/mfp-pxa27x.h> | |
21 | #include <mach/ohci.h> | |
22 | #include <mach/mmc.h> | |
23 | ||
24 | #include "generic.h" | |
25 | ||
26 | /* physical address if local-bus attached devices */ | |
27 | #define RTC_PHYS_BASE (PXA_CS1_PHYS + (5 << 22)) | |
28 | ||
29 | /* GPIO IRQ usage */ | |
30 | #define GPIO83_MMC_IRQ (83) | |
31 | ||
32 | #define CMX270_MMC_IRQ IRQ_GPIO(GPIO83_MMC_IRQ) | |
33 | ||
34 | /* MMC power enable */ | |
35 | #define GPIO105_MMC_POWER (105) | |
36 | ||
37 | static unsigned long cmx270_pin_config[] = { | |
38 | /* AC'97 */ | |
39 | GPIO28_AC97_BITCLK, | |
40 | GPIO29_AC97_SDATA_IN_0, | |
41 | GPIO30_AC97_SDATA_OUT, | |
42 | GPIO31_AC97_SYNC, | |
43 | GPIO98_AC97_SYSCLK, | |
44 | GPIO113_AC97_nRESET, | |
45 | ||
46 | /* BTUART */ | |
47 | GPIO42_BTUART_RXD, | |
48 | GPIO43_BTUART_TXD, | |
49 | GPIO44_BTUART_CTS, | |
50 | GPIO45_BTUART_RTS, | |
51 | ||
52 | /* STUART */ | |
53 | GPIO46_STUART_RXD, | |
54 | GPIO47_STUART_TXD, | |
55 | ||
56 | /* MCI controller */ | |
57 | GPIO32_MMC_CLK, | |
58 | GPIO112_MMC_CMD, | |
59 | GPIO92_MMC_DAT_0, | |
60 | GPIO109_MMC_DAT_1, | |
61 | GPIO110_MMC_DAT_2, | |
62 | GPIO111_MMC_DAT_3, | |
63 | ||
64 | /* LCD */ | |
65 | GPIO58_LCD_LDD_0, | |
66 | GPIO59_LCD_LDD_1, | |
67 | GPIO60_LCD_LDD_2, | |
68 | GPIO61_LCD_LDD_3, | |
69 | GPIO62_LCD_LDD_4, | |
70 | GPIO63_LCD_LDD_5, | |
71 | GPIO64_LCD_LDD_6, | |
72 | GPIO65_LCD_LDD_7, | |
73 | GPIO66_LCD_LDD_8, | |
74 | GPIO67_LCD_LDD_9, | |
75 | GPIO68_LCD_LDD_10, | |
76 | GPIO69_LCD_LDD_11, | |
77 | GPIO70_LCD_LDD_12, | |
78 | GPIO71_LCD_LDD_13, | |
79 | GPIO72_LCD_LDD_14, | |
80 | GPIO73_LCD_LDD_15, | |
81 | GPIO74_LCD_FCLK, | |
82 | GPIO75_LCD_LCLK, | |
83 | GPIO76_LCD_PCLK, | |
84 | GPIO77_LCD_BIAS, | |
85 | ||
86 | /* I2C */ | |
87 | GPIO117_I2C_SCL, | |
88 | GPIO118_I2C_SDA, | |
89 | ||
90 | /* SSP1 */ | |
91 | GPIO23_SSP1_SCLK, | |
92 | GPIO24_SSP1_SFRM, | |
93 | GPIO25_SSP1_TXD, | |
94 | GPIO26_SSP1_RXD, | |
95 | ||
96 | /* SSP2 */ | |
97 | GPIO19_SSP2_SCLK, | |
98 | GPIO14_SSP2_SFRM, | |
99 | GPIO87_SSP2_TXD, | |
100 | GPIO88_SSP2_RXD, | |
101 | ||
102 | /* PC Card */ | |
103 | GPIO48_nPOE, | |
104 | GPIO49_nPWE, | |
105 | GPIO50_nPIOR, | |
106 | GPIO51_nPIOW, | |
107 | GPIO85_nPCE_1, | |
108 | GPIO54_nPCE_2, | |
109 | GPIO55_nPREG, | |
110 | GPIO56_nPWAIT, | |
111 | GPIO57_nIOIS16, | |
112 | ||
113 | /* SDRAM and local bus */ | |
114 | GPIO15_nCS_1, | |
115 | GPIO78_nCS_2, | |
116 | GPIO79_nCS_3, | |
117 | GPIO80_nCS_4, | |
118 | GPIO33_nCS_5, | |
119 | GPIO49_nPWE, | |
120 | GPIO18_RDY, | |
121 | ||
122 | /* GPIO */ | |
123 | GPIO0_GPIO | WAKEUP_ON_EDGE_BOTH, | |
124 | GPIO105_GPIO | MFP_LPM_DRIVE_HIGH, /* MMC/SD power */ | |
125 | GPIO53_GPIO, /* PC card reset */ | |
126 | ||
127 | /* NAND controls */ | |
128 | GPIO11_GPIO | MFP_LPM_DRIVE_HIGH, /* NAND CE# */ | |
129 | GPIO89_GPIO, /* NAND Ready/Busy */ | |
130 | ||
131 | /* interrupts */ | |
132 | GPIO10_GPIO, /* DM9000 interrupt */ | |
133 | GPIO83_GPIO, /* MMC card detect */ | |
134 | }; | |
135 | ||
136 | /* V3020 RTC */ | |
137 | #if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE) | |
138 | static struct resource cmx270_v3020_resource[] = { | |
139 | [0] = { | |
140 | .start = RTC_PHYS_BASE, | |
141 | .end = RTC_PHYS_BASE + 4, | |
142 | .flags = IORESOURCE_MEM, | |
143 | }, | |
144 | }; | |
145 | ||
146 | struct v3020_platform_data cmx270_v3020_pdata = { | |
147 | .leftshift = 16, | |
148 | }; | |
149 | ||
150 | static struct platform_device cmx270_rtc_device = { | |
151 | .name = "v3020", | |
152 | .num_resources = ARRAY_SIZE(cmx270_v3020_resource), | |
153 | .resource = cmx270_v3020_resource, | |
154 | .id = -1, | |
155 | .dev = { | |
156 | .platform_data = &cmx270_v3020_pdata, | |
157 | } | |
158 | }; | |
159 | ||
160 | static void __init cmx270_init_rtc(void) | |
161 | { | |
162 | platform_device_register(&cmx270_rtc_device); | |
163 | } | |
164 | #else | |
165 | static inline void cmx2xx_init_rtc(void) {} | |
166 | #endif | |
167 | ||
168 | /* 2700G graphics */ | |
169 | #if defined(CONFIG_FB_MBX) || defined(CONFIG_FB_MBX_MODULE) | |
170 | static u64 fb_dma_mask = ~(u64)0; | |
171 | ||
172 | static struct resource cmx270_2700G_resource[] = { | |
173 | /* frame buffer memory including ODFB and External SDRAM */ | |
174 | [0] = { | |
175 | .start = PXA_CS2_PHYS, | |
176 | .end = PXA_CS2_PHYS + 0x01ffffff, | |
177 | .flags = IORESOURCE_MEM, | |
178 | }, | |
179 | /* Marathon registers */ | |
180 | [1] = { | |
181 | .start = PXA_CS2_PHYS + 0x03fe0000, | |
182 | .end = PXA_CS2_PHYS + 0x03ffffff, | |
183 | .flags = IORESOURCE_MEM, | |
184 | }, | |
185 | }; | |
186 | ||
187 | static unsigned long save_lcd_regs[10]; | |
188 | ||
189 | static int cmx270_marathon_probe(struct fb_info *fb) | |
190 | { | |
191 | /* save PXA-270 pin settings before enabling 2700G */ | |
192 | save_lcd_regs[0] = GPDR1; | |
193 | save_lcd_regs[1] = GPDR2; | |
194 | save_lcd_regs[2] = GAFR1_U; | |
195 | save_lcd_regs[3] = GAFR2_L; | |
196 | save_lcd_regs[4] = GAFR2_U; | |
197 | ||
198 | /* Disable PXA-270 on-chip controller driving pins */ | |
199 | GPDR1 &= ~(0xfc000000); | |
200 | GPDR2 &= ~(0x00c03fff); | |
201 | GAFR1_U &= ~(0xfff00000); | |
202 | GAFR2_L &= ~(0x0fffffff); | |
203 | GAFR2_U &= ~(0x0000f000); | |
204 | return 0; | |
205 | } | |
206 | ||
207 | static int cmx270_marathon_remove(struct fb_info *fb) | |
208 | { | |
209 | GPDR1 = save_lcd_regs[0]; | |
210 | GPDR2 = save_lcd_regs[1]; | |
211 | GAFR1_U = save_lcd_regs[2]; | |
212 | GAFR2_L = save_lcd_regs[3]; | |
213 | GAFR2_U = save_lcd_regs[4]; | |
214 | return 0; | |
215 | } | |
216 | ||
217 | static struct mbxfb_platform_data cmx270_2700G_data = { | |
218 | .xres = { | |
219 | .min = 240, | |
220 | .max = 1200, | |
221 | .defval = 640, | |
222 | }, | |
223 | .yres = { | |
224 | .min = 240, | |
225 | .max = 1200, | |
226 | .defval = 480, | |
227 | }, | |
228 | .bpp = { | |
229 | .min = 16, | |
230 | .max = 32, | |
231 | .defval = 16, | |
232 | }, | |
233 | .memsize = 8*1024*1024, | |
234 | .probe = cmx270_marathon_probe, | |
235 | .remove = cmx270_marathon_remove, | |
236 | }; | |
237 | ||
238 | static struct platform_device cmx270_2700G = { | |
239 | .name = "mbx-fb", | |
240 | .dev = { | |
241 | .platform_data = &cmx270_2700G_data, | |
242 | .dma_mask = &fb_dma_mask, | |
243 | .coherent_dma_mask = 0xffffffff, | |
244 | }, | |
245 | .num_resources = ARRAY_SIZE(cmx270_2700G_resource), | |
246 | .resource = cmx270_2700G_resource, | |
247 | .id = -1, | |
248 | }; | |
249 | ||
250 | static void __init cmx270_init_2700G(void) | |
251 | { | |
252 | platform_device_register(&cmx270_2700G); | |
253 | } | |
254 | #else | |
255 | static inline void cmx270_init_2700G(void) {} | |
256 | #endif | |
257 | ||
258 | /* PXA27x OHCI controller setup */ | |
259 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) | |
4adc5fb6 MR |
260 | static struct pxaohci_platform_data cmx270_ohci_platform_data = { |
261 | .port_mode = PMM_PERPORT_MODE, | |
097b5334 | 262 | .flags = ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW, |
4adc5fb6 MR |
263 | }; |
264 | ||
265 | static void __init cmx270_init_ohci(void) | |
266 | { | |
267 | pxa_set_ohci_info(&cmx270_ohci_platform_data); | |
268 | } | |
269 | #else | |
270 | static inline void cmx270_init_ohci(void) {} | |
271 | #endif | |
272 | ||
273 | #if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE) | |
274 | static int cmx270_mci_init(struct device *dev, | |
275 | irq_handler_t cmx270_detect_int, | |
276 | void *data) | |
277 | { | |
278 | int err; | |
279 | ||
280 | err = gpio_request(GPIO105_MMC_POWER, "MMC/SD power"); | |
281 | if (err) { | |
282 | dev_warn(dev, "power gpio unavailable\n"); | |
283 | return err; | |
284 | } | |
285 | ||
286 | gpio_direction_output(GPIO105_MMC_POWER, 0); | |
287 | ||
288 | err = request_irq(CMX270_MMC_IRQ, cmx270_detect_int, | |
289 | IRQF_DISABLED | IRQF_TRIGGER_FALLING, | |
290 | "MMC card detect", data); | |
291 | if (err) { | |
292 | gpio_free(GPIO105_MMC_POWER); | |
293 | dev_err(dev, "cmx270_mci_init: MMC/SD: can't" | |
294 | " request MMC card detect IRQ\n"); | |
295 | } | |
296 | ||
297 | return err; | |
298 | } | |
299 | ||
300 | static void cmx270_mci_setpower(struct device *dev, unsigned int vdd) | |
301 | { | |
302 | struct pxamci_platform_data *p_d = dev->platform_data; | |
303 | ||
304 | if ((1 << vdd) & p_d->ocr_mask) { | |
305 | dev_dbg(dev, "power on\n"); | |
306 | gpio_set_value(GPIO105_MMC_POWER, 0); | |
307 | } else { | |
308 | gpio_set_value(GPIO105_MMC_POWER, 1); | |
309 | dev_dbg(dev, "power off\n"); | |
310 | } | |
311 | } | |
312 | ||
313 | static void cmx270_mci_exit(struct device *dev, void *data) | |
314 | { | |
315 | free_irq(CMX270_MMC_IRQ, data); | |
316 | gpio_free(GPIO105_MMC_POWER); | |
317 | } | |
318 | ||
319 | static struct pxamci_platform_data cmx270_mci_platform_data = { | |
320 | .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, | |
321 | .init = cmx270_mci_init, | |
322 | .setpower = cmx270_mci_setpower, | |
323 | .exit = cmx270_mci_exit, | |
324 | }; | |
325 | ||
326 | static void __init cmx270_init_mmc(void) | |
327 | { | |
328 | pxa_set_mci_info(&cmx270_mci_platform_data); | |
329 | } | |
330 | #else | |
331 | static inline void cmx270_init_mmc(void) {} | |
332 | #endif | |
333 | ||
334 | void __init cmx270_init(void) | |
335 | { | |
336 | pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_pin_config)); | |
337 | ||
338 | cmx270_init_rtc(); | |
339 | cmx270_init_mmc(); | |
340 | cmx270_init_ohci(); | |
341 | cmx270_init_2700G(); | |
342 | } |