Lines Matching full:ospi
125 static void f_ospi_clear_irq(struct f_ospi *ospi) in f_ospi_clear_irq() argument
128 ospi->base + OSPI_IRQ); in f_ospi_clear_irq()
131 static void f_ospi_enable_irq_status(struct f_ospi *ospi, u32 irq_bits) in f_ospi_enable_irq_status() argument
135 val = readl(ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_enable_irq_status()
137 writel(val, ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_enable_irq_status()
140 static void f_ospi_disable_irq_status(struct f_ospi *ospi, u32 irq_bits) in f_ospi_disable_irq_status() argument
144 val = readl(ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_disable_irq_status()
146 writel(val, ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_disable_irq_status()
149 static void f_ospi_disable_irq_output(struct f_ospi *ospi, u32 irq_bits) in f_ospi_disable_irq_output() argument
153 val = readl(ospi->base + OSPI_IRQ_SIG_EN); in f_ospi_disable_irq_output()
155 writel(val, ospi->base + OSPI_IRQ_SIG_EN); in f_ospi_disable_irq_output()
158 static int f_ospi_prepare_config(struct f_ospi *ospi) in f_ospi_prepare_config() argument
163 val = readl(ospi->base + OSPI_CLK_CTL); in f_ospi_prepare_config()
165 writel(val, ospi->base + OSPI_CLK_CTL); in f_ospi_prepare_config()
171 return readl_poll_timeout(ospi->base + OSPI_STAT, in f_ospi_prepare_config()
176 static int f_ospi_unprepare_config(struct f_ospi *ospi) in f_ospi_unprepare_config() argument
181 val = readl(ospi->base + OSPI_CLK_CTL); in f_ospi_unprepare_config()
183 writel(val, ospi->base + OSPI_CLK_CTL); in f_ospi_unprepare_config()
186 return readl_poll_timeout(ospi->base + OSPI_STAT, in f_ospi_unprepare_config()
191 static void f_ospi_config_clk(struct f_ospi *ospi, u32 device_hz) in f_ospi_config_clk() argument
193 long rate_hz = clk_get_rate(ospi->clk); in f_ospi_config_clk()
199 dev_warn(ospi->dev, "Device frequency too large: %d\n", in f_ospi_config_clk()
212 dev_warn(ospi->dev, "Device frequency too small: %d\n", in f_ospi_config_clk()
223 val = readl(ospi->base + OSPI_CLK_CTL); in f_ospi_config_clk()
229 writel(val, ospi->base + OSPI_CLK_CTL); in f_ospi_config_clk()
232 static void f_ospi_config_dll(struct f_ospi *ospi) in f_ospi_config_dll() argument
237 static u8 f_ospi_get_mode(struct f_ospi *ospi, int width, int data_size) in f_ospi_get_mode() argument
256 dev_err(ospi->dev, "Invalid buswidth: %d\n", width); in f_ospi_get_mode()
263 static void f_ospi_config_indir_protocol(struct f_ospi *ospi, in f_ospi_config_indir_protocol() argument
273 writel(BIT(spi_get_chipselect(spi, 0)), ospi->base + OSPI_SSEL); in f_ospi_config_indir_protocol()
275 mode = f_ospi_get_mode(ospi, op->cmd.buswidth, 1); in f_ospi_config_indir_protocol()
278 mode = f_ospi_get_mode(ospi, op->addr.buswidth, op->addr.nbytes); in f_ospi_config_indir_protocol()
281 mode = f_ospi_get_mode(ospi, op->data.buswidth, op->data.nbytes); in f_ospi_config_indir_protocol()
327 dev_warn(ospi->dev, "Unsupported direction"); in f_ospi_config_indir_protocol()
334 writel(prot, ospi->base + OSPI_PROT_CTL_INDIR); in f_ospi_config_indir_protocol()
335 writel(val, ospi->base + OSPI_DAT_SIZE_INDIR); in f_ospi_config_indir_protocol()
338 static int f_ospi_indir_prepare_op(struct f_ospi *ospi, struct spi_mem *mem, in f_ospi_indir_prepare_op() argument
344 ret = f_ospi_prepare_config(ospi); in f_ospi_indir_prepare_op()
348 f_ospi_config_clk(ospi, op->max_freq); in f_ospi_indir_prepare_op()
350 f_ospi_config_indir_protocol(ospi, mem, op); in f_ospi_indir_prepare_op()
352 writel(f_ospi_get_dummy_cycle(op), ospi->base + OSPI_DMY_INDIR); in f_ospi_indir_prepare_op()
353 writel(op->addr.val, ospi->base + OSPI_ADDR); in f_ospi_indir_prepare_op()
354 writel(op->cmd.opcode, ospi->base + OSPI_CMD_IDX_INDIR); in f_ospi_indir_prepare_op()
356 f_ospi_clear_irq(ospi); in f_ospi_indir_prepare_op()
372 dev_warn(ospi->dev, "Unsupported direction"); in f_ospi_indir_prepare_op()
376 f_ospi_disable_irq_status(ospi, ~irq_stat_en); in f_ospi_indir_prepare_op()
377 f_ospi_enable_irq_status(ospi, irq_stat_en); in f_ospi_indir_prepare_op()
379 return f_ospi_unprepare_config(ospi); in f_ospi_indir_prepare_op()
382 static void f_ospi_indir_start_xfer(struct f_ospi *ospi) in f_ospi_indir_start_xfer() argument
385 writel(OSPI_TRANS_CTL_START_REQ, ospi->base + OSPI_TRANS_CTL); in f_ospi_indir_start_xfer()
388 static void f_ospi_indir_stop_xfer(struct f_ospi *ospi) in f_ospi_indir_stop_xfer() argument
391 writel(OSPI_TRANS_CTL_STOP_REQ, ospi->base + OSPI_TRANS_CTL); in f_ospi_indir_stop_xfer()
394 static int f_ospi_indir_wait_xfer_complete(struct f_ospi *ospi) in f_ospi_indir_wait_xfer_complete() argument
398 return readl_poll_timeout(ospi->base + OSPI_IRQ, val, in f_ospi_indir_wait_xfer_complete()
403 static int f_ospi_indir_read(struct f_ospi *ospi, struct spi_mem *mem, in f_ospi_indir_read() argument
410 mutex_lock(&ospi->mlock); in f_ospi_indir_read()
413 ret = f_ospi_indir_prepare_op(ospi, mem, op); in f_ospi_indir_read()
417 f_ospi_indir_start_xfer(ospi); in f_ospi_indir_read()
421 ret = readl_poll_timeout(ospi->base + OSPI_IRQ, val, in f_ospi_indir_read()
427 buf[i] = readl(ospi->base + OSPI_DAT) & 0xFF; in f_ospi_indir_read()
431 if (!(readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN)) in f_ospi_indir_read()
432 f_ospi_indir_stop_xfer(ospi); in f_ospi_indir_read()
435 ret = f_ospi_indir_wait_xfer_complete(ospi); in f_ospi_indir_read()
439 writel(OSPI_IRQ_CS_TRANS_COMP, ospi->base + OSPI_IRQ); in f_ospi_indir_read()
442 if (readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN) in f_ospi_indir_read()
446 writel(OSPI_SWRST_INDIR_READ_FIFO, ospi->base + OSPI_SWRST); in f_ospi_indir_read()
448 ret = readl_poll_timeout(ospi->base + OSPI_SWRST, val, in f_ospi_indir_read()
452 mutex_unlock(&ospi->mlock); in f_ospi_indir_read()
457 static int f_ospi_indir_write(struct f_ospi *ospi, struct spi_mem *mem, in f_ospi_indir_write() argument
464 mutex_lock(&ospi->mlock); in f_ospi_indir_write()
467 ret = f_ospi_indir_prepare_op(ospi, mem, op); in f_ospi_indir_write()
471 f_ospi_indir_start_xfer(ospi); in f_ospi_indir_write()
473 if (!(readl(ospi->base + OSPI_PROT_CTL_INDIR) & OSPI_PROT_DATA_EN)) in f_ospi_indir_write()
478 ret = readl_poll_timeout(ospi->base + OSPI_IRQ, val, in f_ospi_indir_write()
484 writel(buf[i], ospi->base + OSPI_DAT); in f_ospi_indir_write()
488 if (!(readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN)) in f_ospi_indir_write()
489 f_ospi_indir_stop_xfer(ospi); in f_ospi_indir_write()
493 ret = f_ospi_indir_wait_xfer_complete(ospi); in f_ospi_indir_write()
497 writel(OSPI_IRQ_CS_TRANS_COMP, ospi->base + OSPI_IRQ); in f_ospi_indir_write()
499 mutex_unlock(&ospi->mlock); in f_ospi_indir_write()
506 struct f_ospi *ospi = spi_controller_get_devdata(mem->spi->controller); in f_ospi_exec_op() local
511 err = f_ospi_indir_read(ospi, mem, op); in f_ospi_exec_op()
517 err = f_ospi_indir_write(ospi, mem, op); in f_ospi_exec_op()
521 dev_warn(ospi->dev, "Unsupported direction"); in f_ospi_exec_op()
586 static int f_ospi_init(struct f_ospi *ospi) in f_ospi_init() argument
590 ret = f_ospi_prepare_config(ospi); in f_ospi_init()
595 writel(OSPI_ACC_MODE_BOOT_DISABLE, ospi->base + OSPI_ACC_MODE); in f_ospi_init()
597 f_ospi_config_dll(ospi); in f_ospi_init()
600 f_ospi_clear_irq(ospi); in f_ospi_init()
601 f_ospi_disable_irq_status(ospi, OSPI_IRQ_ALL); in f_ospi_init()
602 f_ospi_disable_irq_output(ospi, OSPI_IRQ_ALL); in f_ospi_init()
604 return f_ospi_unprepare_config(ospi); in f_ospi_init()
611 struct f_ospi *ospi; in f_ospi_probe() local
615 ctlr = spi_alloc_host(dev, sizeof(*ospi)); in f_ospi_probe()
633 ospi = spi_controller_get_devdata(ctlr); in f_ospi_probe()
634 ospi->dev = dev; in f_ospi_probe()
636 platform_set_drvdata(pdev, ospi); in f_ospi_probe()
638 ospi->base = devm_platform_ioremap_resource(pdev, 0); in f_ospi_probe()
639 if (IS_ERR(ospi->base)) { in f_ospi_probe()
640 ret = PTR_ERR(ospi->base); in f_ospi_probe()
644 ospi->clk = devm_clk_get_enabled(dev, NULL); in f_ospi_probe()
645 if (IS_ERR(ospi->clk)) { in f_ospi_probe()
646 ret = PTR_ERR(ospi->clk); in f_ospi_probe()
650 mutex_init(&ospi->mlock); in f_ospi_probe()
652 ret = f_ospi_init(ospi); in f_ospi_probe()
663 mutex_destroy(&ospi->mlock); in f_ospi_probe()
673 struct f_ospi *ospi = platform_get_drvdata(pdev); in f_ospi_remove() local
675 mutex_destroy(&ospi->mlock); in f_ospi_remove()
679 { .compatible = "socionext,f-ospi" },
686 .name = "socionext,f-ospi",