aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/Makefile3
-rw-r--r--arch/arm/mach-omap2/board-2430sdp.c103
-rw-r--r--arch/arm/mach-omap2/board-3430sdp.c84
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c146
-rw-r--r--arch/arm/mach-omap2/gpmc-smc91x.c189
-rw-r--r--arch/arm/plat-omap/include/mach/gpmc-smc91x.h42
6 files changed, 313 insertions, 254 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 11f7f660879b..e4f6f61c40e7 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -61,3 +61,6 @@ endif
61 61
62onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o 62onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o
63obj-y += $(onenand-m) $(onenand-y) 63obj-y += $(onenand-m) $(onenand-y)
64
65smc91x-$(CONFIG_SMC91X) := gpmc-smc91x.o
66obj-y += $(smc91x-m) $(smc91x-y)
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 22143651037e..ef70b79942cd 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -36,14 +36,11 @@
36#include <mach/common.h> 36#include <mach/common.h>
37#include <mach/gpmc.h> 37#include <mach/gpmc.h>
38#include <mach/usb.h> 38#include <mach/usb.h>
39#include <mach/gpmc-smc91x.h>
39 40
40#include "mmc-twl4030.h" 41#include "mmc-twl4030.h"
41 42
42#define SDP2430_CS0_BASE 0x04000000 43#define SDP2430_CS0_BASE 0x04000000
43#define SDP2430_FLASH_CS 0
44#define SDP2430_SMC91X_CS 5
45
46#define SDP2430_ETHR_GPIO_IRQ 149
47 44
48static struct mtd_partition sdp2430_partitions[] = { 45static struct mtd_partition sdp2430_partitions[] = {
49 /* bootloader (U-Boot, etc) in first sector */ 46 /* bootloader (U-Boot, etc) in first sector */
@@ -99,100 +96,43 @@ static struct platform_device sdp2430_flash_device = {
99 .resource = &sdp2430_flash_resource, 96 .resource = &sdp2430_flash_resource,
100}; 97};
101 98
102static struct resource sdp2430_smc91x_resources[] = {
103 [0] = {
104 .start = SDP2430_CS0_BASE,
105 .end = SDP2430_CS0_BASE + SZ_64M - 1,
106 .flags = IORESOURCE_MEM,
107 },
108 [1] = {
109 .start = OMAP_GPIO_IRQ(SDP2430_ETHR_GPIO_IRQ),
110 .end = OMAP_GPIO_IRQ(SDP2430_ETHR_GPIO_IRQ),
111 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
112 },
113};
114
115static struct platform_device sdp2430_smc91x_device = {
116 .name = "smc91x",
117 .id = -1,
118 .num_resources = ARRAY_SIZE(sdp2430_smc91x_resources),
119 .resource = sdp2430_smc91x_resources,
120};
121
122static struct platform_device *sdp2430_devices[] __initdata = { 99static struct platform_device *sdp2430_devices[] __initdata = {
123 &sdp2430_smc91x_device,
124 &sdp2430_flash_device, 100 &sdp2430_flash_device,
125}; 101};
126 102
127static inline void __init sdp2430_init_smc91x(void) 103#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
128{
129 int eth_cs;
130 unsigned long cs_mem_base;
131 unsigned int rate;
132 struct clk *gpmc_fck;
133
134 eth_cs = SDP2430_SMC91X_CS;
135 104
136 gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */ 105static struct omap_smc91x_platform_data board_smc91x_data = {
137 if (IS_ERR(gpmc_fck)) { 106 .cs = 5,
138 WARN_ON(1); 107 .gpio_irq = 149,
139 return; 108 .flags = GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
140 } 109 IORESOURCE_IRQ_LOWLEVEL,
141 110
142 clk_enable(gpmc_fck); 111};
143 rate = clk_get_rate(gpmc_fck);
144
145 /* Make sure CS1 timings are correct, for 2430 always muxed */
146 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
147
148 if (rate >= 160000000) {
149 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
150 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
151 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
152 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
153 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
154 } else if (rate >= 130000000) {
155 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
156 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
157 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
158 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
159 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
160 } else { /* rate = 100000000 */
161 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
162 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
163 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
164 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
165 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
166 }
167 112
168 if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) { 113static void __init board_smc91x_init(void)
169 printk(KERN_ERR "Failed to request GPMC mem for smc91x\n"); 114{
170 goto out; 115 if (omap_rev() > OMAP3430_REV_ES1_0)
171 } 116 board_smc91x_data.gpio_irq = 6;
117 else
118 board_smc91x_data.gpio_irq = 29;
172 119
173 sdp2430_smc91x_resources[0].start = cs_mem_base + 0x300; 120 gpmc_smc91x_init(&board_smc91x_data);
174 sdp2430_smc91x_resources[0].end = cs_mem_base + 0x30f; 121}
175 udelay(100);
176 122
177 if (gpio_request(SDP2430_ETHR_GPIO_IRQ, "SMC91x irq") < 0) { 123#else
178 printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
179 SDP2430_ETHR_GPIO_IRQ);
180 gpmc_cs_free(eth_cs);
181 goto out;
182 }
183 gpio_direction_input(SDP2430_ETHR_GPIO_IRQ);
184 124
185out: 125static inline void board_smc91x_init(void)
186 clk_disable(gpmc_fck); 126{
187 clk_put(gpmc_fck);
188} 127}
189 128
129#endif
130
190static void __init omap_2430sdp_init_irq(void) 131static void __init omap_2430sdp_init_irq(void)
191{ 132{
192 omap2_init_common_hw(NULL); 133 omap2_init_common_hw(NULL);
193 omap_init_irq(); 134 omap_init_irq();
194 omap_gpio_init(); 135 omap_gpio_init();
195 sdp2430_init_smc91x();
196} 136}
197 137
198static struct omap_uart_config sdp2430_uart_config __initdata = { 138static struct omap_uart_config sdp2430_uart_config __initdata = {
@@ -256,6 +196,7 @@ static void __init omap_2430sdp_init(void)
256 omap_serial_init(); 196 omap_serial_init();
257 twl4030_mmc_init(mmc); 197 twl4030_mmc_init(mmc);
258 usb_musb_init(); 198 usb_musb_init();
199 board_smc91x_init();
259} 200}
260 201
261static void __init omap_2430sdp_map_io(void) 202static void __init omap_2430sdp_map_io(void)
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index ed9274972122..0e6369583958 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -39,15 +39,12 @@
39 39
40#include <mach/control.h> 40#include <mach/control.h>
41#include <mach/keypad.h> 41#include <mach/keypad.h>
42#include <mach/gpmc-smc91x.h>
42 43
43#include "mmc-twl4030.h" 44#include "mmc-twl4030.h"
44 45
45#define CONFIG_DISABLE_HFCLK 1 46#define CONFIG_DISABLE_HFCLK 1
46 47
47#define SDP3430_ETHR_GPIO_IRQ_SDPV1 29
48#define SDP3430_ETHR_GPIO_IRQ_SDPV2 6
49#define SDP3430_SMC91X_CS 3
50
51#define SDP3430_TS_GPIO_IRQ_SDPV1 3 48#define SDP3430_TS_GPIO_IRQ_SDPV1 3
52#define SDP3430_TS_GPIO_IRQ_SDPV2 2 49#define SDP3430_TS_GPIO_IRQ_SDPV2 2
53 50
@@ -56,24 +53,6 @@
56 53
57#define TWL4030_MSECURE_GPIO 22 54#define TWL4030_MSECURE_GPIO 22
58 55
59static struct resource sdp3430_smc91x_resources[] = {
60 [0] = {
61 .flags = IORESOURCE_MEM,
62 },
63 [1] = {
64 .start = 0,
65 .end = 0,
66 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
67 },
68};
69
70static struct platform_device sdp3430_smc91x_device = {
71 .name = "smc91x",
72 .id = -1,
73 .num_resources = ARRAY_SIZE(sdp3430_smc91x_resources),
74 .resource = sdp3430_smc91x_resources,
75};
76
77static int sdp3430_keymap[] = { 56static int sdp3430_keymap[] = {
78 KEY(0, 0, KEY_LEFT), 57 KEY(0, 0, KEY_LEFT),
79 KEY(0, 1, KEY_RIGHT), 58 KEY(0, 1, KEY_RIGHT),
@@ -184,48 +163,14 @@ static struct regulator_consumer_supply sdp3430_vdvi_supply = {
184}; 163};
185 164
186static struct platform_device *sdp3430_devices[] __initdata = { 165static struct platform_device *sdp3430_devices[] __initdata = {
187 &sdp3430_smc91x_device,
188 &sdp3430_lcd_device, 166 &sdp3430_lcd_device,
189}; 167};
190 168
191static inline void __init sdp3430_init_smc91x(void)
192{
193 int eth_cs;
194 unsigned long cs_mem_base;
195 int eth_gpio = 0;
196
197 eth_cs = SDP3430_SMC91X_CS;
198
199 if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
200 printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
201 return;
202 }
203
204 sdp3430_smc91x_resources[0].start = cs_mem_base + 0x300;
205 sdp3430_smc91x_resources[0].end = cs_mem_base + 0x30f;
206 udelay(100);
207
208 if (omap_rev() > OMAP3430_REV_ES1_0)
209 eth_gpio = SDP3430_ETHR_GPIO_IRQ_SDPV2;
210 else
211 eth_gpio = SDP3430_ETHR_GPIO_IRQ_SDPV1;
212
213 sdp3430_smc91x_resources[1].start = gpio_to_irq(eth_gpio);
214
215 if (gpio_request(eth_gpio, "SMC91x irq") < 0) {
216 printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
217 eth_gpio);
218 return;
219 }
220 gpio_direction_input(eth_gpio);
221}
222
223static void __init omap_3430sdp_init_irq(void) 169static void __init omap_3430sdp_init_irq(void)
224{ 170{
225 omap2_init_common_hw(NULL); 171 omap2_init_common_hw(NULL);
226 omap_init_irq(); 172 omap_init_irq();
227 omap_gpio_init(); 173 omap_gpio_init();
228 sdp3430_init_smc91x();
229} 174}
230 175
231static struct omap_uart_config sdp3430_uart_config __initdata = { 176static struct omap_uart_config sdp3430_uart_config __initdata = {
@@ -506,6 +451,32 @@ static int __init omap3430_i2c_init(void)
506 return 0; 451 return 0;
507} 452}
508 453
454#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
455
456static struct omap_smc91x_platform_data board_smc91x_data = {
457 .cs = 3,
458 .flags = GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
459 IORESOURCE_IRQ_LOWLEVEL,
460};
461
462static void __init board_smc91x_init(void)
463{
464 if (omap_rev() > OMAP3430_REV_ES1_0)
465 board_smc91x_data.gpio_irq = 6;
466 else
467 board_smc91x_data.gpio_irq = 29;
468
469 gpmc_smc91x_init(&board_smc91x_data);
470}
471
472#else
473
474static inline void board_smc91x_init(void)
475{
476}
477
478#endif
479
509static void __init omap_3430sdp_init(void) 480static void __init omap_3430sdp_init(void)
510{ 481{
511 omap3430_i2c_init(); 482 omap3430_i2c_init();
@@ -522,6 +493,7 @@ static void __init omap_3430sdp_init(void)
522 ads7846_dev_init(); 493 ads7846_dev_init();
523 omap_serial_init(); 494 omap_serial_init();
524 usb_musb_init(); 495 usb_musb_init();
496 board_smc91x_init();
525} 497}
526 498
527static void __init omap_3430sdp_map_io(void) 499static void __init omap_3430sdp_map_io(void)
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index ca18ae94185a..233c7454d84f 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -28,31 +28,10 @@
28#include <mach/gpmc.h> 28#include <mach/gpmc.h>
29#include <mach/keypad.h> 29#include <mach/keypad.h>
30#include <mach/onenand.h> 30#include <mach/onenand.h>
31#include <mach/gpmc-smc91x.h>
31 32
32#include "mmc-twl4030.h" 33#include "mmc-twl4030.h"
33 34
34
35#define SMC91X_CS 1
36#define SMC91X_GPIO_IRQ 54
37#define SMC91X_GPIO_RESET 164
38#define SMC91X_GPIO_PWRDWN 86
39
40static struct resource rx51_smc91x_resources[] = {
41 [0] = {
42 .flags = IORESOURCE_MEM,
43 },
44 [1] = {
45 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
46 },
47};
48
49static struct platform_device rx51_smc91x_device = {
50 .name = "smc91x",
51 .id = -1,
52 .num_resources = ARRAY_SIZE(rx51_smc91x_resources),
53 .resource = rx51_smc91x_resources,
54};
55
56static int rx51_keymap[] = { 35static int rx51_keymap[] = {
57 KEY(0, 0, KEY_Q), 36 KEY(0, 0, KEY_Q),
58 KEY(0, 1, KEY_W), 37 KEY(0, 1, KEY_W),
@@ -108,98 +87,6 @@ static struct twl4030_keypad_data rx51_kp_data = {
108 .rep = 1, 87 .rep = 1,
109}; 88};
110 89
111static struct platform_device *rx51_peripherals_devices[] = {
112 &rx51_smc91x_device,
113};
114
115/*
116 * Timings are taken from smsc-lan91c96-ms.pdf
117 */
118static int smc91x_init_gpmc(int cs)
119{
120 struct gpmc_timings t;
121 const int t2_r = 45; /* t2 in Figure 12.10 */
122 const int t2_w = 30; /* t2 in Figure 12.11 */
123 const int t3 = 15; /* t3 in Figure 12.10 */
124 const int t5_r = 0; /* t5 in Figure 12.10 */
125 const int t6_r = 45; /* t6 in Figure 12.10 */
126 const int t6_w = 0; /* t6 in Figure 12.11 */
127 const int t7_w = 15; /* t7 in Figure 12.11 */
128 const int t15 = 12; /* t15 in Figure 12.2 */
129 const int t20 = 185; /* t20 in Figure 12.2 */
130
131 memset(&t, 0, sizeof(t));
132
133 t.cs_on = t15;
134 t.cs_rd_off = t3 + t2_r + t5_r; /* Figure 12.10 */
135 t.cs_wr_off = t3 + t2_w + t6_w; /* Figure 12.11 */
136 t.adv_on = t3; /* Figure 12.10 */
137 t.adv_rd_off = t3 + t2_r; /* Figure 12.10 */
138 t.adv_wr_off = t3 + t2_w; /* Figure 12.11 */
139 t.oe_off = t3 + t2_r + t5_r; /* Figure 12.10 */
140 t.oe_on = t.oe_off - t6_r; /* Figure 12.10 */
141 t.we_off = t3 + t2_w + t6_w; /* Figure 12.11 */
142 t.we_on = t.we_off - t7_w; /* Figure 12.11 */
143 t.rd_cycle = t20; /* Figure 12.2 */
144 t.wr_cycle = t20; /* Figure 12.4 */
145 t.access = t3 + t2_r + t5_r; /* Figure 12.10 */
146 t.wr_access = t3 + t2_w + t6_w; /* Figure 12.11 */
147
148 gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_DEVICESIZE_16);
149
150 return gpmc_cs_set_timings(cs, &t);
151}
152
153static void __init rx51_init_smc91x(void)
154{
155 unsigned long cs_mem_base;
156 int ret;
157
158 omap_cfg_reg(U8_34XX_GPIO54_DOWN);
159 omap_cfg_reg(G25_34XX_GPIO86_OUT);
160 omap_cfg_reg(H19_34XX_GPIO164_OUT);
161
162 if (gpmc_cs_request(SMC91X_CS, SZ_16M, &cs_mem_base) < 0) {
163 printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
164 return;
165 }
166
167 rx51_smc91x_resources[0].start = cs_mem_base + 0x300;
168 rx51_smc91x_resources[0].end = cs_mem_base + 0x30f;
169
170 smc91x_init_gpmc(SMC91X_CS);
171
172 if (gpio_request(SMC91X_GPIO_IRQ, "SMC91X irq") < 0)
173 goto free1;
174
175 gpio_direction_input(SMC91X_GPIO_IRQ);
176 rx51_smc91x_resources[1].start = gpio_to_irq(SMC91X_GPIO_IRQ);
177
178 ret = gpio_request(SMC91X_GPIO_PWRDWN, "SMC91X powerdown");
179 if (ret)
180 goto free2;
181 gpio_direction_output(SMC91X_GPIO_PWRDWN, 0);
182
183 ret = gpio_request(SMC91X_GPIO_RESET, "SMC91X reset");
184 if (ret)
185 goto free3;
186 gpio_direction_output(SMC91X_GPIO_RESET, 0);
187 gpio_set_value(SMC91X_GPIO_RESET, 1);
188 msleep(100);
189 gpio_set_value(SMC91X_GPIO_RESET, 0);
190
191 return;
192
193free3:
194 gpio_free(SMC91X_GPIO_PWRDWN);
195free2:
196 gpio_free(SMC91X_GPIO_IRQ);
197free1:
198 gpmc_cs_free(SMC91X_CS);
199
200 printk(KERN_ERR "Could not initialize smc91x\n");
201}
202
203static struct twl4030_madc_platform_data rx51_madc_data = { 90static struct twl4030_madc_platform_data rx51_madc_data = {
204 .irq_line = 1, 91 .irq_line = 1,
205}; 92};
@@ -466,12 +353,37 @@ static inline void board_onenand_init(void)
466 353
467#endif 354#endif
468 355
356#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
357
358static struct omap_smc91x_platform_data board_smc91x_data = {
359 .cs = 1,
360 .gpio_irq = 54,
361 .gpio_pwrdwn = 86,
362 .gpio_reset = 164,
363 .flags = GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_HIGHLEVEL,
364};
365
366static void __init board_smc91x_init(void)
367{
368 omap_cfg_reg(U8_34XX_GPIO54_DOWN);
369 omap_cfg_reg(G25_34XX_GPIO86_OUT);
370 omap_cfg_reg(H19_34XX_GPIO164_OUT);
371
372 gpmc_smc91x_init(&board_smc91x_data);
373}
374
375#else
376
377static inline void board_smc91x_init(void)
378{
379}
380
381#endif
382
469void __init rx51_peripherals_init(void) 383void __init rx51_peripherals_init(void)
470{ 384{
471 platform_add_devices(rx51_peripherals_devices,
472 ARRAY_SIZE(rx51_peripherals_devices));
473 rx51_i2c_init(); 385 rx51_i2c_init();
474 rx51_init_smc91x();
475 board_onenand_init(); 386 board_onenand_init();
387 board_smc91x_init();
476} 388}
477 389
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
new file mode 100644
index 000000000000..df99d31d8b64
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc-smc91x.c
@@ -0,0 +1,189 @@
1/*
2 * linux/arch/arm/mach-omap2/gpmc-smc91x.c
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 * Contact: Tony Lindgren
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/platform_device.h>
14#include <linux/gpio.h>
15#include <linux/delay.h>
16#include <linux/interrupt.h>
17#include <linux/io.h>
18#include <linux/smc91x.h>
19
20#include <mach/board.h>
21#include <mach/gpmc.h>
22#include <mach/gpmc-smc91x.h>
23
24static struct omap_smc91x_platform_data *gpmc_cfg;
25
26static struct resource gpmc_smc91x_resources[] = {
27 [0] = {
28 .flags = IORESOURCE_MEM,
29 },
30 [1] = {
31 .flags = IORESOURCE_IRQ,
32 },
33};
34
35static struct smc91x_platdata gpmc_smc91x_info = {
36 .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_0,
37};
38
39static struct platform_device gpmc_smc91x_device = {
40 .name = "smc91x",
41 .id = -1,
42 .num_resources = ARRAY_SIZE(gpmc_smc91x_resources),
43 .resource = gpmc_smc91x_resources,
44 .dev = {
45 .platform_data = &gpmc_smc91x_info,
46 },
47};
48
49/*
50 * Set the gpmc timings for smc91c96. The timings are taken
51 * from the data sheet available at:
52 * http://www.smsc.com/main/catalog/lan91c96.html
53 * REVISIT: Level shifters can add at least to the access latency.
54 */
55static int smc91c96_gpmc_retime(void)
56{
57 struct gpmc_timings t;
58 const int t3 = 10; /* Figure 12.2 read and 12.4 write */
59 const int t4_r = 20; /* Figure 12.2 read */
60 const int t4_w = 5; /* Figure 12.4 write */
61 const int t5 = 25; /* Figure 12.2 read */
62 const int t6 = 15; /* Figure 12.2 read */
63 const int t7 = 5; /* Figure 12.4 write */
64 const int t8 = 5; /* Figure 12.4 write */
65 const int t20 = 185; /* Figure 12.2 read and 12.4 write */
66 u32 l;
67
68 memset(&t, 0, sizeof(t));
69
70 /* Read timings */
71 t.cs_on = 0;
72 t.adv_on = t.cs_on;
73 t.oe_on = t.adv_on + t3;
74 t.access = t.oe_on + t5;
75 t.oe_off = t.access;
76 t.adv_rd_off = t.oe_off + max(t4_r, t6);
77 t.cs_rd_off = t.oe_off;
78 t.rd_cycle = t20 - t.oe_on;
79
80 /* Write timings */
81 t.we_on = t.adv_on + t3;
82
83 if (cpu_is_omap34xx() && (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)) {
84 t.wr_data_mux_bus = t.we_on;
85 t.we_off = t.wr_data_mux_bus + t7;
86 } else
87 t.we_off = t.we_on + t7;
88 if (cpu_is_omap34xx())
89 t.wr_access = t.we_off;
90 t.adv_wr_off = t.we_off + max(t4_w, t8);
91 t.cs_wr_off = t.we_off + t4_w;
92 t.wr_cycle = t20 - t.we_on;
93
94 l = GPMC_CONFIG1_DEVICESIZE_16;
95 if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
96 l |= GPMC_CONFIG1_MUXADDDATA;
97 if (gpmc_cfg->flags & GPMC_READ_MON)
98 l |= GPMC_CONFIG1_WAIT_READ_MON;
99 if (gpmc_cfg->flags & GPMC_WRITE_MON)
100 l |= GPMC_CONFIG1_WAIT_WRITE_MON;
101 if (gpmc_cfg->wait_pin)
102 l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
103 gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
104
105 /*
106 * FIXME: Calculate the address and data bus muxed timings.
107 * Note that at least adv_rd_off needs to be changed according
108 * to omap3430 TRM Figure 11-11. Are the sdp boards using the
109 * FPGA in between smc91x and omap as the timings are different
110 * from above?
111 */
112 if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
113 return 0;
114
115 return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
116}
117
118/*
119 * Initialize smc91x device connected to the GPMC. Note that we
120 * assume that pin multiplexing is done in the board-*.c file,
121 * or in the bootloader.
122 */
123void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
124{
125 unsigned long cs_mem_base;
126 int ret;
127
128 gpmc_cfg = board_data;
129
130 if (gpmc_cfg->flags & GPMC_TIMINGS_SMC91C96)
131 gpmc_cfg->retime = smc91c96_gpmc_retime;
132
133 if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
134 printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
135 return;
136 }
137
138 gpmc_smc91x_resources[0].start = cs_mem_base + 0x300;
139 gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
140 gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
141
142 if (gpmc_cfg->retime) {
143 ret = gpmc_cfg->retime();
144 if (ret != 0)
145 goto free1;
146 }
147
148 if (gpio_request(gpmc_cfg->gpio_irq, "SMC91X irq") < 0)
149 goto free1;
150
151 gpio_direction_input(gpmc_cfg->gpio_irq);
152 gpmc_smc91x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
153
154 if (gpmc_cfg->gpio_pwrdwn) {
155 ret = gpio_request(gpmc_cfg->gpio_pwrdwn, "SMC91X powerdown");
156 if (ret)
157 goto free2;
158 gpio_direction_output(gpmc_cfg->gpio_pwrdwn, 0);
159 }
160
161 if (gpmc_cfg->gpio_reset) {
162 ret = gpio_request(gpmc_cfg->gpio_reset, "SMC91X reset");
163 if (ret)
164 goto free3;
165
166 gpio_direction_output(gpmc_cfg->gpio_reset, 0);
167 gpio_set_value(gpmc_cfg->gpio_reset, 1);
168 msleep(100);
169 gpio_set_value(gpmc_cfg->gpio_reset, 0);
170 }
171
172 if (platform_device_register(&gpmc_smc91x_device) < 0) {
173 printk(KERN_ERR "Unable to register smc91x device\n");
174 gpio_free(gpmc_cfg->gpio_reset);
175 goto free3;
176 }
177
178 return;
179
180free3:
181 if (gpmc_cfg->gpio_pwrdwn)
182 gpio_free(gpmc_cfg->gpio_pwrdwn);
183free2:
184 gpio_free(gpmc_cfg->gpio_irq);
185free1:
186 gpmc_cs_free(gpmc_cfg->cs);
187
188 printk(KERN_ERR "Could not initialize smc91x\n");
189}
diff --git a/arch/arm/plat-omap/include/mach/gpmc-smc91x.h b/arch/arm/plat-omap/include/mach/gpmc-smc91x.h
new file mode 100644
index 000000000000..b64fbee4d567
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/gpmc-smc91x.h
@@ -0,0 +1,42 @@
1/*
2 * arch/arm/plat-omap/include/mach/gpmc-smc91x.h
3 *
4 * Copyright (C) 2009 Nokia Corporation
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#ifndef __ASM_ARCH_OMAP_GPMC_SMC91X_H__
12
13#define GPMC_TIMINGS_SMC91C96 (1 << 4)
14#define GPMC_MUX_ADD_DATA (1 << 5) /* GPMC_CONFIG1_MUXADDDATA */
15#define GPMC_READ_MON (1 << 6) /* GPMC_CONFIG1_WAIT_READ_MON */
16#define GPMC_WRITE_MON (1 << 7) /* GPMC_CONFIG1_WAIT_WRITE_MON */
17
18struct omap_smc91x_platform_data {
19 int cs;
20 int gpio_irq;
21 int gpio_pwrdwn;
22 int gpio_reset;
23 int wait_pin; /* Optional GPMC_CONFIG1_WAITPINSELECT */
24 u32 flags;
25 int (*retime)(void);
26};
27
28#if defined(CONFIG_SMC91X) || \
29 defined(CONFIG_SMC91X_MODULE)
30
31extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
32
33#else
34
35#define board_smc91x_data NULL
36
37static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
38{
39}
40
41#endif
42#endif