diff mbox series

[net-next,v4,5/6] net: dsa: microchip: use common irq routines for girq and pirq

Message ID 20220922071028.18012-6-arun.ramadoss@microchip.com (mailing list archive)
State Accepted
Commit e1add7dd6183b9d4184847c310f8dd9f1a2ba7a4
Delegated to: Netdev Maintainers
Headers show
Series net: dsa: microchip: ksz9477: enable interrupt for internal phy link detection | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers success CCed 11 of 11 maintainers
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 392 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Arun Ramadoss Sept. 22, 2022, 7:10 a.m. UTC
The global port interrupt routines and individual ports interrupt
routines has similar implementation except the mask & status register
and number of nested irqs in them.  The mask & status register and
pointer to ksz_device is added to ksz_irq and uses the ksz_irq as
irq_chip_data.

Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com>
---
 drivers/net/dsa/microchip/ksz_common.c | 264 +++++++------------------
 drivers/net/dsa/microchip/ksz_common.h |   9 +-
 2 files changed, 81 insertions(+), 192 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 605ce3ffbeff..d612181b3226 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -1768,97 +1768,97 @@  static int ksz_mdio_register(struct ksz_device *dev)
 	return ret;
 }
 
-static void ksz_girq_mask(struct irq_data *d)
+static void ksz_irq_mask(struct irq_data *d)
 {
-	struct ksz_device *dev = irq_data_get_irq_chip_data(d);
-	unsigned int n = d->hwirq;
+	struct ksz_irq *kirq = irq_data_get_irq_chip_data(d);
 
-	dev->girq.masked |= (1 << n);
+	kirq->masked |= BIT(d->hwirq);
 }
 
-static void ksz_girq_unmask(struct irq_data *d)
+static void ksz_irq_unmask(struct irq_data *d)
 {
-	struct ksz_device *dev = irq_data_get_irq_chip_data(d);
-	unsigned int n = d->hwirq;
+	struct ksz_irq *kirq = irq_data_get_irq_chip_data(d);
 
-	dev->girq.masked &= ~(1 << n);
+	kirq->masked &= ~BIT(d->hwirq);
 }
 
-static void ksz_girq_bus_lock(struct irq_data *d)
+static void ksz_irq_bus_lock(struct irq_data *d)
 {
-	struct ksz_device *dev = irq_data_get_irq_chip_data(d);
+	struct ksz_irq *kirq  = irq_data_get_irq_chip_data(d);
 
-	mutex_lock(&dev->lock_irq);
+	mutex_lock(&kirq->dev->lock_irq);
 }
 
-static void ksz_girq_bus_sync_unlock(struct irq_data *d)
+static void ksz_irq_bus_sync_unlock(struct irq_data *d)
 {
-	struct ksz_device *dev = irq_data_get_irq_chip_data(d);
+	struct ksz_irq *kirq  = irq_data_get_irq_chip_data(d);
+	struct ksz_device *dev = kirq->dev;
 	int ret;
 
-	ret = ksz_write32(dev, REG_SW_PORT_INT_MASK__4, dev->girq.masked);
+	ret = ksz_write32(dev, kirq->reg_mask, kirq->masked);
 	if (ret)
 		dev_err(dev->dev, "failed to change IRQ mask\n");
 
 	mutex_unlock(&dev->lock_irq);
 }
 
