Exemplo n.º 1
0
/**
 * xgpiops_set_value - Modify the state of the pin with specified value
 * @chip:	gpio_chip instance to be worked on
 * @pin:	gpio pin number within the device
 * @state:	value used to modify the state of the specified pin
 *
 * This function calculates the register offset (i.e to lower 16 bits or
 * upper 16 bits) based on the given pin number and sets the state of a
 * gpio pin to the specified value. The state is either 0 or non-zero.
 */
static void xgpiops_set_value(struct gpio_chip *chip, unsigned int pin,
			       int state)
{
	unsigned long flags;
	unsigned int reg_offset;
	unsigned int bank_num, bank_pin_num;
	struct xgpiops *gpio = container_of(chip, struct xgpiops, chip);

	xgpiops_get_bank_pin(pin, &bank_num, &bank_pin_num);

	if (bank_pin_num >= 16) {
		bank_pin_num -= 16; /* only 16 data bits in bit maskable reg */
		reg_offset = XGPIOPS_DATA_MSW_OFFSET(bank_num);
	} else {
		reg_offset = XGPIOPS_DATA_LSW_OFFSET(bank_num);
	}

	/*
	 * get the 32 bit value to be written to the mask/data register where
	 * the upper 16 bits is the mask and lower 16 bits is the data
	 */
	if (state)
		state = 1;
	state = ~(1 << (bank_pin_num + 16)) & ((state << bank_pin_num) |
					       0xFFFF0000);

	spin_lock_irqsave(&gpio->gpio_lock, flags);
	xgpiops_writereg(state, gpio->base_addr + reg_offset);
	spin_unlock_irqrestore(&gpio->gpio_lock, flags);
}
Exemplo n.º 2
0
/**
 * xgpiops_irq_unmask - Enable the interrupts for a gpio pin
 * @irq_data: irq data containing irq number of gpio pin for the irq to enable
 *
 * This function calculates the gpio pin number from irq number and sets the
 * bit in the Interrupt Enable register of the corresponding bank to enable
 * interrupts for that pin.
 */
static void xgpiops_irq_unmask(struct irq_data *irq_data)
{
	struct xgpiops *gpio = irq_data_get_irq_chip_data(irq_data);
	unsigned int device_pin_num, bank_num, bank_pin_num;

	device_pin_num = irq_data->hwirq;
	xgpiops_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
	xgpiops_writereg(1 << bank_pin_num,
			  gpio->base_addr + XGPIOPS_INTEN_OFFSET(bank_num));
}
Exemplo n.º 3
0
/**
 * xgpiops_irq_mask - Disable the interrupts for a gpio pin
 * @irq:	irq number of gpio pin for which interrupt is to be disabled
 *
 * This function calculates gpio pin number from irq number and sets the
 * bit in the Interrupt Disable register of the corresponding bank to disable
 * interrupts for that pin.
 */
static void xgpiops_irq_mask(struct irq_data *irq_data)
{
	struct xgpiops *gpio = (struct xgpiops *)irq_data_get_irq_chip_data(irq_data);
	unsigned int device_pin_num, bank_num, bank_pin_num;

	device_pin_num = irq_to_gpio(irq_data->irq); /* get pin num within the device */
	xgpiops_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);
	xgpiops_writereg(1 << bank_pin_num,
			  gpio->base_addr + XGPIOPS_INTDIS_OFFSET(bank_num));
}
Exemplo n.º 4
0
/**
 * xgpiops_set_irq_type - Set the irq type for a gpio pin
 * @irq_data:	irq data containing irq number of gpio pin
 * @type:	interrupt type that is to be set for the gpio pin
 *
 * This function gets the gpio pin number and its bank from the gpio pin number
 * and configures the INT_TYPE, INT_POLARITY and INT_ANY registers. Returns 0,
 * negative error otherwise.
 * TYPE-EDGE_RISING,  INT_TYPE - 1, INT_POLARITY - 1,  INT_ANY - 0;
 * TYPE-EDGE_FALLING, INT_TYPE - 1, INT_POLARITY - 0,  INT_ANY - 0;
 * TYPE-EDGE_BOTH,    INT_TYPE - 1, INT_POLARITY - NA, INT_ANY - 1;
 * TYPE-LEVEL_HIGH,   INT_TYPE - 0, INT_POLARITY - 1,  INT_ANY - NA;
 * TYPE-LEVEL_LOW,    INT_TYPE - 0, INT_POLARITY - 0,  INT_ANY - NA
 */
