diff options
author | Kevin Hilman <khilman@deeprootsystems.com> | 2009-04-29 20:44:58 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2009-05-26 10:18:15 -0400 |
commit | e38d92fdcd04c79d28679682f63a83487c4c4c05 (patch) | |
tree | b48a7614aca3793440cdd995d6eb5c25a8a9ba86 /arch/arm/mach-davinci/board-dm646x-evm.c | |
parent | 95a3477fe57e0669dcb531516f2930fe1cf27e6b (diff) |
davinci: DM646x: add base SoC and board support
Add support for DM646x SoC (a.k.a DaVinci HD) and its Evalution
Module (EVM.)
Original support done by Sudhakar Rajashekhara.
Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-davinci/board-dm646x-evm.c')
-rw-r--r-- | arch/arm/mach-davinci/board-dm646x-evm.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c new file mode 100644 index 000000000000..94cb623b1ec9 --- /dev/null +++ b/arch/arm/mach-davinci/board-dm646x-evm.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * TI DaVinci DM646X EVM board | ||
3 | * | ||
4 | * Derived from: arch/arm/mach-davinci/board-evm.c | ||
5 | * Copyright (C) 2006 Texas Instruments. | ||
6 | * | ||
7 | * (C) 2007-2008, MontaVista Software, Inc. | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public License | ||
10 | * version 2. This program is licensed "as is" without any warranty of any | ||
11 | * kind, whether express or implied. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | /************************************************************************** | ||
16 | * Included Files | ||
17 | **************************************************************************/ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/major.h> | ||
24 | #include <linux/root_dev.h> | ||
25 | #include <linux/dma-mapping.h> | ||
26 | #include <linux/serial.h> | ||
27 | #include <linux/serial_8250.h> | ||
28 | #include <linux/leds.h> | ||
29 | #include <linux/gpio.h> | ||
30 | #include <linux/io.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/i2c/at24.h> | ||
34 | #include <linux/i2c/pcf857x.h> | ||
35 | #include <linux/etherdevice.h> | ||
36 | |||
37 | #include <asm/setup.h> | ||
38 | #include <asm/mach-types.h> | ||
39 | #include <asm/mach/arch.h> | ||
40 | #include <asm/mach/map.h> | ||
41 | #include <asm/mach/flash.h> | ||
42 | |||
43 | #include <mach/dm646x.h> | ||
44 | #include <mach/common.h> | ||
45 | #include <mach/psc.h> | ||
46 | #include <mach/serial.h> | ||
47 | #include <mach/i2c.h> | ||
48 | |||
49 | static struct davinci_uart_config uart_config __initdata = { | ||
50 | .enabled_uarts = (1 << 0), | ||
51 | }; | ||
52 | |||
53 | /* LEDS */ | ||
54 | |||
55 | static struct gpio_led evm_leds[] = { | ||
56 | { .name = "DS1", .active_low = 1, }, | ||
57 | { .name = "DS2", .active_low = 1, }, | ||
58 | { .name = "DS3", .active_low = 1, }, | ||
59 | { .name = "DS4", .active_low = 1, }, | ||
60 | }; | ||
61 | |||
62 | static __initconst struct gpio_led_platform_data evm_led_data = { | ||
63 | .num_leds = ARRAY_SIZE(evm_leds), | ||
64 | .leds = evm_leds, | ||
65 | }; | ||
66 | |||
67 | static struct platform_device *evm_led_dev; | ||
68 | |||
69 | static int evm_led_setup(struct i2c_client *client, int gpio, | ||
70 | unsigned int ngpio, void *c) | ||
71 | { | ||
72 | struct gpio_led *leds = evm_leds; | ||
73 | int status; | ||
74 | |||
75 | while (ngpio--) { | ||
76 | leds->gpio = gpio++; | ||
77 | leds++; | ||
78 | }; | ||
79 | |||
80 | evm_led_dev = platform_device_alloc("leds-gpio", 0); | ||
81 | platform_device_add_data(evm_led_dev, &evm_led_data, | ||
82 | sizeof(evm_led_data)); | ||
83 | |||
84 | evm_led_dev->dev.parent = &client->dev; | ||
85 | status = platform_device_add(evm_led_dev); | ||
86 | if (status < 0) { | ||
87 | platform_device_put(evm_led_dev); | ||
88 | evm_led_dev = NULL; | ||
89 | } | ||
90 | return status; | ||
91 | } | ||
92 | |||
93 | static int evm_led_teardown(struct i2c_client *client, int gpio, | ||
94 | unsigned ngpio, void *c) | ||
95 | { | ||
96 | if (evm_led_dev) { | ||
97 | platform_device_unregister(evm_led_dev); | ||
98 | evm_led_dev = NULL; | ||
99 | } | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int evm_sw_gpio[4] = { -EINVAL, -EINVAL, -EINVAL, -EINVAL }; | ||
104 | |||
105 | static int evm_sw_setup(struct i2c_client *client, int gpio, | ||
106 | unsigned ngpio, void *c) | ||
107 | { | ||
108 | int status; | ||
109 | int i; | ||
110 | char label[10]; | ||
111 | |||
112 | for (i = 0; i < 4; ++i) { | ||
113 | snprintf(label, 10, "user_sw%d", i); | ||
114 | status = gpio_request(gpio, label); | ||
115 | if (status) | ||
116 | goto out_free; | ||
117 | evm_sw_gpio[i] = gpio++; | ||
118 | |||
119 | status = gpio_direction_input(evm_sw_gpio[i]); | ||
120 | if (status) { | ||
121 | gpio_free(evm_sw_gpio[i]); | ||
122 | evm_sw_gpio[i] = -EINVAL; | ||
123 | goto out_free; | ||
124 | } | ||
125 | |||
126 | status = gpio_export(evm_sw_gpio[i], 0); | ||
127 | if (status) { | ||
128 | gpio_free(evm_sw_gpio[i]); | ||
129 | evm_sw_gpio[i] = -EINVAL; | ||
130 | goto out_free; | ||
131 | } | ||
132 | } | ||
133 | return status; | ||
134 | out_free: | ||
135 | for (i = 0; i < 4; ++i) { | ||
136 | if (evm_sw_gpio[i] != -EINVAL) { | ||
137 | gpio_free(evm_sw_gpio[i]); | ||
138 | evm_sw_gpio[i] = -EINVAL; | ||
139 | } | ||
140 | } | ||
141 | return status; | ||
142 | } | ||
143 | |||
144 | static int evm_sw_teardown(struct i2c_client *client, int gpio, | ||
145 | unsigned ngpio, void *c) | ||
146 | { | ||
147 | int i; | ||
148 | |||
149 | for (i = 0; i < 4; ++i) { | ||
150 | if (evm_sw_gpio[i] != -EINVAL) { | ||
151 | gpio_unexport(evm_sw_gpio[i]); | ||
152 | gpio_free(evm_sw_gpio[i]); | ||
153 | evm_sw_gpio[i] = -EINVAL; | ||
154 | } | ||
155 | } | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int evm_pcf_setup(struct i2c_client *client, int gpio, | ||
160 | unsigned int ngpio, void *c) | ||
161 | { | ||
162 | int status; | ||
163 | |||
164 | if (ngpio < 8) | ||
165 | return -EINVAL; | ||
166 | |||
167 | status = evm_sw_setup(client, gpio, 4, c); | ||
168 | if (status) | ||
169 | return status; | ||
170 | |||
171 | return evm_led_setup(client, gpio+4, 4, c); | ||
172 | } | ||
173 | |||
174 | static int evm_pcf_teardown(struct i2c_client *client, int gpio, | ||
175 | unsigned int ngpio, void *c) | ||
176 | { | ||
177 | BUG_ON(ngpio < 8); | ||
178 | |||
179 | evm_sw_teardown(client, gpio, 4, c); | ||
180 | evm_led_teardown(client, gpio+4, 4, c); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static struct pcf857x_platform_data pcf_data = { | ||
186 | .gpio_base = DAVINCI_N_GPIO+1, | ||
187 | .setup = evm_pcf_setup, | ||
188 | .teardown = evm_pcf_teardown, | ||
189 | }; | ||
190 | |||
191 | /* Most of this EEPROM is unused, but U-Boot uses some data: | ||
192 | * - 0x7f00, 6 bytes Ethernet Address | ||
193 | * - ... newer boards may have more | ||
194 | */ | ||
195 | static struct memory_accessor *at24_mem_acc; | ||
196 | |||
197 | static void at24_setup(struct memory_accessor *mem_acc, void *context) | ||
198 | { | ||
199 | char mac_addr[6]; | ||
200 | |||
201 | at24_mem_acc = mem_acc; | ||
202 | |||
203 | /* Read MAC addr from EEPROM */ | ||
204 | if (at24_mem_acc->read(at24_mem_acc, mac_addr, 0x7f00, ETH_ALEN) == | ||
205 | ETH_ALEN) | ||
206 | pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr); | ||
207 | } | ||
208 | |||
209 | static struct at24_platform_data eeprom_info = { | ||
210 | .byte_len = (256*1024) / 8, | ||
211 | .page_size = 64, | ||
212 | .flags = AT24_FLAG_ADDR16, | ||
213 | .setup = at24_setup, | ||
214 | }; | ||
215 | |||
216 | int dm646xevm_eeprom_read(void *buf, off_t off, size_t count) | ||
217 | { | ||
218 | if (at24_mem_acc) | ||
219 | return at24_mem_acc->read(at24_mem_acc, buf, off, count); | ||
220 | return -ENODEV; | ||
221 | } | ||
222 | EXPORT_SYMBOL(dm646xevm_eeprom_read); | ||
223 | |||
224 | int dm646xevm_eeprom_write(void *buf, off_t off, size_t count) | ||
225 | { | ||
226 | if (at24_mem_acc) | ||
227 | return at24_mem_acc->write(at24_mem_acc, buf, off, count); | ||
228 | return -ENODEV; | ||
229 | } | ||
230 | EXPORT_SYMBOL(dm646xevm_eeprom_write); | ||
231 | |||
232 | static struct i2c_board_info __initdata i2c_info[] = { | ||
233 | { | ||
234 | I2C_BOARD_INFO("24c256", 0x50), | ||
235 | .platform_data = &eeprom_info, | ||
236 | }, | ||
237 | { | ||
238 | I2C_BOARD_INFO("pcf8574a", 0x38), | ||
239 | .platform_data = &pcf_data, | ||
240 | }, | ||
241 | }; | ||
242 | |||
243 | static struct davinci_i2c_platform_data i2c_pdata = { | ||
244 | .bus_freq = 100 /* kHz */, | ||
245 | .bus_delay = 0 /* usec */, | ||
246 | }; | ||
247 | |||
248 | static void __init evm_init_i2c(void) | ||
249 | { | ||
250 | davinci_init_i2c(&i2c_pdata); | ||
251 | i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info)); | ||
252 | } | ||
253 | |||
254 | static void __init davinci_map_io(void) | ||
255 | { | ||
256 | davinci_map_common_io(); | ||
257 | dm646x_init(); | ||
258 | } | ||
259 | |||
260 | static __init void evm_init(void) | ||
261 | { | ||
262 | evm_init_i2c(); | ||
263 | davinci_serial_init(&uart_config); | ||
264 | } | ||
265 | |||
266 | static __init void davinci_dm646x_evm_irq_init(void) | ||
267 | { | ||
268 | davinci_irq_init(); | ||
269 | } | ||
270 | |||
271 | MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM") | ||
272 | .phys_io = IO_PHYS, | ||
273 | .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, | ||
274 | .boot_params = (0x80000100), | ||
275 | .map_io = davinci_map_io, | ||
276 | .init_irq = davinci_dm646x_evm_irq_init, | ||
277 | .timer = &davinci_timer, | ||
278 | .init_machine = evm_init, | ||
279 | MACHINE_END | ||
280 | |||