]>
Commit | Line | Data |
---|---|---|
aa44ef4d SK |
1 | /* |
2 | * Copyright (C) 2008-2009 ST-Ericsson | |
3 | * | |
4 | * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2, as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | */ | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/interrupt.h> | |
14 | #include <linux/platform_device.h> | |
15 | #include <linux/io.h> | |
b8410a15 | 16 | #include <linux/i2c.h> |
ea05a57f | 17 | #include <linux/gpio.h> |
aa44ef4d SK |
18 | #include <linux/amba/bus.h> |
19 | #include <linux/amba/pl022.h> | |
5d7b8467 | 20 | #include <linux/amba/serial.h> |
aa44ef4d | 21 | #include <linux/spi/spi.h> |
39ae702c | 22 | #include <linux/mfd/ab8500.h> |
79568b94 | 23 | #include <linux/regulator/ab8500.h> |
20406ebf | 24 | #include <linux/mfd/tc3589x.h> |
3ef374a2 | 25 | #include <linux/mfd/ab8500/gpio.h> |
dd7b2a05 | 26 | #include <linux/leds-lp5521.h> |
a71b819b PL |
27 | #include <linux/input.h> |
28 | #include <linux/gpio_keys.h> | |
aa44ef4d | 29 | |
aa44ef4d SK |
30 | #include <asm/mach-types.h> |
31 | #include <asm/mach/arch.h> | |
32 | ||
d48a41c1 | 33 | #include <plat/i2c.h> |
5d7b8467 | 34 | #include <plat/ste_dma40.h> |
aa44ef4d SK |
35 | |
36 | #include <mach/hardware.h> | |
37 | #include <mach/setup.h> | |
9e4e7fe1 | 38 | #include <mach/devices.h> |
29aeb3cf | 39 | #include <mach/irqs.h> |
aa44ef4d | 40 | |
5d7b8467 | 41 | #include "ste-dma40-db8500.h" |
fbf1eadf | 42 | #include "devices-db8500.h" |
008f8a2f | 43 | #include "board-mop500.h" |
a1e516e3 | 44 | #include "board-mop500-regulators.h" |
ea05a57f | 45 | |
3ef374a2 BB |
46 | static struct ab8500_gpio_platform_data ab8500_gpio_pdata = { |
47 | .gpio_base = MOP500_AB8500_GPIO(0), | |
48 | .irq_base = MOP500_AB8500_VIR_GPIO_IRQ_BASE, | |
49 | /* config_reg is the initial configuration of ab8500 pins. | |
50 | * The pins can be configured as GPIO or alt functions based | |
51 | * on value present in GpioSel1 to GpioSel6 and AlternatFunction | |
52 | * register. This is the array of 7 configuration settings. | |
53 | * One has to compile time decide these settings. Below is the | |
54 | * explaination of these setting | |
55 | * GpioSel1 = 0x00 => Pins GPIO1 to GPIO8 are not used as GPIO | |
56 | * GpioSel2 = 0x1E => Pins GPIO10 to GPIO13 are configured as GPIO | |
57 | * GpioSel3 = 0x80 => Pin GPIO24 is configured as GPIO | |
58 | * GpioSel4 = 0x01 => Pin GPIo25 is configured as GPIO | |
59 | * GpioSel5 = 0x7A => Pins GPIO34, GPIO36 to GPIO39 are conf as GPIO | |
60 | * GpioSel6 = 0x00 => Pins GPIO41 & GPIo42 are not configured as GPIO | |
61 | * AlternaFunction = 0x00 => If Pins GPIO10 to 13 are not configured | |
62 | * as GPIO then this register selectes the alternate fucntions | |
63 | */ | |
64 | .config_reg = {0x00, 0x1E, 0x80, 0x01, | |
65 | 0x7A, 0x00, 0x00}, | |
66 | }; | |
67 | ||
39ae702c RV |
68 | static struct ab8500_platform_data ab8500_platdata = { |
69 | .irq_base = MOP500_AB8500_IRQ_BASE, | |
dfa3a824 BJ |
70 | .regulator_reg_init = ab8500_regulator_reg_init, |
71 | .num_regulator_reg_init = ARRAY_SIZE(ab8500_regulator_reg_init), | |
a1e516e3 BJ |
72 | .regulator = ab8500_regulators, |
73 | .num_regulator = ARRAY_SIZE(ab8500_regulators), | |
3ef374a2 | 74 | .gpio = &ab8500_gpio_pdata, |
39ae702c RV |
75 | }; |
76 | ||
29aeb3cf LW |
77 | static struct resource ab8500_resources[] = { |
78 | [0] = { | |
22039b7c RV |
79 | .start = IRQ_DB8500_AB8500, |
80 | .end = IRQ_DB8500_AB8500, | |
81 | .flags = IORESOURCE_IRQ | |
29aeb3cf LW |
82 | } |
83 | }; | |
84 | ||
85 | struct platform_device ab8500_device = { | |
86 | .name = "ab8500-i2c", | |
87 | .id = 0, | |
88 | .dev = { | |
89 | .platform_data = &ab8500_platdata, | |
90 | }, | |
91 | .num_resources = 1, | |
92 | .resource = ab8500_resources, | |
93 | }; | |
94 | ||
b8410a15 RV |
95 | /* |
96 | * TC35892 | |
97 | */ | |
98 | ||
20406ebf | 99 | static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base) |
b8410a15 RV |
100 | { |
101 | mop500_sdi_tc35892_init(); | |
102 | } | |
103 | ||
20406ebf | 104 | static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = { |
b8410a15 RV |
105 | .gpio_base = MOP500_EGPIO(0), |
106 | .setup = mop500_tc35892_init, | |
107 | }; | |
108 | ||
20406ebf | 109 | static struct tc3589x_platform_data mop500_tc35892_data = { |
611b7590 | 110 | .block = TC3589x_BLOCK_GPIO, |
b8410a15 RV |
111 | .gpio = &mop500_tc35892_gpio_data, |
112 | .irq_base = MOP500_EGPIO_IRQ_BASE, | |
113 | }; | |
114 | ||
dd7b2a05 PL |
115 | static struct lp5521_led_config lp5521_pri_led[] = { |
116 | [0] = { | |
117 | .chan_nr = 0, | |
118 | .led_current = 0x2f, | |
119 | .max_current = 0x5f, | |
120 | }, | |
121 | [1] = { | |
122 | .chan_nr = 1, | |
123 | .led_current = 0x2f, | |
124 | .max_current = 0x5f, | |
125 | }, | |
126 | [2] = { | |
127 | .chan_nr = 2, | |
128 | .led_current = 0x2f, | |
129 | .max_current = 0x5f, | |
130 | }, | |
131 | }; | |
132 | ||
133 | static struct lp5521_platform_data __initdata lp5521_pri_data = { | |
134 | .label = "lp5521_pri", | |
135 | .led_config = &lp5521_pri_led[0], | |
136 | .num_channels = 3, | |
137 | .clock_mode = LP5521_CLOCK_EXT, | |
138 | }; | |
139 | ||
140 | static struct lp5521_led_config lp5521_sec_led[] = { | |
141 | [0] = { | |
142 | .chan_nr = 0, | |
143 | .led_current = 0x2f, | |
144 | .max_current = 0x5f, | |
145 | }, | |
146 | [1] = { | |
147 | .chan_nr = 1, | |
148 | .led_current = 0x2f, | |
149 | .max_current = 0x5f, | |
150 | }, | |
151 | [2] = { | |
152 | .chan_nr = 2, | |
153 | .led_current = 0x2f, | |
154 | .max_current = 0x5f, | |
155 | }, | |
156 | }; | |
157 | ||
158 | static struct lp5521_platform_data __initdata lp5521_sec_data = { | |
159 | .label = "lp5521_sec", | |
160 | .led_config = &lp5521_sec_led[0], | |
161 | .num_channels = 3, | |
162 | .clock_mode = LP5521_CLOCK_EXT, | |
163 | }; | |
164 | ||
b8410a15 RV |
165 | static struct i2c_board_info mop500_i2c0_devices[] = { |
166 | { | |
20406ebf | 167 | I2C_BOARD_INFO("tc3589x", 0x42), |
dd7b2a05 | 168 | .irq = NOMADIK_GPIO_TO_IRQ(217), |
b8410a15 RV |
169 | .platform_data = &mop500_tc35892_data, |
170 | }, | |
171 | }; | |
172 | ||
dd7b2a05 PL |
173 | static struct i2c_board_info __initdata mop500_i2c2_devices[] = { |
174 | { | |
175 | /* lp5521 LED driver, 1st device */ | |
176 | I2C_BOARD_INFO("lp5521", 0x33), | |
177 | .platform_data = &lp5521_pri_data, | |
178 | }, | |
179 | { | |
180 | /* lp5521 LED driver, 2st device */ | |
181 | I2C_BOARD_INFO("lp5521", 0x34), | |
182 | .platform_data = &lp5521_sec_data, | |
183 | }, | |
bb3b2187 LJ |
184 | { |
185 | /* Light sensor Rohm BH1780GLI */ | |
186 | I2C_BOARD_INFO("bh1780", 0x29), | |
187 | }, | |
dd7b2a05 PL |
188 | }; |
189 | ||
d48a41c1 | 190 | #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ |
f9faf237 | 191 | static struct nmk_i2c_controller u8500_i2c##id##_data = { \ |
d48a41c1 SK |
192 | /* \ |
193 | * slave data setup time, which is \ | |
194 | * 250 ns,100ns,10ns which is 14,6,2 \ | |
195 | * respectively for a 48 Mhz \ | |
196 | * i2c clock \ | |
197 | */ \ | |
198 | .slsu = _slsu, \ | |
199 | /* Tx FIFO threshold */ \ | |
200 | .tft = _tft, \ | |
201 | /* Rx FIFO threshold */ \ | |
202 | .rft = _rft, \ | |
203 | /* std. mode operation */ \ | |
204 | .clk_freq = clk, \ | |
205 | .sm = _sm, \ | |
206 | } | |
207 | ||
208 | /* | |
209 | * The board uses 4 i2c controllers, initialize all of | |
210 | * them with slave data setup time of 250 ns, | |
211 | * Tx & Rx FIFO threshold values as 1 and standard | |
212 | * mode of operation | |
213 | */ | |
214 | U8500_I2C_CONTROLLER(0, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); | |
215 | U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); | |
216 | U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); | |
217 | U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); | |
218 | ||
fbf1eadf RV |
219 | static void __init mop500_i2c_init(void) |
220 | { | |
221 | db8500_add_i2c0(&u8500_i2c0_data); | |
222 | db8500_add_i2c1(&u8500_i2c1_data); | |
223 | db8500_add_i2c2(&u8500_i2c2_data); | |
224 | db8500_add_i2c3(&u8500_i2c3_data); | |
225 | } | |
aa44ef4d | 226 | |
a71b819b PL |
227 | static struct gpio_keys_button mop500_gpio_keys[] = { |
228 | { | |
229 | .desc = "SFH7741 Proximity Sensor", | |
230 | .type = EV_SW, | |
231 | .code = SW_FRONT_PROXIMITY, | |
a71b819b PL |
232 | .active_low = 0, |
233 | .can_disable = 1, | |
234 | } | |
235 | }; | |
236 | ||
237 | static struct regulator *prox_regulator; | |
238 | static int mop500_prox_activate(struct device *dev); | |
239 | static void mop500_prox_deactivate(struct device *dev); | |
240 | ||
241 | static struct gpio_keys_platform_data mop500_gpio_keys_data = { | |
242 | .buttons = mop500_gpio_keys, | |
243 | .nbuttons = ARRAY_SIZE(mop500_gpio_keys), | |
244 | .enable = mop500_prox_activate, | |
245 | .disable = mop500_prox_deactivate, | |
246 | }; | |
247 | ||
248 | static struct platform_device mop500_gpio_keys_device = { | |
249 | .name = "gpio-keys", | |
250 | .id = 0, | |
251 | .dev = { | |
252 | .platform_data = &mop500_gpio_keys_data, | |
253 | }, | |
254 | }; | |
255 | ||
256 | static int mop500_prox_activate(struct device *dev) | |
257 | { | |
258 | prox_regulator = regulator_get(&mop500_gpio_keys_device.dev, | |
259 | "vcc"); | |
260 | if (IS_ERR(prox_regulator)) { | |
261 | dev_err(&mop500_gpio_keys_device.dev, | |
262 | "no regulator\n"); | |
263 | return PTR_ERR(prox_regulator); | |
264 | } | |
265 | regulator_enable(prox_regulator); | |
266 | return 0; | |
267 | } | |
268 | ||
269 | static void mop500_prox_deactivate(struct device *dev) | |
270 | { | |
271 | regulator_disable(prox_regulator); | |
272 | regulator_put(prox_regulator); | |
273 | } | |
274 | ||
d48a41c1 SK |
275 | /* add any platform devices here - TODO */ |
276 | static struct platform_device *platform_devs[] __initdata = { | |
a71b819b | 277 | &mop500_gpio_keys_device, |
d48a41c1 SK |
278 | }; |
279 | ||
5d7b8467 LW |
280 | #ifdef CONFIG_STE_DMA40 |
281 | static struct stedma40_chan_cfg ssp0_dma_cfg_rx = { | |
282 | .mode = STEDMA40_MODE_LOGICAL, | |
283 | .dir = STEDMA40_PERIPH_TO_MEM, | |
284 | .src_dev_type = DB8500_DMA_DEV8_SSP0_RX, | |
285 | .dst_dev_type = STEDMA40_DEV_DST_MEMORY, | |
286 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | |
287 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | |
288 | }; | |
289 | ||
290 | static struct stedma40_chan_cfg ssp0_dma_cfg_tx = { | |
291 | .mode = STEDMA40_MODE_LOGICAL, | |
292 | .dir = STEDMA40_MEM_TO_PERIPH, | |
293 | .src_dev_type = STEDMA40_DEV_SRC_MEMORY, | |
294 | .dst_dev_type = DB8500_DMA_DEV8_SSP0_TX, | |
295 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | |
296 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | |
297 | }; | |
298 | #endif | |
299 | ||
300 | static struct pl022_ssp_controller ssp0_platform_data = { | |
301 | .bus_id = 0, | |
302 | #ifdef CONFIG_STE_DMA40 | |
303 | .enable_dma = 1, | |
304 | .dma_filter = stedma40_filter, | |
305 | .dma_rx_param = &ssp0_dma_cfg_rx, | |
306 | .dma_tx_param = &ssp0_dma_cfg_tx, | |
307 | #else | |
308 | .enable_dma = 0, | |
309 | #endif | |
310 | /* on this platform, gpio 31,142,144,214 & | |
311 | * 224 are connected as chip selects | |
312 | */ | |
313 | .num_chipselect = 5, | |
314 | }; | |
315 | ||
fbf1eadf | 316 | static void __init mop500_spi_init(void) |
aa44ef4d | 317 | { |
fbf1eadf RV |
318 | db8500_add_ssp0(&ssp0_platform_data); |
319 | } | |
aa44ef4d | 320 | |
5d7b8467 LW |
321 | #ifdef CONFIG_STE_DMA40 |
322 | static struct stedma40_chan_cfg uart0_dma_cfg_rx = { | |
323 | .mode = STEDMA40_MODE_LOGICAL, | |
324 | .dir = STEDMA40_PERIPH_TO_MEM, | |
325 | .src_dev_type = DB8500_DMA_DEV13_UART0_RX, | |
326 | .dst_dev_type = STEDMA40_DEV_DST_MEMORY, | |
327 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | |
328 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | |
329 | }; | |
330 | ||
331 | static struct stedma40_chan_cfg uart0_dma_cfg_tx = { | |
332 | .mode = STEDMA40_MODE_LOGICAL, | |
333 | .dir = STEDMA40_MEM_TO_PERIPH, | |
334 | .src_dev_type = STEDMA40_DEV_SRC_MEMORY, | |
335 | .dst_dev_type = DB8500_DMA_DEV13_UART0_TX, | |
336 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | |
337 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | |
338 | }; | |
339 | ||
340 | static struct stedma40_chan_cfg uart1_dma_cfg_rx = { | |
341 | .mode = STEDMA40_MODE_LOGICAL, | |
342 | .dir = STEDMA40_PERIPH_TO_MEM, | |
343 | .src_dev_type = DB8500_DMA_DEV12_UART1_RX, | |
344 | .dst_dev_type = STEDMA40_DEV_DST_MEMORY, | |
345 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | |
346 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | |
347 | }; | |
348 | ||
349 | static struct stedma40_chan_cfg uart1_dma_cfg_tx = { | |
350 | .mode = STEDMA40_MODE_LOGICAL, | |
351 | .dir = STEDMA40_MEM_TO_PERIPH, | |
352 | .src_dev_type = STEDMA40_DEV_SRC_MEMORY, | |
353 | .dst_dev_type = DB8500_DMA_DEV12_UART1_TX, | |
354 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | |
355 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | |
356 | }; | |
357 | ||
358 | static struct stedma40_chan_cfg uart2_dma_cfg_rx = { | |
359 | .mode = STEDMA40_MODE_LOGICAL, | |
360 | .dir = STEDMA40_PERIPH_TO_MEM, | |
361 | .src_dev_type = DB8500_DMA_DEV11_UART2_RX, | |
362 | .dst_dev_type = STEDMA40_DEV_DST_MEMORY, | |
363 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | |
364 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | |
365 | }; | |
366 | ||
367 | static struct stedma40_chan_cfg uart2_dma_cfg_tx = { | |
368 | .mode = STEDMA40_MODE_LOGICAL, | |
369 | .dir = STEDMA40_MEM_TO_PERIPH, | |
370 | .src_dev_type = STEDMA40_DEV_SRC_MEMORY, | |
371 | .dst_dev_type = DB8500_DMA_DEV11_UART2_TX, | |
372 | .src_info.data_width = STEDMA40_BYTE_WIDTH, | |
373 | .dst_info.data_width = STEDMA40_BYTE_WIDTH, | |
374 | }; | |
375 | #endif | |
376 | ||
377 | static struct amba_pl011_data uart0_plat = { | |
378 | #ifdef CONFIG_STE_DMA40 | |
379 | .dma_filter = stedma40_filter, | |
380 | .dma_rx_param = &uart0_dma_cfg_rx, | |
381 | .dma_tx_param = &uart0_dma_cfg_tx, | |
382 | #endif | |
383 | }; | |
384 | ||
385 | static struct amba_pl011_data uart1_plat = { | |
386 | #ifdef CONFIG_STE_DMA40 | |
387 | .dma_filter = stedma40_filter, | |
388 | .dma_rx_param = &uart1_dma_cfg_rx, | |
389 | .dma_tx_param = &uart1_dma_cfg_tx, | |
390 | #endif | |
391 | }; | |
392 | ||
393 | static struct amba_pl011_data uart2_plat = { | |
394 | #ifdef CONFIG_STE_DMA40 | |
395 | .dma_filter = stedma40_filter, | |
396 | .dma_rx_param = &uart2_dma_cfg_rx, | |
397 | .dma_tx_param = &uart2_dma_cfg_tx, | |
398 | #endif | |
399 | }; | |
400 | ||
fbf1eadf RV |
401 | static void __init mop500_uart_init(void) |
402 | { | |
5d7b8467 LW |
403 | db8500_add_uart0(&uart0_plat); |
404 | db8500_add_uart1(&uart1_plat); | |
405 | db8500_add_uart2(&uart2_plat); | |
fbf1eadf RV |
406 | } |
407 | ||
4b4f757c | 408 | static void __init mop500_init_machine(void) |
fbf1eadf | 409 | { |
4b4f757c LW |
410 | /* |
411 | * The HREFv60 board removed a GPIO expander and routed | |
412 | * all these GPIO pins to the internal GPIO controller | |
413 | * instead. | |
414 | */ | |
415 | if (machine_is_hrefv60()) | |
416 | mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; | |
417 | else | |
418 | mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; | |
419 | ||
ea05a57f RV |
420 | u8500_init_devices(); |
421 | ||
fe05203b | 422 | mop500_pins_init(); |
ea05a57f | 423 | |
d48a41c1 SK |
424 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); |
425 | ||
fbf1eadf | 426 | mop500_i2c_init(); |
008f8a2f | 427 | mop500_sdi_init(); |
fbf1eadf RV |
428 | mop500_spi_init(); |
429 | mop500_uart_init(); | |
008f8a2f | 430 | |
d5d22815 | 431 | platform_device_register(&ab8500_device); |
b8410a15 RV |
432 | |
433 | i2c_register_board_info(0, mop500_i2c0_devices, | |
434 | ARRAY_SIZE(mop500_i2c0_devices)); | |
dd7b2a05 PL |
435 | i2c_register_board_info(2, mop500_i2c2_devices, |
436 | ARRAY_SIZE(mop500_i2c2_devices)); | |
aa44ef4d SK |
437 | } |
438 | ||
439 | MACHINE_START(U8500, "ST-Ericsson MOP500 platform") | |
440 | /* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */ | |
aa44ef4d SK |
441 | .boot_params = 0x100, |
442 | .map_io = u8500_map_io, | |
178980f9 | 443 | .init_irq = ux500_init_irq, |
aa44ef4d | 444 | /* we re-use nomadik timer here */ |
41ac329f | 445 | .timer = &ux500_timer, |
4b4f757c LW |
446 | .init_machine = mop500_init_machine, |
447 | MACHINE_END | |
448 | ||
449 | MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+") | |
450 | .boot_params = 0x100, | |
451 | .map_io = u8500_map_io, | |
452 | .init_irq = ux500_init_irq, | |
453 | .timer = &ux500_timer, | |
454 | .init_machine = mop500_init_machine, | |
aa44ef4d | 455 | MACHINE_END |