1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * SG2044 SPI NOR controller driver 4 * 5 * Copyright (c) 2025 Longbin Li <looong.bin@gmail.com> 6 */ 7 8 #include <linux/bitfield.h> 9 #include <linux/clk.h> 10 #include <linux/iopoll.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/platform_device.h> 14 #include <linux/spi/spi-mem.h> 15 16 /* Hardware register definitions */ 17 #define SPIFMC_CTRL 0x00 18 #define SPIFMC_CTRL_CPHA BIT(12) 19 #define SPIFMC_CTRL_CPOL BIT(13) 20 #define SPIFMC_CTRL_HOLD_OL BIT(14) 21 #define SPIFMC_CTRL_WP_OL BIT(15) 22 #define SPIFMC_CTRL_LSBF BIT(20) 23 #define SPIFMC_CTRL_SRST BIT(21) 24 #define SPIFMC_CTRL_SCK_DIV_SHIFT 0 25 #define SPIFMC_CTRL_FRAME_LEN_SHIFT 16 26 #define SPIFMC_CTRL_SCK_DIV_MASK 0x7FF 27 28 #define SPIFMC_CE_CTRL 0x04 29 #define SPIFMC_CE_CTRL_CEMANUAL BIT(0) 30 #define SPIFMC_CE_CTRL_CEMANUAL_EN BIT(1) 31 32 #define SPIFMC_DLY_CTRL 0x08 33 #define SPIFMC_CTRL_FM_INTVL_MASK 0x000f 34 #define SPIFMC_CTRL_FM_INTVL BIT(0) 35 #define SPIFMC_CTRL_CET_MASK 0x0f00 36 #define SPIFMC_CTRL_CET BIT(8) 37 38 #define SPIFMC_DMMR 0x0c 39 40 #define SPIFMC_TRAN_CSR 0x10 41 #define SPIFMC_TRAN_CSR_TRAN_MODE_MASK GENMASK(1, 0) 42 #define SPIFMC_TRAN_CSR_TRAN_MODE_RX BIT(0) 43 #define SPIFMC_TRAN_CSR_TRAN_MODE_TX BIT(1) 44 #define SPIFMC_TRAN_CSR_FAST_MODE BIT(3) 45 #define SPIFMC_TRAN_CSR_BUS_WIDTH_1_BIT (0x00 << 4) 46 #define SPIFMC_TRAN_CSR_BUS_WIDTH_2_BIT (0x01 << 4) 47 #define SPIFMC_TRAN_CSR_BUS_WIDTH_4_BIT (0x02 << 4) 48 #define SPIFMC_TRAN_CSR_DMA_EN BIT(6) 49 #define SPIFMC_TRAN_CSR_MISO_LEVEL BIT(7) 50 #define SPIFMC_TRAN_CSR_ADDR_BYTES_MASK GENMASK(10, 8) 51 #define SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT 8 52 #define SPIFMC_TRAN_CSR_WITH_CMD BIT(11) 53 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_MASK GENMASK(13, 12) 54 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE (0x00 << 12) 55 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_2_BYTE (0x01 << 12) 56 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_4_BYTE (0x02 << 12) 57 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE (0x03 << 12) 58 #define SPIFMC_TRAN_CSR_GO_BUSY BIT(15) 59 #define SPIFMC_TRAN_CSR_ADDR4B_SHIFT 20 60 #define SPIFMC_TRAN_CSR_CMD4B_SHIFT 21 61 62 #define SPIFMC_TRAN_NUM 0x14 63 #define SPIFMC_FIFO_PORT 0x18 64 #define SPIFMC_FIFO_PT 0x20 65 66 #define SPIFMC_INT_STS 0x28 67 #define SPIFMC_INT_TRAN_DONE BIT(0) 68 #define SPIFMC_INT_RD_FIFO BIT(2) 69 #define SPIFMC_INT_WR_FIFO BIT(3) 70 #define SPIFMC_INT_RX_FRAME BIT(4) 71 #define SPIFMC_INT_TX_FRAME BIT(5) 72 73 #define SPIFMC_INT_EN 0x2c 74 #define SPIFMC_INT_TRAN_DONE_EN BIT(0) 75 #define SPIFMC_INT_RD_FIFO_EN BIT(2) 76 #define SPIFMC_INT_WR_FIFO_EN BIT(3) 77 #define SPIFMC_INT_RX_FRAME_EN BIT(4) 78 #define SPIFMC_INT_TX_FRAME_EN BIT(5) 79 80 #define SPIFMC_OPT 0x030 81 #define SPIFMC_OPT_DISABLE_FIFO_FLUSH BIT(1) 82 83 #define SPIFMC_MAX_FIFO_DEPTH 8 84 85 #define SPIFMC_MAX_READ_SIZE 0x10000 86 87 struct sg204x_spifmc_chip_info { 88 bool has_opt_reg; 89 u32 rd_fifo_int_trigger_level; 90 }; 91 92 struct sg2044_spifmc { 93 struct spi_controller *ctrl; 94 void __iomem *io_base; 95 struct device *dev; 96 struct mutex lock; 97 struct clk *clk; 98 const struct sg204x_spifmc_chip_info *chip_info; 99 }; 100 101 static int sg2044_spifmc_wait_int(struct sg2044_spifmc *spifmc, u8 int_type) 102 { 103 u32 stat; 104 105 return readl_poll_timeout(spifmc->io_base + SPIFMC_INT_STS, stat, 106 (stat & int_type), 0, 1000000); 107 } 108 109 static int sg2044_spifmc_wait_xfer_size(struct sg2044_spifmc *spifmc, 110 int xfer_size) 111 { 112 u8 stat; 113 114 return readl_poll_timeout(spifmc->io_base + SPIFMC_FIFO_PT, stat, 115 ((stat & 0xf) == xfer_size), 1, 1000000); 116 } 117 118 static u32 sg2044_spifmc_init_reg(struct sg2044_spifmc *spifmc) 119 { 120 u32 reg; 121 122 reg = readl(spifmc->io_base + SPIFMC_TRAN_CSR); 123 reg &= ~(SPIFMC_TRAN_CSR_TRAN_MODE_MASK | 124 SPIFMC_TRAN_CSR_FAST_MODE | 125 SPIFMC_TRAN_CSR_BUS_WIDTH_2_BIT | 126 SPIFMC_TRAN_CSR_BUS_WIDTH_4_BIT | 127 SPIFMC_TRAN_CSR_DMA_EN | 128 SPIFMC_TRAN_CSR_ADDR_BYTES_MASK | 129 SPIFMC_TRAN_CSR_WITH_CMD | 130 SPIFMC_TRAN_CSR_FIFO_TRG_LVL_MASK); 131 132 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR); 133 134 return reg; 135 } 136 137 static ssize_t sg2044_spifmc_read_64k(struct sg2044_spifmc *spifmc, 138 const struct spi_mem_op *op, loff_t from, 139 size_t len, u_char *buf) 140 { 141 int xfer_size, offset; 142 u32 reg; 143 int ret; 144 int i; 145 146 reg = sg2044_spifmc_init_reg(spifmc); 147 reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT; 148 reg |= spifmc->chip_info->rd_fifo_int_trigger_level; 149 reg |= SPIFMC_TRAN_CSR_WITH_CMD; 150 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX; 151 152 writel(0, spifmc->io_base + SPIFMC_FIFO_PT); 153 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT); 154 155 for (i = op->addr.nbytes - 1; i >= 0; i--) 156 writeb((from >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT); 157 158 for (i = 0; i < op->dummy.nbytes; i++) 159 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT); 160 161 writel(len, spifmc->io_base + SPIFMC_TRAN_NUM); 162 writel(0, spifmc->io_base + SPIFMC_INT_STS); 163 reg |= SPIFMC_TRAN_CSR_GO_BUSY; 164 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR); 165 166 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_RD_FIFO); 167 if (ret < 0) 168 return ret; 169 170 offset = 0; 171 while (offset < len) { 172 xfer_size = min_t(size_t, SPIFMC_MAX_FIFO_DEPTH, len - offset); 173 174 ret = sg2044_spifmc_wait_xfer_size(spifmc, xfer_size); 175 if (ret < 0) 176 return ret; 177 178 for (i = 0; i < xfer_size; i++) 179 buf[i + offset] = readb(spifmc->io_base + SPIFMC_FIFO_PORT); 180 181 offset += xfer_size; 182 } 183 184 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE); 185 if (ret < 0) 186 return ret; 187 188 writel(0, spifmc->io_base + SPIFMC_FIFO_PT); 189 190 return len; 191 } 192 193 static ssize_t sg2044_spifmc_read(struct sg2044_spifmc *spifmc, 194 const struct spi_mem_op *op) 195 { 196 size_t xfer_size; 197 size_t offset; 198 loff_t from = op->addr.val; 199 size_t len = op->data.nbytes; 200 int ret; 201 u8 *din = op->data.buf.in; 202 203 offset = 0; 204 while (offset < len) { 205 xfer_size = min_t(size_t, SPIFMC_MAX_READ_SIZE, len - offset); 206 207 ret = sg2044_spifmc_read_64k(spifmc, op, from, xfer_size, din); 208 if (ret < 0) 209 return ret; 210 211 offset += xfer_size; 212 din += xfer_size; 213 from += xfer_size; 214 } 215 216 return 0; 217 } 218 219 static ssize_t sg2044_spifmc_write(struct sg2044_spifmc *spifmc, 220 const struct spi_mem_op *op) 221 { 222 size_t xfer_size; 223 const u8 *dout = op->data.buf.out; 224 int i, offset; 225 int ret; 226 u32 reg; 227 228 reg = sg2044_spifmc_init_reg(spifmc); 229 reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT; 230 reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE; 231 reg |= SPIFMC_TRAN_CSR_WITH_CMD; 232 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX; 233 234 writel(0, spifmc->io_base + SPIFMC_FIFO_PT); 235 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT); 236 237 for (i = op->addr.nbytes - 1; i >= 0; i--) 238 writeb((op->addr.val >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT); 239 240 for (i = 0; i < op->dummy.nbytes; i++) 241 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT); 242 243 writel(0, spifmc->io_base + SPIFMC_INT_STS); 244 writel(op->data.nbytes, spifmc->io_base + SPIFMC_TRAN_NUM); 245 reg |= SPIFMC_TRAN_CSR_GO_BUSY; 246 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR); 247 248 ret = sg2044_spifmc_wait_xfer_size(spifmc, 0); 249 if (ret < 0) 250 return ret; 251 252 writel(0, spifmc->io_base + SPIFMC_FIFO_PT); 253 254 offset = 0; 255 while (offset < op->data.nbytes) { 256 xfer_size = min_t(size_t, SPIFMC_MAX_FIFO_DEPTH, op->data.nbytes - offset); 257 258 ret = sg2044_spifmc_wait_xfer_size(spifmc, 0); 259 if (ret < 0) 260 return ret; 261 262 for (i = 0; i < xfer_size; i++) 263 writeb(dout[i + offset], spifmc->io_base + SPIFMC_FIFO_PORT); 264 265 offset += xfer_size; 266 } 267 268 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE); 269 if (ret < 0) 270 return ret; 271 272 writel(0, spifmc->io_base + SPIFMC_FIFO_PT); 273 274 return 0; 275 } 276 277 static ssize_t sg2044_spifmc_tran_cmd(struct sg2044_spifmc *spifmc, 278 const struct spi_mem_op *op) 279 { 280 int i, ret; 281 u32 reg; 282 283 reg = sg2044_spifmc_init_reg(spifmc); 284 reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT; 285 reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE; 286 reg |= SPIFMC_TRAN_CSR_WITH_CMD; 287 288 writel(0, spifmc->io_base + SPIFMC_FIFO_PT); 289 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT); 290 291 for (i = op->addr.nbytes - 1; i >= 0; i--) 292 writeb((op->addr.val >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT); 293 294 for (i = 0; i < op->dummy.nbytes; i++) 295 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT); 296 297 writel(0, spifmc->io_base + SPIFMC_INT_STS); 298 reg |= SPIFMC_TRAN_CSR_GO_BUSY; 299 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR); 300 301 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE); 302 if (ret < 0) 303 return ret; 304 305 writel(0, spifmc->io_base + SPIFMC_FIFO_PT); 306 307 return 0; 308 } 309 310 static void sg2044_spifmc_trans(struct sg2044_spifmc *spifmc, 311 const struct spi_mem_op *op) 312 { 313 if (op->data.dir == SPI_MEM_DATA_IN) 314 sg2044_spifmc_read(spifmc, op); 315 else if (op->data.dir == SPI_MEM_DATA_OUT) 316 sg2044_spifmc_write(spifmc, op); 317 else 318 sg2044_spifmc_tran_cmd(spifmc, op); 319 } 320 321 static ssize_t sg2044_spifmc_trans_reg(struct sg2044_spifmc *spifmc, 322 const struct spi_mem_op *op) 323 { 324 const u8 *dout = NULL; 325 u8 *din = NULL; 326 size_t len = op->data.nbytes; 327 int ret, i; 328 u32 reg; 329 330 if (op->data.dir == SPI_MEM_DATA_IN) 331 din = op->data.buf.in; 332 else 333 dout = op->data.buf.out; 334 335 reg = sg2044_spifmc_init_reg(spifmc); 336 reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE; 337 reg |= SPIFMC_TRAN_CSR_WITH_CMD; 338 339 if (din) { 340 reg |= SPIFMC_TRAN_CSR_BUS_WIDTH_1_BIT; 341 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX; 342 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX; 343 344 if (spifmc->chip_info->has_opt_reg) 345 writel(SPIFMC_OPT_DISABLE_FIFO_FLUSH, spifmc->io_base + SPIFMC_OPT); 346 } else { 347 /* 348 * If write values to the Status Register, 349 * configure TRAN_CSR register as the same as 350 * sg2044_spifmc_read_reg. 351 */ 352 if (op->cmd.opcode == 0x01) { 353 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX; 354 reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX; 355 writel(len, spifmc->io_base + SPIFMC_TRAN_NUM); 356 } 357 } 358 359 writel(0, spifmc->io_base + SPIFMC_FIFO_PT); 360 writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT); 361 362 for (i = 0; i < len; i++) { 363 if (din) 364 writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT); 365 else 366 writeb(dout[i], spifmc->io_base + SPIFMC_FIFO_PORT); 367 } 368 369 writel(0, spifmc->io_base + SPIFMC_INT_STS); 370 writel(len, spifmc->io_base + SPIFMC_TRAN_NUM); 371 reg |= SPIFMC_TRAN_CSR_GO_BUSY; 372 writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR); 373 374 ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE); 375 if (ret < 0) 376 return ret; 377 378 if (din) { 379 while (len--) 380 *din++ = readb(spifmc->io_base + SPIFMC_FIFO_PORT); 381 } 382 383 writel(0, spifmc->io_base + SPIFMC_FIFO_PT); 384 385 return 0; 386 } 387 388 static int sg2044_spifmc_exec_op(struct spi_mem *mem, 389 const struct spi_mem_op *op) 390 { 391 struct sg2044_spifmc *spifmc; 392 393 spifmc = spi_controller_get_devdata(mem->spi->controller); 394 395 mutex_lock(&spifmc->lock); 396 397 if (op->addr.nbytes == 0) 398 sg2044_spifmc_trans_reg(spifmc, op); 399 else 400 sg2044_spifmc_trans(spifmc, op); 401 402 mutex_unlock(&spifmc->lock); 403 404 return 0; 405 } 406 407 static const struct spi_controller_mem_ops sg2044_spifmc_mem_ops = { 408 .exec_op = sg2044_spifmc_exec_op, 409 }; 410 411 static void sg2044_spifmc_init(struct sg2044_spifmc *spifmc) 412 { 413 u32 tran_csr; 414 u32 reg; 415 416 writel(0, spifmc->io_base + SPIFMC_DMMR); 417 418 reg = readl(spifmc->io_base + SPIFMC_CTRL); 419 reg |= SPIFMC_CTRL_SRST; 420 reg &= ~(SPIFMC_CTRL_SCK_DIV_MASK); 421 reg |= 1; 422 writel(reg, spifmc->io_base + SPIFMC_CTRL); 423 424 writel(0, spifmc->io_base + SPIFMC_CE_CTRL); 425 426 tran_csr = readl(spifmc->io_base + SPIFMC_TRAN_CSR); 427 tran_csr |= (0 << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT); 428 tran_csr |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_4_BYTE; 429 tran_csr |= SPIFMC_TRAN_CSR_WITH_CMD; 430 writel(tran_csr, spifmc->io_base + SPIFMC_TRAN_CSR); 431 } 432 433 static int sg2044_spifmc_probe(struct platform_device *pdev) 434 { 435 struct device *dev = &pdev->dev; 436 struct spi_controller *ctrl; 437 struct sg2044_spifmc *spifmc; 438 int ret; 439 440 ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*spifmc)); 441 if (!ctrl) 442 return -ENOMEM; 443 444 spifmc = spi_controller_get_devdata(ctrl); 445 446 spifmc->clk = devm_clk_get_enabled(&pdev->dev, NULL); 447 if (IS_ERR(spifmc->clk)) 448 return dev_err_probe(dev, PTR_ERR(spifmc->clk), "Cannot get and enable AHB clock\n"); 449 450 spifmc->dev = &pdev->dev; 451 spifmc->ctrl = ctrl; 452 453 spifmc->io_base = devm_platform_ioremap_resource(pdev, 0); 454 if (IS_ERR(spifmc->io_base)) 455 return PTR_ERR(spifmc->io_base); 456 457 ctrl->num_chipselect = 1; 458 ctrl->dev.of_node = pdev->dev.of_node; 459 ctrl->bits_per_word_mask = SPI_BPW_MASK(8); 460 ctrl->auto_runtime_pm = false; 461 ctrl->mem_ops = &sg2044_spifmc_mem_ops; 462 ctrl->mode_bits = SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD; 463 464 ret = devm_mutex_init(dev, &spifmc->lock); 465 if (ret) 466 return ret; 467 spifmc->chip_info = device_get_match_data(&pdev->dev); 468 if (!spifmc->chip_info) { 469 dev_err(&pdev->dev, "Failed to get specific chip info\n"); 470 return -EINVAL; 471 } 472 473 sg2044_spifmc_init(spifmc); 474 sg2044_spifmc_init_reg(spifmc); 475 476 ret = devm_spi_register_controller(&pdev->dev, ctrl); 477 if (ret) 478 return dev_err_probe(dev, ret, "spi_register_controller failed\n"); 479 480 return 0; 481 } 482 483 static const struct sg204x_spifmc_chip_info sg2044_chip_info = { 484 .has_opt_reg = true, 485 .rd_fifo_int_trigger_level = SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE, 486 }; 487 488 static const struct sg204x_spifmc_chip_info sg2042_chip_info = { 489 .has_opt_reg = false, 490 .rd_fifo_int_trigger_level = SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE, 491 }; 492 493 static const struct of_device_id sg2044_spifmc_match[] = { 494 { .compatible = "sophgo,sg2044-spifmc-nor", .data = &sg2044_chip_info }, 495 { .compatible = "sophgo,sg2042-spifmc-nor", .data = &sg2042_chip_info }, 496 { /* sentinel */ } 497 }; 498 MODULE_DEVICE_TABLE(of, sg2044_spifmc_match); 499 500 static struct platform_driver sg2044_nor_driver = { 501 .driver = { 502 .name = "sg2044,spifmc-nor", 503 .of_match_table = sg2044_spifmc_match, 504 }, 505 .probe = sg2044_spifmc_probe, 506 }; 507 module_platform_driver(sg2044_nor_driver); 508 509 MODULE_DESCRIPTION("SG2044 SPI NOR controller driver"); 510 MODULE_AUTHOR("Longbin Li <looong.bin@gmail.com>"); 511 MODULE_LICENSE("GPL"); 512