Commit | Line | Data |
---|---|---|
95790873 CW |
1 | /* Machine specific code for the Acer n30, Acer N35, Navman PiN 570, |
2 | * Yakumo AlphaX and Airis NC05 PDAs. | |
1da177e4 LT |
3 | * |
4 | * Copyright (c) 2003-2005 Simtec Electronics | |
5 | * Ben Dooks <ben@simtec.co.uk> | |
6 | * | |
196a0475 | 7 | * Copyright (c) 2005-2008 Christer Weinigel <christer@weinigel.se> |
1da177e4 LT |
8 | * |
9 | * There is a wiki with more information about the n30 port at | |
10 | * http://handhelds.org/moin/moin.cgi/AcerN30Documentation . | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU General Public License version 2 as | |
14 | * published by the Free Software Foundation. | |
95790873 | 15 | */ |
1da177e4 LT |
16 | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/types.h> | |
196a0475 | 19 | |
1da177e4 | 20 | #include <linux/delay.h> |
62065750 | 21 | #include <linux/gpio_keys.h> |
196a0475 | 22 | #include <linux/init.h> |
62065750 | 23 | #include <linux/input.h> |
196a0475 | 24 | #include <linux/interrupt.h> |
d052d1be | 25 | #include <linux/platform_device.h> |
196a0475 CW |
26 | #include <linux/serial_core.h> |
27 | #include <linux/timer.h> | |
1da177e4 LT |
28 | |
29 | #include <asm/hardware.h> | |
1da177e4 LT |
30 | #include <asm/io.h> |
31 | #include <asm/irq.h> | |
32 | #include <asm/mach-types.h> | |
33 | ||
e43f2383 | 34 | #include <asm/arch/fb.h> |
865cc639 | 35 | #include <asm/arch/leds-gpio.h> |
1da177e4 | 36 | #include <asm/arch/regs-gpio.h> |
e43f2383 | 37 | #include <asm/arch/regs-lcd.h> |
196a0475 CW |
38 | |
39 | #include <asm/mach/arch.h> | |
40 | #include <asm/mach/irq.h> | |
41 | #include <asm/mach/map.h> | |
42 | ||
531b617c | 43 | #include <asm/plat-s3c/iic.h> |
196a0475 | 44 | #include <asm/plat-s3c/regs-serial.h> |
1da177e4 | 45 | |
a21765a7 | 46 | #include <asm/plat-s3c24xx/clock.h> |
a21765a7 | 47 | #include <asm/plat-s3c24xx/cpu.h> |
196a0475 CW |
48 | #include <asm/plat-s3c24xx/devs.h> |
49 | #include <asm/plat-s3c24xx/s3c2410.h> | |
d088e5fe | 50 | #include <asm/plat-s3c24xx/udc.h> |
1da177e4 LT |
51 | |
52 | static struct map_desc n30_iodesc[] __initdata = { | |
53 | /* nothing here yet */ | |
54 | }; | |
55 | ||
56 | static struct s3c2410_uartcfg n30_uartcfgs[] = { | |
57 | /* Normal serial port */ | |
58 | [0] = { | |
59 | .hwport = 0, | |
60 | .flags = 0, | |
61 | .ucon = 0x2c5, | |
62 | .ulcon = 0x03, | |
63 | .ufcon = 0x51, | |
64 | }, | |
65 | /* IR port */ | |
66 | [1] = { | |
67 | .hwport = 1, | |
68 | .flags = 0, | |
69 | .uart_flags = UPF_CONS_FLOW, | |
70 | .ucon = 0x2c5, | |
71 | .ulcon = 0x43, | |
72 | .ufcon = 0x51, | |
73 | }, | |
95790873 CW |
74 | /* On the N30 the bluetooth controller is connected here. |
75 | * On the N35 and variants the GPS receiver is connected here. */ | |
1da177e4 LT |
76 | [2] = { |
77 | .hwport = 2, | |
78 | .flags = 0, | |
79 | .ucon = 0x2c5, | |
80 | .ulcon = 0x03, | |
81 | .ufcon = 0x51, | |
82 | }, | |
83 | }; | |
84 | ||
d088e5fe CW |
85 | static void n30_udc_pullup(enum s3c2410_udc_cmd_e cmd) |
86 | { | |
87 | switch (cmd) | |
88 | { | |
89 | case S3C2410_UDC_P_ENABLE : | |
90 | s3c2410_gpio_setpin(S3C2410_GPB3, 1); | |
91 | break; | |
92 | case S3C2410_UDC_P_DISABLE : | |
93 | s3c2410_gpio_setpin(S3C2410_GPB3, 0); | |
94 | break; | |
95 | case S3C2410_UDC_P_RESET : | |
96 | break; | |
97 | default: | |
98 | break; | |
99 | } | |
100 | } | |
101 | ||
102 | static struct s3c2410_udc_mach_info n30_udc_cfg __initdata = { | |
103 | .udc_command = n30_udc_pullup, | |
104 | .vbus_pin = S3C2410_GPG1, | |
105 | .vbus_pin_inverted = 0, | |
106 | }; | |
107 | ||
62065750 CW |
108 | static struct gpio_keys_button n30_buttons[] = { |
109 | { | |
110 | .gpio = S3C2410_GPF0, | |
111 | .code = KEY_POWER, | |
112 | .desc = "Power", | |
113 | .active_low = 0, | |
114 | }, | |
115 | { | |
116 | .gpio = S3C2410_GPG9, | |
117 | .code = KEY_UP, | |
118 | .desc = "Thumbwheel Up", | |
119 | .active_low = 0, | |
120 | }, | |
121 | { | |
122 | .gpio = S3C2410_GPG8, | |
123 | .code = KEY_DOWN, | |
124 | .desc = "Thumbwheel Down", | |
125 | .active_low = 0, | |
126 | }, | |
127 | { | |
128 | .gpio = S3C2410_GPG7, | |
129 | .code = KEY_ENTER, | |
130 | .desc = "Thumbwheel Press", | |
131 | .active_low = 0, | |
132 | }, | |
133 | { | |
134 | .gpio = S3C2410_GPF7, | |
135 | .code = KEY_HOMEPAGE, | |
136 | .desc = "Home", | |
137 | .active_low = 0, | |
138 | }, | |
139 | { | |
140 | .gpio = S3C2410_GPF6, | |
141 | .code = KEY_CALENDAR, | |
142 | .desc = "Calendar", | |
143 | .active_low = 0, | |
144 | }, | |
145 | { | |
146 | .gpio = S3C2410_GPF5, | |
147 | .code = KEY_ADDRESSBOOK, | |
148 | .desc = "Contacts", | |
149 | .active_low = 0, | |
150 | }, | |
151 | { | |
152 | .gpio = S3C2410_GPF4, | |
153 | .code = KEY_MAIL, | |
154 | .desc = "Mail", | |
155 | .active_low = 0, | |
156 | }, | |
157 | }; | |
158 | ||
159 | static struct gpio_keys_platform_data n30_button_data = { | |
160 | .buttons = n30_buttons, | |
161 | .nbuttons = ARRAY_SIZE(n30_buttons), | |
162 | }; | |
163 | ||
164 | static struct platform_device n30_button_device = { | |
165 | .name = "gpio-keys", | |
166 | .id = -1, | |
167 | .dev = { | |
168 | .platform_data = &n30_button_data, | |
169 | } | |
170 | }; | |
171 | ||
95790873 CW |
172 | static struct gpio_keys_button n35_buttons[] = { |
173 | { | |
174 | .gpio = S3C2410_GPF0, | |
175 | .code = KEY_POWER, | |
176 | .desc = "Power", | |
177 | .active_low = 0, | |
178 | }, | |
179 | { | |
180 | .gpio = S3C2410_GPG9, | |
181 | .code = KEY_UP, | |
182 | .desc = "Joystick Up", | |
183 | .active_low = 0, | |
184 | }, | |
185 | { | |
186 | .gpio = S3C2410_GPG8, | |
187 | .code = KEY_DOWN, | |
188 | .desc = "Joystick Down", | |
189 | .active_low = 0, | |
190 | }, | |
191 | { | |
192 | .gpio = S3C2410_GPG6, | |
193 | .code = KEY_DOWN, | |
194 | .desc = "Joystick Left", | |
195 | .active_low = 0, | |
196 | }, | |
197 | { | |
198 | .gpio = S3C2410_GPG5, | |
199 | .code = KEY_DOWN, | |
200 | .desc = "Joystick Right", | |
201 | .active_low = 0, | |
202 | }, | |
203 | { | |
204 | .gpio = S3C2410_GPG7, | |
205 | .code = KEY_ENTER, | |
206 | .desc = "Joystick Press", | |
207 | .active_low = 0, | |
208 | }, | |
209 | { | |
210 | .gpio = S3C2410_GPF7, | |
211 | .code = KEY_HOMEPAGE, | |
212 | .desc = "Home", | |
213 | .active_low = 0, | |
214 | }, | |
215 | { | |
216 | .gpio = S3C2410_GPF6, | |
217 | .code = KEY_CALENDAR, | |
218 | .desc = "Calendar", | |
219 | .active_low = 0, | |
220 | }, | |
221 | { | |
222 | .gpio = S3C2410_GPF5, | |
223 | .code = KEY_ADDRESSBOOK, | |
224 | .desc = "Contacts", | |
225 | .active_low = 0, | |
226 | }, | |
227 | { | |
228 | .gpio = S3C2410_GPF4, | |
229 | .code = KEY_MAIL, | |
230 | .desc = "Mail", | |
231 | .active_low = 0, | |
232 | }, | |
233 | { | |
234 | .gpio = S3C2410_GPF3, | |
235 | .code = SW_RADIO, | |
236 | .desc = "GPS Antenna", | |
237 | .active_low = 0, | |
238 | }, | |
239 | { | |
240 | .gpio = S3C2410_GPG2, | |
241 | .code = SW_HEADPHONE_INSERT, | |
242 | .desc = "Headphone", | |
243 | .active_low = 0, | |
244 | }, | |
245 | }; | |
246 | ||
247 | static struct gpio_keys_platform_data n35_button_data = { | |
248 | .buttons = n35_buttons, | |
249 | .nbuttons = ARRAY_SIZE(n35_buttons), | |
250 | }; | |
251 | ||
252 | static struct platform_device n35_button_device = { | |
253 | .name = "gpio-keys", | |
254 | .id = -1, | |
255 | .num_resources = 0, | |
256 | .dev = { | |
257 | .platform_data = &n35_button_data, | |
258 | } | |
259 | }; | |
260 | ||
865cc639 CW |
261 | /* This is the bluetooth LED on the device. */ |
262 | static struct s3c24xx_led_platdata n30_blue_led_pdata = { | |
263 | .name = "blue_led", | |
264 | .gpio = S3C2410_GPG6, | |
265 | .def_trigger = "", | |
266 | }; | |
267 | ||
268 | /* This LED is driven by the battery microcontroller, and is blinking | |
269 | * red, blinking green or solid green when the battery is low, | |
270 | * charging or full respectively. By driving GPD9 low, it's possible | |
271 | * to force the LED to blink red, so call that warning LED. */ | |
272 | static struct s3c24xx_led_platdata n30_warning_led_pdata = { | |
273 | .name = "warning_led", | |
274 | .flags = S3C24XX_LEDF_ACTLOW, | |
275 | .gpio = S3C2410_GPD9, | |
276 | .def_trigger = "", | |
277 | }; | |
278 | ||
279 | static struct platform_device n30_blue_led = { | |
280 | .name = "s3c24xx_led", | |
281 | .id = 1, | |
282 | .dev = { | |
283 | .platform_data = &n30_blue_led_pdata, | |
284 | }, | |
285 | }; | |
286 | ||
287 | static struct platform_device n30_warning_led = { | |
288 | .name = "s3c24xx_led", | |
289 | .id = 2, | |
290 | .dev = { | |
291 | .platform_data = &n30_warning_led_pdata, | |
292 | }, | |
293 | }; | |
294 | ||
e43f2383 CW |
295 | static struct s3c2410fb_display n30_display __initdata = { |
296 | .type = S3C2410_LCDCON1_TFT, | |
297 | .width = 240, | |
298 | .height = 320, | |
299 | .pixclock = 170000, | |
300 | .xres = 240, | |
301 | .yres = 320, | |
302 | .bpp = 16, | |
303 | .left_margin = 3, | |
304 | .right_margin = 40, | |
305 | .hsync_len = 40, | |
306 | .upper_margin = 2, | |
307 | .lower_margin = 3, | |
308 | .vsync_len = 2, | |
309 | ||
310 | .lcdcon5 = S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME, | |
311 | }; | |
312 | ||
313 | static struct s3c2410fb_mach_info n30_fb_info __initdata = { | |
314 | .displays = &n30_display, | |
315 | .num_displays = 1, | |
316 | .default_display = 0, | |
317 | .lpcsel= 0x06, | |
318 | }; | |
319 | ||
1da177e4 | 320 | static struct platform_device *n30_devices[] __initdata = { |
1da177e4 LT |
321 | &s3c_device_lcd, |
322 | &s3c_device_wdt, | |
323 | &s3c_device_i2c, | |
324 | &s3c_device_iis, | |
196a0475 | 325 | &s3c_device_usb, |
1da177e4 | 326 | &s3c_device_usbgadget, |
62065750 | 327 | &n30_button_device, |
865cc639 CW |
328 | &n30_blue_led, |
329 | &n30_warning_led, | |
1da177e4 LT |
330 | }; |
331 | ||
95790873 CW |
332 | static struct platform_device *n35_devices[] __initdata = { |
333 | &s3c_device_lcd, | |
334 | &s3c_device_wdt, | |
335 | &s3c_device_i2c, | |
336 | &s3c_device_iis, | |
337 | &s3c_device_usbgadget, | |
338 | &n35_button_device, | |
339 | }; | |
340 | ||
1da177e4 LT |
341 | static struct s3c2410_platform_i2c n30_i2ccfg = { |
342 | .flags = 0, | |
343 | .slave_addr = 0x10, | |
344 | .bus_freq = 10*1000, | |
345 | .max_freq = 10*1000, | |
346 | }; | |
347 | ||
5fe10ab1 | 348 | static void __init n30_map_io(void) |
1da177e4 LT |
349 | { |
350 | s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc)); | |
351 | s3c24xx_init_clocks(0); | |
352 | s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs)); | |
1da177e4 LT |
353 | } |
354 | ||
5fe10ab1 | 355 | static void __init n30_init_irq(void) |
1da177e4 LT |
356 | { |
357 | s3c24xx_init_irq(); | |
358 | } | |
359 | ||
027da01d | 360 | /* GPB3 is the line that controls the pull-up for the USB D+ line */ |
1da177e4 | 361 | |
5fe10ab1 | 362 | static void __init n30_init(void) |
1da177e4 | 363 | { |
e43f2383 | 364 | s3c24xx_fb_set_platdata(&n30_fb_info); |
1da177e4 | 365 | s3c_device_i2c.dev.platform_data = &n30_i2ccfg; |
d088e5fe | 366 | s3c24xx_udc_set_platdata(&n30_udc_cfg); |
1da177e4 | 367 | |
027da01d BD |
368 | /* Turn off suspend on both USB ports, and switch the |
369 | * selectable USB port to USB device mode. */ | |
370 | ||
371 | s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST | | |
372 | S3C2410_MISCCR_USBSUSPND0 | | |
373 | S3C2410_MISCCR_USBSUSPND1, 0x0); | |
57e5171c | 374 | |
95790873 CW |
375 | if (machine_is_n30()) { |
376 | /* Turn off suspend on both USB ports, and switch the | |
377 | * selectable USB port to USB device mode. */ | |
378 | s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST | | |
379 | S3C2410_MISCCR_USBSUSPND0 | | |
380 | S3C2410_MISCCR_USBSUSPND1, 0x0); | |
381 | ||
382 | platform_add_devices(n30_devices, ARRAY_SIZE(n30_devices)); | |
383 | } | |
384 | ||
385 | if (machine_is_n35()) { | |
386 | /* Turn off suspend and switch the selectable USB port | |
387 | * to USB device mode. Turn on suspend for the host | |
388 | * port since it is not connected on the N35. | |
389 | * | |
390 | * Actually, the host port is available at some pads | |
391 | * on the back of the device, so it would actually be | |
392 | * possible to add a USB device inside the N35 if you | |
393 | * are willing to do some hardware modifications. */ | |
394 | s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST | | |
395 | S3C2410_MISCCR_USBSUSPND0 | | |
396 | S3C2410_MISCCR_USBSUSPND1, | |
397 | S3C2410_MISCCR_USBSUSPND1); | |
398 | ||
399 | platform_add_devices(n35_devices, ARRAY_SIZE(n35_devices)); | |
400 | } | |
1da177e4 LT |
401 | } |
402 | ||
403 | MACHINE_START(N30, "Acer-N30") | |
027da01d BD |
404 | /* Maintainer: Christer Weinigel <christer@weinigel.se>, |
405 | Ben Dooks <ben-linux@fluff.org> | |
406 | */ | |
e9dea0c6 RK |
407 | .phys_io = S3C2410_PA_UART, |
408 | .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, | |
409 | .boot_params = S3C2410_SDRAM_PA + 0x100, | |
1da177e4 LT |
410 | .timer = &s3c24xx_timer, |
411 | .init_machine = n30_init, | |
412 | .init_irq = n30_init_irq, | |
413 | .map_io = n30_map_io, | |
414 | MACHINE_END | |
95790873 CW |
415 | |
416 | MACHINE_START(N35, "Acer-N35") | |
417 | /* Maintainer: Christer Weinigel <christer@weinigel.se> | |
418 | */ | |
419 | .phys_io = S3C2410_PA_UART, | |
420 | .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, | |
421 | .boot_params = S3C2410_SDRAM_PA + 0x100, | |
422 | .timer = &s3c24xx_timer, | |
423 | .init_machine = n30_init, | |
424 | .init_irq = n30_init_irq, | |
425 | .map_io = n30_map_io, | |
426 | MACHINE_END |