All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
@ 2020-07-15 13:54 Jeremy Kerr
  2020-07-15 13:54 ` [PATCH 2/2] gpio/aspeed-sgpio: don't enable all interrupts by default Jeremy Kerr
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Jeremy Kerr @ 2020-07-15 13:54 UTC (permalink / raw)
  To: linux-gpio, linux-aspeed, devicetree; +Cc: Joel Stanley, Andrew Jeffery

Currently, the aspeed-sgpio driver exposes up to 80 GPIO lines,
corresponding to the 80 status bits available in hardware. Each of these
lines can be configured as either an input or an output.

However, each of these GPIOs is actually an input *and* an output; we
actually have 80 inputs plus 80 outputs.

This change expands the maximum number of GPIOs to 160; the lower half
of this range are the input-only GPIOs, the upper half are the outputs.
We fix the GPIO directions to correspond to this mapping.

This also fixes a bug when setting GPIOs - we were reading from the
input register, making it impossible to set more than one output GPIO.

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
 .../devicetree/bindings/gpio/sgpio-aspeed.txt |   5 +-
 drivers/gpio/gpio-aspeed-sgpio.c              | 115 +++++++++++-------
 2 files changed, 77 insertions(+), 43 deletions(-)

diff --git a/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt b/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt
index d4d83916c09d..be329ea4794f 100644
--- a/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt
+++ b/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt
@@ -20,8 +20,9 @@ Required properties:
 - gpio-controller : Marks the device node as a GPIO controller
 - interrupts : Interrupt specifier, see interrupt-controller/interrupts.txt
 - interrupt-controller : Mark the GPIO controller as an interrupt-controller
-- ngpios : number of GPIO lines, see gpio.txt
-  (should be multiple of 8, up to 80 pins)
+- ngpios : number of *hardware* GPIO lines, see gpio.txt. This will expose
+  2 software GPIOs per hardware GPIO: one for hardware input, one for hardware
+  output. Up to 80 pins, must be a multiple of 8.
 - clocks : A phandle to the APB clock for SGPM clock division
 - bus-frequency : SGPM CLK frequency
 
diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
index 8319812593e3..927d46f159b8 100644
--- a/drivers/gpio/gpio-aspeed-sgpio.c
+++ b/drivers/gpio/gpio-aspeed-sgpio.c
@@ -17,7 +17,8 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 
-#define MAX_NR_SGPIO			80
+#define MAX_NR_HW_SGPIO			80
+#define SGPIO_OUTPUT_OFFSET		MAX_NR_HW_SGPIO
 
 #define ASPEED_SGPIO_CTRL		0x54
 
@@ -30,8 +31,8 @@ struct aspeed_sgpio {
 	struct clk *pclk;
 	spinlock_t lock;
 	void __iomem *base;
-	uint32_t dir_in[3];
 	int irq;
+	int n_sgpio;
 };
 
 struct aspeed_sgpio_bank {
@@ -111,31 +112,69 @@ static void __iomem *bank_reg(struct aspeed_sgpio *gpio,
 	}
 }
 
-#define GPIO_BANK(x)    ((x) >> 5)
-#define GPIO_OFFSET(x)  ((x) & 0x1f)
+#define GPIO_BANK(x)    ((x % SGPIO_OUTPUT_OFFSET) >> 5)
+#define GPIO_OFFSET(x)  ((x % SGPIO_OUTPUT_OFFSET) & 0x1f)
 #define GPIO_BIT(x)     BIT(GPIO_OFFSET(x))
 
 static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
 {
-	unsigned int bank = GPIO_BANK(offset);
+	unsigned int bank;
+
+	bank = GPIO_BANK(offset);
 
 	WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks));
 	return &aspeed_sgpio_banks[bank];
 }
 
+static int aspeed_sgpio_init_valid_mask(struct gpio_chip *gc,
+		unsigned long *valid_mask, unsigned int ngpios)
+{
+	struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
+	int n = sgpio->n_sgpio;
+	int c = SGPIO_OUTPUT_OFFSET - n;
+
+	WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
+
+	/* input GPIOs in the lower range */
+	bitmap_set(valid_mask, 0, n);
+	bitmap_clear(valid_mask, n, c);
+
+	/* output GPIOS above SGPIO_OUTPUT_OFFSET */
+	bitmap_set(valid_mask, SGPIO_OUTPUT_OFFSET, n);
+	bitmap_clear(valid_mask, SGPIO_OUTPUT_OFFSET + n, c);
+
+	return 0;
+}
+
+static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
+		unsigned long *valid_mask, unsigned int ngpios)
+{
+	struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
+	int n = sgpio->n_sgpio;
+
+	WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
+
+	/* input GPIOs in the lower range */
+	bitmap_set(valid_mask, 0, n);
+	bitmap_clear(valid_mask, n, ngpios - n);
+}
+
+static const bool aspeed_sgpio_is_input(unsigned int offset)
+{
+	return offset < SGPIO_OUTPUT_OFFSET;
+}
+
 static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
 	const struct aspeed_sgpio_bank *bank = to_bank(offset);
 	unsigned long flags;
 	enum aspeed_sgpio_reg reg;
-	bool is_input;
 	int rc = 0;
 
 	spin_lock_irqsave(&gpio->lock, flags);
 
-	is_input = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset);
-	reg = is_input ? reg_val : reg_rdata;
+	reg = aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata;
 	rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
 
 	spin_unlock_irqrestore(&gpio->lock, flags);
@@ -143,22 +182,31 @@ static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
 	return rc;
 }
 
-static void sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
+static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
 	const struct aspeed_sgpio_bank *bank = to_bank(offset);
-	void __iomem *addr;
+	void __iomem *addr_r, *addr_w;
 	u32 reg = 0;
 
-	addr = bank_reg(gpio, bank, reg_val);
-	reg = ioread32(addr);
+	if (aspeed_sgpio_is_input(offset))
+		return -EINVAL;
+
+	/* Since this is an output, read the cached value from rdata, then
+	 * update val. */
+	addr_r = bank_reg(gpio, bank, reg_rdata);
+	addr_w = bank_reg(gpio, bank, reg_val);
+
+	reg = ioread32(addr_r);
 
 	if (val)
 		reg |= GPIO_BIT(offset);
 	else
 		reg &= ~GPIO_BIT(offset);
 
-	iowrite32(reg, addr);
+	iowrite32(reg, addr_w);
+
+	return 0;
 }
 
 static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
@@ -175,26 +223,20 @@ static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
 
 static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
 {
-	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio->lock, flags);
-	gpio->dir_in[GPIO_BANK(offset)] |= GPIO_BIT(offset);
-	spin_unlock_irqrestore(&gpio->lock, flags);
-
-	return 0;
+	return aspeed_sgpio_is_input(offset) ? 0 : -EINVAL;
 }
 
 static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
 	unsigned long flags;
+	int rc;
 
-	spin_lock_irqsave(&gpio->lock, flags);
-
-	gpio->dir_in[GPIO_BANK(offset)] &= ~GPIO_BIT(offset);
-	sgpio_set_value(gc, offset, val);
+	/* No special action is required for setting the direction; we'll
+	 * error-out in sgpio_set_value if this isn't an output GPIO */
 
+	spin_lock_irqsave(&gpio->lock, flags);
+	rc = sgpio_set_value(gc, offset, val);
 	spin_unlock_irqrestore(&gpio->lock, flags);
 
 	return 0;
@@ -202,16 +244,7 @@ static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int v
 
 static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset)
 {
-	int dir_status;
-	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio->lock, flags);
-	dir_status = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset);
-	spin_unlock_irqrestore(&gpio->lock, flags);
-
-	return dir_status;
-
+	return !!aspeed_sgpio_is_input(offset);
 }
 
 static void irqd_to_aspeed_sgpio_data(struct irq_data *d,
@@ -402,6 +435,7 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
 
 	irq = &gpio->chip.irq;
 	irq->chip = &aspeed_sgpio_irqchip;
+	irq->init_valid_mask = aspeed_sgpio_irq_init_valid_mask;
 	irq->handler = handle_bad_irq;
 	irq->default_type = IRQ_TYPE_NONE;
 	irq->parent_handler = aspeed_sgpio_irq_handler;
@@ -452,11 +486,12 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
 	if (rc < 0) {
 		dev_err(&pdev->dev, "Could not read ngpios property\n");
 		return -EINVAL;
-	} else if (nr_gpios > MAX_NR_SGPIO) {
+	} else if (nr_gpios > MAX_NR_HW_SGPIO) {
 		dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n",
-			MAX_NR_SGPIO, nr_gpios);
+			MAX_NR_HW_SGPIO, nr_gpios);
 		return -EINVAL;
 	}
+	gpio->n_sgpio = nr_gpios;
 
 	rc = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq);
 	if (rc < 0) {
@@ -497,7 +532,8 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
 	spin_lock_init(&gpio->lock);
 
 	gpio->chip.parent = &pdev->dev;
-	gpio->chip.ngpio = nr_gpios;
+	gpio->chip.ngpio = MAX_NR_HW_SGPIO * 2;
+	gpio->chip.init_valid_mask = aspeed_sgpio_init_valid_mask;
 	gpio->chip.direction_input = aspeed_sgpio_dir_in;
 	gpio->chip.direction_output = aspeed_sgpio_dir_out;
 	gpio->chip.get_direction = aspeed_sgpio_get_direction;
@@ -509,9 +545,6 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev)
 	gpio->chip.label = dev_name(&pdev->dev);
 	gpio->chip.base = -1;
 
-	/* set all SGPIO pins as input (1). */
-	memset(gpio->dir_in, 0xff, sizeof(gpio->dir_in));
-
 	aspeed_sgpio_setup_irqs(gpio, pdev);
 
 	rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
-- 
2.27.0


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

* [PATCH 2/2] gpio/aspeed-sgpio: don't enable all interrupts by default
  2020-07-15 13:54 [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios Jeremy Kerr
@ 2020-07-15 13:54 ` Jeremy Kerr
  2020-09-10  3:57   ` Joel Stanley
  2020-07-15 19:37   ` kernel test robot
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 11+ messages in thread
From: Jeremy Kerr @ 2020-07-15 13:54 UTC (permalink / raw)
  To: linux-gpio, linux-aspeed, devicetree; +Cc: Joel Stanley, Andrew Jeffery

