diff options
Diffstat (limited to 'target/linux/kirkwood/patches-3.10/0023-net-mv643xx_eth-add-DT-parsing-support.patch')
-rw-r--r-- | target/linux/kirkwood/patches-3.10/0023-net-mv643xx_eth-add-DT-parsing-support.patch | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/target/linux/kirkwood/patches-3.10/0023-net-mv643xx_eth-add-DT-parsing-support.patch b/target/linux/kirkwood/patches-3.10/0023-net-mv643xx_eth-add-DT-parsing-support.patch new file mode 100644 index 0000000000..1970bde098 --- /dev/null +++ b/target/linux/kirkwood/patches-3.10/0023-net-mv643xx_eth-add-DT-parsing-support.patch @@ -0,0 +1,329 @@ +From dd6cae3b60ee88b301f9325db144e70b5e12482e Mon Sep 17 00:00:00 2001 +From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> +Date: Wed, 29 May 2013 21:32:48 +0200 +Subject: [PATCH 23/29] 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 <sebastian.hesselbarth@gmail.com> +--- + .../devicetree/bindings/net/marvell-orion-net.txt | 85 ++++++++++++ + drivers/net/ethernet/marvell/mv643xx_eth.c | 153 ++++++++++++++++++++- + 2 files changed, 234 insertions(+), 4 deletions(-) + create mode 100644 Documentation/devicetree/bindings/net/marvell-orion-net.txt + +diff --git a/Documentation/devicetree/bindings/net/marvell-orion-net.txt b/Documentation/devicetree/bindings/net/marvell-orion-net.txt +new file mode 100644 +index 0000000..a73b79f +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/marvell-orion-net.txt +@@ -0,0 +1,85 @@ ++Marvell Orion/Discovery ethernet controller ++============================================= ++ ++The Marvell Discovery ethernet controller can be found on Marvell Orion SoCs ++(Kirkwood, Dove, Orion5x, and Discovery Innovation) and as part of Marvell ++Discovery system controller chips (mv64[345]60). ++ ++The Discovery ethernet controller is described with two levels of nodes. The ++first level describes the ethernet controller itself and the second level ++describes up to 3 ethernet port nodes within that controller. The reason for ++the multiple levels is that the port registers are interleaved within a single ++set of controller registers. Each port node describes port-specific properties. ++ ++Note: The above separation is only true for Discovery system controllers. ++For Orion SoCs we stick to the separation, although there each controller has ++only one port associated. Multiple ports are implemented as multiple single-port ++controllers. As Kirkwood has some issues with proper initialization after reset, ++an extra compatible string is added for it. ++ ++* Ethernet controller node ++ ++Required controller properties: ++ - #address-cells: shall be 1. ++ - #size-cells: shall be 0. ++ - compatible: shall be one of "marvell,orion-eth", "marvell,kirkwood-eth". ++ - reg: address and length of the controller registers. ++ ++Optional controller properties: ++ - clocks: phandle reference to the controller clock. ++ - marvell,tx-checksum-limit: max tx packet size for hardware checksum. ++ ++* Ethernet port node ++ ++Required port properties: ++ - device_type: shall be "network". ++ - compatible: shall be one of "marvell,orion-eth-port", ++ "marvell,kirkwood-eth-port". ++ - reg: port number relative to ethernet controller, shall be 0, 1, or 2. ++ - interrupts: port interrupt. ++ - local-mac-address: 6 bytes MAC address. ++ ++Optional port properties: ++ - marvell,tx-queue-size: size of the transmit ring buffer. ++ - marvell,tx-sram-addr: address of transmit descriptor buffer located in SRAM. ++ - marvell,tx-sram-size: size of transmit descriptor buffer located in SRAM. ++ - marvell,rx-queue-size: size of the receive ring buffer. ++ - marvell,rx-sram-addr: address of receive descriptor buffer located in SRAM. ++ - marvell,rx-sram-size: size of receive descriptor buffer located in SRAM. ++ ++and ++ ++ - phy-handle: phandle reference to ethernet PHY. ++ ++or ++ ++ - speed: port speed if no PHY connected. ++ - duplex: port mode if no PHY connected. ++ ++* Node example: ++ ++mdio-bus { ++ ... ++ ethphy: ethernet-phy@8 { ++ device_type = "ethernet-phy"; ++ ... ++ }; ++}; ++ ++eth: ethernet-controller@72000 { ++ compatible = "marvell,orion-eth"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x72000 0x2000>; ++ clocks = <&gate_clk 2>; ++ marvell,tx-checksum-limit = <1600>; ++ ++ ethernet@0 { ++ device_type = "network"; ++ compatible = "marvell,orion-eth-port"; ++ reg = <0>; ++ interrupts = <29>; ++ phy-handle = <ðphy>; ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++}; +diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c +index af6bdcc..004a250 100644 +--- a/drivers/net/ethernet/marvell/mv643xx_eth.c ++++ b/drivers/net/ethernet/marvell/mv643xx_eth.c +@@ -60,6 +60,9 @@ + #include <linux/types.h> + #include <linux/slab.h> + #include <linux/clk.h> ++#include <linux/of.h> ++#include <linux/of_irq.h> ++#include <linux/of_net.h> + #include <linux/of_mdio.h> + + static char mv643xx_eth_driver_name[] = "mv643xx_eth"; +@@ -2453,13 +2456,148 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp) + } + } + ++#if defined(CONFIG_OF) ++static const struct of_device_id mv643xx_eth_shared_ids[] = { ++ { .compatible = "marvell,orion-eth", }, ++ { .compatible = "marvell,kirkwood-eth", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, mv643xx_eth_shared_ids); ++#endif ++ ++#if defined(CONFIG_OF) && !defined(CONFIG_MV64X60) ++#define mv643xx_eth_property(_np, _name, _v) \ ++ do { \ ++ u32 tmp; \ ++ if (!of_property_read_u32(_np, "marvell," _name, &tmp)) \ ++ _v = tmp; \ ++ } while (0) ++ ++static struct platform_device *port_platdev[3]; ++ ++static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, ++ struct device_node *pnp) ++{ ++ struct platform_device *ppdev; ++ struct mv643xx_eth_platform_data ppd; ++ struct resource res; ++ const char *mac_addr; ++ int ret; ++ ++ memset(&ppd, 0, sizeof(ppd)); ++ ppd.shared = pdev; ++ ++ memset(&res, 0, sizeof(res)); ++ if (!of_irq_to_resource(pnp, 0, &res)) { ++ dev_err(&pdev->dev, "missing interrupt on %s\n", pnp->name); ++ return -EINVAL; ++ } ++ ++ if (of_property_read_u32(pnp, "reg", &ppd.port_number)) { ++ dev_err(&pdev->dev, "missing reg property on %s\n", pnp->name); ++ return -EINVAL; ++ } ++ ++ if (ppd.port_number >= 3) { ++ dev_err(&pdev->dev, "invalid reg property on %s\n", pnp->name); ++ return -EINVAL; ++ } ++ ++ mac_addr = of_get_mac_address(pnp); ++ if (mac_addr) ++ memcpy(ppd.mac_addr, mac_addr, 6); ++ ++ mv643xx_eth_property(pnp, "tx-queue-size", ppd.tx_queue_size); ++ mv643xx_eth_property(pnp, "tx-sram-addr", ppd.tx_sram_addr); ++ mv643xx_eth_property(pnp, "tx-sram-size", ppd.tx_sram_size); ++ mv643xx_eth_property(pnp, "rx-queue-size", ppd.rx_queue_size); ++ mv643xx_eth_property(pnp, "rx-sram-addr", ppd.rx_sram_addr); ++ mv643xx_eth_property(pnp, "rx-sram-size", ppd.rx_sram_size); ++ ++ ppd.phy_node = of_parse_phandle(pnp, "phy-handle", 0); ++ if (!ppd.phy_node) { ++ ppd.phy_addr = MV643XX_ETH_PHY_NONE; ++ of_property_read_u32(pnp, "speed", &ppd.speed); ++ of_property_read_u32(pnp, "duplex", &ppd.duplex); ++ } ++ ++ ppdev = platform_device_alloc(MV643XX_ETH_NAME, ppd.port_number); ++ if (!ppdev) ++ return -ENOMEM; ++ ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); ++ ++ ret = platform_device_add_resources(ppdev, &res, 1); ++ if (ret) ++ goto port_err; ++ ++ ret = platform_device_add_data(ppdev, &ppd, sizeof(ppd)); ++ if (ret) ++ goto port_err; ++ ++ ret = platform_device_add(ppdev); ++ if (ret) ++ goto port_err; ++ ++ port_platdev[ppd.port_number] = ppdev; ++ ++ return 0; ++ ++port_err: ++ platform_device_put(ppdev); ++ return ret; ++} ++ ++static int mv643xx_eth_shared_of_probe(struct platform_device *pdev) ++{ ++ struct mv643xx_eth_shared_platform_data *pd; ++ struct device_node *pnp, *np = pdev->dev.of_node; ++ int ret; ++ ++ /* bail out if not registered from DT */ ++ if (!np) ++ return 0; ++ ++ pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL); ++ if (!pd) ++ return -ENOMEM; ++ pdev->dev.platform_data = pd; ++ ++ mv643xx_eth_property(np, "tx-checksum-limit", pd->tx_csum_limit); ++ ++ for_each_available_child_of_node(np, pnp) { ++ ret = mv643xx_eth_shared_of_add_port(pdev, pnp); ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++ ++static void mv643xx_eth_shared_of_remove(void) ++{ ++ int n; ++ ++ for (n = 0; n < 3; n++) { ++ platform_device_del(port_platdev[n]); ++ port_platdev[n] = NULL; ++ } ++} ++#else ++static int mv643xx_eth_shared_of_probe(struct platform_device *pdev) ++{ ++ return 0 ++} ++ ++#define mv643xx_eth_shared_of_remove() ++#endif ++ + static int mv643xx_eth_shared_probe(struct platform_device *pdev) + { + static int mv643xx_eth_version_printed; +- struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data; ++ struct mv643xx_eth_shared_platform_data *pd; + struct mv643xx_eth_shared_private *msp; + const struct mbus_dram_target_info *dram; + struct resource *res; ++ int ret; + + if (!mv643xx_eth_version_printed++) + 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) + msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL); + if (msp == NULL) + return -ENOMEM; ++ platform_set_drvdata(pdev, msp); + + msp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (msp->base == NULL) +@@ -2488,12 +2627,15 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) + if (dram) + mv643xx_eth_conf_mbus_windows(msp, dram); + ++ ret = mv643xx_eth_shared_of_probe(pdev); ++ if (ret) ++ return ret; ++ pd = pdev->dev.platform_data; ++ + msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ? + pd->tx_csum_limit : 9 * 1024; + infer_hw_params(msp); + +- platform_set_drvdata(pdev, msp); +- + return 0; + } + +@@ -2501,9 +2643,9 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev) + { + struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev); + ++ mv643xx_eth_shared_of_remove(); + if (!IS_ERR(msp->clk)) + clk_disable_unprepare(msp->clk); +- + return 0; + } + +@@ -2513,6 +2655,7 @@ static struct platform_driver mv643xx_eth_shared_driver = { + .driver = { + .name = MV643XX_ETH_SHARED_NAME, + .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(mv643xx_eth_shared_ids), + }, + }; + +@@ -2721,6 +2864,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) + if (!IS_ERR(mp->clk)) { + clk_prepare_enable(mp->clk); + mp->t_clk = clk_get_rate(mp->clk); ++ } else if (!IS_ERR(mp->shared->clk)) { ++ mp->t_clk = clk_get_rate(mp->shared->clk); + } + + set_params(mp, pd); +-- +1.8.4.rc1 + |