• Home
  • Raw
  • Download

Lines Matching +full:imx7ulp +full:- +full:spi

1 // SPDX-License-Identifier: GPL-2.0+
20 #include <linux/spi/spi.h>
21 #include <linux/spi/spi_bitbang.h>
97 { .compatible = "fsl,imx7ulp-spi", },
105 unsigned int val = readl(fsl_lpspi->base + IMX7ULP_RDR); \
107 if (fsl_lpspi->rx_buf) { \
108 *(type *)fsl_lpspi->rx_buf = val; \
109 fsl_lpspi->rx_buf += sizeof(type); \
118 if (fsl_lpspi->tx_buf) { \
119 val = *(type *)fsl_lpspi->tx_buf; \
120 fsl_lpspi->tx_buf += sizeof(type); \
123 fsl_lpspi->remain -= sizeof(type); \
124 writel(val, fsl_lpspi->base + IMX7ULP_TDR); \
137 writel(enable, fsl_lpspi->base + IMX7ULP_IER); in LPSPI_BUF_TX()
144 return clk_prepare_enable(fsl_lpspi->clk); in lpspi_prepare_xfer_hardware()
151 clk_disable_unprepare(fsl_lpspi->clk); in lpspi_unprepare_xfer_hardware()
162 txcnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff; in fsl_lpspi_txfifo_empty()
165 dev_dbg(fsl_lpspi->dev, "txfifo empty timeout\n"); in fsl_lpspi_txfifo_empty()
166 return -ETIMEDOUT; in fsl_lpspi_txfifo_empty()
179 txfifo_cnt = readl(fsl_lpspi->base + IMX7ULP_FSR) & 0xff; in fsl_lpspi_write_tx_fifo()
181 while (txfifo_cnt < fsl_lpspi->txfifosize) { in fsl_lpspi_write_tx_fifo()
182 if (!fsl_lpspi->remain) in fsl_lpspi_write_tx_fifo()
184 fsl_lpspi->tx(fsl_lpspi); in fsl_lpspi_write_tx_fifo()
188 if (!fsl_lpspi->remain && (txfifo_cnt < fsl_lpspi->txfifosize)) in fsl_lpspi_write_tx_fifo()
189 writel(0, fsl_lpspi->base + IMX7ULP_TDR); in fsl_lpspi_write_tx_fifo()
196 while (!(readl(fsl_lpspi->base + IMX7ULP_RSR) & RSR_RXEMPTY)) in fsl_lpspi_read_rx_fifo()
197 fsl_lpspi->rx(fsl_lpspi); in fsl_lpspi_read_rx_fifo()
205 temp |= fsl_lpspi->config.bpw - 1; in fsl_lpspi_set_cmd()
206 temp |= fsl_lpspi->config.prescale << 27; in fsl_lpspi_set_cmd()
207 temp |= (fsl_lpspi->config.mode & 0x3) << 30; in fsl_lpspi_set_cmd()
208 temp |= (fsl_lpspi->config.chip_select & 0x3) << 24; in fsl_lpspi_set_cmd()
221 writel(temp, fsl_lpspi->base + IMX7ULP_TCR); in fsl_lpspi_set_cmd()
223 dev_dbg(fsl_lpspi->dev, "TCR=0x%x\n", temp); in fsl_lpspi_set_cmd()
230 temp = fsl_lpspi->txfifosize >> 1 | (fsl_lpspi->rxfifosize >> 1) << 16; in fsl_lpspi_set_watermark()
232 writel(temp, fsl_lpspi->base + IMX7ULP_FCR); in fsl_lpspi_set_watermark()
234 dev_dbg(fsl_lpspi->dev, "FCR=0x%x\n", temp); in fsl_lpspi_set_watermark()
239 struct lpspi_config config = fsl_lpspi->config; in fsl_lpspi_set_bitrate()
243 perclk_rate = clk_get_rate(fsl_lpspi->clk); in fsl_lpspi_set_bitrate()
246 (clkdivs[prescale] * config.speed_hz) - 2; in fsl_lpspi_set_bitrate()
248 fsl_lpspi->config.prescale = prescale; in fsl_lpspi_set_bitrate()
254 return -EINVAL; in fsl_lpspi_set_bitrate()
256 writel(scldiv, fsl_lpspi->base + IMX7ULP_CCR); in fsl_lpspi_set_bitrate()
258 dev_dbg(fsl_lpspi->dev, "perclk=%d, speed=%d, prescale =%d, scldiv=%d\n", in fsl_lpspi_set_bitrate()
270 writel(temp, fsl_lpspi->base + IMX7ULP_CR); in fsl_lpspi_config()
271 writel(0, fsl_lpspi->base + IMX7ULP_CR); in fsl_lpspi_config()
280 if (fsl_lpspi->config.mode & SPI_CS_HIGH) in fsl_lpspi_config()
282 writel(temp, fsl_lpspi->base + IMX7ULP_CFGR1); in fsl_lpspi_config()
284 temp = readl(fsl_lpspi->base + IMX7ULP_CR); in fsl_lpspi_config()
286 writel(temp, fsl_lpspi->base + IMX7ULP_CR); in fsl_lpspi_config()
291 static void fsl_lpspi_setup_transfer(struct spi_device *spi, in fsl_lpspi_setup_transfer() argument
294 struct fsl_lpspi_data *fsl_lpspi = spi_master_get_devdata(spi->master); in fsl_lpspi_setup_transfer()
296 fsl_lpspi->config.mode = spi->mode; in fsl_lpspi_setup_transfer()
297 fsl_lpspi->config.bpw = t ? t->bits_per_word : spi->bits_per_word; in fsl_lpspi_setup_transfer()
298 fsl_lpspi->config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; in fsl_lpspi_setup_transfer()
299 fsl_lpspi->config.chip_select = spi->chip_select; in fsl_lpspi_setup_transfer()
301 if (!fsl_lpspi->config.speed_hz) in fsl_lpspi_setup_transfer()
302 fsl_lpspi->config.speed_hz = spi->max_speed_hz; in fsl_lpspi_setup_transfer()
303 if (!fsl_lpspi->config.bpw) in fsl_lpspi_setup_transfer()
304 fsl_lpspi->config.bpw = spi->bits_per_word; in fsl_lpspi_setup_transfer()
307 if (fsl_lpspi->config.bpw <= 8) { in fsl_lpspi_setup_transfer()
308 fsl_lpspi->rx = fsl_lpspi_buf_rx_u8; in fsl_lpspi_setup_transfer()
309 fsl_lpspi->tx = fsl_lpspi_buf_tx_u8; in fsl_lpspi_setup_transfer()
310 } else if (fsl_lpspi->config.bpw <= 16) { in fsl_lpspi_setup_transfer()
311 fsl_lpspi->rx = fsl_lpspi_buf_rx_u16; in fsl_lpspi_setup_transfer()
312 fsl_lpspi->tx = fsl_lpspi_buf_tx_u16; in fsl_lpspi_setup_transfer()
314 fsl_lpspi->rx = fsl_lpspi_buf_rx_u32; in fsl_lpspi_setup_transfer()
315 fsl_lpspi->tx = fsl_lpspi_buf_tx_u32; in fsl_lpspi_setup_transfer()
322 struct spi_device *spi, in fsl_lpspi_transfer_one() argument
328 fsl_lpspi->tx_buf = t->tx_buf; in fsl_lpspi_transfer_one()
329 fsl_lpspi->rx_buf = t->rx_buf; in fsl_lpspi_transfer_one()
330 fsl_lpspi->remain = t->len; in fsl_lpspi_transfer_one()
332 reinit_completion(&fsl_lpspi->xfer_done); in fsl_lpspi_transfer_one()
335 ret = wait_for_completion_timeout(&fsl_lpspi->xfer_done, HZ); in fsl_lpspi_transfer_one()
337 dev_dbg(fsl_lpspi->dev, "wait for completion timeout\n"); in fsl_lpspi_transfer_one()
338 return -ETIMEDOUT; in fsl_lpspi_transfer_one()
354 struct spi_device *spi = msg->spi; in fsl_lpspi_transfer_one_msg() local
360 msg->status = 0; in fsl_lpspi_transfer_one_msg()
361 msg->actual_length = 0; in fsl_lpspi_transfer_one_msg()
363 list_for_each_entry(xfer, &msg->transfers, transfer_list) { in fsl_lpspi_transfer_one_msg()
364 fsl_lpspi_setup_transfer(spi, xfer); in fsl_lpspi_transfer_one_msg()
369 ret = fsl_lpspi_transfer_one(master, spi, xfer); in fsl_lpspi_transfer_one_msg()
373 msg->actual_length += xfer->len; in fsl_lpspi_transfer_one_msg()
377 /* de-assert SS, then finalize current message */ in fsl_lpspi_transfer_one_msg()
378 temp = readl(fsl_lpspi->base + IMX7ULP_TCR); in fsl_lpspi_transfer_one_msg()
380 writel(temp, fsl_lpspi->base + IMX7ULP_TCR); in fsl_lpspi_transfer_one_msg()
382 msg->status = ret; in fsl_lpspi_transfer_one_msg()
394 temp = readl(fsl_lpspi->base + IMX7ULP_SR); in fsl_lpspi_isr()
401 if (!fsl_lpspi->remain) in fsl_lpspi_isr()
402 complete(&fsl_lpspi->xfer_done); in fsl_lpspi_isr()
418 master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_lpspi_data)); in fsl_lpspi_probe()
420 return -ENOMEM; in fsl_lpspi_probe()
424 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); in fsl_lpspi_probe()
425 master->bus_num = pdev->id; in fsl_lpspi_probe()
428 fsl_lpspi->dev = &pdev->dev; in fsl_lpspi_probe()
430 master->transfer_one_message = fsl_lpspi_transfer_one_msg; in fsl_lpspi_probe()
431 master->prepare_transfer_hardware = lpspi_prepare_xfer_hardware; in fsl_lpspi_probe()
432 master->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware; in fsl_lpspi_probe()
433 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; in fsl_lpspi_probe()
434 master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; in fsl_lpspi_probe()
435 master->dev.of_node = pdev->dev.of_node; in fsl_lpspi_probe()
436 master->bus_num = pdev->id; in fsl_lpspi_probe()
438 init_completion(&fsl_lpspi->xfer_done); in fsl_lpspi_probe()
441 fsl_lpspi->base = devm_ioremap_resource(&pdev->dev, res); in fsl_lpspi_probe()
442 if (IS_ERR(fsl_lpspi->base)) { in fsl_lpspi_probe()
443 ret = PTR_ERR(fsl_lpspi->base); in fsl_lpspi_probe()
453 ret = devm_request_irq(&pdev->dev, irq, fsl_lpspi_isr, 0, in fsl_lpspi_probe()
454 dev_name(&pdev->dev), fsl_lpspi); in fsl_lpspi_probe()
456 dev_err(&pdev->dev, "can't get irq%d: %d\n", irq, ret); in fsl_lpspi_probe()
460 fsl_lpspi->clk = devm_clk_get(&pdev->dev, "ipg"); in fsl_lpspi_probe()
461 if (IS_ERR(fsl_lpspi->clk)) { in fsl_lpspi_probe()
462 ret = PTR_ERR(fsl_lpspi->clk); in fsl_lpspi_probe()
466 ret = clk_prepare_enable(fsl_lpspi->clk); in fsl_lpspi_probe()
468 dev_err(&pdev->dev, "can't enable lpspi clock, ret=%d\n", ret); in fsl_lpspi_probe()
472 temp = readl(fsl_lpspi->base + IMX7ULP_PARAM); in fsl_lpspi_probe()
473 fsl_lpspi->txfifosize = 1 << (temp & 0x0f); in fsl_lpspi_probe()
474 fsl_lpspi->rxfifosize = 1 << ((temp >> 8) & 0x0f); in fsl_lpspi_probe()
476 clk_disable_unprepare(fsl_lpspi->clk); in fsl_lpspi_probe()
478 ret = devm_spi_register_master(&pdev->dev, master); in fsl_lpspi_probe()
480 dev_err(&pdev->dev, "spi_register_master error.\n"); in fsl_lpspi_probe()
497 clk_disable_unprepare(fsl_lpspi->clk); in fsl_lpspi_remove()