Skip to content

Commit 2443c2e

Browse files
Alban BedelBartosz Golaszewski
authored andcommitted
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>
1 parent 84cb463 commit 2443c2e

1 file changed

Lines changed: 60 additions & 0 deletions

File tree

drivers/gpio/gpio-kempld.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,33 @@ static int kempld_gpio_get(struct gpio_chip *chip, unsigned offset)
6565
return !!kempld_gpio_get_bit(pld, KEMPLD_GPIO_LVL, offset);
6666
}
6767

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+
6895
static int kempld_gpio_set(struct gpio_chip *chip, unsigned int offset,
6996
int value)
7097
{
@@ -78,6 +105,37 @@ static int kempld_gpio_set(struct gpio_chip *chip, unsigned int offset,
78105
return 0;
79106
}
80107

108+
static int kempld_gpio_set_multiple(struct gpio_chip *chip,
109+
unsigned long *mask, unsigned long *bits)
110+
{
111+
struct kempld_gpio_data *gpio = gpiochip_get_data(chip);
112+
struct kempld_device_data *pld = gpio->pld;
113+
u8 reg = gpio->out_lvl_reg;
114+
unsigned int shift;
115+
116+
kempld_get_mutex(pld);
117+
118+
/* Try to reduce to a single 8 bits access if possible */
119+
for (shift = 0; shift < gpio->chip.ngpio; shift += 8, reg++) {
120+
u8 val, msk = mask[0] >> shift;
121+
122+
if (!msk)
123+
continue;
124+
125+
if (msk != 0xFF)
126+
val = kempld_read8(pld, reg) & ~msk;
127+
else
128+
val = 0;
129+
130+
val |= (bits[0] >> shift) & msk;
131+
kempld_write8(pld, reg, val);
132+
}
133+
134+
kempld_release_mutex(pld);
135+
136+
return 0;
137+
}
138+
81139
static int kempld_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
82140
{
83141
struct kempld_gpio_data *gpio = gpiochip_get_data(chip);
@@ -180,7 +238,9 @@ static int kempld_gpio_probe(struct platform_device *pdev)
180238
chip->direction_output = kempld_gpio_direction_output;
181239
chip->get_direction = kempld_gpio_get_direction;
182240
chip->get = kempld_gpio_get;
241+
chip->get_multiple = kempld_gpio_get_multiple;
183242
chip->set = kempld_gpio_set;
243+
chip->set_multiple = kempld_gpio_set_multiple;
184244
chip->ngpio = kempld_gpio_pincount(pld);
185245
if (chip->ngpio == 0) {
186246
dev_err(dev, "No GPIO pins detected\n");

0 commit comments

Comments
 (0)