From: Andrew Lunn <andrew@lunn.ch>
To: Florian Fainelli <f.fainelli@gmail.com>,
narmstrong@baylibre.com, vivien.didelot@savoirfairelinux.com
Cc: netdev <netdev@vger.kernel.org>, Andrew Lunn <andrew@lunn.ch>
Subject: [PATCH RFC 19/28] net: dsa: bcm_sf2: make it a real platform driver
Date: Wed, 23 Dec 2015 13:56:33 +0100 [thread overview]
Message-ID: <1450875402-20740-20-git-send-email-andrew@lunn.ch> (raw)
In-Reply-To: <1450875402-20740-1-git-send-email-andrew@lunn.ch>
From: Florian Fainelli <f.fainelli@gmail.com>
The Broadcom Starfighter 2 switch driver should be a proper platform
driver, now that the DSA code has been updated to allow that, register
a switch device, feed it with the proper configuration data coming
from Device Tree and register our switch device with DSA.
The bulk of the changes consist in moving what bcm_sf2_sw_setup() did
into the component slave bind function.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
.../devicetree/bindings/net/dsa/broadcom.txt | 48 ++++
drivers/net/dsa/bcm_sf2.c | 248 ++++++++++++---------
2 files changed, 192 insertions(+), 104 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/dsa/broadcom.txt
diff --git a/Documentation/devicetree/bindings/net/dsa/broadcom.txt b/Documentation/devicetree/bindings/net/dsa/broadcom.txt
new file mode 100644
index 000000000000..bd92be0ef2c8
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/broadcom.txt
@@ -0,0 +1,48 @@
+* Broadcom Starfighter 2 integrated switch device
+
+Required properties:
+
+- compatible: should be "brcm,brcm-sf2"
+- reg: addresses and length of the register sets for the device, must be 6
+ pairs of register addresses and lengths
+- interrupts: interrupts for the devices, must be two interrupts
+
+Optional properties:
+
+- reg-names: litteral names for the device base register addresses,
+ when present must be: "core", "reg", "intrl2_0", "intrl2_1", "fcb",
+ "acb"
+
+- interrupt-names: litternal names for the device interrupt lines,
+ when present must be: "switch_0" and "switch_1"
+
+- brcm,num-gphy: specify the maximum number of integrated gigabit PHYs
+ in the switch
+
+- brcm,num-rgmii-ports: specify the maximum number of RGMII interfaces
+ supported by the switch
+
+- brcm,fcb-pause-override: boolean property, if present indicates that
+ the switch supports Failover Control Block pause override capability
+
+- brcm,acb-packets-inflight: boolean property, if present indicates
+ that the switch Admission Control Block supports reporting the
+ number of packets in-flight in a switch queue
+
+Example:
+
+ switchdev0: switchdev0 {
+ compatible = "brcm,brcm-sf2";
+ reg = <0x0 0x40000
+ 0x40000 0x110
+ 0x40340 0x30
+ 0x40380 0x30
+ 0x40400 0x34
+ 0x40600 0x208>;
+ interrupts = <0 0x18 0
+ 0 0x19 0>;
+ brcm,num-gphy = <1>;
+ brcm,num-rgmii-ports = <2>;
+ brcm,fcb-pause-override;
+ brcm,acb-packets-inflight;
+ };
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index a0222ebd31c6..4f95e03b8c64 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -9,6 +9,7 @@
* (at your option) any later version.
*/
+#include <linux/component.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/netdevice.h>
@@ -928,81 +929,8 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv,
static int bcm_sf2_sw_setup(struct dsa_switch *ds, struct device *dev)
{
- const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
- struct bcm_sf2_priv *priv;
- struct device_node *dn;
- void __iomem **base;
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
unsigned int port;
- unsigned int i;
- u32 reg, rev;
- int ret;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- spin_lock_init(&priv->indir_lock);
- mutex_init(&priv->stats_mutex);
-
- /* All the interesting properties are at the parent device_node
- * level
- */
- dn = ds->pd->of_node->parent;
- bcm_sf2_identify_ports(priv, ds->pd->of_node);
-
- priv->irq0 = irq_of_parse_and_map(dn, 0);
- priv->irq1 = irq_of_parse_and_map(dn, 1);
-
- base = &priv->core;
- for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
- *base = of_iomap(dn, i);
- if (*base == NULL) {
- pr_err("unable to find register: %s\n", reg_names[i]);
- ret = -ENOMEM;
- goto out_unmap;
- }
- base++;
- }
-
- ret = bcm_sf2_sw_rst(priv);
- if (ret) {
- pr_err("unable to software reset switch: %d\n", ret);
- goto out_unmap;
- }
-
- /* Disable all interrupts and request them */
- bcm_sf2_intr_disable(priv);
-
- ret = request_irq(priv->irq0, bcm_sf2_switch_0_isr, 0,
- "switch_0", priv);
- if (ret < 0) {
- pr_err("failed to request switch_0 IRQ\n");
- goto out_unmap;
- }
-
- ret = request_irq(priv->irq1, bcm_sf2_switch_1_isr, 0,
- "switch_1", priv);
- if (ret < 0) {
- pr_err("failed to request switch_1 IRQ\n");
- goto out_free_irq0;
- }
-
- /* Reset the MIB counters */
- reg = core_readl(priv, CORE_GMNCFGCFG);
- reg |= RST_MIB_CNT;
- core_writel(priv, reg, CORE_GMNCFGCFG);
- reg &= ~RST_MIB_CNT;
- core_writel(priv, reg, CORE_GMNCFGCFG);
-
- /* Get the maximum number of ports for this switch */
- priv->hw_params.num_ports = core_readl(priv, CORE_IMP0_PRT_ID) + 1;
- if (priv->hw_params.num_ports > DSA_MAX_PORTS)
- priv->hw_params.num_ports = DSA_MAX_PORTS;
-
- /* Assume a single GPHY setup if we can't read that property */
- if (of_property_read_u32(dn, "brcm,num-gphy",
- &priv->hw_params.num_gphy))
- priv->hw_params.num_gphy = 1;
/* Enable all valid ports and disable those unused */
for (port = 0; port < priv->hw_params.num_ports; port++) {
@@ -1031,31 +959,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds, struct device *dev)
else
ds->phys_mii_mask = 0;
- rev = reg_readl(priv, REG_SWITCH_REVISION);
- priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) &
- SWITCH_TOP_REV_MASK;
- priv->hw_params.core_rev = (rev & SF2_REV_MASK);
-
- rev = reg_readl(priv, REG_PHY_REVISION);
- priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;
-
- pr_info("Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: %d, %d\n",
- priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff,
- priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
- priv->core, priv->irq0, priv->irq1);
-
return 0;
-
-out_free_irq0:
- free_irq(priv->irq0, priv);
-out_unmap:
- base = &priv->core;
- for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
- if (*base)
- iounmap(*base);
- base++;
- }
- return ret;
}
static int bcm_sf2_sw_set_addr(struct dsa_switch *ds, u8 *addr)
@@ -1397,19 +1301,155 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = {
.port_fdb_dump = bcm_sf2_sw_fdb_dump,
};
-static int __init bcm_sf2_init(void)
+static int bcm_sf2_sw_bind(struct device *dev,
+ struct device *master, void *data)
{
- register_switch_driver(&bcm_sf2_switch_driver);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct dsa_switch_tree *dst = data;
+ const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
+ struct resource *res;
+ struct dsa_switch *ds;
+ struct bcm_sf2_priv *priv;
+ struct device_node *dn = pdev->dev.of_node;
+ void __iomem **base;
+ unsigned int i;
+ u32 reg, rev;
+ int ret;
+
+ ds = devm_kzalloc(&pdev->dev, sizeof(*ds) + sizeof(*priv), GFP_KERNEL);
+ if (!ds)
+ return -ENOMEM;
+
+ priv = (struct bcm_sf2_priv *)(ds + 1);
+ ds->priv = priv;
+ ds->drv = &bcm_sf2_switch_driver;
+
+ spin_lock_init(&priv->indir_lock);
+ mutex_init(&priv->stats_mutex);
+
+ /* The port information of the switch is in the immediate child
+ * sub-node
+ */
+ bcm_sf2_identify_ports(priv, dn->child);
+
+ priv->irq0 = platform_get_irq(pdev, 0);
+ priv->irq1 = platform_get_irq(pdev, 1);
+
+ base = &priv->core;
+ for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ *base = devm_ioremap_resource(&pdev->dev, res);
+ if (!*base) {
+ dev_err(&pdev->dev,
+ "unable to find register: %s\n", reg_names[i]);
+ return -ENODEV;
+ }
+ base++;
+ }
+
+ ret = bcm_sf2_sw_rst(priv);
+ if (ret) {
+ pr_err("unable to software reset switch: %d\n", ret);
+ return ret;
+ }
+
+ /* Disable all interrupts and request them */
+ bcm_sf2_intr_disable(priv);
+
+ ret = devm_request_irq(&pdev->dev, priv->irq0, bcm_sf2_switch_0_isr, 0,
+ "switch_0", priv);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request switch_0 IRQ\n");
+ return ret;
+ }
+
+ ret = devm_request_irq(&pdev->dev, priv->irq1, bcm_sf2_switch_1_isr, 0,
+ "switch_1", priv);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request switch_1 IRQ\n");
+ return ret;
+ }
+
+ /* Reset the MIB counters */
+ reg = core_readl(priv, CORE_GMNCFGCFG);
+ reg |= RST_MIB_CNT;
+ core_writel(priv, reg, CORE_GMNCFGCFG);
+ reg &= ~RST_MIB_CNT;
+ core_writel(priv, reg, CORE_GMNCFGCFG);
+
+ /* Get the maximum number of ports for this switch */
+ priv->hw_params.num_ports = core_readl(priv, CORE_IMP0_PRT_ID) + 1;
+ if (priv->hw_params.num_ports > DSA_MAX_PORTS)
+ priv->hw_params.num_ports = DSA_MAX_PORTS;
+
+ /* Assume a single GPHY setup if we can't read that property */
+ if (of_property_read_u32(dn, "brcm,num-gphy",
+ &priv->hw_params.num_gphy))
+ priv->hw_params.num_gphy = 1;
+
+ rev = reg_readl(priv, REG_SWITCH_REVISION);
+ priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) &
+ SWITCH_TOP_REV_MASK;
+ priv->hw_params.core_rev = (rev & SF2_REV_MASK);
+
+ rev = reg_readl(priv, REG_PHY_REVISION);
+ priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;
+
+ dev_info(&pdev->dev,
+ "Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: %d, %d\n",
+ priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff,
+ priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
+ priv->core, priv->irq0, priv->irq1);
+
+ platform_set_drvdata(pdev, ds);
+
+ return dsa_switch_register(dst, ds, dn, "Starfighter 2");
+}
+
+static void bcm_sf2_sw_unbind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct dsa_switch *ds = dev_get_drvdata(dev);
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
+
+ /* Disable all ports and interrupts */
+ priv->wol_ports_mask = 0;
+ bcm_sf2_sw_suspend(ds);
+ dsa_switch_unregister(ds);
+}
+
+static const struct component_ops bcm_sf2_component_ops = {
+ .bind = bcm_sf2_sw_bind,
+ .unbind = bcm_sf2_sw_unbind,
+};
+
+static int bcm_sf2_sw_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &bcm_sf2_component_ops);
return 0;
}
-module_init(bcm_sf2_init);
-static void __exit bcm_sf2_exit(void)
+static int bcm_sf2_sw_probe(struct platform_device *pdev)
{
- unregister_switch_driver(&bcm_sf2_switch_driver);
+ return component_add(&pdev->dev, &bcm_sf2_component_ops);
}
-module_exit(bcm_sf2_exit);
+
+static const struct of_device_id bcm_sf2_of_match[] = {
+ { .compatible = "brcm,brcm-sf2" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, bcm_sf2_of_match);
+
+static struct platform_driver bcm_sf2_driver = {
+ .probe = bcm_sf2_sw_probe,
+ .remove = bcm_sf2_sw_remove,
+ .driver = {
+ .name = "brcm-sf2",
+ .of_match_table = bcm_sf2_of_match,
+ },
+};
+module_platform_driver(bcm_sf2_driver);
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Driver for Broadcom Starfighter 2 ethernet switch chip");
--
2.6.3
next prev parent reply other threads:[~2015-12-23 12:57 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-23 12:56 [PATCH RFC 00/28] DSA: Restructure probing Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 01/28] component: remove old add_components method Andrew Lunn
2015-12-23 13:21 ` Russell King - ARM Linux
2015-12-23 15:57 ` Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 02/28] ARM: VF610: Add Zodiac Inflight Innovations development boards Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 03/28] net: dsa: Move platform data allocation for OF Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 04/28] dsa: Rename mv88e6123_61_65 to mv88e6123 to be consistent Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 05/28] net: dsa: Pass the dsa device to the switch drivers Andrew Lunn
2015-12-23 20:36 ` Florian Fainelli
2015-12-23 12:56 ` [PATCH RFC 06/28] net: dsa: Have the switch driver allocate there own private memory Andrew Lunn
2015-12-23 20:39 ` Florian Fainelli
2015-12-23 12:56 ` [PATCH RFC 07/28] net: dsa: Remove allocation of driver " Andrew Lunn
2015-12-23 20:39 ` Florian Fainelli
2015-12-23 12:56 ` [PATCH RFC 08/28] net: dsa: Keep the mii bus and address in the private structure Andrew Lunn
2015-12-23 20:40 ` Florian Fainelli
2016-01-21 20:41 ` Vivien Didelot
2016-01-21 20:50 ` Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 09/28] net: dsa: Add basic support for component master support Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 10/28] net: dsa: Keep a reference to the switch device for component matching Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 11/28] net: dsa: Add slave component matches based on a phandle to the slave Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 12/28] net: dsa: Make dsa,mii-bus optional Andrew Lunn
2015-12-23 20:42 ` Florian Fainelli
2015-12-23 12:56 ` [PATCH RFC 13/28] net: dsa: Add register/unregister functions for switch drivers Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 14/28] net: dsa: Rename DSA probe function Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 15/28] of_mdio: Add "mii-bus" and address property parser Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 16/28] dsa: mv88e6xxx: Use bus in mv88e6xxx_lookup_name() Andrew Lunn
2016-01-21 20:54 ` Vivien Didelot
2015-12-23 12:56 ` [PATCH RFC 17/28] dsa: mv88e6xxx: Add shared code for binding/unbinding a switch driver Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 18/28] dsa: Add platform device support to Marvell switches Andrew Lunn
2016-01-21 21:05 ` Vivien Didelot
2015-12-23 12:56 ` Andrew Lunn [this message]
2015-12-23 20:32 ` [PATCH RFC 19/28] net: dsa: bcm_sf2: make it a real platform driver Florian Fainelli
2015-12-23 12:56 ` [PATCH RFC 20/28] vf610: Zii: Convert rev b to switches as individual devices Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 21/28] net: dsa: Add some debug prints for error cases Andrew Lunn
2015-12-23 20:42 ` Florian Fainelli
2015-12-23 12:56 ` [PATCH RFC 22/28] net: dsa: Setup the switches after all have been probed Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 23/28] net: dsa: Only setup platform switches, not device switches Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 24/28] net: dsa: If a switch fails to probe, defer probing Andrew Lunn
2015-12-23 20:46 ` Florian Fainelli
2015-12-23 12:56 ` [PATCH RFC 25/28] Documentation: DSA: Describe how probe of DSA and switches work Andrew Lunn
2015-12-23 20:48 ` Florian Fainelli
2015-12-23 22:53 ` Andrew Lunn
2015-12-25 1:29 ` Florian Fainelli
2015-12-25 10:00 ` Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 26/28] dsa: Convert mv88e6xxx into a library allowing driver modules Andrew Lunn
2015-12-25 21:47 ` Florian Fainelli
2016-01-21 21:29 ` Vivien Didelot
2016-01-21 21:54 ` Andrew Lunn
2015-12-23 12:56 ` [PATCH RFC 27/28] dsa: slave: Don't reference NULL pointer during phy_disconnect Andrew Lunn
2015-12-23 20:45 ` Florian Fainelli
2015-12-23 12:56 ` [PATCH RFC 28/28] dsa: Destroy fixed link phys after the phy has been disconnected Andrew Lunn
2015-12-23 20:45 ` Florian Fainelli
2015-12-23 20:44 ` [PATCH RFC 00/28] DSA: Restructure probing Florian Fainelli
2015-12-23 22:33 ` Andrew Lunn
2015-12-23 23:13 ` Florian Fainelli
2015-12-24 12:58 ` Andrew Lunn
2015-12-25 1:47 ` Florian Fainelli
2015-12-25 11:31 ` Andrew Lunn
2015-12-25 22:00 ` Florian Fainelli
2015-12-25 23:41 ` Andrew Lunn
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1450875402-20740-20-git-send-email-andrew@lunn.ch \
--to=andrew@lunn.ch \
--cc=f.fainelli@gmail.com \
--cc=narmstrong@baylibre.com \
--cc=netdev@vger.kernel.org \
--cc=vivien.didelot@savoirfairelinux.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).