-static const struct irq_chip ksz_girq_chip = {
-	.name			= "ksz-global",
-	.irq_mask		= ksz_girq_mask,
-	.irq_unmask		= ksz_girq_unmask,
-	.irq_bus_lock		= ksz_girq_bus_lock,
-	.irq_bus_sync_unlock	= ksz_girq_bus_sync_unlock,
+static const struct irq_chip ksz_irq_chip = {
+	.name			= "ksz-irq",
+	.irq_mask		= ksz_irq_mask,
+	.irq_unmask		= ksz_irq_unmask,
+	.irq_bus_lock		= ksz_irq_bus_lock,
+	.irq_bus_sync_unlock	= ksz_irq_bus_sync_unlock,
 };
 
-static int ksz_girq_domain_map(struct irq_domain *d,
-			       unsigned int irq, irq_hw_number_t hwirq)
+static int ksz_irq_domain_map(struct irq_domain *d,
+			      unsigned int irq, irq_hw_number_t hwirq)
 {
-	struct ksz_device *dev = d->host_data;
-
 	irq_set_chip_data(irq, d->host_data);
-	irq_set_chip_and_handler(irq, &dev->girq.chip, handle_level_irq);
+	irq_set_chip_and_handler(irq, &ksz_irq_chip, handle_level_irq);
 	irq_set_noprobe(irq);
 
 	return 0;
 }
 
-static const struct irq_domain_ops ksz_girq_domain_ops = {
-	.map	= ksz_girq_domain_map,
+static const struct irq_domain_ops ksz_irq_domain_ops = {
+	.map	= ksz_irq_domain_map,
 	.xlate	= irq_domain_xlate_twocell,
 };
 
-static void ksz_girq_free(struct ksz_device *dev)
+static void ksz_irq_free(struct ksz_irq *kirq)
 {
 	int irq, virq;
 
-	free_irq(dev->irq, dev);
+	free_irq(kirq->irq_num, kirq);
 
-	for (irq = 0; irq < dev->girq.nirqs; irq++) {
-		virq = irq_find_mapping(dev->girq.domain, irq);
+	for (irq = 0; irq < kirq->nirqs; irq++) {
+		virq = irq_find_mapping(kirq->domain, irq);
 		irq_dispose_mapping(virq);
 	}
 
-	irq_domain_remove(dev->girq.domain);
+	irq_domain_remove(kirq->domain);
 }
 
-static irqreturn_t ksz_girq_thread_fn(int irq, void *dev_id)
+static irqreturn_t ksz_irq_thread_fn(int irq, void *dev_id)
 {
-	struct ksz_device *dev = dev_id;
+	struct ksz_irq *kirq = dev_id;
 	unsigned int nhandled = 0;
+	struct ksz_device *dev;
 	unsigned int sub_irq;
-	unsigned int n;
-	u32 data;
+	u8 data;
 	int ret;
+	u8 n;
 
-	/* Read global interrupt status register */
-	ret = ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data);
+	dev = kirq->dev;
+
+	/* Read interrupt status register */
+	ret = ksz_read8(dev, kirq->reg_status, &data);
 	if (ret)
 		goto out;
 
-	for (n = 0; n < dev->girq.nirqs; ++n) {
-		if (data & (1 << n)) {
-			sub_irq = irq_find_mapping(dev->girq.domain, n);
+	for (n = 0; n < kirq->nirqs; ++n) {
+		if (data & BIT(n)) {
+			sub_irq = irq_find_mapping(kirq->domain, n);
 			handle_nested_irq(sub_irq);
 			++nhandled;
 		}
@@ -1867,177 +1867,63 @@  static irqreturn_t ksz_girq_thread_fn(int irq, void *dev_id)
 	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
 }
 
-static int ksz_girq_setup(struct ksz_device *dev)
+static int ksz_irq_common_setup(struct ksz_device *dev, struct ksz_irq *kirq)
 {
-	int ret, irq;
+	int ret, n;
 
-	dev->girq.nirqs = dev->info->port_cnt;
-	dev->girq.domain = irq_domain_add_simple(NULL, dev->girq.nirqs, 0,
-						 &ksz_girq_domain_ops, dev);
-	if (!dev->girq.domain)
-		return -ENOMEM;
+	kirq->dev = dev;
+	kirq->masked = ~0;
 
-	for (irq = 0; irq < dev->girq.nirqs; irq++)
-		irq_create_mapping(dev->girq.domain, irq);
+	kirq->domain = irq_domain_add_simple(dev->dev->of_node, kirq->nirqs, 0,
+					     &ksz_irq_domain_ops, kirq);
+	if (!kirq->domain)
+		return -ENOMEM;
 
-	dev->girq.chip = ksz_girq_chip;
-	dev->girq.masked = ~0;
+	for (n = 0; n < kirq->nirqs; n++)
+		irq_create_mapping(kirq->domain, n);
 
-	ret = request_threaded_irq(dev->irq, NULL, ksz_girq_thread_fn,
+	ret = request_threaded_irq(kirq->irq_num, NULL, ksz_irq_thread_fn,
 				   IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
-				   dev_name(dev->dev), dev);
+				   kirq->name, kirq);
 	if (ret)
 		goto out;
 
 	return 0;
 
 out:
-	ksz_girq_free(dev);
+	ksz_irq_free(kirq);
 
 	return ret;
 }
 
-static void ksz_pirq_mask(struct irq_data *d)
-{
-	struct ksz_port *port = irq_data_get_irq_chip_data(d);
-	unsigned int n = d->hwirq;
-
-	port->pirq.masked |= (1 << n);
-}
-
-static void ksz_pirq_unmask(struct irq_data *d)
-{
-	struct ksz_port *port = irq_data_get_irq_chip_data(d);
-	unsigned int n = d->hwirq;
-
-	port->pirq.masked &= ~(1 << n);
-}
-
-static void ksz_pirq_bus_lock(struct irq_data *d)
-{
-	struct ksz_port *port = irq_data_get_irq_chip_data(d);
-	struct ksz_device *dev = port->ksz_dev;
-
-	mutex_lock(&dev->lock_irq);
-}
-
-static void ksz_pirq_bus_sync_unlock(struct irq_data *d)
-{
-	struct ksz_port *port = irq_data_get_irq_chip_data(d);
-	struct ksz_device *dev = port->ksz_dev;
-
-	ksz_pwrite8(dev, port->num, REG_PORT_INT_MASK, port->pirq.masked);
-	mutex_unlock(&dev->lock_irq);
-}
-
-static const struct irq_chip ksz_pirq_chip = {
-	.name			= "ksz-port",
-	.irq_mask		= ksz_pirq_mask,
-	.irq_unmask		= ksz_pirq_unmask,
-	.irq_bus_lock		= ksz_pirq_bus_lock,
-	.irq_bus_sync_unlock	= ksz_pirq_bus_sync_unlock,
-};
-
-static int ksz_pirq_domain_map(struct irq_domain *d, unsigned int irq,
-			       irq_hw_number_t hwirq)
-{
-	struct ksz_port *port = d->host_data;
-
-	irq_set_chip_data(irq, d->host_data);
-	irq_set_chip_and_handler(irq, &port->pirq.chip, handle_level_irq);
-	irq_set_noprobe(irq);
-
-	return 0;
-}
-
-static const struct irq_domain_ops ksz_pirq_domain_ops = {
-	.map	= ksz_pirq_domain_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
-static void ksz_pirq_free(struct ksz_device *dev, u8 p)
-{
-	struct ksz_port *port = &dev->ports[p];
-	int irq, virq;
-	int irq_num;
-
-	irq_num = irq_find_mapping(dev->girq.domain, p);
-	if (irq_num < 0)
-		return;
-
-	free_irq(irq_num, port);
-
-	for (irq = 0; irq < port->pirq.nirqs; irq++) {
-		virq = irq_find_mapping(port->pirq.domain, irq);
-		irq_dispose_mapping(virq);
-	}
-
-	irq_domain_remove(port->pirq.domain);
-}
-
-static irqreturn_t ksz_pirq_thread_fn(int irq, void *dev_id)
+static int ksz_girq_setup(struct ksz_device *dev)
 {
-	struct ksz_port *port = dev_id;
-	unsigned int nhandled = 0;
-	struct ksz_device *dev;
-	unsigned int sub_irq;
-	unsigned int n;
-	u8 data;
-
-	dev = port->ksz_dev;
+	struct ksz_irq *girq = &dev->girq;
 
-	/* Read port interrupt status register */
-	ksz_pread8(dev, port->num, REG_PORT_INT_STATUS, &data);
+	girq->nirqs = dev->info->port_cnt;
+	girq->reg_mask = REG_SW_PORT_INT_MASK__1;
+	girq->reg_status = REG_SW_PORT_INT_STATUS__1;
+	snprintf(girq->name, sizeof(girq->name), "global_port_irq");
 
-	for (n = 0; n < port->pirq.nirqs; ++n) {
-		if (data & (1 << n)) {
-			sub_irq = irq_find_mapping(port->pirq.domain, n);
-			handle_nested_irq(sub_irq);
-			++nhandled;
-		}
-	}
+	girq->irq_num = dev->irq;
 
-	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+	return ksz_irq_common_setup(dev, girq);
 }
 
 static int ksz_pirq_setup(struct ksz_device *dev, u8 p)
 {
-	struct ksz_port *port = &dev->ports[p];
-	int ret, irq;
-	int irq_num;
-
-	port->pirq.nirqs = dev->info->port_nirqs;
-	port->pirq.domain = irq_domain_add_simple(dev->dev->of_node,
-						  port->pirq.nirqs, 0,
-						  &ksz_pirq_domain_ops,
-						  port);
-	if (!port->pirq.domain)
-		return -ENOMEM;
-
-	for (irq = 0; irq < port->pirq.nirqs; irq++)
-		irq_create_mapping(port->pirq.domain, irq);
-
-	port->pirq.chip = ksz_pirq_chip;
-	port->pirq.masked = ~0;
+	struct ksz_irq *pirq = &dev->ports[p].pirq;
 
-	irq_num = irq_find_mapping(dev->girq.domain, p);
-	if (irq_num < 0)
-		return irq_num;
+	pirq->nirqs = dev->info->port_nirqs;
+	pirq->reg_mask = dev->dev_ops->get_port_addr(p, REG_PORT_INT_MASK);
+	pirq->reg_status = dev->dev_ops->get_port_addr(p, REG_PORT_INT_STATUS);
+	snprintf(pirq->name, sizeof(pirq->name), "port_irq-%d", p);
 
-	snprintf(port->pirq.name, sizeof(port->pirq.name), "port_irq-%d", p);
+	pirq->irq_num = irq_find_mapping(dev->girq.domain, p);
+	if (pirq->irq_num < 0)
+		return pirq->irq_num;
 
-	ret = request_threaded_irq(irq_num, NULL, ksz_pirq_thread_fn,
-				   IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
-				   port->pirq.name, port);
-	if (ret)
-		goto out;
-
-	return 0;
-
-out:
-	ksz_pirq_free(dev, p);
-
-	return ret;
+	return ksz_irq_common_setup(dev, pirq);
 }
 
 static int ksz_setup(struct dsa_switch *ds)
@@ -2119,10 +2005,10 @@  static int ksz_setup(struct dsa_switch *ds)
 out_pirq:
 	if (dev->irq > 0)
 		dsa_switch_for_each_user_port(dp, dev->ds)
-			ksz_pirq_free(dev, dp->index);
+			ksz_irq_free(&dev->ports[dp->index].pirq);
 out_girq:
 	if (dev->irq > 0)
-		ksz_girq_free(dev);
+		ksz_irq_free(&dev->girq);
 
 	return ret;
 }
@@ -2134,9 +2020,9 @@  static void ksz_teardown(struct dsa_switch *ds)
 
 	if (dev->irq > 0) {
 		dsa_switch_for_each_user_port(dp, dev->ds)
-			ksz_pirq_free(dev, dp->index);
+			ksz_irq_free(&dev->ports[dp->index].pirq);
 
-		ksz_girq_free(dev);
+		ksz_irq_free(&dev->girq);
 	}
 
 	if (dev->dev_ops->teardown)
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 6edce587bfd2..9cfa179575ce 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -72,10 +72,13 @@  struct ksz_chip_data {
 
 struct ksz_irq {
 	u16 masked;
-	struct irq_chip chip;
+	u16 reg_mask;
+	u16 reg_status;
 	struct irq_domain *domain;
 	int nirqs;
+	int irq_num;
 	char name[16];
+	struct ksz_device *dev;
 };
 
 struct ksz_port {
@@ -574,8 +577,8 @@  static inline int is_lan937x(struct ksz_device *dev)
 #define P_MII_SEL_M			0x3
 
 /* Interrupt */
-#define REG_SW_PORT_INT_STATUS__4	0x0018
-#define REG_SW_PORT_INT_MASK__4		0x001C
+#define REG_SW_PORT_INT_STATUS__1	0x001B
+#define REG_SW_PORT_INT_MASK__1		0x001F
 
 #define REG_PORT_INT_STATUS		0x001B
 #define REG_PORT_INT_MASK		0x001F