diff options
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-2430sdp.c | 103 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-3430sdp.c | 84 | ||||
-rw-r--r-- | arch/arm/mach-omap2/board-rx51-peripherals.c | 146 | ||||
-rw-r--r-- | arch/arm/mach-omap2/gpmc-smc91x.c | 189 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/mach/gpmc-smc91x.h | 42 |
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 | ||
62 | onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o | 62 | onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o |
63 | obj-y += $(onenand-m) $(onenand-y) | 63 | obj-y += $(onenand-m) $(onenand-y) |
64 | |||
65 | smc91x-$(CONFIG_SMC91X) := gpmc-smc91x.o | ||
66 | obj-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 | ||
48 | static struct mtd_partition sdp2430_partitions[] = { | 45 | static 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 | ||
102 | static 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 | |||
115 | static 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 | |||
122 | static struct platform_device *sdp2430_devices[] __initdata = { | 99 | static struct platform_device *sdp2430_devices[] __initdata = { |
123 | &sdp2430_smc91x_device, | ||
124 | &sdp2430_flash_device, | 100 | &sdp2430_flash_device, |
125 | }; | 101 | }; |
126 | 102 | ||
127 | static 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 */ | 105 | static 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) { | 113 | static 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 | ||
185 | out: | 125 | static inline void board_smc91x_init(void) |
186 | clk_disable(gpmc_fck); | 126 | { |
187 | clk_put(gpmc_fck); | ||
188 | } | 127 | } |
189 | 128 | ||
129 | #endif | ||
130 | |||
190 | static void __init omap_2430sdp_init_irq(void) | 131 | static 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 | ||
198 | static struct omap_uart_config sdp2430_uart_config __initdata = { | 138 | static 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 | ||
261 | static void __init omap_2430sdp_map_io(void) | 202 | static 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 | ||
59 | static 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 | |||
70 | static 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 | |||
77 | static int sdp3430_keymap[] = { | 56 | static 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 | ||
186 | static struct platform_device *sdp3430_devices[] __initdata = { | 165 | static struct platform_device *sdp3430_devices[] __initdata = { |
187 | &sdp3430_smc91x_device, | ||
188 | &sdp3430_lcd_device, | 166 | &sdp3430_lcd_device, |
189 | }; | 167 | }; |
190 | 168 | ||
191 | static 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 | |||
223 | static void __init omap_3430sdp_init_irq(void) | 169 | static 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 | ||
231 | static struct omap_uart_config sdp3430_uart_config __initdata = { | 176 | static 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 | |||
456 | static 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 | |||
462 | static 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 | |||
474 | static inline void board_smc91x_init(void) | ||
475 | { | ||
476 | } | ||
477 | |||
478 | #endif | ||
479 | |||
509 | static void __init omap_3430sdp_init(void) | 480 | static 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 | ||
527 | static void __init omap_3430sdp_map_io(void) | 499 | static 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 | |||
40 | static struct resource rx51_smc91x_resources[] = { | ||
41 | [0] = { | ||
42 | .flags = IORESOURCE_MEM, | ||
43 | }, | ||
44 | [1] = { | ||
45 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | static 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 | |||
56 | static int rx51_keymap[] = { | 35 | static 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 | ||
111 | static struct platform_device *rx51_peripherals_devices[] = { | ||
112 | &rx51_smc91x_device, | ||
113 | }; | ||
114 | |||
115 | /* | ||
116 | * Timings are taken from smsc-lan91c96-ms.pdf | ||
117 | */ | ||
118 | static 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 | |||
153 | static 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 | |||
193 | free3: | ||
194 | gpio_free(SMC91X_GPIO_PWRDWN); | ||
195 | free2: | ||
196 | gpio_free(SMC91X_GPIO_IRQ); | ||
197 | free1: | ||
198 | gpmc_cs_free(SMC91X_CS); | ||
199 | |||
200 | printk(KERN_ERR "Could not initialize smc91x\n"); | ||
201 | } | ||
202 | |||
203 | static struct twl4030_madc_platform_data rx51_madc_data = { | 90 | static 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 | |||
358 | static 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 | |||
366 | static 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 | |||
377 | static inline void board_smc91x_init(void) | ||
378 | { | ||
379 | } | ||
380 | |||
381 | #endif | ||
382 | |||
469 | void __init rx51_peripherals_init(void) | 383 | void __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 | |||
24 | static struct omap_smc91x_platform_data *gpmc_cfg; | ||
25 | |||
26 | static struct resource gpmc_smc91x_resources[] = { | ||
27 | [0] = { | ||
28 | .flags = IORESOURCE_MEM, | ||
29 | }, | ||
30 | [1] = { | ||
31 | .flags = IORESOURCE_IRQ, | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | static struct smc91x_platdata gpmc_smc91x_info = { | ||
36 | .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_0, | ||
37 | }; | ||
38 | |||
39 | static 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 | */ | ||
55 | static 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 | */ | ||
123 | void __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 | |||
180 | free3: | ||
181 | if (gpmc_cfg->gpio_pwrdwn) | ||
182 | gpio_free(gpmc_cfg->gpio_pwrdwn); | ||
183 | free2: | ||
184 | gpio_free(gpmc_cfg->gpio_irq); | ||
185 | free1: | ||
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 | |||
18 | struct 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 | |||
31 | extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d); | ||
32 | |||
33 | #else | ||
34 | |||
35 | #define board_smc91x_data NULL | ||
36 | |||
37 | static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d) | ||
38 | { | ||
39 | } | ||
40 | |||
41 | #endif | ||
42 | #endif | ||