linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/8] gpio: exar: refactor the driver
@ 2020-11-04 19:30 Bartosz Golaszewski
  2020-11-04 19:30 ` [PATCH v2 1/8] regmap: provide regmap_assign_bits() Bartosz Golaszewski
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-04 19:30 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight, Mark Brown
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

I just wanted to convert the driver to using simpler IDA API but ended up
quickly converting it to using regmap. Unfortunately I don't have the HW
to test it so marking the patches that introduce functional change as RFT
and Cc'ing the original author.

v1 -> v2:
- add new regmap helper: regmap_assign_bits()
- fix lvl vs sel register access
- set value in direction_output callback

Note: I didn't use the fancy method of offset calculation Andy and David
suggested because this series broke the driver according to Jan - let's
get it right before we modify it any more. I found a couple problems that
could maybe cause the crash. Jan: could you give it another spin?

Bartosz Golaszewski (8):
  regmap: provide regmap_assign_bits()
  gpio: exar: add a newline after the copyright notice
  gpio: exar: include idr.h
  gpio: exar: switch to a simpler IDA interface
  gpio: exar: use a helper variable for &pdev->dev
  gpio: exar: unduplicate address and offset computation
  gpio: exar: switch to using regmap
  gpio: exar: use devm action for freeing the IDA and drop remove()

 drivers/gpio/Kconfig     |   1 +
 drivers/gpio/gpio-exar.c | 151 +++++++++++++++++++--------------------
 include/linux/regmap.h   |  16 +++++
 3 files changed, 90 insertions(+), 78 deletions(-)

-- 
2.29.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 1/8] regmap: provide regmap_assign_bits()
  2020-11-04 19:30 [PATCH v2 0/8] gpio: exar: refactor the driver Bartosz Golaszewski
@ 2020-11-04 19:30 ` Bartosz Golaszewski
  2020-11-04 19:30 ` [PATCH v2 2/8] gpio: exar: add a newline after the copyright notice Bartosz Golaszewski
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-04 19:30 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight, Mark Brown
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski, Andy Shevchenko

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Add another bits helper to regmap API: this one sets given bits if value
is true and clears them if it's false.

Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 include/linux/regmap.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index e7834d98207f..62099e7a3ed6 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -1148,6 +1148,15 @@ static inline int regmap_clear_bits(struct regmap *map,
 	return regmap_update_bits_base(map, reg, bits, 0, NULL, false, false);
 }
 
+static inline int regmap_assign_bits(struct regmap *map, unsigned int reg,
+				     unsigned int bits, bool value)
+{
+	if (value)
+		return regmap_set_bits(map, reg, bits);
+	else
+		return regmap_clear_bits(map, reg, bits);
+}
+
 int regmap_test_bits(struct regmap *map, unsigned int reg, unsigned int bits);
 
 /**
@@ -1554,6 +1563,13 @@ static inline int regmap_clear_bits(struct regmap *map,
 	return -EINVAL;
 }
 
+static inline int regmap_assign_bits(struct regmap *map, unsigned int reg,
+				     unsigned int bits, bool value)
+{
+	WARN_ONCE(1, "regmap API is disabled");
+	return -EINVAL;
+}
+
 static inline int regmap_test_bits(struct regmap *map,
 				   unsigned int reg, unsigned int bits)
 {
-- 
2.29.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 2/8] gpio: exar: add a newline after the copyright notice
  2020-11-04 19:30 [PATCH v2 0/8] gpio: exar: refactor the driver Bartosz Golaszewski
  2020-11-04 19:30 ` [PATCH v2 1/8] regmap: provide regmap_assign_bits() Bartosz Golaszewski
@ 2020-11-04 19:30 ` Bartosz Golaszewski
  2020-11-04 19:30 ` [PATCH v2 3/8] gpio: exar: include idr.h Bartosz Golaszewski
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-04 19:30 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight, Mark Brown
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

It's customary to have a newline between the copyright header and the
includes. Add one to gpio-exar.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/gpio/gpio-exar.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index b1accfba017d..4202dd363a11 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -4,6 +4,7 @@
  *
  * Copyright (C) 2015 Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
  */
+
 #include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/gpio/driver.h>
-- 
2.29.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 3/8] gpio: exar: include idr.h
  2020-11-04 19:30 [PATCH v2 0/8] gpio: exar: refactor the driver Bartosz Golaszewski
  2020-11-04 19:30 ` [PATCH v2 1/8] regmap: provide regmap_assign_bits() Bartosz Golaszewski
  2020-11-04 19:30 ` [PATCH v2 2/8] gpio: exar: add a newline after the copyright notice Bartosz Golaszewski
