refresh patch
[openwrt.git] / target / linux / coldfire / patches / 010-m5445x_fec.patch
1 From c562ab80fe383e6fa49dbe38257421cf37f0e4b3 Mon Sep 17 00:00:00 2001
2 From: Kurt Mahan <kmahan@freescale.com>
3 Date: Wed, 31 Oct 2007 17:07:25 -0600
4 Subject: [PATCH] MCF5445x FEC support.
5
6 LTIBName: m5445x-fec
7 Signed-off-by: Kurt Mahan <kmahan@freescale.com>
8 ---
9 drivers/net/Kconfig | 8 ++-
10 drivers/net/fec.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++----
11 drivers/net/fec.h | 2 +-
12 3 files changed, 198 insertions(+), 19 deletions(-)
13
14 --- a/drivers/net/Kconfig
15 +++ b/drivers/net/Kconfig
16 @@ -1973,7 +1973,7 @@ config 68360_ENET
17
18 config FEC
19 bool "FEC ethernet controller (of ColdFire CPUs)"
20 - depends on M523x || M527x || M5272 || M528x || M520x
21 + depends on M523x || M527x || M5272 || M528x || M520x || M54455
22 help
23 Say Y here if you want to use the built-in 10/100 Fast ethernet
24 controller on some Motorola ColdFire processors.
25 @@ -1985,6 +1985,12 @@ config FEC2
26 Say Y here if you want to use the second built-in 10/100 Fast
27 ethernet controller on some Motorola ColdFire processors.
28
29 +config FEC_SHARED_PHY
30 + bool "Shared PHY interface(on some ColdFire designs)"
31 + depends on FEC2
32 + help
33 + Say Y here if both PHYs are controlled via a single channel.
34 +
35 config FEC_MPC52xx
36 tristate "MPC52xx FEC driver"
37 depends on PPC_MERGE && PPC_MPC52xx && PPC_BESTCOMM_FEC
38 --- a/drivers/net/fec.c
39 +++ b/drivers/net/fec.c
40 @@ -51,7 +51,9 @@
41
42 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
43 defined(CONFIG_M5272) || defined(CONFIG_M528x) || \
44 - defined(CONFIG_M520x) || defined(CONFIG_M532x)
45 + defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
46 + defined(CONFIG_M54455)
47 +
48 #include <asm/coldfire.h>
49 #include <asm/mcfsim.h>
50 #include "fec.h"
51 @@ -82,6 +84,11 @@ static unsigned int fec_hw[] = {
52 (MCF_MBAR+0x30000),
53 #elif defined(CONFIG_M532x)
54 (MCF_MBAR+0xfc030000),
55 +#elif defined(CONFIG_M54455)
56 + (MCF_MBAR+0xfc030000),
57 +#if defined(CONFIG_FEC2)
58 + (MCF_MBAR+0xfc034000),
59 +#endif
60 #else
61 &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
62 #endif
63 @@ -172,7 +179,7 @@ typedef struct {
64 * account when setting it.
65 */
66 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
67 - defined(CONFIG_M520x) || defined(CONFIG_M532x)
68 + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_M54455)
69 #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
70 #else
71 #define OPT_FRAME_SIZE 0
72 @@ -213,6 +220,7 @@ struct fec_enet_private {
73 uint phy_speed;
74 phy_info_t const *phy;
75 struct work_struct phy_task;
76 + volatile fec_t *phy_hwp;
77
78 uint sequence_done;
79 uint mii_phy_task_queued;
80 @@ -349,7 +357,8 @@ fec_enet_start_xmit(struct sk_buff *skb,
81 if (bdp->cbd_bufaddr & 0x3) {
82 unsigned int index;
83 index = bdp - fep->tx_bd_base;
84 - memcpy(fep->tx_bounce[index], (void *) bdp->cbd_bufaddr, bdp->cbd_datlen);
85 + memcpy(fep->tx_bounce[index],
86 + (void *)skb->data, bdp->cbd_datlen);
87 bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
88 }
89
90 @@ -702,7 +711,7 @@ fec_enet_mii(struct net_device *dev)
91 uint mii_reg;
92
93 fep = netdev_priv(dev);
94 - ep = fep->hwp;
95 + ep = fep->phy_hwp;
96 mii_reg = ep->fec_mii_data;
97
98 spin_lock(&fep->lock);
99 @@ -753,7 +762,7 @@ mii_queue(struct net_device *dev, int re
100 mii_tail = mip;
101 } else {
102 mii_head = mii_tail = mip;
103 - fep->hwp->fec_mii_data = regval;
104 + fep->phy_hwp->fec_mii_data = regval;
105 }
106 } else {
107 retval = 1;
108 @@ -1151,8 +1160,7 @@ static phy_info_t const phy_info_ks8721b
109 };
110
111 /* ------------------------------------------------------------------------- */
112 -/* register definitions for the DP83848 */
113 -
114 +/* register definitions for the DP83848 and DP83849 */
115 #define MII_DP8384X_PHYSTST 16 /* PHY Status Register */
116
117 static void mii_parse_dp8384x_sr2(uint mii_reg, struct net_device *dev)
118 @@ -1186,27 +1194,50 @@ static void mii_parse_dp8384x_sr2(uint m
119 *s |= PHY_STAT_FAULT;
120 }
121
122 +static phy_cmd_t const phy_cmd_dp8384x_ack_int[] = {
123 + { mk_mii_end, }
124 + };
125 +
126 +static phy_cmd_t const phy_cmd_dp8384x_shutdown[] = {
127 + { mk_mii_end, }
128 + };
129 +
130 static phy_info_t phy_info_dp83848= {
131 - 0x020005c9,
132 - "DP83848",
133 + .id = 0x020005c9,
134 + .name = "DP83848",
135
136 - (const phy_cmd_t []) { /* config */
137 + .config = (const phy_cmd_t []) { /* config */
138 { mk_mii_read(MII_REG_CR), mii_parse_cr },
139 { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
140 { mk_mii_read(MII_DP8384X_PHYSTST), mii_parse_dp8384x_sr2 },
141 { mk_mii_end, }
142 },
143 - (const phy_cmd_t []) { /* startup - enable interrupts */
144 + .startup = (const phy_cmd_t []) { /* startup - enable interrupts */
145 { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
146 { mk_mii_read(MII_REG_SR), mii_parse_sr },
147 { mk_mii_end, }
148 },
149 - (const phy_cmd_t []) { /* ack_int - never happens, no interrupt */
150 + .ack_int = phy_cmd_dp8384x_ack_int,
151 + .shutdown = phy_cmd_dp8384x_shutdown,
152 +};
153 +
154 +static phy_info_t phy_info_dp83849 = {
155 + .id = 0x020005ca,
156 + .name = "DP83849",
157 +
158 + .config = (const phy_cmd_t []) { /* config */
159 + { mk_mii_read(MII_REG_CR), mii_parse_cr },
160 + { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
161 + { mk_mii_read(MII_DP8384X_PHYSTST), mii_parse_dp8384x_sr2 },
162 { mk_mii_end, }
163 },
164 - (const phy_cmd_t []) { /* shutdown */
165 + .startup = (const phy_cmd_t []) { /* startup - enable interrupts */
166 + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
167 + { mk_mii_read(MII_REG_SR), mii_parse_sr },
168 { mk_mii_end, }
169 },
170 + .ack_int = phy_cmd_dp8384x_ack_int,
171 + .shutdown = phy_cmd_dp8384x_shutdown,
172 };
173
174 /* ------------------------------------------------------------------------- */
175 @@ -1218,6 +1249,7 @@ static phy_info_t const * const phy_info
176 &phy_info_am79c874,
177 &phy_info_ks8721bl,
178 &phy_info_dp83848,
179 + &phy_info_dp83849,
180 NULL
181 };
182
183 @@ -1799,6 +1831,138 @@ static void __inline__ fec_uncache(unsig
184
185 /* ------------------------------------------------------------------------- */
186
187 +#elif defined(CONFIG_M54455)
188 +/*
189 + * Code specific for M54455
190 + */
191 +
192 +static void __inline__ fec_request_intrs(struct net_device *dev)
193 +{
194 + struct fec_enet_private *fep;
195 + int b;
196 + static const struct idesc {
197 + char *name;
198 + unsigned short irq;
199 + } *idp, id[] = {
200 + { "fec(TXF)", 36 },
201 + { "fec(TXB)", 37 },
202 + { "fec(TXFIFO)", 38 },
203 + { "fec(TXCR)", 39 },
204 + { "fec(RXF)", 40 },
205 + { "fec(RXB)", 41 },
206 + { "fec(MII)", 42 },
207 + { "fec(LC)", 43 },
208 + { "fec(HBERR)", 44 },
209 + { "fec(GRA)", 45 },
210 + { "fec(EBERR)", 46 },
211 + { "fec(BABT)", 47 },
212 + { "fec(BABR)", 48 },
213 + { NULL },
214 + };
215 +
216 + fep = netdev_priv(dev);
217 + b = (fep->index) ? 77 : 64;
218 +
219 + /* Setup interrupt handlers. */
220 + for (idp = id; idp->name; idp++) {
221 + if (request_irq(b+idp->irq, fec_enet_interrupt, 0,
222 + idp->name, dev) != 0)
223 + printk(KERN_ERR "FEC: Could not alloc %s IRQ(%d)!\n",
224 + idp->name, b+idp->irq);
225 + }
226 +
227 + if (fep->index) {
228 + /* Configure RMII */
229 + MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
230 + MCF_GPIO_PAR_FEC_FEC1_MASK) |
231 + MCF_GPIO_PAR_FEC_FEC1_RMII_GPIO;
232 + } else {
233 + /* Configure RMII */
234 + MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
235 + MCF_GPIO_PAR_FEC_FEC0_MASK) |
236 + MCF_GPIO_PAR_FEC_FEC0_RMII_GPIO;
237 + }
238 +
239 + /* Set up gpio outputs for MII lines on FEC0 */
240 + MCF_GPIO_PAR_FECI2C |= (0 |
241 + MCF_GPIO_PAR_FECI2C_MDIO0_MDIO0 |
242 + MCF_GPIO_PAR_FECI2C_MDC0_MDC0);
243 +}
244 +
245 +static void __inline__ fec_set_mii(struct net_device *dev,
246 + struct fec_enet_private *fep)
247 +{
248 + volatile fec_t *fecp;
249 +
250 + fecp = fep->hwp;
251 + fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;
252 + fecp->fec_x_cntrl = 0x00;
253 +
254 + /*
255 + * Set MII speed to 2.5 MHz
256 + */
257 + fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
258 + fecp->fec_mii_speed = fep->phy_speed;
259 +
260 + fec_restart(dev, 0);
261 +}
262 +
263 +static void __inline__ fec_get_mac(struct net_device *dev)
264 +{
265 + struct fec_enet_private *fep = netdev_priv(dev);
266 + volatile fec_t *fecp;
267 + unsigned char *iap, tmpaddr[ETH_ALEN];
268 +
269 + fecp = fep->hwp;
270 +
271 + if (FEC_FLASHMAC) {
272 + /*
273 + * Get MAC address from FLASH.
274 + * If it is all 1's or 0's, use the default.
275 + */
276 + iap = FEC_FLASHMAC;
277 + if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
278 + (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
279 + iap = fec_mac_default;
280 + if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) &&
281 + (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))
282 + iap = fec_mac_default;
283 + } else {
284 + *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low;
285 + *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16);
286 + iap = &tmpaddr[0];
287 + }
288 +
289 + memcpy(dev->dev_addr, iap, ETH_ALEN);
290 +
291 + /* Adjust MAC if using default MAC address */
292 + if (iap == fec_mac_default)
293 + dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] +
294 + fep->index;
295 +}
296 +
297 +static void __inline__ fec_enable_phy_intr(void)
298 +{
299 +}
300 +
301 +static void __inline__ fec_disable_phy_intr(void)
302 +{
303 +}
304 +
305 +static void __inline__ fec_phy_ack_intr(void)
306 +{
307 +}
308 +
309 +static void __inline__ fec_localhw_setup(void)
310 +{
311 +}
312 +
313 +static void __inline__ fec_uncache(unsigned long addr)
314 +{
315 +}
316 +
317 +/* ------------------------------------------------------------------------- */
318 +
319
320 #else
321
322 @@ -2305,7 +2469,7 @@ fec_set_mac_address(struct net_device *d
323
324 }
325
326 -/* Initialize the FEC Ethernet on 860T (or ColdFire 5272).
327 +/* Initialize the FEC Ethernet.
328 */
329 /*
330 * XXX: We need to clean up on failure exits here.
331 @@ -2326,7 +2490,7 @@ int __init fec_enet_init(struct net_devi
332
333 /* Allocate memory for buffer descriptors.
334 */
335 - mem_addr = __get_free_page(GFP_KERNEL);
336 + mem_addr = __get_free_page(GFP_DMA);
337 if (mem_addr == 0) {
338 printk("FEC: allocate descriptor memory failed?\n");
339 return -ENOMEM;
340 @@ -2339,6 +2503,11 @@ int __init fec_enet_init(struct net_devi
341 fep->index = index;
342 fep->hwp = fecp;
343 fep->netdev = dev;
344 +#ifdef CONFIG_FEC_SHARED_PHY
345 + fep->phy_hwp = (volatile fec_t *) fec_hw[index & ~1];
346 +#else
347 + fep->phy_hwp = fecp;
348 +#endif
349
350 /* Whack a reset. We should wait for this.
351 */
352 @@ -2375,7 +2544,7 @@ int __init fec_enet_init(struct net_devi
353
354 /* Allocate a page.
355 */
356 - mem_addr = __get_free_page(GFP_KERNEL);
357 + mem_addr = __get_free_page(GFP_DMA);
358 /* XXX: missing check for allocation failure */
359
360 fec_uncache(mem_addr);
361 @@ -2400,7 +2569,7 @@ int __init fec_enet_init(struct net_devi
362 bdp = fep->tx_bd_base;
363 for (i=0, j=FEC_ENET_TX_FRPPG; i<TX_RING_SIZE; i++) {
364 if (j >= FEC_ENET_TX_FRPPG) {
365 - mem_addr = __get_free_page(GFP_KERNEL);
366 + mem_addr = __get_free_page(GFP_DMA);
367 j = 1;
368 } else {
369 mem_addr += FEC_ENET_TX_FRSIZE;
370 @@ -2462,7 +2631,11 @@ int __init fec_enet_init(struct net_devi
371 * remainder of the interface.
372 */
373 fep->phy_id_done = 0;
374 +#ifndef CONFIG_FEC_SHARED_PHY
375 fep->phy_addr = 0;
376 +#else
377 + fep->phy_addr = fep->index;
378 +#endif
379 mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy);
380
381 index++;
382 --- a/drivers/net/fec.h
383 +++ b/drivers/net/fec.h
384 @@ -14,7 +14,7 @@
385 /****************************************************************************/
386
387 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
388 - defined(CONFIG_M520x) || defined(CONFIG_M532x)
389 + defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_M54455)
390 /*
391 * Just figures, Motorola would have to change the offsets for
392 * registers in the same peripheral device on different models
This page took 0.058732 seconds and 5 git commands to generate.