Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6b2ea66 authored by Russell King's avatar Russell King
Browse files

NET: sa11x0-ir: move SIR and FIR interrupt support



Move the interrupt handlers to the SIR and FIR sections of the file.
This improves the localization of the protocol handlers.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 374f7739
Loading
Loading
Loading
Loading
+141 −149
Original line number Diff line number Diff line
@@ -164,151 +164,6 @@ static int sa1100_irda_sir_tx_start(struct sk_buff *skb, struct net_device *dev,
	return NETDEV_TX_OK;
}

/*
 * FIR format support.
 */
static int sa1100_irda_fir_tx_start(struct sk_buff *skb, struct net_device *dev,
	struct sa1100_irda *si)
{
	int mtt = irda_get_mtt(skb);

	si->dma_tx.skb = skb;
	si->dma_tx.dma = dma_map_single(si->dev, skb->data, skb->len,
					DMA_TO_DEVICE);
	if (dma_mapping_error(si->dev, si->dma_tx.dma)) {
		si->dma_tx.skb = NULL;
		netif_wake_queue(dev);
		dev->stats.tx_dropped++;
		dev_kfree_skb(skb);
		return NETDEV_TX_OK;
	}

	sa1100_start_dma(si->dma_tx.regs, si->dma_tx.dma, skb->len);

	/*
	 * If we have a mean turn-around time, impose the specified
	 * specified delay.  We could shorten this by timing from
	 * the point we received the packet.
	 */
	if (mtt)
		udelay(mtt);

	Ser2HSCR0 = si->hscr0 | HSCR0_HSSP | HSCR0_TXE;

	return NETDEV_TX_OK;
}

static irqreturn_t sa1100_irda_sir_irq(struct net_device *, struct sa1100_irda *);
static irqreturn_t sa1100_irda_fir_irq(struct net_device *, struct sa1100_irda *);

/*
 * Set the IrDA communications speed.
 */
static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed)
{
	unsigned long flags;
	int brd, ret = -EINVAL;

	switch (speed) {
	case 9600:	case 19200:	case 38400:
	case 57600:	case 115200:
		brd = 3686400 / (16 * speed) - 1;

		/*
		 * Stop the receive DMA.
		 */
		if (IS_FIR(si))
			sa1100_stop_dma(si->dma_rx.regs);

		local_irq_save(flags);

		Ser2UTCR3 = 0;
		Ser2HSCR0 = HSCR0_UART;

		Ser2UTCR1 = brd >> 8;
		Ser2UTCR2 = brd;

		/*
		 * Clear status register
		 */
		Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
		Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;

		if (si->pdata->set_speed)
			si->pdata->set_speed(si->dev, speed);

		si->speed = speed;
		si->tx_start = sa1100_irda_sir_tx_start;
		si->irq = sa1100_irda_sir_irq;

		local_irq_restore(flags);
		ret = 0;
		break;

	case 4000000:
		local_irq_save(flags);

		si->hscr0 = 0;

		Ser2HSSR0 = 0xff;
		Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
		Ser2UTCR3 = 0;

		si->speed = speed;
		si->tx_start = sa1100_irda_fir_tx_start;
		si->irq = sa1100_irda_fir_irq;

		if (si->pdata->set_speed)
			si->pdata->set_speed(si->dev, speed);

		sa1100_irda_rx_alloc(si);
		sa1100_irda_rx_dma_start(si);

		local_irq_restore(flags);

		break;

	default:
		break;
	}

	return ret;
}

/*
 * Control the power state of the IrDA transmitter.
 * State:
 *  0 - off
 *  1 - short range, lowest power
 *  2 - medium range, medium power
 *  3 - maximum range, high power
 *
 * Currently, only assabet is known to support this.
 */
static int
__sa1100_irda_set_power(struct sa1100_irda *si, unsigned int state)
{
	int ret = 0;
	if (si->pdata->set_power)
		ret = si->pdata->set_power(si->dev, state);
	return ret;
}

static inline int
sa1100_set_power(struct sa1100_irda *si, unsigned int state)
{
	int ret;

	ret = __sa1100_irda_set_power(si, state);
	if (ret == 0)
		si->power = state;

	return ret;
}

/*
 * HP-SIR format interrupt service routines.
 */
