Skip to content

Commit 76723bc

Browse files
shesselbadavem330
authored andcommitted
net: mv643xx_eth: add DT parsing support
This adds device tree parsing support for the shared driver of mv643xx_eth. As the bindings are slightly different from current PPC bindings new binding documentation is also added. Following PPC-style device setup, the shared driver now also adds port platform_devices and sets up port platform_data. Signed-off-by: Sebastian Hesselbarth <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent cb85215 commit 76723bc

File tree

2 files changed

+234
-4
lines changed

2 files changed

+234
-4
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
Marvell Orion/Discovery ethernet controller
2+
=============================================
3+
4+
The Marvell Discovery ethernet controller can be found on Marvell Orion SoCs
5+
(Kirkwood, Dove, Orion5x, and Discovery Innovation) and as part of Marvell
6+
Discovery system controller chips (mv64[345]60).
7+
8+
The Discovery ethernet controller is described with two levels of nodes. The
9+
first level describes the ethernet controller itself and the second level
10+
describes up to 3 ethernet port nodes within that controller. The reason for
11+
the multiple levels is that the port registers are interleaved within a single
12+
set of controller registers. Each port node describes port-specific properties.
13+
14+
Note: The above separation is only true for Discovery system controllers.
15+
For Orion SoCs we stick to the separation, although there each controller has
16+
only one port associated. Multiple ports are implemented as multiple single-port
17+
controllers. As Kirkwood has some issues with proper initialization after reset,
18+
an extra compatible string is added for it.
19+
20+
* Ethernet controller node
21+
22+
Required controller properties:
23+
- #address-cells: shall be 1.
24+
- #size-cells: shall be 0.
25+
- compatible: shall be one of "marvell,orion-eth", "marvell,kirkwood-eth".
26+
- reg: address and length of the controller registers.
27+
28+
Optional controller properties:
29+
- clocks: phandle reference to the controller clock.
30+
- marvell,tx-checksum-limit: max tx packet size for hardware checksum.
31+
32+
* Ethernet port node
33+
34+
Required port properties:
35+
- device_type: shall be "network".
36+
- compatible: shall be one of "marvell,orion-eth-port",
37+
"marvell,kirkwood-eth-port".
38+
- reg: port number relative to ethernet controller, shall be 0, 1, or 2.
39+
- interrupts: port interrupt.
40+
- local-mac-address: 6 bytes MAC address.
41+
42+
Optional port properties:
43+
- marvell,tx-queue-size: size of the transmit ring buffer.
44+
- marvell,tx-sram-addr: address of transmit descriptor buffer located in SRAM.
45+
- marvell,tx-sram-size: size of transmit descriptor buffer located in SRAM.
46+
- marvell,rx-queue-size: size of the receive ring buffer.
47+
- marvell,rx-sram-addr: address of receive descriptor buffer located in SRAM.
48+
- marvell,rx-sram-size: size of receive descriptor buffer located in SRAM.
49+
50+
and
51+
52+
- phy-handle: phandle reference to ethernet PHY.
53+
54+
or
55+
56+
- speed: port speed if no PHY connected.
57+
- duplex: port mode if no PHY connected.
58+
59+
* Node example:
60+
61+
mdio-bus {
62+
...
63+
ethphy: ethernet-phy@8 {
64+
device_type = "ethernet-phy";
65+
...
66+
};
67+
};
68+
69+
eth: ethernet-controller@72000 {
70+
compatible = "marvell,orion-eth";
71+
#address-cells = <1>;
72+
#size-cells = <0>;
73+
reg = <0x72000 0x2000>;
74+
clocks = <&gate_clk 2>;
75+
marvell,tx-checksum-limit = <1600>;
76+
77+
ethernet@0 {
78+
device_type = "network";
79+
compatible = "marvell,orion-eth-port";
80+
reg = <0>;
81+
interrupts = <29>;
82+
phy-handle = <&ethphy>;
83+
local-mac-address = [00 00 00 00 00 00];
84+
};
85+
};

drivers/net/ethernet/marvell/mv643xx_eth.c

