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

Configure Feed

Select the types of activity you want to include in your feed.

gpio: kempld: Add support for get/set multiple

As the bus accesses are quiet slow with this device, supporting the
get/set multiple API can help with performences. The implementation
tries to keep the number of bus access to a minimum by checking
the mask to only read or write the needed bytes.

Signed-off-by: Alban Bedel <alban.bedel@lht.dlh.de>
Link: https://patch.msgid.link/20260311143120.2179347-4-alban.bedel@lht.dlh.de
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

authored by

Alban Bedel and committed by
Bartosz Golaszewski
2443c2e1 84cb463d

+60
+60
drivers/gpio/gpio-kempld.c
··· 65 65 return !!kempld_gpio_get_bit(pld, KEMPLD_GPIO_LVL, offset); 66 66 } 67 67 68 + static int kempld_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, 69 + unsigned long *bits) 70 + { 71 + struct kempld_gpio_data *gpio = gpiochip_get_data(chip); 72 + struct kempld_device_data *pld = gpio->pld; 73 + u8 reg = KEMPLD_GPIO_LVL; 74 + unsigned int shift; 75 + 76 + bits[0] &= ~mask[0]; 77 + 78 + kempld_get_mutex(pld); 79 + 80 + /* Try to reduce to a single 8 bits access if possible */ 81 + for (shift = 0; shift < gpio->chip.ngpio; shift += 8, reg++) { 82 + unsigned long msk = (mask[0] >> shift) & 0xff; 83 + 84 + if (!msk) 85 + continue; 86 + 87 + bits[0] |= (kempld_read8(pld, reg) & msk) << shift; 88 + } 89 + 90 + kempld_release_mutex(pld); 91 + 92 + return 0; 93 + } 94 + 68 95 static int kempld_gpio_set(struct gpio_chip *chip, unsigned int offset, 69 96 int value) 70 97 { ··· 100 73 101 74 kempld_get_mutex(pld); 102 75 kempld_gpio_bitop(pld, gpio->out_lvl_reg, offset, value); 76 + kempld_release_mutex(pld); 77 + 78 + return 0; 79 + } 80 + 81 + static int kempld_gpio_set_multiple(struct gpio_chip *chip, 82 + unsigned long *mask, unsigned long *bits) 83 + { 84 + struct kempld_gpio_data *gpio = gpiochip_get_data(chip); 85 + struct kempld_device_data *pld = gpio->pld; 86 + u8 reg = gpio->out_lvl_reg; 87 + unsigned int shift; 88 + 89 + kempld_get_mutex(pld); 90 + 91 + /* Try to reduce to a single 8 bits access if possible */ 92 + for (shift = 0; shift < gpio->chip.ngpio; shift += 8, reg++) { 93 + u8 val, msk = mask[0] >> shift; 94 + 95 + if (!msk) 96 + continue; 97 + 98 + if (msk != 0xFF) 99 + val = kempld_read8(pld, reg) & ~msk; 100 + else 101 + val = 0; 102 + 103 + val |= (bits[0] >> shift) & msk; 104 + kempld_write8(pld, reg, val); 105 + } 106 + 103 107 kempld_release_mutex(pld); 104 108 105 109 return 0; ··· 238 180 chip->direction_output = kempld_gpio_direction_output; 239 181 chip->get_direction = kempld_gpio_get_direction; 240 182 chip->get = kempld_gpio_get; 183 + chip->get_multiple = kempld_gpio_get_multiple; 241 184 chip->set = kempld_gpio_set; 185 + chip->set_multiple = kempld_gpio_set_multiple; 242 186 chip->ngpio = kempld_gpio_pincount(pld); 243 187 if (chip->ngpio == 0) { 244 188 dev_err(dev, "No GPIO pins detected\n");