@ 2020-11-04 19:30 ` Bartosz Golaszewski
  2020-11-04 19:30 ` [PATCH v2 4/8] gpio: exar: switch to a simpler IDA interface Bartosz Golaszewski
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-04 19:30 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight, Mark Brown
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

This driver uses IDA APIs but doesn't include the relevant header. This
fixes it.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/gpio/gpio-exar.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index 4202dd363a11..1941ae533418 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -8,6 +8,7 @@
 #include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/gpio/driver.h>
+#include <linux/idr.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-- 
2.29.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 4/8] gpio: exar: switch to a simpler IDA interface
  2020-11-04 19:30 [PATCH v2 0/8] gpio: exar: refactor the driver Bartosz Golaszewski
                   ` (2 preceding siblings ...)
  2020-11-04 19:30 ` [PATCH v2 3/8] gpio: exar: include idr.h Bartosz Golaszewski
@ 2020-11-04 19:30 ` Bartosz Golaszewski
  2020-11-04 19:30 ` [PATCH v2 5/8] gpio: exar: use a helper variable for &pdev->dev Bartosz Golaszewski
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-04 19:30 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight, Mark Brown
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

We don't need to specify any ranges when allocating IDs so we can switch
to ida_alloc() and ida_free() instead of the ida_simple_ counterparts.

ida_simple_get(ida, 0, 0, gfp) is equivalent to
ida_alloc_range(ida, 0, UINT_MAX, gfp) which is equivalent to
ida_alloc(ida, gfp). Note: IDR will never actually allocate an ID
larger than INT_MAX.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/gpio/gpio-exar.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index 1941ae533418..752e8437ff80 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -149,7 +149,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
 
 	mutex_init(&exar_gpio->lock);
 