Currently, the IRQ setup for the SGPIO driver enables all interrupts for
dual-edge trigger mode. Since the default handler is handle_bad_irq, any
state change on input GPIOs will trigger bad IRQ warnings.

This change applies sensible (disabled) IRQ defaults.

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
 drivers/gpio/gpio-aspeed-sgpio.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
index 927d46f159b8..23a3a40901d6 100644
--- a/drivers/gpio/gpio-aspeed-sgpio.c
+++ b/drivers/gpio/gpio-aspeed-sgpio.c
@@ -451,9 +451,7 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
 		/* trigger type is edge */
 		iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1));
 		/* dual edge trigger mode. */
-		iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type2));
-		/* enable irq */
-		iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_enable));
+		iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type2));
 	}
 
 	return 0;
-- 
2.27.0


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

* Re: [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
  2020-07-15 13:54 [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios Jeremy Kerr
@ 2020-07-15 19:37   ` kernel test robot
  2020-07-15 19:37   ` kernel test robot
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: kernel test robot @ 2020-07-15 19:37 UTC (permalink / raw)
  To: Jeremy Kerr, linux-gpio, linux-aspeed, devicetree
  Cc: kbuild-all, Joel Stanley, Andrew Jeffery

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

Hi Jeremy,

I love your patch! Perhaps something to improve:

[auto build test WARNING on gpio/for-next]
[also build test WARNING on joel-aspeed/for-next v5.8-rc5 next-20200715]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jeremy-Kerr/gpio-aspeed-sgpio-enable-access-to-all-80-input-output-sgpios/20200715-221503
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git for-next
config: arm64-allyesconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/gpio/gpio-aspeed-sgpio.c:162:8: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
     162 | static const bool aspeed_sgpio_is_input(unsigned int offset)
         |        ^~~~~
   drivers/gpio/gpio-aspeed-sgpio.c: In function 'aspeed_sgpio_dir_out':
>> drivers/gpio/gpio-aspeed-sgpio.c:233:6: warning: variable 'rc' set but not used [-Wunused-but-set-variable]
     233 |  int rc;
         |      ^~

vim +162 drivers/gpio/gpio-aspeed-sgpio.c

   161	
 > 162	static const bool aspeed_sgpio_is_input(unsigned int offset)
   163	{
   164		return offset < SGPIO_OUTPUT_OFFSET;
   165	}
   166	
   167	static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
   168	{
   169		struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
   170		const struct aspeed_sgpio_bank *bank = to_bank(offset);
   171		unsigned long flags;
   172		enum aspeed_sgpio_reg reg;
   173		int rc = 0;
   174	
   175		spin_lock_irqsave(&gpio->lock, flags);
   176	
   177		reg = aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata;
   178		rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
   179	
   180		spin_unlock_irqrestore(&gpio->lock, flags);
   181	
   182		return rc;
   183	}
   184	
   185	static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
   186	{
   187		struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
   188		const struct aspeed_sgpio_bank *bank = to_bank(offset);
   189		void __iomem *addr_r, *addr_w;
   190		u32 reg = 0;
   191	
   192		if (aspeed_sgpio_is_input(offset))
   193			return -EINVAL;
   194	
   195		/* Since this is an output, read the cached value from rdata, then
   196		 * update val. */
   197		addr_r = bank_reg(gpio, bank, reg_rdata);
   198		addr_w = bank_reg(gpio, bank, reg_val);
   199	
   200		reg = ioread32(addr_r);
   201	
   202		if (val)
   203			reg |= GPIO_BIT(offset);
   204		else
   205			reg &= ~GPIO_BIT(offset);
   206	
   207		iowrite32(reg, addr_w);
   208	
   209		return 0;
   210	}
   211	
   212	static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
   213	{
   214		struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
   215		unsigned long flags;
   216	
   217		spin_lock_irqsave(&gpio->lock, flags);
   218	
   219		sgpio_set_value(gc, offset, val);
   220	
   221		spin_unlock_irqrestore(&gpio->lock, flags);
   222	}
   223	
   224	static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
   225	{
   226		return aspeed_sgpio_is_input(offset) ? 0 : -EINVAL;
   227	}
   228	
   229	static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
   230	{
   231		struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
   232		unsigned long flags;
 > 233		int rc;
   234	
   235		/* No special action is required for setting the direction; we'll
   236		 * error-out in sgpio_set_value if this isn't an output GPIO */
   237	
   238		spin_lock_irqsave(&gpio->lock, flags);
   239		rc = sgpio_set_value(gc, offset, val);
   240		spin_unlock_irqrestore(&gpio->lock, flags);
   241	
   242		return 0;
   243	}
   244	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 73535 bytes --]

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

* Re: [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
@ 2020-07-15 19:37   ` kernel test robot
  0 siblings, 0 replies; 11+ messages in thread
From: kernel test robot @ 2020-07-15 19:37 UTC (permalink / raw)
  To: kbuild-all

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

Hi Jeremy,

I love your patch! Perhaps something to improve:

[auto build test WARNING on gpio/for-next]
[also build test WARNING on joel-aspeed/for-next v5.8-rc5 next-20200715]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jeremy-Kerr/gpio-aspeed-sgpio-enable-access-to-all-80-input-output-sgpios/20200715-221503
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git for-next
config: arm64-allyesconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/gpio/gpio-aspeed-sgpio.c:162:8: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
     162 | static const bool aspeed_sgpio_is_input(unsigned int offset)
         |        ^~~~~
   drivers/gpio/gpio-aspeed-sgpio.c: In function 'aspeed_sgpio_dir_out':
>> drivers/gpio/gpio-aspeed-sgpio.c:233:6: warning: variable 'rc' set but not used [-Wunused-but-set-variable]
     233 |  int rc;
         |      ^~

vim +162 drivers/gpio/gpio-aspeed-sgpio.c

   161	
 > 162	static const bool aspeed_sgpio_is_input(unsigned int offset)
   163	{
   164		return offset < SGPIO_OUTPUT_OFFSET;
   165	}
   166	
   167	static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
   168	{
   169		struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
   170		const struct aspeed_sgpio_bank *bank = to_bank(offset);
   171		unsigned long flags;
   172		enum aspeed_sgpio_reg reg;
   173		int rc = 0;
   174	
   175		spin_lock_irqsave(&gpio->lock, flags);
   176	
   177		reg = aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata;
   178		rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
   179	
   180		spin_unlock_irqrestore(&gpio->lock, flags);
   181	
   182		return rc;
   183	}
   184	
   185	static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
   186	{
   187		struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
   188		const struct aspeed_sgpio_bank *bank = to_bank(offset);
   189		void __iomem *addr_r, *addr_w;
   190		u32 reg = 0;
   191	
   192		if (aspeed_sgpio_is_input(offset))
   193			return -EINVAL;
   194	
   195		/* Since this is an output, read the cached value from rdata, then
   196		 * update val. */
   197		addr_r = bank_reg(gpio, bank, reg_rdata);
   198		addr_w = bank_reg(gpio, bank, reg_val);
   199	
   200		reg = ioread32(addr_r);
   201	
   202		if (val)
   203			reg |= GPIO_BIT(offset);
   204		else
   205			reg &= ~GPIO_BIT(offset);
   206	
   207		iowrite32(reg, addr_w);
   208	
   209		return 0;
   210	}
   211	
   212	static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
   213	{
   214		struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
   215		unsigned long flags;
   216	
   217		spin_lock_irqsave(&gpio->lock, flags);
   218	
   219		sgpio_set_value(gc, offset, val);
   220	
   221		spin_unlock_irqrestore(&gpio->lock, flags);
   222	}
   223	
   224	static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
   225	{
   226		return aspeed_sgpio_is_input(offset) ? 0 : -EINVAL;
   227	}
   228	
   229	static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
   230	{
   231		struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
   232		unsigned long flags;
 > 233		int rc;
   234	
   235		/* No special action is required for setting the direction; we'll
   236		 * error-out in sgpio_set_value if this isn't an output GPIO */
   237	
   238		spin_lock_irqsave(&gpio->lock, flags);
   239		rc = sgpio_set_value(gc, offset, val);
   240		spin_unlock_irqrestore(&gpio->lock, flags);
   241	
   242		return 0;
   243	}
   244	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 73535 bytes --]

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

* Re: [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
  2020-07-15 13:54 [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios Jeremy Kerr
@ 2020-07-15 22:50   ` kernel test robot
  2020-07-15 19:37   ` kernel test robot
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: kernel test robot @ 2020-07-15 22:50 UTC (permalink / raw)
  To: Jeremy Kerr, linux-gpio, linux-aspeed, devicetree
  Cc: kbuild-all, clang-built-linux, Joel Stanley, Andrew Jeffery

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

Hi Jeremy,

I love your patch! Perhaps something to improve:

[auto build test WARNING on gpio/for-next]
[also build test WARNING on joel-aspeed/for-next v5.8-rc5 next-20200715]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jeremy-Kerr/gpio-aspeed-sgpio-enable-access-to-all-80-input-output-sgpios/20200715-221503
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git for-next
config: x86_64-allyesconfig (attached as .config)
compiler: clang version 11.0.0 (https://github.com/llvm/llvm-project 02946de3802d3bc65bc9f2eb9b8d4969b5a7add8)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/gpio/gpio-aspeed-sgpio.c:162:8: warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]
   static const bool aspeed_sgpio_is_input(unsigned int offset)
          ^~~~~~
   1 warning generated.

vim +/const +162 drivers/gpio/gpio-aspeed-sgpio.c

   161	
 > 162	static const bool aspeed_sgpio_is_input(unsigned int offset)
   163	{
   164		return offset < SGPIO_OUTPUT_OFFSET;
   165	}
   166	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 75338 bytes --]

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

* Re: [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
@ 2020-07-15 22:50   ` kernel test robot
  0 siblings, 0 replies; 11+ messages in thread
From: kernel test robot @ 2020-07-15 22:50 UTC (permalink / raw)
  To: kbuild-all

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

Hi Jeremy,

I love your patch! Perhaps something to improve:

[auto build test WARNING on gpio/for-next]
[also build test WARNING on joel-aspeed/for-next v5.8-rc5 next-20200715]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jeremy-Kerr/gpio-aspeed-sgpio-enable-access-to-all-80-input-output-sgpios/20200715-221503
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git for-next
config: x86_64-allyesconfig (attached as .config)
compiler: clang version 11.0.0 (https://github.com/llvm/llvm-project 02946de3802d3bc65bc9f2eb9b8d4969b5a7add8)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/gpio/gpio-aspeed-sgpio.c:162:8: warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]
   static const bool aspeed_sgpio_is_input(unsigned int offset)
          ^~~~~~
   1 warning generated.

vim +/const +162 drivers/gpio/gpio-aspeed-sgpio.c

   161	
 > 162	static const bool aspeed_sgpio_is_input(unsigned int offset)
   163	{
   164		return offset < SGPIO_OUTPUT_OFFSET;
   165	}
   166	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 75338 bytes --]

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

* Re: [PATCH 2/2] gpio/aspeed-sgpio: don't enable all interrupts by default
  2020-07-15 13:54 ` [PATCH 2/2] gpio/aspeed-sgpio: don't enable all interrupts by default Jeremy Kerr
@ 2020-09-10  3:57   ` Joel Stanley
  2020-09-11  1:12     ` Jeremy Kerr
  0 siblings, 1 reply; 11+ messages in thread
From: Joel Stanley @ 2020-09-10  3:57 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: open list:GPIO SUBSYSTEM, linux-aspeed, devicetree, Andrew Jeffery

On Wed, 15 Jul 2020 at 14:06, Jeremy Kerr <jk@codeconstruct.com.au> wrote:
>
> Currently, the IRQ setup for the SGPIO driver enables all interrupts for
> dual-edge trigger mode. Since the default handler is handle_bad_irq, any
> state change on input GPIOs will trigger bad IRQ warnings.
>
> This change applies sensible (disabled) IRQ defaults.
>
> Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
> ---
>  drivers/gpio/gpio-aspeed-sgpio.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
> index 927d46f159b8..23a3a40901d6 100644
> --- a/drivers/gpio/gpio-aspeed-sgpio.c
> +++ b/drivers/gpio/gpio-aspeed-sgpio.c

I've re-ordered the lines in the diff to make it easier to review:

> @@ -451,9 +451,7 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
>                 /* trigger type is edge */
>                 iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1));
>                 /* dual edge trigger mode. */
> -               iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type2));
> +               iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type2));

You're changing the trigger mode from dual edge to single edge.

> -               /* enable irq */
> -               iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_enable));

And also removing the enabling of IRQs. This part makes sense, as it's
what the commit message says.

If you think a sensible default should be single edge (and I would
agree with that change), perhaps update the comment to say "set single
edge trigger mode" and mention it in your commit message.

Cheers,

Joel

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

* Re: [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
  2020-07-15 13:54 [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios Jeremy Kerr
                   ` (2 preceding siblings ...)
  2020-07-15 22:50   ` kernel test robot
@ 2020-09-10  4:10 ` Joel Stanley
  2020-09-11  1:10   ` Jeremy Kerr
  3 siblings, 1 reply; 11+ messages in thread
From: Joel Stanley @ 2020-09-10  4:10 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: open list:GPIO SUBSYSTEM, linux-aspeed, devicetree, Andrew Jeffery

On Wed, 15 Jul 2020 at 14:06, Jeremy Kerr <jk@codeconstruct.com.au> wrote:
>
> Currently, the aspeed-sgpio driver exposes up to 80 GPIO lines,
> corresponding to the 80 status bits available in hardware. Each of these
> lines can be configured as either an input or an output.
>
> However, each of these GPIOs is actually an input *and* an output; we
> actually have 80 inputs plus 80 outputs.
>
> This change expands the maximum number of GPIOs to 160; the lower half
> of this range are the input-only GPIOs, the upper half are the outputs.
> We fix the GPIO directions to correspond to this mapping.
>
> This also fixes a bug when setting GPIOs - we were reading from the
> input register, making it impossible to set more than one output GPIO.
>
> Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>

A Fixes: might be a good idea.

> ---
>  .../devicetree/bindings/gpio/sgpio-aspeed.txt |   5 +-
>  drivers/gpio/gpio-aspeed-sgpio.c              | 115 +++++++++++-------
>  2 files changed, 77 insertions(+), 43 deletions(-)

> diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
> index 8319812593e3..927d46f159b8 100644
> --- a/drivers/gpio/gpio-aspeed-sgpio.c
> +++ b/drivers/gpio/gpio-aspeed-sgpio.c
> @@ -17,7 +17,8 @@
>  #include <linux/spinlock.h>
>  #include <linux/string.h>
>
> -#define MAX_NR_SGPIO                   80
> +#define MAX_NR_HW_SGPIO                        80
> +#define SGPIO_OUTPUT_OFFSET            MAX_NR_HW_SGPIO

A short comment explaining what's going on with these defines (as you
did in your commit message) will help future reviewers.

> +static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
> +               unsigned long *valid_mask, unsigned int ngpios)
> +{
> +       struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
> +       int n = sgpio->n_sgpio;
> +
> +       WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
> +
> +       /* input GPIOs in the lower range */
> +       bitmap_set(valid_mask, 0, n);
> +       bitmap_clear(valid_mask, n, ngpios - n);
> +}
> +
> +static const bool aspeed_sgpio_is_input(unsigned int offset)

The 0day bot complained about the 'const' here.

> +{
> +       return offset < SGPIO_OUTPUT_OFFSET;
> +}

>  static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
>  {
>         struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
>         unsigned long flags;
> +       int rc;
>
> -       spin_lock_irqsave(&gpio->lock, flags);
> -
> -       gpio->dir_in[GPIO_BANK(offset)] &= ~GPIO_BIT(offset);
> -       sgpio_set_value(gc, offset, val);
> +       /* No special action is required for setting the direction; we'll
> +        * error-out in sgpio_set_value if this isn't an output GPIO */
>
> +       spin_lock_irqsave(&gpio->lock, flags);
> +       rc = sgpio_set_value(gc, offset, val);
>         spin_unlock_irqrestore(&gpio->lock, flags);
>
>         return 0;

I think this should be 'return rc'

Cheers,

Joel

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

* Re: [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
  2020-09-10  4:10 ` Joel Stanley
@ 2020-09-11  1:10   ` Jeremy Kerr
  2020-09-11  1:15     ` Joel Stanley
  0 siblings, 1 reply; 11+ messages in thread
From: Jeremy Kerr @ 2020-09-11  1:10 UTC (permalink / raw)
  To: Joel Stanley
  Cc: open list:GPIO SUBSYSTEM, linux-aspeed, devicetree, Andrew Jeffery

Hi Joel,

Thanks for the review!

> A Fixes: might be a good idea.

OK, given this isn't strictly (just) a fix, should I split that out?

> > -#define MAX_NR_SGPIO                   80
> > +#define MAX_NR_HW_SGPIO                        80
> > +#define SGPIO_OUTPUT_OFFSET            MAX_NR_HW_SGPIO
> 
> A short comment explaining what's going on with these defines (as you
> did in your commit message) will help future reviewers.

Sounds good, I'll add one.

> 
> > +static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
> > +               unsigned long *valid_mask, unsigned int ngpios)
> > +{
> > +       struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
> > +       int n = sgpio->n_sgpio;
> > +
> > +       WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
> > +
> > +       /* input GPIOs in the lower range */
> > +       bitmap_set(valid_mask, 0, n);
> > +       bitmap_clear(valid_mask, n, ngpios - n);
> > +}
> > +
> > +static const bool aspeed_sgpio_is_input(unsigned int offset)
> 
> The 0day bot complained about the 'const' here.

