Lines Matching +full:spi +full:- +full:nor

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * HiSilicon FMC SPI NOR flash controller driver
5 * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd.
9 #include <linux/dma-mapping.h>
13 #include <linux/mtd/spi-nor.h>
64 #define HIFMC_DMA_MASK (HIFMC_DMA_MAX_LEN - 1)
99 struct spi_nor *nor[HIFMC_MAX_CHIP_NUM]; member
107 return readl_poll_timeout(host->regbase + FMC_INT, reg, in hisi_spi_nor_wait_op_finish()
144 writel(reg, host->regbase + FMC_SPI_TIMING_CFG); in hisi_spi_nor_init()
147 static int hisi_spi_nor_prep(struct spi_nor *nor) in hisi_spi_nor_prep() argument
149 struct hifmc_priv *priv = nor->priv; in hisi_spi_nor_prep()
150 struct hifmc_host *host = priv->host; in hisi_spi_nor_prep()
153 mutex_lock(&host->lock); in hisi_spi_nor_prep()
155 ret = clk_set_rate(host->clk, priv->clkrate); in hisi_spi_nor_prep()
159 ret = clk_prepare_enable(host->clk); in hisi_spi_nor_prep()
166 mutex_unlock(&host->lock); in hisi_spi_nor_prep()
170 static void hisi_spi_nor_unprep(struct spi_nor *nor) in hisi_spi_nor_unprep() argument
172 struct hifmc_priv *priv = nor->priv; in hisi_spi_nor_unprep()
173 struct hifmc_host *host = priv->host; in hisi_spi_nor_unprep()
175 clk_disable_unprepare(host->clk); in hisi_spi_nor_unprep()
176 mutex_unlock(&host->lock); in hisi_spi_nor_unprep()
179 static int hisi_spi_nor_op_reg(struct spi_nor *nor, in hisi_spi_nor_op_reg() argument
182 struct hifmc_priv *priv = nor->priv; in hisi_spi_nor_op_reg()
183 struct hifmc_host *host = priv->host; in hisi_spi_nor_op_reg()
187 writel(reg, host->regbase + FMC_CMD); in hisi_spi_nor_op_reg()
190 writel(reg, host->regbase + FMC_DATA_NUM); in hisi_spi_nor_op_reg()
192 reg = OP_CFG_FM_CS(priv->chipselect); in hisi_spi_nor_op_reg()
193 writel(reg, host->regbase + FMC_OP_CFG); in hisi_spi_nor_op_reg()
195 writel(0xff, host->regbase + FMC_INT_CLR); in hisi_spi_nor_op_reg()
197 writel(reg, host->regbase + FMC_OP); in hisi_spi_nor_op_reg()
202 static int hisi_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, in hisi_spi_nor_read_reg() argument
205 struct hifmc_priv *priv = nor->priv; in hisi_spi_nor_read_reg()
206 struct hifmc_host *host = priv->host; in hisi_spi_nor_read_reg()
209 ret = hisi_spi_nor_op_reg(nor, opcode, len, FMC_OP_READ_DATA_EN); in hisi_spi_nor_read_reg()
213 memcpy_fromio(buf, host->iobase, len); in hisi_spi_nor_read_reg()
217 static int hisi_spi_nor_write_reg(struct spi_nor *nor, u8 opcode, in hisi_spi_nor_write_reg() argument
220 struct hifmc_priv *priv = nor->priv; in hisi_spi_nor_write_reg()
221 struct hifmc_host *host = priv->host; in hisi_spi_nor_write_reg()
224 memcpy_toio(host->iobase, buf, len); in hisi_spi_nor_write_reg()
226 return hisi_spi_nor_op_reg(nor, opcode, len, FMC_OP_WRITE_DATA_EN); in hisi_spi_nor_write_reg()
229 static int hisi_spi_nor_dma_transfer(struct spi_nor *nor, loff_t start_off, in hisi_spi_nor_dma_transfer() argument
232 struct hifmc_priv *priv = nor->priv; in hisi_spi_nor_dma_transfer()
233 struct hifmc_host *host = priv->host; in hisi_spi_nor_dma_transfer()
237 reg = readl(host->regbase + FMC_CFG); in hisi_spi_nor_dma_transfer()
240 reg |= (nor->addr_nbytes == 4) ? SPI_NOR_ADDR_MODE_4BYTES in hisi_spi_nor_dma_transfer()
242 writel(reg, host->regbase + FMC_CFG); in hisi_spi_nor_dma_transfer()
244 writel(start_off, host->regbase + FMC_ADDRL); in hisi_spi_nor_dma_transfer()
245 writel(dma_buf, host->regbase + FMC_DMA_SADDR_D0); in hisi_spi_nor_dma_transfer()
246 writel(FMC_DMA_LEN_SET(len), host->regbase + FMC_DMA_LEN); in hisi_spi_nor_dma_transfer()
248 reg = OP_CFG_FM_CS(priv->chipselect); in hisi_spi_nor_dma_transfer()
250 if_type = hisi_spi_nor_get_if_type(nor->read_proto); in hisi_spi_nor_dma_transfer()
252 if_type = hisi_spi_nor_get_if_type(nor->write_proto); in hisi_spi_nor_dma_transfer()
255 reg |= OP_CFG_DUMMY_NUM(nor->read_dummy >> 3); in hisi_spi_nor_dma_transfer()
256 writel(reg, host->regbase + FMC_OP_CFG); in hisi_spi_nor_dma_transfer()
258 writel(0xff, host->regbase + FMC_INT_CLR); in hisi_spi_nor_dma_transfer()
261 ? OP_CTRL_RD_OPCODE(nor->read_opcode) in hisi_spi_nor_dma_transfer()
262 : OP_CTRL_WR_OPCODE(nor->program_opcode); in hisi_spi_nor_dma_transfer()
263 writel(reg, host->regbase + FMC_OP_DMA); in hisi_spi_nor_dma_transfer()
268 static ssize_t hisi_spi_nor_read(struct spi_nor *nor, loff_t from, size_t len, in hisi_spi_nor_read() argument
271 struct hifmc_priv *priv = nor->priv; in hisi_spi_nor_read()
272 struct hifmc_host *host = priv->host; in hisi_spi_nor_read()
277 size_t trans = min_t(size_t, HIFMC_DMA_MAX_LEN, len - offset); in hisi_spi_nor_read()
279 ret = hisi_spi_nor_dma_transfer(nor, in hisi_spi_nor_read()
280 from + offset, host->dma_buffer, trans, FMC_OP_READ); in hisi_spi_nor_read()
282 dev_warn(nor->dev, "DMA read timeout\n"); in hisi_spi_nor_read()
285 memcpy(read_buf + offset, host->buffer, trans); in hisi_spi_nor_read()
291 static ssize_t hisi_spi_nor_write(struct spi_nor *nor, loff_t to, in hisi_spi_nor_write() argument
294 struct hifmc_priv *priv = nor->priv; in hisi_spi_nor_write()
295 struct hifmc_host *host = priv->host; in hisi_spi_nor_write()
300 size_t trans = min_t(size_t, HIFMC_DMA_MAX_LEN, len - offset); in hisi_spi_nor_write()
302 memcpy(host->buffer, write_buf + offset, trans); in hisi_spi_nor_write()
303 ret = hisi_spi_nor_dma_transfer(nor, in hisi_spi_nor_write()
304 to + offset, host->dma_buffer, trans, FMC_OP_WRITE); in hisi_spi_nor_write()
306 dev_warn(nor->dev, "DMA write timeout\n"); in hisi_spi_nor_write()
324 * Get spi flash device information and register it as a mtd device.
336 struct device *dev = host->dev; in hisi_spi_nor_register()
337 struct spi_nor *nor; in hisi_spi_nor_register() local
342 nor = devm_kzalloc(dev, sizeof(*nor), GFP_KERNEL); in hisi_spi_nor_register()
343 if (!nor) in hisi_spi_nor_register()
344 return -ENOMEM; in hisi_spi_nor_register()
346 nor->dev = dev; in hisi_spi_nor_register()
347 spi_nor_set_flash_node(nor, np); in hisi_spi_nor_register()
351 return -ENOMEM; in hisi_spi_nor_register()
353 ret = of_property_read_u32(np, "reg", &priv->chipselect); in hisi_spi_nor_register()
360 ret = of_property_read_u32(np, "spi-max-frequency", in hisi_spi_nor_register()
361 &priv->clkrate); in hisi_spi_nor_register()
363 dev_err(dev, "There's no spi-max-frequency property for %pOF\n", in hisi_spi_nor_register()
367 priv->host = host; in hisi_spi_nor_register()
368 nor->priv = priv; in hisi_spi_nor_register()
369 nor->controller_ops = &hisi_controller_ops; in hisi_spi_nor_register()
371 ret = spi_nor_scan(nor, NULL, &hwcaps); in hisi_spi_nor_register()
375 mtd = &nor->mtd; in hisi_spi_nor_register()
376 mtd->name = np->name; in hisi_spi_nor_register()
381 host->nor[host->num_chip] = nor; in hisi_spi_nor_register()
382 host->num_chip++; in hisi_spi_nor_register()
390 for (i = 0; i < host->num_chip; i++) in hisi_spi_nor_unregister_all()
391 mtd_device_unregister(&host->nor[i]->mtd); in hisi_spi_nor_unregister_all()
396 struct device *dev = host->dev; in hisi_spi_nor_register_all()
400 for_each_available_child_of_node(dev->of_node, np) { in hisi_spi_nor_register_all()
407 if (host->num_chip == HIFMC_MAX_CHIP_NUM) { in hisi_spi_nor_register_all()
423 struct device *dev = &pdev->dev; in hisi_spi_nor_probe()
429 return -ENOMEM; in hisi_spi_nor_probe()
432 host->dev = dev; in hisi_spi_nor_probe()
434 host->regbase = devm_platform_ioremap_resource_byname(pdev, "control"); in hisi_spi_nor_probe()
435 if (IS_ERR(host->regbase)) in hisi_spi_nor_probe()
436 return PTR_ERR(host->regbase); in hisi_spi_nor_probe()
438 host->iobase = devm_platform_ioremap_resource_byname(pdev, "memory"); in hisi_spi_nor_probe()
439 if (IS_ERR(host->iobase)) in hisi_spi_nor_probe()
440 return PTR_ERR(host->iobase); in hisi_spi_nor_probe()
442 host->clk = devm_clk_get(dev, NULL); in hisi_spi_nor_probe()
443 if (IS_ERR(host->clk)) in hisi_spi_nor_probe()
444 return PTR_ERR(host->clk); in hisi_spi_nor_probe()
452 host->buffer = dmam_alloc_coherent(dev, HIFMC_DMA_MAX_LEN, in hisi_spi_nor_probe()
453 &host->dma_buffer, GFP_KERNEL); in hisi_spi_nor_probe()
454 if (!host->buffer) in hisi_spi_nor_probe()
455 return -ENOMEM; in hisi_spi_nor_probe()
457 ret = clk_prepare_enable(host->clk); in hisi_spi_nor_probe()
461 mutex_init(&host->lock); in hisi_spi_nor_probe()
465 mutex_destroy(&host->lock); in hisi_spi_nor_probe()
467 clk_disable_unprepare(host->clk); in hisi_spi_nor_probe()
476 mutex_destroy(&host->lock); in hisi_spi_nor_remove()
480 { .compatible = "hisilicon,fmc-spi-nor"},
487 .name = "hisi-sfc",
496 MODULE_DESCRIPTION("HiSilicon SPI Nor Flash Controller Driver");