-	index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL);
+	index = ida_alloc(&ida_index, GFP_KERNEL);
 	if (index < 0) {
 		ret = index;
 		goto err_mutex_destroy;
@@ -179,7 +179,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
 	return 0;
 
 err_destroy:
-	ida_simple_remove(&ida_index, index);
+	ida_free(&ida_index, index);
 err_mutex_destroy:
 	mutex_destroy(&exar_gpio->lock);
 	return ret;
@@ -189,7 +189,7 @@ static int gpio_exar_remove(struct platform_device *pdev)
 {
 	struct exar_gpio_chip *exar_gpio = platform_get_drvdata(pdev);
 
-	ida_simple_remove(&ida_index, exar_gpio->index);
+	ida_free(&ida_index, exar_gpio->index);
 	mutex_destroy(&exar_gpio->lock);
 
 	return 0;
-- 
2.29.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 5/8] gpio: exar: use a helper variable for &pdev->dev
  2020-11-04 19:30 [PATCH v2 0/8] gpio: exar: refactor the driver Bartosz Golaszewski
                   ` (3 preceding siblings ...)
  2020-11-04 19:30 ` [PATCH v2 4/8] gpio: exar: switch to a simpler IDA interface Bartosz Golaszewski
@ 2020-11-04 19:30 ` Bartosz Golaszewski
  2020-11-04 19:30 ` [RFT PATCH v2 6/8] gpio: exar: unduplicate address and offset computation Bartosz Golaszewski
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-04 19:30 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight, Mark Brown
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

It's more elegant to use a helper local variable to store the address
of the underlying struct device than to dereference pdev everywhere. It
also has the benefit of avoiding unnecessary line breaks.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/gpio/gpio-exar.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index 752e8437ff80..db366d85b6b4 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -120,7 +120,8 @@ static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
 
 static int gpio_exar_probe(struct platform_device *pdev)
 {
-	struct pci_dev *pcidev = to_pci_dev(pdev->dev.parent);
+	struct device *dev = &pdev->dev;
+	struct pci_dev *pcidev = to_pci_dev(dev->parent);
 	struct exar_gpio_chip *exar_gpio;
 	u32 first_pin, ngpios;
 	void __iomem *p;
@@ -134,16 +135,15 @@ static int gpio_exar_probe(struct platform_device *pdev)
 	if (!p)
 		return -ENOMEM;
 
-	ret = device_property_read_u32(&pdev->dev, "exar,first-pin",
-				       &first_pin);
+	ret = device_property_read_u32(dev, "exar,first-pin", &first_pin);
 	if (ret)
 		return ret;
 
-	ret = device_property_read_u32(&pdev->dev, "ngpios", &ngpios);
+	ret = device_property_read_u32(dev, "ngpios", &ngpios);
 	if (ret)
 		return ret;
 
-	exar_gpio = devm_kzalloc(&pdev->dev, sizeof(*exar_gpio), GFP_KERNEL);
+	exar_gpio = devm_kzalloc(dev, sizeof(*exar_gpio), GFP_KERNEL);
 	if (!exar_gpio)
 		return -ENOMEM;
 
@@ -157,7 +157,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
 
 	sprintf(exar_gpio->name, "exar_gpio%d", index);
 	exar_gpio->gpio_chip.label = exar_gpio->name;
-	exar_gpio->gpio_chip.parent = &pdev->dev;
+	exar_gpio->gpio_chip.parent = dev;
 	exar_gpio->gpio_chip.direction_output = exar_direction_output;
 	exar_gpio->gpio_chip.direction_input = exar_direction_input;
 	exar_gpio->gpio_chip.get_direction = exar_get_direction;
@@ -169,8 +169,7 @@ static int gpio_exar_probe(struct platform_device *pdev)
 	exar_gpio->index = index;
 	exar_gpio->first_pin = first_pin;
 
-	ret = devm_gpiochip_add_data(&pdev->dev,
-				     &exar_gpio->gpio_chip, exar_gpio);
+	ret = devm_gpiochip_add_data(dev, &exar_gpio->gpio_chip, exar_gpio);
 	if (ret)
 		goto err_destroy;
 
-- 
2.29.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFT PATCH v2 6/8] gpio: exar: unduplicate address and offset computation
  2020-11-04 19:30 [PATCH v2 0/8] gpio: exar: refactor the driver Bartosz Golaszewski
                   ` (4 preceding siblings ...)
  2020-11-04 19:30 ` [PATCH v2 5/8] gpio: exar: use a helper variable for &pdev->dev Bartosz Golaszewski
@ 2020-11-04 19:30 ` Bartosz Golaszewski
  2020-11-04 19:30 ` [RFT PATCH v2 7/8] gpio: exar: switch to using regmap Bartosz Golaszewski
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-04 19:30 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight, Mark Brown
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

Provide and use helpers for calculating the register address and bit
offset instead of hand coding it in every function.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/gpio/gpio-exar.c | 40 ++++++++++++++++++++++++++++------------
 1 file changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index db366d85b6b4..28b0b4b5fa35 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -33,6 +33,26 @@ struct exar_gpio_chip {
 	unsigned int first_pin;
 };
 
+static unsigned int
+exar_offset_to_sel_addr(struct exar_gpio_chip *exar_gpio, unsigned int offset)
+{
+	return (offset + exar_gpio->first_pin) / 8 ? EXAR_OFFSET_MPIOSEL_HI
+						   : EXAR_OFFSET_MPIOSEL_LO;
+}
+
+static unsigned int
+exar_offset_to_lvl_addr(struct exar_gpio_chip *exar_gpio, unsigned int offset)
+{
+	return (offset + exar_gpio->first_pin) / 8 ? EXAR_OFFSET_MPIOLVL_HI
+						   : EXAR_OFFSET_MPIOLVL_LO;
+}
+
+static unsigned int
+exar_offset_to_bit(struct exar_gpio_chip *exar_gpio, unsigned int offset)
+{
+	return (offset + exar_gpio->first_pin) % 8;
+}
+
 static void exar_update(struct gpio_chip *chip, unsigned int reg, int val,
 			unsigned int offset)
 {
@@ -52,9 +72,8 @@ static int exar_set_direction(struct gpio_chip *chip, int direction,
 			      unsigned int offset)
 {
 	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
-	unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
-		EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
-	unsigned int bit  = (offset + exar_gpio->first_pin) % 8;
+	unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
+	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
 
 	exar_update(chip, addr, direction, bit);
 	return 0;
@@ -75,9 +94,8 @@ static int exar_get(struct gpio_chip *chip, unsigned int reg)
 static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
 {
 	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
-	unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
-		EXAR_OFFSET_MPIOSEL_HI : EXAR_OFFSET_MPIOSEL_LO;
-	unsigned int bit  = (offset + exar_gpio->first_pin) % 8;
+	unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
+	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
 
 	if (exar_get(chip, addr) & BIT(bit))
 		return GPIO_LINE_DIRECTION_IN;
@@ -88,9 +106,8 @@ static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
 static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
 {
 	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
-	unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
-		EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
-	unsigned int bit  = (offset + exar_gpio->first_pin) % 8;
+	unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
+	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
 
 	return !!(exar_get(chip, addr) & BIT(bit));
 }
@@ -99,9 +116,8 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
 			   int value)
 {
 	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
-	unsigned int addr = (offset + exar_gpio->first_pin) / 8 ?
-		EXAR_OFFSET_MPIOLVL_HI : EXAR_OFFSET_MPIOLVL_LO;
-	unsigned int bit  = (offset + exar_gpio->first_pin) % 8;
+	unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
+	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
 
 	exar_update(chip, addr, value, bit);
 }
-- 
2.29.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFT PATCH v2 7/8] gpio: exar: switch to using regmap
  2020-11-04 19:30 [PATCH v2 0/8] gpio: exar: refactor the driver Bartosz Golaszewski
                   ` (5 preceding siblings ...)
  2020-11-04 19:30 ` [RFT PATCH v2 6/8] gpio: exar: unduplicate address and offset computation Bartosz Golaszewski
@ 2020-11-04 19:30 ` Bartosz Golaszewski
  2020-11-04 20:35   ` Andy Shevchenko
  2020-11-05 17:40   ` Mark Brown
  2020-11-04 19:30 ` [PATCH v2 8/8] gpio: exar: use devm action for freeing the IDA and drop remove() Bartosz Golaszewski
  2020-11-04 20:36 ` [PATCH v2 0/8] gpio: exar: refactor the driver Andy Shevchenko
  8 siblings, 2 replies; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-04 19:30 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight, Mark Brown
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

We can simplify the code in gpio-exar by using regmap. This allows us to
drop the mutex (regmap provides its own locking) and we can also reuse
regmap's bit operations instead of implementing our own update function.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/gpio/Kconfig     |  1 +
 drivers/gpio/gpio-exar.c | 87 ++++++++++++++++------------------------
 2 files changed, 35 insertions(+), 53 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 5d4de5cd6759..253a61ec9645 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -255,6 +255,7 @@ config GPIO_EP93XX
 config GPIO_EXAR
 	tristate "Support for GPIO pins on XR17V352/354/358"
 	depends on SERIAL_8250_EXAR
+	select REGMAP_MMIO
 	help
 	  Selecting this option will enable handling of GPIO pins present
 	  on Exar XR17V352/354/358 chips.
diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index 28b0b4b5fa35..94ef500567ef 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 
 #define EXAR_OFFSET_MPIOLVL_LO 0x90
 #define EXAR_OFFSET_MPIOSEL_LO 0x93
@@ -26,9 +27,8 @@ static DEFINE_IDA(ida_index);
 
 struct exar_gpio_chip {
 	struct gpio_chip gpio_chip;
-	struct mutex lock;
+	struct regmap *regs;
 	int index;
-	void __iomem *regs;
 	char name[20];
 	unsigned int first_pin;
 };
@@ -53,51 +53,13 @@ exar_offset_to_bit(struct exar_gpio_chip *exar_gpio, unsigned int offset)
 	return (offset + exar_gpio->first_pin) % 8;
 }
 
-static void exar_update(struct gpio_chip *chip, unsigned int reg, int val,
-			unsigned int offset)
-{
-	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
-	int temp;
-
-	mutex_lock(&exar_gpio->lock);
-	temp = readb(exar_gpio->regs + reg);
-	temp &= ~BIT(offset);
-	if (val)
-		temp |= BIT(offset);
-	writeb(temp, exar_gpio->regs + reg);
-	mutex_unlock(&exar_gpio->lock);
-}
-
-static int exar_set_direction(struct gpio_chip *chip, int direction,
-			      unsigned int offset)
-{
-	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
-	unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
-	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
-
-	exar_update(chip, addr, direction, bit);
-	return 0;
-}
-
-static int exar_get(struct gpio_chip *chip, unsigned int reg)
-{
-	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
-	int value;
-
-	mutex_lock(&exar_gpio->lock);
-	value = readb(exar_gpio->regs + reg);
-	mutex_unlock(&exar_gpio->lock);
-
-	return value;
-}
-
 static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)
 {
 	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
 	unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
 	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
 
-	if (exar_get(chip, addr) & BIT(bit))
+	if (regmap_test_bits(exar_gpio->regs, addr, BIT(bit)))
 		return GPIO_LINE_DIRECTION_IN;
 
 	return GPIO_LINE_DIRECTION_OUT;
@@ -109,7 +71,7 @@ static int exar_get_value(struct gpio_chip *chip, unsigned int offset)
 	unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
 	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
 
-	return !!(exar_get(chip, addr) & BIT(bit));
+	return !!(regmap_test_bits(exar_gpio->regs, addr, BIT(bit)));
 }
 
 static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
@@ -119,21 +81,39 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
 	unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
 	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
 
-	exar_update(chip, addr, value, bit);
+	regmap_assign_bits(exar_gpio->regs, addr, BIT(bit), value);
 }
 
 static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
 				 int value)
 {
+	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
+	unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
+	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
+
 	exar_set_value(chip, offset, value);
-	return exar_set_direction(chip, 0, offset);
+	regmap_clear_bits(exar_gpio->regs, addr, BIT(bit));
+
+	return 0;
 }
 
 static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
 {
-	return exar_set_direction(chip, 1, offset);
+	struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
+	unsigned int addr = exar_offset_to_sel_addr(exar_gpio, offset);
+	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
+
+	regmap_set_bits(exar_gpio->regs, addr, BIT(bit));
+
+	return 0;
 }
 
+static const struct regmap_config exar_regmap_config = {
+	.name		= "exar-gpio",
+	.reg_bits	= 8,
+	.val_bits	= 8,
+};
+
 static int gpio_exar_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -163,13 +143,17 @@ static int gpio_exar_probe(struct platform_device *pdev)
 	if (!exar_gpio)
 		return -ENOMEM;
 
-	mutex_init(&exar_gpio->lock);
+	/*
+	 * We don't need to check the return values of mmio regmap operations (unless
+	 * the regmap has a clock attached which is not the case here).
+	 */
+	exar_gpio->regs = devm_regmap_init_mmio(dev, p, &exar_regmap_config);
+	if (IS_ERR(exar_gpio->regs))
+		return PTR_ERR(exar_gpio->regs);
 
 	index = ida_alloc(&ida_index, GFP_KERNEL);
-	if (index < 0) {
-		ret = index;
-		goto err_mutex_destroy;
-	}
+	if (index < 0)
+		return index;
 
 	sprintf(exar_gpio->name, "exar_gpio%d", index);
 	exar_gpio->gpio_chip.label = exar_gpio->name;
@@ -195,8 +179,6 @@ static int gpio_exar_probe(struct platform_device *pdev)
 
 err_destroy:
 	ida_free(&ida_index, index);
-err_mutex_destroy:
-	mutex_destroy(&exar_gpio->lock);
 	return ret;
 }
 
@@ -205,7 +187,6 @@ static int gpio_exar_remove(struct platform_device *pdev)
 	struct exar_gpio_chip *exar_gpio = platform_get_drvdata(pdev);
 
 	ida_free(&ida_index, exar_gpio->index);
-	mutex_destroy(&exar_gpio->lock);
 
 	return 0;
 }
-- 
2.29.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 8/8] gpio: exar: use devm action for freeing the IDA and drop remove()
  2020-11-04 19:30 [PATCH v2 0/8] gpio: exar: refactor the driver Bartosz Golaszewski
                   ` (6 preceding siblings ...)
  2020-11-04 19:30 ` [RFT PATCH v2 7/8] gpio: exar: switch to using regmap Bartosz Golaszewski
@ 2020-11-04 19:30 ` Bartosz Golaszewski
  2020-11-04 20:36 ` [PATCH v2 0/8] gpio: exar: refactor the driver Andy Shevchenko
  8 siblings, 0 replies; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-04 19:30 UTC (permalink / raw)
  To: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight, Mark Brown
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bgolaszewski@baylibre.com>

We can simplify the error path in probe() and drop remove() entirely if
we provide a devm action for freeing the device ID.

Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
---
 drivers/gpio/gpio-exar.c | 27 ++++++++++++---------------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
index 94ef500567ef..b3372279188d 100644
--- a/drivers/gpio/gpio-exar.c
+++ b/drivers/gpio/gpio-exar.c
@@ -108,6 +108,13 @@ static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)
 	return 0;
 }
 
+static void exar_devm_ida_free(void *data)
+{
+	struct exar_gpio_chip *exar_gpio = data;
+
+	ida_free(&ida_index, exar_gpio->index);
+}
+
 static const struct regmap_config exar_regmap_config = {
 	.name		= "exar-gpio",
 	.reg_bits	= 8,
@@ -155,6 +162,10 @@ static int gpio_exar_probe(struct platform_device *pdev)
 	if (index < 0)
 		return index;
 
+	ret = devm_add_action_or_reset(dev, exar_devm_ida_free, exar_gpio);
+	if (ret)
+		return ret;
+
 	sprintf(exar_gpio->name, "exar_gpio%d", index);
 	exar_gpio->gpio_chip.label = exar_gpio->name;
 	exar_gpio->gpio_chip.parent = dev;
@@ -171,29 +182,15 @@ static int gpio_exar_probe(struct platform_device *pdev)
 
 	ret = devm_gpiochip_add_data(dev, &exar_gpio->gpio_chip, exar_gpio);
 	if (ret)
-		goto err_destroy;
+		return ret;
 
 	platform_set_drvdata(pdev, exar_gpio);
 
-	return 0;
-
-err_destroy:
-	ida_free(&ida_index, index);
-	return ret;
-}
-
-static int gpio_exar_remove(struct platform_device *pdev)
-{
-	struct exar_gpio_chip *exar_gpio = platform_get_drvdata(pdev);
-
-	ida_free(&ida_index, exar_gpio->index);
-
 	return 0;
 }
 
 static struct platform_driver gpio_exar_driver = {
 	.probe	= gpio_exar_probe,
-	.remove	= gpio_exar_remove,
 	.driver	= {
 		.name = DRIVER_NAME,
 	},
-- 
2.29.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [RFT PATCH v2 7/8] gpio: exar: switch to using regmap
  2020-11-04 19:30 ` [RFT PATCH v2 7/8] gpio: exar: switch to using regmap Bartosz Golaszewski
@ 2020-11-04 20:35   ` Andy Shevchenko
  2020-11-05  8:56     ` Bartosz Golaszewski
  2020-11-05 17:40   ` Mark Brown
  1 sibling, 1 reply; 15+ messages in thread
From: Andy Shevchenko @ 2020-11-04 20:35 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight,
	Mark Brown, open list:GPIO SUBSYSTEM, Linux Kernel Mailing List,
	Bartosz Golaszewski

On Wed, Nov 4, 2020 at 9:34 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:

...

> +static const struct regmap_config exar_regmap_config = {
> +       .name           = "exar-gpio",
> +       .reg_bits       = 8,
> +       .val_bits       = 8,
> +};

Looking at gpio-pca953xx regmap conversion I'm wondering shouldn't you
provide a callback to define volatile registers (such as GPIO input
bits)?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 0/8] gpio: exar: refactor the driver
  2020-11-04 19:30 [PATCH v2 0/8] gpio: exar: refactor the driver Bartosz Golaszewski
                   ` (7 preceding siblings ...)
  2020-11-04 19:30 ` [PATCH v2 8/8] gpio: exar: use devm action for freeing the IDA and drop remove() Bartosz Golaszewski
@ 2020-11-04 20:36 ` Andy Shevchenko
  8 siblings, 0 replies; 15+ messages in thread
From: Andy Shevchenko @ 2020-11-04 20:36 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight,
	Mark Brown, open list:GPIO SUBSYSTEM, Linux Kernel Mailing List,
	Bartosz Golaszewski

On Wed, Nov 4, 2020 at 9:34 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>
> From: Bartosz Golaszewski <bgolaszewski@baylibre.com>
>
> I just wanted to convert the driver to using simpler IDA API but ended up
> quickly converting it to using regmap. Unfortunately I don't have the HW
> to test it so marking the patches that introduce functional change as RFT
> and Cc'ing the original author.
>
> v1 -> v2:
> - add new regmap helper: regmap_assign_bits()
> - fix lvl vs sel register access
> - set value in direction_output callback
>
> Note: I didn't use the fancy method of offset calculation Andy and David
> suggested because this series broke the driver according to Jan - let's
> get it right before we modify it any more. I found a couple problems that
> could maybe cause the crash. Jan: could you give it another spin?

I would suggest perform two tests:
 a) full set
 b) with last two patches reverted / not being applied