Lines changed: 149 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@
6060
#include <linux/types.h>
6161
#include <linux/slab.h>
6262
#include <linux/clk.h>
63+
#include <linux/of.h>
64+
#include <linux/of_irq.h>
65+
#include <linux/of_net.h>
6366
#include <linux/of_mdio.h>
6467

6568
static char mv643xx_eth_driver_name[] = "mv643xx_eth";
@@ -2453,13 +2456,148 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
24532456
}
24542457
}
24552458

2459+
#if defined(CONFIG_OF)
2460+
static const struct of_device_id mv643xx_eth_shared_ids[] = {
2461+
{ .compatible = "marvell,orion-eth", },
2462+
{ .compatible = "marvell,kirkwood-eth", },
2463+
{ }
2464+
};
2465+
MODULE_DEVICE_TABLE(of, mv643xx_eth_shared_ids);
2466+
#endif
2467+
2468+
#if defined(CONFIG_OF) && !defined(CONFIG_MV64X60)
2469+
#define mv643xx_eth_property(_np, _name, _v) \
2470+
do { \
2471+
u32 tmp; \
2472+
if (!of_property_read_u32(_np, "marvell," _name, &tmp)) \
2473+
_v = tmp; \
2474+
} while (0)
2475+
2476+
static struct platform_device *port_platdev[3];
2477+
2478+
static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
2479+
struct device_node *pnp)
2480+
{
2481+
struct platform_device *ppdev;
2482+
struct mv643xx_eth_platform_data ppd;
2483+
struct resource res;
2484+
const char *mac_addr;
2485+
int ret;
2486+
2487+
memset(&ppd, 0, sizeof(ppd));
2488+
ppd.shared = pdev;
2489+
2490+
memset(&res, 0, sizeof(res));
2491+
if (!of_irq_to_resource(pnp, 0, &res)) {
2492+
dev_err(&pdev->dev, "missing interrupt on %s\n", pnp->name);
2493+
return -EINVAL;
2494+
}
2495+
2496+
if (of_property_read_u32(pnp, "reg", &ppd.port_number)) {
2497+
dev_err(&pdev->dev, "missing reg property on %s\n", pnp->name);
2498+
return -EINVAL;
2499+
}
2500+
2501+
if (ppd.port_number >= 3) {
2502+
dev_err(&pdev->dev, "invalid reg property on %s\n", pnp->name);
2503+
return -EINVAL;
2504+
}
2505+
2506+
mac_addr = of_get_mac_address(pnp);
2507+
if (mac_addr)
2508+
memcpy(ppd.mac_addr, mac_addr, 6);
2509+
2510+
mv643xx_eth_property(pnp, "tx-queue-size", ppd.tx_queue_size);
2511+
mv643xx_eth_property(pnp, "tx-sram-addr", ppd.tx_sram_addr);
2512+
mv643xx_eth_property(pnp, "tx-sram-size", ppd.tx_sram_size);
2513+
mv643xx_eth_property(pnp, "rx-queue-size", ppd.rx_queue_size);
2514+
mv643xx_eth_property(pnp, "rx-sram-addr", ppd.rx_sram_addr);
2515+
mv643xx_eth_property(pnp, "rx-sram-size", ppd.rx_sram_size);
2516+
2517+
ppd.phy_node = of_parse_phandle(pnp, "phy-handle", 0);
2518+
if (!ppd.phy_node) {
2519+
ppd.phy_addr = MV643XX_ETH_PHY_NONE;
2520+
of_property_read_u32(pnp, "speed", &ppd.speed);
2521+
of_property_read_u32(pnp, "duplex", &ppd.duplex);
2522+
}
2523+
2524+
ppdev = platform_device_alloc(MV643XX_ETH_NAME, ppd.port_number);
2525+
if (!ppdev)
2526+
return -ENOMEM;
2527+
ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
2528+
2529+
ret = platform_device_add_resources(ppdev, &res, 1);
2530+
if (ret)
2531+
goto port_err;
2532+
2533+
ret = platform_device_add_data(ppdev, &ppd, sizeof(ppd));
2534+
if (ret)
2535+
goto port_err;
2536+
2537+
ret = platform_device_add(ppdev);
2538+
if (ret)
2539+
goto port_err;
2540+
2541+
port_platdev[ppd.port_number] = ppdev;
2542+
2543+
return 0;
2544+
2545+
port_err:
2546+
platform_device_put(ppdev);
2547+
return ret;
2548+
}
2549+
2550+
static int mv643xx_eth_shared_of_probe(struct platform_device *pdev)
2551+
{
2552+
struct mv643xx_eth_shared_platform_data *pd;
2553+
struct device_node *pnp, *np = pdev->dev.of_node;
2554+
int ret;
2555+
2556+
/* bail out if not registered from DT */
2557+
if (!np)
2558+
return 0;
2559+
2560+
pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
2561+
if (!pd)
2562+
return -ENOMEM;
2563+
pdev->dev.platform_data = pd;
2564+
2565+
mv643xx_eth_property(np, "tx-checksum-limit", pd->tx_csum_limit);
2566+
2567+
for_each_available_child_of_node(np, pnp) {
2568+
ret = mv643xx_eth_shared_of_add_port(pdev, pnp);
2569+
if (ret)
2570+
return ret;
2571+
}
2572+
return 0;
2573+
}
2574+
2575+
static void mv643xx_eth_shared_of_remove(void)
2576+
{
2577+
int n;
2578+
2579+
for (n = 0; n < 3; n++) {
2580+
platform_device_del(port_platdev[n]);
2581+
port_platdev[n] = NULL;
2582+
}
2583+
}
2584+
#else
2585+
static int mv643xx_eth_shared_of_probe(struct platform_device *pdev)
2586+
{
2587+
return 0
2588+
}
2589+
2590+
#define mv643xx_eth_shared_of_remove()
2591+
#endif
2592+
24562593
static int mv643xx_eth_shared_probe(struct platform_device *pdev)
24572594
{
24582595
static int mv643xx_eth_version_printed;
2459-
struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
2596+
struct mv643xx_eth_shared_platform_data *pd;
24602597
struct mv643xx_eth_shared_private *msp;
24612598
const struct mbus_dram_target_info *dram;
24622599
struct resource *res;
2600+
int ret;
24632601

24642602
if (!mv643xx_eth_version_printed++)
24652603
pr_notice("MV-643xx 10/100/1000 ethernet driver version %s\n",
@@ -2472,6 +2610,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
24722610
msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL);
24732611
if (msp == NULL)
24742612
return -ENOMEM;
2613+
platform_set_drvdata(pdev, msp);
24752614

24762615
msp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
24772616
if (msp->base == NULL)
@@ -2488,22 +2627,25 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
24882627
if (dram)
24892628
mv643xx_eth_conf_mbus_windows(msp, dram);
24902629

2630+
ret = mv643xx_eth_shared_of_probe(pdev);
2631+
if (ret)
2632+
return ret;
2633+
pd = pdev->dev.platform_data;
2634+
24912635
msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ?
24922636
pd->tx_csum_limit : 9 * 1024;
24932637
infer_hw_params(msp);
24942638

2495-
platform_set_drvdata(pdev, msp);
2496-
24972639
return 0;
24982640
}
24992641

25002642
static int mv643xx_eth_shared_remove(struct platform_device *pdev)
25012643
{
25022644
struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev);
25032645

2646+
mv643xx_eth_shared_of_remove();
25042647
if (!IS_ERR(msp->clk))
25052648
clk_disable_unprepare(msp->clk);
2506-
25072649
return 0;
25082650
}
25092651

@@ -2513,6 +2655,7 @@ static struct platform_driver mv643xx_eth_shared_driver = {
25132655
.driver = {
25142656
.name = MV643XX_ETH_SHARED_NAME,
25152657
.owner = THIS_MODULE,
2658+
.of_match_table = of_match_ptr(mv643xx_eth_shared_ids),
25162659
},
25172660
};
25182661

@@ -2721,6 +2864,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
27212864
if (!IS_ERR(mp->clk)) {
27222865
clk_prepare_enable(mp->clk);
27232866
mp->t_clk = clk_get_rate(mp->clk);
2867+
} else if (!IS_ERR(mp->shared->clk)) {
2868+
mp->t_clk = clk_get_rate(mp->shared->clk);
27242869
}
27252870

27262871
set_params(mp, pd);

0 commit comments

Comments
 (0)