Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: stmpe: Add STMPE1600 support

The particularities of this variant are:
- GPIO_XXX_LSB and GPIO_XXX_MSB memory locations are inverted compared
to other variants.
- There is no Edge detection, Rising Edge and Falling Edge registers.
- IRQ flags are cleared when read, no need to write in Status register.

Signed-off-by: Amelie DELAUNAY <amelie.delaunay@st.com>
Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Patrice Chotard and committed by
Lee Jones
c6a05a05 6bb9f0d9

+38 -10
+38 -10
drivers/gpio/gpio-stmpe.c
··· 144 144 if (type & IRQ_TYPE_LEVEL_LOW || type & IRQ_TYPE_LEVEL_HIGH) 145 145 return -EINVAL; 146 146 147 - /* STMPE801 doesn't have RE and FE registers */ 148 - if (stmpe_gpio->stmpe->partnum == STMPE801) 147 + /* STMPE801 and STMPE 1600 don't have RE and FE registers */ 148 + if (stmpe_gpio->stmpe->partnum == STMPE801 || 149 + stmpe_gpio->stmpe->partnum == STMPE1600) 149 150 return 0; 150 151 151 152 if (type & IRQ_TYPE_EDGE_RISING) ··· 190 189 int i, j; 191 190 192 191 for (i = 0; i < CACHE_NR_REGS; i++) { 193 - /* STMPE801 doesn't have RE and FE registers */ 194 - if ((stmpe->partnum == STMPE801) && 195 - (i != REG_IE)) 192 + /* STMPE801 and STMPE1600 don't have RE and FE registers */ 193 + if ((stmpe->partnum == STMPE801 || 194 + stmpe->partnum == STMPE1600) && 195 + (i != REG_IE)) 196 196 continue; 197 197 198 198 for (j = 0; j < num_banks; j++) { ··· 226 224 { 227 225 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 228 226 struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc); 227 + struct stmpe *stmpe = stmpe_gpio->stmpe; 229 228 int offset = d->hwirq; 230 229 int regoffset = offset / 8; 231 230 int mask = 1 << (offset % 8); 232 231 233 232 stmpe_gpio->regs[REG_IE][regoffset] |= mask; 233 + 234 + /* 235 + * STMPE1600 workaround: to be able to get IRQ from pins, 236 + * a read must be done on GPMR register, or a write in 237 + * GPSR or GPCR registers 238 + */ 239 + if (stmpe->partnum == STMPE1600) 240 + stmpe_reg_read(stmpe, 241 + stmpe->regs[STMPE_IDX_GPMR_LSB + regoffset]); 234 242 } 235 243 236 244 static void stmpe_dbg_show_one(struct seq_file *s, ··· 313 301 fall = !!(ret & mask); 314 302 315 303 case STMPE801: 304 + case STMPE1600: 316 305 irqen_reg = stmpe->regs[STMPE_IDX_IEGPIOR_LSB + bank]; 317 306 break; 318 307 ··· 360 347 { 361 348 struct stmpe_gpio *stmpe_gpio = dev; 362 349 struct stmpe *stmpe = stmpe_gpio->stmpe; 363 - u8 statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB]; 350 + u8 statmsbreg; 364 351 int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); 365 352 u8 status[num_banks]; 366 353 int ret; 367 354 int i; 355 + 356 + /* 357 + * the stmpe_block_read() call below, imposes to set statmsbreg 358 + * with the register located at the lowest address. As STMPE1600 359 + * variant is the only one which respect registers address's order 360 + * (LSB regs located at lowest address than MSB ones) whereas all 361 + * the others have a registers layout with MSB located before the 362 + * LSB regs. 363 + */ 364 + if (stmpe->partnum == STMPE1600) 365 + statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_LSB]; 366 + else 367 + statmsbreg = stmpe->regs[STMPE_IDX_ISGPIOR_MSB]; 368 368 369 369 ret = stmpe_block_read(stmpe, statmsbreg, num_banks, status); 370 370 if (ret < 0) 371 371 return IRQ_NONE; 372 372 373 373 for (i = 0; i < num_banks; i++) { 374 - int bank = num_banks - i - 1; 374 + int bank = (stmpe_gpio->stmpe->partnum == STMPE1600) ? i : 375 + num_banks - i - 1; 375 376 unsigned int enabled = stmpe_gpio->regs[REG_IE][bank]; 376 377 unsigned int stat = status[i]; 377 378 ··· 405 378 406 379 /* 407 380 * interrupt status register write has no effect on 408 - * 801 and 1801, bits are cleared when read. 409 - * Edge detect register is not present on 801 and 1801 381 + * 801/1801/1600, bits are cleared when read. 382 + * Edge detect register is not present on 801/1600/1801 410 383 */ 411 - if (stmpe->partnum != STMPE801 || stmpe->partnum != STMPE1801) { 384 + if (stmpe->partnum != STMPE801 || stmpe->partnum != STMPE1600 || 385 + stmpe->partnum != STMPE1801) { 412 386 stmpe_reg_write(stmpe, statmsbreg + i, status[i]); 413 387 stmpe_reg_write(stmpe, 414 388 stmpe->regs[STMPE_IDX_GPEDR_LSB + i],