In that case if the series is still broken we may go with cleanups first.

>
> Bartosz Golaszewski (8):
>   regmap: provide regmap_assign_bits()
>   gpio: exar: add a newline after the copyright notice
>   gpio: exar: include idr.h
>   gpio: exar: switch to a simpler IDA interface
>   gpio: exar: use a helper variable for &pdev->dev
>   gpio: exar: unduplicate address and offset computation
>   gpio: exar: switch to using regmap
>   gpio: exar: use devm action for freeing the IDA and drop remove()
>
>  drivers/gpio/Kconfig     |   1 +
>  drivers/gpio/gpio-exar.c | 151 +++++++++++++++++++--------------------
>  include/linux/regmap.h   |  16 +++++
>  3 files changed, 90 insertions(+), 78 deletions(-)
>
> --
> 2.29.1
>


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFT PATCH v2 7/8] gpio: exar: switch to using regmap
  2020-11-04 20:35   ` Andy Shevchenko
@ 2020-11-05  8:56     ` Bartosz Golaszewski
  0 siblings, 0 replies; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-05  8:56 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight,
	Mark Brown, open list:GPIO SUBSYSTEM, Linux Kernel Mailing List,
	Bartosz Golaszewski

On Wed, Nov 4, 2020 at 9:35 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
>
> On Wed, Nov 4, 2020 at 9:34 PM Bartosz Golaszewski <brgl@bgdev.pl> wrote:
>
> ...
>
> > +static const struct regmap_config exar_regmap_config = {
> > +       .name           = "exar-gpio",
> > +       .reg_bits       = 8,
> > +       .val_bits       = 8,
> > +};
>
> Looking at gpio-pca953xx regmap conversion I'm wondering shouldn't you
> provide a callback to define volatile registers (such as GPIO input
> bits)?
>
> --
> With Best Regards,
> Andy Shevchenko

