1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
5 * Intel Platform Controller Hub EG20T (codename Topcliff) GMAC Driver
18 #if !defined(CONFIG_PHYLIB)
19 # error "PCH Gigabit Ethernet driver requires PHYLIB - missing CONFIG_PHYLIB"
22 static struct pci_device_id supported
[] = {
23 { PCI_DEVICE(PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_TCF_GBE
) },
27 static void pch_gbe_mac_read(struct pch_gbe_regs
*mac_regs
, u8
*addr
)
29 u32 macid_hi
, macid_lo
;
31 macid_hi
= readl(&mac_regs
->mac_adr
[0].high
);
32 macid_lo
= readl(&mac_regs
->mac_adr
[0].low
) & 0xffff;
33 debug("pch_gbe: macid_hi %#x macid_lo %#x\n", macid_hi
, macid_lo
);
35 addr
[0] = (u8
)(macid_hi
& 0xff);
36 addr
[1] = (u8
)((macid_hi
>> 8) & 0xff);
37 addr
[2] = (u8
)((macid_hi
>> 16) & 0xff);
38 addr
[3] = (u8
)((macid_hi
>> 24) & 0xff);
39 addr
[4] = (u8
)(macid_lo
& 0xff);
40 addr
[5] = (u8
)((macid_lo
>> 8) & 0xff);
43 static int pch_gbe_mac_write(struct pch_gbe_regs
*mac_regs
, u8
*addr
)
45 u32 macid_hi
, macid_lo
;
48 macid_hi
= addr
[0] + (addr
[1] << 8) + (addr
[2] << 16) + (addr
[3] << 24);
49 macid_lo
= addr
[4] + (addr
[5] << 8);
51 writel(macid_hi
, &mac_regs
->mac_adr
[0].high
);
52 writel(macid_lo
, &mac_regs
->mac_adr
[0].low
);
53 writel(0xfffe, &mac_regs
->addr_mask
);
56 while (get_timer(start
) < PCH_GBE_TIMEOUT
) {
57 if (!(readl(&mac_regs
->addr_mask
) & PCH_GBE_BUSY
))
66 static int pch_gbe_reset(struct udevice
*dev
)
68 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
69 struct eth_pdata
*plat
= dev_get_platdata(dev
);
70 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
76 writel(PCH_GBE_ALL_RST
, &mac_regs
->reset
);
79 * Configure the MAC to RGMII mode after reset
81 * For some unknown reason, we must do the configuration here right
82 * after resetting the whole MAC, otherwise the reset bit in the RESET
83 * register will never be cleared by the hardware. And there is another
84 * way of having the same magic, that is to configure the MODE register
85 * to have the MAC work in MII/GMII mode, which is how current Linux
86 * pch_gbe driver does. Since anyway we need program the MAC to RGMII
87 * mode in the driver, we just do it here.
89 * Note: this behavior is not documented in the hardware manual.
91 writel(PCH_GBE_RGMII_MODE_RGMII
| PCH_GBE_CHIP_TYPE_INTERNAL
,
92 &mac_regs
->rgmii_ctrl
);
95 while (get_timer(start
) < PCH_GBE_TIMEOUT
) {
96 if (!(readl(&mac_regs
->reset
) & PCH_GBE_ALL_RST
)) {
98 * Soft reset clears hardware MAC address registers,
99 * so we have to reload MAC address here in order to
100 * make linux pch_gbe driver happy.
102 return pch_gbe_mac_write(mac_regs
, plat
->enetaddr
);
108 debug("pch_gbe: reset timeout\n");
112 static void pch_gbe_rx_descs_init(struct udevice
*dev
)
114 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
115 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
116 struct pch_gbe_rx_desc
*rx_desc
= &priv
->rx_desc
[0];
119 memset(rx_desc
, 0, sizeof(struct pch_gbe_rx_desc
) * PCH_GBE_DESC_NUM
);
120 for (i
= 0; i
< PCH_GBE_DESC_NUM
; i
++)
121 rx_desc
[i
].buffer_addr
= dm_pci_virt_to_mem(priv
->dev
,
124 flush_dcache_range((ulong
)rx_desc
, (ulong
)&rx_desc
[PCH_GBE_DESC_NUM
]);
126 writel(dm_pci_virt_to_mem(priv
->dev
, rx_desc
),
127 &mac_regs
->rx_dsc_base
);
128 writel(sizeof(struct pch_gbe_rx_desc
) * (PCH_GBE_DESC_NUM
- 1),
129 &mac_regs
->rx_dsc_size
);
131 writel(dm_pci_virt_to_mem(priv
->dev
, rx_desc
+ 1),
132 &mac_regs
->rx_dsc_sw_p
);
135 static void pch_gbe_tx_descs_init(struct udevice
*dev
)
137 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
138 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
139 struct pch_gbe_tx_desc
*tx_desc
= &priv
->tx_desc
[0];
141 memset(tx_desc
, 0, sizeof(struct pch_gbe_tx_desc
) * PCH_GBE_DESC_NUM
);
143 flush_dcache_range((ulong
)tx_desc
, (ulong
)&tx_desc
[PCH_GBE_DESC_NUM
]);
145 writel(dm_pci_virt_to_mem(priv
->dev
, tx_desc
),
146 &mac_regs
->tx_dsc_base
);
147 writel(sizeof(struct pch_gbe_tx_desc
) * (PCH_GBE_DESC_NUM
- 1),
148 &mac_regs
->tx_dsc_size
);
149 writel(dm_pci_virt_to_mem(priv
->dev
, tx_desc
+ 1),
150 &mac_regs
->tx_dsc_sw_p
);
153 static void pch_gbe_adjust_link(struct pch_gbe_regs
*mac_regs
,
154 struct phy_device
*phydev
)
157 printf("%s: No link.\n", phydev
->dev
->name
);
161 clrbits_le32(&mac_regs
->rgmii_ctrl
,
162 PCH_GBE_RGMII_RATE_2_5M
| PCH_GBE_CRS_SEL
);
163 clrbits_le32(&mac_regs
->mode
,
164 PCH_GBE_MODE_GMII_ETHER
| PCH_GBE_MODE_FULL_DUPLEX
);
166 switch (phydev
->speed
) {
168 setbits_le32(&mac_regs
->rgmii_ctrl
, PCH_GBE_RGMII_RATE_125M
);
169 setbits_le32(&mac_regs
->mode
, PCH_GBE_MODE_GMII_ETHER
);
172 setbits_le32(&mac_regs
->rgmii_ctrl
, PCH_GBE_RGMII_RATE_25M
);
173 setbits_le32(&mac_regs
->mode
, PCH_GBE_MODE_MII_ETHER
);
176 setbits_le32(&mac_regs
->rgmii_ctrl
, PCH_GBE_RGMII_RATE_2_5M
);
177 setbits_le32(&mac_regs
->mode
, PCH_GBE_MODE_MII_ETHER
);
181 if (phydev
->duplex
) {
182 setbits_le32(&mac_regs
->rgmii_ctrl
, PCH_GBE_CRS_SEL
);
183 setbits_le32(&mac_regs
->mode
, PCH_GBE_MODE_FULL_DUPLEX
);
186 printf("Speed: %d, %s duplex\n", phydev
->speed
,
187 (phydev
->duplex
) ? "full" : "half");
192 static int pch_gbe_start(struct udevice
*dev
)
194 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
195 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
197 if (pch_gbe_reset(dev
))
200 pch_gbe_rx_descs_init(dev
);
201 pch_gbe_tx_descs_init(dev
);
203 /* Enable frame bursting */
204 writel(PCH_GBE_MODE_FR_BST
, &mac_regs
->mode
);
205 /* Disable TCP/IP accelerator */
206 writel(PCH_GBE_RX_TCPIPACC_OFF
, &mac_regs
->tcpip_acc
);
207 /* Disable RX flow control */
208 writel(0, &mac_regs
->rx_fctrl
);
209 /* Configure RX/TX mode */
210 writel(PCH_GBE_RH_ALM_EMP_16
| PCH_GBE_RH_ALM_FULL_16
|
211 PCH_GBE_RH_RD_TRG_32
, &mac_regs
->rx_mode
);
212 writel(PCH_GBE_TM_TH_TX_STRT_32
| PCH_GBE_TM_TH_ALM_EMP_16
|
213 PCH_GBE_TM_TH_ALM_FULL_32
| PCH_GBE_TM_ST_AND_FD
|
214 PCH_GBE_TM_SHORT_PKT
, &mac_regs
->tx_mode
);
216 /* Start up the PHY */
217 if (phy_startup(priv
->phydev
)) {
218 printf("Could not initialize PHY %s\n",
219 priv
->phydev
->dev
->name
);
223 pch_gbe_adjust_link(mac_regs
, priv
->phydev
);
225 if (!priv
->phydev
->link
)
229 writel(PCH_GBE_RX_DMA_EN
| PCH_GBE_TX_DMA_EN
, &mac_regs
->dma_ctrl
);
230 writel(PCH_GBE_MRE_MAC_RX_EN
, &mac_regs
->mac_rx_en
);
235 static void pch_gbe_stop(struct udevice
*dev
)
237 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
241 phy_shutdown(priv
->phydev
);
244 static int pch_gbe_send(struct udevice
*dev
, void *packet
, int length
)
246 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
247 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
248 struct pch_gbe_tx_desc
*tx_head
, *tx_desc
;
253 flush_dcache_range((ulong
)packet
, (ulong
)packet
+ length
);
255 tx_head
= &priv
->tx_desc
[0];
256 tx_desc
= &priv
->tx_desc
[priv
->tx_idx
];
259 frame_ctrl
|= PCH_GBE_TXD_CTRL_APAD
;
261 tx_desc
->buffer_addr
= dm_pci_virt_to_mem(priv
->dev
, packet
);
262 tx_desc
->length
= length
;
263 tx_desc
->tx_words_eob
= length
+ 3;
264 tx_desc
->tx_frame_ctrl
= frame_ctrl
;
265 tx_desc
->dma_status
= 0;
266 tx_desc
->gbec_status
= 0;
268 flush_dcache_range((ulong
)tx_desc
, (ulong
)&tx_desc
[1]);
270 /* Test the wrap-around condition */
271 if (++priv
->tx_idx
>= PCH_GBE_DESC_NUM
)
274 writel(dm_pci_virt_to_mem(priv
->dev
, tx_head
+ priv
->tx_idx
),
275 &mac_regs
->tx_dsc_sw_p
);
277 start
= get_timer(0);
278 while (get_timer(start
) < PCH_GBE_TIMEOUT
) {
279 int_st
= readl(&mac_regs
->int_st
);
280 if (int_st
& PCH_GBE_INT_TX_CMPLT
)
286 debug("pch_gbe: sent failed\n");
290 static int pch_gbe_recv(struct udevice
*dev
, int flags
, uchar
**packetp
)
292 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
293 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
294 struct pch_gbe_rx_desc
*rx_desc
;
295 ulong hw_desc
, length
;
298 rx_desc
= &priv
->rx_desc
[priv
->rx_idx
];
300 readl(&mac_regs
->int_st
);
301 hw_desc
= readl(&mac_regs
->rx_dsc_hw_p_hld
);
303 /* Just return if not receiving any packet */
304 if (virt_to_phys(rx_desc
) == hw_desc
)
307 /* Invalidate the descriptor */
308 invalidate_dcache_range((ulong
)rx_desc
, (ulong
)&rx_desc
[1]);
310 length
= rx_desc
->rx_words_eob
- 3 - ETH_FCS_LEN
;
311 buffer
= dm_pci_mem_to_virt(priv
->dev
, rx_desc
->buffer_addr
, length
, 0);
312 invalidate_dcache_range((ulong
)buffer
, (ulong
)buffer
+ length
);
313 *packetp
= (uchar
*)buffer
;
318 static int pch_gbe_free_pkt(struct udevice
*dev
, uchar
*packet
, int length
)
320 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
321 struct pch_gbe_regs
*mac_regs
= priv
->mac_regs
;
322 struct pch_gbe_rx_desc
*rx_head
= &priv
->rx_desc
[0];
325 /* Test the wrap-around condition */
326 if (++priv
->rx_idx
>= PCH_GBE_DESC_NUM
)
328 rx_swp
= priv
->rx_idx
;
329 if (++rx_swp
>= PCH_GBE_DESC_NUM
)
332 writel(dm_pci_virt_to_mem(priv
->dev
, rx_head
+ rx_swp
),
333 &mac_regs
->rx_dsc_sw_p
);
338 static int pch_gbe_mdio_ready(struct pch_gbe_regs
*mac_regs
)
340 ulong start
= get_timer(0);
342 while (get_timer(start
) < PCH_GBE_TIMEOUT
) {
343 if (readl(&mac_regs
->miim
) & PCH_GBE_MIIM_OPER_READY
)
352 static int pch_gbe_mdio_read(struct mii_dev
*bus
, int addr
, int devad
, int reg
)
354 struct pch_gbe_regs
*mac_regs
= bus
->priv
;
357 if (pch_gbe_mdio_ready(mac_regs
))
360 miim
= (addr
<< PCH_GBE_MIIM_PHY_ADDR_SHIFT
) |
361 (reg
<< PCH_GBE_MIIM_REG_ADDR_SHIFT
) |
362 PCH_GBE_MIIM_OPER_READ
;
363 writel(miim
, &mac_regs
->miim
);
365 if (pch_gbe_mdio_ready(mac_regs
))
368 return readl(&mac_regs
->miim
) & 0xffff;
371 static int pch_gbe_mdio_write(struct mii_dev
*bus
, int addr
, int devad
,
374 struct pch_gbe_regs
*mac_regs
= bus
->priv
;
377 if (pch_gbe_mdio_ready(mac_regs
))
380 miim
= (addr
<< PCH_GBE_MIIM_PHY_ADDR_SHIFT
) |
381 (reg
<< PCH_GBE_MIIM_REG_ADDR_SHIFT
) |
382 PCH_GBE_MIIM_OPER_WRITE
| val
;
383 writel(miim
, &mac_regs
->miim
);
385 if (pch_gbe_mdio_ready(mac_regs
))
391 static int pch_gbe_mdio_init(const char *name
, struct pch_gbe_regs
*mac_regs
)
397 debug("pch_gbe: failed to allocate MDIO bus\n");
401 bus
->read
= pch_gbe_mdio_read
;
402 bus
->write
= pch_gbe_mdio_write
;
403 strcpy(bus
->name
, name
);
405 bus
->priv
= (void *)mac_regs
;
407 return mdio_register(bus
);
410 static int pch_gbe_phy_init(struct udevice
*dev
)
412 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
413 struct eth_pdata
*plat
= dev_get_platdata(dev
);
414 struct phy_device
*phydev
;
415 int mask
= 0xffffffff;
417 phydev
= phy_find_by_mask(priv
->bus
, mask
, plat
->phy_interface
);
419 printf("pch_gbe: cannot find the phy\n");
423 phy_connect_dev(phydev
, dev
);
425 phydev
->supported
&= PHY_GBIT_FEATURES
;
426 phydev
->advertising
= phydev
->supported
;
428 priv
->phydev
= phydev
;
434 static int pch_gbe_probe(struct udevice
*dev
)
436 struct pch_gbe_priv
*priv
;
437 struct eth_pdata
*plat
= dev_get_platdata(dev
);
442 * The priv structure contains the descriptors and frame buffers which
443 * need a strict buswidth alignment (64 bytes). This is guaranteed by
444 * DM_FLAG_ALLOC_PRIV_DMA flag in the U_BOOT_DRIVER.
446 priv
= dev_get_priv(dev
);
450 iobase
= dm_pci_map_bar(dev
, PCI_BASE_ADDRESS_1
, PCI_REGION_MEM
);
452 plat
->iobase
= (ulong
)iobase
;
453 priv
->mac_regs
= (struct pch_gbe_regs
*)iobase
;
455 /* Read MAC address from SROM and initialize dev->enetaddr with it */
456 pch_gbe_mac_read(priv
->mac_regs
, plat
->enetaddr
);
458 plat
->phy_interface
= PHY_INTERFACE_MODE_RGMII
;
459 pch_gbe_mdio_init(dev
->name
, priv
->mac_regs
);
460 priv
->bus
= miiphy_get_dev_by_name(dev
->name
);
462 err
= pch_gbe_reset(dev
);
466 return pch_gbe_phy_init(dev
);
469 static int pch_gbe_remove(struct udevice
*dev
)
471 struct pch_gbe_priv
*priv
= dev_get_priv(dev
);
474 mdio_unregister(priv
->bus
);
475 mdio_free(priv
->bus
);
480 static const struct eth_ops pch_gbe_ops
= {
481 .start
= pch_gbe_start
,
482 .send
= pch_gbe_send
,
483 .recv
= pch_gbe_recv
,
484 .free_pkt
= pch_gbe_free_pkt
,
485 .stop
= pch_gbe_stop
,
488 static const struct udevice_id pch_gbe_ids
[] = {
489 { .compatible
= "intel,pch-gbe" },
493 U_BOOT_DRIVER(eth_pch_gbe
) = {
496 .of_match
= pch_gbe_ids
,
497 .probe
= pch_gbe_probe
,
498 .remove
= pch_gbe_remove
,
500 .priv_auto_alloc_size
= sizeof(struct pch_gbe_priv
),
501 .platdata_auto_alloc_size
= sizeof(struct eth_pdata
),
502 .flags
= DM_FLAG_ALLOC_PRIV_DMA
,
505 U_BOOT_PCI_DEVICE(eth_pch_gbe
, supported
);