struct mpc52xx_psc_spi { /* driver internal data */ struct mpc52xx_psc __iomem *psc; struct mpc52xx_psc_fifo __iomem *fifo; int irq;
u8 bits_per_word;
struct completion done;
};
/* controller state */ struct mpc52xx_psc_spi_cs { int bits_per_word; int speed_hz;
};
/* set clock freq, clock ramp, bits per work * if t is NULL then reset the values to the default values
*/ staticint mpc52xx_psc_spi_transfer_setup(struct spi_device *spi, struct spi_transfer *t)
{ struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
/* Set clock frequency and bits per word * Because psc->ccr is defined as 16bit register instead of 32bit * just set the lower byte of BitClkDiv
*/
ccr = in_be16((u16 __iomem *)&psc->ccr);
ccr &= 0xFF00; if (cs->speed_hz)
ccr |= (MCLK / cs->speed_hz - 1) & 0xFF; else/* by default SPI Clk 1MHz */
ccr |= (MCLK / 1000000 - 1) & 0xFF;
out_be16((u16 __iomem *)&psc->ccr, ccr);
mps->bits_per_word = cs->bits_per_word;
}
#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1) /* wake up when 80% fifo full */ #define MPC52xx_PSC_RFALARM (MPC52xx_PSC_BUFSIZE * 20 / 100)
staticint mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi, struct spi_transfer *t)
{ struct mpc52xx_psc_spi *mps = spi_controller_get_devdata(spi->controller); struct mpc52xx_psc __iomem *psc = mps->psc; struct mpc52xx_psc_fifo __iomem *fifo = mps->fifo; unsigned rb = 0; /* number of bytes received */ unsigned sb = 0; /* number of bytes sent */ unsignedchar *rx_buf = (unsignedchar *)t->rx_buf; unsignedchar *tx_buf = (unsignedchar *)t->tx_buf; unsigned rfalarm; unsigned send_at_once = MPC52xx_PSC_BUFSIZE; unsigned recv_at_once; int last_block = 0;
if (!t->tx_buf && !t->rx_buf && t->len) return -EINVAL;
dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once); for (; send_at_once; sb++, send_at_once--) { /* set EOF flag before the last word is sent */ if (send_at_once == 1 && last_block)
out_8(&psc->ircr2, 0x01);
if (tx_buf)
out_8(&psc->mpc52xx_psc_buffer_8, tx_buf[sb]); else
out_8(&psc->mpc52xx_psc_buffer_8, 0);
}
/* enable interrupts and wait for wake up * if just one byte is expected the Rx FIFO genererates no * FFULL interrupt, so activate the RxRDY interrupt
*/
out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); if (t->len - rb == 1) {
out_8(&psc->mode, 0);
} else {
out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
out_be16(&fifo->rfalarm, rfalarm);
}
out_be16(&psc->mpc52xx_psc_imr, MPC52xx_PSC_IMR_RXRDY);
wait_for_completion(&mps->done);
recv_at_once = in_be16(&fifo->rfnum);
dev_dbg(&spi->dev, "%d bytes received\n", recv_at_once);
/* default sysclk is 512MHz */
mclken_div = 512000000 / MCLK;
ret = mpc52xx_set_psc_clkdiv(psc_id, mclken_div); if (ret) return ret;
/* Reset the PSC into a known state */
out_8(&psc->command, MPC52xx_PSC_RST_RX);
out_8(&psc->command, MPC52xx_PSC_RST_TX);
out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
/* Disable interrupts, interrupts are based on alarm level */
out_be16(&psc->mpc52xx_psc_imr, 0);
out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
out_8(&fifo->rfcntl, 0);
out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
/* Configure 8bit codec mode as a SPI host and use EOF flags */ /* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
out_be32(&psc->sicr, 0x0180C800);
out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */
/* Set 2ms DTL delay */
out_8(&psc->ctur, 0x00);
out_8(&psc->ctlr, 0x84);
/* disable interrupt and wake up the work queue */ if (in_be16(&psc->mpc52xx_psc_isr) & MPC52xx_PSC_IMR_RXRDY) {
out_be16(&psc->mpc52xx_psc_imr, 0);
complete(&mps->done); return IRQ_HANDLED;
} return IRQ_NONE;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.