I think this was done in pca953x due to weird calculations of banks
and registers. For a rather simple driver like this one I don't think
this is needed.

Bartosz

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFT PATCH v2 7/8] gpio: exar: switch to using regmap
  2020-11-04 19:30 ` [RFT PATCH v2 7/8] gpio: exar: switch to using regmap Bartosz Golaszewski
  2020-11-04 20:35   ` Andy Shevchenko
@ 2020-11-05 17:40   ` Mark Brown
  2020-11-06 11:13     ` Bartosz Golaszewski
  1 sibling, 1 reply; 15+ messages in thread
From: Mark Brown @ 2020-11-05 17:40 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight,
	linux-gpio, linux-kernel, Bartosz Golaszewski

[-- Attachment #1: Type: text/plain, Size: 1213 bytes --]

On Wed, Nov 04, 2020 at 08:30:50PM +0100, Bartosz Golaszewski wrote:

> @@ -119,21 +81,39 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
>  	unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
>  	unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
>  
> -	exar_update(chip, addr, value, bit);
> +	regmap_assign_bits(exar_gpio->regs, addr, BIT(bit), value);
>  }

This appears to be the use of _assign_bits() and TBH I'm still both
having a hard time understanding the motivation for it and liking the
name, especially since AFAICT it's only setting a single bit here.  The
above is just

	regmap_update_bits(exar_gpio->regs, addr, 1 << bit, value << bit);

