460 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * SPI NOR driver for NXP SPI Flash Interface (SPIFI)4 *5 * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>6 *7 * Based on Freescale QuadSPI driver:8 * Copyright (C) 2013 Freescale Semiconductor, Inc.9 */10 11#include <linux/clk.h>12#include <linux/err.h>13#include <linux/io.h>14#include <linux/iopoll.h>15#include <linux/module.h>16#include <linux/mtd/mtd.h>17#include <linux/mtd/partitions.h>18#include <linux/mtd/spi-nor.h>19#include <linux/of.h>20#include <linux/platform_device.h>21#include <linux/spi/spi.h>22 23/* NXP SPIFI registers, bits and macros */24#define SPIFI_CTRL 0x00025#define SPIFI_CTRL_TIMEOUT(timeout) (timeout)26#define SPIFI_CTRL_CSHIGH(cshigh) ((cshigh) << 16)27#define SPIFI_CTRL_MODE3 BIT(23)28#define SPIFI_CTRL_DUAL BIT(28)29#define SPIFI_CTRL_FBCLK BIT(30)30#define SPIFI_CMD 0x00431#define SPIFI_CMD_DATALEN(dlen) ((dlen) & 0x3fff)32#define SPIFI_CMD_DOUT BIT(15)33#define SPIFI_CMD_INTLEN(ilen) ((ilen) << 16)34#define SPIFI_CMD_FIELDFORM(field) ((field) << 19)35#define SPIFI_CMD_FIELDFORM_ALL_SERIAL SPIFI_CMD_FIELDFORM(0x0)36#define SPIFI_CMD_FIELDFORM_QUAD_DUAL_DATA SPIFI_CMD_FIELDFORM(0x1)37#define SPIFI_CMD_FRAMEFORM(frame) ((frame) << 21)38#define SPIFI_CMD_FRAMEFORM_OPCODE_ONLY SPIFI_CMD_FRAMEFORM(0x1)39#define SPIFI_CMD_OPCODE(op) ((op) << 24)40#define SPIFI_ADDR 0x00841#define SPIFI_IDATA 0x00c42#define SPIFI_CLIMIT 0x01043#define SPIFI_DATA 0x01444#define SPIFI_MCMD 0x01845#define SPIFI_STAT 0x01c46#define SPIFI_STAT_MCINIT BIT(0)47#define SPIFI_STAT_CMD BIT(1)48#define SPIFI_STAT_RESET BIT(4)49 50#define SPI_NOR_MAX_ID_LEN 651 52struct nxp_spifi {53 struct device *dev;54 struct clk *clk_spifi;55 struct clk *clk_reg;56 void __iomem *io_base;57 void __iomem *flash_base;58 struct spi_nor nor;59 bool memory_mode;60 u32 mcmd;61};62 63static int nxp_spifi_wait_for_cmd(struct nxp_spifi *spifi)64{65 u8 stat;66 int ret;67 68 ret = readb_poll_timeout(spifi->io_base + SPIFI_STAT, stat,69 !(stat & SPIFI_STAT_CMD), 10, 30);70 if (ret)71 dev_warn(spifi->dev, "command timed out\n");72 73 return ret;74}75 76static int nxp_spifi_reset(struct nxp_spifi *spifi)77{78 u8 stat;79 int ret;80 81 writel(SPIFI_STAT_RESET, spifi->io_base + SPIFI_STAT);82 ret = readb_poll_timeout(spifi->io_base + SPIFI_STAT, stat,83 !(stat & SPIFI_STAT_RESET), 10, 30);84 if (ret)85 dev_warn(spifi->dev, "state reset timed out\n");86 87 return ret;88}89 90static int nxp_spifi_set_memory_mode_off(struct nxp_spifi *spifi)91{92 int ret;93 94 if (!spifi->memory_mode)95 return 0;96 97 ret = nxp_spifi_reset(spifi);98 if (ret)99 dev_err(spifi->dev, "unable to enter command mode\n");100 else101 spifi->memory_mode = false;102 103 return ret;104}105 106static int nxp_spifi_set_memory_mode_on(struct nxp_spifi *spifi)107{108 u8 stat;109 int ret;110 111 if (spifi->memory_mode)112 return 0;113 114 writel(spifi->mcmd, spifi->io_base + SPIFI_MCMD);115 ret = readb_poll_timeout(spifi->io_base + SPIFI_STAT, stat,116 stat & SPIFI_STAT_MCINIT, 10, 30);117 if (ret)118 dev_err(spifi->dev, "unable to enter memory mode\n");119 else120 spifi->memory_mode = true;121 122 return ret;123}124 125static int nxp_spifi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,126 size_t len)127{128 struct nxp_spifi *spifi = nor->priv;129 u32 cmd;130 int ret;131 132 ret = nxp_spifi_set_memory_mode_off(spifi);133 if (ret)134 return ret;135 136 cmd = SPIFI_CMD_DATALEN(len) |137 SPIFI_CMD_OPCODE(opcode) |138 SPIFI_CMD_FIELDFORM_ALL_SERIAL |139 SPIFI_CMD_FRAMEFORM_OPCODE_ONLY;140 writel(cmd, spifi->io_base + SPIFI_CMD);141 142 while (len--)143 *buf++ = readb(spifi->io_base + SPIFI_DATA);144 145 return nxp_spifi_wait_for_cmd(spifi);146}147 148static int nxp_spifi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,149 size_t len)150{151 struct nxp_spifi *spifi = nor->priv;152 u32 cmd;153 int ret;154 155 ret = nxp_spifi_set_memory_mode_off(spifi);156 if (ret)157 return ret;158 159 cmd = SPIFI_CMD_DOUT |160 SPIFI_CMD_DATALEN(len) |161 SPIFI_CMD_OPCODE(opcode) |162 SPIFI_CMD_FIELDFORM_ALL_SERIAL |163 SPIFI_CMD_FRAMEFORM_OPCODE_ONLY;164 writel(cmd, spifi->io_base + SPIFI_CMD);165 166 while (len--)167 writeb(*buf++, spifi->io_base + SPIFI_DATA);168 169 return nxp_spifi_wait_for_cmd(spifi);170}171 172static ssize_t nxp_spifi_read(struct spi_nor *nor, loff_t from, size_t len,173 u_char *buf)174{175 struct nxp_spifi *spifi = nor->priv;176 int ret;177 178 ret = nxp_spifi_set_memory_mode_on(spifi);179 if (ret)180 return ret;181 182 memcpy_fromio(buf, spifi->flash_base + from, len);183 184 return len;185}186 187static ssize_t nxp_spifi_write(struct spi_nor *nor, loff_t to, size_t len,188 const u_char *buf)189{190 struct nxp_spifi *spifi = nor->priv;191 u32 cmd;192 int ret;193 size_t i;194 195 ret = nxp_spifi_set_memory_mode_off(spifi);196 if (ret)197 return ret;198 199 writel(to, spifi->io_base + SPIFI_ADDR);200 201 cmd = SPIFI_CMD_DOUT |202 SPIFI_CMD_DATALEN(len) |203 SPIFI_CMD_FIELDFORM_ALL_SERIAL |204 SPIFI_CMD_OPCODE(nor->program_opcode) |205 SPIFI_CMD_FRAMEFORM(spifi->nor.addr_nbytes + 1);206 writel(cmd, spifi->io_base + SPIFI_CMD);207 208 for (i = 0; i < len; i++)209 writeb(buf[i], spifi->io_base + SPIFI_DATA);210 211 ret = nxp_spifi_wait_for_cmd(spifi);212 if (ret)213 return ret;214 215 return len;216}217 218static int nxp_spifi_erase(struct spi_nor *nor, loff_t offs)219{220 struct nxp_spifi *spifi = nor->priv;221 u32 cmd;222 int ret;223 224 ret = nxp_spifi_set_memory_mode_off(spifi);225 if (ret)226 return ret;227 228 writel(offs, spifi->io_base + SPIFI_ADDR);229 230 cmd = SPIFI_CMD_FIELDFORM_ALL_SERIAL |231 SPIFI_CMD_OPCODE(nor->erase_opcode) |232 SPIFI_CMD_FRAMEFORM(spifi->nor.addr_nbytes + 1);233 writel(cmd, spifi->io_base + SPIFI_CMD);234 235 return nxp_spifi_wait_for_cmd(spifi);236}237 238static int nxp_spifi_setup_memory_cmd(struct nxp_spifi *spifi)239{240 switch (spifi->nor.read_proto) {241 case SNOR_PROTO_1_1_1:242 spifi->mcmd = SPIFI_CMD_FIELDFORM_ALL_SERIAL;243 break;244 case SNOR_PROTO_1_1_2:245 case SNOR_PROTO_1_1_4:246 spifi->mcmd = SPIFI_CMD_FIELDFORM_QUAD_DUAL_DATA;247 break;248 default:249 dev_err(spifi->dev, "unsupported SPI read mode\n");250 return -EINVAL;251 }252 253 /* Memory mode supports address length between 1 and 4 */254 if (spifi->nor.addr_nbytes < 1 || spifi->nor.addr_nbytes > 4)255 return -EINVAL;256 257 spifi->mcmd |= SPIFI_CMD_OPCODE(spifi->nor.read_opcode) |258 SPIFI_CMD_INTLEN(spifi->nor.read_dummy / 8) |259 SPIFI_CMD_FRAMEFORM(spifi->nor.addr_nbytes + 1);260 261 return 0;262}263 264static void nxp_spifi_dummy_id_read(struct spi_nor *nor)265{266 u8 id[SPI_NOR_MAX_ID_LEN];267 nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,268 SPI_NOR_MAX_ID_LEN);269}270 271static const struct spi_nor_controller_ops nxp_spifi_controller_ops = {272 .read_reg = nxp_spifi_read_reg,273 .write_reg = nxp_spifi_write_reg,274 .read = nxp_spifi_read,275 .write = nxp_spifi_write,276 .erase = nxp_spifi_erase,277};278 279static int nxp_spifi_setup_flash(struct nxp_spifi *spifi,280 struct device_node *np)281{282 struct spi_nor_hwcaps hwcaps = {283 .mask = SNOR_HWCAPS_READ |284 SNOR_HWCAPS_READ_FAST |285 SNOR_HWCAPS_PP,286 };287 u32 ctrl, property;288 u16 mode = 0;289 int ret;290 291 if (!of_property_read_u32(np, "spi-rx-bus-width", &property)) {292 switch (property) {293 case 1:294 break;295 case 2:296 mode |= SPI_RX_DUAL;297 break;298 case 4:299 mode |= SPI_RX_QUAD;300 break;301 default:302 dev_err(spifi->dev, "unsupported rx-bus-width\n");303 return -EINVAL;304 }305 }306 307 if (of_property_read_bool(np, "spi-cpha"))308 mode |= SPI_CPHA;309 310 if (of_property_read_bool(np, "spi-cpol"))311 mode |= SPI_CPOL;312 313 /* Setup control register defaults */314 ctrl = SPIFI_CTRL_TIMEOUT(1000) |315 SPIFI_CTRL_CSHIGH(15) |316 SPIFI_CTRL_FBCLK;317 318 if (mode & SPI_RX_DUAL) {319 ctrl |= SPIFI_CTRL_DUAL;320 hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;321 } else if (mode & SPI_RX_QUAD) {322 ctrl &= ~SPIFI_CTRL_DUAL;323 hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;324 } else {325 ctrl |= SPIFI_CTRL_DUAL;326 }327 328 switch (mode & SPI_MODE_X_MASK) {329 case SPI_MODE_0:330 ctrl &= ~SPIFI_CTRL_MODE3;331 break;332 case SPI_MODE_3:333 ctrl |= SPIFI_CTRL_MODE3;334 break;335 default:336 dev_err(spifi->dev, "only mode 0 and 3 supported\n");337 return -EINVAL;338 }339 340 writel(ctrl, spifi->io_base + SPIFI_CTRL);341 342 spifi->nor.dev = spifi->dev;343 spi_nor_set_flash_node(&spifi->nor, np);344 spifi->nor.priv = spifi;345 spifi->nor.controller_ops = &nxp_spifi_controller_ops;346 347 /*348 * The first read on a hard reset isn't reliable so do a349 * dummy read of the id before calling spi_nor_scan().350 * The reason for this problem is unknown.351 *352 * The official NXP spifilib uses more or less the same353 * workaround that is applied here by reading the device354 * id multiple times.355 */356 nxp_spifi_dummy_id_read(&spifi->nor);357 358 ret = spi_nor_scan(&spifi->nor, NULL, &hwcaps);359 if (ret) {360 dev_err(spifi->dev, "device scan failed\n");361 return ret;362 }363 364 ret = nxp_spifi_setup_memory_cmd(spifi);365 if (ret) {366 dev_err(spifi->dev, "memory command setup failed\n");367 return ret;368 }369 370 ret = mtd_device_register(&spifi->nor.mtd, NULL, 0);371 if (ret) {372 dev_err(spifi->dev, "mtd device parse failed\n");373 return ret;374 }375 376 return 0;377}378 379static int nxp_spifi_probe(struct platform_device *pdev)380{381 struct device_node *flash_np;382 struct nxp_spifi *spifi;383 int ret;384 385 spifi = devm_kzalloc(&pdev->dev, sizeof(*spifi), GFP_KERNEL);386 if (!spifi)387 return -ENOMEM;388 389 spifi->io_base = devm_platform_ioremap_resource_byname(pdev, "spifi");390 if (IS_ERR(spifi->io_base))391 return PTR_ERR(spifi->io_base);392 393 spifi->flash_base = devm_platform_ioremap_resource_byname(pdev, "flash");394 if (IS_ERR(spifi->flash_base))395 return PTR_ERR(spifi->flash_base);396 397 spifi->clk_spifi = devm_clk_get_enabled(&pdev->dev, "spifi");398 if (IS_ERR(spifi->clk_spifi)) {399 dev_err(&pdev->dev, "spifi clock not found or unable to enable\n");400 return PTR_ERR(spifi->clk_spifi);401 }402 403 spifi->clk_reg = devm_clk_get_enabled(&pdev->dev, "reg");404 if (IS_ERR(spifi->clk_reg)) {405 dev_err(&pdev->dev, "reg clock not found or unable to enable\n");406 return PTR_ERR(spifi->clk_reg);407 }408 409 spifi->dev = &pdev->dev;410 platform_set_drvdata(pdev, spifi);411 412 /* Initialize and reset device */413 nxp_spifi_reset(spifi);414 writel(0, spifi->io_base + SPIFI_IDATA);415 writel(0, spifi->io_base + SPIFI_MCMD);416 nxp_spifi_reset(spifi);417 418 flash_np = of_get_next_available_child(pdev->dev.of_node, NULL);419 if (!flash_np) {420 dev_err(&pdev->dev, "no SPI flash device to configure\n");421 return -ENODEV;422 }423 424 ret = nxp_spifi_setup_flash(spifi, flash_np);425 of_node_put(flash_np);426 if (ret) {427 dev_err(&pdev->dev, "unable to setup flash chip\n");428 return ret;429 }430 431 return 0;432}433 434static void nxp_spifi_remove(struct platform_device *pdev)435{436 struct nxp_spifi *spifi = platform_get_drvdata(pdev);437 438 mtd_device_unregister(&spifi->nor.mtd);439}440 441static const struct of_device_id nxp_spifi_match[] = {442 {.compatible = "nxp,lpc1773-spifi"},443 { /* sentinel */ }444};445MODULE_DEVICE_TABLE(of, nxp_spifi_match);446 447static struct platform_driver nxp_spifi_driver = {448 .probe = nxp_spifi_probe,449 .remove_new = nxp_spifi_remove,450 .driver = {451 .name = "nxp-spifi",452 .of_match_table = nxp_spifi_match,453 },454};455module_platform_driver(nxp_spifi_driver);456 457MODULE_DESCRIPTION("NXP SPI Flash Interface driver");458MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");459MODULE_LICENSE("GPL v2");460