Lines Matching +full:spi +full:- +full:slave

2  * Freescale i.MX28 SPI driver
7 * SPDX-License-Identifier: GPL-2.0+
9 * NOTE: This driver only supports the SPI-controller chipselects,
16 #include <spi.h>
20 #include <asm/arch/imx-regs.h>
22 #include <asm/mach-imx/dma.h>
32 struct spi_slave slave; member
38 static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave) in to_mxs_slave() argument
40 return container_of(slave, struct mxs_spi_slave, slave); in to_mxs_slave()
49 /* MXS SPI: 4 ports and 3 chip selects maximum */ in spi_cs_is_valid()
73 mxs_slave->max_khz = max_hz / 1000; in spi_setup_slave()
74 mxs_slave->mode = mode; in spi_setup_slave()
75 mxs_slave->regs = mxs_ssp_regs_by_bus(bus); in spi_setup_slave()
77 return &mxs_slave->slave; in spi_setup_slave()
84 void spi_free_slave(struct spi_slave *slave) in spi_free_slave() argument
86 struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave); in spi_free_slave()
90 int spi_claim_bus(struct spi_slave *slave) in spi_claim_bus() argument
92 struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave); in spi_claim_bus()
93 struct mxs_ssp_regs *ssp_regs = mxs_slave->regs; in spi_claim_bus()
96 mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg); in spi_claim_bus()
98 writel((slave->cs << MXS_SSP_CHIPSELECT_SHIFT) | in spi_claim_bus()
100 &ssp_regs->hw_ssp_ctrl0); in spi_claim_bus()
103 reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0; in spi_claim_bus()
104 reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0; in spi_claim_bus()
105 writel(reg, &ssp_regs->hw_ssp_ctrl1); in spi_claim_bus()
107 writel(0, &ssp_regs->hw_ssp_cmd0); in spi_claim_bus()
109 mxs_set_ssp_busclock(slave->bus, mxs_slave->max_khz); in spi_claim_bus()
114 void spi_release_bus(struct spi_slave *slave) in spi_release_bus() argument
120 writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set); in mxs_spi_start_xfer()
121 writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_clr); in mxs_spi_start_xfer()
126 writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_clr); in mxs_spi_end_xfer()
127 writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set); in mxs_spi_end_xfer()
130 static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave, in mxs_spi_xfer_pio() argument
133 struct mxs_ssp_regs *ssp_regs = slave->regs; in mxs_spi_xfer_pio()
138 while (length--) { in mxs_spi_xfer_pio()
141 writel(SSP_CTRL0_XFER_COUNT_MASK, &ssp_regs->hw_ssp_ctrl0_clr); in mxs_spi_xfer_pio()
142 writel(1, &ssp_regs->hw_ssp_ctrl0_set); in mxs_spi_xfer_pio()
144 writel(1, &ssp_regs->hw_ssp_xfer_size); in mxs_spi_xfer_pio()
151 writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_clr); in mxs_spi_xfer_pio()
153 writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_set); in mxs_spi_xfer_pio()
155 writel(SSP_CTRL0_RUN, &ssp_regs->hw_ssp_ctrl0_set); in mxs_spi_xfer_pio()
157 if (mxs_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg, in mxs_spi_xfer_pio()
159 printf("MXS SPI: Timeout waiting for start\n"); in mxs_spi_xfer_pio()
160 return -ETIMEDOUT; in mxs_spi_xfer_pio()
164 writel(*data++, &ssp_regs->hw_ssp_data); in mxs_spi_xfer_pio()
166 writel(SSP_CTRL0_DATA_XFER, &ssp_regs->hw_ssp_ctrl0_set); in mxs_spi_xfer_pio()
169 if (mxs_wait_mask_clr(&ssp_regs->hw_ssp_status_reg, in mxs_spi_xfer_pio()
171 printf("MXS SPI: Timeout waiting for data\n"); in mxs_spi_xfer_pio()
172 return -ETIMEDOUT; in mxs_spi_xfer_pio()
175 *data = readl(&ssp_regs->hw_ssp_data); in mxs_spi_xfer_pio()
179 if (mxs_wait_mask_clr(&ssp_regs->hw_ssp_ctrl0_reg, in mxs_spi_xfer_pio()
181 printf("MXS SPI: Timeout waiting for finish\n"); in mxs_spi_xfer_pio()
182 return -ETIMEDOUT; in mxs_spi_xfer_pio()
189 static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave, in mxs_spi_xfer_dma() argument
194 struct mxs_ssp_regs *ssp_regs = slave->regs; in mxs_spi_xfer_dma()
213 ctrl0 = readl(&ssp_regs->hw_ssp_ctrl0); in mxs_spi_xfer_dma()
233 dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + slave->slave.bus; in mxs_spi_xfer_dma()
237 dp->address = (dma_addr_t)dp; in mxs_spi_xfer_dma()
238 dp->cmd.address = (dma_addr_t)data; in mxs_spi_xfer_dma()
244 * and employed ;-) in mxs_spi_xfer_dma()
247 dp->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ; in mxs_spi_xfer_dma()
249 dp->cmd.data = MXS_DMA_DESC_COMMAND_DMA_WRITE; in mxs_spi_xfer_dma()
262 dp->cmd.data |= in mxs_spi_xfer_dma()
269 length -= tl; in mxs_spi_xfer_dma()
272 dp->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM; in mxs_spi_xfer_dma()
285 * a per-descriptor basis with the same size as is the in mxs_spi_xfer_dma()
288 dp->cmd.pio_words[0] = ctrl0; in mxs_spi_xfer_dma()
290 dp->cmd.pio_words[1] = 0; in mxs_spi_xfer_dma()
291 dp->cmd.pio_words[2] = 0; in mxs_spi_xfer_dma()
292 dp->cmd.pio_words[3] = tl; in mxs_spi_xfer_dma()
301 ret = -EINVAL; in mxs_spi_xfer_dma()
310 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, in spi_xfer() argument
313 struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave); in spi_xfer()
314 struct mxs_ssp_regs *ssp_regs = mxs_slave->regs; in spi_xfer()
329 /* Half-duplex only */ in spi_xfer()
331 return -EINVAL; in spi_xfer()
350 if (((uint32_t)data) & (ARCH_DMA_MINALIGN - 1)) in spi_xfer()
352 if (((uint32_t)len) & (ARCH_DMA_MINALIGN - 1)) in spi_xfer()
357 writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr); in spi_xfer()
360 writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set); in spi_xfer()