Merge branch 'parisc-4.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller...
[sfrench/cifs-2.6.git] / arch / arm / mach-omap1 / board-sx1.c
1 /*
2 * linux/arch/arm/mach-omap1/board-sx1.c
3 *
4 * Modified from board-generic.c
5 *
6 * Support for the Siemens SX1 mobile phone.
7 *
8 * Original version : Vladimir Ananiev (Vovan888-at-gmail com)
9 *
10 * Maintainters : Vladimir Ananiev (aka Vovan888), Sergge
11 *               oslik.ru
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17 #include <linux/gpio.h>
18 #include <linux/kernel.h>
19 #include <linux/init.h>
20 #include <linux/input.h>
21 #include <linux/platform_device.h>
22 #include <linux/notifier.h>
23 #include <linux/mtd/mtd.h>
24 #include <linux/mtd/partitions.h>
25 #include <linux/mtd/physmap.h>
26 #include <linux/types.h>
27 #include <linux/i2c.h>
28 #include <linux/errno.h>
29 #include <linux/export.h>
30 #include <linux/omapfb.h>
31 #include <linux/platform_data/keypad-omap.h>
32
33 #include <asm/mach-types.h>
34 #include <asm/mach/arch.h>
35 #include <asm/mach/map.h>
36
37 #include "flash.h"
38 #include <mach/mux.h>
39 #include <linux/omap-dma.h>
40 #include <mach/tc.h>
41 #include "board-sx1.h"
42
43 #include <mach/hardware.h>
44 #include <mach/usb.h>
45
46 #include "common.h"
47
48 /* Write to I2C device */
49 int sx1_i2c_write_byte(u8 devaddr, u8 regoffset, u8 value)
50 {
51         struct i2c_adapter *adap;
52         int err;
53         struct i2c_msg msg[1];
54         unsigned char data[2];
55
56         adap = i2c_get_adapter(0);
57         if (!adap)
58                 return -ENODEV;
59         msg->addr = devaddr;    /* I2C address of chip */
60         msg->flags = 0;
61         msg->len = 2;
62         msg->buf = data;
63         data[0] = regoffset;    /* register num */
64         data[1] = value;                /* register data */
65         err = i2c_transfer(adap, msg, 1);
66         i2c_put_adapter(adap);
67         if (err >= 0)
68                 return 0;
69         return err;
70 }
71
72 /* Read from I2C device */
73 int sx1_i2c_read_byte(u8 devaddr, u8 regoffset, u8 *value)
74 {
75         struct i2c_adapter *adap;
76         int err;
77         struct i2c_msg msg[1];
78         unsigned char data[2];
79
80         adap = i2c_get_adapter(0);
81         if (!adap)
82                 return -ENODEV;
83
84         msg->addr = devaddr;    /* I2C address of chip */
85         msg->flags = 0;
86         msg->len = 1;
87         msg->buf = data;
88         data[0] = regoffset;    /* register num */
89         err = i2c_transfer(adap, msg, 1);
90
91         msg->addr = devaddr;    /* I2C address */
92         msg->flags = I2C_M_RD;
93         msg->len = 1;
94         msg->buf = data;
95         err = i2c_transfer(adap, msg, 1);
96         *value = data[0];
97         i2c_put_adapter(adap);
98
99         if (err >= 0)
100                 return 0;
101         return err;
102 }
103 /* set keyboard backlight intensity */
104 int sx1_setkeylight(u8 keylight)
105 {
106         if (keylight > SOFIA_MAX_LIGHT_VAL)
107                 keylight = SOFIA_MAX_LIGHT_VAL;
108         return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_KEYLIGHT_REG, keylight);
109 }
110 /* get current keylight intensity */
111 int sx1_getkeylight(u8 * keylight)
112 {
113         return sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_KEYLIGHT_REG, keylight);
114 }
115 /* set LCD backlight intensity */
116 int sx1_setbacklight(u8 backlight)
117 {
118         if (backlight > SOFIA_MAX_LIGHT_VAL)
119                 backlight = SOFIA_MAX_LIGHT_VAL;
120         return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_BACKLIGHT_REG,
121                                   backlight);
122 }
123 /* get current LCD backlight intensity */
124 int sx1_getbacklight (u8 * backlight)
125 {
126         return sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_BACKLIGHT_REG,
127                                  backlight);
128 }
129 /* set LCD backlight power on/off */
130 int sx1_setmmipower(u8 onoff)
131 {
132         int err;
133         u8 dat = 0;
134         err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
135         if (err < 0)
136                 return err;
137         if (onoff)
138                 dat |= SOFIA_MMILIGHT_POWER;
139         else
140                 dat &= ~SOFIA_MMILIGHT_POWER;
141         return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
142 }
143
144 /* set USB power on/off */
145 int sx1_setusbpower(u8 onoff)
146 {
147         int err;
148         u8 dat = 0;
149         err = sx1_i2c_read_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, &dat);
150         if (err < 0)
151                 return err;
152         if (onoff)
153                 dat |= SOFIA_USB_POWER;
154         else
155                 dat &= ~SOFIA_USB_POWER;
156         return sx1_i2c_write_byte(SOFIA_I2C_ADDR, SOFIA_POWER1_REG, dat);
157 }
158
159 EXPORT_SYMBOL(sx1_setkeylight);
160 EXPORT_SYMBOL(sx1_getkeylight);
161 EXPORT_SYMBOL(sx1_setbacklight);
162 EXPORT_SYMBOL(sx1_getbacklight);
163 EXPORT_SYMBOL(sx1_setmmipower);
164 EXPORT_SYMBOL(sx1_setusbpower);
165
166 /*----------- Keypad -------------------------*/
167
168 static const unsigned int sx1_keymap[] = {
169         KEY(3, 5, GROUP_0 | 117), /* camera Qt::Key_F17 */
170         KEY(4, 0, GROUP_0 | 114), /* voice memo Qt::Key_F14 */
171         KEY(4, 1, GROUP_2 | 114), /* voice memo */
172         KEY(4, 2, GROUP_3 | 114), /* voice memo */
173         KEY(0, 0, GROUP_1 | KEY_F12),   /* red button Qt::Key_Hangup */
174         KEY(3, 4, GROUP_1 | KEY_LEFT),
175         KEY(3, 2, GROUP_1 | KEY_DOWN),
176         KEY(3, 1, GROUP_1 | KEY_RIGHT),
177         KEY(3, 0, GROUP_1 | KEY_UP),
178         KEY(3, 3, GROUP_1 | KEY_POWER), /* joystick press or Qt::Key_Select */
179         KEY(0, 5, GROUP_1 | KEY_1),
180         KEY(0, 4, GROUP_1 | KEY_2),
181         KEY(0, 3, GROUP_1 | KEY_3),
182         KEY(4, 3, GROUP_1 | KEY_4),
183         KEY(4, 4, GROUP_1 | KEY_5),
184         KEY(4, 5, GROUP_1 | KEY_KPASTERISK),/* "*" */
185         KEY(1, 4, GROUP_1 | KEY_6),
186         KEY(1, 5, GROUP_1 | KEY_7),
187         KEY(1, 3, GROUP_1 | KEY_8),
188         KEY(2, 3, GROUP_1 | KEY_9),
189         KEY(2, 5, GROUP_1 | KEY_0),
190         KEY(2, 4, GROUP_1 | 113), /* # F13 Toggle input method Qt::Key_F13 */
191         KEY(1, 0, GROUP_1 | KEY_F11),   /* green button Qt::Key_Call */
192         KEY(2, 1, GROUP_1 | KEY_YEN),   /* left soft Qt::Key_Context1 */
193         KEY(2, 2, GROUP_1 | KEY_F8),    /* right soft Qt::Key_Back */
194         KEY(1, 2, GROUP_1 | KEY_LEFTSHIFT), /* shift */
195         KEY(1, 1, GROUP_1 | KEY_BACKSPACE), /* C (clear) */
196         KEY(2, 0, GROUP_1 | KEY_F7),    /* menu Qt::Key_Menu */
197 };
198
199 static struct resource sx1_kp_resources[] = {
200         [0] = {
201                 .start  = INT_KEYBOARD,
202                 .end    = INT_KEYBOARD,
203                 .flags  = IORESOURCE_IRQ,
204         },
205 };
206
207 static const struct matrix_keymap_data sx1_keymap_data = {
208         .keymap         = sx1_keymap,
209         .keymap_size    = ARRAY_SIZE(sx1_keymap),
210 };
211
212 static struct omap_kp_platform_data sx1_kp_data = {
213         .rows           = 6,
214         .cols           = 6,
215         .keymap_data    = &sx1_keymap_data,
216         .delay  = 80,
217 };
218
219 static struct platform_device sx1_kp_device = {
220         .name           = "omap-keypad",
221         .id             = -1,
222         .dev            = {
223                 .platform_data = &sx1_kp_data,
224         },
225         .num_resources  = ARRAY_SIZE(sx1_kp_resources),
226         .resource       = sx1_kp_resources,
227 };
228
229 /*----------- MTD -------------------------*/
230
231 static struct mtd_partition sx1_partitions[] = {
232         /* bootloader (U-Boot, etc) in first sector */
233         {
234                 .name           = "bootloader",
235                 .offset         = 0x01800000,
236                 .size           = SZ_128K,
237                 .mask_flags     = MTD_WRITEABLE, /* force read-only */
238         },
239         /* bootloader params in the next sector */
240         {
241                 .name           = "params",
242                 .offset         = MTDPART_OFS_APPEND,
243                 .size           = SZ_128K,
244                 .mask_flags     = 0,
245         },
246         /* kernel */
247         {
248                 .name           = "kernel",
249                 .offset         = MTDPART_OFS_APPEND,
250                 .size           = SZ_2M - 2 * SZ_128K,
251                 .mask_flags     = 0
252         },
253         /* file system */
254         {
255                 .name           = "filesystem",
256                 .offset         = MTDPART_OFS_APPEND,
257                 .size           = MTDPART_SIZ_FULL,
258                 .mask_flags     = 0
259         }
260 };
261
262 static struct physmap_flash_data sx1_flash_data = {
263         .width          = 2,
264         .set_vpp        = omap1_set_vpp,
265         .parts          = sx1_partitions,
266         .nr_parts       = ARRAY_SIZE(sx1_partitions),
267 };
268
269 /* MTD Intel 4000 flash - new flashes */
270 static struct resource sx1_new_flash_resource = {
271         .start          = OMAP_CS0_PHYS,
272         .end            = OMAP_CS0_PHYS + SZ_32M - 1,
273         .flags          = IORESOURCE_MEM,
274 };
275
276 static struct platform_device sx1_flash_device = {
277         .name           = "physmap-flash",
278         .id             = 0,
279         .dev            = {
280                 .platform_data  = &sx1_flash_data,
281         },
282         .num_resources  = 1,
283         .resource       = &sx1_new_flash_resource,
284 };
285
286 /*----------- USB -------------------------*/
287
288 static struct omap_usb_config sx1_usb_config __initdata = {
289         .otg            = 0,
290         .register_dev   = 1,
291         .register_host  = 0,
292         .hmc_mode       = 0,
293         .pins[0]        = 2,
294         .pins[1]        = 0,
295         .pins[2]        = 0,
296 };
297
298 /*----------- LCD -------------------------*/
299
300 static const struct omap_lcd_config sx1_lcd_config __initconst = {
301         .ctrl_name      = "internal",
302 };
303
304 /*-----------------------------------------*/
305 static struct platform_device *sx1_devices[] __initdata = {
306         &sx1_flash_device,
307         &sx1_kp_device,
308 };
309
310 /*-----------------------------------------*/
311
312 static void __init omap_sx1_init(void)
313 {
314         /* mux pins for uarts */
315         omap_cfg_reg(UART1_TX);
316         omap_cfg_reg(UART1_RTS);
317         omap_cfg_reg(UART2_TX);
318         omap_cfg_reg(UART2_RTS);
319         omap_cfg_reg(UART3_TX);
320         omap_cfg_reg(UART3_RX);
321
322         platform_add_devices(sx1_devices, ARRAY_SIZE(sx1_devices));
323
324         omap_serial_init();
325         omap_register_i2c_bus(1, 100, NULL, 0);
326         omap1_usb_init(&sx1_usb_config);
327         sx1_mmc_init();
328
329         /* turn on USB power */
330         /* sx1_setusbpower(1); can't do it here because i2c is not ready */
331         gpio_request(1, "A_IRDA_OFF");
332         gpio_request(11, "A_SWITCH");
333         gpio_request(15, "A_USB_ON");
334         gpio_direction_output(1, 1);    /*A_IRDA_OFF = 1 */
335         gpio_direction_output(11, 0);   /*A_SWITCH = 0 */
336         gpio_direction_output(15, 0);   /*A_USB_ON = 0 */
337
338         omapfb_set_lcd_config(&sx1_lcd_config);
339 }
340
341 MACHINE_START(SX1, "OMAP310 based Siemens SX1")
342         .atag_offset    = 0x100,
343         .map_io         = omap15xx_map_io,
344         .init_early     = omap1_init_early,
345         .init_irq       = omap1_init_irq,
346         .handle_irq     = omap1_handle_irq,
347         .init_machine   = omap_sx1_init,
348         .init_late      = omap1_init_late,
349         .init_time      = omap1_timer_init,
350         .restart        = omap1_restart,
351 MACHINE_END