diff mbox series

[v2,3/3] pinctrl: pinctrl-single: fix pcs_pin_dbg_show() when bits_per_mux != 0

Message ID 20210316202434.27555-4-hhhawa@amazon.com
State New
Headers show
Series Fix pinctrl-single pcs_pin_dbg_show() | expand

Commit Message

Hanna Hawa March 16, 2021, 8:24 p.m. UTC
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 != 0. In addition move offset calculation and pin offset in
register to common function.

Signed-off-by: Hanna Hawa <hhhawa@amazon.com>
---
 drivers/pinctrl/pinctrl-single.c | 66 ++++++++++++++++++++++----------
 1 file changed, 45 insertions(+), 21 deletions(-)

Comments

Andy Shevchenko March 17, 2021, 12:27 p.m. UTC | #1
On Tue, Mar 16, 2021 at 11:24 PM Hanna Hawa <hhhawa@amazon.com> wrote:
>

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


What SError is?

> pinctrl device which supports multiple pins per register. This change

> fixes the pcs_pin_dbg_show() in pinctrl-single driver when

> bits_per_mux != 0. In addition move offset calculation and pin offset in


'!= 0' -> 'is not zero'

> register to common function.


Fixes tag?

> Signed-off-by: Hanna Hawa <hhhawa@amazon.com>

> ---

>  drivers/pinctrl/pinctrl-single.c | 66 ++++++++++++++++++++++----------

>  1 file changed, 45 insertions(+), 21 deletions(-)

>

> diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c

> index f3394517cb2e..434f90c8b1b3 100644

> --- a/drivers/pinctrl/pinctrl-single.c

> +++ b/drivers/pinctrl/pinctrl-single.c

> @@ -270,20 +270,53 @@ 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 offset, mux_bytes;


Offset can be replaced by direct return statements.

> +       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;

> +               offset = (pin_offset_bytes / mux_bytes) * mux_bytes;

> +       } else {

> +               offset = pin * mux_bytes;

> +       }

> +

> +       return offset;

> +}

> +

> +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);


Too many parentheses.

> +}

> +

>  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;

> -       val = pcs->read(pcs->base + offset);

> +       offset = pcs_pin_reg_offset_get(pcs, pin);

> +

> +       if (pcs->bits_per_mux) {

> +               unsigned int pin_shift_in_reg = pcs_pin_shift_reg_get(pcs, pin);


> +               val = pcs->read(pcs->base + offset)

> +                       & (pcs->fmask << pin_shift_in_reg);


One line?
At least move & to the upper line.

> +       } else {

> +               val = pcs->read(pcs->base + offset);


It's the same as in above branch, why not

val = read();
if ()
 val &= fmask << _reg_get(...);

?

> +       }

> +

>         pa = pcs->res->start + offset;

>

>         seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME);

> @@ -384,7 +417,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 +424,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 +754,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

>



-- 
With Best Regards,
Andy Shevchenko
Hanna Hawa March 17, 2021, 7:35 p.m. UTC | #2
On 3/17/2021 2:27 PM, Andy Shevchenko wrote:
> 

> On Tue, Mar 16, 2021 at 11:24 PM Hanna Hawa <hhhawa@amazon.com> wrote:

>>

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

> 

> What SError is?


System error:
[   24.257831] SError Interrupt on CPU0, code 0xbf000002 -- SError
...
[   24.257855] Kernel panic - not syncing: Asynchronous SError Interrupt

> 

>> pinctrl device which supports multiple pins per register. This change

>> fixes the pcs_pin_dbg_show() in pinctrl-single driver when

>> bits_per_mux != 0. In addition move offset calculation and pin offset in

> 

> '!= 0' -> 'is not zero'


Will be fixed.

> 

>> register to common function.

> 

> Fixes tag?


Sure, will be added.

> 

>> Signed-off-by: Hanna Hawa <hhhawa@amazon.com>

>> ---

>>   drivers/pinctrl/pinctrl-single.c | 66 ++++++++++++++++++++++----------

>>   1 file changed, 45 insertions(+), 21 deletions(-)

>>

>> diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c

>> index f3394517cb2e..434f90c8b1b3 100644

>> --- a/drivers/pinctrl/pinctrl-single.c

>> +++ b/drivers/pinctrl/pinctrl-single.c

>> @@ -270,20 +270,53 @@ 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 offset, mux_bytes;

> 

> Offset can be replaced by direct return statements.


Ack.

> 

>> +       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;

>> +               offset = (pin_offset_bytes / mux_bytes) * mux_bytes;

>> +       } else {

>> +               offset = pin * mux_bytes;

>> +       }

>> +

>> +       return offset;

>> +}

>> +

>> +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);

> 

> Too many parentheses.


Will remove the extra parentheses.

> 

>> +}

>> +

>>   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;

>> -       val = pcs->read(pcs->base + offset);

>> +       offset = pcs_pin_reg_offset_get(pcs, pin);

>> +

>> +       if (pcs->bits_per_mux) {

>> +               unsigned int pin_shift_in_reg = pcs_pin_shift_reg_get(pcs, pin);

> 

>> +               val = pcs->read(pcs->base + offset)

>> +                       & (pcs->fmask << pin_shift_in_reg);

> 

> One line?

> At least move & to the upper line.

> 

>> +       } else {

>> +               val = pcs->read(pcs->base + offset);

> 

> It's the same as in above branch, why not

> 

> val = read();

> if ()

>   val &= fmask << _reg_get(...);

> 

> ?


Agree, looks better

Thanks Andy, will send new patchset soon.

Thanks,
Hanna
diff mbox series

Patch

diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index f3394517cb2e..434f90c8b1b3 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -270,20 +270,53 @@  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 offset, 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;
+		offset = (pin_offset_bytes / mux_bytes) * mux_bytes;
+	} else {
+		offset = pin * mux_bytes;
+	}
+
+	return offset;
+}
+
+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;
-	val = pcs->read(pcs->base + offset);
+	offset = pcs_pin_reg_offset_get(pcs, pin);
+
+	if (pcs->bits_per_mux) {
+		unsigned int pin_shift_in_reg = pcs_pin_shift_reg_get(pcs, pin);
+
+		val = pcs->read(pcs->base + offset)
+			& (pcs->fmask << pin_shift_in_reg);
+	} else {
+		val = pcs->read(pcs->base + offset);
+	}
+
 	pa = pcs->res->start + offset;
 
 	seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME);
@@ -384,7 +417,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 +424,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 +754,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);