Skip to contentSkip to conversation

Fix pinctrl-single pcs_pin_dbg_show()

PATCH Superseded Hanna Hawa 2 participants 7 messages Mar 17, 2021 – Mar 19, 2021

Subsystems (3)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore

Hanna Hawa

author
#0 lore raw

v2 cover Fix pinctrl-single pcs_pin_dbg_show()

These patches fix the pcs_pin_dbg_show() function for the scenario where a single register controls multiple pins (i.e. bits_per_mux is not zero) Additionally, the common formula is moved to a separate function to allow reuse.

Changes since v2:
-----------------
- move read() register to be outside of if condition (as it common read()).
- Remove extra parentheses
- replace offset variable by direct return statements

Changes since v1:
-----------------
- remove unused variable in In function 'pcs_allocate_pin_table' (Reported-by: kernel test robot <[email protected]>)

Hanna Hawa (3):
pinctrl: pinctrl-single: remove unused variable
pinctrl: pinctrl-single: remove unused parameter
pinctrl: pinctrl-single: fix pcs_pin_dbg_show() when bits_per_mux is
not zero

 drivers/pinctrl/pinctrl-single.c | 67 +++++++++++++++++++-------------
 1 file changed, 39 insertions(+), 28 deletions(-)
Signature · 1 line
2.17.1
author
#1 lore raw

PATCH v3 1/3 pinctrl: pinctrl-single: remove unused variable

Remove unused parameter 'num_pins_in_register' from pcs_allocate_pin_table().

---
 drivers/pinctrl/pinctrl-single.c | 2 --
 1 file changed, 2 deletions(-)
drivers/pinctrl/pinctrl-single.c +0 -2
index 7771316dfffa..91c638b85d2c 100644
@@ -703,14 +703,12 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
 static int pcs_allocate_pin_table(struct pcs_device *pcs)
 {
 	int mux_bytes, nr_pins, i;
-	int num_pins_in_register = 0;
 
 	mux_bytes = pcs->width / BITS_PER_BYTE;
 
 	if (pcs->bits_per_mux) {
 		pcs->bits_per_pin = fls(pcs->fmask);
 		nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
-		num_pins_in_register = pcs->width / pcs->bits_per_pin;
 	} else {
 		nr_pins = pcs->size / mux_bytes;
 	}
Signature · 1 line
2.17.1
author
#2 lore raw

PATCH v3 2/3 pinctrl: pinctrl-single: remove unused parameter

In reply to Hanna Hawa

Remove unused parameter 'pin_pos' from pcs_add_pin().

---
 drivers/pinctrl/pinctrl-single.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)
drivers/pinctrl/pinctrl-single.c +2 -6
index 91c638b85d2c..f3394517cb2e 100644
@@ -656,10 +656,8 @@ static const struct pinconf_ops pcs_pinconf_ops = {
  * pcs_add_pin() - add a pin to the static per controller pin array
  * @pcs: pcs driver instance
  * @offset: register offset from base
- * @pin_pos: unused
  */
-static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
-		unsigned pin_pos)
+static int pcs_add_pin(struct pcs_device *pcs, unsigned int offset)
 {
 	struct pcs_soc_data *pcs_soc = &pcs->socdata;
 	struct pinctrl_pin_desc *pin;
@@ -727,16 +725,14 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
 		unsigned offset;
 		int res;
 		int byte_num;
-		int pin_pos = 0;
 
 		if (pcs->bits_per_mux) {
 			byte_num = (pcs->bits_per_pin * i) / BITS_PER_BYTE;
 			offset = (byte_num / mux_bytes) * mux_bytes;
-			pin_pos = i % num_pins_in_register;
 		} else {
 			offset = i * mux_bytes;
 		}
-		res = pcs_add_pin(pcs, offset, pin_pos);
+		res = pcs_add_pin(pcs, offset);
 		if (res < 0) {
 			dev_err(pcs->dev, "error adding pins: %i\n", res);
 			return res;
Signature · 1 line
2.17.1
author
#3 lore raw

PATCH v3 3/3 pinctrl: pinctrl-single: fix pcs_pin_dbg_show() when bits_per_mux is not zero

In reply to Hanna Hawa

An SError was detected when trying to print the supported pins in a pinctrl device which supports multiple pins per register. This change fixes the pcs_pin_dbg_show() in pinctrl-single driver when bits_per_mux is not zero. In addition move offset calculation and pin offset in register to common function.

Fixes 4e7e8017a80e ("pinctrl: pinctrl-single: enhance to configure multiple pins of different modules")
---
 drivers/pinctrl/pinctrl-single.c | 57 +++++++++++++++++++++-----------
 1 file changed, 37 insertions(+), 20 deletions(-)
drivers/pinctrl/pinctrl-single.c +37 -20
index f3394517cb2e..4595acf6545e 100644
@@ -270,20 +270,46 @@ static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg)
 	writel(val, reg);
 }
 
