aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2009-05-28 16:23:52 -0400
committerTony Lindgren <tony@atomide.com>2009-05-28 16:23:52 -0400
commit1a48e1575188d4023b3428b623caeefe8c599e79 (patch)
tree50bdac2821ab3c9f769c204cd15bc303f08d6670 /arch/arm/mach-omap2
parentaa62e90fe0700c037675926fff9f75b0b1c00d78 (diff)
ARM: OMAP2/3: Add generic smc91x support when connected to GPMC
Convert the board-rx51 smc91x code to be generic and make the boards to use it. This allows future recalculation of the timings when the source clock gets scaled. Also correct the rx51 interrupt to be IORESOURCE_IRQ_HIGHLEVEL. Thanks to Paul Walmsley <paul@pwsan.com> for better GPMC timing calculations. Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-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
5 files changed, 271 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}