コード例 #1
0
ファイル: max3107-aava.c プロジェクト: 3sOx/asuswrt-merlin
/* GPIO direction to input function */
static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
	struct max3107_port *s = container_of(chip, struct max3107_port, chip);
	u16 buf[1];		/* Buffer for SPI transfer */

	if (offset >= MAX3107_GPIO_COUNT) {
		dev_err(&s->spi->dev, "Invalid GPIO\n");
		return -EINVAL;
	}

	/* Read current GPIO configuration register */
	buf[0] = MAX3107_GPIOCFG_REG;
	/* Perform SPI transfer */
	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
		dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n");
		return -EIO;
	}
	buf[0] &= MAX3107_SPI_RX_DATA_MASK;

	/* Set GPIO to input */
	buf[0] &= ~(0x0001 << offset);

	/* Write new GPIO configuration register value */
	buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
	/* Perform SPI transfer */
	if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
		dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n");
		return -EIO;
	}
	return 0;
}
コード例 #2
0
/* Handle interrupts
 * Also reads and returns current RX FIFO level
 */
static u16 handle_interrupt(struct max3107_port *s)
{
	u16 buf[4];	/* Buffer for SPI transfers */
	u8 irq_status;
	u16 rx_level;
	unsigned long flags;

	/* Read IRQ status register */
	buf[0] = MAX3107_IRQSTS_REG;
	/* Read status IRQ status register */
	buf[1] = MAX3107_STS_IRQSTS_REG;
	/* Read LSR IRQ status register */
	buf[2] = MAX3107_LSR_IRQSTS_REG;
	/* Query RX level */
	buf[3] = MAX3107_RXFIFOLVL_REG;

	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 8)) {
		dev_err(&s->spi->dev,
			"SPI transfer for INTR handling failed\n");
		return 0;
	}

	irq_status = (u8)buf[0];
	pr_debug("IRQSTS %x\n", irq_status);
	rx_level = (buf[3] & MAX3107_SPI_RX_DATA_MASK);

	if (irq_status & MAX3107_IRQ_LSR_BIT) {
		/* LSR interrupt */
		if (buf[2] & MAX3107_LSR_RXTO_BIT)
			/* RX timeout interrupt,
			 * handled by normal RX handling
			 */
			pr_debug("RX TO INT\n");
	}

	if (irq_status & MAX3107_IRQ_TXEMPTY_BIT) {
		/* Tx empty interrupt,
		 * disable TX and set tx_fifo_empty flag
		 */
		pr_debug("TE INT, disabling TX\n");
		buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
		spin_lock_irqsave(&s->data_lock, flags);
		s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT;
		buf[0] |= s->mode1_reg;
		spin_unlock_irqrestore(&s->data_lock, flags);
		if (max3107_rw(s, (u8 *)buf, NULL, 2))
			dev_err(&s->spi->dev, "SPI transfer TX dis failed\n");
		s->tx_enabled = 0;
		s->tx_fifo_empty = 1;
	}

	if (irq_status & MAX3107_IRQ_RXFIFO_BIT)
		/* RX FIFO interrupt,
		 * handled by normal RX handling
		 */
		pr_debug("RFIFO INT\n");

	/* Return RX level */
	return rx_level;
}
コード例 #3
0
ファイル: max3107-aava.c プロジェクト: 3sOx/asuswrt-merlin
/* GPIO direction to output function */
static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
					int value)
{
	struct max3107_port *s = container_of(chip, struct max3107_port, chip);
	u16 buf[2];	/* Buffer for SPI transfers */

	if (offset >= MAX3107_GPIO_COUNT) {
		dev_err(&s->spi->dev, "Invalid GPIO\n");
		return -EINVAL;
	}

	/* Read current GPIO configuration and data registers */
	buf[0] = MAX3107_GPIOCFG_REG;
	buf[1] = MAX3107_GPIODATA_REG;
	/* Perform SPI transfer */
	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
		dev_err(&s->spi->dev, "SPI transfer gpio failed\n");
		return -EIO;
	}
	buf[0] &= MAX3107_SPI_RX_DATA_MASK;
	buf[1] &= MAX3107_SPI_RX_DATA_MASK;

	/* Set GPIO to output */
	buf[0] |= (0x0001 << offset);
	/* Set value */
	if (value)
		buf[1] |= (0x0001 << offset);
	else
		buf[1] &= ~(0x0001 << offset);

	/* Write new GPIO configuration and data register values */
	buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
	buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
	/* Perform SPI transfer */
	if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
		dev_err(&s->spi->dev,
			"SPI transfer for GPIO conf data w failed\n");
		return -EIO;
	}
	return 0;
}
コード例 #4
0
ファイル: max3107-aava.c プロジェクト: 3sOx/asuswrt-merlin
/* GPIO value set function */
static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
	struct max3107_port *s = container_of(chip, struct max3107_port, chip);
	u16 buf[2];	/* Buffer for SPI transfers */

	if (offset >= MAX3107_GPIO_COUNT) {
		dev_err(&s->spi->dev, "Invalid GPIO\n");
		return;
	}

	/* Read current GPIO configuration registers*/
	buf[0] = MAX3107_GPIODATA_REG;
	buf[1] = MAX3107_GPIOCFG_REG;
	/* Perform SPI transfer */
	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
		dev_err(&s->spi->dev,
			"SPI transfer for GPIO data and config read failed\n");
		return;
	}
	buf[0] &= MAX3107_SPI_RX_DATA_MASK;
	buf[1] &= MAX3107_SPI_RX_DATA_MASK;

	if (!(buf[1] & (0x0001 << offset))) {
		/* Configured as input, can't set value */
		dev_warn(&s->spi->dev,
				"Trying to set value for input GPIO\n");
		return;
	}

	/* Set value */
	if (value)
		buf[0] |= (0x0001 << offset);
	else
		buf[0] &= ~(0x0001 << offset);

	/* Write new GPIO data register value */
	buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
	/* Perform SPI transfer */
	if (max3107_rw(s, (u8 *)buf, NULL, 2))
		dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n");
}
コード例 #5
0
ファイル: max3107-aava.c プロジェクト: 3sOx/asuswrt-merlin
/* GPIO value query function */
static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
{
	struct max3107_port *s = container_of(chip, struct max3107_port, chip);
	u16 buf[1];	/* Buffer for SPI transfer */

	if (offset >= MAX3107_GPIO_COUNT) {
		dev_err(&s->spi->dev, "Invalid GPIO\n");
		return -EINVAL;
	}

	/* Read current GPIO data register */
	buf[0] = MAX3107_GPIODATA_REG;
	/* Perform SPI transfer */
	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
		dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n");
		return -EIO;
	}
	buf[0] &= MAX3107_SPI_RX_DATA_MASK;

	/* Return value */
	return buf[0] & (0x0001 << offset);
}
コード例 #6
0
/* Work thread */
static void max3107_work(struct work_struct *w)
{
	struct max3107_port *s = container_of(w, struct max3107_port, work);
	u16 rxlvl = 0;
	int len;	/* SPI transfer buffer length */
	u16 buf[5];	/* Buffer for SPI transfers */
	unsigned long flags;

	/* Start by reading current RX FIFO level */
	buf[0] = MAX3107_RXFIFOLVL_REG;
	if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
		dev_err(&s->spi->dev, "SPI transfer RX lev failed\n");
		rxlvl = 0;
	} else {
		rxlvl = (buf[0] & MAX3107_SPI_RX_DATA_MASK);
	}

	do {
		pr_debug("rxlvl %d\n", rxlvl);

		/* Handle RX */
		max3107_handlerx(s, rxlvl);
		rxlvl = 0;

		if (s->handle_irq) {
			/* Handle pending interrupts
			 * We also get new RX FIFO level since new data may
			 * have been received while pushing received data to
			 * receivers
			 */
			s->handle_irq = 0;
			rxlvl = handle_interrupt(s);
		}

		/* Handle TX */
		max3107_handletx(s);

		/* Handle configuration changes */
		len = 0;
		spin_lock_irqsave(&s->data_lock, flags);
		if (s->mode1_commit) {
			pr_debug("mode1_commit\n");
			buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
			buf[len++] |= s->mode1_reg;
			s->mode1_commit = 0;
		}
		if (s->lcr_commit) {
			pr_debug("lcr_commit\n");
			buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG);
			buf[len++] |= s->lcr_reg;
			s->lcr_commit = 0;
		}
		if (s->brg_commit) {
			pr_debug("brg_commit\n");
			buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG);
			buf[len++] |= ((s->brg_cfg >> 16) &
						MAX3107_SPI_TX_DATA_MASK);
			buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG);
			buf[len++] |= ((s->brg_cfg >> 8) &
						MAX3107_SPI_TX_DATA_MASK);
			buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG);
			buf[len++] |= ((s->brg_cfg) & 0xff);
			s->brg_commit = 0;
		}
		spin_unlock_irqrestore(&s->data_lock, flags);

		if (len > 0) {
			if (max3107_rw(s, (u8 *)buf, NULL, len * 2))
				dev_err(&s->spi->dev,
					"SPI transfer config failed\n");
		}

		/* Reloop if interrupt handling indicated data in RX FIFO */
	} while (rxlvl);
