summaryrefslogtreecommitdiff
path: root/target/linux/kirkwood/patches-3.10/0023-net-mv643xx_eth-add-DT-parsing-support.patch
diff options
context:
space:
mode:
authorluka <luka@3c298f89-4303-0410-b956-a3cf2f4a3e73>2013-10-02 00:33:47 +0000
committerluka <luka@3c298f89-4303-0410-b956-a3cf2f4a3e73>2013-10-02 00:33:47 +0000
commit7730eb8430d5e708c1b649173045bdf3c4056b9c (patch)
tree46a17cfdfe54d9f96fdfb53263ba377c738d1bff /target/linux/kirkwood/patches-3.10/0023-net-mv643xx_eth-add-DT-parsing-support.patch
parentd8eb02a921fa2c06118347231f3fd69285b8a5c7 (diff)
kirkwood: add linux 3.10 support
Backport appropriate patches to allow using device tree only board defintions. Signed-off-by: Jonas Gorski <jogo@openwrt.org> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@38280 3c298f89-4303-0410-b956-a3cf2f4a3e73
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.patch329
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 = <&ethphy>;
++ 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
+