+static unsigned int pcs_pin_reg_offset_get(struct pcs_device *pcs,
+					   unsigned int pin)
+{
+	unsigned int mux_bytes;
+
+	mux_bytes = pcs->width / BITS_PER_BYTE;
+
+	if (pcs->bits_per_mux) {
+		unsigned int pin_offset_bytes;
+
+		pin_offset_bytes = (pcs->bits_per_pin * pin) / BITS_PER_BYTE;
+		return (pin_offset_bytes / mux_bytes) * mux_bytes;
+	}
+
+	return pin * mux_bytes;
+}
+
+static unsigned int pcs_pin_shift_reg_get(struct pcs_device *pcs,
+					  unsigned int pin)
+{
+	return (pin % (pcs->width / pcs->bits_per_pin)) * pcs->bits_per_pin;
+}
+
 static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
 					struct seq_file *s,
 					unsigned pin)
 {
 	struct pcs_device *pcs;
-	unsigned val, mux_bytes;
+	unsigned int val;
 	unsigned long offset;
 	size_t pa;
 
 	pcs = pinctrl_dev_get_drvdata(pctldev);
 
-	mux_bytes = pcs->width / BITS_PER_BYTE;
-	offset = pin * mux_bytes;
+	offset = pcs_pin_reg_offset_get(pcs, pin);
 	val = pcs->read(pcs->base + offset);
+
+	if (pcs->bits_per_mux)
+		val &= pcs->fmask << pcs_pin_shift_reg_get(pcs, pin);
+
 	pa = pcs->res->start + offset;
 
 	seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME);
