Skip to content

Commit ee50a33

Browse files
FreeFlyingSheepchenhuacai
authored andcommitted
stmmac: pci: Add LS7A support for dwmac-loongson
Current dwmac-loongson only support LS2K in the "probed with PCI and configured with DT" manner. We add LS7A support on which the devices are fully PCI (non-DT). Signed-off-by: Huacai Chen <[email protected]> Signed-off-by: Feiyang Chen <[email protected]>
1 parent e721170 commit ee50a33

File tree

1 file changed

+122
-54
lines changed

1 file changed

+122
-54
lines changed

drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c

Lines changed: 122 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,22 @@
99
#include <linux/of_irq.h>
1010
#include "stmmac.h"
1111

12-
static int loongson_default_data(struct plat_stmmacenet_data *plat)
12+
struct stmmac_pci_info {
13+
int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
14+
};
15+
16+
static void common_default_data(struct pci_dev *pdev,
17+
struct plat_stmmacenet_data *plat)
1318
{
19+
plat->bus_id = (pci_domain_nr(pdev->bus) << 16) | PCI_DEVID(pdev->bus->number, pdev->devfn);
20+
plat->interface = PHY_INTERFACE_MODE_GMII;
21+
1422
plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
1523
plat->has_gmac = 1;
1624
plat->force_sf_dma_mode = 1;
1725

1826
/* Set default value for multicast hash bins */
19-
plat->multicast_filter_bins = HASH_TABLE_SIZE;
27+
plat->multicast_filter_bins = 256;
2028

2129
/* Set default value for unicast filter entries */
2230
plat->unicast_filter_entries = 1;
@@ -35,31 +43,80 @@ static int loongson_default_data(struct plat_stmmacenet_data *plat)
3543
/* Disable RX queues routing by default */
3644
plat->rx_queues_cfg[0].pkt_route = 0x0;
3745

38-
/* Default to phy auto-detection */
39-
plat->phy_addr = -1;
40-
4146
plat->dma_cfg->pbl = 32;
4247
plat->dma_cfg->pblx8 = true;
4348

44-
plat->multicast_filter_bins = 256;
49+
plat->clk_ref_rate = 125000000;
50+
plat->clk_ptp_rate = 125000000;
51+
}
52+
53+
static int loongson_gmac_data(struct pci_dev *pdev,
54+
struct plat_stmmacenet_data *plat)
55+
{
56+
common_default_data(pdev, plat);
57+
58+
plat->mdio_bus_data->phy_mask = 0;
59+
60+
plat->phy_addr = -1;
61+
plat->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
62+
63+
stmmac_flow_ctrl = FLOW_OFF;
64+
4565
return 0;
4666
}
4767

48-
static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
68+
static struct stmmac_pci_info loongson_gmac_pci_info = {
69+
.setup = loongson_gmac_data,
70+
};
71+
72+
static void loongson_gnet_fix_speed(void *priv, unsigned int speed)
73+
{
74+
struct net_device *ndev = (struct net_device *)(*(unsigned long *)priv);
75+
struct stmmac_priv *ptr = netdev_priv(ndev);
76+
77+
if (speed == SPEED_1000) {
78+
if (readl(ptr->ioaddr + MAC_CTRL_REG) & (1 << 15) /* PS */) {
79+
/* reset phy */
80+
phy_set_bits(ndev->phydev, 0 /*MII_BMCR*/,
81+
0x200 /*BMCR_ANRESTART*/);
82+
}
83+
}
84+
}
85+
86+
static int loongson_gnet_data(struct pci_dev *pdev,
87+
struct plat_stmmacenet_data *plat)
88+
{
89+
common_default_data(pdev, plat);
90+
91+
plat->mdio_bus_data->phy_mask = 0xfffffffb;
92+
93+
plat->phy_addr = 2;
94+
plat->phy_interface = PHY_INTERFACE_MODE_GMII;
95+
96+
/* GNET 1000M speed need workaround */
97+
plat->fix_mac_speed = loongson_gnet_fix_speed;
98+
99+
/* Get netdev pointer address */
100+
plat->bsp_priv = &(pdev->dev.driver_data);
101+
102+
return 0;
103+
}
104+
105+
static struct stmmac_pci_info loongson_gnet_pci_info = {
106+
.setup = loongson_gnet_data,
107+
};
108+
109+
static int loongson_dwmac_probe(struct pci_dev *pdev,
110+
const struct pci_device_id *id)
49111
{
50112
struct plat_stmmacenet_data *plat;
113+
struct stmmac_pci_info *info;
51114
struct stmmac_resources res;
52115
struct device_node *np;
53-
int ret, i, phy_mode;
116+
int ret, i, bus_id, phy_mode;
54117

55118
np = dev_of_node(&pdev->dev);
56-
57-
if (!np) {
58-
pr_info("dwmac_loongson_pci: No OF node\n");
59-
return -ENODEV;
60-
}
61-
62-
if (!of_device_is_compatible(np, "loongson, pci-gmac")) {
119+
if (np && !of_device_is_compatible(np, "loongson, pci-gmac")) {
63120
pr_info("dwmac_loongson_pci: Incompatible OF node\n");
64121
return -ENODEV;
65122
}
@@ -68,17 +125,14 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
68125
if (!plat)
69126
return -ENOMEM;
70127

128+
plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
129+
sizeof(*plat->mdio_bus_data), GFP_KERNEL);
130+
if (!plat->mdio_bus_data)
131+
return -ENOMEM;
132+
71133
plat->mdio_node = of_get_child_by_name(np, "mdio");
72134
if (plat->mdio_node) {
73135
dev_info(&pdev->dev, "Found MDIO subnode\n");
74-
75-
plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
76-
sizeof(*plat->mdio_bus_data),
77-
GFP_KERNEL);
78-
if (!plat->mdio_bus_data) {
79-
ret = -ENOMEM;
80-
goto err_put_node;
81-
}
82136
plat->mdio_bus_data->needs_reset = true;
83137
}
84138

