Lines Matching refs:ospi

122 static void f_ospi_clear_irq(struct f_ospi *ospi)  in f_ospi_clear_irq()  argument
125 ospi->base + OSPI_IRQ); in f_ospi_clear_irq()
128 static void f_ospi_enable_irq_status(struct f_ospi *ospi, u32 irq_bits) in f_ospi_enable_irq_status() argument
132 val = readl(ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_enable_irq_status()
134 writel(val, ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_enable_irq_status()
137 static void f_ospi_disable_irq_status(struct f_ospi *ospi, u32 irq_bits) in f_ospi_disable_irq_status() argument
141 val = readl(ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_disable_irq_status()
143 writel(val, ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_disable_irq_status()
146 static void f_ospi_disable_irq_output(struct f_ospi *ospi, u32 irq_bits) in f_ospi_disable_irq_output() argument
150 val = readl(ospi->base + OSPI_IRQ_SIG_EN); in f_ospi_disable_irq_output()
152 writel(val, ospi->base + OSPI_IRQ_SIG_EN); in f_ospi_disable_irq_output()
155 static int f_ospi_prepare_config(struct f_ospi *ospi) in f_ospi_prepare_config() argument
160 val = readl(ospi->base + OSPI_CLK_CTL); in f_ospi_prepare_config()
162 writel(val, ospi->base + OSPI_CLK_CTL); in f_ospi_prepare_config()
168 return readl_poll_timeout(ospi->base + OSPI_STAT, in f_ospi_prepare_config()
173 static int f_ospi_unprepare_config(struct f_ospi *ospi) in f_ospi_unprepare_config() argument
178 val = readl(ospi->base + OSPI_CLK_CTL); in f_ospi_unprepare_config()
180 writel(val, ospi->base + OSPI_CLK_CTL); in f_ospi_unprepare_config()
183 return readl_poll_timeout(ospi->base + OSPI_STAT, in f_ospi_unprepare_config()
188 static void f_ospi_config_clk(struct f_ospi *ospi, u32 device_hz) in f_ospi_config_clk() argument
190 long rate_hz = clk_get_rate(ospi->clk); in f_ospi_config_clk()
196 dev_warn(ospi->dev, "Device frequency too large: %d\n", in f_ospi_config_clk()
209 dev_warn(ospi->dev, "Device frequency too small: %d\n", in f_ospi_config_clk()
220 val = readl(ospi->base + OSPI_CLK_CTL); in f_ospi_config_clk()
226 writel(val, ospi->base + OSPI_CLK_CTL); in f_ospi_config_clk()
229 static void f_ospi_config_dll(struct f_ospi *ospi) in f_ospi_config_dll() argument
234 static u8 f_ospi_get_mode(struct f_ospi *ospi, int width, int data_size) in f_ospi_get_mode() argument
253 dev_err(ospi->dev, "Invalid buswidth: %d\n", width); in f_ospi_get_mode()
260 static void f_ospi_config_indir_protocol(struct f_ospi *ospi, in f_ospi_config_indir_protocol() argument
270 writel(BIT(spi_get_chipselect(spi, 0)), ospi->base + OSPI_SSEL); in f_ospi_config_indir_protocol()
272 mode = f_ospi_get_mode(ospi, op->cmd.buswidth, 1); in f_ospi_config_indir_protocol()
275 mode = f_ospi_get_mode(ospi, op->addr.buswidth, op->addr.nbytes); in f_ospi_config_indir_protocol()
278 mode = f_ospi_get_mode(ospi, op->data.buswidth, op->data.nbytes); in f_ospi_config_indir_protocol()
324 dev_warn(ospi->dev, "Unsupported direction"); in f_ospi_config_indir_protocol()
331 writel(prot, ospi->base + OSPI_PROT_CTL_INDIR); in f_ospi_config_indir_protocol()
332 writel(val, ospi->base + OSPI_DAT_SIZE_INDIR); in f_ospi_config_indir_protocol()
335 static int f_ospi_indir_prepare_op(struct f_ospi *ospi, struct spi_mem *mem, in f_ospi_indir_prepare_op() argument
342 ret = f_ospi_prepare_config(ospi); in f_ospi_indir_prepare_op()
346 f_ospi_config_clk(ospi, spi->max_speed_hz); in f_ospi_indir_prepare_op()
348 f_ospi_config_indir_protocol(ospi, mem, op); in f_ospi_indir_prepare_op()
350 writel(f_ospi_get_dummy_cycle(op), ospi->base + OSPI_DMY_INDIR); in f_ospi_indir_prepare_op()
351 writel(op->addr.val, ospi->base + OSPI_ADDR); in f_ospi_indir_prepare_op()
352 writel(op->cmd.opcode, ospi->base + OSPI_CMD_IDX_INDIR); in f_ospi_indir_prepare_op()
354 f_ospi_clear_irq(ospi); in f_ospi_indir_prepare_op()
370 dev_warn(ospi->dev, "Unsupported direction"); in f_ospi_indir_prepare_op()
374 f_ospi_disable_irq_status(ospi, ~irq_stat_en); in f_ospi_indir_prepare_op()
375 f_ospi_enable_irq_status(ospi, irq_stat_en); in f_ospi_indir_prepare_op()
377 return f_ospi_unprepare_config(ospi); in f_ospi_indir_prepare_op()
380 static void f_ospi_indir_start_xfer(struct f_ospi *ospi) in f_ospi_indir_start_xfer() argument
383 writel(OSPI_TRANS_CTL_START_REQ, ospi->base + OSPI_TRANS_CTL); in f_ospi_indir_start_xfer()
386 static void f_ospi_indir_stop_xfer(struct f_ospi *ospi) in f_ospi_indir_stop_xfer() argument
389 writel(OSPI_TRANS_CTL_STOP_REQ, ospi->base + OSPI_TRANS_CTL); in f_ospi_indir_stop_xfer()
392 static int f_ospi_indir_wait_xfer_complete(struct f_ospi *ospi) in f_ospi_indir_wait_xfer_complete() argument
396 return readl_poll_timeout(ospi->base + OSPI_IRQ, val, in f_ospi_indir_wait_xfer_complete()
401 static int f_ospi_indir_read(struct f_ospi *ospi, struct spi_mem *mem, in f_ospi_indir_read() argument
408 mutex_lock(&ospi->mlock); in f_ospi_indir_read()
411 ret = f_ospi_indir_prepare_op(ospi, mem, op); in f_ospi_indir_read()
415 f_ospi_indir_start_xfer(ospi); in f_ospi_indir_read()
419 ret = readl_poll_timeout(ospi->base + OSPI_IRQ, val, in f_ospi_indir_read()
425 buf[i] = readl(ospi->base + OSPI_DAT) & 0xFF; in f_ospi_indir_read()
429 if (!(readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN)) in f_ospi_indir_read()
430 f_ospi_indir_stop_xfer(ospi); in f_ospi_indir_read()
433 ret = f_ospi_indir_wait_xfer_complete(ospi); in f_ospi_indir_read()
437 writel(OSPI_IRQ_CS_TRANS_COMP, ospi->base + OSPI_IRQ); in f_ospi_indir_read()
440 if (readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN) in f_ospi_indir_read()
444 writel(OSPI_SWRST_INDIR_READ_FIFO, ospi->base + OSPI_SWRST); in f_ospi_indir_read()
446 ret = readl_poll_timeout(ospi->base + OSPI_SWRST, val, in f_ospi_indir_read()
450 mutex_unlock(&ospi->mlock); in f_ospi_indir_read()
455 static int f_ospi_indir_write(struct f_ospi *ospi, struct spi_mem *mem, in f_ospi_indir_write() argument
462 mutex_lock(&ospi->mlock); in f_ospi_indir_write()
465 ret = f_ospi_indir_prepare_op(ospi, mem, op); in f_ospi_indir_write()
469 f_ospi_indir_start_xfer(ospi); in f_ospi_indir_write()
471 if (!(readl(ospi->base + OSPI_PROT_CTL_INDIR) & OSPI_PROT_DATA_EN)) in f_ospi_indir_write()
476 ret = readl_poll_timeout(ospi->base + OSPI_IRQ, val, in f_ospi_indir_write()
482 writel(buf[i], ospi->base + OSPI_DAT); in f_ospi_indir_write()
486 if (!(readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN)) in f_ospi_indir_write()
487 f_ospi_indir_stop_xfer(ospi); in f_ospi_indir_write()
491 ret = f_ospi_indir_wait_xfer_complete(ospi); in f_ospi_indir_write()
495 writel(OSPI_IRQ_CS_TRANS_COMP, ospi->base + OSPI_IRQ); in f_ospi_indir_write()
497 mutex_unlock(&ospi->mlock); in f_ospi_indir_write()
504 struct f_ospi *ospi = spi_controller_get_devdata(mem->spi->controller); in f_ospi_exec_op() local
509 err = f_ospi_indir_read(ospi, mem, op); in f_ospi_exec_op()
515 err = f_ospi_indir_write(ospi, mem, op); in f_ospi_exec_op()
519 dev_warn(ospi->dev, "Unsupported direction"); in f_ospi_exec_op()
580 static int f_ospi_init(struct f_ospi *ospi) in f_ospi_init() argument
584 ret = f_ospi_prepare_config(ospi); in f_ospi_init()
589 writel(OSPI_ACC_MODE_BOOT_DISABLE, ospi->base + OSPI_ACC_MODE); in f_ospi_init()
591 f_ospi_config_dll(ospi); in f_ospi_init()
594 f_ospi_clear_irq(ospi); in f_ospi_init()
595 f_ospi_disable_irq_status(ospi, OSPI_IRQ_ALL); in f_ospi_init()
596 f_ospi_disable_irq_output(ospi, OSPI_IRQ_ALL); in f_ospi_init()
598 return f_ospi_unprepare_config(ospi); in f_ospi_init()
605 struct f_ospi *ospi; in f_ospi_probe() local
609 ctlr = spi_alloc_host(dev, sizeof(*ospi)); in f_ospi_probe()
626 ospi = spi_controller_get_devdata(ctlr); in f_ospi_probe()
627 ospi->dev = dev; in f_ospi_probe()
629 platform_set_drvdata(pdev, ospi); in f_ospi_probe()
631 ospi->base = devm_platform_ioremap_resource(pdev, 0); in f_ospi_probe()
632 if (IS_ERR(ospi->base)) { in f_ospi_probe()
633 ret = PTR_ERR(ospi->base); in f_ospi_probe()
637 ospi->clk = devm_clk_get_enabled(dev, NULL); in f_ospi_probe()
638 if (IS_ERR(ospi->clk)) { in f_ospi_probe()
639 ret = PTR_ERR(ospi->clk); in f_ospi_probe()
643 mutex_init(&ospi->mlock); in f_ospi_probe()
645 ret = f_ospi_init(ospi); in f_ospi_probe()
656 mutex_destroy(&ospi->mlock); in f_ospi_probe()
666 struct f_ospi *ospi = platform_get_drvdata(pdev); in f_ospi_remove() local
668 mutex_destroy(&ospi->mlock); in f_ospi_remove()