@@ -384,7 +410,6 @@ static int pcs_request_gpio(struct pinctrl_dev *pctldev,
 	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
 	struct pcs_gpiofunc_range *frange = NULL;
 	struct list_head *pos, *tmp;
-	int mux_bytes = 0;
 	unsigned data;
 
 	/* If function mask is null, return directly. */
@@ -392,29 +417,27 @@ static int pcs_request_gpio(struct pinctrl_dev *pctldev,
 		return -ENOTSUPP;
 
 	list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
+		u32 offset;
+
 		frange = list_entry(pos, struct pcs_gpiofunc_range, node);
 		if (pin >= frange->offset + frange->npins
 			|| pin < frange->offset)
 			continue;
-		mux_bytes = pcs->width / BITS_PER_BYTE;
 
-		if (pcs->bits_per_mux) {
-			int byte_num, offset, pin_shift;
+		offset = pcs_pin_reg_offset_get(pcs, pin);
 
-			byte_num = (pcs->bits_per_pin * pin) / BITS_PER_BYTE;
-			offset = (byte_num / mux_bytes) * mux_bytes;
-			pin_shift = pin % (pcs->width / pcs->bits_per_pin) *
-				    pcs->bits_per_pin;
+		if (pcs->bits_per_mux) {
+			int pin_shift = pcs_pin_shift_reg_get(pcs, pin);
 
 			data = pcs->read(pcs->base + offset);
 			data &= ~(pcs->fmask << pin_shift);
 			data |= frange->gpiofunc << pin_shift;
 			pcs->write(data, pcs->base + offset);
 		} else {
-			data = pcs->read(pcs->base + pin * mux_bytes);
+			data = pcs->read(pcs->base + offset);
 			data &= ~pcs->fmask;
 			data |= frange->gpiofunc;
-			pcs->write(data, pcs->base + pin * mux_bytes);
+			pcs->write(data, pcs->base + offset);
 		}
 		break;
 	}
@@ -724,14 +747,8 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
 	for (i = 0; i < pcs->desc.npins; i++) {
 		unsigned offset;
 		int res;
-		int byte_num;
 
-		if (pcs->bits_per_mux) {
-			byte_num = (pcs->bits_per_pin * i) / BITS_PER_BYTE;
-			offset = (byte_num / mux_bytes) * mux_bytes;
-		} else {
-			offset = i * mux_bytes;
-		}
+		offset = pcs_pin_reg_offset_get(pcs, i);
 		res = pcs_add_pin(pcs, offset);
 		if (res < 0) {
 			dev_err(pcs->dev, "error adding pins: %i\n", res);
Signature · 1 line
2.17.1
Reviewed-by on v3 3/3
#4 lore raw

Re: [PATCH v3 3/3] pinctrl: pinctrl-single: fix pcs_pin_dbg_show() when bits_per_mux is not zero

Quoted 3 lines · Hanna Hawa

An SError was detected when trying to print the supported pins in a

What is SError? Yes, I have read a discussion, but here is the hint:
if a person sees this as a first text due to, for example, bisecting an issue, what she/he can get from this cryptic name?

Quoted 4 lines

pinctrl device which supports multiple pins per register. This change fixes the pcs_pin_dbg_show() in pinctrl-single driver when bits_per_mux is not zero. In addition move offset calculation and pin offset in register to common function.

Quoted 11 lines
Fixes 4e7e8017a80e ("pinctrl: pinctrl-single: enhance to configure multiple pins of different modules")
---
 drivers/pinctrl/pinctrl-single.c | 57 +++++++++++++++++++++-----------
 1 file changed, 37 insertions(+), 20 deletions(-)
drivers/pinctrl/pinctrl-single.c +0 -0
index f3394517cb2e..4595acf6545e 100644

drivers/pinctrl/pinctrl-single.c static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg) · line 279

Quoted 10 lines
drivers/pinctrl/pinctrl-single.c +6 -0
@@ -270,20 +270,46 @@ static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg)
        writel(val, reg);
 }
 
+static unsigned int pcs_pin_reg_offset_get(struct pcs_device *pcs,
+                                          unsigned int pin)
+{
 
+       unsigned int mux_bytes;
+
+       mux_bytes = pcs->width / BITS_PER_BYTE;

Can be folded to one line.

drivers/pinctrl/pinctrl-single.c static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg) · line 284

Quoted 5 lines
drivers/pinctrl/pinctrl-single.c +5 -0
+       if (pcs->bits_per_mux) {
+               unsigned int pin_offset_bytes;
+
+               pin_offset_bytes = (pcs->bits_per_pin * pin) / BITS_PER_BYTE;
+               return (pin_offset_bytes / mux_bytes) * mux_bytes;

Side note for the further improvements (in a separate change, because I see that you just copied an original code, and after all this is just a fix patch): this can be replaced by round down APIs (one which works for arbitrary divisors).

drivers/pinctrl/pinctrl-single.c static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg) · line 293

Quoted 9 lines
drivers/pinctrl/pinctrl-single.c +9 -0
+       }
+
+       return pin * mux_bytes;
+}
+
+static unsigned int pcs_pin_shift_reg_get(struct pcs_device *pcs,
+                                         unsigned int pin)
+{
+       return (pin % (pcs->width / pcs->bits_per_pin)) * pcs->bits_per_pin;

Also a side note: I'm wondering if this can be optimized to have less divisions.

Quoted 89 lines
drivers/pinctrl/pinctrl-single.c +16 -21
+}
+
 static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
                                        struct seq_file *s,
                                        unsigned pin)
 {
        struct pcs_device *pcs;
-       unsigned val, mux_bytes;
+       unsigned int val;
        unsigned long offset;
        size_t pa;
 
        pcs = pinctrl_dev_get_drvdata(pctldev);
 
-       mux_bytes = pcs->width / BITS_PER_BYTE;
-       offset = pin * mux_bytes;
+       offset = pcs_pin_reg_offset_get(pcs, pin);
        val = pcs->read(pcs->base + offset);
+
+       if (pcs->bits_per_mux)
+               val &= pcs->fmask << pcs_pin_shift_reg_get(pcs, pin);
+
        pa = pcs->res->start + offset;
 
        seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME);
