1 From ba751e28d44255744a30190faad0ca09b455c44d Mon Sep 17 00:00:00 2001
2 From: DENG Qingfang <dqfext@gmail.com>
3 Date: Wed, 19 May 2021 11:32:00 +0800
4 Subject: [PATCH] net: dsa: mt7530: add interrupt support
6 Add support for MT7530 interrupt controller to handle internal PHYs.
7 In order to assign an IRQ number to each PHY, the registration of MDIO bus
8 is also done in this driver.
10 Signed-off-by: DENG Qingfang <dqfext@gmail.com>
11 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
12 Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
13 Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
14 Signed-off-by: David S. Miller <davem@davemloft.net>
16 drivers/net/dsa/mt7530.c | 264 +++++++++++++++++++++++++++++++++++----
17 drivers/net/dsa/mt7530.h | 20 ++-
18 2 files changed, 256 insertions(+), 28 deletions(-)
20 --- a/drivers/net/dsa/mt7530.c
21 +++ b/drivers/net/dsa/mt7530.c
23 #include <linux/mfd/syscon.h>
24 #include <linux/module.h>
25 #include <linux/netdevice.h>
26 +#include <linux/of_irq.h>
27 #include <linux/of_mdio.h>
28 #include <linux/of_net.h>
29 #include <linux/of_platform.h>
30 @@ -603,18 +604,14 @@ mt7530_mib_reset(struct dsa_switch *ds)
31 mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE);
34 -static int mt7530_phy_read(struct dsa_switch *ds, int port, int regnum)
35 +static int mt7530_phy_read(struct mt7530_priv *priv, int port, int regnum)
37 - struct mt7530_priv *priv = ds->priv;
39 return mdiobus_read_nested(priv->bus, port, regnum);
42 -static int mt7530_phy_write(struct dsa_switch *ds, int port, int regnum,
43 +static int mt7530_phy_write(struct mt7530_priv *priv, int port, int regnum,
46 - struct mt7530_priv *priv = ds->priv;
48 return mdiobus_write_nested(priv->bus, port, regnum, val);
51 @@ -792,9 +789,8 @@ out:
55 -mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum)
56 +mt7531_ind_phy_read(struct mt7530_priv *priv, int port, int regnum)
58 - struct mt7530_priv *priv = ds->priv;
62 @@ -810,10 +806,9 @@ mt7531_ind_phy_read(struct dsa_switch *d
66 -mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum,
67 +mt7531_ind_phy_write(struct mt7530_priv *priv, int port, int regnum,
70 - struct mt7530_priv *priv = ds->priv;
74 @@ -829,6 +824,22 @@ mt7531_ind_phy_write(struct dsa_switch *
79 +mt753x_phy_read(struct mii_bus *bus, int port, int regnum)
81 + struct mt7530_priv *priv = bus->priv;
83 + return priv->info->phy_read(priv, port, regnum);
87 +mt753x_phy_write(struct mii_bus *bus, int port, int regnum, u16 val)
89 + struct mt7530_priv *priv = bus->priv;
91 + return priv->info->phy_write(priv, port, regnum, val);
95 mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset,
97 @@ -1796,6 +1807,210 @@ mt7530_setup_gpio(struct mt7530_priv *pr
98 return devm_gpiochip_add_data(dev, gc, priv);
102 +mt7530_irq_thread_fn(int irq, void *dev_id)
104 + struct mt7530_priv *priv = dev_id;
105 + bool handled = false;
109 + mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
110 + val = mt7530_mii_read(priv, MT7530_SYS_INT_STS);
111 + mt7530_mii_write(priv, MT7530_SYS_INT_STS, val);
112 + mutex_unlock(&priv->bus->mdio_lock);
114 + for (p = 0; p < MT7530_NUM_PHYS; p++) {
115 + if (BIT(p) & val) {
118 + irq = irq_find_mapping(priv->irq_domain, p);
119 + handle_nested_irq(irq);
124 + return IRQ_RETVAL(handled);
128 +mt7530_irq_mask(struct irq_data *d)
130 + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
132 + priv->irq_enable &= ~BIT(d->hwirq);
136 +mt7530_irq_unmask(struct irq_data *d)
138 + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
140 + priv->irq_enable |= BIT(d->hwirq);
144 +mt7530_irq_bus_lock(struct irq_data *d)
146 + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
148 + mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
152 +mt7530_irq_bus_sync_unlock(struct irq_data *d)
154 + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
156 + mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable);
157 + mutex_unlock(&priv->bus->mdio_lock);
160 +static struct irq_chip mt7530_irq_chip = {
161 + .name = KBUILD_MODNAME,
162 + .irq_mask = mt7530_irq_mask,
163 + .irq_unmask = mt7530_irq_unmask,
164 + .irq_bus_lock = mt7530_irq_bus_lock,
165 + .irq_bus_sync_unlock = mt7530_irq_bus_sync_unlock,
169 +mt7530_irq_map(struct irq_domain *domain, unsigned int irq,
170 + irq_hw_number_t hwirq)
172 + irq_set_chip_data(irq, domain->host_data);
173 + irq_set_chip_and_handler(irq, &mt7530_irq_chip, handle_simple_irq);
174 + irq_set_nested_thread(irq, true);
175 + irq_set_noprobe(irq);
180 +static const struct irq_domain_ops mt7530_irq_domain_ops = {
181 + .map = mt7530_irq_map,
182 + .xlate = irq_domain_xlate_onecell,
186 +mt7530_setup_mdio_irq(struct mt7530_priv *priv)
188 + struct dsa_switch *ds = priv->ds;
191 + for (p = 0; p < MT7530_NUM_PHYS; p++) {
192 + if (BIT(p) & ds->phys_mii_mask) {
195 + irq = irq_create_mapping(priv->irq_domain, p);
196 + ds->slave_mii_bus->irq[p] = irq;
202 +mt7530_setup_irq(struct mt7530_priv *priv)
204 + struct device *dev = priv->dev;
205 + struct device_node *np = dev->of_node;
208 + if (!of_property_read_bool(np, "interrupt-controller")) {
209 + dev_info(dev, "no interrupt support\n");
213 + priv->irq = of_irq_get(np, 0);
214 + if (priv->irq <= 0) {
215 + dev_err(dev, "failed to get parent IRQ: %d\n", priv->irq);
216 + return priv->irq ? : -EINVAL;
219 + priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
220 + &mt7530_irq_domain_ops, priv);
221 + if (!priv->irq_domain) {
222 + dev_err(dev, "failed to create IRQ domain\n");
226 + /* This register must be set for MT7530 to properly fire interrupts */
227 + if (priv->id != ID_MT7531)
228 + mt7530_set(priv, MT7530_TOP_SIG_CTRL, TOP_SIG_CTRL_NORMAL);
230 + ret = request_threaded_irq(priv->irq, NULL, mt7530_irq_thread_fn,
231 + IRQF_ONESHOT, KBUILD_MODNAME, priv);
233 + irq_domain_remove(priv->irq_domain);
234 + dev_err(dev, "failed to request IRQ: %d\n", ret);
242 +mt7530_free_mdio_irq(struct mt7530_priv *priv)
246 + for (p = 0; p < MT7530_NUM_PHYS; p++) {
247 + if (BIT(p) & priv->ds->phys_mii_mask) {
250 + irq = irq_find_mapping(priv->irq_domain, p);
251 + irq_dispose_mapping(irq);
257 +mt7530_free_irq_common(struct mt7530_priv *priv)
259 + free_irq(priv->irq, priv);
260 + irq_domain_remove(priv->irq_domain);
264 +mt7530_free_irq(struct mt7530_priv *priv)
266 + mt7530_free_mdio_irq(priv);
267 + mt7530_free_irq_common(priv);
271 +mt7530_setup_mdio(struct mt7530_priv *priv)
273 + struct dsa_switch *ds = priv->ds;
274 + struct device *dev = priv->dev;
275 + struct mii_bus *bus;
279 + bus = devm_mdiobus_alloc(dev);
283 + ds->slave_mii_bus = bus;
285 + bus->name = KBUILD_MODNAME "-mii";
286 + snprintf(bus->id, MII_BUS_ID_SIZE, KBUILD_MODNAME "-%d", idx++);
287 + bus->read = mt753x_phy_read;
288 + bus->write = mt753x_phy_write;
290 + bus->phy_mask = ~ds->phys_mii_mask;
293 + mt7530_setup_mdio_irq(priv);
295 + ret = devm_mdiobus_register(dev, bus);
297 + dev_err(dev, "failed to register MDIO bus: %d\n", ret);
299 + mt7530_free_mdio_irq(priv);
306 mt7530_setup(struct dsa_switch *ds)
308 @@ -2747,24 +2962,20 @@ static int
309 mt753x_setup(struct dsa_switch *ds)
311 struct mt7530_priv *priv = ds->priv;
312 + int ret = priv->info->sw_setup(ds);
314 - return priv->info->sw_setup(ds);
318 -mt753x_phy_read(struct dsa_switch *ds, int port, int regnum)
320 - struct mt7530_priv *priv = ds->priv;
324 - return priv->info->phy_read(ds, port, regnum);
326 + ret = mt7530_setup_irq(priv);
331 -mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
333 - struct mt7530_priv *priv = ds->priv;
334 + ret = mt7530_setup_mdio(priv);
335 + if (ret && priv->irq)
336 + mt7530_free_irq_common(priv);
338 - return priv->info->phy_write(ds, port, regnum, val);
342 static int mt753x_get_mac_eee(struct dsa_switch *ds, int port,
343 @@ -2801,8 +3012,6 @@ static const struct dsa_switch_ops mt753
344 .get_tag_protocol = mtk_get_tag_protocol,
345 .setup = mt753x_setup,
346 .get_strings = mt7530_get_strings,
347 - .phy_read = mt753x_phy_read,
348 - .phy_write = mt753x_phy_write,
349 .get_ethtool_stats = mt7530_get_ethtool_stats,
350 .get_sset_count = mt7530_get_sset_count,
351 .set_ageing_time = mt7530_set_ageing_time,
352 @@ -2985,6 +3194,9 @@ mt7530_remove(struct mdio_device *mdiode
353 dev_err(priv->dev, "Failed to disable io pwr: %d\n",
357 + mt7530_free_irq(priv);
359 dsa_unregister_switch(priv->ds);
360 mutex_destroy(&priv->reg_mutex);
362 --- a/drivers/net/dsa/mt7530.h
363 +++ b/drivers/net/dsa/mt7530.h
367 #define MT7530_NUM_PORTS 7
368 +#define MT7530_NUM_PHYS 5
369 #define MT7530_CPU_PORT 6
370 #define MT7530_NUM_FDB_RECORDS 2048
371 #define MT7530_ALL_MEMBERS 0xff
372 @@ -392,6 +393,12 @@ enum mt7531_sgmii_force_duplex {
373 #define SYS_CTRL_SW_RST BIT(1)
374 #define SYS_CTRL_REG_RST BIT(0)
376 +/* Register for system interrupt */
377 +#define MT7530_SYS_INT_EN 0x7008
379 +/* Register for system interrupt status */
380 +#define MT7530_SYS_INT_STS 0x700c
382 /* Register for PHY Indirect Access Control */
383 #define MT7531_PHY_IAC 0x701C
384 #define MT7531_PHY_ACS_ST BIT(31)
385 @@ -713,6 +720,8 @@ static const char *p5_intf_modes(unsigne
391 /* struct mt753x_info - This is the main data structure for holding the specific
392 * part for each supported device
393 * @sw_setup: Holding the handler to a device initialization
394 @@ -737,8 +746,8 @@ struct mt753x_info {
397 int (*sw_setup)(struct dsa_switch *ds);
398 - int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
399 - int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val);
400 + int (*phy_read)(struct mt7530_priv *priv, int port, int regnum);
401 + int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val);
402 int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface);
403 int (*cpu_port_config)(struct dsa_switch *ds, int port);
404 bool (*phy_mode_supported)(struct dsa_switch *ds, int port,
405 @@ -772,6 +781,10 @@ struct mt753x_info {
407 * @p6_interface Holding the current port 6 interface
408 * @p5_intf_sel: Holding the current port 5 interface select
410 + * @irq: IRQ number of the switch
411 + * @irq_domain: IRQ domain of the switch irq_chip
412 + * @irq_enable: IRQ enable bits, synced to SYS_INT_EN
416 @@ -793,6 +806,9 @@ struct mt7530_priv {
417 struct mt7530_port ports[MT7530_NUM_PORTS];
418 /* protect among processes for registers access*/
419 struct mutex reg_mutex;
421 + struct irq_domain *irq_domain;
425 struct mt7530_hw_vlan_entry {