Lines Matching +full:dev +full:- +full:ctrl
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2017-2018, The Linux foundation. All rights reserved.
14 #include <linux/spi/spi-mem.h>
141 struct device *dev; member
151 static u32 qspi_buswidth_to_iomode(struct qcom_qspi *ctrl, in qspi_buswidth_to_iomode() argument
162 dev_warn_once(ctrl->dev, in qspi_buswidth_to_iomode()
168 static void qcom_qspi_pio_xfer_cfg(struct qcom_qspi *ctrl) in qcom_qspi_pio_xfer_cfg() argument
173 xfer = &ctrl->xfer; in qcom_qspi_pio_xfer_cfg()
174 pio_xfer_cfg = readl(ctrl->base + PIO_XFER_CFG); in qcom_qspi_pio_xfer_cfg()
176 pio_xfer_cfg |= xfer->dir; in qcom_qspi_pio_xfer_cfg()
177 if (xfer->is_last) in qcom_qspi_pio_xfer_cfg()
182 pio_xfer_cfg |= qspi_buswidth_to_iomode(ctrl, xfer->buswidth); in qcom_qspi_pio_xfer_cfg()
184 writel(pio_xfer_cfg, ctrl->base + PIO_XFER_CFG); in qcom_qspi_pio_xfer_cfg()
187 static void qcom_qspi_pio_xfer_ctrl(struct qcom_qspi *ctrl) in qcom_qspi_pio_xfer_ctrl() argument
191 pio_xfer_ctrl = readl(ctrl->base + PIO_XFER_CTRL); in qcom_qspi_pio_xfer_ctrl()
193 pio_xfer_ctrl |= ctrl->xfer.rem_bytes; in qcom_qspi_pio_xfer_ctrl()
194 writel(pio_xfer_ctrl, ctrl->base + PIO_XFER_CTRL); in qcom_qspi_pio_xfer_ctrl()
197 static void qcom_qspi_pio_xfer(struct qcom_qspi *ctrl) in qcom_qspi_pio_xfer() argument
201 qcom_qspi_pio_xfer_cfg(ctrl); in qcom_qspi_pio_xfer()
204 writel(QSPI_ALL_IRQS, ctrl->base + MSTR_INT_STATUS); in qcom_qspi_pio_xfer()
207 if (ctrl->xfer.dir == QSPI_WRITE) in qcom_qspi_pio_xfer()
211 writel(ints, ctrl->base + MSTR_INT_EN); in qcom_qspi_pio_xfer()
214 qcom_qspi_pio_xfer_ctrl(ctrl); in qcom_qspi_pio_xfer()
220 struct qcom_qspi *ctrl = spi_master_get_devdata(master); in qcom_qspi_handle_err() local
223 spin_lock_irqsave(&ctrl->lock, flags); in qcom_qspi_handle_err()
224 writel(0, ctrl->base + MSTR_INT_EN); in qcom_qspi_handle_err()
225 ctrl->xfer.rem_bytes = 0; in qcom_qspi_handle_err()
226 spin_unlock_irqrestore(&ctrl->lock, flags); in qcom_qspi_handle_err()
229 static int qcom_qspi_set_speed(struct qcom_qspi *ctrl, unsigned long speed_hz) in qcom_qspi_set_speed() argument
234 if (speed_hz == ctrl->last_speed) in qcom_qspi_set_speed()
238 ret = dev_pm_opp_set_rate(ctrl->dev, speed_hz * 4); in qcom_qspi_set_speed()
240 dev_err(ctrl->dev, "Failed to set core clk %d\n", ret); in qcom_qspi_set_speed()
249 ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, avg_bw_cpu, avg_bw_cpu); in qcom_qspi_set_speed()
251 dev_err(ctrl->dev, "%s: ICC BW voting failed for cpu: %d\n", in qcom_qspi_set_speed()
256 ctrl->last_speed = speed_hz; in qcom_qspi_set_speed()
265 struct qcom_qspi *ctrl = spi_master_get_devdata(master); in qcom_qspi_transfer_one() local
270 speed_hz = slv->max_speed_hz; in qcom_qspi_transfer_one()
271 if (xfer->speed_hz) in qcom_qspi_transfer_one()
272 speed_hz = xfer->speed_hz; in qcom_qspi_transfer_one()
274 ret = qcom_qspi_set_speed(ctrl, speed_hz); in qcom_qspi_transfer_one()
278 spin_lock_irqsave(&ctrl->lock, flags); in qcom_qspi_transfer_one()
281 if (xfer->rx_buf) { in qcom_qspi_transfer_one()
282 ctrl->xfer.dir = QSPI_READ; in qcom_qspi_transfer_one()
283 ctrl->xfer.buswidth = xfer->rx_nbits; in qcom_qspi_transfer_one()
284 ctrl->xfer.rx_buf = xfer->rx_buf; in qcom_qspi_transfer_one()
286 ctrl->xfer.dir = QSPI_WRITE; in qcom_qspi_transfer_one()
287 ctrl->xfer.buswidth = xfer->tx_nbits; in qcom_qspi_transfer_one()
288 ctrl->xfer.tx_buf = xfer->tx_buf; in qcom_qspi_transfer_one()
290 ctrl->xfer.is_last = list_is_last(&xfer->transfer_list, in qcom_qspi_transfer_one()
291 &master->cur_msg->transfers); in qcom_qspi_transfer_one()
292 ctrl->xfer.rem_bytes = xfer->len; in qcom_qspi_transfer_one()
293 qcom_qspi_pio_xfer(ctrl); in qcom_qspi_transfer_one()
295 spin_unlock_irqrestore(&ctrl->lock, flags); in qcom_qspi_transfer_one()
305 struct qcom_qspi *ctrl; in qcom_qspi_prepare_message() local
310 ctrl = spi_master_get_devdata(master); in qcom_qspi_prepare_message()
311 spin_lock_irqsave(&ctrl->lock, flags); in qcom_qspi_prepare_message()
313 mstr_cfg = readl(ctrl->base + MSTR_CONFIG); in qcom_qspi_prepare_message()
315 if (message->spi->chip_select) in qcom_qspi_prepare_message()
320 mstr_cfg |= message->spi->mode << SPI_MODE_SHFT; in qcom_qspi_prepare_message()
325 writel(mstr_cfg, ctrl->base + MSTR_CONFIG); in qcom_qspi_prepare_message()
326 spin_unlock_irqrestore(&ctrl->lock, flags); in qcom_qspi_prepare_message()
331 static irqreturn_t pio_read(struct qcom_qspi *ctrl) in pio_read() argument
342 rd_fifo_status = readl(ctrl->base + RD_FIFO_STATUS); in pio_read()
345 dev_dbg(ctrl->dev, "Spurious IRQ %#x\n", rd_fifo_status); in pio_read()
350 wr_cnts = min(wr_cnts, ctrl->xfer.rem_bytes); in pio_read()
356 word_buf = ctrl->xfer.rx_buf; in pio_read()
357 ctrl->xfer.rem_bytes -= words_to_read * QSPI_BYTES_PER_WORD; in pio_read()
358 ioread32_rep(ctrl->base + RD_FIFO, word_buf, words_to_read); in pio_read()
359 ctrl->xfer.rx_buf = word_buf + words_to_read; in pio_read()
363 byte_buf = ctrl->xfer.rx_buf; in pio_read()
364 rd_fifo = readl(ctrl->base + RD_FIFO); in pio_read()
365 ctrl->xfer.rem_bytes -= bytes_to_read; in pio_read()
368 ctrl->xfer.rx_buf = byte_buf; in pio_read()
374 static irqreturn_t pio_write(struct qcom_qspi *ctrl) in pio_write() argument
376 const void *xfer_buf = ctrl->xfer.tx_buf; in pio_write()
384 wr_fifo_bytes = readl(ctrl->base + PIO_XFER_STATUS); in pio_write()
387 if (ctrl->xfer.rem_bytes < QSPI_BYTES_PER_WORD) { in pio_write()
388 /* Process the last 1-3 bytes */ in pio_write()
389 wr_size = min(wr_fifo_bytes, ctrl->xfer.rem_bytes); in pio_write()
390 ctrl->xfer.rem_bytes -= wr_size; in pio_write()
393 while (wr_size--) in pio_write()
395 ctrl->base + PIO_DATAOUT_1B); in pio_write()
396 ctrl->xfer.tx_buf = byte_buf; in pio_write()
400 * just wait for the next interrupt to handle the last 1-3 in pio_write()
403 rem_words = ctrl->xfer.rem_bytes / QSPI_BYTES_PER_WORD; in pio_write()
407 ctrl->xfer.rem_bytes -= wr_size * QSPI_BYTES_PER_WORD; in pio_write()
410 iowrite32_rep(ctrl->base + PIO_DATAOUT_4B, word_buf, wr_size); in pio_write()
411 ctrl->xfer.tx_buf = word_buf + wr_size; in pio_write()
421 struct qcom_qspi *ctrl = dev_id; in qcom_qspi_irq() local
424 spin_lock(&ctrl->lock); in qcom_qspi_irq()
426 int_status = readl(ctrl->base + MSTR_INT_STATUS); in qcom_qspi_irq()
427 writel(int_status, ctrl->base + MSTR_INT_STATUS); in qcom_qspi_irq()
429 if (ctrl->xfer.dir == QSPI_WRITE) { in qcom_qspi_irq()
431 ret = pio_write(ctrl); in qcom_qspi_irq()
434 ret = pio_read(ctrl); in qcom_qspi_irq()
439 dev_err(ctrl->dev, "IRQ error: FIFO underrun\n"); in qcom_qspi_irq()
441 dev_err(ctrl->dev, "IRQ error: FIFO overrun\n"); in qcom_qspi_irq()
443 dev_err(ctrl->dev, "IRQ error: NOC response error\n"); in qcom_qspi_irq()
447 if (!ctrl->xfer.rem_bytes) { in qcom_qspi_irq()
448 writel(0, ctrl->base + MSTR_INT_EN); in qcom_qspi_irq()
449 spi_finalize_current_transfer(dev_get_drvdata(ctrl->dev)); in qcom_qspi_irq()
452 spin_unlock(&ctrl->lock); in qcom_qspi_irq()
459 struct device *dev; in qcom_qspi_probe() local
461 struct qcom_qspi *ctrl; in qcom_qspi_probe() local
463 dev = &pdev->dev; in qcom_qspi_probe()
465 master = devm_spi_alloc_master(dev, sizeof(*ctrl)); in qcom_qspi_probe()
467 return -ENOMEM; in qcom_qspi_probe()
471 ctrl = spi_master_get_devdata(master); in qcom_qspi_probe()
473 spin_lock_init(&ctrl->lock); in qcom_qspi_probe()
474 ctrl->dev = dev; in qcom_qspi_probe()
475 ctrl->base = devm_platform_ioremap_resource(pdev, 0); in qcom_qspi_probe()
476 if (IS_ERR(ctrl->base)) in qcom_qspi_probe()
477 return PTR_ERR(ctrl->base); in qcom_qspi_probe()
479 ctrl->clks = devm_kcalloc(dev, QSPI_NUM_CLKS, in qcom_qspi_probe()
480 sizeof(*ctrl->clks), GFP_KERNEL); in qcom_qspi_probe()
481 if (!ctrl->clks) in qcom_qspi_probe()
482 return -ENOMEM; in qcom_qspi_probe()
484 ctrl->clks[QSPI_CLK_CORE].id = "core"; in qcom_qspi_probe()
485 ctrl->clks[QSPI_CLK_IFACE].id = "iface"; in qcom_qspi_probe()
486 ret = devm_clk_bulk_get(dev, QSPI_NUM_CLKS, ctrl->clks); in qcom_qspi_probe()
490 ctrl->icc_path_cpu_to_qspi = devm_of_icc_get(dev, "qspi-config"); in qcom_qspi_probe()
491 if (IS_ERR(ctrl->icc_path_cpu_to_qspi)) in qcom_qspi_probe()
492 return dev_err_probe(dev, PTR_ERR(ctrl->icc_path_cpu_to_qspi), in qcom_qspi_probe()
496 ret = icc_set_bw(ctrl->icc_path_cpu_to_qspi, Bps_to_icc(1000), in qcom_qspi_probe()
499 dev_err(ctrl->dev, "%s: ICC BW voting failed for cpu: %d\n", in qcom_qspi_probe()
504 ret = icc_disable(ctrl->icc_path_cpu_to_qspi); in qcom_qspi_probe()
506 dev_err(ctrl->dev, "%s: ICC disable failed for cpu: %d\n", in qcom_qspi_probe()
514 ret = devm_request_irq(dev, ret, qcom_qspi_irq, in qcom_qspi_probe()
515 IRQF_TRIGGER_HIGH, dev_name(dev), ctrl); in qcom_qspi_probe()
517 dev_err(dev, "Failed to request irq %d\n", ret); in qcom_qspi_probe()
521 master->max_speed_hz = 300000000; in qcom_qspi_probe()
522 master->num_chipselect = QSPI_NUM_CS; in qcom_qspi_probe()
523 master->bus_num = -1; in qcom_qspi_probe()
524 master->dev.of_node = pdev->dev.of_node; in qcom_qspi_probe()
525 master->mode_bits = SPI_MODE_0 | in qcom_qspi_probe()
528 master->flags = SPI_MASTER_HALF_DUPLEX; in qcom_qspi_probe()
529 master->prepare_message = qcom_qspi_prepare_message; in qcom_qspi_probe()
530 master->transfer_one = qcom_qspi_transfer_one; in qcom_qspi_probe()
531 master->handle_err = qcom_qspi_handle_err; in qcom_qspi_probe()
532 master->auto_runtime_pm = true; in qcom_qspi_probe()
534 ctrl->opp_table = dev_pm_opp_set_clkname(&pdev->dev, "core"); in qcom_qspi_probe()
535 if (IS_ERR(ctrl->opp_table)) in qcom_qspi_probe()
536 return PTR_ERR(ctrl->opp_table); in qcom_qspi_probe()
538 ret = dev_pm_opp_of_add_table(&pdev->dev); in qcom_qspi_probe()
539 if (ret && ret != -ENODEV) { in qcom_qspi_probe()
540 dev_err(&pdev->dev, "invalid OPP table in device tree\n"); in qcom_qspi_probe()
544 pm_runtime_use_autosuspend(dev); in qcom_qspi_probe()
545 pm_runtime_set_autosuspend_delay(dev, 250); in qcom_qspi_probe()
546 pm_runtime_enable(dev); in qcom_qspi_probe()
552 pm_runtime_disable(dev); in qcom_qspi_probe()
553 dev_pm_opp_of_remove_table(&pdev->dev); in qcom_qspi_probe()
556 dev_pm_opp_put_clkname(ctrl->opp_table); in qcom_qspi_probe()
564 struct qcom_qspi *ctrl = spi_master_get_devdata(master); in qcom_qspi_remove() local
569 pm_runtime_disable(&pdev->dev); in qcom_qspi_remove()
570 dev_pm_opp_of_remove_table(&pdev->dev); in qcom_qspi_remove()
571 dev_pm_opp_put_clkname(ctrl->opp_table); in qcom_qspi_remove()
576 static int __maybe_unused qcom_qspi_runtime_suspend(struct device *dev) in qcom_qspi_runtime_suspend() argument
578 struct spi_master *master = dev_get_drvdata(dev); in qcom_qspi_runtime_suspend()
579 struct qcom_qspi *ctrl = spi_master_get_devdata(master); in qcom_qspi_runtime_suspend() local
583 dev_pm_opp_set_rate(dev, 0); in qcom_qspi_runtime_suspend()
584 clk_bulk_disable_unprepare(QSPI_NUM_CLKS, ctrl->clks); in qcom_qspi_runtime_suspend()
586 ret = icc_disable(ctrl->icc_path_cpu_to_qspi); in qcom_qspi_runtime_suspend()
588 dev_err_ratelimited(ctrl->dev, "%s: ICC disable failed for cpu: %d\n", in qcom_qspi_runtime_suspend()
596 static int __maybe_unused qcom_qspi_runtime_resume(struct device *dev) in qcom_qspi_runtime_resume() argument
598 struct spi_master *master = dev_get_drvdata(dev); in qcom_qspi_runtime_resume()
599 struct qcom_qspi *ctrl = spi_master_get_devdata(master); in qcom_qspi_runtime_resume() local
602 ret = icc_enable(ctrl->icc_path_cpu_to_qspi); in qcom_qspi_runtime_resume()
604 dev_err_ratelimited(ctrl->dev, "%s: ICC enable failed for cpu: %d\n", in qcom_qspi_runtime_resume()
609 ret = clk_bulk_prepare_enable(QSPI_NUM_CLKS, ctrl->clks); in qcom_qspi_runtime_resume()
613 return dev_pm_opp_set_rate(dev, ctrl->last_speed * 4); in qcom_qspi_runtime_resume()
616 static int __maybe_unused qcom_qspi_suspend(struct device *dev) in qcom_qspi_suspend() argument
618 struct spi_master *master = dev_get_drvdata(dev); in qcom_qspi_suspend()
625 ret = pm_runtime_force_suspend(dev); in qcom_qspi_suspend()
632 static int __maybe_unused qcom_qspi_resume(struct device *dev) in qcom_qspi_resume() argument
634 struct spi_master *master = dev_get_drvdata(dev); in qcom_qspi_resume()
637 ret = pm_runtime_force_resume(dev); in qcom_qspi_resume()
643 pm_runtime_force_suspend(dev); in qcom_qspi_resume()
655 { .compatible = "qcom,qspi-v1", },