@@ -384,7 +410,6 @@ static int pcs_request_gpio(struct pinctrl_dev *pctldev,
        struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
        struct pcs_gpiofunc_range *frange = NULL;
        struct list_head *pos, *tmp;
-       int mux_bytes = 0;
        unsigned data;
 
        /* If function mask is null, return directly. */
@@ -392,29 +417,27 @@ static int pcs_request_gpio(struct pinctrl_dev *pctldev,
                return -ENOTSUPP;
 
        list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
+               u32 offset;
+
                frange = list_entry(pos, struct pcs_gpiofunc_range, node);
                if (pin >= frange->offset + frange->npins
                        || pin < frange->offset)
                        continue;
-               mux_bytes = pcs->width / BITS_PER_BYTE;
 
-               if (pcs->bits_per_mux) {
-                       int byte_num, offset, pin_shift;
+               offset = pcs_pin_reg_offset_get(pcs, pin);
 
-                       byte_num = (pcs->bits_per_pin * pin) / BITS_PER_BYTE;
-                       offset = (byte_num / mux_bytes) * mux_bytes;
-                       pin_shift = pin % (pcs->width / pcs->bits_per_pin) *
-                                   pcs->bits_per_pin;
+               if (pcs->bits_per_mux) {
+                       int pin_shift = pcs_pin_shift_reg_get(pcs, pin);
 
                        data = pcs->read(pcs->base + offset);
                        data &= ~(pcs->fmask << pin_shift);
                        data |= frange->gpiofunc << pin_shift;
                        pcs->write(data, pcs->base + offset);
                } else {
-                       data = pcs->read(pcs->base + pin * mux_bytes);
+                       data = pcs->read(pcs->base + offset);
                        data &= ~pcs->fmask;
                        data |= frange->gpiofunc;
-                       pcs->write(data, pcs->base + pin * mux_bytes);
+                       pcs->write(data, pcs->base + offset);
                }
                break;
        }
@@ -724,14 +747,8 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
        for (i = 0; i < pcs->desc.npins; i++) {
                unsigned offset;
                int res;
-               int byte_num;
 
-               if (pcs->bits_per_mux) {
-                       byte_num = (pcs->bits_per_pin * i) / BITS_PER_BYTE;
-                       offset = (byte_num / mux_bytes) * mux_bytes;
-               } else {
-                       offset = i * mux_bytes;
-               }
+               offset = pcs_pin_reg_offset_get(pcs, i);
                res = pcs_add_pin(pcs, offset);
                if (res < 0) {
                        dev_err(pcs->dev, "error adding pins: %i\n", res);
--

2.17.1

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#5 lore raw

Re: [PATCH v3 3/3] pinctrl: pinctrl-single: fix pcs_pin_dbg_show() when bits_per_mux is not zero

Quoted 7 lines · Andy Shevchenko
Quoted 1 line · Hanna Hawa

An SError was detected when trying to print the supported pins in a

What is SError? Yes, I have read a discussion, but here is the hint:
if a person sees this as a first text due to, for example, bisecting an issue, what she/he can get from this cryptic name?

What you suggest?
s/An SError/A kernel-panic/?
Or remove the sentence and keep the below:
"
This change fixes the pcs_pin_dbg_show() in pinctrl-single driver when bits_per_mux is not zero. In addition move offset calculation and pin offset in register to common function. "

Quoted 6 lines
Quoted 5 lines

pinctrl device which supports multiple pins per register. This change fixes the pcs_pin_dbg_show() in pinctrl-single driver when bits_per_mux is not zero. In addition move offset calculation and pin offset in register to common function.

Thanks

Quoted 15 lines
Quoted 15 lines
Fixes 4e7e8017a80e ("pinctrl: pinctrl-single: enhance to configure multiple pins of different modules")
---
  drivers/pinctrl/pinctrl-single.c | 57 +++++++++++++++++++++-----------
  1 file changed, 37 insertions(+), 20 deletions(-)
drivers/pinctrl/pinctrl-single.c +0 -0
index f3394517cb2e..4595acf6545e 100644
@@ -270,20 +270,46 @@ static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg)
         writel(val, reg);
  }
 
Quoted 7 lines

drivers/pinctrl/pinctrl-single.c static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg) · line 278

Quoted 6 lines
drivers/pinctrl/pinctrl-single.c +6 -0
+static unsigned int pcs_pin_reg_offset_get(struct pcs_device *pcs,
+                                          unsigned int pin)
+{
+       unsigned int mux_bytes;
+
+       mux_bytes = pcs->width / BITS_PER_BYTE;

Can be folded to one line.

Ack

Quoted 10 lines

drivers/pinctrl/pinctrl-single.c static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg) · line 284

Quoted 6 lines
drivers/pinctrl/pinctrl-single.c +5 -0
+       if (pcs->bits_per_mux) {
+               unsigned int pin_offset_bytes;
+
+               pin_offset_bytes = (pcs->bits_per_pin * pin) / BITS_PER_BYTE;
+               return (pin_offset_bytes / mux_bytes) * mux_bytes;

Side note for the further improvements (in a separate change, because I see that you just copied an original code, and after all this is just a fix patch): this can be replaced by round down APIs (one which works for arbitrary divisors).

Agree, didn't want to change the formula as it's fix patch. (here and below), this can be taken for further improvements.

Quoted 12 lines

drivers/pinctrl/pinctrl-single.c static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg) · line 293

Quoted 10 lines
drivers/pinctrl/pinctrl-single.c +9 -0
+       }
+
+       return pin * mux_bytes;
+}
+
+static unsigned int pcs_pin_shift_reg_get(struct pcs_device *pcs,
+                                         unsigned int pin)
+{
+       return (pin % (pcs->width / pcs->bits_per_pin)) * pcs->bits_per_pin;

Also a side note: I'm wondering if this can be optimized to have less divisions.

Quoted 6 lines

drivers/pinctrl/pinctrl-single.c static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg) · line 299

Quoted 6 lines
drivers/pinctrl/pinctrl-single.c +2 -0
+}
+
  static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
                                         struct seq_file *s,
                                         unsigned pin)
  {

Thanks,
Hanna

#6 lore raw

Re: [PATCH v3 3/3] pinctrl: pinctrl-single: fix pcs_pin_dbg_show() when bits_per_mux is not zero

Quoted 9 lines · Hanna
Quoted 5 lines · Andy Shevchenko
Quoted 1 line · Hanna Hawa

An SError was detected when trying to print the supported pins in a

What is SError? Yes, I have read a discussion, but here is the hint:
if a person sees this as a first text due to, for example, bisecting an issue, what she/he can get from this cryptic name?

What you suggest?
s/An SError/A kernel-panic/?

Not below, but something which makes clear what SError is.

Like "A System Error (SError, followed by kernel panic) ..."

Quoted 6 lines

Or remove the sentence and keep the below:
"
This change fixes the pcs_pin_dbg_show() in pinctrl-single driver when bits_per_mux is not zero. In addition move offset calculation and pin offset in register to common function.
"

Signature · 2 lines
With Best Regards,
Andy Shevchenko