/* This Function Wait Data TX Ready, and Write Data to SSP */ uint16_t ssp_transfer(ssp_num_t ssp_num, uint16_t data) { uint32_t ssp_port; if (ssp_num == SSP0_NUM) { ssp_port = SSP0; } else { ssp_port = SSP1; } /* Wait Until FIFO not full */ while ((SSP_SR(ssp_port) & SSP_SR_TNF) == 0); SSP_DR(ssp_port) = data; /* Wait for not busy, since we're controlling CS# of * devices manually and need to wait for the data to * be sent. It may also be important to wait here * in case we're configuring devices via SPI and also * with GPIO control -- we need to know when SPI * commands are effective before altering a device's * state with GPIO. I'm thinking the MAX2837, for * example... */ ssp_wait_until_not_busy(ssp_num); /* Wait Until Data Received (Rx FIFO not Empty) */ while ((SSP_SR(ssp_port) & SSP_SR_RNE) == 0); return SSP_DR(ssp_port); }
static int flush(struct pl022 *pl022) { unsigned long limit = loops_per_jiffy << 1; dev_dbg(&pl022->adev->dev, "flush\n"); do { while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) readw(SSP_DR(pl022->virtbase)); } while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_BSY) && limit--); return limit; }
static void readwriter(struct pl022 *pl022) { /* * The FIFO depth is different inbetween primecell variants. * I believe filling in too much in the FIFO might cause * errons in 8bit wide transfers on ARM variants (just 8 words * FIFO, means only 8x8 = 64 bits in FIFO) at least. * * To prevent this issue, the TX FIFO is only filled to the * unused RX FIFO fill length, regardless of what the TX * FIFO status flag indicates. */ dev_dbg(&pl022->adev->dev, "%s, rx: %p, rxend: %p, tx: %p, txend: %p\n", __func__, pl022->rx, pl022->rx_end, pl022->tx, pl022->tx_end); /* Read as much as you can */ while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) && (pl022->rx < pl022->rx_end)) { switch (pl022->read) { case READING_NULL: readw(SSP_DR(pl022->virtbase)); break; case READING_U8: *(u8 *) (pl022->rx) = readw(SSP_DR(pl022->virtbase)) & 0xFFU; break; case READING_U16: *(u16 *) (pl022->rx) = (u16) readw(SSP_DR(pl022->virtbase)); break; case READING_U32: *(u32 *) (pl022->rx) = readl(SSP_DR(pl022->virtbase)); break; } pl022->rx += (pl022->cur_chip->n_bytes); pl022->exp_fifo_level--; } /* * Write as much as possible up to the RX FIFO size */ while ((pl022->exp_fifo_level < pl022->vendor->fifodepth) && (pl022->tx < pl022->tx_end)) { switch (pl022->write) { case WRITING_NULL: writew(0x0, SSP_DR(pl022->virtbase)); break; case WRITING_U8: writew(*(u8 *) (pl022->tx), SSP_DR(pl022->virtbase)); break; case WRITING_U16: writew((*(u16 *) (pl022->tx)), SSP_DR(pl022->virtbase)); break; case WRITING_U32: writel(*(u32 *) (pl022->tx), SSP_DR(pl022->virtbase)); break; } pl022->tx += (pl022->cur_chip->n_bytes); pl022->exp_fifo_level++; /* * This inner reader takes care of things appearing in the RX * FIFO as we're transmitting. This will happen a lot since the * clock starts running when you put things into the TX FIFO, * and then things are continously clocked into the RX FIFO. */ while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) && (pl022->rx < pl022->rx_end)) { switch (pl022->read) { case READING_NULL: readw(SSP_DR(pl022->virtbase)); break; case READING_U8: *(u8 *) (pl022->rx) = readw(SSP_DR(pl022->virtbase)) & 0xFFU; break; case READING_U16: *(u16 *) (pl022->rx) = (u16) readw(SSP_DR(pl022->virtbase)); break; case READING_U32: *(u32 *) (pl022->rx) = readl(SSP_DR(pl022->virtbase)); break; } pl022->rx += (pl022->cur_chip->n_bytes); pl022->exp_fifo_level--; } } /* * When we exit here the TX FIFO should be full and the RX FIFO * should be empty */ }
static void readwriter(struct pl022 *pl022) { dev_dbg(&pl022->adev->dev, "%s, rx: %p, rxend: %p, tx: %p, txend: %p\n", __func__, pl022->rx, pl022->rx_end, pl022->tx, pl022->tx_end); while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) && (pl022->rx < pl022->rx_end)) { switch (pl022->read) { case READING_NULL: readw(SSP_DR(pl022->virtbase)); break; case READING_U8: *(u8 *) (pl022->rx) = readw(SSP_DR(pl022->virtbase)) & 0xFFU; break; case READING_U16: *(u16 *) (pl022->rx) = (u16) readw(SSP_DR(pl022->virtbase)); break; case READING_U32: *(u32 *) (pl022->rx) = readl(SSP_DR(pl022->virtbase)); break; } pl022->rx += (pl022->cur_chip->n_bytes); } while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF) && (pl022->tx < pl022->tx_end)) { switch (pl022->write) { case WRITING_NULL: writew(0x0, SSP_DR(pl022->virtbase)); break; case WRITING_U8: writew(*(u8 *) (pl022->tx), SSP_DR(pl022->virtbase)); break; case WRITING_U16: writew((*(u16 *) (pl022->tx)), SSP_DR(pl022->virtbase)); break; case WRITING_U32: writel(*(u32 *) (pl022->tx), SSP_DR(pl022->virtbase)); break; } pl022->tx += (pl022->cur_chip->n_bytes); while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE) && (pl022->rx < pl022->rx_end)) { switch (pl022->read) { case READING_NULL: readw(SSP_DR(pl022->virtbase)); break; case READING_U8: *(u8 *) (pl022->rx) = readw(SSP_DR(pl022->virtbase)) & 0xFFU; break; case READING_U16: *(u16 *) (pl022->rx) = (u16) readw(SSP_DR(pl022->virtbase)); break; case READING_U32: *(u32 *) (pl022->rx) = readl(SSP_DR(pl022->virtbase)); break; } pl022->rx += (pl022->cur_chip->n_bytes); } } }