[PATCH 2/3] gpio: 104-idi-48: Migrate to regmap API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The regmap API supports IO port accessors so we can take advantage of
regmap abstractions rather than handling access to the device registers
directly in the driver.

Signed-off-by: William Breathitt Gray <william.gray@xxxxxxxxxx>
---
 drivers/gpio/gpio-104-idi-48.c | 54 ++++++++++++++++++++++++----------
 1 file changed, 39 insertions(+), 15 deletions(-)

diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
index c5e231fde1af..5d9de5b5e7af 100644
--- a/drivers/gpio/gpio-104-idi-48.c
+++ b/drivers/gpio/gpio-104-idi-48.c
@@ -8,9 +8,9 @@
  */
 #include <linux/bits.h>
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/gpio/driver.h>
-#include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/irqdesc.h>
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/regmap.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
@@ -43,22 +44,27 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
  * @port0:	Port 0 Inputs
  * @unused:	Unused
  * @port1:	Port 1 Inputs
- * @irq:	Read: IRQ Status Register/IRQ Clear
- *		Write: IRQ Enable/Disable
  */
 struct idi_48_reg {
 	u8 port0[3];
 	u8 unused;
 	u8 port1[3];
-	u8 irq;
 };
 
+#define IDI48_NAME "104-idi-48"
+
+#define IDI48_REGS_OFFSET 0x3
+#define IDI48_IRQ_STATUS 0x0
+#define IDI48_IRQ_CLEAR 0x0
+#define IDI48_IRQ_ENABLE 0x0
+
 /**
  * struct idi_48_gpio - GPIO device private data structure
  * @chip:	instance of the gpio_chip
  * @lock:	synchronization lock to prevent I/O race conditions
  * @irq_mask:	input bits affected by interrupts
  * @reg:	I/O address offset for the device registers
+ * @map:	device register map
  * @cos_enb:	Change-Of-State IRQ enable boundaries mask
  */
 struct idi_48_gpio {
@@ -66,6 +72,7 @@ struct idi_48_gpio {
 	spinlock_t lock;
 	unsigned char irq_mask[6];
 	struct idi_48_reg __iomem *reg;
+	struct regmap *map;
 	unsigned char cos_enb;
 };
 
@@ -122,7 +129,7 @@ static void idi_48_irq_mask(struct irq_data *data)
 
 	idi48gpio->cos_enb &= ~BIT(boundary);
 
-	iowrite8(idi48gpio->cos_enb, &idi48gpio->reg->irq);
+	regmap_write(idi48gpio->map, IDI48_IRQ_ENABLE, idi48gpio->cos_enb);
 
 exit:
 	spin_unlock_irqrestore(&idi48gpio->lock, flags);
@@ -151,7 +158,7 @@ static void idi_48_irq_unmask(struct irq_data *data)
 
 	idi48gpio->cos_enb |= BIT(boundary);
 
-	iowrite8(idi48gpio->cos_enb, &idi48gpio->reg->irq);
+	regmap_write(idi48gpio->map, IDI48_IRQ_ENABLE, idi48gpio->cos_enb);
 
 exit:
 	spin_unlock_irqrestore(&idi48gpio->lock, flags);
@@ -168,7 +175,7 @@ static int idi_48_irq_set_type(struct irq_data *data, unsigned int flow_type)
 }
 
 static const struct irq_chip idi_48_irqchip = {
-	.name = "104-idi-48",
+	.name = IDI48_NAME,
 	.irq_ack = idi_48_irq_ack,
 	.irq_mask = idi_48_irq_mask,
 	.irq_unmask = idi_48_irq_unmask,
@@ -180,6 +187,7 @@ static const struct irq_chip idi_48_irqchip = {
 static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
 {
 	struct idi_48_gpio *const idi48gpio = dev_id;
+	unsigned int irq_status;
 	unsigned long cos_status;
 	unsigned long boundary;
 	unsigned long irq_mask;
@@ -189,7 +197,8 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
 
 	spin_lock(&idi48gpio->lock);
 
-	cos_status = ioread8(&idi48gpio->reg->irq);
+	regmap_read(idi48gpio->map, IDI48_IRQ_STATUS, &irq_status);
+	cos_status = irq_status;
 
 	/* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
 	if (cos_status & BIT(6)) {
@@ -231,18 +240,27 @@ static const char *idi48_names[IDI48_NGPIO] = {
 static int idi_48_irq_init_hw(struct gpio_chip *gc)
 {
 	struct idi_48_gpio *const idi48gpio = gpiochip_get_data(gc);
+	unsigned int val;
 
 	/* Disable IRQ by default */
-	iowrite8(0, &idi48gpio->reg->irq);
-	ioread8(&idi48gpio->reg->irq);
-
-	return 0;
+	regmap_write(idi48gpio->map, IDI48_IRQ_ENABLE, 0x00);
+	return regmap_read(idi48gpio->map, IDI48_IRQ_CLEAR, &val);
 }
 
+static const struct regmap_config idi48_regmap_config = {
+	.name = IDI48_NAME,
+	.reg_bits = 8,
+	.val_bits = 8,
+	.reg_stride = 1,
+	.io_port = true,
+	.max_register = 0x0,
+};
+
 static int idi_48_probe(struct device *dev, unsigned int id)
 {
 	struct idi_48_gpio *idi48gpio;
 	const char *const name = dev_name(dev);
+	void __iomem *regs;
 	struct gpio_irq_chip *girq;
 	int err;
 
@@ -256,9 +274,15 @@ static int idi_48_probe(struct device *dev, unsigned int id)
 		return -EBUSY;
 	}
 
-	idi48gpio->reg = devm_ioport_map(dev, base[id], IDI_48_EXTENT);
-	if (!idi48gpio->reg)
+	regs = devm_ioport_map(dev, base[id], IDI_48_EXTENT);
+	if (!regs)
 		return -ENOMEM;
+	idi48gpio->reg = regs;
+
+	idi48gpio->map = devm_regmap_init_mmio(dev, regs + IDI48_REGS_OFFSET,
+					       &idi48_regmap_config);
+	if (IS_ERR(idi48gpio->map))
+		return PTR_ERR(idi48gpio->map);
 
 	idi48gpio->chip.label = name;
 	idi48gpio->chip.parent = dev;
@@ -302,7 +326,7 @@ static int idi_48_probe(struct device *dev, unsigned int id)
 static struct isa_driver idi_48_driver = {
 	.probe = idi_48_probe,
 	.driver = {
-		.name = "104-idi-48"
+		.name = IDI48_NAME,
 	},
 };
 module_isa_driver_with_irq(idi_48_driver, num_idi_48, num_irq);
-- 
2.37.3




[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux