]>
git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/net/pic32_eth.c
2 * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
4 * SPDX-License-Identifier: GPL-2.0+
16 #include "pic32_eth.h"
18 #define MAX_RX_BUF_SIZE 1536
19 #define MAX_RX_DESCR PKTBUFSRX
20 #define MAX_TX_DESCR 2
22 DECLARE_GLOBAL_DATA_PTR
;
25 struct eth_dma_desc rxd_ring
[MAX_RX_DESCR
];
26 struct eth_dma_desc txd_ring
[MAX_TX_DESCR
];
27 u32 rxd_idx
; /* index of RX desc to read */
29 struct pic32_ectl_regs
*ectl_regs
;
30 struct pic32_emac_regs
*emac_regs
;
32 struct phy_device
*phydev
;
33 phy_interface_t phyif
;
35 struct gpio_desc rst_gpio
;
38 void __weak
board_netphy_reset(void *dev
)
40 struct pic32eth_dev
*priv
= dev
;
42 if (!dm_gpio_is_valid(&priv
->rst_gpio
))
46 dm_gpio_set_value(&priv
->rst_gpio
, 0);
48 dm_gpio_set_value(&priv
->rst_gpio
, 1);
52 /* Initialize mii(MDIO) interface, discover which PHY is
53 * attached to the device, and configure it properly.
55 static int pic32_mii_init(struct pic32eth_dev
*priv
)
57 struct pic32_ectl_regs
*ectl_p
= priv
->ectl_regs
;
58 struct pic32_emac_regs
*emac_p
= priv
->emac_regs
;
61 board_netphy_reset(priv
);
63 /* disable RX, TX & all transactions */
64 writel(ETHCON_ON
| ETHCON_TXRTS
| ETHCON_RXEN
, &ectl_p
->con1
.clr
);
67 wait_for_bit(__func__
, &ectl_p
->stat
.raw
, ETHSTAT_BUSY
, false,
68 CONFIG_SYS_HZ
, false);
70 /* turn controller ON to access PHY over MII */
71 writel(ETHCON_ON
, &ectl_p
->con1
.set
);
76 writel(EMAC_SOFTRESET
, &emac_p
->cfg1
.set
); /* reset assert */
78 writel(EMAC_SOFTRESET
, &emac_p
->cfg1
.clr
); /* reset deassert */
80 /* initialize MDIO/MII */
81 if (priv
->phyif
== PHY_INTERFACE_MODE_RMII
) {
82 writel(EMAC_RMII_RESET
, &emac_p
->supp
.set
);
84 writel(EMAC_RMII_RESET
, &emac_p
->supp
.clr
);
87 return pic32_mdio_init(PIC32_MDIO_NAME
, (ulong
)&emac_p
->mii
);
90 static int pic32_phy_init(struct pic32eth_dev
*priv
, struct udevice
*dev
)
94 mii
= miiphy_get_dev_by_name(PIC32_MDIO_NAME
);
96 /* find & connect PHY */
97 priv
->phydev
= phy_connect(mii
, priv
->phy_addr
,
100 printf("%s: %s: Error, PHY connect\n", __FILE__
, __func__
);
104 /* Wait for phy to complete reset */
107 /* configure supported modes */
108 priv
->phydev
->supported
= SUPPORTED_10baseT_Half
|
109 SUPPORTED_10baseT_Full
|
110 SUPPORTED_100baseT_Half
|
111 SUPPORTED_100baseT_Full
|
114 priv
->phydev
->advertising
= ADVERTISED_10baseT_Half
|
115 ADVERTISED_10baseT_Full
|
116 ADVERTISED_100baseT_Half
|
117 ADVERTISED_100baseT_Full
|
120 priv
->phydev
->autoneg
= AUTONEG_ENABLE
;
125 /* Configure MAC based on negotiated speed and duplex
128 static int pic32_mac_adjust_link(struct pic32eth_dev
*priv
)
130 struct phy_device
*phydev
= priv
->phydev
;
131 struct pic32_emac_regs
*emac_p
= priv
->emac_regs
;
134 printf("%s: No link.\n", phydev
->dev
->name
);
138 if (phydev
->duplex
) {
139 writel(EMAC_FULLDUP
, &emac_p
->cfg2
.set
);
140 writel(FULLDUP_GAP_TIME
, &emac_p
->ipgt
.raw
);
142 writel(EMAC_FULLDUP
, &emac_p
->cfg2
.clr
);
143 writel(HALFDUP_GAP_TIME
, &emac_p
->ipgt
.raw
);
146 switch (phydev
->speed
) {
148 writel(EMAC_RMII_SPD100
, &emac_p
->supp
.set
);
151 writel(EMAC_RMII_SPD100
, &emac_p
->supp
.clr
);
154 printf("%s: Speed was bad\n", phydev
->dev
->name
);
158 printf("pic32eth: PHY is %s with %dbase%s, %s\n",
159 phydev
->drv
->name
, phydev
->speed
,
160 (phydev
->port
== PORT_TP
) ? "T" : "X",
161 (phydev
->duplex
) ? "full" : "half");
166 static void pic32_mac_init(struct pic32eth_dev
*priv
, u8
*macaddr
)
168 struct pic32_emac_regs
*emac_p
= priv
->emac_regs
;
172 v
= EMAC_TXPAUSE
| EMAC_RXPAUSE
| EMAC_RXENABLE
;
173 writel(v
, &emac_p
->cfg1
.raw
);
175 v
= EMAC_EXCESS
| EMAC_AUTOPAD
| EMAC_PADENABLE
|
176 EMAC_CRCENABLE
| EMAC_LENGTHCK
| EMAC_FULLDUP
;
177 writel(v
, &emac_p
->cfg2
.raw
);
179 /* recommended back-to-back inter-packet gap for 10 Mbps half duplex */
180 writel(HALFDUP_GAP_TIME
, &emac_p
->ipgt
.raw
);
182 /* recommended non-back-to-back interpacket gap is 0xc12 */
183 writel(0xc12, &emac_p
->ipgr
.raw
);
185 /* recommended collision window retry limit is 0x370F */
186 writel(0x370f, &emac_p
->clrt
.raw
);
188 /* set maximum frame length: allow VLAN tagged frame */
189 writel(0x600, &emac_p
->maxf
.raw
);
191 /* set the mac address */
192 writel(macaddr
[0] | (macaddr
[1] << 8), &emac_p
->sa2
.raw
);
193 writel(macaddr
[2] | (macaddr
[3] << 8), &emac_p
->sa1
.raw
);
194 writel(macaddr
[4] | (macaddr
[5] << 8), &emac_p
->sa0
.raw
);
196 /* default, enable 10 Mbps operation */
197 writel(EMAC_RMII_SPD100
, &emac_p
->supp
.clr
);
199 /* wait until link status UP or deadline elapsed */
200 expire
= get_ticks() + get_tbclk() * 2;
201 for (; get_ticks() < expire
;) {
202 stat
= phy_read(priv
->phydev
, priv
->phy_addr
, MII_BMSR
);
203 if (stat
& BMSR_LSTATUS
)
207 if (!(stat
& BMSR_LSTATUS
))
208 printf("MAC: Link is DOWN!\n");
210 /* delay to stabilize before any tx/rx */
214 static void pic32_mac_reset(struct pic32eth_dev
*priv
)
216 struct pic32_emac_regs
*emac_p
= priv
->emac_regs
;
220 writel(EMAC_SOFTRESET
, &emac_p
->cfg1
.raw
);
224 writel(0, &emac_p
->cfg1
.raw
);
227 mii
= priv
->phydev
->bus
;
228 if (mii
&& mii
->reset
)
232 /* initializes the MAC and PHY, then establishes a link */
233 static void pic32_ctrl_reset(struct pic32eth_dev
*priv
)
235 struct pic32_ectl_regs
*ectl_p
= priv
->ectl_regs
;
238 /* disable RX, TX & any other transactions */
239 writel(ETHCON_ON
| ETHCON_TXRTS
| ETHCON_RXEN
, &ectl_p
->con1
.clr
);
242 wait_for_bit(__func__
, &ectl_p
->stat
.raw
, ETHSTAT_BUSY
, false,
243 CONFIG_SYS_HZ
, false);
244 /* decrement received buffcnt to zero. */
245 while (readl(&ectl_p
->stat
.raw
) & ETHSTAT_BUFCNT
)
246 writel(ETHCON_BUFCDEC
, &ectl_p
->con1
.set
);
248 /* clear any existing interrupt event */
249 writel(0xffffffff, &ectl_p
->irq
.clr
);
251 /* clear RX/TX start address */
252 writel(0xffffffff, &ectl_p
->txst
.clr
);
253 writel(0xffffffff, &ectl_p
->rxst
.clr
);
255 /* clear the receive filters */
256 writel(0x00ff, &ectl_p
->rxfc
.clr
);
258 /* set the receive filters
259 * ETH_FILT_CRC_ERR_REJECT
260 * ETH_FILT_RUNT_REJECT
261 * ETH_FILT_UCAST_ACCEPT
262 * ETH_FILT_MCAST_ACCEPT
263 * ETH_FILT_BCAST_ACCEPT
265 v
= ETHRXFC_BCEN
| ETHRXFC_MCEN
| ETHRXFC_UCEN
|
266 ETHRXFC_RUNTEN
| ETHRXFC_CRCOKEN
;
267 writel(v
, &ectl_p
->rxfc
.set
);
269 /* turn controller ON to access PHY over MII */
270 writel(ETHCON_ON
, &ectl_p
->con1
.set
);
273 static void pic32_rx_desc_init(struct pic32eth_dev
*priv
)
275 struct pic32_ectl_regs
*ectl_p
= priv
->ectl_regs
;
276 struct eth_dma_desc
*rxd
;
280 for (idx
= 0; idx
< MAX_RX_DESCR
; idx
++) {
281 rxd
= &priv
->rxd_ring
[idx
];
284 rxd
->hdr
= EDH_NPV
| EDH_EOWN
| EDH_STICKY
;
286 /* packet buffer address */
287 rxd
->data_buff
= virt_to_phys(net_rx_packets
[idx
]);
289 /* link to next desc */
290 rxd
->next_ed
= virt_to_phys(rxd
+ 1);
296 /* decrement bufcnt */
297 writel(ETHCON_BUFCDEC
, &ectl_p
->con1
.set
);
300 /* link last descr to beginning of list */
301 rxd
->next_ed
= virt_to_phys(&priv
->rxd_ring
[0]);
304 flush_dcache_range((ulong
)priv
->rxd_ring
,
305 (ulong
)priv
->rxd_ring
+ sizeof(priv
->rxd_ring
));
307 /* set rx desc-ring start address */
308 writel((ulong
)virt_to_phys(&priv
->rxd_ring
[0]), &ectl_p
->rxst
.raw
);
311 bufsz
= readl(&ectl_p
->con2
.raw
);
312 bufsz
&= ~(ETHCON_RXBUFSZ
<< ETHCON_RXBUFSZ_SHFT
);
313 bufsz
|= ((MAX_RX_BUF_SIZE
/ 16) << ETHCON_RXBUFSZ_SHFT
);
314 writel(bufsz
, &ectl_p
->con2
.raw
);
316 /* enable the receiver in hardware which allows hardware
317 * to DMA received pkts to the descriptor pointer address.
319 writel(ETHCON_RXEN
, &ectl_p
->con1
.set
);
322 static int pic32_eth_start(struct udevice
*dev
)
324 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
325 struct pic32eth_dev
*priv
= dev_get_priv(dev
);
328 pic32_ctrl_reset(priv
);
331 pic32_mac_reset(priv
);
334 phy_config(priv
->phydev
);
337 pic32_mac_init(priv
, &pdata
->enetaddr
[0]);
339 /* init RX descriptor; TX descriptors are handled in xmit */
340 pic32_rx_desc_init(priv
);
342 /* Start up & update link status of PHY */
343 phy_startup(priv
->phydev
);
345 /* adjust mac with phy link status */
346 return pic32_mac_adjust_link(priv
);
349 static void pic32_eth_stop(struct udevice
*dev
)
351 struct pic32eth_dev
*priv
= dev_get_priv(dev
);
352 struct pic32_ectl_regs
*ectl_p
= priv
->ectl_regs
;
353 struct pic32_emac_regs
*emac_p
= priv
->emac_regs
;
355 /* Reset the phy if the controller is enabled */
356 if (readl(&ectl_p
->con1
.raw
) & ETHCON_ON
)
357 phy_reset(priv
->phydev
);
359 /* Shut down the PHY */
360 phy_shutdown(priv
->phydev
);
363 writel(ETHCON_TXRTS
| ETHCON_RXEN
, &ectl_p
->con1
.clr
);
367 writel(EMAC_SOFTRESET
, &emac_p
->cfg1
.raw
);
370 writel(0, &emac_p
->cfg1
.raw
);
373 /* disable controller */
374 writel(ETHCON_ON
, &ectl_p
->con1
.clr
);
377 /* wait until everything is down */
378 wait_for_bit(__func__
, &ectl_p
->stat
.raw
, ETHSTAT_BUSY
, false,
379 2 * CONFIG_SYS_HZ
, false);
381 /* clear any existing interrupt event */
382 writel(0xffffffff, &ectl_p
->irq
.clr
);
385 static int pic32_eth_send(struct udevice
*dev
, void *packet
, int length
)
387 struct pic32eth_dev
*priv
= dev_get_priv(dev
);
388 struct pic32_ectl_regs
*ectl_p
= priv
->ectl_regs
;
389 struct eth_dma_desc
*txd
;
392 txd
= &priv
->txd_ring
[0];
394 /* set proper flags & length in descriptor header */
395 txd
->hdr
= EDH_SOP
| EDH_EOP
| EDH_EOWN
| EDH_BCOUNT(length
);
397 /* pass buffer address to hardware */
398 txd
->data_buff
= virt_to_phys(packet
);
400 debug("%s: %d / .hdr %x, .data_buff %x, .stat %x, .nexted %x\n",
401 __func__
, __LINE__
, txd
->hdr
, txd
->data_buff
, txd
->stat2
,
404 /* cache flush (packet) */
405 flush_dcache_range((ulong
)packet
, (ulong
)packet
+ length
);
407 /* cache flush (txd) */
408 flush_dcache_range((ulong
)txd
, (ulong
)txd
+ sizeof(*txd
));
410 /* pass descriptor table base to h/w */
411 writel(virt_to_phys(txd
), &ectl_p
->txst
.raw
);
413 /* ready to send enabled, hardware can now send the packet(s) */
414 writel(ETHCON_TXRTS
| ETHCON_ON
, &ectl_p
->con1
.set
);
416 /* wait until tx has completed and h/w has released ownership
417 * of the tx descriptor or timeout elapsed.
419 deadline
= get_ticks() + get_tbclk();
422 if (get_ticks() > deadline
)
429 if (readl(&ectl_p
->con1
.raw
) & ETHCON_TXRTS
) {
434 /* h/w not released ownership yet? */
435 invalidate_dcache_range((ulong
)txd
, (ulong
)txd
+ sizeof(*txd
));
436 if (!(txd
->hdr
& EDH_EOWN
))
443 static int pic32_eth_recv(struct udevice
*dev
, int flags
, uchar
**packetp
)
445 struct pic32eth_dev
*priv
= dev_get_priv(dev
);
446 struct eth_dma_desc
*rxd
;
447 u32 idx
= priv
->rxd_idx
;
450 /* find the next ready to receive */
451 rxd
= &priv
->rxd_ring
[idx
];
453 invalidate_dcache_range((ulong
)rxd
, (ulong
)rxd
+ sizeof(*rxd
));
454 /* check if owned by MAC */
455 if (rxd
->hdr
& EDH_EOWN
)
458 /* Sanity check on header: SOP and EOP */
459 if ((rxd
->hdr
& (EDH_SOP
| EDH_EOP
)) != (EDH_SOP
| EDH_EOP
)) {
460 printf("%s: %s, rx pkt across multiple descr\n",
465 debug("%s: %d /idx %i, hdr=%x, data_buff %x, stat %x, nexted %x\n",
466 __func__
, __LINE__
, idx
, rxd
->hdr
,
467 rxd
->data_buff
, rxd
->stat2
, rxd
->next_ed
);
469 /* Sanity check on rx_stat: OK, CRC */
470 if (!RSV_RX_OK(rxd
->stat2
) || RSV_CRC_ERR(rxd
->stat2
)) {
471 debug("%s: %s: Error, rx problem detected\n",
476 /* invalidate dcache */
477 rx_count
= RSV_RX_COUNT(rxd
->stat2
);
478 invalidate_dcache_range((ulong
)net_rx_packets
[idx
],
479 (ulong
)net_rx_packets
[idx
] + rx_count
);
481 /* Pass the packet to protocol layer */
482 *packetp
= net_rx_packets
[idx
];
484 /* increment number of bytes rcvd (ignore CRC) */
488 static int pic32_eth_free_pkt(struct udevice
*dev
, uchar
*packet
, int length
)
490 struct pic32eth_dev
*priv
= dev_get_priv(dev
);
491 struct pic32_ectl_regs
*ectl_p
= priv
->ectl_regs
;
492 struct eth_dma_desc
*rxd
;
493 int idx
= priv
->rxd_idx
;
496 if (packet
!= net_rx_packets
[idx
]) {
497 printf("rxd_id %d: packet is not matched,\n", idx
);
501 /* prepare for receive */
502 rxd
= &priv
->rxd_ring
[idx
];
503 rxd
->hdr
= EDH_STICKY
| EDH_NPV
| EDH_EOWN
;
505 flush_dcache_range((ulong
)rxd
, (ulong
)rxd
+ sizeof(*rxd
));
507 /* decrement rx pkt count */
508 writel(ETHCON_BUFCDEC
, &ectl_p
->con1
.set
);
510 debug("%s: %d / idx %i, hdr %x, data_buff %x, stat %x, nexted %x\n",
511 __func__
, __LINE__
, idx
, rxd
->hdr
, rxd
->data_buff
,
512 rxd
->stat2
, rxd
->next_ed
);
514 priv
->rxd_idx
= (priv
->rxd_idx
+ 1) % MAX_RX_DESCR
;
519 static const struct eth_ops pic32_eth_ops
= {
520 .start
= pic32_eth_start
,
521 .send
= pic32_eth_send
,
522 .recv
= pic32_eth_recv
,
523 .free_pkt
= pic32_eth_free_pkt
,
524 .stop
= pic32_eth_stop
,
527 static int pic32_eth_probe(struct udevice
*dev
)
529 struct eth_pdata
*pdata
= dev_get_platdata(dev
);
530 struct pic32eth_dev
*priv
= dev_get_priv(dev
);
531 const char *phy_mode
;
532 void __iomem
*iobase
;
538 addr
= fdtdec_get_addr_size(gd
->fdt_blob
, dev_of_offset(dev
), "reg",
540 if (addr
== FDT_ADDR_T_NONE
)
543 iobase
= ioremap(addr
, size
);
544 pdata
->iobase
= (phys_addr_t
)addr
;
547 pdata
->phy_interface
= -1;
548 phy_mode
= fdt_getprop(gd
->fdt_blob
, dev_of_offset(dev
), "phy-mode",
551 pdata
->phy_interface
= phy_get_interface_by_name(phy_mode
);
552 if (pdata
->phy_interface
== -1) {
553 debug("%s: Invalid PHY interface '%s'\n", __func__
, phy_mode
);
558 offset
= fdtdec_lookup_phandle(gd
->fdt_blob
, dev_of_offset(dev
),
561 phy_addr
= fdtdec_get_int(gd
->fdt_blob
, offset
, "reg", -1);
564 gpio_request_by_name_nodev(dev_ofnode(dev
), "reset-gpios", 0,
565 &priv
->rst_gpio
, GPIOD_IS_OUT
);
567 priv
->phyif
= pdata
->phy_interface
;
568 priv
->phy_addr
= phy_addr
;
569 priv
->ectl_regs
= iobase
;
570 priv
->emac_regs
= iobase
+ PIC32_EMAC1CFG1
;
572 pic32_mii_init(priv
);
574 return pic32_phy_init(priv
, dev
);
577 static int pic32_eth_remove(struct udevice
*dev
)
579 struct pic32eth_dev
*priv
= dev_get_priv(dev
);
582 dm_gpio_free(dev
, &priv
->rst_gpio
);
583 phy_shutdown(priv
->phydev
);
585 bus
= miiphy_get_dev_by_name(PIC32_MDIO_NAME
);
586 mdio_unregister(bus
);
588 iounmap(priv
->ectl_regs
);
592 static const struct udevice_id pic32_eth_ids
[] = {
593 { .compatible
= "microchip,pic32mzda-eth" },
597 U_BOOT_DRIVER(pic32_ethernet
) = {
598 .name
= "pic32_ethernet",
600 .of_match
= pic32_eth_ids
,
601 .probe
= pic32_eth_probe
,
602 .remove
= pic32_eth_remove
,
603 .ops
= &pic32_eth_ops
,
604 .priv_auto_alloc_size
= sizeof(struct pic32eth_dev
),
605 .platdata_auto_alloc_size
= sizeof(struct eth_pdata
),