コード例 #7
0
/* Handle data sending */
static void max3107_handletx(struct max3107_port *s)
{
	struct circ_buf *xmit = &s->port.state->xmit;
	int i;
	unsigned long flags;
	int len;				/* SPI transfer buffer length */
	u16 *buf;

	if (!s->tx_fifo_empty)
		/* Don't send more data before previous data is sent */
		return;

	if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port))
		/* No data to send or TX is stopped */
		return;

	if (!s->txbuf) {
		dev_warn(&s->spi->dev, "Txbuf isn't ready\n");
		return;
	}
	buf = s->txbuf;
	/* Get length of data pending in circular buffer */
	len = uart_circ_chars_pending(xmit);
	if (len) {
		/* Limit to size of TX FIFO */
		if (len > MAX3107_TX_FIFO_SIZE)
			len = MAX3107_TX_FIFO_SIZE;

		pr_debug("txlen %d\n", len);

		/* Update TX counter */
		s->port.icount.tx += len;

		/* TX FIFO will no longer be empty */
		s->tx_fifo_empty = 0;

		i = 0;
		if (s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT) {
			/* First disable TX empty interrupt */
			pr_debug("Disabling TE INT\n");
			buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
			s->irqen_reg &= ~MAX3107_IRQ_TXEMPTY_BIT;
			buf[i] |= s->irqen_reg;
			i++;
			len++;
		}
		/* Add data to send */
		spin_lock_irqsave(&s->port.lock, flags);
		for ( ; i < len ; i++) {
			buf[i] = (MAX3107_WRITE_BIT | MAX3107_THR_REG);
			buf[i] |= ((u16)xmit->buf[xmit->tail] &
						MAX3107_SPI_TX_DATA_MASK);
			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		}
		spin_unlock_irqrestore(&s->port.lock, flags);
		if (!(s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT)) {
			/* Enable TX empty interrupt */
			pr_debug("Enabling TE INT\n");
			buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
			s->irqen_reg |= MAX3107_IRQ_TXEMPTY_BIT;
			buf[i] |= s->irqen_reg;
			i++;
			len++;
		}
		if (!s->tx_enabled) {
			/* Enable TX */
			pr_debug("Enable TX\n");
			buf[i] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG);
			spin_lock_irqsave(&s->data_lock, flags);
			s->mode1_reg &= ~MAX3107_MODE1_TXDIS_BIT;
			buf[i] |= s->mode1_reg;
			spin_unlock_irqrestore(&s->data_lock, flags);
			s->tx_enabled = 1;
			i++;
			len++;
		}

		/* Perform the SPI transfer */
		if (max3107_rw(s, (u8 *)buf, NULL, len*2)) {
			dev_err(&s->spi->dev,
				"SPI transfer TX handling failed\n");
			return;
		}
	}

	/* Indicate wake up if circular buffer is getting low on data */
	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(&s->port);

}
コード例 #8
0
/* Handle data receiving */
static void max3107_handlerx(struct max3107_port *s, u16 rxlvl)
{
	int i;
	int j;
	int len;				/* SPI transfer buffer length */
	u16 *buf;
	u8 *valid_str;

	if (!s->rx_enabled)
		/* RX is disabled */
		return;

	if (rxlvl == 0) {
		/* RX fifo is empty */
		return;
	} else if (rxlvl >= MAX3107_RX_FIFO_SIZE) {
		dev_warn(&s->spi->dev, "Possible RX FIFO overrun %d\n", rxlvl);
		/* Ensure sanity of RX level */
		rxlvl = MAX3107_RX_FIFO_SIZE;
	}
	if ((s->rxbuf == 0) || (s->rxstr == 0)) {
		dev_warn(&s->spi->dev, "Rx buffer/str isn't ready\n");
		return;
	}
	buf = s->rxbuf;
	valid_str = s->rxstr;
	while (rxlvl) {
		pr_debug("rxlvl %d\n", rxlvl);
		/* Clear buffer */
		memset(buf, 0, sizeof(u16) * (MAX3107_RX_FIFO_SIZE + 2));
		len = 0;
		if (s->irqen_reg & MAX3107_IRQ_RXFIFO_BIT) {
			/* First disable RX FIFO interrupt */
			pr_debug("Disabling RX INT\n");
			buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
			s->irqen_reg &= ~MAX3107_IRQ_RXFIFO_BIT;
			buf[0] |= s->irqen_reg;
			len++;
		}
		/* Just increase the length by amount of words in FIFO since
		 * buffer was zeroed and SPI transfer of 0x0000 means reading
		 * from RX FIFO
		 */
		len += rxlvl;
		/* Append RX level query */
		buf[len] = MAX3107_RXFIFOLVL_REG;
		len++;

		/* Perform the SPI transfer */
		if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len * 2)) {
			dev_err(&s->spi->dev, "SPI transfer for RX h failed\n");
			return;
		}

		/* Skip RX FIFO interrupt disabling word if it was added */
		j = ((len - 1) - rxlvl);
		/* Read received words */
		for (i = 0; i < rxlvl; i++, j++)
			valid_str[i] = (u8)buf[j];
		put_data_to_circ_buf(s, valid_str, rxlvl);
		/* Get new RX level */
		rxlvl = (buf[len - 1] & MAX3107_SPI_RX_DATA_MASK);
	}

	if (s->rx_enabled) {
		/* RX still enabled, re-enable RX FIFO interrupt */
		pr_debug("Enabling RX INT\n");
		buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG);
		s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT;
		buf[0] |= s->irqen_reg;
		if (max3107_rw(s, (u8 *)buf, NULL, 2))
			dev_err(&s->spi->dev, "RX FIFO INT enabling failed\n");
	}

	/* Push the received data to receivers */
	if (s->port.state->port.tty)
		tty_flip_buffer_push(s->port.state->port.tty);
}