static int xgpiops_set_irq_type(struct irq_data *irq_data, unsigned int type)
{
	struct xgpiops *gpio = irq_data_get_irq_chip_data(irq_data);
	unsigned int device_pin_num, bank_num, bank_pin_num;
	unsigned int int_type, int_pol, int_any;

	device_pin_num = irq_data->hwirq;
	xgpiops_get_bank_pin(device_pin_num, &bank_num, &bank_pin_num);

	int_type = xgpiops_readreg(gpio->base_addr +
				    XGPIOPS_INTTYPE_OFFSET(bank_num));
	int_pol = xgpiops_readreg(gpio->base_addr +
				   XGPIOPS_INTPOL_OFFSET(bank_num));
	int_any = xgpiops_readreg(gpio->base_addr +
				   XGPIOPS_INTANY_OFFSET(bank_num));

	/*
	 * based on the type requested, configure the INT_TYPE, INT_POLARITY
	 * and INT_ANY registers
	 */
	switch (type) {
	case IRQ_TYPE_EDGE_RISING:
		int_type |= (1 << bank_pin_num);
		int_pol |= (1 << bank_pin_num);
		int_any &= ~(1 << bank_pin_num);
		break;
	case IRQ_TYPE_EDGE_FALLING:
		int_type |= (1 << bank_pin_num);
		int_pol &= ~(1 << bank_pin_num);
		int_any &= ~(1 << bank_pin_num);
		break;
	case IRQ_TYPE_EDGE_BOTH:
		int_type |= (1 << bank_pin_num);
		int_any |= (1 << bank_pin_num);
		break;
	case IRQ_TYPE_LEVEL_HIGH:
		int_type &= ~(1 << bank_pin_num);
		int_pol |= (1 << bank_pin_num);
		break;
	case IRQ_TYPE_LEVEL_LOW:
		int_type &= ~(1 << bank_pin_num);
		int_pol &= ~(1 << bank_pin_num);
		break;
	default:
		return -EINVAL;
	}

	xgpiops_writereg(int_type,
			  gpio->base_addr + XGPIOPS_INTTYPE_OFFSET(bank_num));
	xgpiops_writereg(int_pol,
			  gpio->base_addr + XGPIOPS_INTPOL_OFFSET(bank_num));
	xgpiops_writereg(int_any,
			  gpio->base_addr + XGPIOPS_INTANY_OFFSET(bank_num));
	return 0;
}
Exemplo n.º 5
0
/**
 * xgpiops_get_value - Get the state of the specified pin of GPIO device
 * @chip:	gpio_chip instance to be worked on
 * @pin:	gpio pin number within the device
 *
 * This function reads the state of the specified pin of the GPIO device.
 * It returns 0 if the pin is low, 1 if pin is high.
 */
static int xgpiops_get_value(struct gpio_chip *chip, unsigned int pin)
{
	unsigned int bank_num, bank_pin_num;
	struct xgpiops *gpio = container_of(chip, struct xgpiops, chip);

	xgpiops_get_bank_pin(pin, &bank_num, &bank_pin_num);

	return (xgpiops_readreg(gpio->base_addr +
				 XGPIOPS_DATA_OFFSET(bank_num)) >>
		bank_pin_num) & 1;
}
Exemplo n.º 6
0
/**
 * xgpiops_dir_in - Set the direction of the specified GPIO pin as input
 * @chip:	gpio_chip instance to be worked on
 * @pin:	gpio pin number within the device
 *
 * This function uses the read-modify-write sequence to set the direction of
 * the gpio pin as input. Returns 0 always.
 */
static int xgpiops_dir_in(struct gpio_chip *chip, unsigned int pin)
{
	unsigned int reg, bank_num, bank_pin_num;
	struct xgpiops *gpio = container_of(chip, struct xgpiops, chip);

	xgpiops_get_bank_pin(pin, &bank_num, &bank_pin_num);
	/* clear the bit in direction mode reg to set the pin as input */
	reg = xgpiops_readreg(gpio->base_addr + XGPIOPS_DIRM_OFFSET(bank_num));
	reg &= ~(1 << bank_pin_num);
	xgpiops_writereg(reg, gpio->base_addr + XGPIOPS_DIRM_OFFSET(bank_num));

	return 0;
}
Exemplo n.º 7
0
/**
 * xgpiops_dir_out - Set the direction of the specified GPIO pin as output
 * @chip:	gpio_chip instance to be worked on
 * @pin:	gpio pin number within the device
 * @state:	value to be written to specified pin
 *
 * This function sets the direction of specified GPIO pin as output, configures
 * the Output Enable register for the pin and uses xgpiops_set to set the state
 * of the pin to the value specified. Returns 0 always.
 */
static int xgpiops_dir_out(struct gpio_chip *chip, unsigned int pin, int state)
{
	struct xgpiops *gpio = container_of(chip, struct xgpiops, chip);
	unsigned int reg, bank_num, bank_pin_num;

	xgpiops_get_bank_pin(pin, &bank_num, &bank_pin_num);

	/* set the GPIO pin as output */
	reg = xgpiops_readreg(gpio->base_addr + XGPIOPS_DIRM_OFFSET(bank_num));
	reg |= 1 << bank_pin_num;
	xgpiops_writereg(reg, gpio->base_addr + XGPIOPS_DIRM_OFFSET(bank_num));

	/* configure the output enable reg for the pin */
	reg = xgpiops_readreg(gpio->base_addr + XGPIOPS_OUTEN_OFFSET(bank_num));
	reg |= 1 << bank_pin_num;
	xgpiops_writereg(reg, gpio->base_addr + XGPIOPS_OUTEN_OFFSET(bank_num));

	/* set the state of the pin */
	xgpiops_set_value(chip, pin, state);
	return 0;
}