1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Machine specific code for the Acer n30, Acer N35, Navman PiN 570,
4*4882a593Smuzhiyun // Yakumo AlphaX and Airis NC05 PDAs.
5*4882a593Smuzhiyun //
6*4882a593Smuzhiyun // Copyright (c) 2003-2005 Simtec Electronics
7*4882a593Smuzhiyun // Ben Dooks <ben@simtec.co.uk>
8*4882a593Smuzhiyun //
9*4882a593Smuzhiyun // Copyright (c) 2005-2008 Christer Weinigel <christer@weinigel.se>
10*4882a593Smuzhiyun //
11*4882a593Smuzhiyun // There is a wiki with more information about the n30 port at
12*4882a593Smuzhiyun // https://handhelds.org/moin/moin.cgi/AcerN30Documentation .
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <linux/kernel.h>
15*4882a593Smuzhiyun #include <linux/types.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/gpio_keys.h>
18*4882a593Smuzhiyun #include <linux/init.h>
19*4882a593Smuzhiyun #include <linux/gpio.h>
20*4882a593Smuzhiyun #include <linux/gpio/machine.h>
21*4882a593Smuzhiyun #include <linux/input.h>
22*4882a593Smuzhiyun #include <linux/interrupt.h>
23*4882a593Smuzhiyun #include <linux/platform_device.h>
24*4882a593Smuzhiyun #include <linux/serial_core.h>
25*4882a593Smuzhiyun #include <linux/serial_s3c.h>
26*4882a593Smuzhiyun #include <linux/timer.h>
27*4882a593Smuzhiyun #include <linux/io.h>
28*4882a593Smuzhiyun #include <linux/mmc/host.h>
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include "hardware-s3c24xx.h"
31*4882a593Smuzhiyun #include <asm/irq.h>
32*4882a593Smuzhiyun #include <asm/mach-types.h>
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include <linux/platform_data/fb-s3c2410.h>
35*4882a593Smuzhiyun #include <linux/platform_data/leds-s3c24xx.h>
36*4882a593Smuzhiyun #include "regs-gpio.h"
37*4882a593Smuzhiyun #include "gpio-samsung.h"
38*4882a593Smuzhiyun #include "gpio-cfg.h"
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #include <asm/mach/arch.h>
41*4882a593Smuzhiyun #include <asm/mach/irq.h>
42*4882a593Smuzhiyun #include <asm/mach/map.h>
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #include <linux/platform_data/i2c-s3c2410.h>
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #include "cpu.h"
47*4882a593Smuzhiyun #include "devs.h"
48*4882a593Smuzhiyun #include <linux/platform_data/mmc-s3cmci.h>
49*4882a593Smuzhiyun #include <linux/platform_data/usb-s3c2410_udc.h>
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #include "s3c24xx.h"
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun static struct map_desc n30_iodesc[] __initdata = {
54*4882a593Smuzhiyun /* nothing here yet */
55*4882a593Smuzhiyun };
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun static struct s3c2410_uartcfg n30_uartcfgs[] = {
58*4882a593Smuzhiyun /* Normal serial port */
59*4882a593Smuzhiyun [0] = {
60*4882a593Smuzhiyun .hwport = 0,
61*4882a593Smuzhiyun .flags = 0,
62*4882a593Smuzhiyun .ucon = 0x2c5,
63*4882a593Smuzhiyun .ulcon = 0x03,
64*4882a593Smuzhiyun .ufcon = 0x51,
65*4882a593Smuzhiyun },
66*4882a593Smuzhiyun /* IR port */
67*4882a593Smuzhiyun [1] = {
68*4882a593Smuzhiyun .hwport = 1,
69*4882a593Smuzhiyun .flags = 0,
70*4882a593Smuzhiyun .uart_flags = UPF_CONS_FLOW,
71*4882a593Smuzhiyun .ucon = 0x2c5,
72*4882a593Smuzhiyun .ulcon = 0x43,
73*4882a593Smuzhiyun .ufcon = 0x51,
74*4882a593Smuzhiyun },
75*4882a593Smuzhiyun /* On the N30 the bluetooth controller is connected here.
76*4882a593Smuzhiyun * On the N35 and variants the GPS receiver is connected here. */
77*4882a593Smuzhiyun [2] = {
78*4882a593Smuzhiyun .hwport = 2,
79*4882a593Smuzhiyun .flags = 0,
80*4882a593Smuzhiyun .ucon = 0x2c5,
81*4882a593Smuzhiyun .ulcon = 0x03,
82*4882a593Smuzhiyun .ufcon = 0x51,
83*4882a593Smuzhiyun },
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun static struct s3c2410_udc_mach_info n30_udc_cfg __initdata = {
87*4882a593Smuzhiyun .vbus_pin = S3C2410_GPG(1),
88*4882a593Smuzhiyun .vbus_pin_inverted = 0,
89*4882a593Smuzhiyun .pullup_pin = S3C2410_GPB(3),
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun static struct gpio_keys_button n30_buttons[] = {
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun .gpio = S3C2410_GPF(0),
95*4882a593Smuzhiyun .code = KEY_POWER,
96*4882a593Smuzhiyun .desc = "Power",
97*4882a593Smuzhiyun .active_low = 0,
98*4882a593Smuzhiyun },
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun .gpio = S3C2410_GPG(9),
101*4882a593Smuzhiyun .code = KEY_UP,
102*4882a593Smuzhiyun .desc = "Thumbwheel Up",
103*4882a593Smuzhiyun .active_low = 0,
104*4882a593Smuzhiyun },
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun .gpio = S3C2410_GPG(8),
107*4882a593Smuzhiyun .code = KEY_DOWN,
108*4882a593Smuzhiyun .desc = "Thumbwheel Down",
109*4882a593Smuzhiyun .active_low = 0,
110*4882a593Smuzhiyun },
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun .gpio = S3C2410_GPG(7),
113*4882a593Smuzhiyun .code = KEY_ENTER,
114*4882a593Smuzhiyun .desc = "Thumbwheel Press",
115*4882a593Smuzhiyun .active_low = 0,
116*4882a593Smuzhiyun },
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun .gpio = S3C2410_GPF(7),
119*4882a593Smuzhiyun .code = KEY_HOMEPAGE,
120*4882a593Smuzhiyun .desc = "Home",
121*4882a593Smuzhiyun .active_low = 0,
122*4882a593Smuzhiyun },
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun .gpio = S3C2410_GPF(6),
125*4882a593Smuzhiyun .code = KEY_CALENDAR,
126*4882a593Smuzhiyun .desc = "Calendar",
127*4882a593Smuzhiyun .active_low = 0,
128*4882a593Smuzhiyun },
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun .gpio = S3C2410_GPF(5),
131*4882a593Smuzhiyun .code = KEY_ADDRESSBOOK,
132*4882a593Smuzhiyun .desc = "Contacts",
133*4882a593Smuzhiyun .active_low = 0,
134*4882a593Smuzhiyun },
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun .gpio = S3C2410_GPF(4),
137*4882a593Smuzhiyun .code = KEY_MAIL,
138*4882a593Smuzhiyun .desc = "Mail",
139*4882a593Smuzhiyun .active_low = 0,
140*4882a593Smuzhiyun },
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun static struct gpio_keys_platform_data n30_button_data = {
144*4882a593Smuzhiyun .buttons = n30_buttons,
145*4882a593Smuzhiyun .nbuttons = ARRAY_SIZE(n30_buttons),
146*4882a593Smuzhiyun };
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun static struct platform_device n30_button_device = {
149*4882a593Smuzhiyun .name = "gpio-keys",
150*4882a593Smuzhiyun .id = -1,
151*4882a593Smuzhiyun .dev = {
152*4882a593Smuzhiyun .platform_data = &n30_button_data,
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun static struct gpio_keys_button n35_buttons[] = {
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun .gpio = S3C2410_GPF(0),
159*4882a593Smuzhiyun .code = KEY_POWER,
160*4882a593Smuzhiyun .type = EV_PWR,
161*4882a593Smuzhiyun .desc = "Power",
162*4882a593Smuzhiyun .active_low = 0,
163*4882a593Smuzhiyun .wakeup = 1,
164*4882a593Smuzhiyun },
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun .gpio = S3C2410_GPG(9),
167*4882a593Smuzhiyun .code = KEY_UP,
168*4882a593Smuzhiyun .desc = "Joystick Up",
169*4882a593Smuzhiyun .active_low = 0,
170*4882a593Smuzhiyun },
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun .gpio = S3C2410_GPG(8),
173*4882a593Smuzhiyun .code = KEY_DOWN,
174*4882a593Smuzhiyun .desc = "Joystick Down",
175*4882a593Smuzhiyun .active_low = 0,
176*4882a593Smuzhiyun },
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun .gpio = S3C2410_GPG(6),
179*4882a593Smuzhiyun .code = KEY_DOWN,
180*4882a593Smuzhiyun .desc = "Joystick Left",
181*4882a593Smuzhiyun .active_low = 0,
182*4882a593Smuzhiyun },
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun .gpio = S3C2410_GPG(5),
185*4882a593Smuzhiyun .code = KEY_DOWN,
186*4882a593Smuzhiyun .desc = "Joystick Right",
187*4882a593Smuzhiyun .active_low = 0,
188*4882a593Smuzhiyun },
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun .gpio = S3C2410_GPG(7),
191*4882a593Smuzhiyun .code = KEY_ENTER,
192*4882a593Smuzhiyun .desc = "Joystick Press",
193*4882a593Smuzhiyun .active_low = 0,
194*4882a593Smuzhiyun },
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun .gpio = S3C2410_GPF(7),
197*4882a593Smuzhiyun .code = KEY_HOMEPAGE,
198*4882a593Smuzhiyun .desc = "Home",
199*4882a593Smuzhiyun .active_low = 0,
200*4882a593Smuzhiyun },
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun .gpio = S3C2410_GPF(6),
203*4882a593Smuzhiyun .code = KEY_CALENDAR,
204*4882a593Smuzhiyun .desc = "Calendar",
205*4882a593Smuzhiyun .active_low = 0,
206*4882a593Smuzhiyun },
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun .gpio = S3C2410_GPF(5),
209*4882a593Smuzhiyun .code = KEY_ADDRESSBOOK,
210*4882a593Smuzhiyun .desc = "Contacts",
211*4882a593Smuzhiyun .active_low = 0,
212*4882a593Smuzhiyun },
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun .gpio = S3C2410_GPF(4),
215*4882a593Smuzhiyun .code = KEY_MAIL,
216*4882a593Smuzhiyun .desc = "Mail",
217*4882a593Smuzhiyun .active_low = 0,
218*4882a593Smuzhiyun },
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun .gpio = S3C2410_GPF(3),
221*4882a593Smuzhiyun .code = SW_RADIO,
222*4882a593Smuzhiyun .desc = "GPS Antenna",
223*4882a593Smuzhiyun .active_low = 0,
224*4882a593Smuzhiyun },
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun .gpio = S3C2410_GPG(2),
227*4882a593Smuzhiyun .code = SW_HEADPHONE_INSERT,
228*4882a593Smuzhiyun .desc = "Headphone",
229*4882a593Smuzhiyun .active_low = 0,
230*4882a593Smuzhiyun },
231*4882a593Smuzhiyun };
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun static struct gpio_keys_platform_data n35_button_data = {
234*4882a593Smuzhiyun .buttons = n35_buttons,
235*4882a593Smuzhiyun .nbuttons = ARRAY_SIZE(n35_buttons),
236*4882a593Smuzhiyun };
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun static struct platform_device n35_button_device = {
239*4882a593Smuzhiyun .name = "gpio-keys",
240*4882a593Smuzhiyun .id = -1,
241*4882a593Smuzhiyun .num_resources = 0,
242*4882a593Smuzhiyun .dev = {
243*4882a593Smuzhiyun .platform_data = &n35_button_data,
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun };
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun /* This is the bluetooth LED on the device. */
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun static struct gpiod_lookup_table n30_blue_led_gpio_table = {
250*4882a593Smuzhiyun .dev_id = "s3c24xx_led.1",
251*4882a593Smuzhiyun .table = {
252*4882a593Smuzhiyun GPIO_LOOKUP("GPG", 6, NULL, GPIO_ACTIVE_HIGH),
253*4882a593Smuzhiyun { },
254*4882a593Smuzhiyun },
255*4882a593Smuzhiyun };
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun static struct s3c24xx_led_platdata n30_blue_led_pdata = {
258*4882a593Smuzhiyun .name = "blue_led",
259*4882a593Smuzhiyun .def_trigger = "",
260*4882a593Smuzhiyun };
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun /* This is the blue LED on the device. Originally used to indicate GPS activity
263*4882a593Smuzhiyun * by flashing. */
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun static struct gpiod_lookup_table n35_blue_led_gpio_table = {
266*4882a593Smuzhiyun .dev_id = "s3c24xx_led.1",
267*4882a593Smuzhiyun .table = {
268*4882a593Smuzhiyun GPIO_LOOKUP("GPD", 8, NULL, GPIO_ACTIVE_HIGH),
269*4882a593Smuzhiyun { },
270*4882a593Smuzhiyun },
271*4882a593Smuzhiyun };
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun static struct s3c24xx_led_platdata n35_blue_led_pdata = {
274*4882a593Smuzhiyun .name = "blue_led",
275*4882a593Smuzhiyun .def_trigger = "",
276*4882a593Smuzhiyun };
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun /* This LED is driven by the battery microcontroller, and is blinking
279*4882a593Smuzhiyun * red, blinking green or solid green when the battery is low,
280*4882a593Smuzhiyun * charging or full respectively. By driving GPD9 low, it's possible
281*4882a593Smuzhiyun * to force the LED to blink red, so call that warning LED. */
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun static struct gpiod_lookup_table n30_warning_led_gpio_table = {
284*4882a593Smuzhiyun .dev_id = "s3c24xx_led.2",
285*4882a593Smuzhiyun .table = {
286*4882a593Smuzhiyun GPIO_LOOKUP("GPD", 9, NULL, GPIO_ACTIVE_LOW),
287*4882a593Smuzhiyun { },
288*4882a593Smuzhiyun },
289*4882a593Smuzhiyun };
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun static struct s3c24xx_led_platdata n30_warning_led_pdata = {
292*4882a593Smuzhiyun .name = "warning_led",
293*4882a593Smuzhiyun .def_trigger = "",
294*4882a593Smuzhiyun };
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun static struct gpiod_lookup_table n35_warning_led_gpio_table = {
297*4882a593Smuzhiyun .dev_id = "s3c24xx_led.2",
298*4882a593Smuzhiyun .table = {
299*4882a593Smuzhiyun GPIO_LOOKUP("GPD", 9, NULL, GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN),
300*4882a593Smuzhiyun { },
301*4882a593Smuzhiyun },
302*4882a593Smuzhiyun };
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun static struct s3c24xx_led_platdata n35_warning_led_pdata = {
305*4882a593Smuzhiyun .name = "warning_led",
306*4882a593Smuzhiyun .def_trigger = "",
307*4882a593Smuzhiyun };
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun static struct platform_device n30_blue_led = {
310*4882a593Smuzhiyun .name = "s3c24xx_led",
311*4882a593Smuzhiyun .id = 1,
312*4882a593Smuzhiyun .dev = {
313*4882a593Smuzhiyun .platform_data = &n30_blue_led_pdata,
314*4882a593Smuzhiyun },
315*4882a593Smuzhiyun };
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun static struct platform_device n35_blue_led = {
318*4882a593Smuzhiyun .name = "s3c24xx_led",
319*4882a593Smuzhiyun .id = 1,
320*4882a593Smuzhiyun .dev = {
321*4882a593Smuzhiyun .platform_data = &n35_blue_led_pdata,
322*4882a593Smuzhiyun },
323*4882a593Smuzhiyun };
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun static struct platform_device n30_warning_led = {
326*4882a593Smuzhiyun .name = "s3c24xx_led",
327*4882a593Smuzhiyun .id = 2,
328*4882a593Smuzhiyun .dev = {
329*4882a593Smuzhiyun .platform_data = &n30_warning_led_pdata,
330*4882a593Smuzhiyun },
331*4882a593Smuzhiyun };
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun static struct platform_device n35_warning_led = {
334*4882a593Smuzhiyun .name = "s3c24xx_led",
335*4882a593Smuzhiyun .id = 2,
336*4882a593Smuzhiyun .dev = {
337*4882a593Smuzhiyun .platform_data = &n35_warning_led_pdata,
338*4882a593Smuzhiyun },
339*4882a593Smuzhiyun };
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun static struct s3c2410fb_display n30_display __initdata = {
342*4882a593Smuzhiyun .type = S3C2410_LCDCON1_TFT,
343*4882a593Smuzhiyun .width = 240,
344*4882a593Smuzhiyun .height = 320,
345*4882a593Smuzhiyun .pixclock = 170000,
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun .xres = 240,
348*4882a593Smuzhiyun .yres = 320,
349*4882a593Smuzhiyun .bpp = 16,
350*4882a593Smuzhiyun .left_margin = 3,
351*4882a593Smuzhiyun .right_margin = 40,
352*4882a593Smuzhiyun .hsync_len = 40,
353*4882a593Smuzhiyun .upper_margin = 2,
354*4882a593Smuzhiyun .lower_margin = 3,
355*4882a593Smuzhiyun .vsync_len = 2,
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun .lcdcon5 = S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME,
358*4882a593Smuzhiyun };
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun static struct s3c2410fb_mach_info n30_fb_info __initdata = {
361*4882a593Smuzhiyun .displays = &n30_display,
362*4882a593Smuzhiyun .num_displays = 1,
363*4882a593Smuzhiyun .default_display = 0,
364*4882a593Smuzhiyun .lpcsel = 0x06,
365*4882a593Smuzhiyun };
366*4882a593Smuzhiyun
n30_sdi_set_power(unsigned char power_mode,unsigned short vdd)367*4882a593Smuzhiyun static void n30_sdi_set_power(unsigned char power_mode, unsigned short vdd)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun s3c24xx_mci_def_set_power(power_mode, vdd);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun switch (power_mode) {
372*4882a593Smuzhiyun case MMC_POWER_ON:
373*4882a593Smuzhiyun case MMC_POWER_UP:
374*4882a593Smuzhiyun gpio_set_value(S3C2410_GPG(4), 1);
375*4882a593Smuzhiyun break;
376*4882a593Smuzhiyun case MMC_POWER_OFF:
377*4882a593Smuzhiyun default:
378*4882a593Smuzhiyun gpio_set_value(S3C2410_GPG(4), 0);
379*4882a593Smuzhiyun break;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun static struct s3c24xx_mci_pdata n30_mci_cfg __initdata = {
384*4882a593Smuzhiyun .ocr_avail = MMC_VDD_32_33,
385*4882a593Smuzhiyun .set_power = n30_sdi_set_power,
386*4882a593Smuzhiyun };
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun static struct gpiod_lookup_table n30_mci_gpio_table = {
389*4882a593Smuzhiyun .dev_id = "s3c2410-sdi",
390*4882a593Smuzhiyun .table = {
391*4882a593Smuzhiyun /* Card detect S3C2410_GPF(1) */
392*4882a593Smuzhiyun GPIO_LOOKUP("GPIOF", 1, "cd", GPIO_ACTIVE_LOW),
393*4882a593Smuzhiyun /* Write protect S3C2410_GPG(10) */
394*4882a593Smuzhiyun GPIO_LOOKUP("GPIOG", 10, "wp", GPIO_ACTIVE_LOW),
395*4882a593Smuzhiyun { },
396*4882a593Smuzhiyun /* bus pins */
397*4882a593Smuzhiyun GPIO_LOOKUP_IDX("GPIOE", 5, "bus", 0, GPIO_ACTIVE_HIGH),
398*4882a593Smuzhiyun GPIO_LOOKUP_IDX("GPIOE", 6, "bus", 1, GPIO_ACTIVE_HIGH),
399*4882a593Smuzhiyun GPIO_LOOKUP_IDX("GPIOE", 7, "bus", 2, GPIO_ACTIVE_HIGH),
400*4882a593Smuzhiyun GPIO_LOOKUP_IDX("GPIOE", 8, "bus", 3, GPIO_ACTIVE_HIGH),
401*4882a593Smuzhiyun GPIO_LOOKUP_IDX("GPIOE", 9, "bus", 4, GPIO_ACTIVE_HIGH),
402*4882a593Smuzhiyun GPIO_LOOKUP_IDX("GPIOE", 10, "bus", 5, GPIO_ACTIVE_HIGH),
403*4882a593Smuzhiyun },
404*4882a593Smuzhiyun };
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun static struct platform_device *n30_devices[] __initdata = {
407*4882a593Smuzhiyun &s3c_device_lcd,
408*4882a593Smuzhiyun &s3c_device_wdt,
409*4882a593Smuzhiyun &s3c_device_i2c0,
410*4882a593Smuzhiyun &s3c_device_iis,
411*4882a593Smuzhiyun &s3c_device_ohci,
412*4882a593Smuzhiyun &s3c_device_rtc,
413*4882a593Smuzhiyun &s3c_device_usbgadget,
414*4882a593Smuzhiyun &s3c_device_sdi,
415*4882a593Smuzhiyun &n30_button_device,
416*4882a593Smuzhiyun &n30_blue_led,
417*4882a593Smuzhiyun &n30_warning_led,
418*4882a593Smuzhiyun };
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun static struct platform_device *n35_devices[] __initdata = {
421*4882a593Smuzhiyun &s3c_device_lcd,
422*4882a593Smuzhiyun &s3c_device_wdt,
423*4882a593Smuzhiyun &s3c_device_i2c0,
424*4882a593Smuzhiyun &s3c_device_iis,
425*4882a593Smuzhiyun &s3c_device_rtc,
426*4882a593Smuzhiyun &s3c_device_usbgadget,
427*4882a593Smuzhiyun &s3c_device_sdi,
428*4882a593Smuzhiyun &n35_button_device,
429*4882a593Smuzhiyun &n35_blue_led,
430*4882a593Smuzhiyun &n35_warning_led,
431*4882a593Smuzhiyun };
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun static struct s3c2410_platform_i2c __initdata n30_i2ccfg = {
434*4882a593Smuzhiyun .flags = 0,
435*4882a593Smuzhiyun .slave_addr = 0x10,
436*4882a593Smuzhiyun .frequency = 10*1000,
437*4882a593Smuzhiyun };
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun /* Lots of hardcoded stuff, but it sets up the hardware in a useful
440*4882a593Smuzhiyun * state so that we can boot Linux directly from flash. */
n30_hwinit(void)441*4882a593Smuzhiyun static void __init n30_hwinit(void)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun /* GPA0-11 special functions -- unknown what they do
444*4882a593Smuzhiyun * GPA12 N30 special function -- unknown what it does
445*4882a593Smuzhiyun * N35/PiN output -- unknown what it does
446*4882a593Smuzhiyun *
447*4882a593Smuzhiyun * A12 is nGCS1 on the N30 and an output on the N35/PiN. I
448*4882a593Smuzhiyun * don't think it does anything useful on the N30, so I ought
449*4882a593Smuzhiyun * to make it an output there too since it always driven to 0
450*4882a593Smuzhiyun * as far as I can tell. */
451*4882a593Smuzhiyun if (machine_is_n30())
452*4882a593Smuzhiyun __raw_writel(0x007fffff, S3C2410_GPACON);
453*4882a593Smuzhiyun if (machine_is_n35())
454*4882a593Smuzhiyun __raw_writel(0x007fefff, S3C2410_GPACON);
455*4882a593Smuzhiyun __raw_writel(0x00000000, S3C2410_GPADAT);
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun /* GPB0 TOUT0 backlight level
458*4882a593Smuzhiyun * GPB1 output 1=backlight on
459*4882a593Smuzhiyun * GPB2 output IrDA enable 0=transceiver enabled, 1=disabled
460*4882a593Smuzhiyun * GPB3 output USB D+ pull up 0=disabled, 1=enabled
461*4882a593Smuzhiyun * GPB4 N30 output -- unknown function
462*4882a593Smuzhiyun * N30/PiN GPS control 0=GPS enabled, 1=GPS disabled
463*4882a593Smuzhiyun * GPB5 output -- unknown function
464*4882a593Smuzhiyun * GPB6 input -- unknown function
465*4882a593Smuzhiyun * GPB7 output -- unknown function
466*4882a593Smuzhiyun * GPB8 output -- probably LCD driver enable
467*4882a593Smuzhiyun * GPB9 output -- probably LCD VSYNC driver enable
468*4882a593Smuzhiyun * GPB10 output -- probably LCD HSYNC driver enable
469*4882a593Smuzhiyun */
470*4882a593Smuzhiyun __raw_writel(0x00154556, S3C2410_GPBCON);
471*4882a593Smuzhiyun __raw_writel(0x00000750, S3C2410_GPBDAT);
472*4882a593Smuzhiyun __raw_writel(0x00000073, S3C2410_GPBUP);
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun /* GPC0 input RS232 DCD/DSR/RI
475*4882a593Smuzhiyun * GPC1 LCD
476*4882a593Smuzhiyun * GPC2 output RS232 DTR?
477*4882a593Smuzhiyun * GPC3 input RS232 DCD/DSR/RI
478*4882a593Smuzhiyun * GPC4 LCD
479*4882a593Smuzhiyun * GPC5 output 0=NAND write enabled, 1=NAND write protect
480*4882a593Smuzhiyun * GPC6 input -- unknown function
481*4882a593Smuzhiyun * GPC7 input charger status 0=charger connected
482*4882a593Smuzhiyun * this input can be triggered by power on the USB device
483*4882a593Smuzhiyun * port too, but will go back to disconnected soon after.
484*4882a593Smuzhiyun * GPC8 N30/N35 output -- unknown function, always driven to 1
485*4882a593Smuzhiyun * PiN input -- unknown function, always read as 1
486*4882a593Smuzhiyun * Make it an input with a pull up for all models.
487*4882a593Smuzhiyun * GPC9-15 LCD
488*4882a593Smuzhiyun */
489*4882a593Smuzhiyun __raw_writel(0xaaa80618, S3C2410_GPCCON);
490*4882a593Smuzhiyun __raw_writel(0x0000014c, S3C2410_GPCDAT);
491*4882a593Smuzhiyun __raw_writel(0x0000fef2, S3C2410_GPCUP);
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun /* GPD0 input -- unknown function
494*4882a593Smuzhiyun * GPD1-D7 LCD
495*4882a593Smuzhiyun * GPD8 N30 output -- unknown function
496*4882a593Smuzhiyun * N35/PiN output 1=GPS LED on
497*4882a593Smuzhiyun * GPD9 output 0=power led blinks red, 1=normal power led function
498*4882a593Smuzhiyun * GPD10 output -- unknown function
499*4882a593Smuzhiyun * GPD11-15 LCD drivers
500*4882a593Smuzhiyun */
501*4882a593Smuzhiyun __raw_writel(0xaa95aaa4, S3C2410_GPDCON);
502*4882a593Smuzhiyun __raw_writel(0x00000601, S3C2410_GPDDAT);
503*4882a593Smuzhiyun __raw_writel(0x0000fbfe, S3C2410_GPDUP);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun /* GPE0-4 I2S audio bus
506*4882a593Smuzhiyun * GPE5-10 SD/MMC bus
507*4882a593Smuzhiyun * E11-13 outputs -- unknown function, probably power management
508*4882a593Smuzhiyun * E14-15 I2C bus connected to the battery controller
509*4882a593Smuzhiyun */
510*4882a593Smuzhiyun __raw_writel(0xa56aaaaa, S3C2410_GPECON);
511*4882a593Smuzhiyun __raw_writel(0x0000efc5, S3C2410_GPEDAT);
512*4882a593Smuzhiyun __raw_writel(0x0000f81f, S3C2410_GPEUP);
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun /* GPF0 input 0=power button pressed
515*4882a593Smuzhiyun * GPF1 input SD/MMC switch 0=card present
516*4882a593Smuzhiyun * GPF2 N30 1=reset button pressed (inverted compared to the rest)
517*4882a593Smuzhiyun * N35/PiN 0=reset button pressed
518*4882a593Smuzhiyun * GPF3 N30/PiN input -- unknown function
519*4882a593Smuzhiyun * N35 input GPS antenna position, 0=antenna closed, 1=open
520*4882a593Smuzhiyun * GPF4 input 0=button 4 pressed
521*4882a593Smuzhiyun * GPF5 input 0=button 3 pressed
522*4882a593Smuzhiyun * GPF6 input 0=button 2 pressed
523*4882a593Smuzhiyun * GPF7 input 0=button 1 pressed
524*4882a593Smuzhiyun */
525*4882a593Smuzhiyun __raw_writel(0x0000aaaa, S3C2410_GPFCON);
526*4882a593Smuzhiyun __raw_writel(0x00000000, S3C2410_GPFDAT);
527*4882a593Smuzhiyun __raw_writel(0x000000ff, S3C2410_GPFUP);
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /* GPG0 input RS232 DCD/DSR/RI
530*4882a593Smuzhiyun * GPG1 input 1=USB gadget port has power from a host
531*4882a593Smuzhiyun * GPG2 N30 input -- unknown function
532*4882a593Smuzhiyun * N35/PiN input 0=headphones plugged in, 1=not plugged in
533*4882a593Smuzhiyun * GPG3 N30 output -- unknown function
534*4882a593Smuzhiyun * N35/PiN input with unknown function
535*4882a593Smuzhiyun * GPG4 N30 output 0=MMC enabled, 1=MMC disabled
536*4882a593Smuzhiyun * GPG5 N30 output 0=BlueTooth chip disabled, 1=enabled
537*4882a593Smuzhiyun * N35/PiN input joystick right
538*4882a593Smuzhiyun * GPG6 N30 output 0=blue led on, 1=off
539*4882a593Smuzhiyun * N35/PiN input joystick left
540*4882a593Smuzhiyun * GPG7 input 0=thumbwheel pressed
541*4882a593Smuzhiyun * GPG8 input 0=thumbwheel down
542*4882a593Smuzhiyun * GPG9 input 0=thumbwheel up
543*4882a593Smuzhiyun * GPG10 input SD/MMC write protect switch
544*4882a593Smuzhiyun * GPG11 N30 input -- unknown function
545*4882a593Smuzhiyun * N35 output 0=GPS antenna powered, 1=not powered
546*4882a593Smuzhiyun * PiN output -- unknown function
547*4882a593Smuzhiyun * GPG12-15 touch screen functions
548*4882a593Smuzhiyun *
549*4882a593Smuzhiyun * The pullups differ between the models, so enable all
550*4882a593Smuzhiyun * pullups that are enabled on any of the models.
551*4882a593Smuzhiyun */
552*4882a593Smuzhiyun if (machine_is_n30())
553*4882a593Smuzhiyun __raw_writel(0xff0a956a, S3C2410_GPGCON);
554*4882a593Smuzhiyun if (machine_is_n35())
555*4882a593Smuzhiyun __raw_writel(0xff4aa92a, S3C2410_GPGCON);
556*4882a593Smuzhiyun __raw_writel(0x0000e800, S3C2410_GPGDAT);
557*4882a593Smuzhiyun __raw_writel(0x0000f86f, S3C2410_GPGUP);
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun /* GPH0/1/2/3 RS232 serial port
560*4882a593Smuzhiyun * GPH4/5 IrDA serial port
561*4882a593Smuzhiyun * GPH6/7 N30 BlueTooth serial port
562*4882a593Smuzhiyun * N35/PiN GPS receiver
563*4882a593Smuzhiyun * GPH8 input -- unknown function
564*4882a593Smuzhiyun * GPH9 CLKOUT0 HCLK -- unknown use
565*4882a593Smuzhiyun * GPH10 CLKOUT1 FCLK -- unknown use
566*4882a593Smuzhiyun *
567*4882a593Smuzhiyun * The pull ups for H6/H7 are enabled on N30 but not on the
568*4882a593Smuzhiyun * N35/PiN. I suppose is useful for a budget model of the N30
569*4882a593Smuzhiyun * with no bluetooth. It doesn't hurt to have the pull ups
570*4882a593Smuzhiyun * enabled on the N35, so leave them enabled for all models.
571*4882a593Smuzhiyun */
572*4882a593Smuzhiyun __raw_writel(0x0028aaaa, S3C2410_GPHCON);
573*4882a593Smuzhiyun __raw_writel(0x000005ef, S3C2410_GPHDAT);
574*4882a593Smuzhiyun __raw_writel(0x0000063f, S3C2410_GPHUP);
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
n30_map_io(void)577*4882a593Smuzhiyun static void __init n30_map_io(void)
578*4882a593Smuzhiyun {
579*4882a593Smuzhiyun s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc));
580*4882a593Smuzhiyun n30_hwinit();
581*4882a593Smuzhiyun s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs));
582*4882a593Smuzhiyun s3c24xx_set_timer_source(S3C24XX_PWM3, S3C24XX_PWM4);
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun
n30_init_time(void)585*4882a593Smuzhiyun static void __init n30_init_time(void)
586*4882a593Smuzhiyun {
587*4882a593Smuzhiyun s3c2410_init_clocks(12000000);
588*4882a593Smuzhiyun s3c24xx_timer_init();
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun /* GPB3 is the line that controls the pull-up for the USB D+ line */
592*4882a593Smuzhiyun
n30_init(void)593*4882a593Smuzhiyun static void __init n30_init(void)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun WARN_ON(gpio_request(S3C2410_GPG(4), "mmc power"));
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun s3c24xx_fb_set_platdata(&n30_fb_info);
598*4882a593Smuzhiyun s3c24xx_udc_set_platdata(&n30_udc_cfg);
599*4882a593Smuzhiyun gpiod_add_lookup_table(&n30_mci_gpio_table);
600*4882a593Smuzhiyun s3c24xx_mci_set_platdata(&n30_mci_cfg);
601*4882a593Smuzhiyun s3c_i2c0_set_platdata(&n30_i2ccfg);
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun /* Turn off suspend on both USB ports, and switch the
604*4882a593Smuzhiyun * selectable USB port to USB device mode. */
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
607*4882a593Smuzhiyun S3C2410_MISCCR_USBSUSPND0 |
608*4882a593Smuzhiyun S3C2410_MISCCR_USBSUSPND1, 0x0);
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun /* Configure the I2S pins (GPE0...GPE4) in correct mode */
611*4882a593Smuzhiyun s3c_gpio_cfgall_range(S3C2410_GPE(0), 5, S3C_GPIO_SFN(2),
612*4882a593Smuzhiyun S3C_GPIO_PULL_NONE);
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun if (machine_is_n30()) {
615*4882a593Smuzhiyun /* Turn off suspend on both USB ports, and switch the
616*4882a593Smuzhiyun * selectable USB port to USB device mode. */
617*4882a593Smuzhiyun s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
618*4882a593Smuzhiyun S3C2410_MISCCR_USBSUSPND0 |
619*4882a593Smuzhiyun S3C2410_MISCCR_USBSUSPND1, 0x0);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun /* Disable pull-up and add GPIO tables */
622*4882a593Smuzhiyun s3c_gpio_setpull(S3C2410_GPG(6), S3C_GPIO_PULL_NONE);
623*4882a593Smuzhiyun s3c_gpio_setpull(S3C2410_GPD(9), S3C_GPIO_PULL_NONE);
624*4882a593Smuzhiyun gpiod_add_lookup_table(&n30_blue_led_gpio_table);
625*4882a593Smuzhiyun gpiod_add_lookup_table(&n30_warning_led_gpio_table);
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun platform_add_devices(n30_devices, ARRAY_SIZE(n30_devices));
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun if (machine_is_n35()) {
631*4882a593Smuzhiyun /* Turn off suspend and switch the selectable USB port
632*4882a593Smuzhiyun * to USB device mode. Turn on suspend for the host
633*4882a593Smuzhiyun * port since it is not connected on the N35.
634*4882a593Smuzhiyun *
635*4882a593Smuzhiyun * Actually, the host port is available at some pads
636*4882a593Smuzhiyun * on the back of the device, so it would actually be
637*4882a593Smuzhiyun * possible to add a USB device inside the N35 if you
638*4882a593Smuzhiyun * are willing to do some hardware modifications. */
639*4882a593Smuzhiyun s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
640*4882a593Smuzhiyun S3C2410_MISCCR_USBSUSPND0 |
641*4882a593Smuzhiyun S3C2410_MISCCR_USBSUSPND1,
642*4882a593Smuzhiyun S3C2410_MISCCR_USBSUSPND0);
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun /* Disable pull-up and add GPIO tables */
645*4882a593Smuzhiyun s3c_gpio_setpull(S3C2410_GPD(8), S3C_GPIO_PULL_NONE);
646*4882a593Smuzhiyun s3c_gpio_setpull(S3C2410_GPD(9), S3C_GPIO_PULL_NONE);
647*4882a593Smuzhiyun gpiod_add_lookup_table(&n35_blue_led_gpio_table);
648*4882a593Smuzhiyun gpiod_add_lookup_table(&n35_warning_led_gpio_table);
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun platform_add_devices(n35_devices, ARRAY_SIZE(n35_devices));
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun MACHINE_START(N30, "Acer-N30")
655*4882a593Smuzhiyun /* Maintainer: Christer Weinigel <christer@weinigel.se>,
656*4882a593Smuzhiyun Ben Dooks <ben-linux@fluff.org>
657*4882a593Smuzhiyun */
658*4882a593Smuzhiyun .atag_offset = 0x100,
659*4882a593Smuzhiyun .init_time = n30_init_time,
660*4882a593Smuzhiyun .init_machine = n30_init,
661*4882a593Smuzhiyun .init_irq = s3c2410_init_irq,
662*4882a593Smuzhiyun .map_io = n30_map_io,
663*4882a593Smuzhiyun MACHINE_END
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun MACHINE_START(N35, "Acer-N35")
666*4882a593Smuzhiyun /* Maintainer: Christer Weinigel <christer@weinigel.se>
667*4882a593Smuzhiyun */
668*4882a593Smuzhiyun .atag_offset = 0x100,
669*4882a593Smuzhiyun .init_time = n30_init_time,
670*4882a593Smuzhiyun .init_machine = n30_init,
671*4882a593Smuzhiyun .init_irq = s3c2410_init_irq,
672*4882a593Smuzhiyun .map_io = n30_map_io,
673*4882a593Smuzhiyun MACHINE_END
674