@@ -105,45 +159,55 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
105159
break;
106160
}
107161

108-
plat->bus_id = of_alias_get_id(np, "ethernet");
109-
if (plat->bus_id < 0)
110-
plat->bus_id = pci_dev_id(pdev);
162+
pci_set_master(pdev);
111163

112-
phy_mode = device_get_phy_mode(&pdev->dev);
113-
if (phy_mode < 0) {
114-
dev_err(&pdev->dev, "phy_mode not found\n");
115-
ret = phy_mode;
116-
goto err_disable_device;
117-
}
164+
info = (struct stmmac_pci_info *)id->driver_data;
165+
ret = info->setup(pdev, plat);
166+
if (ret)
167+
return ret;
118168

119-
plat->phy_interface = phy_mode;
120-
plat->interface = PHY_INTERFACE_MODE_GMII;
169+
if (np) {
170+
bus_id = of_alias_get_id(np, "ethernet");
171+
if (bus_id >= 0)
172+
plat->bus_id = bus_id;
121173

122-
pci_set_master(pdev);
174+
phy_mode = device_get_phy_mode(&pdev->dev);
175+
if (phy_mode < 0) {
176+
dev_err(&pdev->dev, "phy_mode not found\n");
177+
ret = phy_mode;
178+
goto err_disable_device;
179+
}
180+
plat->phy_interface = phy_mode;
181+
}
123182

124-
loongson_default_data(plat);
125183
pci_enable_msi(pdev);
184+
126185
memset(&res, 0, sizeof(res));
127186
res.addr = pcim_iomap_table(pdev)[0];
187+
if (np) {
188+
res.irq = of_irq_get_byname(np, "macirq");
189+
if (res.irq < 0) {
190+
dev_err(&pdev->dev, "IRQ macirq not found\n");
191+
ret = -ENODEV;
192+
goto err_disable_msi;
193+
}
128194

129-
res.irq = of_irq_get_byname(np, "macirq");
130-
if (res.irq < 0) {
131-
dev_err(&pdev->dev, "IRQ macirq not found\n");
132-
ret = -ENODEV;
133-
goto err_disable_msi;
134-
}
135-
136-
res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
137-
if (res.wol_irq < 0) {
138-
dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n");
139-
res.wol_irq = res.irq;
140-
}
195+
res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
196+
if (res.wol_irq < 0) {
197+
dev_info(&pdev->dev,
198+
"IRQ eth_wake_irq not found, using macirq\n");
199+
res.wol_irq = res.irq;
200+
}
141201

142-
res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
143-
if (res.lpi_irq < 0) {
144-
dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
145-
ret = -ENODEV;
146-
goto err_disable_msi;
202+
res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
203+
if (res.lpi_irq < 0) {
204+
dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
205+
ret = -ENODEV;
206+
goto err_disable_msi;
207+
}
208+
} else {
209+
res.irq = pdev->irq;
210+
res.wol_irq = pdev->irq;
147211
}
148212

149213
ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
@@ -219,8 +283,12 @@ static int __maybe_unused loongson_dwmac_resume(struct device *dev)
219283
static SIMPLE_DEV_PM_OPS(loongson_dwmac_pm_ops, loongson_dwmac_suspend,
220284
loongson_dwmac_resume);
221285

286+
#define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03
287+
#define PCI_DEVICE_ID_LOONGSON_GNET 0x7a13
288+
222289
static const struct pci_device_id loongson_dwmac_id_table[] = {
223-
{ PCI_VDEVICE(LOONGSON, 0x7a03) },
290+
{ PCI_DEVICE_DATA(LOONGSON, GMAC, &loongson_gmac_pci_info) },
291+
{ PCI_DEVICE_DATA(LOONGSON, GNET, &loongson_gnet_pci_info) },
224292
{}
225293
};
226294
MODULE_DEVICE_TABLE(pci, loongson_dwmac_id_table);

0 commit comments

Comments
 (0)