AFAICT (and indeed now I dig around assign_bit() only works on a single
bit and does both shifts which makes the correspondance with that
interface super unclear, we're not mirroring that interface here).  If
you're trying to clone the bitops function it should probably be an
actual clone of the bitops function not something different, that would
be clearer and it'd be easier to understand why someone would want the
API in the first place.  But perhaps I'm missing something here?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFT PATCH v2 7/8] gpio: exar: switch to using regmap
  2020-11-05 17:40   ` Mark Brown
@ 2020-11-06 11:13     ` Bartosz Golaszewski
  2020-11-06 12:17       ` Mark Brown
  0 siblings, 1 reply; 15+ messages in thread
From: Bartosz Golaszewski @ 2020-11-06 11:13 UTC (permalink / raw)
  To: Mark Brown
  Cc: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight,
	open list:GPIO SUBSYSTEM, Linux Kernel Mailing List,
	Bartosz Golaszewski

On Thu, Nov 5, 2020 at 6:41 PM Mark Brown <broonie@kernel.org> wrote:
>
> On Wed, Nov 04, 2020 at 08:30:50PM +0100, Bartosz Golaszewski wrote:
>
> > @@ -119,21 +81,39 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
> >       unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
> >       unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
> >
> > -     exar_update(chip, addr, value, bit);
> > +     regmap_assign_bits(exar_gpio->regs, addr, BIT(bit), value);
> >  }
>
> This appears to be the use of _assign_bits() and TBH I'm still both
> having a hard time understanding the motivation for it and liking the
> name, especially since AFAICT it's only setting a single bit here.  The
> above is just
>
>         regmap_update_bits(exar_gpio->regs, addr, 1 << bit, value << bit);
>
> AFAICT (and indeed now I dig around assign_bit() only works on a single
> bit and does both shifts which makes the correspondance with that
> interface super unclear, we're not mirroring that interface here).  If
> you're trying to clone the bitops function it should probably be an
> actual clone of the bitops function not something different, that would
> be clearer and it'd be easier to understand why someone would want the
> API in the first place.  But perhaps I'm missing something here?

It's true that bitops set/clear/assign bit macros work on single bits
and take their offsets as arguments. However all regmap helpers
operate on masks. Two release cycles back we added two helpers
regmap_set_bits() and regmap_clear_bits() which are just wrappers
around regmap_update_bits(). The naming was inspired by bitops
(because how would one name these operations differently anyway?) but
it was supposed to be able to clear/set multiple bits at once - at
least this was my use-case in mtk-star-emac driver I was writing at
the time and for which I wrote these helpers.

Now the regmap_assign_bits() helper is just an extension to these two
which allows users to use one line instead of four. I'm not trying to
clone bitops - it's just that I don't have a better idea for the
naming.

Bartosz

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFT PATCH v2 7/8] gpio: exar: switch to using regmap
  2020-11-06 11:13     ` Bartosz Golaszewski
@ 2020-11-06 12:17       ` Mark Brown
  0 siblings, 0 replies; 15+ messages in thread
From: Mark Brown @ 2020-11-06 12:17 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Linus Walleij, Andy Shevchenko, Jan Kiszka, David Laight,
	open list:GPIO SUBSYSTEM, Linux Kernel Mailing List,
	Bartosz Golaszewski

[-- Attachment #1: Type: text/plain, Size: 2136 bytes --]

On Fri, Nov 06, 2020 at 12:13:55PM +0100, Bartosz Golaszewski wrote:
> On Thu, Nov 5, 2020 at 6:41 PM Mark Brown <broonie@kernel.org> wrote:

> > AFAICT (and indeed now I dig around assign_bit() only works on a single
> > bit and does both shifts which makes the correspondance with that
> > interface super unclear, we're not mirroring that interface here).  If
> > you're trying to clone the bitops function it should probably be an
> > actual clone of the bitops function not something different, that would
> > be clearer and it'd be easier to understand why someone would want the
> > API in the first place.  But perhaps I'm missing something here?

> It's true that bitops set/clear/assign bit macros work on single bits
> and take their offsets as arguments. However all regmap helpers
> operate on masks. Two release cycles back we added two helpers
> regmap_set_bits() and regmap_clear_bits() which are just wrappers
> around regmap_update_bits(). The naming was inspired by bitops
> (because how would one name these operations differently anyway?) but
> it was supposed to be able to clear/set multiple bits at once - at
> least this was my use-case in mtk-star-emac driver I was writing at
> the time and for which I wrote these helpers.

Which is fine and not at all unclear since there's no separate value
argument, the value comes along with the name.  

> Now the regmap_assign_bits() helper is just an extension to these two
> which allows users to use one line instead of four. I'm not trying to
> clone bitops - it's just that I don't have a better idea for the
> naming.

I really don't see the benefit to the helper, it makes sense in the
context of bitops where the operation does all the shifting and it's
only a single bit but for regmap where it's dealing with bitmasks as
well and the naming doesn't make it crystal clear I can only see this
being confusing to people.  Had the set and clear helpers for regmap
been done as single bits it'd be a lot easier but that's not the case
and it'd also be odd to have just this one helper that took a shift
rather than a bitmask.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2020-11-06 12:17 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-04 19:30 [PATCH v2 0/8] gpio: exar: refactor the driver Bartosz Golaszewski
2020-11-04 19:30 ` [PATCH v2 1/8] regmap: provide regmap_assign_bits() Bartosz Golaszewski
2020-11-04 19:30 ` [PATCH v2 2/8] gpio: exar: add a newline after the copyright notice Bartosz Golaszewski
2020-11-04 19:30 ` [PATCH v2 3/8] gpio: exar: include idr.h Bartosz Golaszewski
2020-11-04 19:30 ` [PATCH v2 4/8] gpio: exar: switch to a simpler IDA interface Bartosz Golaszewski
2020-11-04 19:30 ` [PATCH v2 5/8] gpio: exar: use a helper variable for &pdev->dev Bartosz Golaszewski
2020-11-04 19:30 ` [RFT PATCH v2 6/8] gpio: exar: unduplicate address and offset computation Bartosz Golaszewski
2020-11-04 19:30 ` [RFT PATCH v2 7/8] gpio: exar: switch to using regmap Bartosz Golaszewski
2020-11-04 20:35   ` Andy Shevchenko
2020-11-05  8:56     ` Bartosz Golaszewski
2020-11-05 17:40   ` Mark Brown
2020-11-06 11:13     ` Bartosz Golaszewski
2020-11-06 12:17       ` Mark Brown
2020-11-04 19:30 ` [PATCH v2 8/8] gpio: exar: use devm action for freeing the IDA and drop remove() Bartosz Golaszewski
2020-11-04 20:36 ` [PATCH v2 0/8] gpio: exar: refactor the driver Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).