xref: /openbmc/linux/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c (revision b9663b7ca6ff780555108394c9c1b409f63b99a7)
158da0cfaSVoon Weifeng // SPDX-License-Identifier: GPL-2.0
258da0cfaSVoon Weifeng /* Copyright (c) 2020, Intel Corporation
358da0cfaSVoon Weifeng  */
458da0cfaSVoon Weifeng 
558da0cfaSVoon Weifeng #include <linux/clk-provider.h>
658da0cfaSVoon Weifeng #include <linux/pci.h>
758da0cfaSVoon Weifeng #include <linux/dmi.h>
8*b9663b7cSVoon Weifeng #include "dwmac-intel.h"
958da0cfaSVoon Weifeng #include "stmmac.h"
1058da0cfaSVoon Weifeng 
11*b9663b7cSVoon Weifeng struct intel_priv_data {
12*b9663b7cSVoon Weifeng 	int mdio_adhoc_addr;	/* mdio address for serdes & etc */
13*b9663b7cSVoon Weifeng };
14*b9663b7cSVoon Weifeng 
1558da0cfaSVoon Weifeng /* This struct is used to associate PCI Function of MAC controller on a board,
1658da0cfaSVoon Weifeng  * discovered via DMI, with the address of PHY connected to the MAC. The
1758da0cfaSVoon Weifeng  * negative value of the address means that MAC controller is not connected
1858da0cfaSVoon Weifeng  * with PHY.
1958da0cfaSVoon Weifeng  */
2058da0cfaSVoon Weifeng struct stmmac_pci_func_data {
2158da0cfaSVoon Weifeng 	unsigned int func;
2258da0cfaSVoon Weifeng 	int phy_addr;
2358da0cfaSVoon Weifeng };
2458da0cfaSVoon Weifeng 
2558da0cfaSVoon Weifeng struct stmmac_pci_dmi_data {
2658da0cfaSVoon Weifeng 	const struct stmmac_pci_func_data *func;
2758da0cfaSVoon Weifeng 	size_t nfuncs;
2858da0cfaSVoon Weifeng };
2958da0cfaSVoon Weifeng 
3058da0cfaSVoon Weifeng struct stmmac_pci_info {
3158da0cfaSVoon Weifeng 	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
3258da0cfaSVoon Weifeng };
3358da0cfaSVoon Weifeng 
3458da0cfaSVoon Weifeng static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
3558da0cfaSVoon Weifeng 				    const struct dmi_system_id *dmi_list)
3658da0cfaSVoon Weifeng {
3758da0cfaSVoon Weifeng 	const struct stmmac_pci_func_data *func_data;
3858da0cfaSVoon Weifeng 	const struct stmmac_pci_dmi_data *dmi_data;
3958da0cfaSVoon Weifeng 	const struct dmi_system_id *dmi_id;
4058da0cfaSVoon Weifeng 	int func = PCI_FUNC(pdev->devfn);
4158da0cfaSVoon Weifeng 	size_t n;
4258da0cfaSVoon Weifeng 
4358da0cfaSVoon Weifeng 	dmi_id = dmi_first_match(dmi_list);
4458da0cfaSVoon Weifeng 	if (!dmi_id)
4558da0cfaSVoon Weifeng 		return -ENODEV;
4658da0cfaSVoon Weifeng 
4758da0cfaSVoon Weifeng 	dmi_data = dmi_id->driver_data;
4858da0cfaSVoon Weifeng 	func_data = dmi_data->func;
4958da0cfaSVoon Weifeng 
5058da0cfaSVoon Weifeng 	for (n = 0; n < dmi_data->nfuncs; n++, func_data++)
5158da0cfaSVoon Weifeng 		if (func_data->func == func)
5258da0cfaSVoon Weifeng 			return func_data->phy_addr;
5358da0cfaSVoon Weifeng 
5458da0cfaSVoon Weifeng 	return -ENODEV;
5558da0cfaSVoon Weifeng }
5658da0cfaSVoon Weifeng 
57*b9663b7cSVoon Weifeng static int serdes_status_poll(struct stmmac_priv *priv, int phyaddr,
58*b9663b7cSVoon Weifeng 			      int phyreg, u32 mask, u32 val)
59*b9663b7cSVoon Weifeng {
60*b9663b7cSVoon Weifeng 	unsigned int retries = 10;
61*b9663b7cSVoon Weifeng 	int val_rd;
62*b9663b7cSVoon Weifeng 
63*b9663b7cSVoon Weifeng 	do {
64*b9663b7cSVoon Weifeng 		val_rd = mdiobus_read(priv->mii, phyaddr, phyreg);
65*b9663b7cSVoon Weifeng 		if ((val_rd & mask) == (val & mask))
66*b9663b7cSVoon Weifeng 			return 0;
67*b9663b7cSVoon Weifeng 		udelay(POLL_DELAY_US);
68*b9663b7cSVoon Weifeng 	} while (--retries);
69*b9663b7cSVoon Weifeng 
70*b9663b7cSVoon Weifeng 	return -ETIMEDOUT;
71*b9663b7cSVoon Weifeng }
72*b9663b7cSVoon Weifeng 
73*b9663b7cSVoon Weifeng static int intel_serdes_powerup(struct net_device *ndev, void *priv_data)
74*b9663b7cSVoon Weifeng {
75*b9663b7cSVoon Weifeng 	struct intel_priv_data *intel_priv = priv_data;
76*b9663b7cSVoon Weifeng 	struct stmmac_priv *priv = netdev_priv(ndev);
77*b9663b7cSVoon Weifeng 	int serdes_phy_addr = 0;
78*b9663b7cSVoon Weifeng 	u32 data = 0;
79*b9663b7cSVoon Weifeng 
80*b9663b7cSVoon Weifeng 	if (!intel_priv->mdio_adhoc_addr)
81*b9663b7cSVoon Weifeng 		return 0;
82*b9663b7cSVoon Weifeng 
83*b9663b7cSVoon Weifeng 	serdes_phy_addr = intel_priv->mdio_adhoc_addr;
84*b9663b7cSVoon Weifeng 
85*b9663b7cSVoon Weifeng 	/* assert clk_req */
86*b9663b7cSVoon Weifeng 	data = mdiobus_read(priv->mii, serdes_phy_addr,
87*b9663b7cSVoon Weifeng 			    SERDES_GCR0);
88*b9663b7cSVoon Weifeng 
89*b9663b7cSVoon Weifeng 	data |= SERDES_PLL_CLK;
90*b9663b7cSVoon Weifeng 
91*b9663b7cSVoon Weifeng 	mdiobus_write(priv->mii, serdes_phy_addr,
92*b9663b7cSVoon Weifeng 		      SERDES_GCR0, data);
93*b9663b7cSVoon Weifeng 
94*b9663b7cSVoon Weifeng 	/* check for clk_ack assertion */
95*b9663b7cSVoon Weifeng 	data = serdes_status_poll(priv, serdes_phy_addr,
96*b9663b7cSVoon Weifeng 				  SERDES_GSR0,
97*b9663b7cSVoon Weifeng 				  SERDES_PLL_CLK,
98*b9663b7cSVoon Weifeng 				  SERDES_PLL_CLK);
99*b9663b7cSVoon Weifeng 
100*b9663b7cSVoon Weifeng 	if (data) {
101*b9663b7cSVoon Weifeng 		dev_err(priv->device, "Serdes PLL clk request timeout\n");
102*b9663b7cSVoon Weifeng 		return data;
103*b9663b7cSVoon Weifeng 	}
104*b9663b7cSVoon Weifeng 
105*b9663b7cSVoon Weifeng 	/* assert lane reset */
106*b9663b7cSVoon Weifeng 	data = mdiobus_read(priv->mii, serdes_phy_addr,
107*b9663b7cSVoon Weifeng 			    SERDES_GCR0);
108*b9663b7cSVoon Weifeng 
109*b9663b7cSVoon Weifeng 	data |= SERDES_RST;
110*b9663b7cSVoon Weifeng 
111*b9663b7cSVoon Weifeng 	mdiobus_write(priv->mii, serdes_phy_addr,
112*b9663b7cSVoon Weifeng 		      SERDES_GCR0, data);
113*b9663b7cSVoon Weifeng 
114*b9663b7cSVoon Weifeng 	/* check for assert lane reset reflection */
115*b9663b7cSVoon Weifeng 	data = serdes_status_poll(priv, serdes_phy_addr,
116*b9663b7cSVoon Weifeng 				  SERDES_GSR0,
117*b9663b7cSVoon Weifeng 				  SERDES_RST,
118*b9663b7cSVoon Weifeng 				  SERDES_RST);
119*b9663b7cSVoon Weifeng 
120*b9663b7cSVoon Weifeng 	if (data) {
121*b9663b7cSVoon Weifeng 		dev_err(priv->device, "Serdes assert lane reset timeout\n");
122*b9663b7cSVoon Weifeng 		return data;
123*b9663b7cSVoon Weifeng 	}
124*b9663b7cSVoon Weifeng 
125*b9663b7cSVoon Weifeng 	/*  move power state to P0 */
126*b9663b7cSVoon Weifeng 	data = mdiobus_read(priv->mii, serdes_phy_addr,
127*b9663b7cSVoon Weifeng 			    SERDES_GCR0);
128*b9663b7cSVoon Weifeng 
129*b9663b7cSVoon Weifeng 	data &= ~SERDES_PWR_ST_MASK;
130*b9663b7cSVoon Weifeng 	data |= SERDES_PWR_ST_P0 << SERDES_PWR_ST_SHIFT;
131*b9663b7cSVoon Weifeng 
132*b9663b7cSVoon Weifeng 	mdiobus_write(priv->mii, serdes_phy_addr,
133*b9663b7cSVoon Weifeng 		      SERDES_GCR0, data);
134*b9663b7cSVoon Weifeng 
135*b9663b7cSVoon Weifeng 	/* Check for P0 state */
136*b9663b7cSVoon Weifeng 	data = serdes_status_poll(priv, serdes_phy_addr,
137*b9663b7cSVoon Weifeng 				  SERDES_GSR0,
138*b9663b7cSVoon Weifeng 				  SERDES_PWR_ST_MASK,
139*b9663b7cSVoon Weifeng 				  SERDES_PWR_ST_P0 << SERDES_PWR_ST_SHIFT);
140*b9663b7cSVoon Weifeng 
141*b9663b7cSVoon Weifeng 	if (data) {
142*b9663b7cSVoon Weifeng 		dev_err(priv->device, "Serdes power state P0 timeout.\n");
143*b9663b7cSVoon Weifeng 		return data;
144*b9663b7cSVoon Weifeng 	}
145*b9663b7cSVoon Weifeng 
146*b9663b7cSVoon Weifeng 	return 0;
147*b9663b7cSVoon Weifeng }
148*b9663b7cSVoon Weifeng 
149*b9663b7cSVoon Weifeng static void intel_serdes_powerdown(struct net_device *ndev, void *intel_data)
150*b9663b7cSVoon Weifeng {
151*b9663b7cSVoon Weifeng 	struct intel_priv_data *intel_priv = intel_data;
152*b9663b7cSVoon Weifeng 	struct stmmac_priv *priv = netdev_priv(ndev);
153*b9663b7cSVoon Weifeng 	int serdes_phy_addr = 0;
154*b9663b7cSVoon Weifeng 	u32 data = 0;
155*b9663b7cSVoon Weifeng 
156*b9663b7cSVoon Weifeng 	if (!intel_priv->mdio_adhoc_addr)
157*b9663b7cSVoon Weifeng 		return;
158*b9663b7cSVoon Weifeng 
159*b9663b7cSVoon Weifeng 	serdes_phy_addr = intel_priv->mdio_adhoc_addr;
160*b9663b7cSVoon Weifeng 
161*b9663b7cSVoon Weifeng 	/*  move power state to P3 */
162*b9663b7cSVoon Weifeng 	data = mdiobus_read(priv->mii, serdes_phy_addr,
163*b9663b7cSVoon Weifeng 			    SERDES_GCR0);
164*b9663b7cSVoon Weifeng 
165*b9663b7cSVoon Weifeng 	data &= ~SERDES_PWR_ST_MASK;
166*b9663b7cSVoon Weifeng 	data |= SERDES_PWR_ST_P3 << SERDES_PWR_ST_SHIFT;
167*b9663b7cSVoon Weifeng 
168*b9663b7cSVoon Weifeng 	mdiobus_write(priv->mii, serdes_phy_addr,
169*b9663b7cSVoon Weifeng 		      SERDES_GCR0, data);
170*b9663b7cSVoon Weifeng 
171*b9663b7cSVoon Weifeng 	/* Check for P3 state */
172*b9663b7cSVoon Weifeng 	data = serdes_status_poll(priv, serdes_phy_addr,
173*b9663b7cSVoon Weifeng 				  SERDES_GSR0,
174*b9663b7cSVoon Weifeng 				  SERDES_PWR_ST_MASK,
175*b9663b7cSVoon Weifeng 				  SERDES_PWR_ST_P3 << SERDES_PWR_ST_SHIFT);
176*b9663b7cSVoon Weifeng 
177*b9663b7cSVoon Weifeng 	if (data) {
178*b9663b7cSVoon Weifeng 		dev_err(priv->device, "Serdes power state P3 timeout\n");
179*b9663b7cSVoon Weifeng 		return;
180*b9663b7cSVoon Weifeng 	}
181*b9663b7cSVoon Weifeng 
182*b9663b7cSVoon Weifeng 	/* de-assert clk_req */
183*b9663b7cSVoon Weifeng 	data = mdiobus_read(priv->mii, serdes_phy_addr,
184*b9663b7cSVoon Weifeng 			    SERDES_GCR0);
185*b9663b7cSVoon Weifeng 
186*b9663b7cSVoon Weifeng 	data &= ~SERDES_PLL_CLK;
187*b9663b7cSVoon Weifeng 
188*b9663b7cSVoon Weifeng 	mdiobus_write(priv->mii, serdes_phy_addr,
189*b9663b7cSVoon Weifeng 		      SERDES_GCR0, data);
190*b9663b7cSVoon Weifeng 
191*b9663b7cSVoon Weifeng 	/* check for clk_ack de-assert */
192*b9663b7cSVoon Weifeng 	data = serdes_status_poll(priv, serdes_phy_addr,
193*b9663b7cSVoon Weifeng 				  SERDES_GSR0,
194*b9663b7cSVoon Weifeng 				  SERDES_PLL_CLK,
195*b9663b7cSVoon Weifeng 				  (u32)~SERDES_PLL_CLK);
196*b9663b7cSVoon Weifeng 
197*b9663b7cSVoon Weifeng 	if (data) {
198*b9663b7cSVoon Weifeng 		dev_err(priv->device, "Serdes PLL clk de-assert timeout\n");
199*b9663b7cSVoon Weifeng 		return;
200*b9663b7cSVoon Weifeng 	}
201*b9663b7cSVoon Weifeng 
202*b9663b7cSVoon Weifeng 	/* de-assert lane reset */
203*b9663b7cSVoon Weifeng 	data = mdiobus_read(priv->mii, serdes_phy_addr,
204*b9663b7cSVoon Weifeng 			    SERDES_GCR0);
205*b9663b7cSVoon Weifeng 
206*b9663b7cSVoon Weifeng 	data &= ~SERDES_RST;
207*b9663b7cSVoon Weifeng 
208*b9663b7cSVoon Weifeng 	mdiobus_write(priv->mii, serdes_phy_addr,
209*b9663b7cSVoon Weifeng 		      SERDES_GCR0, data);
210*b9663b7cSVoon Weifeng 
211*b9663b7cSVoon Weifeng 	/* check for de-assert lane reset reflection */
212*b9663b7cSVoon Weifeng 	data = serdes_status_poll(priv, serdes_phy_addr,
213*b9663b7cSVoon Weifeng 				  SERDES_GSR0,
214*b9663b7cSVoon Weifeng 				  SERDES_RST,
215*b9663b7cSVoon Weifeng 				  (u32)~SERDES_RST);
216*b9663b7cSVoon Weifeng 
217*b9663b7cSVoon Weifeng 	if (data) {
218*b9663b7cSVoon Weifeng 		dev_err(priv->device, "Serdes de-assert lane reset timeout\n");
219*b9663b7cSVoon Weifeng 		return;
220*b9663b7cSVoon Weifeng 	}
221*b9663b7cSVoon Weifeng }
222*b9663b7cSVoon Weifeng 
22358da0cfaSVoon Weifeng static void common_default_data(struct plat_stmmacenet_data *plat)
22458da0cfaSVoon Weifeng {
22558da0cfaSVoon Weifeng 	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
22658da0cfaSVoon Weifeng 	plat->has_gmac = 1;
22758da0cfaSVoon Weifeng 	plat->force_sf_dma_mode = 1;
22858da0cfaSVoon Weifeng 
22958da0cfaSVoon Weifeng 	plat->mdio_bus_data->needs_reset = true;
23058da0cfaSVoon Weifeng 
23158da0cfaSVoon Weifeng 	/* Set default value for multicast hash bins */
23258da0cfaSVoon Weifeng 	plat->multicast_filter_bins = HASH_TABLE_SIZE;
23358da0cfaSVoon Weifeng 
23458da0cfaSVoon Weifeng 	/* Set default value for unicast filter entries */
23558da0cfaSVoon Weifeng 	plat->unicast_filter_entries = 1;
23658da0cfaSVoon Weifeng 
23758da0cfaSVoon Weifeng 	/* Set the maxmtu to a default of JUMBO_LEN */
23858da0cfaSVoon Weifeng 	plat->maxmtu = JUMBO_LEN;
23958da0cfaSVoon Weifeng 
24058da0cfaSVoon Weifeng 	/* Set default number of RX and TX queues to use */
24158da0cfaSVoon Weifeng 	plat->tx_queues_to_use = 1;
24258da0cfaSVoon Weifeng 	plat->rx_queues_to_use = 1;
24358da0cfaSVoon Weifeng 
24458da0cfaSVoon Weifeng 	/* Disable Priority config by default */
24558da0cfaSVoon Weifeng 	plat->tx_queues_cfg[0].use_prio = false;
24658da0cfaSVoon Weifeng 	plat->rx_queues_cfg[0].use_prio = false;
24758da0cfaSVoon Weifeng 
24858da0cfaSVoon Weifeng 	/* Disable RX queues routing by default */
24958da0cfaSVoon Weifeng 	plat->rx_queues_cfg[0].pkt_route = 0x0;
25058da0cfaSVoon Weifeng }
25158da0cfaSVoon Weifeng 
25258da0cfaSVoon Weifeng static int intel_mgbe_common_data(struct pci_dev *pdev,
25358da0cfaSVoon Weifeng 				  struct plat_stmmacenet_data *plat)
25458da0cfaSVoon Weifeng {
25558da0cfaSVoon Weifeng 	int i;
25658da0cfaSVoon Weifeng 
25758da0cfaSVoon Weifeng 	plat->clk_csr = 5;
25858da0cfaSVoon Weifeng 	plat->has_gmac = 0;
25958da0cfaSVoon Weifeng 	plat->has_gmac4 = 1;
26058da0cfaSVoon Weifeng 	plat->force_sf_dma_mode = 0;
26158da0cfaSVoon Weifeng 	plat->tso_en = 1;
26258da0cfaSVoon Weifeng 
26358da0cfaSVoon Weifeng 	plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
26458da0cfaSVoon Weifeng 
26558da0cfaSVoon Weifeng 	for (i = 0; i < plat->rx_queues_to_use; i++) {
26658da0cfaSVoon Weifeng 		plat->rx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB;
26758da0cfaSVoon Weifeng 		plat->rx_queues_cfg[i].chan = i;
26858da0cfaSVoon Weifeng 
26958da0cfaSVoon Weifeng 		/* Disable Priority config by default */
27058da0cfaSVoon Weifeng 		plat->rx_queues_cfg[i].use_prio = false;
27158da0cfaSVoon Weifeng 
27258da0cfaSVoon Weifeng 		/* Disable RX queues routing by default */
27358da0cfaSVoon Weifeng 		plat->rx_queues_cfg[i].pkt_route = 0x0;
27458da0cfaSVoon Weifeng 	}
27558da0cfaSVoon Weifeng 
27658da0cfaSVoon Weifeng 	for (i = 0; i < plat->tx_queues_to_use; i++) {
27758da0cfaSVoon Weifeng 		plat->tx_queues_cfg[i].mode_to_use = MTL_QUEUE_DCB;
27858da0cfaSVoon Weifeng 
27958da0cfaSVoon Weifeng 		/* Disable Priority config by default */
28058da0cfaSVoon Weifeng 		plat->tx_queues_cfg[i].use_prio = false;
28158da0cfaSVoon Weifeng 	}
28258da0cfaSVoon Weifeng 
28358da0cfaSVoon Weifeng 	/* FIFO size is 4096 bytes for 1 tx/rx queue */
28458da0cfaSVoon Weifeng 	plat->tx_fifo_size = plat->tx_queues_to_use * 4096;
28558da0cfaSVoon Weifeng 	plat->rx_fifo_size = plat->rx_queues_to_use * 4096;
28658da0cfaSVoon Weifeng 
28758da0cfaSVoon Weifeng 	plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WRR;
28858da0cfaSVoon Weifeng 	plat->tx_queues_cfg[0].weight = 0x09;
28958da0cfaSVoon Weifeng 	plat->tx_queues_cfg[1].weight = 0x0A;
29058da0cfaSVoon Weifeng 	plat->tx_queues_cfg[2].weight = 0x0B;
29158da0cfaSVoon Weifeng 	plat->tx_queues_cfg[3].weight = 0x0C;
29258da0cfaSVoon Weifeng 	plat->tx_queues_cfg[4].weight = 0x0D;
29358da0cfaSVoon Weifeng 	plat->tx_queues_cfg[5].weight = 0x0E;
29458da0cfaSVoon Weifeng 	plat->tx_queues_cfg[6].weight = 0x0F;
29558da0cfaSVoon Weifeng 	plat->tx_queues_cfg[7].weight = 0x10;
29658da0cfaSVoon Weifeng 
29758da0cfaSVoon Weifeng 	plat->dma_cfg->pbl = 32;
29858da0cfaSVoon Weifeng 	plat->dma_cfg->pblx8 = true;
29958da0cfaSVoon Weifeng 	plat->dma_cfg->fixed_burst = 0;
30058da0cfaSVoon Weifeng 	plat->dma_cfg->mixed_burst = 0;
30158da0cfaSVoon Weifeng 	plat->dma_cfg->aal = 0;
30258da0cfaSVoon Weifeng 
30358da0cfaSVoon Weifeng 	plat->axi = devm_kzalloc(&pdev->dev, sizeof(*plat->axi),
30458da0cfaSVoon Weifeng 				 GFP_KERNEL);
30558da0cfaSVoon Weifeng 	if (!plat->axi)
30658da0cfaSVoon Weifeng 		return -ENOMEM;
30758da0cfaSVoon Weifeng 
30858da0cfaSVoon Weifeng 	plat->axi->axi_lpi_en = 0;
30958da0cfaSVoon Weifeng 	plat->axi->axi_xit_frm = 0;
31058da0cfaSVoon Weifeng 	plat->axi->axi_wr_osr_lmt = 1;
31158da0cfaSVoon Weifeng 	plat->axi->axi_rd_osr_lmt = 1;
31258da0cfaSVoon Weifeng 	plat->axi->axi_blen[0] = 4;
31358da0cfaSVoon Weifeng 	plat->axi->axi_blen[1] = 8;
31458da0cfaSVoon Weifeng 	plat->axi->axi_blen[2] = 16;
31558da0cfaSVoon Weifeng 
31658da0cfaSVoon Weifeng 	plat->ptp_max_adj = plat->clk_ptp_rate;
31758da0cfaSVoon Weifeng 
31858da0cfaSVoon Weifeng 	/* Set system clock */
31958da0cfaSVoon Weifeng 	plat->stmmac_clk = clk_register_fixed_rate(&pdev->dev,
32058da0cfaSVoon Weifeng 						   "stmmac-clk", NULL, 0,
32158da0cfaSVoon Weifeng 						   plat->clk_ptp_rate);
32258da0cfaSVoon Weifeng 
32358da0cfaSVoon Weifeng 	if (IS_ERR(plat->stmmac_clk)) {
32458da0cfaSVoon Weifeng 		dev_warn(&pdev->dev, "Fail to register stmmac-clk\n");
32558da0cfaSVoon Weifeng 		plat->stmmac_clk = NULL;
32658da0cfaSVoon Weifeng 	}
32758da0cfaSVoon Weifeng 	clk_prepare_enable(plat->stmmac_clk);
32858da0cfaSVoon Weifeng 
32958da0cfaSVoon Weifeng 	/* Set default value for multicast hash bins */
33058da0cfaSVoon Weifeng 	plat->multicast_filter_bins = HASH_TABLE_SIZE;
33158da0cfaSVoon Weifeng 
33258da0cfaSVoon Weifeng 	/* Set default value for unicast filter entries */
33358da0cfaSVoon Weifeng 	plat->unicast_filter_entries = 1;
33458da0cfaSVoon Weifeng 
33558da0cfaSVoon Weifeng 	/* Set the maxmtu to a default of JUMBO_LEN */
33658da0cfaSVoon Weifeng 	plat->maxmtu = JUMBO_LEN;
33758da0cfaSVoon Weifeng 
33858da0cfaSVoon Weifeng 	return 0;
33958da0cfaSVoon Weifeng }
34058da0cfaSVoon Weifeng 
34158da0cfaSVoon Weifeng static int ehl_common_data(struct pci_dev *pdev,
34258da0cfaSVoon Weifeng 			   struct plat_stmmacenet_data *plat)
34358da0cfaSVoon Weifeng {
34458da0cfaSVoon Weifeng 	int ret;
34558da0cfaSVoon Weifeng 
34658da0cfaSVoon Weifeng 	plat->rx_queues_to_use = 8;
34758da0cfaSVoon Weifeng 	plat->tx_queues_to_use = 8;
34858da0cfaSVoon Weifeng 	plat->clk_ptp_rate = 200000000;
34958da0cfaSVoon Weifeng 	ret = intel_mgbe_common_data(pdev, plat);
35058da0cfaSVoon Weifeng 	if (ret)
35158da0cfaSVoon Weifeng 		return ret;
35258da0cfaSVoon Weifeng 
35358da0cfaSVoon Weifeng 	return 0;
35458da0cfaSVoon Weifeng }
35558da0cfaSVoon Weifeng 
35658da0cfaSVoon Weifeng static int ehl_sgmii_data(struct pci_dev *pdev,
35758da0cfaSVoon Weifeng 			  struct plat_stmmacenet_data *plat)
35858da0cfaSVoon Weifeng {
35958da0cfaSVoon Weifeng 	plat->bus_id = 1;
36058da0cfaSVoon Weifeng 	plat->phy_addr = 0;
36158da0cfaSVoon Weifeng 	plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
36258da0cfaSVoon Weifeng 
363*b9663b7cSVoon Weifeng 	plat->serdes_powerup = intel_serdes_powerup;
364*b9663b7cSVoon Weifeng 	plat->serdes_powerdown = intel_serdes_powerdown;
365*b9663b7cSVoon Weifeng 
36658da0cfaSVoon Weifeng 	return ehl_common_data(pdev, plat);
36758da0cfaSVoon Weifeng }
36858da0cfaSVoon Weifeng 
36958da0cfaSVoon Weifeng static struct stmmac_pci_info ehl_sgmii1g_pci_info = {
37058da0cfaSVoon Weifeng 	.setup = ehl_sgmii_data,
37158da0cfaSVoon Weifeng };
37258da0cfaSVoon Weifeng 
37358da0cfaSVoon Weifeng static int ehl_rgmii_data(struct pci_dev *pdev,
37458da0cfaSVoon Weifeng 			  struct plat_stmmacenet_data *plat)
37558da0cfaSVoon Weifeng {
37658da0cfaSVoon Weifeng 	plat->bus_id = 1;
37758da0cfaSVoon Weifeng 	plat->phy_addr = 0;
37858da0cfaSVoon Weifeng 	plat->phy_interface = PHY_INTERFACE_MODE_RGMII;
37958da0cfaSVoon Weifeng 
38058da0cfaSVoon Weifeng 	return ehl_common_data(pdev, plat);
38158da0cfaSVoon Weifeng }
38258da0cfaSVoon Weifeng 
38358da0cfaSVoon Weifeng static struct stmmac_pci_info ehl_rgmii1g_pci_info = {
38458da0cfaSVoon Weifeng 	.setup = ehl_rgmii_data,
38558da0cfaSVoon Weifeng };
38658da0cfaSVoon Weifeng 
38767c08ac4SVoon Weifeng static int ehl_pse0_common_data(struct pci_dev *pdev,
38867c08ac4SVoon Weifeng 				struct plat_stmmacenet_data *plat)
38967c08ac4SVoon Weifeng {
39067c08ac4SVoon Weifeng 	plat->bus_id = 2;
39167c08ac4SVoon Weifeng 	plat->phy_addr = 1;
39267c08ac4SVoon Weifeng 	return ehl_common_data(pdev, plat);
39367c08ac4SVoon Weifeng }
39467c08ac4SVoon Weifeng 
39567c08ac4SVoon Weifeng static int ehl_pse0_rgmii1g_data(struct pci_dev *pdev,
39667c08ac4SVoon Weifeng 				 struct plat_stmmacenet_data *plat)
39767c08ac4SVoon Weifeng {
39867c08ac4SVoon Weifeng 	plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
39967c08ac4SVoon Weifeng 	return ehl_pse0_common_data(pdev, plat);
40067c08ac4SVoon Weifeng }
40167c08ac4SVoon Weifeng 
40267c08ac4SVoon Weifeng static struct stmmac_pci_info ehl_pse0_rgmii1g_pci_info = {
40367c08ac4SVoon Weifeng 	.setup = ehl_pse0_rgmii1g_data,
40467c08ac4SVoon Weifeng };
40567c08ac4SVoon Weifeng 
40667c08ac4SVoon Weifeng static int ehl_pse0_sgmii1g_data(struct pci_dev *pdev,
40767c08ac4SVoon Weifeng 				 struct plat_stmmacenet_data *plat)
40867c08ac4SVoon Weifeng {
40967c08ac4SVoon Weifeng 	plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
410*b9663b7cSVoon Weifeng 	plat->serdes_powerup = intel_serdes_powerup;
411*b9663b7cSVoon Weifeng 	plat->serdes_powerdown = intel_serdes_powerdown;
41267c08ac4SVoon Weifeng 	return ehl_pse0_common_data(pdev, plat);
41367c08ac4SVoon Weifeng }
41467c08ac4SVoon Weifeng 
41567c08ac4SVoon Weifeng static struct stmmac_pci_info ehl_pse0_sgmii1g_pci_info = {
41667c08ac4SVoon Weifeng 	.setup = ehl_pse0_sgmii1g_data,
41767c08ac4SVoon Weifeng };
41867c08ac4SVoon Weifeng 
41967c08ac4SVoon Weifeng static int ehl_pse1_common_data(struct pci_dev *pdev,
42067c08ac4SVoon Weifeng 				struct plat_stmmacenet_data *plat)
42167c08ac4SVoon Weifeng {
42267c08ac4SVoon Weifeng 	plat->bus_id = 3;
42367c08ac4SVoon Weifeng 	plat->phy_addr = 1;
42467c08ac4SVoon Weifeng 	return ehl_common_data(pdev, plat);
42567c08ac4SVoon Weifeng }
42667c08ac4SVoon Weifeng 
42767c08ac4SVoon Weifeng static int ehl_pse1_rgmii1g_data(struct pci_dev *pdev,
42867c08ac4SVoon Weifeng 				 struct plat_stmmacenet_data *plat)
42967c08ac4SVoon Weifeng {
43067c08ac4SVoon Weifeng 	plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
43167c08ac4SVoon Weifeng 	return ehl_pse1_common_data(pdev, plat);
43267c08ac4SVoon Weifeng }
43367c08ac4SVoon Weifeng 
43467c08ac4SVoon Weifeng static struct stmmac_pci_info ehl_pse1_rgmii1g_pci_info = {
43567c08ac4SVoon Weifeng 	.setup = ehl_pse1_rgmii1g_data,
43667c08ac4SVoon Weifeng };
43767c08ac4SVoon Weifeng 
43867c08ac4SVoon Weifeng static int ehl_pse1_sgmii1g_data(struct pci_dev *pdev,
43967c08ac4SVoon Weifeng 				 struct plat_stmmacenet_data *plat)
44067c08ac4SVoon Weifeng {
44167c08ac4SVoon Weifeng 	plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
442*b9663b7cSVoon Weifeng 	plat->serdes_powerup = intel_serdes_powerup;
443*b9663b7cSVoon Weifeng 	plat->serdes_powerdown = intel_serdes_powerdown;
44467c08ac4SVoon Weifeng 	return ehl_pse1_common_data(pdev, plat);
44567c08ac4SVoon Weifeng }
44667c08ac4SVoon Weifeng 
44767c08ac4SVoon Weifeng static struct stmmac_pci_info ehl_pse1_sgmii1g_pci_info = {
44867c08ac4SVoon Weifeng 	.setup = ehl_pse1_sgmii1g_data,
44967c08ac4SVoon Weifeng };
45067c08ac4SVoon Weifeng 
45158da0cfaSVoon Weifeng static int tgl_common_data(struct pci_dev *pdev,
45258da0cfaSVoon Weifeng 			   struct plat_stmmacenet_data *plat)
45358da0cfaSVoon Weifeng {
45458da0cfaSVoon Weifeng 	int ret;
45558da0cfaSVoon Weifeng 
45658da0cfaSVoon Weifeng 	plat->rx_queues_to_use = 6;
45758da0cfaSVoon Weifeng 	plat->tx_queues_to_use = 4;
45858da0cfaSVoon Weifeng 	plat->clk_ptp_rate = 200000000;
45958da0cfaSVoon Weifeng 	ret = intel_mgbe_common_data(pdev, plat);
46058da0cfaSVoon Weifeng 	if (ret)
46158da0cfaSVoon Weifeng 		return ret;
46258da0cfaSVoon Weifeng 
46358da0cfaSVoon Weifeng 	return 0;
46458da0cfaSVoon Weifeng }
46558da0cfaSVoon Weifeng 
46658da0cfaSVoon Weifeng static int tgl_sgmii_data(struct pci_dev *pdev,
46758da0cfaSVoon Weifeng 			  struct plat_stmmacenet_data *plat)
46858da0cfaSVoon Weifeng {
46958da0cfaSVoon Weifeng 	plat->bus_id = 1;
47058da0cfaSVoon Weifeng 	plat->phy_addr = 0;
47158da0cfaSVoon Weifeng 	plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
472*b9663b7cSVoon Weifeng 	plat->serdes_powerup = intel_serdes_powerup;
473*b9663b7cSVoon Weifeng 	plat->serdes_powerdown = intel_serdes_powerdown;
47458da0cfaSVoon Weifeng 	return tgl_common_data(pdev, plat);
47558da0cfaSVoon Weifeng }
47658da0cfaSVoon Weifeng 
47758da0cfaSVoon Weifeng static struct stmmac_pci_info tgl_sgmii1g_pci_info = {
47858da0cfaSVoon Weifeng 	.setup = tgl_sgmii_data,
47958da0cfaSVoon Weifeng };
48058da0cfaSVoon Weifeng 
48158da0cfaSVoon Weifeng static const struct stmmac_pci_func_data galileo_stmmac_func_data[] = {
48258da0cfaSVoon Weifeng 	{
48358da0cfaSVoon Weifeng 		.func = 6,
48458da0cfaSVoon Weifeng 		.phy_addr = 1,
48558da0cfaSVoon Weifeng 	},
48658da0cfaSVoon Weifeng };
48758da0cfaSVoon Weifeng 
48858da0cfaSVoon Weifeng static const struct stmmac_pci_dmi_data galileo_stmmac_dmi_data = {
48958da0cfaSVoon Weifeng 	.func = galileo_stmmac_func_data,
49058da0cfaSVoon Weifeng 	.nfuncs = ARRAY_SIZE(galileo_stmmac_func_data),
49158da0cfaSVoon Weifeng };
49258da0cfaSVoon Weifeng 
49358da0cfaSVoon Weifeng static const struct stmmac_pci_func_data iot2040_stmmac_func_data[] = {
49458da0cfaSVoon Weifeng 	{
49558da0cfaSVoon Weifeng 		.func = 6,
49658da0cfaSVoon Weifeng 		.phy_addr = 1,
49758da0cfaSVoon Weifeng 	},
49858da0cfaSVoon Weifeng 	{
49958da0cfaSVoon Weifeng 		.func = 7,
50058da0cfaSVoon Weifeng 		.phy_addr = 1,
50158da0cfaSVoon Weifeng 	},
50258da0cfaSVoon Weifeng };
50358da0cfaSVoon Weifeng 
50458da0cfaSVoon Weifeng static const struct stmmac_pci_dmi_data iot2040_stmmac_dmi_data = {
50558da0cfaSVoon Weifeng 	.func = iot2040_stmmac_func_data,
50658da0cfaSVoon Weifeng 	.nfuncs = ARRAY_SIZE(iot2040_stmmac_func_data),
50758da0cfaSVoon Weifeng };
50858da0cfaSVoon Weifeng 
50958da0cfaSVoon Weifeng static const struct dmi_system_id quark_pci_dmi[] = {
51058da0cfaSVoon Weifeng 	{
51158da0cfaSVoon Weifeng 		.matches = {
51258da0cfaSVoon Weifeng 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "Galileo"),
51358da0cfaSVoon Weifeng 		},
51458da0cfaSVoon Weifeng 		.driver_data = (void *)&galileo_stmmac_dmi_data,
51558da0cfaSVoon Weifeng 	},
51658da0cfaSVoon Weifeng 	{
51758da0cfaSVoon Weifeng 		.matches = {
51858da0cfaSVoon Weifeng 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"),
51958da0cfaSVoon Weifeng 		},
52058da0cfaSVoon Weifeng 		.driver_data = (void *)&galileo_stmmac_dmi_data,
52158da0cfaSVoon Weifeng 	},
52258da0cfaSVoon Weifeng 	/* There are 2 types of SIMATIC IOT2000: IOT2020 and IOT2040.
52358da0cfaSVoon Weifeng 	 * The asset tag "6ES7647-0AA00-0YA2" is only for IOT2020 which
52458da0cfaSVoon Weifeng 	 * has only one pci network device while other asset tags are
52558da0cfaSVoon Weifeng 	 * for IOT2040 which has two.
52658da0cfaSVoon Weifeng 	 */
52758da0cfaSVoon Weifeng 	{
52858da0cfaSVoon Weifeng 		.matches = {
52958da0cfaSVoon Weifeng 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
53058da0cfaSVoon Weifeng 			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
53158da0cfaSVoon Weifeng 					"6ES7647-0AA00-0YA2"),
53258da0cfaSVoon Weifeng 		},
53358da0cfaSVoon Weifeng 		.driver_data = (void *)&galileo_stmmac_dmi_data,
53458da0cfaSVoon Weifeng 	},
53558da0cfaSVoon Weifeng 	{
53658da0cfaSVoon Weifeng 		.matches = {
53758da0cfaSVoon Weifeng 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
53858da0cfaSVoon Weifeng 		},
53958da0cfaSVoon Weifeng 		.driver_data = (void *)&iot2040_stmmac_dmi_data,
54058da0cfaSVoon Weifeng 	},
54158da0cfaSVoon Weifeng 	{}
54258da0cfaSVoon Weifeng };
54358da0cfaSVoon Weifeng 
54458da0cfaSVoon Weifeng static int quark_default_data(struct pci_dev *pdev,
54558da0cfaSVoon Weifeng 			      struct plat_stmmacenet_data *plat)
54658da0cfaSVoon Weifeng {
54758da0cfaSVoon Weifeng 	int ret;
54858da0cfaSVoon Weifeng 
54958da0cfaSVoon Weifeng 	/* Set common default data first */
55058da0cfaSVoon Weifeng 	common_default_data(plat);
55158da0cfaSVoon Weifeng 
55258da0cfaSVoon Weifeng 	/* Refuse to load the driver and register net device if MAC controller
55358da0cfaSVoon Weifeng 	 * does not connect to any PHY interface.
55458da0cfaSVoon Weifeng 	 */
55558da0cfaSVoon Weifeng 	ret = stmmac_pci_find_phy_addr(pdev, quark_pci_dmi);
55658da0cfaSVoon Weifeng 	if (ret < 0) {
55758da0cfaSVoon Weifeng 		/* Return error to the caller on DMI enabled boards. */
55858da0cfaSVoon Weifeng 		if (dmi_get_system_info(DMI_BOARD_NAME))
55958da0cfaSVoon Weifeng 			return ret;
56058da0cfaSVoon Weifeng 
56158da0cfaSVoon Weifeng 		/* Galileo boards with old firmware don't support DMI. We always
56258da0cfaSVoon Weifeng 		 * use 1 here as PHY address, so at least the first found MAC
56358da0cfaSVoon Weifeng 		 * controller would be probed.
56458da0cfaSVoon Weifeng 		 */
56558da0cfaSVoon Weifeng 		ret = 1;
56658da0cfaSVoon Weifeng 	}
56758da0cfaSVoon Weifeng 
56858da0cfaSVoon Weifeng 	plat->bus_id = pci_dev_id(pdev);
56958da0cfaSVoon Weifeng 	plat->phy_addr = ret;
57058da0cfaSVoon Weifeng 	plat->phy_interface = PHY_INTERFACE_MODE_RMII;
57158da0cfaSVoon Weifeng 
57258da0cfaSVoon Weifeng 	plat->dma_cfg->pbl = 16;
57358da0cfaSVoon Weifeng 	plat->dma_cfg->pblx8 = true;
57458da0cfaSVoon Weifeng 	plat->dma_cfg->fixed_burst = 1;
57558da0cfaSVoon Weifeng 	/* AXI (TODO) */
57658da0cfaSVoon Weifeng 
57758da0cfaSVoon Weifeng 	return 0;
57858da0cfaSVoon Weifeng }
57958da0cfaSVoon Weifeng 
58058da0cfaSVoon Weifeng static const struct stmmac_pci_info quark_pci_info = {
58158da0cfaSVoon Weifeng 	.setup = quark_default_data,
58258da0cfaSVoon Weifeng };
58358da0cfaSVoon Weifeng 
58458da0cfaSVoon Weifeng /**
58558da0cfaSVoon Weifeng  * intel_eth_pci_probe
58658da0cfaSVoon Weifeng  *
58758da0cfaSVoon Weifeng  * @pdev: pci device pointer
58858da0cfaSVoon Weifeng  * @id: pointer to table of device id/id's.
58958da0cfaSVoon Weifeng  *
59058da0cfaSVoon Weifeng  * Description: This probing function gets called for all PCI devices which
59158da0cfaSVoon Weifeng  * match the ID table and are not "owned" by other driver yet. This function
59258da0cfaSVoon Weifeng  * gets passed a "struct pci_dev *" for each device whose entry in the ID table
59358da0cfaSVoon Weifeng  * matches the device. The probe functions returns zero when the driver choose
59458da0cfaSVoon Weifeng  * to take "ownership" of the device or an error code(-ve no) otherwise.
59558da0cfaSVoon Weifeng  */
59658da0cfaSVoon Weifeng static int intel_eth_pci_probe(struct pci_dev *pdev,
59758da0cfaSVoon Weifeng 			       const struct pci_device_id *id)
59858da0cfaSVoon Weifeng {
59958da0cfaSVoon Weifeng 	struct stmmac_pci_info *info = (struct stmmac_pci_info *)id->driver_data;
600*b9663b7cSVoon Weifeng 	struct intel_priv_data *intel_priv;
60158da0cfaSVoon Weifeng 	struct plat_stmmacenet_data *plat;
60258da0cfaSVoon Weifeng 	struct stmmac_resources res;
60358da0cfaSVoon Weifeng 	int i;
60458da0cfaSVoon Weifeng 	int ret;
60558da0cfaSVoon Weifeng 
606*b9663b7cSVoon Weifeng 	intel_priv = devm_kzalloc(&pdev->dev, sizeof(*intel_priv),
607*b9663b7cSVoon Weifeng 				  GFP_KERNEL);
608*b9663b7cSVoon Weifeng 	if (!intel_priv)
609*b9663b7cSVoon Weifeng 		return -ENOMEM;
610*b9663b7cSVoon Weifeng 
61158da0cfaSVoon Weifeng 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
61258da0cfaSVoon Weifeng 	if (!plat)
61358da0cfaSVoon Weifeng 		return -ENOMEM;
61458da0cfaSVoon Weifeng 
61558da0cfaSVoon Weifeng 	plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
61658da0cfaSVoon Weifeng 					   sizeof(*plat->mdio_bus_data),
61758da0cfaSVoon Weifeng 					   GFP_KERNEL);
61858da0cfaSVoon Weifeng 	if (!plat->mdio_bus_data)
61958da0cfaSVoon Weifeng 		return -ENOMEM;
62058da0cfaSVoon Weifeng 
62158da0cfaSVoon Weifeng 	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg),
62258da0cfaSVoon Weifeng 				     GFP_KERNEL);
62358da0cfaSVoon Weifeng 	if (!plat->dma_cfg)
62458da0cfaSVoon Weifeng 		return -ENOMEM;
62558da0cfaSVoon Weifeng 
62658da0cfaSVoon Weifeng 	/* Enable pci device */
62758da0cfaSVoon Weifeng 	ret = pci_enable_device(pdev);
62858da0cfaSVoon Weifeng 	if (ret) {
62958da0cfaSVoon Weifeng 		dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n",
63058da0cfaSVoon Weifeng 			__func__);
63158da0cfaSVoon Weifeng 		return ret;
63258da0cfaSVoon Weifeng 	}
63358da0cfaSVoon Weifeng 
63458da0cfaSVoon Weifeng 	/* Get the base address of device */
63558da0cfaSVoon Weifeng 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
63658da0cfaSVoon Weifeng 		if (pci_resource_len(pdev, i) == 0)
63758da0cfaSVoon Weifeng 			continue;
63858da0cfaSVoon Weifeng 		ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev));
63958da0cfaSVoon Weifeng 		if (ret)
64058da0cfaSVoon Weifeng 			return ret;
64158da0cfaSVoon Weifeng 		break;
64258da0cfaSVoon Weifeng 	}
64358da0cfaSVoon Weifeng 
64458da0cfaSVoon Weifeng 	pci_set_master(pdev);
64558da0cfaSVoon Weifeng 
646*b9663b7cSVoon Weifeng 	plat->bsp_priv = intel_priv;
647*b9663b7cSVoon Weifeng 	intel_priv->mdio_adhoc_addr = 0x15;
648*b9663b7cSVoon Weifeng 
64958da0cfaSVoon Weifeng 	ret = info->setup(pdev, plat);
65058da0cfaSVoon Weifeng 	if (ret)
65158da0cfaSVoon Weifeng 		return ret;
65258da0cfaSVoon Weifeng 
65358da0cfaSVoon Weifeng 	pci_enable_msi(pdev);
65458da0cfaSVoon Weifeng 
65558da0cfaSVoon Weifeng 	memset(&res, 0, sizeof(res));
65658da0cfaSVoon Weifeng 	res.addr = pcim_iomap_table(pdev)[i];
65758da0cfaSVoon Weifeng 	res.wol_irq = pdev->irq;
65858da0cfaSVoon Weifeng 	res.irq = pdev->irq;
65958da0cfaSVoon Weifeng 
66058da0cfaSVoon Weifeng 	return stmmac_dvr_probe(&pdev->dev, plat, &res);
66158da0cfaSVoon Weifeng }
66258da0cfaSVoon Weifeng 
66358da0cfaSVoon Weifeng /**
66458da0cfaSVoon Weifeng  * intel_eth_pci_remove
66558da0cfaSVoon Weifeng  *
66658da0cfaSVoon Weifeng  * @pdev: platform device pointer
66758da0cfaSVoon Weifeng  * Description: this function calls the main to free the net resources
66858da0cfaSVoon Weifeng  * and releases the PCI resources.
66958da0cfaSVoon Weifeng  */
67058da0cfaSVoon Weifeng static void intel_eth_pci_remove(struct pci_dev *pdev)
67158da0cfaSVoon Weifeng {
67258da0cfaSVoon Weifeng 	struct net_device *ndev = dev_get_drvdata(&pdev->dev);
67358da0cfaSVoon Weifeng 	struct stmmac_priv *priv = netdev_priv(ndev);
67458da0cfaSVoon Weifeng 	int i;
67558da0cfaSVoon Weifeng 
67658da0cfaSVoon Weifeng 	stmmac_dvr_remove(&pdev->dev);
67758da0cfaSVoon Weifeng 
67858da0cfaSVoon Weifeng 	if (priv->plat->stmmac_clk)
67958da0cfaSVoon Weifeng 		clk_unregister_fixed_rate(priv->plat->stmmac_clk);
68058da0cfaSVoon Weifeng 
68158da0cfaSVoon Weifeng 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
68258da0cfaSVoon Weifeng 		if (pci_resource_len(pdev, i) == 0)
68358da0cfaSVoon Weifeng 			continue;
68458da0cfaSVoon Weifeng 		pcim_iounmap_regions(pdev, BIT(i));
68558da0cfaSVoon Weifeng 		break;
68658da0cfaSVoon Weifeng 	}
68758da0cfaSVoon Weifeng 
68858da0cfaSVoon Weifeng 	pci_disable_device(pdev);
68958da0cfaSVoon Weifeng }
69058da0cfaSVoon Weifeng 
69158da0cfaSVoon Weifeng static int __maybe_unused intel_eth_pci_suspend(struct device *dev)
69258da0cfaSVoon Weifeng {
69358da0cfaSVoon Weifeng 	struct pci_dev *pdev = to_pci_dev(dev);
69458da0cfaSVoon Weifeng 	int ret;
69558da0cfaSVoon Weifeng 
69658da0cfaSVoon Weifeng 	ret = stmmac_suspend(dev);
69758da0cfaSVoon Weifeng 	if (ret)
69858da0cfaSVoon Weifeng 		return ret;
69958da0cfaSVoon Weifeng 
70058da0cfaSVoon Weifeng 	ret = pci_save_state(pdev);
70158da0cfaSVoon Weifeng 	if (ret)
70258da0cfaSVoon Weifeng 		return ret;
70358da0cfaSVoon Weifeng 
70458da0cfaSVoon Weifeng 	pci_disable_device(pdev);
70558da0cfaSVoon Weifeng 	pci_wake_from_d3(pdev, true);
70658da0cfaSVoon Weifeng 	return 0;
70758da0cfaSVoon Weifeng }
70858da0cfaSVoon Weifeng 
70958da0cfaSVoon Weifeng static int __maybe_unused intel_eth_pci_resume(struct device *dev)
71058da0cfaSVoon Weifeng {
71158da0cfaSVoon Weifeng 	struct pci_dev *pdev = to_pci_dev(dev);
71258da0cfaSVoon Weifeng 	int ret;
71358da0cfaSVoon Weifeng 
71458da0cfaSVoon Weifeng 	pci_restore_state(pdev);
71558da0cfaSVoon Weifeng 	pci_set_power_state(pdev, PCI_D0);
71658da0cfaSVoon Weifeng 
71758da0cfaSVoon Weifeng 	ret = pci_enable_device(pdev);
71858da0cfaSVoon Weifeng 	if (ret)
71958da0cfaSVoon Weifeng 		return ret;
72058da0cfaSVoon Weifeng 
72158da0cfaSVoon Weifeng 	pci_set_master(pdev);
72258da0cfaSVoon Weifeng 
72358da0cfaSVoon Weifeng 	return stmmac_resume(dev);
72458da0cfaSVoon Weifeng }
72558da0cfaSVoon Weifeng 
72658da0cfaSVoon Weifeng static SIMPLE_DEV_PM_OPS(intel_eth_pm_ops, intel_eth_pci_suspend,
72758da0cfaSVoon Weifeng 			 intel_eth_pci_resume);
72858da0cfaSVoon Weifeng 
72958da0cfaSVoon Weifeng #define PCI_DEVICE_ID_INTEL_QUARK_ID			0x0937
73058da0cfaSVoon Weifeng #define PCI_DEVICE_ID_INTEL_EHL_RGMII1G_ID		0x4b30
73158da0cfaSVoon Weifeng #define PCI_DEVICE_ID_INTEL_EHL_SGMII1G_ID		0x4b31
732d63439f5SVoon Weifeng #define PCI_DEVICE_ID_INTEL_EHL_SGMII2G5_ID		0x4b32
73367c08ac4SVoon Weifeng /* Intel(R) Programmable Services Engine (Intel(R) PSE) consist of 2 MAC
73467c08ac4SVoon Weifeng  * which are named PSE0 and PSE1
73567c08ac4SVoon Weifeng  */
73667c08ac4SVoon Weifeng #define PCI_DEVICE_ID_INTEL_EHL_PSE0_RGMII1G_ID		0x4ba0
73767c08ac4SVoon Weifeng #define PCI_DEVICE_ID_INTEL_EHL_PSE0_SGMII1G_ID		0x4ba1
738d63439f5SVoon Weifeng #define PCI_DEVICE_ID_INTEL_EHL_PSE0_SGMII2G5_ID	0x4ba2
73967c08ac4SVoon Weifeng #define PCI_DEVICE_ID_INTEL_EHL_PSE1_RGMII1G_ID		0x4bb0
74067c08ac4SVoon Weifeng #define PCI_DEVICE_ID_INTEL_EHL_PSE1_SGMII1G_ID		0x4bb1
741d63439f5SVoon Weifeng #define PCI_DEVICE_ID_INTEL_EHL_PSE1_SGMII2G5_ID	0x4bb2
74258da0cfaSVoon Weifeng #define PCI_DEVICE_ID_INTEL_TGL_SGMII1G_ID		0xa0ac
74358da0cfaSVoon Weifeng 
74458da0cfaSVoon Weifeng static const struct pci_device_id intel_eth_pci_id_table[] = {
74558da0cfaSVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, QUARK_ID, &quark_pci_info) },
74658da0cfaSVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, EHL_RGMII1G_ID, &ehl_rgmii1g_pci_info) },
74758da0cfaSVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, EHL_SGMII1G_ID, &ehl_sgmii1g_pci_info) },
748d63439f5SVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, EHL_SGMII2G5_ID, &ehl_sgmii1g_pci_info) },
74967c08ac4SVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, EHL_PSE0_RGMII1G_ID,
75067c08ac4SVoon Weifeng 			  &ehl_pse0_rgmii1g_pci_info) },
75167c08ac4SVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, EHL_PSE0_SGMII1G_ID,
75267c08ac4SVoon Weifeng 			  &ehl_pse0_sgmii1g_pci_info) },
753d63439f5SVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, EHL_PSE0_SGMII2G5_ID,
754d63439f5SVoon Weifeng 			  &ehl_pse0_sgmii1g_pci_info) },
75567c08ac4SVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, EHL_PSE1_RGMII1G_ID,
75667c08ac4SVoon Weifeng 			  &ehl_pse1_rgmii1g_pci_info) },
75767c08ac4SVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, EHL_PSE1_SGMII1G_ID,
75867c08ac4SVoon Weifeng 			  &ehl_pse1_sgmii1g_pci_info) },
759d63439f5SVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, EHL_PSE1_SGMII2G5_ID,
760d63439f5SVoon Weifeng 			  &ehl_pse1_sgmii1g_pci_info) },
76158da0cfaSVoon Weifeng 	{ PCI_DEVICE_DATA(INTEL, TGL_SGMII1G_ID, &tgl_sgmii1g_pci_info) },
76258da0cfaSVoon Weifeng 	{}
76358da0cfaSVoon Weifeng };
76458da0cfaSVoon Weifeng 
76558da0cfaSVoon Weifeng MODULE_DEVICE_TABLE(pci, intel_eth_pci_id_table);
76658da0cfaSVoon Weifeng 
76758da0cfaSVoon Weifeng static struct pci_driver intel_eth_pci_driver = {
76858da0cfaSVoon Weifeng 	.name = "intel-eth-pci",
76958da0cfaSVoon Weifeng 	.id_table = intel_eth_pci_id_table,
77058da0cfaSVoon Weifeng 	.probe = intel_eth_pci_probe,
77158da0cfaSVoon Weifeng 	.remove = intel_eth_pci_remove,
77258da0cfaSVoon Weifeng 	.driver         = {
77358da0cfaSVoon Weifeng 		.pm     = &intel_eth_pm_ops,
77458da0cfaSVoon Weifeng 	},
77558da0cfaSVoon Weifeng };
77658da0cfaSVoon Weifeng 
77758da0cfaSVoon Weifeng module_pci_driver(intel_eth_pci_driver);
77858da0cfaSVoon Weifeng 
77958da0cfaSVoon Weifeng MODULE_DESCRIPTION("INTEL 10/100/1000 Ethernet PCI driver");
78058da0cfaSVoon Weifeng MODULE_AUTHOR("Voon Weifeng <weifeng.voon@intel.com>");
78158da0cfaSVoon Weifeng MODULE_LICENSE("GPL v2");
782