gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
Subsystems (3)
PATCH 1/2 gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
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.
--- .../devicetree/bindings/gpio/sgpio-aspeed.txt | 5 +- drivers/gpio/gpio-aspeed-sgpio.c | 115 +++++++++++------- 2 files changed, 77 insertions(+), 43 deletions(-)
Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt +3 -2
@@ -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
drivers/gpio/gpio-aspeed-sgpio.c +74 -41
217 lines not on this page · raw message
Signature · 1 line
2.27.0
PATCH 2/2 gpio/aspeed-sgpio: don't enable all interrupts by default
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.
--- drivers/gpio/gpio-aspeed-sgpio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/gpio/gpio-aspeed-sgpio.c +1 -3
@@ -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 ;
Signature · 1 line
2.27.0
Joel Stanley
maintainerPATCH 2/2 gpio/aspeed-sgpio: don't enable all interrupts by default
drivers/gpio/gpio-aspeed-sgpio.c
Quoted 16 lines · Jeremy Kerr
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 <[email protected]>--- drivers/gpio/gpio-aspeed-sgpio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)drivers/gpio/gpio-aspeed-sgpio.c +0
-0
I've re-ordered the lines in the diff to make it easier to review:
drivers/gpio/gpio-aspeed-sgpio.c static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, · line 454
Quoted 6 lines
drivers/gpio/gpio-aspeed-sgpio.c +1
-1@@ -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.
drivers/gpio/gpio-aspeed-sgpio.c static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, · line 456
Quoted 2 lines
drivers/gpio/gpio-aspeed-sgpio.c +0
-2-/* 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
PATCH 2/2 gpio/aspeed-sgpio: don't enable all interrupts by default
Hi Joel,
Quoted 6 lines
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
kernel test robot
build botI love your patch! Perhaps something to improve:
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
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 at lists.01.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 73535 bytes
Desc: not available
URL: <http://lists.ozlabs.org/pipermail/linux-aspeed/attachments/20200716/0386f5c3/attachment-0001.gz>
kernel test robot
build botI love your patch! Perhaps something to improve:
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
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/[email protected]
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 75338 bytes
Desc: not available
URL: <http://lists.ozlabs.org/pipermail/linux-aspeed/attachments/20200716/3722f2e0/attachment-0001.gz>
Joel Stanley
maintainerPATCH 1/2 gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
In reply to Jeremy KerrQuoted 8 lines · Jeremy Kerr
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.
Quoted 8 lines
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 <[email protected]>
A Fixes: might be a good idea.
Quoted 10 lines
--- .../devicetree/bindings/gpio/sgpio-aspeed.txt | 5 +- drivers/gpio/gpio-aspeed-sgpio.c | 115 +++++++++++------- 2 files changed, 77 insertions(+), 43 deletions(-)drivers/gpio/gpio-aspeed-sgpio.c +0
-0
drivers/gpio/gpio-aspeed-sgpio.c line 21
Quoted 6 lines
drivers/gpio/gpio-aspeed-sgpio.c +2
-1@@ -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.
Quoted 4 lines
drivers/gpio/gpio-aspeed-sgpio.c +4
-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);
drivers/gpio/gpio-aspeed-sgpio.c static void __iomem *bank_reg(struct aspeed_sgpio *gpio, · line 162
Quoted 10 lines
drivers/gpio/gpio-aspeed-sgpio.c +10
-0+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.
Quoted 12 lines
drivers/gpio/gpio-aspeed-sgpio.c +4
-2+{ +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); -
drivers/gpio/gpio-aspeed-sgpio.c static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val) · line 242
Quoted 10 lines
drivers/gpio/gpio-aspeed-sgpio.c +4
-2- 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
PATCH 1/2 gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
Hi Joel,
Thanks for the review!
Quoted 1 line
A Fixes: might be a good idea.
OK, given this isn't strictly (just) a fix, should I split that out?
Quoted 6 lines
drivers/gpio/gpio-aspeed-sgpio.c line 21
Quoted 3 lines
drivers/gpio/gpio-aspeed-sgpio.c +2
-1-#define MAX_NR_SGPIO 80 +#define MAX_NR_HW_SGPIO 80 +#define SGPIO_OUTPUT_OFFSET MAX_NR_HW_SGPIOA 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.
Quoted 17 lines
Quoted 5 lines
drivers/gpio/gpio-aspeed-sgpio.c +4
-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);drivers/gpio/gpio-aspeed-sgpio.c static void __iomem *bank_reg(struct aspeed_sgpio *gpio, · line 162
Quoted 10 lines
drivers/gpio/gpio-aspeed-sgpio.c +10
-0+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.
Quoted 16 lines
Quoted 16 lines
drivers/gpio/gpio-aspeed-sgpio.c +6
-4+{ +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 */
Quoted 7 lines
drivers/gpio/gpio-aspeed-sgpio.c static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val) · line 242
Quoted 5 lines
drivers/gpio/gpio-aspeed-sgpio.c +2
-0+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
Joel Stanley
maintainerPATCH 1/2 gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
Quoted 8 lines · Jeremy Kerr
Hi Joel,
Thanks for the review!
Quoted 1 line
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
Quoted 61 lines
Quoted 7 lines
drivers/gpio/gpio-aspeed-sgpio.c line 21
Quoted 4 lines
drivers/gpio/gpio-aspeed-sgpio.c +2
-1-#define MAX_NR_SGPIO 80 +#define MAX_NR_HW_SGPIO 80 +#define SGPIO_OUTPUT_OFFSET MAX_NR_HW_SGPIOA 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.
Quoted 17 lines
Quoted 5 lines
drivers/gpio/gpio-aspeed-sgpio.c +4
-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);drivers/gpio/gpio-aspeed-sgpio.c static void __iomem *bank_reg(struct aspeed_sgpio *gpio, · line 162
Quoted 10 lines
drivers/gpio/gpio-aspeed-sgpio.c +10
-0+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.
Quoted 16 lines
Quoted 16 lines
drivers/gpio/gpio-aspeed-sgpio.c +6
-4+{ +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 */ Quoted 7 lines
drivers/gpio/gpio-aspeed-sgpio.c static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val) · line 242
Quoted 5 lines
drivers/gpio/gpio-aspeed-sgpio.c +2
-0+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