Lines Matching +full:rx +full:- +full:fifo +full:- +full:size
1 // SPDX-License-Identifier: GPL-2.0-or-later
7 * Hongjun Chen <hong-jun.chen@freescale.com>
39 switch (mps->type) { \
41 struct mpc52xx_psc __iomem *psc = mps->psc; \
42 __ret = &psc->regname; \
46 struct mpc5125_psc __iomem *psc = mps->psc; \
47 __ret = &psc->regname; \
59 struct mpc512x_psc_fifo __iomem *fifo; member
81 struct mpc512x_psc_spi_cs *cs = spi->controller_state; in mpc512x_psc_spi_transfer_setup()
83 cs->speed_hz = (t && t->speed_hz) in mpc512x_psc_spi_transfer_setup()
84 ? t->speed_hz : spi->max_speed_hz; in mpc512x_psc_spi_transfer_setup()
85 cs->bits_per_word = (t && t->bits_per_word) in mpc512x_psc_spi_transfer_setup()
86 ? t->bits_per_word : spi->bits_per_word; in mpc512x_psc_spi_transfer_setup()
87 cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8; in mpc512x_psc_spi_transfer_setup()
93 struct mpc512x_psc_spi_cs *cs = spi->controller_state; in mpc512x_psc_spi_activate_cs()
94 struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); in mpc512x_psc_spi_activate_cs()
103 if (spi->mode & SPI_CPHA) in mpc512x_psc_spi_activate_cs()
108 if (spi->mode & SPI_CPOL) in mpc512x_psc_spi_activate_cs()
113 if (spi->mode & SPI_LSB_FIRST) in mpc512x_psc_spi_activate_cs()
121 speed = cs->speed_hz; in mpc512x_psc_spi_activate_cs()
124 bclkdiv = (mps->mclk_rate / speed) - 1; in mpc512x_psc_spi_activate_cs()
128 mps->bits_per_word = cs->bits_per_word; in mpc512x_psc_spi_activate_cs()
130 if (spi->cs_gpiod) { in mpc512x_psc_spi_activate_cs()
131 if (mps->cs_control) in mpc512x_psc_spi_activate_cs()
133 mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0); in mpc512x_psc_spi_activate_cs()
136 gpiod_set_value(spi->cs_gpiod, 1); in mpc512x_psc_spi_activate_cs()
142 struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); in mpc512x_psc_spi_deactivate_cs()
144 if (spi->cs_gpiod) { in mpc512x_psc_spi_deactivate_cs()
145 if (mps->cs_control) in mpc512x_psc_spi_deactivate_cs()
147 mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1); in mpc512x_psc_spi_deactivate_cs()
150 gpiod_set_value(spi->cs_gpiod, 0); in mpc512x_psc_spi_deactivate_cs()
154 /* extract and scale size field in txsz or rxsz */
162 struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); in mpc512x_psc_spi_transfer_rxtx()
163 struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; in mpc512x_psc_spi_transfer_rxtx() local
164 size_t tx_len = t->len; in mpc512x_psc_spi_transfer_rxtx()
165 size_t rx_len = t->len; in mpc512x_psc_spi_transfer_rxtx()
166 u8 *tx_buf = (u8 *)t->tx_buf; in mpc512x_psc_spi_transfer_rxtx()
167 u8 *rx_buf = (u8 *)t->rx_buf; in mpc512x_psc_spi_transfer_rxtx()
169 if (!tx_buf && !rx_buf && t->len) in mpc512x_psc_spi_transfer_rxtx()
170 return -EINVAL; in mpc512x_psc_spi_transfer_rxtx()
181 * but neither exceed the TX nor the RX FIFOs in mpc512x_psc_spi_transfer_rxtx()
183 fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz)); in mpc512x_psc_spi_transfer_rxtx()
185 fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->rxsz)); in mpc512x_psc_spi_transfer_rxtx()
186 fifosz -= in_be32(&fifo->rxcnt) + 1; in mpc512x_psc_spi_transfer_rxtx()
190 /* fill the TX FIFO */ in mpc512x_psc_spi_transfer_rxtx()
191 while (txcount-- > 0) { in mpc512x_psc_spi_transfer_rxtx()
193 if (tx_len == EOFBYTE && t->cs_change) in mpc512x_psc_spi_transfer_rxtx()
194 setbits32(&fifo->txcmd, in mpc512x_psc_spi_transfer_rxtx()
196 out_8(&fifo->txdata_8, data); in mpc512x_psc_spi_transfer_rxtx()
197 tx_len--; in mpc512x_psc_spi_transfer_rxtx()
200 /* have the ISR trigger when the TX FIFO is empty */ in mpc512x_psc_spi_transfer_rxtx()
201 reinit_completion(&mps->txisrdone); in mpc512x_psc_spi_transfer_rxtx()
202 out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); in mpc512x_psc_spi_transfer_rxtx()
203 out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY); in mpc512x_psc_spi_transfer_rxtx()
204 wait_for_completion(&mps->txisrdone); in mpc512x_psc_spi_transfer_rxtx()
208 * consume as much RX data as the FIFO holds, while we in mpc512x_psc_spi_transfer_rxtx()
211 * only insist in draining all the remaining RX bytes in mpc512x_psc_spi_transfer_rxtx()
220 * grab whatever was in the FIFO when we started in mpc512x_psc_spi_transfer_rxtx()
222 * the FIFO while we read from it -- we'll return in mpc512x_psc_spi_transfer_rxtx()
226 fifosz = in_be32(&fifo->rxcnt); in mpc512x_psc_spi_transfer_rxtx()
228 while (rxcount-- > 0) { in mpc512x_psc_spi_transfer_rxtx()
229 data = in_8(&fifo->rxdata_8); in mpc512x_psc_spi_transfer_rxtx()
232 rx_len--; in mpc512x_psc_spi_transfer_rxtx()
237 * bail out of the RX drain loop if all of the TX data in mpc512x_psc_spi_transfer_rxtx()
238 * was sent and all of the RX data was received (i.e. in mpc512x_psc_spi_transfer_rxtx()
247 * TX data transmission has completed while RX data in mpc512x_psc_spi_transfer_rxtx()
248 * is still pending -- that's a transient situation in mpc512x_psc_spi_transfer_rxtx()
262 * ticks in the system _and_ RX data still wasn't in mpc512x_psc_spi_transfer_rxtx()
273 } while (--rxtries > 0); in mpc512x_psc_spi_transfer_rxtx()
276 * not enough RX bytes even after several retries in mpc512x_psc_spi_transfer_rxtx()
279 rxcount = in_be32(&fifo->rxcnt); in mpc512x_psc_spi_transfer_rxtx()
280 dev_warn(&spi->dev, in mpc512x_psc_spi_transfer_rxtx()
281 "short xfer, missing %zd RX bytes, FIFO level %zd\n", in mpc512x_psc_spi_transfer_rxtx()
286 * drain and drop RX data which "should not be there" in in mpc512x_psc_spi_transfer_rxtx()
288 * into a NOP (except for the FIFO level fetch) in mpc512x_psc_spi_transfer_rxtx()
291 while (in_be32(&fifo->rxcnt)) in mpc512x_psc_spi_transfer_rxtx()
292 in_8(&fifo->rxdata_8); in mpc512x_psc_spi_transfer_rxtx()
307 spi = m->spi; in mpc512x_psc_spi_msg_xfer()
310 list_for_each_entry(t, &m->transfers, transfer_list) { in mpc512x_psc_spi_msg_xfer()
317 cs_change = t->cs_change; in mpc512x_psc_spi_msg_xfer()
322 m->actual_length += t->len; in mpc512x_psc_spi_msg_xfer()
330 m->status = status; in mpc512x_psc_spi_msg_xfer()
331 if (m->complete) in mpc512x_psc_spi_msg_xfer()
332 m->complete(m->context); in mpc512x_psc_spi_msg_xfer()
347 dev_dbg(&master->dev, "%s()\n", __func__); in mpc512x_psc_spi_prep_xfer_hw()
362 struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; in mpc512x_psc_spi_unprep_xfer_hw() local
364 dev_dbg(&master->dev, "%s()\n", __func__); in mpc512x_psc_spi_unprep_xfer_hw()
366 /* disable transmitter/receiver and fifo interrupt */ in mpc512x_psc_spi_unprep_xfer_hw()
368 out_be32(&fifo->tximr, 0); in mpc512x_psc_spi_unprep_xfer_hw()
375 struct mpc512x_psc_spi_cs *cs = spi->controller_state; in mpc512x_psc_spi_setup()
377 if (spi->bits_per_word % 8) in mpc512x_psc_spi_setup()
378 return -EINVAL; in mpc512x_psc_spi_setup()
383 return -ENOMEM; in mpc512x_psc_spi_setup()
385 spi->controller_state = cs; in mpc512x_psc_spi_setup()
388 cs->bits_per_word = spi->bits_per_word; in mpc512x_psc_spi_setup()
389 cs->speed_hz = spi->max_speed_hz; in mpc512x_psc_spi_setup()
396 kfree(spi->controller_state); in mpc512x_psc_spi_cleanup()
402 struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; in mpc512x_psc_spi_port_config() local
413 /* Disable psc interrupts all useful interrupts are in fifo */ in mpc512x_psc_spi_port_config()
416 /* Disable fifo interrupts, will be enabled later */ in mpc512x_psc_spi_port_config()
417 out_be32(&fifo->tximr, 0); in mpc512x_psc_spi_port_config()
418 out_be32(&fifo->rximr, 0); in mpc512x_psc_spi_port_config()
420 /* Setup fifo slice address and size */ in mpc512x_psc_spi_port_config()
421 /*out_be32(&fifo->txsz, 0x0fe00004);*/ in mpc512x_psc_spi_port_config()
422 /*out_be32(&fifo->rxsz, 0x0ff00004);*/ in mpc512x_psc_spi_port_config()
424 sicr = 0x01000000 | /* SIM = 0001 -- 8 bit */ in mpc512x_psc_spi_port_config()
425 0x00800000 | /* GenClk = 1 -- internal clk */ in mpc512x_psc_spi_port_config()
427 0x00004000 | /* MSTR = 1 -- SPI master */ in mpc512x_psc_spi_port_config()
428 0x00000800; /* UseEOF = 1 -- SS low until EOF */ in mpc512x_psc_spi_port_config()
435 bclkdiv = (mps->mclk_rate / speed) - 1; in mpc512x_psc_spi_port_config()
444 out_be32(&fifo->rxalarm, 0xfff); in mpc512x_psc_spi_port_config()
445 out_be32(&fifo->txalarm, 0); in mpc512x_psc_spi_port_config()
447 /* Enable FIFO slices for Rx/Tx */ in mpc512x_psc_spi_port_config()
448 out_be32(&fifo->rxcmd, in mpc512x_psc_spi_port_config()
450 out_be32(&fifo->txcmd, in mpc512x_psc_spi_port_config()
453 mps->bits_per_word = 8; in mpc512x_psc_spi_port_config()
461 struct mpc512x_psc_fifo __iomem *fifo = mps->fifo; in mpc512x_psc_spi_isr() local
463 /* clear interrupt and wake up the rx/tx routine */ in mpc512x_psc_spi_isr()
464 if (in_be32(&fifo->txisr) & in mpc512x_psc_spi_isr()
465 in_be32(&fifo->tximr) & MPC512x_PSC_FIFO_EMPTY) { in mpc512x_psc_spi_isr()
466 out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY); in mpc512x_psc_spi_isr()
467 out_be32(&fifo->tximr, 0); in mpc512x_psc_spi_isr()
468 complete(&mps->txisrdone); in mpc512x_psc_spi_isr()
475 u32 size, unsigned int irq) in mpc512x_psc_spi_do_probe() argument
486 return -ENOMEM; in mpc512x_psc_spi_do_probe()
490 mps->type = (int)of_device_get_match_data(dev); in mpc512x_psc_spi_do_probe()
491 mps->irq = irq; in mpc512x_psc_spi_do_probe()
494 mps->cs_control = pdata->cs_control; in mpc512x_psc_spi_do_probe()
495 master->bus_num = pdata->bus_num; in mpc512x_psc_spi_do_probe()
496 master->num_chipselect = pdata->max_chipselect; in mpc512x_psc_spi_do_probe()
499 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; in mpc512x_psc_spi_do_probe()
500 master->setup = mpc512x_psc_spi_setup; in mpc512x_psc_spi_do_probe()
501 master->prepare_transfer_hardware = mpc512x_psc_spi_prep_xfer_hw; in mpc512x_psc_spi_do_probe()
502 master->transfer_one_message = mpc512x_psc_spi_msg_xfer; in mpc512x_psc_spi_do_probe()
503 master->unprepare_transfer_hardware = mpc512x_psc_spi_unprep_xfer_hw; in mpc512x_psc_spi_do_probe()
504 master->use_gpio_descriptors = true; in mpc512x_psc_spi_do_probe()
505 master->cleanup = mpc512x_psc_spi_cleanup; in mpc512x_psc_spi_do_probe()
506 master->dev.of_node = dev->of_node; in mpc512x_psc_spi_do_probe()
508 tempp = devm_ioremap(dev, regaddr, size); in mpc512x_psc_spi_do_probe()
511 ret = -EFAULT; in mpc512x_psc_spi_do_probe()
514 mps->psc = tempp; in mpc512x_psc_spi_do_probe()
515 mps->fifo = in mpc512x_psc_spi_do_probe()
517 ret = devm_request_irq(dev, mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED, in mpc512x_psc_spi_do_probe()
518 "mpc512x-psc-spi", mps); in mpc512x_psc_spi_do_probe()
521 init_completion(&mps->txisrdone); in mpc512x_psc_spi_do_probe()
531 mps->clk_mclk = clk; in mpc512x_psc_spi_do_probe()
532 mps->mclk_rate = clk_get_rate(clk); in mpc512x_psc_spi_do_probe()
542 mps->clk_ipg = clk; in mpc512x_psc_spi_do_probe()
555 clk_disable_unprepare(mps->clk_ipg); in mpc512x_psc_spi_do_probe()
557 clk_disable_unprepare(mps->clk_mclk); in mpc512x_psc_spi_do_probe()
569 clk_disable_unprepare(mps->clk_mclk); in mpc512x_psc_spi_do_remove()
570 clk_disable_unprepare(mps->clk_ipg); in mpc512x_psc_spi_do_remove()
580 regaddr_p = of_get_address(op->dev.of_node, 0, &size64, NULL); in mpc512x_psc_spi_of_probe()
582 dev_err(&op->dev, "Invalid PSC address\n"); in mpc512x_psc_spi_of_probe()
583 return -EINVAL; in mpc512x_psc_spi_of_probe()
585 regaddr64 = of_translate_address(op->dev.of_node, regaddr_p); in mpc512x_psc_spi_of_probe()
587 return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64, in mpc512x_psc_spi_of_probe()
588 irq_of_parse_and_map(op->dev.of_node, 0)); in mpc512x_psc_spi_of_probe()
593 return mpc512x_psc_spi_do_remove(&op->dev); in mpc512x_psc_spi_of_remove()
597 { .compatible = "fsl,mpc5121-psc-spi", .data = (void *)TYPE_MPC5121 },
598 { .compatible = "fsl,mpc5125-psc-spi", .data = (void *)TYPE_MPC5125 },
608 .name = "mpc512x-psc-spi",