/* * This macro is used to define some register default values. * reg is masked with mask, the OR:ed with an (again masked) * val shifted sb steps to the left.
*/ #define SSP_WRITE_BITS(reg, val, mask, sb) \
((reg) = (((reg) & ~(mask)) | (((val)<<(sb)) & (mask))))
/* * This macro is also used to define some default values. * It will just shift val by sb steps to the left and mask * the result with mask.
*/ #define GEN_MASK_BITS(val, mask, sb) \
(((val)<<(sb)) & (mask))
/* * The ST version of this block moves som bits * in SSP_CR0 and extends it to 32 bits
*/ #define SSP_CR0_MASK_DSS_ST (0x1FUL << 0) #define SSP_CR0_MASK_HALFDUP_ST (0x1UL << 5) #define SSP_CR0_MASK_CSS_ST (0x1FUL << 16) #define SSP_CR0_MASK_FRF_ST (0x3UL << 21)
/* * The ST version of this block adds some bits * in SSP_CR1
*/ #define SSP_CR1_MASK_RENDN_ST (0x1UL << 4) #define SSP_CR1_MASK_TENDN_ST (0x1UL << 5) #define SSP_CR1_MASK_MWAIT_ST (0x1UL << 6) #define SSP_CR1_MASK_RXIFLSEL_ST (0x7UL << 7) #define SSP_CR1_MASK_TXIFLSEL_ST (0x7UL << 10) /* This one is only in the PL023 variant */ #define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13)
/* * SSP Status Register - SSP_SR
*/ #define SSP_SR_MASK_TFE (0x1UL << 0) /* Transmit FIFO empty */ #define SSP_SR_MASK_TNF (0x1UL << 1) /* Transmit FIFO not full */ #define SSP_SR_MASK_RNE (0x1UL << 2) /* Receive FIFO not empty */ #define SSP_SR_MASK_RFF (0x1UL << 3) /* Receive FIFO full */ #define SSP_SR_MASK_BSY (0x1UL << 4) /* Busy Flag */
/* * SSP Test Data Register - SSP_TDR
*/ #define TDR_MASK_TESTDATA (0xFFFFFFFF)
/* * Message State * we use the spi_message.state (void *) pointer to * hold a single state value, that's why all this * (void *) casting is done here.
*/ #define STATE_START ((void *) 0) #define STATE_RUNNING ((void *) 1) #define STATE_DONE ((void *) 2) #define STATE_ERROR ((void *) -1) #define STATE_TIMEOUT ((void *) -2)
/* * SSP State - Whether Enabled or Disabled
*/ #define SSP_DISABLED (0) #define SSP_ENABLED (1)
/* * SSP DMA State - Whether DMA Enabled or Disabled
*/ #define SSP_DMA_DISABLED (0) #define SSP_DMA_ENABLED (1)
/* * The type of reading going on this chip
*/ enum ssp_reading {
READING_NULL,
READING_U8,
READING_U16,
READING_U32
};
/* * The type of writing going on this chip
*/ enum ssp_writing {
WRITING_NULL,
WRITING_U8,
WRITING_U16,
WRITING_U32
};
/** * struct vendor_data - vendor-specific config parameters * for PL022 derivates * @fifodepth: depth of FIFOs (both) * @max_bpw: maximum number of bits per word * @unidir: supports unidirection transfers * @extended_cr: 32 bit wide control register 0 with extra * features and extra features in CR1 as found in the ST variants * @pl023: supports a subset of the ST extensions called "PL023" * @loopback: supports loopback mode * @internal_cs_ctrl: supports chip select control register
*/ struct vendor_data { int fifodepth; int max_bpw; bool unidir; bool extended_cr; bool pl023; bool loopback; bool internal_cs_ctrl;
};
/** * struct pl022 - This is the private SSP driver data structure * @adev: AMBA device model hookup * @vendor: vendor data for the IP block * @phybase: the physical memory where the SSP device resides * @virtbase: the virtual memory where the SSP is mapped * @clk: outgoing clock "SPICLK" for the SPI bus * @host: SPI framework hookup * @host_info: controller-specific data from machine setup * @cur_transfer: Pointer to current spi_transfer * @cur_chip: pointer to current clients chip(assigned from controller_state) * @tx: current position in TX buffer to be read * @tx_end: end position in TX buffer to be read * @rx: current position in RX buffer to be written * @rx_end: end position in RX buffer to be written * @read: the type of read currently going on * @write: the type of write currently going on * @exp_fifo_level: expected FIFO level * @rx_lev_trig: receive FIFO watermark level which triggers IRQ * @tx_lev_trig: transmit FIFO watermark level which triggers IRQ * @dma_rx_channel: optional channel for RX DMA * @dma_tx_channel: optional channel for TX DMA * @sgt_rx: scattertable for the RX transfer * @sgt_tx: scattertable for the TX transfer * @dummypage: a dummy page used for driving data on the bus with DMA * @dma_running: indicates whether DMA is in operation * @cur_cs: current chip select index
*/ struct pl022 { struct amba_device *adev; struct vendor_data *vendor;
resource_size_t phybase; void __iomem *virtbase; struct clk *clk; struct spi_controller *host; struct pl022_ssp_controller *host_info; struct spi_transfer *cur_transfer; struct chip_data *cur_chip; void *tx; void *tx_end; void *rx; void *rx_end; enum ssp_reading read; enum ssp_writing write;
u32 exp_fifo_level; enum ssp_rx_level_trig rx_lev_trig; enum ssp_tx_level_trig tx_lev_trig; /* DMA settings */ #ifdef CONFIG_DMA_ENGINE struct dma_chan *dma_rx_channel; struct dma_chan *dma_tx_channel; struct sg_table sgt_rx; struct sg_table sgt_tx; char *dummypage; bool dma_running; #endif int cur_cs;
};
/** * struct chip_data - To maintain runtime state of SSP for each client chip * @cr0: Value of control register CR0 of SSP - on later ST variants this * register is 32 bits wide rather than just 16 * @cr1: Value of control register CR1 of SSP * @dmacr: Value of DMA control Register of SSP * @cpsr: Value of Clock prescale register * @n_bytes: how many bytes(power of 2) reqd for a given data width of client * @enable_dma: Whether to enable DMA or not * @read: function ptr to be used to read when doing xfer for this chip * @write: function ptr to be used to write when doing xfer for this chip * @xfer_type: polling/interrupt/DMA * * Runtime state of the SSP controller, maintained per chip, * This would be set according to the current message that would be served
*/ struct chip_data {
u32 cr0;
u16 cr1;
u16 dmacr;
u16 cpsr;
u8 n_bytes; bool enable_dma; enum ssp_reading read; enum ssp_writing write; int xfer_type;
};
/** * internal_cs_control - Control chip select signals via SSP_CSR. * @pl022: SSP driver private data structure * @enable: select/delect the chip * * Used on controller with internal chip select control via SSP_CSR register * (vendor extension). Each of the 5 LSB in the register controls one chip * select signal.
*/ staticvoid internal_cs_control(struct pl022 *pl022, bool enable)
{
u32 tmp;
/* * This will write to TX and read from RX according to the parameters * set in pl022.
*/ staticvoid readwriter(struct pl022 *pl022)
{
/* * The FIFO depth is different between 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 continuously 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
*/
}
/* * This DMA functionality is only compiled in if we have * access to the generic DMA devices/DMA engine.
*/ #ifdef CONFIG_DMA_ENGINE staticvoid unmap_free_dma_scatter(struct pl022 *pl022)
{ /* Unmap and free the SG tables */
dma_unmap_sg(pl022->dma_tx_channel->device->dev, pl022->sgt_tx.sgl,
pl022->sgt_tx.nents, DMA_TO_DEVICE);
dma_unmap_sg(pl022->dma_rx_channel->device->dev, pl022->sgt_rx.sgl,
pl022->sgt_rx.nents, DMA_FROM_DEVICE);
sg_free_table(&pl022->sgt_rx);
sg_free_table(&pl022->sgt_tx);
}
#ifdef VERBOSE_DEBUG /* * Optionally dump out buffers to inspect contents, this is * good if you want to convince yourself that the loopback * read/write contents are the same, when adopting to a new * DMA engine.
*/
{ struct scatterlist *sg; unsignedint i;
staticvoid setup_dma_scatter(struct pl022 *pl022, void *buffer, unsignedint length, struct sg_table *sgtab)
{ struct scatterlist *sg; int bytesleft = length; void *bufp = buffer; int mapbytes; int i;
if (buffer) {
for_each_sg(sgtab->sgl, sg, sgtab->nents, i) { /* * If there are less bytes left than what fits * in the current page (plus page alignment offset) * we just feed in this, else we stuff in as much * as we can.
*/ if (bytesleft < (PAGE_SIZE - offset_in_page(bufp)))
mapbytes = bytesleft; else
mapbytes = PAGE_SIZE - offset_in_page(bufp);
sg_set_page(sg, virt_to_page(bufp),
mapbytes, offset_in_page(bufp));
bufp += mapbytes;
bytesleft -= mapbytes;
dev_dbg(&pl022->adev->dev, "set RX/TX target page @ %p, %d bytes, %d left\n",
bufp, mapbytes, bytesleft);
}
} else { /* Map the dummy buffer on every page */
for_each_sg(sgtab->sgl, sg, sgtab->nents, i) { if (bytesleft < PAGE_SIZE)
mapbytes = bytesleft; else
mapbytes = PAGE_SIZE;
sg_set_page(sg, virt_to_page(pl022->dummypage),
mapbytes, 0);
bytesleft -= mapbytes;
dev_dbg(&pl022->adev->dev, "set RX/TX to dummy page %d bytes, %d left\n",
mapbytes, bytesleft);
}
}
BUG_ON(bytesleft);
}
/** * configure_dma - configures the channels for the next transfer * @pl022: SSP driver's private data structure
*/ staticint configure_dma(struct pl022 *pl022)
{ struct dma_slave_config rx_conf = {
.src_addr = SSP_DR(pl022->phybase),
.direction = DMA_DEV_TO_MEM,
.device_fc = false,
}; struct dma_slave_config tx_conf = {
.dst_addr = SSP_DR(pl022->phybase),
.direction = DMA_MEM_TO_DEV,
.device_fc = false,
}; unsignedint pages; int ret; int rx_sglen, tx_sglen; struct dma_chan *rxchan = pl022->dma_rx_channel; struct dma_chan *txchan = pl022->dma_tx_channel; struct dma_async_tx_descriptor *rxdesc; struct dma_async_tx_descriptor *txdesc;
/* Check that the channels are available */ if (!rxchan || !txchan) return -ENODEV;
/* * If supplied, the DMA burstsize should equal the FIFO trigger level. * Notice that the DMA engine uses one-to-one mapping. Since we can * not trigger on 2 elements this needs explicit mapping rather than * calculation.
*/ switch (pl022->rx_lev_trig) { case SSP_RX_1_OR_MORE_ELEM:
rx_conf.src_maxburst = 1; break; case SSP_RX_4_OR_MORE_ELEM:
rx_conf.src_maxburst = 4; break; case SSP_RX_8_OR_MORE_ELEM:
rx_conf.src_maxburst = 8; break; case SSP_RX_16_OR_MORE_ELEM:
rx_conf.src_maxburst = 16; break; case SSP_RX_32_OR_MORE_ELEM:
rx_conf.src_maxburst = 32; break; default:
rx_conf.src_maxburst = pl022->vendor->fifodepth >> 1; break;
}
switch (pl022->tx_lev_trig) { case SSP_TX_1_OR_MORE_EMPTY_LOC:
tx_conf.dst_maxburst = 1; break; case SSP_TX_4_OR_MORE_EMPTY_LOC:
tx_conf.dst_maxburst = 4; break; case SSP_TX_8_OR_MORE_EMPTY_LOC:
tx_conf.dst_maxburst = 8; break; case SSP_TX_16_OR_MORE_EMPTY_LOC:
tx_conf.dst_maxburst = 16; break; case SSP_TX_32_OR_MORE_EMPTY_LOC:
tx_conf.dst_maxburst = 32; break; default:
tx_conf.dst_maxburst = pl022->vendor->fifodepth >> 1; break;
}
switch (pl022->read) { case READING_NULL: /* Use the same as for writing */
rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; break; case READING_U8:
rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; break; case READING_U16:
rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; break; case READING_U32:
rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break;
}
switch (pl022->write) { case WRITING_NULL: /* Use the same as for reading */
tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED; break; case WRITING_U8:
tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; break; case WRITING_U16:
tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; break; case WRITING_U32:
tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; break;
}
/* SPI peculiarity: we need to read and write the same width */ if (rx_conf.src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
rx_conf.src_addr_width = tx_conf.dst_addr_width; if (tx_conf.dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
tx_conf.dst_addr_width = rx_conf.src_addr_width;
BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width);
/* Create sglists for the transfers */
pages = DIV_ROUND_UP(pl022->cur_transfer->len, PAGE_SIZE);
dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_ATOMIC); if (ret) goto err_alloc_rx_sg;
ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_ATOMIC); if (ret) goto err_alloc_tx_sg;
/* Fill in the scatterlists for the RX+TX buffers */
setup_dma_scatter(pl022, pl022->rx,
pl022->cur_transfer->len, &pl022->sgt_rx);
setup_dma_scatter(pl022, pl022->tx,
pl022->cur_transfer->len, &pl022->sgt_tx);
/* Put the callback on the RX transfer only, that should finish last */
rxdesc->callback = dma_callback;
rxdesc->callback_param = pl022;
/* Submit and fire RX and TX with TX last so we're ready to read! */
dmaengine_submit(rxdesc);
dmaengine_submit(txdesc);
dma_async_issue_pending(rxchan);
dma_async_issue_pending(txchan);
pl022->dma_running = true;
/* Try to acquire a generic DMA engine slave channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask); /* * We need both RX and TX channels to do DMA, else do none * of them.
*/
pl022->dma_rx_channel = dma_request_channel(mask,
pl022->host_info->dma_filter,
pl022->host_info->dma_rx_param); if (!pl022->dma_rx_channel) {
dev_dbg(&pl022->adev->dev, "no RX DMA channel!\n"); goto err_no_rxchan;
}
pl022->dma_tx_channel = dma_request_channel(mask,
pl022->host_info->dma_filter,
pl022->host_info->dma_tx_param); if (!pl022->dma_tx_channel) {
dev_dbg(&pl022->adev->dev, "no TX DMA channel!\n"); goto err_no_txchan;
}
pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!pl022->dummypage) goto err_no_dummypage;
dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n",
dma_chan_name(pl022->dma_rx_channel),
dma_chan_name(pl022->dma_tx_channel));
return 0;
err_no_dummypage:
dma_release_channel(pl022->dma_tx_channel);
err_no_txchan:
dma_release_channel(pl022->dma_rx_channel);
pl022->dma_rx_channel = NULL;
err_no_rxchan:
dev_err(&pl022->adev->dev, "Failed to work in dma mode, work without dma!\n"); return -ENODEV;
}
/** * pl022_interrupt_handler - Interrupt handler for SSP controller * @irq: IRQ number * @dev_id: Local device data * * This function handles interrupts generated for an interrupt based transfer. * If a receive overrun (ROR) interrupt is there then we disable SSP, flag the * current message's state as STATE_ERROR and schedule the tasklet * pump_transfers which will do the postprocessing of the current message by * calling giveback(). Otherwise it reads data from RX FIFO till there is no * more data, and writes data in TX FIFO till it is not full. If we complete * the transfer we move to the next transfer and schedule the tasklet.
*/ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
{ struct pl022 *pl022 = dev_id;
u16 irq_status = 0; /* Read the Interrupt Status Register */
irq_status = readw(SSP_MIS(pl022->virtbase));
if (unlikely(!irq_status)) return IRQ_NONE;
/* * This handles the FIFO interrupts, the timeout * interrupts are flatly ignored, they cannot be * trusted.
*/ if (unlikely(irq_status & SSP_MIS_MASK_RORMIS)) { /* * Overrun interrupt - bail out since our Data has been * corrupted
*/
dev_err(&pl022->adev->dev, "FIFO overrun\n"); if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
dev_err(&pl022->adev->dev, "RXFIFO is full\n");
/* * Disable and clear interrupts, disable SSP, * mark message with bad status so it can be * retried.
*/
writew(DISABLE_ALL_INTERRUPTS,
SSP_IMSC(pl022->virtbase));
writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
writew((readw(SSP_CR1(pl022->virtbase)) &
(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
pl022->cur_transfer->error |= SPI_TRANS_FAIL_IO;
spi_finalize_current_transfer(pl022->host); return IRQ_HANDLED;
}
/* * Since all transactions must write as much as shall be read, * we can conclude the entire transaction once RX is complete. * At this point, all TX will always be finished.
*/ if (pl022->rx >= pl022->rx_end) {
writew(DISABLE_ALL_INTERRUPTS,
SSP_IMSC(pl022->virtbase));
writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase)); if (unlikely(pl022->rx > pl022->rx_end)) {
dev_warn(&pl022->adev->dev, "read %u surplus " "bytes (did you request an odd " "number of bytes on a 16bit bus?)\n",
(u32) (pl022->rx - pl022->rx_end));
}
spi_finalize_current_transfer(pl022->host); return IRQ_HANDLED;
}
return IRQ_HANDLED;
}
/* * This sets up the pointers to memory for the next message to * send out on the SPI bus.
*/ staticint set_up_next_transfer(struct pl022 *pl022, struct spi_transfer *transfer)
{ int residue;
/* Sanity check the message for this bus width */
residue = pl022->cur_transfer->len % pl022->cur_chip->n_bytes; if (unlikely(residue != 0)) {
dev_err(&pl022->adev->dev, "message of %u bytes to transmit but the current " "chip bus has a data width of %u bytes!\n",
pl022->cur_transfer->len,
pl022->cur_chip->n_bytes);
dev_err(&pl022->adev->dev, "skipping this message\n"); return -EIO;
}
pl022->tx = (void *)transfer->tx_buf;
pl022->tx_end = pl022->tx + pl022->cur_transfer->len;
pl022->rx = (void *)transfer->rx_buf;
pl022->rx_end = pl022->rx + pl022->cur_transfer->len;
pl022->write =
pl022->tx ? pl022->cur_chip->write : WRITING_NULL;
pl022->read = pl022->rx ? pl022->cur_chip->read : READING_NULL; return 0;
}
staticint do_interrupt_dma_transfer(struct pl022 *pl022)
{ int ret;
/* * Default is to enable all interrupts except RX - * this will be enabled once TX is complete
*/
u32 irqflags = (u32)(ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM);
ret = set_up_next_transfer(pl022, pl022->cur_transfer); if (ret) return ret;
/* If we're using DMA, set up DMA here */ if (pl022->cur_chip->enable_dma) { /* Configure DMA transfer */ if (configure_dma(pl022)) {
dev_dbg(&pl022->adev->dev, "configuration of DMA failed, fall back to interrupt mode\n"); goto err_config_dma;
} /* Disable interrupts in DMA mode, IRQ from DMA controller */
irqflags = DISABLE_ALL_INTERRUPTS;
}
err_config_dma: /* Enable SSP, turn on interrupts */
writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
SSP_CR1(pl022->virtbase));
writew(irqflags, SSP_IMSC(pl022->virtbase)); return 1;
}
if (freq > max_tclk)
dev_warn(&pl022->adev->dev, "Max speed that can be programmed is %d Hz, you requested %d\n",
max_tclk, freq);
if (freq < min_tclk) {
dev_err(&pl022->adev->dev, "Requested frequency: %d Hz is less than minimum possible %d Hz\n",
freq, min_tclk); return -EINVAL;
}
/* * best_freq will give closest possible available rate (<= requested * freq) for all values of scr & cpsdvsr.
*/ while ((cpsdvsr <= CPSDVR_MAX) && !found) { while (scr <= SCR_MAX) {
tmp = spi_rate(rate, cpsdvsr, scr);
if (tmp > freq) { /* we need lower freq */
scr++; continue;
}
/* * If found exact value, mark found and break. * If found more closer value, update and break.
*/ if (tmp > best_freq) {
best_freq = tmp;
best_cpsdvsr = cpsdvsr;
best_scr = scr;
if (tmp == freq)
found = 1;
} /* * increased scr will give lower rates, which are not * required
*/ break;
}
cpsdvsr += 2;
scr = SCR_MIN;
}
WARN(!best_freq, "pl022: Matching cpsdvsr and scr not found for %d Hz rate \n",
freq);
clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
clk_freq->scr = (u8) (best_scr & 0xFF);
dev_dbg(&pl022->adev->dev, "SSP Target Frequency is: %u, Effective Frequency is %u\n",
freq, best_freq);
dev_dbg(&pl022->adev->dev, "SSP cpsdvsr = %d, scr = %d\n",
clk_freq->cpsdvsr, clk_freq->scr);
return 0;
}
/* * A piece of default chip info unless the platform * supplies it.
*/ staticconststruct pl022_config_chip pl022_default_chip_info = {
.com_mode = INTERRUPT_TRANSFER,
.iface = SSP_INTERFACE_MOTOROLA_SPI,
.hierarchy = SSP_MASTER,
.slave_tx_disable = DO_NOT_DRIVE_TX,
.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
.ctrl_len = SSP_BITS_8,
.wait_state = SSP_MWIRE_WAIT_ZERO,
.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
};
/** * pl022_setup - setup function registered to SPI host framework * @spi: spi device which is requesting setup * * This function is registered to the SPI framework for this SPI host * controller. If it is the first time when setup is called by this device, * this function will initialize the runtime state for this chip and save * the same in the device structure. Else it will update the runtime info * with the updated chip info. Nothing is really being written to the * controller hardware here, that is not done until the actual transfer * commence.
*/ staticint pl022_setup(struct spi_device *spi)
{ struct pl022_config_chip const *chip_info; struct pl022_config_chip chip_info_dt; struct chip_data *chip; struct ssp_clock_params clk_freq = { .cpsdvsr = 0, .scr = 0}; int status = 0; struct pl022 *pl022 = spi_controller_get_devdata(spi->controller); unsignedint bits = spi->bits_per_word;
u32 tmp; struct device_node *np = spi->dev.of_node;
if (!spi->max_speed_hz) return -EINVAL;
/* Get controller_state if one is supplied */
chip = spi_get_ctldata(spi);
if (chip == NULL) {
chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); if (!chip) return -ENOMEM;
dev_dbg(&spi->dev, "allocated memory for controller's runtime state\n");
}
/* Get controller data if one is supplied */
chip_info = spi->controller_data;
if (chip_info == NULL) { if (np) {
chip_info_dt = pl022_default_chip_info;
/* Now set controller state based on controller data */
chip->xfer_type = chip_info->com_mode;
/* Check bits per word with vendor specific range */ if ((bits <= 3) || (bits > pl022->vendor->max_bpw)) {
status = -ENOTSUPP;
dev_err(&spi->dev, "illegal data size for this controller!\n");
dev_err(&spi->dev, "This controller can only handle 4 <= n <= %d bit words\n",
pl022->vendor->max_bpw); goto err_config_params;
} elseif (bits <= 8) {
dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
chip->n_bytes = 1;
chip->read = READING_U8;
chip->write = WRITING_U8;
} elseif (bits <= 16) {
dev_dbg(&spi->dev, "9 <= n <= 16 bits per word\n");
chip->n_bytes = 2;
chip->read = READING_U16;
chip->write = WRITING_U16;
} else {
dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
chip->n_bytes = 4;
chip->read = READING_U32;
chip->write = WRITING_U32;
}
/* Now Initialize all register settings required for this chip */
chip->cr0 = 0;
chip->cr1 = 0;
chip->dmacr = 0;
chip->cpsr = 0; if ((chip_info->com_mode == DMA_TRANSFER)
&& ((pl022->host_info)->enable_dma)) {
chip->enable_dma = true;
dev_dbg(&spi->dev, "DMA mode set in controller state\n");
SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
SSP_DMACR_MASK_RXDMAE, 0);
SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
SSP_DMACR_MASK_TXDMAE, 1);
} else {
chip->enable_dma = false;
dev_dbg(&spi->dev, "DMA mode NOT set in controller state\n");
SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED,
SSP_DMACR_MASK_RXDMAE, 0);
SSP_WRITE_BITS(chip->dmacr, SSP_DMA_DISABLED,
SSP_DMACR_MASK_TXDMAE, 1);
}
chip->cpsr = clk_freq.cpsdvsr;
/* Special setup for the ST micro extended control registers */ if (pl022->vendor->extended_cr) {
u32 etx;
if (pl022->vendor->pl023) { /* These bits are only in the PL023 */
SSP_WRITE_BITS(chip->cr1, chip_info->clkdelay,
SSP_CR1_MASK_FBCLKDEL_ST, 13);
} else { /* These bits are in the PL022 but not PL023 */
SSP_WRITE_BITS(chip->cr0, chip_info->duplex,
SSP_CR0_MASK_HALFDUP_ST, 5);
SSP_WRITE_BITS(chip->cr0, chip_info->ctrl_len,
SSP_CR0_MASK_CSS_ST, 16);
SSP_WRITE_BITS(chip->cr0, chip_info->iface,
SSP_CR0_MASK_FRF_ST, 21);
SSP_WRITE_BITS(chip->cr1, chip_info->wait_state,
SSP_CR1_MASK_MWAIT_ST, 6);
}
SSP_WRITE_BITS(chip->cr0, bits - 1,
SSP_CR0_MASK_DSS_ST, 0);
/* Stuff that is common for all versions */ if (spi->mode & SPI_CPOL)
tmp = SSP_CLK_POL_IDLE_HIGH; else
tmp = SSP_CLK_POL_IDLE_LOW;
SSP_WRITE_BITS(chip->cr0, tmp, SSP_CR0_MASK_SPO, 6);
/** * pl022_cleanup - cleanup function registered to SPI host framework * @spi: spi device which is requesting cleanup * * This function is registered to the SPI framework for this SPI host * controller. It will free the runtime state of chip.
*/ staticvoid pl022_cleanup(struct spi_device *spi)
{ struct chip_data *chip = spi_get_ctldata(spi);
/* * Bus Number Which has been Assigned to this SSP controller * on this board
*/
host->bus_num = platform_info->bus_id;
host->cleanup = pl022_cleanup;
host->setup = pl022_setup;
host->auto_runtime_pm = true;
host->transfer_one = pl022_transfer_one;
host->set_cs = pl022_cs_control;
host->handle_err = pl022_handle_err;
host->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
host->rt = platform_info->rt;
host->dev.of_node = dev->of_node;
host->use_gpio_descriptors = true;
/* * Supports mode 0-3, loopback, and active low CS. Transfers are * always MS bit first on the original pl022.
*/
host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; if (pl022->vendor->extended_cr)
host->mode_bits |= SPI_LSB_FIRST;
status = amba_request_regions(adev, NULL); if (status) goto err_no_ioregion;
pl022->phybase = adev->res.start;
pl022->virtbase = devm_ioremap(dev, adev->res.start,
resource_size(&adev->res)); if (pl022->virtbase == NULL) {
status = -ENOMEM; goto err_no_ioremap;
}
dev_info(&adev->dev, "mapped registers from %pa to %p\n",
&adev->res.start, pl022->virtbase);
pl022->clk = devm_clk_get_enabled(&adev->dev, NULL); if (IS_ERR(pl022->clk)) {
status = PTR_ERR(pl022->clk);
dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n"); goto err_no_clk;
}
status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
0, "pl022", pl022); if (status < 0) {
dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status); goto err_no_irq;
}
/* Get DMA channels, try autoconfiguration first */
status = pl022_dma_autoprobe(pl022); if (status == -EPROBE_DEFER) {
dev_dbg(dev, "deferring probe to get DMA channel\n"); goto err_no_irq;
}
/* If that failed, use channels from platform_info */ if (status == 0)
platform_info->enable_dma = 1; elseif (platform_info->enable_dma) {
status = pl022_dma_probe(pl022); if (status != 0)
platform_info->enable_dma = 0;
}
/* Register with the SPI framework */
amba_set_drvdata(adev, pl022);
status = devm_spi_register_controller(&adev->dev, host); if (status != 0) {
dev_err_probe(&adev->dev, status, "problem registering spi host\n"); goto err_spi_register;
}
dev_dbg(dev, "probe succeeded\n");
/* let runtime pm put suspend */ if (platform_info->autosuspend_delay > 0) {
dev_info(&adev->dev, "will use autosuspend for runtime pm, delay %dms\n",
platform_info->autosuspend_delay);
pm_runtime_set_autosuspend_delay(dev,
platform_info->autosuspend_delay);
pm_runtime_use_autosuspend(dev);
}
pm_runtime_put(dev);
staticconststruct amba_id pl022_ids[] = {
{ /* * ARM PL022 variant, this has a 16bit wide * and 8 locations deep TX/RX FIFO
*/
.id = 0x00041022,
.mask = 0x000fffff,
.data = &vendor_arm,
},
{ /* * ST Micro derivative, this has 32bit wide * and 32 locations deep TX/RX FIFO
*/
.id = 0x01080022,
.mask = 0xffffffff,
.data = &vendor_st,
},
{ /* * ST-Ericsson derivative "PL023" (this is not * an official ARM number), this is a PL022 SSP block * stripped to SPI mode only, it has 32bit wide * and 32 locations deep TX/RX FIFO but no extended * CR0/CR1 register
*/
.id = 0x00080023,
.mask = 0xffffffff,
.data = &vendor_st_pl023,
},
{ /* * PL022 variant that has a chip select control register whih * allows control of 5 output signals nCS[0:4].
*/
.id = 0x000b6022,
.mask = 0x000fffff,
.data = &vendor_lsi,
},
{ 0, 0 },
};
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.