static irqreturn_t sa1100_irda_sir_irq(struct net_device *dev, struct sa1100_irda *si)
{
	int status;
@@ -403,6 +258,40 @@ static irqreturn_t sa1100_irda_sir_irq(struct net_device *dev, struct sa1100_ird
	return IRQ_HANDLED;
}

/*
 * FIR format support.
 */
static int sa1100_irda_fir_tx_start(struct sk_buff *skb, struct net_device *dev,
	struct sa1100_irda *si)
{
	int mtt = irda_get_mtt(skb);

	si->dma_tx.skb = skb;
	si->dma_tx.dma = dma_map_single(si->dev, skb->data, skb->len,
					DMA_TO_DEVICE);
	if (dma_mapping_error(si->dev, si->dma_tx.dma)) {
		si->dma_tx.skb = NULL;
		netif_wake_queue(dev);
		dev->stats.tx_dropped++;
		dev_kfree_skb(skb);
		return NETDEV_TX_OK;
	}

	sa1100_start_dma(si->dma_tx.regs, si->dma_tx.dma, skb->len);

	/*
	 * If we have a mean turn-around time, impose the specified
	 * specified delay.  We could shorten this by timing from
	 * the point we received the packet.
	 */
	if (mtt)
		udelay(mtt);

	Ser2HSCR0 = si->hscr0 | HSCR0_HSSP | HSCR0_TXE;

	return NETDEV_TX_OK;
}

static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev)
{
	struct sk_buff *skb = si->dma_rx.skb;
@@ -476,10 +365,8 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
}

/*
 * FIR format interrupt service routine.  We only have to
 * handle RX events; transmit events go via the TX DMA handler.
 *
 * No matter what, we disable RX, process, and the restart RX.
 * We only have to handle RX events here; transmit events go via the TX
 * DMA handler. We disable RX, process, and the restart RX.
 */
static irqreturn_t sa1100_irda_fir_irq(struct net_device *dev, struct sa1100_irda *si)
{
@@ -528,6 +415,111 @@ static irqreturn_t sa1100_irda_fir_irq(struct net_device *dev, struct sa1100_ird
	return IRQ_HANDLED;
}

/*
 * Set the IrDA communications speed.
 */
static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed)
{
	unsigned long flags;
	int brd, ret = -EINVAL;

	switch (speed) {
	case 9600:	case 19200:	case 38400:
	case 57600:	case 115200:
		brd = 3686400 / (16 * speed) - 1;

		/*
		 * Stop the receive DMA.
		 */
		if (IS_FIR(si))
			sa1100_stop_dma(si->dma_rx.regs);

		local_irq_save(flags);

		Ser2UTCR3 = 0;
		Ser2HSCR0 = HSCR0_UART;

		Ser2UTCR1 = brd >> 8;
		Ser2UTCR2 = brd;

		/*
		 * Clear status register
		 */
		Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
		Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;

		if (si->pdata->set_speed)
			si->pdata->set_speed(si->dev, speed);

		si->speed = speed;
		si->tx_start = sa1100_irda_sir_tx_start;
		si->irq = sa1100_irda_sir_irq;

		local_irq_restore(flags);
		ret = 0;
		break;

	case 4000000:
		local_irq_save(flags);

		si->hscr0 = 0;

		Ser2HSSR0 = 0xff;
		Ser2HSCR0 = si->hscr0 | HSCR0_HSSP;
		Ser2UTCR3 = 0;

		si->speed = speed;
		si->tx_start = sa1100_irda_fir_tx_start;
		si->irq = sa1100_irda_fir_irq;

		if (si->pdata->set_speed)
			si->pdata->set_speed(si->dev, speed);

		sa1100_irda_rx_alloc(si);
		sa1100_irda_rx_dma_start(si);

		local_irq_restore(flags);

		break;

	default:
		break;
	}

	return ret;
}

/*
 * Control the power state of the IrDA transmitter.
 * State:
 *  0 - off
 *  1 - short range, lowest power
 *  2 - medium range, medium power
 *  3 - maximum range, high power
 *
 * Currently, only assabet is known to support this.
 */
static int
__sa1100_irda_set_power(struct sa1100_irda *si, unsigned int state)
{
	int ret = 0;
	if (si->pdata->set_power)
		ret = si->pdata->set_power(si->dev, state);
	return ret;
}

static inline int
sa1100_set_power(struct sa1100_irda *si, unsigned int state)
{
	int ret;

	ret = __sa1100_irda_set_power(si, state);
	if (ret == 0)
		si->power = state;

	return ret;
}

static irqreturn_t sa1100_irda_irq(int irq, void *dev_id)
{
	struct net_device *dev = dev_id;