Skip to content

Commit 83a77e9

Browse files
Bartosz Foltadavem330
authored andcommitted
net: macb: Added PCI wrapper for Platform Driver.
There are hardware PCI implementations of Cadence GEM network controller. This patch will allow to use such hardware with reuse of existing Platform Driver. Signed-off-by: Bartosz Folta <bfolta@cadence.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 94acf16 commit 83a77e9

File tree

5 files changed

+195
-5
lines changed

5 files changed

+195
-5
lines changed

drivers/net/ethernet/cadence/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,13 @@ config MACB
3131
To compile this driver as a module, choose M here: the module
3232
will be called macb.
3333

34+
config MACB_PCI
35+
tristate "Cadence PCI MACB/GEM support"
36+
depends on MACB && PCI && COMMON_CLK
37+
---help---
38+
This is PCI wrapper for MACB driver.
39+
40+
To compile this driver as a module, choose M here: the module
41+
will be called macb_pci.
42+
3443
endif # NET_CADENCE

drivers/net/ethernet/cadence/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
#
44

55
obj-$(CONFIG_MACB) += macb.o
6+
obj-$(CONFIG_MACB_PCI) += macb_pci.o

drivers/net/ethernet/cadence/macb.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,8 @@ static int macb_mii_probe(struct net_device *dev)
404404
phy_irq = gpio_to_irq(pdata->phy_irq_pin);
405405
phydev->irq = (phy_irq < 0) ? PHY_POLL : phy_irq;
406406
}
407+
} else {
408+
phydev->irq = PHY_POLL;
407409
}
408410

