Lines Matching +full:uniphier +full:- +full:scssi
1 // SPDX-License-Identifier: GPL-2.0
2 // spi-uniphier.c - Socionext UniPhier SPI controller driver
4 // Copyright 2016-2018 Socionext Inc.
96 struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master); in uniphier_spi_irq_enable()
99 val = readl(priv->base + SSI_IE); in uniphier_spi_irq_enable()
101 writel(val, priv->base + SSI_IE); in uniphier_spi_irq_enable()
106 struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master); in uniphier_spi_irq_disable()
109 val = readl(priv->base + SSI_IE); in uniphier_spi_irq_disable()
111 writel(val, priv->base + SSI_IE); in uniphier_spi_irq_disable()
116 struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master); in uniphier_spi_set_mode()
131 switch (spi->mode & (SPI_CPOL | SPI_CPHA)) { in uniphier_spi_set_mode()
154 if (!(spi->mode & SPI_CS_HIGH)) in uniphier_spi_set_mode()
157 writel(val1, priv->base + SSI_CKS); in uniphier_spi_set_mode()
158 writel(val2, priv->base + SSI_FPS); in uniphier_spi_set_mode()
161 if (spi->mode & SPI_LSB_FIRST) in uniphier_spi_set_mode()
163 writel(val1, priv->base + SSI_TXWDS); in uniphier_spi_set_mode()
164 writel(val1, priv->base + SSI_RXWDS); in uniphier_spi_set_mode()
169 struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master); in uniphier_spi_set_transfer_size()
172 val = readl(priv->base + SSI_TXWDS); in uniphier_spi_set_transfer_size()
176 writel(val, priv->base + SSI_TXWDS); in uniphier_spi_set_transfer_size()
178 val = readl(priv->base + SSI_RXWDS); in uniphier_spi_set_transfer_size()
181 writel(val, priv->base + SSI_RXWDS); in uniphier_spi_set_transfer_size()
187 struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master); in uniphier_spi_set_baudrate()
194 ckdiv = DIV_ROUND_UP(clk_get_rate(priv->clk), speed); in uniphier_spi_set_baudrate()
197 val = readl(priv->base + SSI_CKS); in uniphier_spi_set_baudrate()
200 writel(val, priv->base + SSI_CKS); in uniphier_spi_set_baudrate()
206 struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master); in uniphier_spi_setup_transfer()
209 priv->error = 0; in uniphier_spi_setup_transfer()
210 priv->tx_buf = t->tx_buf; in uniphier_spi_setup_transfer()
211 priv->rx_buf = t->rx_buf; in uniphier_spi_setup_transfer()
212 priv->tx_bytes = priv->rx_bytes = t->len; in uniphier_spi_setup_transfer()
214 if (!priv->is_save_param || priv->mode != spi->mode) { in uniphier_spi_setup_transfer()
216 priv->mode = spi->mode; in uniphier_spi_setup_transfer()
219 if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) { in uniphier_spi_setup_transfer()
220 uniphier_spi_set_transfer_size(spi, t->bits_per_word); in uniphier_spi_setup_transfer()
221 priv->bits_per_word = t->bits_per_word; in uniphier_spi_setup_transfer()
224 if (!priv->is_save_param || priv->speed_hz != t->speed_hz) { in uniphier_spi_setup_transfer()
225 uniphier_spi_set_baudrate(spi, t->speed_hz); in uniphier_spi_setup_transfer()
226 priv->speed_hz = t->speed_hz; in uniphier_spi_setup_transfer()
229 if (!priv->is_save_param) in uniphier_spi_setup_transfer()
230 priv->is_save_param = true; in uniphier_spi_setup_transfer()
234 writel(val, priv->base + SSI_FC); in uniphier_spi_setup_transfer()
242 wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes); in uniphier_spi_send()
243 priv->tx_bytes -= wsize; in uniphier_spi_send()
245 if (priv->tx_buf) { in uniphier_spi_send()
248 val = *priv->tx_buf; in uniphier_spi_send()
251 val = get_unaligned_le16(priv->tx_buf); in uniphier_spi_send()
254 val = get_unaligned_le32(priv->tx_buf); in uniphier_spi_send()
258 priv->tx_buf += wsize; in uniphier_spi_send()
261 writel(val, priv->base + SSI_TXDR); in uniphier_spi_send()
269 rsize = min(bytes_per_word(priv->bits_per_word), priv->rx_bytes); in uniphier_spi_recv()
270 priv->rx_bytes -= rsize; in uniphier_spi_recv()
272 val = readl(priv->base + SSI_RXDR); in uniphier_spi_recv()
274 if (priv->rx_buf) { in uniphier_spi_recv()
277 *priv->rx_buf = val; in uniphier_spi_recv()
280 put_unaligned_le16(val, priv->rx_buf); in uniphier_spi_recv()
283 put_unaligned_le32(val, priv->rx_buf); in uniphier_spi_recv()
287 priv->rx_buf += rsize; in uniphier_spi_recv()
296 tx_count = DIV_ROUND_UP(priv->tx_bytes, in uniphier_spi_fill_tx_fifo()
297 bytes_per_word(priv->bits_per_word)); in uniphier_spi_fill_tx_fifo()
301 val = readl(priv->base + SSI_FC); in uniphier_spi_fill_tx_fifo()
305 writel(val, priv->base + SSI_FC); in uniphier_spi_fill_tx_fifo()
307 while (tx_count--) in uniphier_spi_fill_tx_fifo()
313 struct uniphier_spi_priv *priv = spi_master_get_devdata(spi->master); in uniphier_spi_set_cs()
316 val = readl(priv->base + SSI_FPS); in uniphier_spi_set_cs()
323 writel(val, priv->base + SSI_FPS); in uniphier_spi_set_cs()
335 reinit_completion(&priv->xfer_done); in uniphier_spi_transfer_one()
341 status = wait_for_completion_timeout(&priv->xfer_done, in uniphier_spi_transfer_one()
349 return priv->error; in uniphier_spi_transfer_one()
356 writel(SSI_CTL_EN, priv->base + SSI_CTL); in uniphier_spi_prepare_transfer_hardware()
365 writel(0, priv->base + SSI_CTL); in uniphier_spi_unprepare_transfer_hardware()
375 stat = readl(priv->base + SSI_IS); in uniphier_spi_handler()
377 writel(val, priv->base + SSI_IC); in uniphier_spi_handler()
381 priv->error = -EIO; in uniphier_spi_handler()
387 while ((readl(priv->base + SSI_SR) & SSI_SR_RNE) && in uniphier_spi_handler()
388 (priv->rx_bytes - priv->tx_bytes) > 0) in uniphier_spi_handler()
391 if ((readl(priv->base + SSI_SR) & SSI_SR_RNE) || in uniphier_spi_handler()
392 (priv->rx_bytes != priv->tx_bytes)) { in uniphier_spi_handler()
393 priv->error = -EIO; in uniphier_spi_handler()
395 } else if (priv->rx_bytes == 0) in uniphier_spi_handler()
407 complete(&priv->xfer_done); in uniphier_spi_handler()
420 master = spi_alloc_master(&pdev->dev, sizeof(*priv)); in uniphier_spi_probe()
422 return -ENOMEM; in uniphier_spi_probe()
427 priv->master = master; in uniphier_spi_probe()
428 priv->is_save_param = false; in uniphier_spi_probe()
431 priv->base = devm_ioremap_resource(&pdev->dev, res); in uniphier_spi_probe()
432 if (IS_ERR(priv->base)) { in uniphier_spi_probe()
433 ret = PTR_ERR(priv->base); in uniphier_spi_probe()
437 priv->clk = devm_clk_get(&pdev->dev, NULL); in uniphier_spi_probe()
438 if (IS_ERR(priv->clk)) { in uniphier_spi_probe()
439 dev_err(&pdev->dev, "failed to get clock\n"); in uniphier_spi_probe()
440 ret = PTR_ERR(priv->clk); in uniphier_spi_probe()
444 ret = clk_prepare_enable(priv->clk); in uniphier_spi_probe()
450 dev_err(&pdev->dev, "failed to get IRQ\n"); in uniphier_spi_probe()
455 ret = devm_request_irq(&pdev->dev, irq, uniphier_spi_handler, in uniphier_spi_probe()
456 0, "uniphier-spi", priv); in uniphier_spi_probe()
458 dev_err(&pdev->dev, "failed to request IRQ\n"); in uniphier_spi_probe()
462 init_completion(&priv->xfer_done); in uniphier_spi_probe()
464 clk_rate = clk_get_rate(priv->clk); in uniphier_spi_probe()
466 master->max_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MIN_CLK_DIVIDER); in uniphier_spi_probe()
467 master->min_speed_hz = DIV_ROUND_UP(clk_rate, SSI_MAX_CLK_DIVIDER); in uniphier_spi_probe()
468 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; in uniphier_spi_probe()
469 master->dev.of_node = pdev->dev.of_node; in uniphier_spi_probe()
470 master->bus_num = pdev->id; in uniphier_spi_probe()
471 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); in uniphier_spi_probe()
473 master->set_cs = uniphier_spi_set_cs; in uniphier_spi_probe()
474 master->transfer_one = uniphier_spi_transfer_one; in uniphier_spi_probe()
475 master->prepare_transfer_hardware in uniphier_spi_probe()
477 master->unprepare_transfer_hardware in uniphier_spi_probe()
479 master->num_chipselect = 1; in uniphier_spi_probe()
481 ret = devm_spi_register_master(&pdev->dev, master); in uniphier_spi_probe()
488 clk_disable_unprepare(priv->clk); in uniphier_spi_probe()
499 clk_disable_unprepare(priv->clk); in uniphier_spi_remove()
505 { .compatible = "socionext,uniphier-scssi" },
514 .name = "uniphier-spi",
522 MODULE_DESCRIPTION("Socionext UniPhier SPI controller driver");