2 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
4 * Intel Platform Controller Hub EG20T (codename Topcliff) GMAC Driver
6 * SPDX-License-Identifier: GPL-2.0+
17 #if !defined(CONFIG_PHYLIB)
18 # error "PCH Gigabit Ethernet driver requires PHYLIB - missing CONFIG_PHYLIB"
21 static struct pci_device_id supported
[] = {
22 { PCI_DEVICE(PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_TCF_GBE
) },
26 static void pch_gbe_mac_read(struct pch_gbe_regs
*mac_regs
, u8
*addr
)
28 u32 macid_hi
, macid_lo
;
30 macid_hi
= readl(&mac_regs
->mac_adr
[0].high
);
31 macid_lo
= readl(&mac_regs
->mac_adr
[0].low
) & 0xffff;
32 debug("pch_gbe: macid_hi %#x macid_lo %#x\n", macid_hi
, macid_lo
);
34 addr
[0] = (u8
)(macid_hi
& 0xff);
35 addr
[1] = (u8
)((macid_hi
>> 8) & 0xff);
36 addr
[2] = (u8
)((macid_hi
>> 16) & 0xff);
37 addr
[3] = (u8
)((macid_hi
>> 24) & 0xff);
38 addr
[4] = (u8
)(macid_lo
& 0xff);
39 addr
[5] = (u8
)((macid_lo
>> 8) & 0xff);
42 static int pch_gbe_mac_write(struct pch_gbe_regs
*mac_regs
, u8
*addr
)
44 u32 macid_hi
, macid_lo
;
47 macid_hi
= addr
[0] + (addr
[1] << 8) + (addr
[2] << 16) + (addr
[3] << 24);
48 macid_lo
= addr
[4] + (addr
[5] << 8);
50 writel(macid_hi
, &mac_regs
->mac_adr
[0].high
);
51 writel(macid_lo
, &mac_regs
->mac_adr
[0].low
);
52 writel(0xfffe, &mac_regs
->addr_mask
);
55 while (get_timer(start
) < PCH_GBE_TIMEOUT
) {
56 if (!(readl(&mac_regs
->addr_mask
) & PCH_GBE_BUSY
))
65 static int pch_gbe_reset(struct udevice
*dev
)
67 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
68 struct eth_pdata
*plat
= dev_get_platdata(dev
);
69 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
75 writel(PCH_GBE_ALL_RST
, &mac_regs
->reset
);
78 * Configure the MAC to RGMII mode after reset
80 * For some unknown reason, we must do the configuration here right
81 * after resetting the whole MAC, otherwise the reset bit in the RESET
82 * register will never be cleared by the hardware. And there is another
83 * way of having the same magic, that is to configure the MODE register
84 * to have the MAC work in MII/GMII mode, which is how current Linux
85 * pch_gbe driver does. Since anyway we need program the MAC to RGMII
86 * mode in the driver, we just do it here.
88 * Note: this behavior is not documented in the hardware manual.
90 writel(PCH_GBE_RGMII_MODE_RGMII
| PCH_GBE_CHIP_TYPE_INTERNAL
,
91 &mac_regs
->rgmii_ctrl
);
94 while (get_timer(start
) < PCH_GBE_TIMEOUT
) {
95 if (!(readl(&mac_regs
->reset
) & PCH_GBE_ALL_RST
)) {
97 * Soft reset clears hardware MAC address registers,
98 * so we have to reload MAC address here in order to
99 * make linux pch_gbe driver happy.
101 return pch_gbe_mac_write(mac_regs
, plat
->enetaddr
);
107 debug("pch_gbe: reset timeout\n");
111 static void pch_gbe_rx_descs_init(struct udevice
*dev
)
113 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
114 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
115 struct pch_gbe_rx_desc
*rx_desc
= &priv
->rx_desc
[0];
118 memset(rx_desc
, 0, sizeof(struct pch_gbe_rx_desc
) * PCH_GBE_DESC_NUM
);
119 for (i
= 0; i
< PCH_GBE_DESC_NUM
; i
++)
120 rx_desc
[i
].buffer_addr
= dm_pci_virt_to_mem(priv
->dev
,
123 flush_dcache_range((ulong
)rx_desc
, (ulong
)&rx_desc
[PCH_GBE_DESC_NUM
]);
125 writel(dm_pci_virt_to_mem(priv
->dev
, rx_desc
),
126 &mac_regs
->rx_dsc_base
);
127 writel(sizeof(struct pch_gbe_rx_desc
) * (PCH_GBE_DESC_NUM
- 1),
128 &mac_regs
->rx_dsc_size
);
130 writel(dm_pci_virt_to_mem(priv
->dev
, rx_desc
+ 1),
131 &mac_regs
->rx_dsc_sw_p
);
134 static void pch_gbe_tx_descs_init(struct udevice
*dev
)
136 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
137 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
138 struct pch_gbe_tx_desc
*tx_desc
= &priv
->tx_desc
[0];
140 memset(tx_desc
, 0, sizeof(struct pch_gbe_tx_desc
) * PCH_GBE_DESC_NUM
);
142 flush_dcache_range((ulong
)tx_desc
, (ulong
)&tx_desc
[PCH_GBE_DESC_NUM
]);
144 writel(dm_pci_virt_to_mem(priv
->dev
, tx_desc
),
145 &mac_regs
->tx_dsc_base
);
146 writel(sizeof(struct pch_gbe_tx_desc
) * (PCH_GBE_DESC_NUM
- 1),
147 &mac_regs
->tx_dsc_size
);
148 writel(dm_pci_virt_to_mem(priv
->dev
, tx_desc
+ 1),
149 &mac_regs
->tx_dsc_sw_p
);
152 static void pch_gbe_adjust_link(struct pch_gbe_regs
*mac_regs
,
153 struct phy_device
*phydev
)
156 printf("%s: No link.\n", phydev
->dev
->name
);
160 clrbits_le32(&mac_regs
->rgmii_ctrl
,
161 PCH_GBE_RGMII_RATE_2_5M
| PCH_GBE_CRS_SEL
);
162 clrbits_le32(&mac_regs
->mode
,
163 PCH_GBE_MODE_GMII_ETHER
| PCH_GBE_MODE_FULL_DUPLEX
);
165 switch (phydev
->speed
) {
167 setbits_le32(&mac_regs
->rgmii_ctrl
, PCH_GBE_RGMII_RATE_125M
);
168 setbits_le32(&mac_regs
->mode
, PCH_GBE_MODE_GMII_ETHER
);
171 setbits_le32(&mac_regs
->rgmii_ctrl
, PCH_GBE_RGMII_RATE_25M
);
172 setbits_le32(&mac_regs
->mode
, PCH_GBE_MODE_MII_ETHER
);
175 setbits_le32(&mac_regs
->rgmii_ctrl
, PCH_GBE_RGMII_RATE_2_5M
);
176 setbits_le32(&mac_regs
->mode
, PCH_GBE_MODE_MII_ETHER
);
180 if (phydev
->duplex
) {
181 setbits_le32(&mac_regs
->rgmii_ctrl
, PCH_GBE_CRS_SEL
);
182 setbits_le32(&mac_regs
->mode
, PCH_GBE_MODE_FULL_DUPLEX
);
185 printf("Speed: %d, %s duplex\n", phydev
->speed
,
186 (phydev
->duplex
) ? "full" : "half");
191 static int pch_gbe_start(struct udevice
*dev
)
193 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
194 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
196 if (pch_gbe_reset(dev
))
199 pch_gbe_rx_descs_init(dev
);
200 pch_gbe_tx_descs_init(dev
);
202 /* Enable frame bursting */
203 writel(PCH_GBE_MODE_FR_BST
, &mac_regs
->mode
);
204 /* Disable TCP/IP accelerator */
205 writel(PCH_GBE_RX_TCPIPACC_OFF
, &mac_regs
->tcpip_acc
);
206 /* Disable RX flow control */
207 writel(0, &mac_regs
->rx_fctrl
);
208 /* Configure RX/TX mode */
209 writel(PCH_GBE_RH_ALM_EMP_16
| PCH_GBE_RH_ALM_FULL_16
|
210 PCH_GBE_RH_RD_TRG_32
, &mac_regs
->rx_mode
);
211 writel(PCH_GBE_TM_TH_TX_STRT_32
| PCH_GBE_TM_TH_ALM_EMP_16
|
212 PCH_GBE_TM_TH_ALM_FULL_32
| PCH_GBE_TM_ST_AND_FD
|
213 PCH_GBE_TM_SHORT_PKT
, &mac_regs
->tx_mode
);
215 /* Start up the PHY */
216 if (phy_startup(priv
->phydev
)) {
217 printf("Could not initialize PHY %s\n",
218 priv
->phydev
->dev
->name
);
222 pch_gbe_adjust_link(mac_regs
, priv
->phydev
);
224 if (!priv
->phydev
->link
)
228 writel(PCH_GBE_RX_DMA_EN
| PCH_GBE_TX_DMA_EN
, &mac_regs
->dma_ctrl
);
229 writel(PCH_GBE_MRE_MAC_RX_EN
, &mac_regs
->mac_rx_en
);
234 static void pch_gbe_stop(struct udevice
*dev
)
236 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
240 phy_shutdown(priv
->phydev
);
243 static int pch_gbe_send(struct udevice
*dev
, void *packet
, int length
)
245 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
246 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
247 struct pch_gbe_tx_desc
*tx_head
, *tx_desc
;
252 flush_dcache_range((ulong
)packet
, (ulong
)packet
+ length
);
254 tx_head
= &priv
->tx_desc
[0];
255 tx_desc
= &priv
->tx_desc
[priv
->tx_idx
];
258 frame_ctrl
|= PCH_GBE_TXD_CTRL_APAD
;
260 tx_desc
->buffer_addr
= dm_pci_virt_to_mem(priv
->dev
, packet
);
261 tx_desc
->length
= length
;
262 tx_desc
->tx_words_eob
= length
+ 3;
263 tx_desc
->tx_frame_ctrl
= frame_ctrl
;
264 tx_desc
->dma_status
= 0;
265 tx_desc
->gbec_status
= 0;
267 flush_dcache_range((ulong
)tx_desc
, (ulong
)&tx_desc
[1]);
269 /* Test the wrap-around condition */
270 if (++priv
->tx_idx
>= PCH_GBE_DESC_NUM
)
273 writel(dm_pci_virt_to_mem(priv
->dev
, tx_head
+ priv
->tx_idx
),
274 &mac_regs
->tx_dsc_sw_p
);
276 start
= get_timer(0);
277 while (get_timer(start
) < PCH_GBE_TIMEOUT
) {
278 int_st
= readl(&mac_regs
->int_st
);
279 if (int_st
& PCH_GBE_INT_TX_CMPLT
)
285 debug("pch_gbe: sent failed\n");
289 static int pch_gbe_recv(struct udevice
*dev
, int flags
, uchar
**packetp
)
291 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
292 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
293 struct pch_gbe_rx_desc
*rx_desc
;
294 ulong hw_desc
, length
;
297 rx_desc
= &priv
->rx_desc
[priv
->rx_idx
];
299 readl(&mac_regs
->int_st
);
300 hw_desc
= readl(&mac_regs
->rx_dsc_hw_p_hld
);
302 /* Just return if not receiving any packet */
303 if (virt_to_phys(rx_desc
) == hw_desc
)
306 /* Invalidate the descriptor */
307 invalidate_dcache_range((ulong
)rx_desc
, (ulong
)&rx_desc
[1]);
309 length
= rx_desc
->rx_words_eob
- 3 - ETH_FCS_LEN
;
310 buffer
= dm_pci_mem_to_virt(priv
->dev
, rx_desc
->buffer_addr
, length
, 0);
311 invalidate_dcache_range((ulong
)buffer
, (ulong
)buffer
+ length
);
312 *packetp
= (uchar
*)buffer
;
317 static int pch_gbe_free_pkt(struct udevice
*dev
, uchar
*packet
, int length
)
319 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
320 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
321 struct pch_gbe_rx_desc
*rx_head
= &priv
->rx_desc
[0];
324 /* Test the wrap-around condition */
325 if (++priv
->rx_idx
>= PCH_GBE_DESC_NUM
)
327 rx_swp
= priv
->rx_idx
;
328 if (++rx_swp
>= PCH_GBE_DESC_NUM
)
331 writel(dm_pci_virt_to_mem(priv
->dev
, rx_head
+ rx_swp
),
332 &mac_regs
->rx_dsc_sw_p
);
337 static int pch_gbe_mdio_ready(struct pch_gbe_regs
*mac_regs
)
339 ulong start
= get_timer(0);
341 while (get_timer(start
) < PCH_GBE_TIMEOUT
) {
342 if (readl(&mac_regs
->miim
) & PCH_GBE_MIIM_OPER_READY
)
351 static int pch_gbe_mdio_read(struct mii_dev
*bus
, int addr
, int devad
, int reg
)
353 struct pch_gbe_regs
*mac_regs
= bus
->priv
;
356 if (pch_gbe_mdio_ready(mac_regs
))
359 miim
= (addr
<< PCH_GBE_MIIM_PHY_ADDR_SHIFT
) |
360 (reg
<< PCH_GBE_MIIM_REG_ADDR_SHIFT
) |
361 PCH_GBE_MIIM_OPER_READ
;
362 writel(miim
, &mac_regs
->miim
);
364 if (pch_gbe_mdio_ready(mac_regs
))
367 return readl(&mac_regs
->miim
) & 0xffff;
370 static int pch_gbe_mdio_write(struct mii_dev
*bus
, int addr
, int devad
,
373 struct pch_gbe_regs
*mac_regs
= bus
->priv
;
376 if (pch_gbe_mdio_ready(mac_regs
))
379 miim
= (addr
<< PCH_GBE_MIIM_PHY_ADDR_SHIFT
) |
380 (reg
<< PCH_GBE_MIIM_REG_ADDR_SHIFT
) |
381 PCH_GBE_MIIM_OPER_WRITE
| val
;
382 writel(miim
, &mac_regs
->miim
);
384 if (pch_gbe_mdio_ready(mac_regs
))
390 static int pch_gbe_mdio_init(const char *name
, struct pch_gbe_regs
*mac_regs
)
396 debug("pch_gbe: failed to allocate MDIO bus\n");
400 bus
->read
= pch_gbe_mdio_read
;
401 bus
->write
= pch_gbe_mdio_write
;
402 strcpy(bus
->name
, name
);
404 bus
->priv
= (void *)mac_regs
;
406 return mdio_register(bus
);
409 static int pch_gbe_phy_init(struct udevice
*dev
)
411 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
412 struct eth_pdata
*plat
= dev_get_platdata(dev
);
413 struct phy_device
*phydev
;
414 int mask
= 0xffffffff;
416 phydev
= phy_find_by_mask(priv
->bus
, mask
, plat
->phy_interface
);
418 printf("pch_gbe: cannot find the phy\n");
422 phy_connect_dev(phydev
, dev
);
424 phydev
->supported
&= PHY_GBIT_FEATURES
;
425 phydev
->advertising
= phydev
->supported
;
427 priv
->phydev
= phydev
;
433 int pch_gbe_probe(struct udevice
*dev
)
435 struct pch_gbe_priv
*priv
;
436 struct eth_pdata
*plat
= dev_get_platdata(dev
);
441 * The priv structure contains the descriptors and frame buffers which
442 * need a strict buswidth alignment (64 bytes). This is guaranteed by
443 * DM_FLAG_ALLOC_PRIV_DMA flag in the U_BOOT_DRIVER.
445 priv
= dev_get_priv(dev
);
449 iobase
= dm_pci_map_bar(dev
, PCI_BASE_ADDRESS_1
, PCI_REGION_MEM
);
451 plat
->iobase
= (ulong
)iobase
;
452 priv
->mac_regs
= (struct pch_gbe_regs
*)iobase
;
454 /* Read MAC address from SROM and initialize dev->enetaddr with it */
455 pch_gbe_mac_read(priv
->mac_regs
, plat
->enetaddr
);
457 plat
->phy_interface
= PHY_INTERFACE_MODE_RGMII
;
458 pch_gbe_mdio_init(dev
->name
, priv
->mac_regs
);
459 priv
->bus
= miiphy_get_dev_by_name(dev
->name
);
461 err
= pch_gbe_reset(dev
);
465 return pch_gbe_phy_init(dev
);
468 int pch_gbe_remove(struct udevice
*dev
)
470 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
473 mdio_unregister(priv
->bus
);
474 mdio_free(priv
->bus
);
479 static const struct eth_ops pch_gbe_ops
= {
480 .start
= pch_gbe_start
,
481 .send
= pch_gbe_send
,
482 .recv
= pch_gbe_recv
,
483 .free_pkt
= pch_gbe_free_pkt
,
484 .stop
= pch_gbe_stop
,
487 static const struct udevice_id pch_gbe_ids
[] = {
488 { .compatible
= "intel,pch-gbe" },
492 U_BOOT_DRIVER(eth_pch_gbe
) = {
495 .of_match
= pch_gbe_ids
,
496 .probe
= pch_gbe_probe
,
497 .remove
= pch_gbe_remove
,
499 .priv_auto_alloc_size
= sizeof(struct pch_gbe_priv
),
500 .platdata_auto_alloc_size
= sizeof(struct eth_pdata
),
501 .flags
= DM_FLAG_ALLOC_PRIV_DMA
,
504 U_BOOT_PCI_DEVICE(eth_pch_gbe
, supported
);