diff options
Diffstat (limited to 'drivers/gpio/gpio-gpio-mm.c')
| -rw-r--r-- | drivers/gpio/gpio-gpio-mm.c | 78 | 
1 files changed, 25 insertions, 53 deletions
diff --git a/drivers/gpio/gpio-gpio-mm.c b/drivers/gpio/gpio-gpio-mm.c index 78a1db24e931..b89b8c5ff1f5 100644 --- a/drivers/gpio/gpio-gpio-mm.c +++ b/drivers/gpio/gpio-gpio-mm.c @@ -52,7 +52,10 @@ static int gpiomm_gpio_get_direction(struct gpio_chip *chip,  	const unsigned int port = offset / 8;  	const unsigned int mask = BIT(offset % 8); -	return !!(gpiommgpio->io_state[port] & mask); +	if (gpiommgpio->io_state[port] & mask) +		return GPIO_LINE_DIRECTION_IN; + +	return GPIO_LINE_DIRECTION_OUT;  }  static int gpiomm_gpio_direction_input(struct gpio_chip *chip, @@ -164,46 +167,25 @@ static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset)  	return !!(port_state & mask);  } +static const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; +  static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,  	unsigned long *bits)  {  	struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); -	size_t i; -	static const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; -	const unsigned int gpio_reg_size = 8; -	unsigned int bits_offset; -	size_t word_index; -	unsigned int word_offset; -	unsigned long word_mask; -	const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); +	unsigned long offset; +	unsigned long gpio_mask; +	unsigned int port_addr;  	unsigned long port_state;  	/* clear bits array to a clean slate */  	bitmap_zero(bits, chip->ngpio); -	/* get bits are evaluated a gpio port register at a time */ -	for (i = 0; i < ARRAY_SIZE(ports); i++) { -		/* gpio offset in bits array */ -		bits_offset = i * gpio_reg_size; - -		/* word index for bits array */ -		word_index = BIT_WORD(bits_offset); +	for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { +		port_addr = gpiommgpio->base + ports[offset / 8]; +		port_state = inb(port_addr) & gpio_mask; -		/* gpio offset within current word of bits array */ -		word_offset = bits_offset % BITS_PER_LONG; - -		/* mask of get bits for current gpio within current word */ -		word_mask = mask[word_index] & (port_mask << word_offset); -		if (!word_mask) { -			/* no get bits in this port so skip to next one */ -			continue; -		} - -		/* read bits from current gpio port */ -		port_state = inb(gpiommgpio->base + ports[i]); - -		/* store acquired bits at respective bits array offset */ -		bits[word_index] |= (port_state << word_offset) & word_mask; +		bitmap_set_value8(bits, port_state, offset);  	}  	return 0; @@ -234,37 +216,27 @@ static void gpiomm_gpio_set_multiple(struct gpio_chip *chip,  	unsigned long *mask, unsigned long *bits)  {  	struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); -	unsigned int i; -	const unsigned int gpio_reg_size = 8; -	unsigned int port; -	unsigned int out_port; -	unsigned int bitmask; +	unsigned long offset; +	unsigned long gpio_mask; +	size_t index; +	unsigned int port_addr; +	unsigned long bitmask;  	unsigned long flags; -	/* set bits are evaluated a gpio register size at a time */ -	for (i = 0; i < chip->ngpio; i += gpio_reg_size) { -		/* no more set bits in this mask word; skip to the next word */ -		if (!mask[BIT_WORD(i)]) { -			i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size; -			continue; -		} +	for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { +		index = offset / 8; +		port_addr = gpiommgpio->base + ports[index]; -		port = i / gpio_reg_size; -		out_port = (port > 2) ? port + 1 : port; -		bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)]; +		bitmask = bitmap_get_value8(bits, offset) & gpio_mask;  		spin_lock_irqsave(&gpiommgpio->lock, flags);  		/* update output state data and set device gpio register */ -		gpiommgpio->out_state[port] &= ~mask[BIT_WORD(i)]; -		gpiommgpio->out_state[port] |= bitmask; -		outb(gpiommgpio->out_state[port], gpiommgpio->base + out_port); +		gpiommgpio->out_state[index] &= ~gpio_mask; +		gpiommgpio->out_state[index] |= bitmask; +		outb(gpiommgpio->out_state[index], port_addr);  		spin_unlock_irqrestore(&gpiommgpio->lock, flags); - -		/* prepare for next gpio register set */ -		mask[BIT_WORD(i)] >>= gpio_reg_size; -		bits[BIT_WORD(i)] >>= gpio_reg_size;  	}  }  |