409411
/* attach the mac to the phy */
@@ -482,6 +484,9 @@ static int macb_mii_init(struct macb *bp)
482484
goto err_out_unregister_bus;
483485
}
484486
} else {
487+
for (i = 0; i < PHY_MAX_ADDR; i++)
488+
bp->mii_bus->irq[i] = PHY_POLL;
489+
485490
if (pdata)
486491
bp->mii_bus->phy_mask = pdata->phy_mask;
487492

@@ -2523,16 +2528,24 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
25232528
struct clk **hclk, struct clk **tx_clk,
25242529
struct clk **rx_clk)
25252530
{
2531+
struct macb_platform_data *pdata;
25262532
int err;
25272533

2528-
*pclk = devm_clk_get(&pdev->dev, "pclk");
2534+
pdata = dev_get_platdata(&pdev->dev);
2535+
if (pdata) {
2536+
*pclk = pdata->pclk;
2537+
*hclk = pdata->hclk;
2538+
} else {
2539+
*pclk = devm_clk_get(&pdev->dev, "pclk");
2540+
*hclk = devm_clk_get(&pdev->dev, "hclk");
2541+
}
2542+
25292543
if (IS_ERR(*pclk)) {
25302544
err = PTR_ERR(*pclk);
25312545
dev_err(&pdev->dev, "failed to get macb_clk (%u)\n", err);
25322546
return err;
25332547
}
25342548

2535-
*hclk = devm_clk_get(&pdev->dev, "hclk");
25362549
if (IS_ERR(*hclk)) {
25372550
err = PTR_ERR(*hclk);
25382551
dev_err(&pdev->dev, "failed to get hclk (%u)\n", err);
@@ -3107,15 +3120,23 @@ static const struct of_device_id macb_dt_ids[] = {
31073120
MODULE_DEVICE_TABLE(of, macb_dt_ids);
31083121
#endif /* CONFIG_OF */
31093122

3123+
static const struct macb_config default_gem_config = {
3124+
.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO,
3125+
.dma_burst_length = 16,
3126+
.clk_init = macb_clk_init,
3127+
.init = macb_init,
3128+
.jumbo_max_len = 10240,
3129+
};
3130+
31103131
static int macb_probe(struct platform_device *pdev)
31113132
{
3133+
const struct macb_config *macb_config = &default_gem_config;
31123134
int (*clk_init)(struct platform_device *, struct clk **,
31133135
struct clk **, struct clk **, struct clk **)
3114-
= macb_clk_init;
3115-
int (*init)(struct platform_device *) = macb_init;
3136+
= macb_config->clk_init;
3137+
int (*init)(struct platform_device *) = macb_config->init;
31163138
struct device_node *np = pdev->dev.of_node;
31173139
struct device_node *phy_node;
3118-
const struct macb_config *macb_config = NULL;
31193140
struct clk *pclk, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL;
31203141
unsigned int queue_mask, num_queues;
31213142
struct macb_platform_data *pdata;
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/**
2+
* macb_pci.c - Cadence GEM PCI wrapper.
3+
*
4+
* Copyright (C) 2016 Cadence Design Systems - http://www.cadence.com
5+
*
6+
* Authors: Rafal Ozieblo <rafalo@cadence.com>
7+
* Bartosz Folta <bfolta@cadence.com>
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU General Public License version 2 of
11+
* the License as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20+
*/
21+
22+
#include <linux/clk.h>
23+
#include <linux/clk-provider.h>
24+
#include <linux/etherdevice.h>
25+
#include <linux/module.h>
26+
#include <linux/pci.h>
27+
#include <linux/platform_data/macb.h>
28+
#include <linux/platform_device.h>
29+
#include "macb.h"
30+
31+
#define PCI_DRIVER_NAME "macb_pci"
32+
#define PLAT_DRIVER_NAME "macb"
33+
34+
#define CDNS_VENDOR_ID 0x17cd
35+
#define CDNS_DEVICE_ID 0xe007
36+
37+
#define GEM_PCLK_RATE 50000000
38+
#define GEM_HCLK_RATE 50000000
39+
40+
static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
41+
{
42+
int err;
43+
struct platform_device *plat_dev;
44+
struct platform_device_info plat_info;
45+
struct macb_platform_data plat_data;
46+
struct resource res[2];
47+
48+
/* sanity check */
49+
if (!id)
50+
return -EINVAL;
51+
52+
/* enable pci device */
53+
err = pci_enable_device(pdev);
54+
if (err < 0) {
55+
dev_err(&pdev->dev, "Enabling PCI device has failed: 0x%04X",
56+
err);
57+
return -EACCES;
58+
}
59+
60+
pci_set_master(pdev);
61+
62+
/* set up resources */
63+
memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
64+
res[0].start = pdev->resource[0].start;
65+
res[0].end = pdev->resource[0].end;
66+
res[0].name = PCI_DRIVER_NAME;
67+
res[0].flags = IORESOURCE_MEM;
68+
res[1].start = pdev->irq;
69+
res[1].name = PCI_DRIVER_NAME;
70+
res[1].flags = IORESOURCE_IRQ;
71+
72+
dev_info(&pdev->dev, "EMAC physical base addr = 0x%p\n",
73+
(void *)(uintptr_t)pci_resource_start(pdev, 0));
74+
75+
/* set up macb platform data */
76+
memset(&plat_data, 0, sizeof(plat_data));
77+
78+
/* initialize clocks */
79+
plat_data.pclk = clk_register_fixed_rate(&pdev->dev, "pclk", NULL, 0,
80+
GEM_PCLK_RATE);
81+
if (IS_ERR(plat_data.pclk)) {
82+
err = PTR_ERR(plat_data.pclk);
83+
goto err_pclk_register;
84+
}
85+
86+
plat_data.hclk = clk_register_fixed_rate(&pdev->dev, "hclk", NULL, 0,
87+
GEM_HCLK_RATE);
88+
if (IS_ERR(plat_data.hclk)) {
89+
err = PTR_ERR(plat_data.hclk);
90+
goto err_hclk_register;
91+
}
92+
93+
/* set up platform device info */
94+
memset(&plat_info, 0, sizeof(plat_info));
95+
plat_info.parent = &pdev->dev;
96+
plat_info.fwnode = pdev->dev.fwnode;
97+
plat_info.name = PLAT_DRIVER_NAME;
98+
plat_info.id = pdev->devfn;
99+
plat_info.res = res;
100+
plat_info.num_res = ARRAY_SIZE(res);
101+
plat_info.data = &plat_data;
102+
plat_info.size_data = sizeof(plat_data);
103+
plat_info.dma_mask = DMA_BIT_MASK(32);
104+
105+
/* register platform device */
106+
plat_dev = platform_device_register_full(&plat_info);
107+
if (IS_ERR(plat_dev)) {
108+
err = PTR_ERR(plat_dev);
109+
goto err_plat_dev_register;
110+
}
111+
112+
pci_set_drvdata(pdev, plat_dev);
113+
114+
return 0;
115+
116+
err_plat_dev_register:
117+
clk_unregister(plat_data.hclk);
118+
119+
err_hclk_register:
120+
clk_unregister(plat_data.pclk);
121+
122+
err_pclk_register:
123+
pci_disable_device(pdev);
124+
return err;
125+
}
126+
127+
static void macb_remove(struct pci_dev *pdev)
128+
{
129+
struct platform_device *plat_dev = pci_get_drvdata(pdev);
130+
struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev);
131+
132+
platform_device_unregister(plat_dev);
133+
pci_disable_device(pdev);
134+
clk_unregister(plat_data->pclk);
135+
clk_unregister(plat_data->hclk);
136+
}
137+
138+
static struct pci_device_id dev_id_table[] = {
139+
{ PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), },
140+
{ 0, }
141+
};
142+
143+
static struct pci_driver macb_pci_driver = {
144+
.name = PCI_DRIVER_NAME,
145+
.id_table = dev_id_table,
146+
.probe = macb_probe,
147+
.remove = macb_remove,
148+
};
149+
150+
module_pci_driver(macb_pci_driver);
151+
MODULE_DEVICE_TABLE(pci, dev_id_table);
152+
MODULE_LICENSE("GPL");
153+
MODULE_DESCRIPTION("Cadence NIC PCI wrapper");

include/linux/platform_data/macb.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,25 @@
88
#ifndef __MACB_PDATA_H__
99
#define __MACB_PDATA_H__
1010

11+
#include <linux/clk.h>
12+
1113
/**
1214
* struct macb_platform_data - platform data for MACB Ethernet
1315
* @phy_mask: phy mask passed when register the MDIO bus
1416
* within the driver
1517
* @phy_irq_pin: PHY IRQ
1618
* @is_rmii: using RMII interface?
1719
* @rev_eth_addr: reverse Ethernet address byte order
20+
* @pclk: platform clock
21+
* @hclk: AHB clock
1822
*/
1923
struct macb_platform_data {
2024
u32 phy_mask;
2125
int phy_irq_pin;
2226
u8 is_rmii;
2327
u8 rev_eth_addr;
28+
struct clk *pclk;
29+
struct clk *hclk;
2430
};
2531

2632
#endif /* __MACB_PDATA_H__ */

0 commit comments

Comments
 (0)