kernel: backport MT7530 IRQ support
Support MT7530 PHY link change interrupts, and enable for MT7621. For external MT7530, a GPIO IRQ line is required, which is board-specific, so it should be added to each DTS. In case the interrupt-controller property is missing, it will fall back to polling mode. Signed-off-by: DENG Qingfang <dqfext@gmail.com>
This commit is contained in:
		 DENG Qingfang
					DENG Qingfang
				
			
				
					committed by
					
						 Daniel Golle
						Daniel Golle
					
				
			
			
				
	
			
			
			 Daniel Golle
						Daniel Golle
					
				
			
						parent
						
							8d8d26ba42
						
					
				
				
					commit
					f9cfe7af1f
				
			| @@ -0,0 +1,425 @@ | |||||||
|  | From ba751e28d44255744a30190faad0ca09b455c44d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: DENG Qingfang <dqfext@gmail.com> | ||||||
|  | Date: Wed, 19 May 2021 11:32:00 +0800 | ||||||
|  | Subject: [PATCH] net: dsa: mt7530: add interrupt support | ||||||
|  |  | ||||||
|  | Add support for MT7530 interrupt controller to handle internal PHYs. | ||||||
|  | In order to assign an IRQ number to each PHY, the registration of MDIO bus | ||||||
|  | is also done in this driver. | ||||||
|  |  | ||||||
|  | Signed-off-by: DENG Qingfang <dqfext@gmail.com> | ||||||
|  | Reviewed-by: Andrew Lunn <andrew@lunn.ch> | ||||||
|  | Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||||
|  | Reviewed-by: Vladimir Oltean <olteanv@gmail.com> | ||||||
|  | Signed-off-by: David S. Miller <davem@davemloft.net> | ||||||
|  | --- | ||||||
|  |  drivers/net/dsa/mt7530.c | 264 +++++++++++++++++++++++++++++++++++---- | ||||||
|  |  drivers/net/dsa/mt7530.h |  20 ++- | ||||||
|  |  2 files changed, 256 insertions(+), 28 deletions(-) | ||||||
|  |  | ||||||
|  | --- a/drivers/net/dsa/mt7530.c | ||||||
|  | +++ b/drivers/net/dsa/mt7530.c | ||||||
|  | @@ -10,6 +10,7 @@ | ||||||
|  |  #include <linux/mfd/syscon.h> | ||||||
|  |  #include <linux/module.h> | ||||||
|  |  #include <linux/netdevice.h> | ||||||
|  | +#include <linux/of_irq.h> | ||||||
|  |  #include <linux/of_mdio.h> | ||||||
|  |  #include <linux/of_net.h> | ||||||
|  |  #include <linux/of_platform.h> | ||||||
|  | @@ -602,18 +603,14 @@ mt7530_mib_reset(struct dsa_switch *ds) | ||||||
|  |  	mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int mt7530_phy_read(struct dsa_switch *ds, int port, int regnum) | ||||||
|  | +static int mt7530_phy_read(struct mt7530_priv *priv, int port, int regnum) | ||||||
|  |  { | ||||||
|  | -	struct mt7530_priv *priv = ds->priv; | ||||||
|  | - | ||||||
|  |  	return mdiobus_read_nested(priv->bus, port, regnum); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static int mt7530_phy_write(struct dsa_switch *ds, int port, int regnum, | ||||||
|  | +static int mt7530_phy_write(struct mt7530_priv *priv, int port, int regnum, | ||||||
|  |  			    u16 val) | ||||||
|  |  { | ||||||
|  | -	struct mt7530_priv *priv = ds->priv; | ||||||
|  | - | ||||||
|  |  	return mdiobus_write_nested(priv->bus, port, regnum, val); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -791,9 +788,8 @@ out: | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | -mt7531_ind_phy_read(struct dsa_switch *ds, int port, int regnum) | ||||||
|  | +mt7531_ind_phy_read(struct mt7530_priv *priv, int port, int regnum) | ||||||
|  |  { | ||||||
|  | -	struct mt7530_priv *priv = ds->priv; | ||||||
|  |  	int devad; | ||||||
|  |  	int ret; | ||||||
|  |   | ||||||
|  | @@ -809,10 +805,9 @@ mt7531_ind_phy_read(struct dsa_switch *d | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int | ||||||
|  | -mt7531_ind_phy_write(struct dsa_switch *ds, int port, int regnum, | ||||||
|  | +mt7531_ind_phy_write(struct mt7530_priv *priv, int port, int regnum, | ||||||
|  |  		     u16 data) | ||||||
|  |  { | ||||||
|  | -	struct mt7530_priv *priv = ds->priv; | ||||||
|  |  	int devad; | ||||||
|  |  	int ret; | ||||||
|  |   | ||||||
|  | @@ -828,6 +823,22 @@ mt7531_ind_phy_write(struct dsa_switch * | ||||||
|  |  	return ret; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int | ||||||
|  | +mt753x_phy_read(struct mii_bus *bus, int port, int regnum) | ||||||
|  | +{ | ||||||
|  | +	struct mt7530_priv *priv = bus->priv; | ||||||
|  | + | ||||||
|  | +	return priv->info->phy_read(priv, port, regnum); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  | +mt753x_phy_write(struct mii_bus *bus, int port, int regnum, u16 val) | ||||||
|  | +{ | ||||||
|  | +	struct mt7530_priv *priv = bus->priv; | ||||||
|  | + | ||||||
|  | +	return priv->info->phy_write(priv, port, regnum, val); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static void | ||||||
|  |  mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset, | ||||||
|  |  		   uint8_t *data) | ||||||
|  | @@ -1824,6 +1835,210 @@ mt7530_setup_gpio(struct mt7530_priv *pr | ||||||
|  |  	return devm_gpiochip_add_data(dev, gc, priv); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static irqreturn_t | ||||||
|  | +mt7530_irq_thread_fn(int irq, void *dev_id) | ||||||
|  | +{ | ||||||
|  | +	struct mt7530_priv *priv = dev_id; | ||||||
|  | +	bool handled = false; | ||||||
|  | +	u32 val; | ||||||
|  | +	int p; | ||||||
|  | + | ||||||
|  | +	mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); | ||||||
|  | +	val = mt7530_mii_read(priv, MT7530_SYS_INT_STS); | ||||||
|  | +	mt7530_mii_write(priv, MT7530_SYS_INT_STS, val); | ||||||
|  | +	mutex_unlock(&priv->bus->mdio_lock); | ||||||
|  | + | ||||||
|  | +	for (p = 0; p < MT7530_NUM_PHYS; p++) { | ||||||
|  | +		if (BIT(p) & val) { | ||||||
|  | +			unsigned int irq; | ||||||
|  | + | ||||||
|  | +			irq = irq_find_mapping(priv->irq_domain, p); | ||||||
|  | +			handle_nested_irq(irq); | ||||||
|  | +			handled = true; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return IRQ_RETVAL(handled); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void | ||||||
|  | +mt7530_irq_mask(struct irq_data *d) | ||||||
|  | +{ | ||||||
|  | +	struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); | ||||||
|  | + | ||||||
|  | +	priv->irq_enable &= ~BIT(d->hwirq); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void | ||||||
|  | +mt7530_irq_unmask(struct irq_data *d) | ||||||
|  | +{ | ||||||
|  | +	struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); | ||||||
|  | + | ||||||
|  | +	priv->irq_enable |= BIT(d->hwirq); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void | ||||||
|  | +mt7530_irq_bus_lock(struct irq_data *d) | ||||||
|  | +{ | ||||||
|  | +	struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); | ||||||
|  | + | ||||||
|  | +	mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void | ||||||
|  | +mt7530_irq_bus_sync_unlock(struct irq_data *d) | ||||||
|  | +{ | ||||||
|  | +	struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); | ||||||
|  | + | ||||||
|  | +	mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable); | ||||||
|  | +	mutex_unlock(&priv->bus->mdio_lock); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct irq_chip mt7530_irq_chip = { | ||||||
|  | +	.name = KBUILD_MODNAME, | ||||||
|  | +	.irq_mask = mt7530_irq_mask, | ||||||
|  | +	.irq_unmask = mt7530_irq_unmask, | ||||||
|  | +	.irq_bus_lock = mt7530_irq_bus_lock, | ||||||
|  | +	.irq_bus_sync_unlock = mt7530_irq_bus_sync_unlock, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  | +mt7530_irq_map(struct irq_domain *domain, unsigned int irq, | ||||||
|  | +	       irq_hw_number_t hwirq) | ||||||
|  | +{ | ||||||
|  | +	irq_set_chip_data(irq, domain->host_data); | ||||||
|  | +	irq_set_chip_and_handler(irq, &mt7530_irq_chip, handle_simple_irq); | ||||||
|  | +	irq_set_nested_thread(irq, true); | ||||||
|  | +	irq_set_noprobe(irq); | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static const struct irq_domain_ops mt7530_irq_domain_ops = { | ||||||
|  | +	.map = mt7530_irq_map, | ||||||
|  | +	.xlate = irq_domain_xlate_onecell, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +static void | ||||||
|  | +mt7530_setup_mdio_irq(struct mt7530_priv *priv) | ||||||
|  | +{ | ||||||
|  | +	struct dsa_switch *ds = priv->ds; | ||||||
|  | +	int p; | ||||||
|  | + | ||||||
|  | +	for (p = 0; p < MT7530_NUM_PHYS; p++) { | ||||||
|  | +		if (BIT(p) & ds->phys_mii_mask) { | ||||||
|  | +			unsigned int irq; | ||||||
|  | + | ||||||
|  | +			irq = irq_create_mapping(priv->irq_domain, p); | ||||||
|  | +			ds->slave_mii_bus->irq[p] = irq; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  | +mt7530_setup_irq(struct mt7530_priv *priv) | ||||||
|  | +{ | ||||||
|  | +	struct device *dev = priv->dev; | ||||||
|  | +	struct device_node *np = dev->of_node; | ||||||
|  | +	int ret; | ||||||
|  | + | ||||||
|  | +	if (!of_property_read_bool(np, "interrupt-controller")) { | ||||||
|  | +		dev_info(dev, "no interrupt support\n"); | ||||||
|  | +		return 0; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	priv->irq = of_irq_get(np, 0); | ||||||
|  | +	if (priv->irq <= 0) { | ||||||
|  | +		dev_err(dev, "failed to get parent IRQ: %d\n", priv->irq); | ||||||
|  | +		return priv->irq ? : -EINVAL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS, | ||||||
|  | +						 &mt7530_irq_domain_ops, priv); | ||||||
|  | +	if (!priv->irq_domain) { | ||||||
|  | +		dev_err(dev, "failed to create IRQ domain\n"); | ||||||
|  | +		return -ENOMEM; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* This register must be set for MT7530 to properly fire interrupts */ | ||||||
|  | +	if (priv->id != ID_MT7531) | ||||||
|  | +		mt7530_set(priv, MT7530_TOP_SIG_CTRL, TOP_SIG_CTRL_NORMAL); | ||||||
|  | + | ||||||
|  | +	ret = request_threaded_irq(priv->irq, NULL, mt7530_irq_thread_fn, | ||||||
|  | +				   IRQF_ONESHOT, KBUILD_MODNAME, priv); | ||||||
|  | +	if (ret) { | ||||||
|  | +		irq_domain_remove(priv->irq_domain); | ||||||
|  | +		dev_err(dev, "failed to request IRQ: %d\n", ret); | ||||||
|  | +		return ret; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void | ||||||
|  | +mt7530_free_mdio_irq(struct mt7530_priv *priv) | ||||||
|  | +{ | ||||||
|  | +	int p; | ||||||
|  | + | ||||||
|  | +	for (p = 0; p < MT7530_NUM_PHYS; p++) { | ||||||
|  | +		if (BIT(p) & priv->ds->phys_mii_mask) { | ||||||
|  | +			unsigned int irq; | ||||||
|  | + | ||||||
|  | +			irq = irq_find_mapping(priv->irq_domain, p); | ||||||
|  | +			irq_dispose_mapping(irq); | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void | ||||||
|  | +mt7530_free_irq_common(struct mt7530_priv *priv) | ||||||
|  | +{ | ||||||
|  | +	free_irq(priv->irq, priv); | ||||||
|  | +	irq_domain_remove(priv->irq_domain); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static void | ||||||
|  | +mt7530_free_irq(struct mt7530_priv *priv) | ||||||
|  | +{ | ||||||
|  | +	mt7530_free_mdio_irq(priv); | ||||||
|  | +	mt7530_free_irq_common(priv); | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int | ||||||
|  | +mt7530_setup_mdio(struct mt7530_priv *priv) | ||||||
|  | +{ | ||||||
|  | +	struct dsa_switch *ds = priv->ds; | ||||||
|  | +	struct device *dev = priv->dev; | ||||||
|  | +	struct mii_bus *bus; | ||||||
|  | +	static int idx; | ||||||
|  | +	int ret; | ||||||
|  | + | ||||||
|  | +	bus = devm_mdiobus_alloc(dev); | ||||||
|  | +	if (!bus) | ||||||
|  | +		return -ENOMEM; | ||||||
|  | + | ||||||
|  | +	ds->slave_mii_bus = bus; | ||||||
|  | +	bus->priv = priv; | ||||||
|  | +	bus->name = KBUILD_MODNAME "-mii"; | ||||||
|  | +	snprintf(bus->id, MII_BUS_ID_SIZE, KBUILD_MODNAME "-%d", idx++); | ||||||
|  | +	bus->read = mt753x_phy_read; | ||||||
|  | +	bus->write = mt753x_phy_write; | ||||||
|  | +	bus->parent = dev; | ||||||
|  | +	bus->phy_mask = ~ds->phys_mii_mask; | ||||||
|  | + | ||||||
|  | +	if (priv->irq) | ||||||
|  | +		mt7530_setup_mdio_irq(priv); | ||||||
|  | + | ||||||
|  | +	ret = devm_mdiobus_register(dev, bus); | ||||||
|  | +	if (ret) { | ||||||
|  | +		dev_err(dev, "failed to register MDIO bus: %d\n", ret); | ||||||
|  | +		if (priv->irq) | ||||||
|  | +			mt7530_free_mdio_irq(priv); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int | ||||||
|  |  mt7530_setup(struct dsa_switch *ds) | ||||||
|  |  { | ||||||
|  | @@ -2798,24 +3013,20 @@ static int | ||||||
|  |  mt753x_setup(struct dsa_switch *ds) | ||||||
|  |  { | ||||||
|  |  	struct mt7530_priv *priv = ds->priv; | ||||||
|  | +	int ret = priv->info->sw_setup(ds); | ||||||
|  |   | ||||||
|  | -	return priv->info->sw_setup(ds); | ||||||
|  | -} | ||||||
|  | - | ||||||
|  | -static int | ||||||
|  | -mt753x_phy_read(struct dsa_switch *ds, int port, int regnum) | ||||||
|  | -{ | ||||||
|  | -	struct mt7530_priv *priv = ds->priv; | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  |   | ||||||
|  | -	return priv->info->phy_read(ds, port, regnum); | ||||||
|  | -} | ||||||
|  | +	ret = mt7530_setup_irq(priv); | ||||||
|  | +	if (ret) | ||||||
|  | +		return ret; | ||||||
|  |   | ||||||
|  | -static int | ||||||
|  | -mt753x_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) | ||||||
|  | -{ | ||||||
|  | -	struct mt7530_priv *priv = ds->priv; | ||||||
|  | +	ret = mt7530_setup_mdio(priv); | ||||||
|  | +	if (ret && priv->irq) | ||||||
|  | +		mt7530_free_irq_common(priv); | ||||||
|  |   | ||||||
|  | -	return priv->info->phy_write(ds, port, regnum, val); | ||||||
|  | +	return ret; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static int mt753x_get_mac_eee(struct dsa_switch *ds, int port, | ||||||
|  | @@ -2852,8 +3063,6 @@ static const struct dsa_switch_ops mt753 | ||||||
|  |  	.get_tag_protocol	= mtk_get_tag_protocol, | ||||||
|  |  	.setup			= mt753x_setup, | ||||||
|  |  	.get_strings		= mt7530_get_strings, | ||||||
|  | -	.phy_read		= mt753x_phy_read, | ||||||
|  | -	.phy_write		= mt753x_phy_write, | ||||||
|  |  	.get_ethtool_stats	= mt7530_get_ethtool_stats, | ||||||
|  |  	.get_sset_count		= mt7530_get_sset_count, | ||||||
|  |  	.set_ageing_time	= mt7530_set_ageing_time, | ||||||
|  | @@ -3036,6 +3245,9 @@ mt7530_remove(struct mdio_device *mdiode | ||||||
|  |  		dev_err(priv->dev, "Failed to disable io pwr: %d\n", | ||||||
|  |  			ret); | ||||||
|  |   | ||||||
|  | +	if (priv->irq) | ||||||
|  | +		mt7530_free_irq(priv); | ||||||
|  | + | ||||||
|  |  	dsa_unregister_switch(priv->ds); | ||||||
|  |  	mutex_destroy(&priv->reg_mutex); | ||||||
|  |  } | ||||||
|  | --- a/drivers/net/dsa/mt7530.h | ||||||
|  | +++ b/drivers/net/dsa/mt7530.h | ||||||
|  | @@ -7,6 +7,7 @@ | ||||||
|  |  #define __MT7530_H | ||||||
|  |   | ||||||
|  |  #define MT7530_NUM_PORTS		7 | ||||||
|  | +#define MT7530_NUM_PHYS			5 | ||||||
|  |  #define MT7530_CPU_PORT			6 | ||||||
|  |  #define MT7530_NUM_FDB_RECORDS		2048 | ||||||
|  |  #define MT7530_ALL_MEMBERS		0xff | ||||||
|  | @@ -401,6 +402,12 @@ enum mt7531_sgmii_force_duplex { | ||||||
|  |  #define  SYS_CTRL_SW_RST		BIT(1) | ||||||
|  |  #define  SYS_CTRL_REG_RST		BIT(0) | ||||||
|  |   | ||||||
|  | +/* Register for system interrupt */ | ||||||
|  | +#define MT7530_SYS_INT_EN		0x7008 | ||||||
|  | + | ||||||
|  | +/* Register for system interrupt status */ | ||||||
|  | +#define MT7530_SYS_INT_STS		0x700c | ||||||
|  | + | ||||||
|  |  /* Register for PHY Indirect Access Control */ | ||||||
|  |  #define MT7531_PHY_IAC			0x701C | ||||||
|  |  #define  MT7531_PHY_ACS_ST		BIT(31) | ||||||
|  | @@ -722,6 +729,8 @@ static const char *p5_intf_modes(unsigne | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +struct mt7530_priv; | ||||||
|  | + | ||||||
|  |  /* struct mt753x_info -	This is the main data structure for holding the specific | ||||||
|  |   *			part for each supported device | ||||||
|  |   * @sw_setup:		Holding the handler to a device initialization | ||||||
|  | @@ -746,8 +755,8 @@ struct mt753x_info { | ||||||
|  |  	enum mt753x_id id; | ||||||
|  |   | ||||||
|  |  	int (*sw_setup)(struct dsa_switch *ds); | ||||||
|  | -	int (*phy_read)(struct dsa_switch *ds, int port, int regnum); | ||||||
|  | -	int (*phy_write)(struct dsa_switch *ds, int port, int regnum, u16 val); | ||||||
|  | +	int (*phy_read)(struct mt7530_priv *priv, int port, int regnum); | ||||||
|  | +	int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val); | ||||||
|  |  	int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface); | ||||||
|  |  	int (*cpu_port_config)(struct dsa_switch *ds, int port); | ||||||
|  |  	bool (*phy_mode_supported)(struct dsa_switch *ds, int port, | ||||||
|  | @@ -781,6 +790,10 @@ struct mt753x_info { | ||||||
|  |   *			registers | ||||||
|  |   * @p6_interface	Holding the current port 6 interface | ||||||
|  |   * @p5_intf_sel:	Holding the current port 5 interface select | ||||||
|  | + * | ||||||
|  | + * @irq:		IRQ number of the switch | ||||||
|  | + * @irq_domain:		IRQ domain of the switch irq_chip | ||||||
|  | + * @irq_enable:		IRQ enable bits, synced to SYS_INT_EN | ||||||
|  |   */ | ||||||
|  |  struct mt7530_priv { | ||||||
|  |  	struct device		*dev; | ||||||
|  | @@ -802,6 +815,9 @@ struct mt7530_priv { | ||||||
|  |  	struct mt7530_port	ports[MT7530_NUM_PORTS]; | ||||||
|  |  	/* protect among processes for registers access*/ | ||||||
|  |  	struct mutex reg_mutex; | ||||||
|  | +	int irq; | ||||||
|  | +	struct irq_domain *irq_domain; | ||||||
|  | +	u32 irq_enable; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  struct mt7530_hw_vlan_entry { | ||||||
| @@ -487,6 +487,9 @@ | |||||||
| 				mediatek,mcm; | 				mediatek,mcm; | ||||||
| 				resets = <&rstctrl 2>; | 				resets = <&rstctrl 2>; | ||||||
| 				reset-names = "mcm"; | 				reset-names = "mcm"; | ||||||
|  | 				interrupt-controller; | ||||||
|  | 				#interrupt-cells = <1>; | ||||||
|  | 				interrupts = <GIC_SHARED 23 IRQ_TYPE_LEVEL_HIGH>; | ||||||
|  |  | ||||||
| 				ports { | 				ports { | ||||||
| 					#address-cells = <1>; | 					#address-cells = <1>; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user