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/Kconfig | 1 +
17 drivers/net/dsa/mt7530.c | 263 +++++++++++++++++++++++++++++++++++----
18 drivers/net/dsa/mt7530.h | 21 +++-
19 3 files changed, 256 insertions(+), 29 deletions(-)
21 --- a/drivers/net/dsa/Kconfig
22 +++ b/drivers/net/dsa/Kconfig
23 @@ -36,6 +36,7 @@ config NET_DSA_MT7530
24 tristate "MediaTek MT753x and MT7621 Ethernet switch support"
26 select NET_DSA_TAG_MTK
27 + select MEDIATEK_GE_PHY
29 This enables support for the MediaTek MT7530, MT7531, and MT7621
30 Ethernet switch chips.
31 --- a/drivers/net/dsa/mt7530.c
32 +++ b/drivers/net/dsa/mt7530.c
34 #include <linux/mfd/syscon.h>
35 #include <linux/module.h>
36 #include <linux/netdevice.h>
37 +#include <linux/of_irq.h>
38 #include <linux/of_mdio.h>
39 #include <linux/of_net.h>
40 #include <linux/of_platform.h>
41 @@ -602,18 +603,14 @@ mt7530_mib_reset(struct dsa_switch *ds)
42 mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE);
45 -static int mt7530_phy_read(struct dsa_switch *ds, int port, int regnum)
46 +static int mt7530_phy_read(struct mt7530_priv *priv, int port, int regnum)
48 - struct mt7530_priv *priv = ds->priv;
50 return mdiobus_read_nested(priv->bus, port, regnum);
53 -static int mt7530_phy_write(struct dsa_switch *ds, int port, int regnum,
54 +static int mt7530_phy_write(struct mt7530_priv *priv, int port, int regnum,
57 - struct mt7530_priv *priv = ds->priv;
59 return mdiobus_write_nested(priv->bus, port, regnum, val);
62 @@ -791,9 +788,8 @@ out:
66 -mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum)
67 +mt7531_ind_phy_read(struct mt7530_priv *priv, int port, int regnum)
69 - struct mt7530_priv *priv = ds->priv;
73 @@ -809,10 +805,9 @@ mt7531_ind_phy_read(struct dsa_switch *d
77 -mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum,
78 +mt7531_ind_phy_write(struct mt7530_priv *priv, int port, int regnum,
81 - struct mt7530_priv *priv = ds->priv;
85 @@ -828,6 +823,22 @@ mt7531_ind_phy_write(struct dsa_switch *
90 +mt753x_phy_read(struct mii_bus *bus, int port, int regnum)
92 + struct mt7530_priv *priv = bus->priv;
94 + return priv->info->phy_read(priv, port, regnum);
98 +mt753x_phy_write(struct mii_bus *bus, int port, int regnum, u16 val)
100 + struct mt7530_priv *priv = bus->priv;
102 + return priv->info->phy_write(priv, port, regnum, val);
106 mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset,
108 @@ -1991,6 +2002,211 @@ mt7530_setup(struct dsa_switch *ds)
113 +mt7530_irq_thread_fn(int irq, void *dev_id)
115 + struct mt7530_priv *priv = dev_id;
116 + bool handled = false;
120 + mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
121 + val = mt7530_mii_read(priv, MT7530_SYS_INT_STS);
122 + mt7530_mii_write(priv, MT7530_SYS_INT_STS, val);
123 + mutex_unlock(&priv->bus->mdio_lock);
125 + for (p = 0; p < MT7530_NUM_PHYS; p++) {
126 + if (BIT(p) & val) {
129 + irq = irq_find_mapping(priv->irq_domain, p);
130 + handle_nested_irq(irq);
135 + return IRQ_RETVAL(handled);
139 +mt7530_irq_mask(struct irq_data *d)
141 + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
143 + priv->irq_enable &= ~BIT(d->hwirq);
147 +mt7530_irq_unmask(struct irq_data *d)
149 + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
151 + priv->irq_enable |= BIT(d->hwirq);
155 +mt7530_irq_bus_lock(struct irq_data *d)
157 + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
159 + mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
163 +mt7530_irq_bus_sync_unlock(struct irq_data *d)
165 + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
167 + mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable);
168 + mutex_unlock(&priv->bus->mdio_lock);
171 +static struct irq_chip mt7530_irq_chip = {
172 + .name = KBUILD_MODNAME,
173 + .irq_mask = mt7530_irq_mask,
174 + .irq_unmask = mt7530_irq_unmask,
175 + .irq_bus_lock = mt7530_irq_bus_lock,
176 + .irq_bus_sync_unlock = mt7530_irq_bus_sync_unlock,
180 +mt7530_irq_map(struct irq_domain *domain, unsigned int irq,
181 + irq_hw_number_t hwirq)
183 + irq_set_chip_data(irq, domain->host_data);
184 + irq_set_chip_and_handler(irq, &mt7530_irq_chip, handle_simple_irq);
185 + irq_set_nested_thread(irq, true);
186 + irq_set_noprobe(irq);
191 +static const struct irq_domain_ops mt7530_irq_domain_ops = {
192 + .map = mt7530_irq_map,
193 + .xlate = irq_domain_xlate_onecell,
197 +mt7530_setup_mdio_irq(struct mt7530_priv *priv)
199 + struct dsa_switch *ds = priv->ds;
202 + for (p = 0; p < MT7530_NUM_PHYS; p++) {
203 + if (BIT(p) & ds->phys_mii_mask) {
206 + irq = irq_create_mapping(priv->irq_domain, p);
207 + ds->slave_mii_bus->irq[p] = irq;
213 +mt7530_setup_irq(struct mt7530_priv *priv)
215 + struct device *dev = priv->dev;
216 + struct device_node *np = dev->of_node;
219 + if (!of_property_read_bool(np, "interrupt-controller")) {
220 + dev_info(dev, "no interrupt support\n");
224 + priv->irq = of_irq_get(np, 0);
225 + if (priv->irq <= 0) {
226 + dev_err(dev, "failed to get parent IRQ: %d\n", priv->irq);
227 + return priv->irq ? : -EINVAL;
230 + priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
231 + &mt7530_irq_domain_ops, priv);
232 + if (!priv->irq_domain) {
233 + dev_err(dev, "failed to create IRQ domain\n");
237 + /* This register must be set for MT7530 to properly fire interrupts */
238 + if (priv->id != ID_MT7531)
239 + mt7530_set(priv, MT7530_TOP_SIG_CTRL, TOP_SIG_CTRL_NORMAL);
241 + ret = request_threaded_irq(priv->irq, NULL, mt7530_irq_thread_fn,
242 + IRQF_ONESHOT, KBUILD_MODNAME, priv);
244 + irq_domain_remove(priv->irq_domain);
245 + dev_err(dev, "failed to request IRQ: %d\n", ret);
253 +mt7530_free_mdio_irq(struct mt7530_priv *priv)
257 + for (p = 0; p < MT7530_NUM_PHYS; p++) {
258 + if (BIT(p) & priv->ds->phys_mii_mask) {
261 + irq = irq_find_mapping(priv->irq_domain, p);
262 + irq_dispose_mapping(irq);
269 +mt7530_free_irq_common(struct mt7530_priv *priv)
271 + free_irq(priv->irq, priv);
272 + irq_domain_remove(priv->irq_domain);
276 +mt7530_free_irq(struct mt7530_priv *priv)
278 + mt7530_free_mdio_irq(priv);
279 + mt7530_free_irq_common(priv);
283 +mt7530_setup_mdio(struct mt7530_priv *priv)
285 + struct dsa_switch *ds = priv->ds;
286 + struct device *dev = priv->dev;
287 + struct mii_bus *bus;
291 + bus = devm_mdiobus_alloc(dev);
295 + ds->slave_mii_bus = bus;
297 + bus->name = KBUILD_MODNAME "-mii";
298 + snprintf(bus->id, MII_BUS_ID_SIZE, KBUILD_MODNAME "-%d", idx++);
299 + bus->read = mt753x_phy_read;
300 + bus->write = mt753x_phy_write;
302 + bus->phy_mask = ~ds->phys_mii_mask;
305 + mt7530_setup_mdio_irq(priv);
307 + ret = mdiobus_register(bus);
309 + dev_err(dev, "failed to register MDIO bus: %d\n", ret);
311 + mt7530_free_mdio_irq(priv);
318 mt7531_setup(struct dsa_switch *ds)
320 @@ -2798,24 +3014,19 @@ static int
321 mt753x_setup(struct dsa_switch *ds)
323 struct mt7530_priv *priv = ds->priv;
324 + int ret = priv->info->sw_setup(ds);
328 - return priv->info->sw_setup(ds);
332 -mt753x_phy_read(struct dsa_switch *ds, int port, int regnum)
334 - struct mt7530_priv *priv = ds->priv;
336 - return priv->info->phy_read(ds, port, regnum);
338 + ret = mt7530_setup_irq(priv);
343 -mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
345 - struct mt7530_priv *priv = ds->priv;
346 + ret = mt7530_setup_mdio(priv);
347 + if (ret && priv->irq)
348 + mt7530_free_irq_common(priv);
350 - return priv->info->phy_write(ds, port, regnum, val);
354 static int mt753x_get_mac_eee(struct dsa_switch *ds, int port,
355 @@ -2852,8 +3063,6 @@ static const struct dsa_switch_ops mt753
356 .get_tag_protocol = mtk_get_tag_protocol,
357 .setup = mt753x_setup,
358 .get_strings = mt7530_get_strings,
359 - .phy_read = mt753x_phy_read,
360 - .phy_write = mt753x_phy_write,
361 .get_ethtool_stats = mt7530_get_ethtool_stats,
362 .get_sset_count = mt7530_get_sset_count,
363 .set_ageing_time = mt7530_set_ageing_time,
364 --- a/drivers/net/dsa/mt7530.h
365 +++ b/drivers/net/dsa/mt7530.h
369 #define MT7530_NUM_PORTS 7
370 +#define MT7530_NUM_PHYS 5
371 #define MT7530_CPU_PORT 6
372 #define MT7530_NUM_FDB_RECORDS 2048
373 #define MT7530_ALL_MEMBERS 0xff
374 @@ -401,6 +402,12 @@ enum mt7531_sgmii_force_duplex {
375 #define SYS_CTRL_SW_RST BIT(1)
376 #define SYS_CTRL_REG_RST BIT(0)
378 +/* Register for system interrupt */
379 +#define MT7530_SYS_INT_EN 0x7008
381 +/* Register for system interrupt status */
382 +#define MT7530_SYS_INT_STS 0x700c
384 /* Register for PHY Indirect Access Control */
385 #define MT7531_PHY_IAC 0x701C
386 #define MT7531_PHY_ACS_ST BIT(31)
387 @@ -722,6 +729,9 @@ static const char *p5_intf_modes(unsigne
391 +/* Forward declaration */
394 /* struct mt753x_info - This is the main data structure for holding the specific
395 * part for each supported device
396 * @sw_setup: Holding the handler to a device initialization
397 @@ -746,8 +756,8 @@ struct mt753x_info {
400 int (*sw_setup)(struct dsa_switch *ds);
401 - int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
402 - int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val);
403 + int (*phy_read)(struct mt7530_priv *priv, int port, int regnum);
404 + int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val);
405 int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface);
406 int (*cpu_port_config)(struct dsa_switch *ds, int port);
407 bool (*phy_mode_supported)(struct dsa_switch *ds, int port,
408 @@ -781,6 +791,10 @@ struct mt753x_info {
410 * @p6_interface Holding the current port 6 interface
411 * @p5_intf_sel: Holding the current port 5 interface select
413 + * @irq: IRQ number of the switch
414 + * @irq_domain: IRQ domain of the switch irq_chip
415 + * @irq_enable: IRQ enable bits, synced to SYS_INT_EN
419 @@ -802,6 +816,9 @@ struct mt7530_priv {
420 struct mt7530_port ports[MT7530_NUM_PORTS];
421 /* protect among processes for registers access*/
422 struct mutex reg_mutex;
424 + struct irq_domain *irq_domain;
428 struct mt7530_hw_vlan_entry {