ack, will remove.

> > +{
> > +       return offset < SGPIO_OUTPUT_OFFSET;
> > +}
> >  static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
> >  {
> >         struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
> >         unsigned long flags;
> > +       int rc;
> > 
> > -       spin_lock_irqsave(&gpio->lock, flags);
> > -
> > -       gpio->dir_in[GPIO_BANK(offset)] &= ~GPIO_BIT(offset);
> > -       sgpio_set_value(gc, offset, val);
> > +       /* No special action is required for setting the direction; we'll
> > +        * error-out in sgpio_set_value if this isn't an output GPIO */
> > 
> > +       spin_lock_irqsave(&gpio->lock, flags);
> > +       rc = sgpio_set_value(gc, offset, val);
> >         spin_unlock_irqrestore(&gpio->lock, flags);
> > 
> >         return 0;
> 
> I think this should be 'return rc'

Yup. I'll send a v2 with these changes.

Cheers,


Jeremy


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

* Re: [PATCH 2/2] gpio/aspeed-sgpio: don't enable all interrupts by default
  2020-09-10  3:57   ` Joel Stanley
@ 2020-09-11  1:12     ` Jeremy Kerr
  0 siblings, 0 replies; 11+ messages in thread
From: Jeremy Kerr @ 2020-09-11  1:12 UTC (permalink / raw)
  To: Joel Stanley
  Cc: open list:GPIO SUBSYSTEM, linux-aspeed, devicetree, Andrew Jeffery

Hi Joel,

> And also removing the enabling of IRQs. This part makes sense, as
> it's what the commit message says.
> 
> If you think a sensible default should be single edge (and I would
> agree with that change), perhaps update the comment to say "set
> single edge trigger mode" and mention it in your commit message.

OK, shall do. That was my intention with the "reasonable defaults"
reference, but being explicit about that better here.

I'll send a v2 with an updated commit message.

Cheers,


Jeremy



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

* Re: [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
  2020-09-11  1:10   ` Jeremy Kerr
@ 2020-09-11  1:15     ` Joel Stanley
  0 siblings, 0 replies; 11+ messages in thread
From: Joel Stanley @ 2020-09-11  1:15 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: open list:GPIO SUBSYSTEM, linux-aspeed, devicetree, Andrew Jeffery

On Fri, 11 Sep 2020 at 01:10, Jeremy Kerr <jk@codeconstruct.com.au> wrote:
>
> Hi Joel,
>
> Thanks for the review!
>
> > A Fixes: might be a good idea.
>
> OK, given this isn't strictly (just) a fix, should I split that out?

I assume anyone using the sgpio driver in anger would need this patch
for it to work properly, so a fix tag will help them there. No need to
break it down any further in my opinion.

Cheers,

Joel

>
> > > -#define MAX_NR_SGPIO                   80
> > > +#define MAX_NR_HW_SGPIO                        80
> > > +#define SGPIO_OUTPUT_OFFSET            MAX_NR_HW_SGPIO
> >
> > A short comment explaining what's going on with these defines (as you
> > did in your commit message) will help future reviewers.
>
> Sounds good, I'll add one.
>
> >
> > > +static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
> > > +               unsigned long *valid_mask, unsigned int ngpios)
> > > +{
> > > +       struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
> > > +       int n = sgpio->n_sgpio;
> > > +
> > > +       WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
> > > +
> > > +       /* input GPIOs in the lower range */
> > > +       bitmap_set(valid_mask, 0, n);
> > > +       bitmap_clear(valid_mask, n, ngpios - n);
> > > +}
> > > +
> > > +static const bool aspeed_sgpio_is_input(unsigned int offset)
> >
> > The 0day bot complained about the 'const' here.
>
> ack, will remove.
>
> > > +{
> > > +       return offset < SGPIO_OUTPUT_OFFSET;
> > > +}
> > >  static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
> > >  {
> > >         struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
> > >         unsigned long flags;
> > > +       int rc;
> > >
> > > -       spin_lock_irqsave(&gpio->lock, flags);
> > > -
> > > -       gpio->dir_in[GPIO_BANK(offset)] &= ~GPIO_BIT(offset);
> > > -       sgpio_set_value(gc, offset, val);
> > > +       /* No special action is required for setting the direction; we'll
> > > +        * error-out in sgpio_set_value if this isn't an output GPIO */
> > >
> > > +       spin_lock_irqsave(&gpio->lock, flags);
> > > +       rc = sgpio_set_value(gc, offset, val);
> > >         spin_unlock_irqrestore(&gpio->lock, flags);
> > >
> > >         return 0;
> >
> > I think this should be 'return rc'
>
> Yup. I'll send a v2 with these changes.
>
> Cheers,
>
>
> Jeremy
>

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

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

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-15 13:54 [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios Jeremy Kerr
2020-07-15 13:54 ` [PATCH 2/2] gpio/aspeed-sgpio: don't enable all interrupts by default Jeremy Kerr
2020-09-10  3:57   ` Joel Stanley
2020-09-11  1:12     ` Jeremy Kerr
2020-07-15 19:37 ` [PATCH 1/2] gpio/aspeed-sgpio: enable access to all 80 input & output sgpios kernel test robot
2020-07-15 19:37   ` kernel test robot
2020-07-15 22:50 ` kernel test robot
2020-07-15 22:50   ` kernel test robot
2020-09-10  4:10 ` Joel Stanley
2020-09-11  1:10   ` Jeremy Kerr
2020-09-11  1:15     ` Joel Stanley

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.