1 // SPDX-License-Identifier: GPL-2.0+ 2 // 3 // Driver for Amlogic Meson SPI flash controller (SPIFC) 4 // 5 // Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> 6 // 7 8 #include <linux/clk.h> 9 #include <linux/delay.h> 10 #include <linux/device.h> 11 #include <linux/io.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/platform_device.h> 16 #include <linux/pm_runtime.h> 17 #include <linux/regmap.h> 18 #include <linux/spi/spi.h> 19 #include <linux/types.h> 20 21 /* register map */ 22 #define REG_CMD 0x00 23 #define REG_ADDR 0x04 24 #define REG_CTRL 0x08 25 #define REG_CTRL1 0x0c 26 #define REG_STATUS 0x10 27 #define REG_CTRL2 0x14 28 #define REG_CLOCK 0x18 29 #define REG_USER 0x1c 30 #define REG_USER1 0x20 31 #define REG_USER2 0x24 32 #define REG_USER3 0x28 33 #define REG_USER4 0x2c 34 #define REG_SLAVE 0x30 35 #define REG_SLAVE1 0x34 36 #define REG_SLAVE2 0x38 37 #define REG_SLAVE3 0x3c 38 #define REG_C0 0x40 39 #define REG_B8 0x60 40 #define REG_MAX 0x7c 41 42 /* register fields */ 43 #define CMD_USER BIT(18) 44 #define CTRL_ENABLE_AHB BIT(17) 45 #define CLOCK_SOURCE BIT(31) 46 #define CLOCK_DIV_SHIFT 12 47 #define CLOCK_DIV_MASK (0x3f << CLOCK_DIV_SHIFT) 48 #define CLOCK_CNT_HIGH_SHIFT 6 49 #define CLOCK_CNT_HIGH_MASK (0x3f << CLOCK_CNT_HIGH_SHIFT) 50 #define CLOCK_CNT_LOW_SHIFT 0 51 #define CLOCK_CNT_LOW_MASK (0x3f << CLOCK_CNT_LOW_SHIFT) 52 #define USER_DIN_EN_MS BIT(0) 53 #define USER_CMP_MODE BIT(2) 54 #define USER_UC_DOUT_SEL BIT(27) 55 #define USER_UC_DIN_SEL BIT(28) 56 #define USER_UC_MASK ((BIT(5) - 1) << 27) 57 #define USER1_BN_UC_DOUT_SHIFT 17 58 #define USER1_BN_UC_DOUT_MASK (0xff << 16) 59 #define USER1_BN_UC_DIN_SHIFT 8 60 #define USER1_BN_UC_DIN_MASK (0xff << 8) 61 #define USER4_CS_ACT BIT(30) 62 #define SLAVE_TRST_DONE BIT(4) 63 #define SLAVE_OP_MODE BIT(30) 64 #define SLAVE_SW_RST BIT(31) 65 66 #define SPIFC_BUFFER_SIZE 64 67 68 /** 69 * struct meson_spifc 70 * @master: the SPI master 71 * @regmap: regmap for device registers 72 * @clk: input clock of the built-in baud rate generator 73 * @dev: the device structure 74 */ 75 struct meson_spifc { 76 struct spi_master *master; 77 struct regmap *regmap; 78 struct clk *clk; 79 struct device *dev; 80 }; 81 82 static const struct regmap_config spifc_regmap_config = { 83 .reg_bits = 32, 84 .val_bits = 32, 85 .reg_stride = 4, 86 .max_register = REG_MAX, 87 }; 88 89 /** 90 * meson_spifc_wait_ready() - wait for the current operation to terminate 91 * @spifc: the Meson SPI device 92 * Return: 0 on success, a negative value on error 93 */ 94 static int meson_spifc_wait_ready(struct meson_spifc *spifc) 95 { 96 unsigned long deadline = jiffies + msecs_to_jiffies(5); 97 u32 data; 98 99 do { 100 regmap_read(spifc->regmap, REG_SLAVE, &data); 101 if (data & SLAVE_TRST_DONE) 102 return 0; 103 cond_resched(); 104 } while (!time_after(jiffies, deadline)); 105 106 return -ETIMEDOUT; 107 } 108 109 /** 110 * meson_spifc_drain_buffer() - copy data from device buffer to memory 111 * @spifc: the Meson SPI device 112 * @buf: the destination buffer 113 * @len: number of bytes to copy 114 */ 115 static void meson_spifc_drain_buffer(struct meson_spifc *spifc, u8 *buf, 116 int len) 117 { 118 u32 data; 119 int i = 0; 120 121 while (i < len) { 122 regmap_read(spifc->regmap, REG_C0 + i, &data); 123 124 if (len - i >= 4) { 125 *((u32 *)buf) = data; 126 buf += 4; 127 } else { 128 memcpy(buf, &data, len - i); 129 break; 130 } 131 i += 4; 132 } 133 } 134 135 /** 136 * meson_spifc_fill_buffer() - copy data from memory to device buffer 137 * @spifc: the Meson SPI device 138 * @buf: the source buffer 139 * @len: number of bytes to copy 140 */ 141 static void meson_spifc_fill_buffer(struct meson_spifc *spifc, const u8 *buf, 142 int len) 143 { 144 u32 data; 145 int i = 0; 146 147 while (i < len) { 148 if (len - i >= 4) 149 data = *(u32 *)buf; 150 else 151 memcpy(&data, buf, len - i); 152 153 regmap_write(spifc->regmap, REG_C0 + i, data); 154 155 buf += 4; 156 i += 4; 157 } 158 } 159 160 /** 161 * meson_spifc_setup_speed() - program the clock divider 162 * @spifc: the Meson SPI device 163 * @speed: desired speed in Hz 164 */ 165 static void meson_spifc_setup_speed(struct meson_spifc *spifc, u32 speed) 166 { 167 unsigned long parent, value; 168 int n; 169 170 parent = clk_get_rate(spifc->clk); 171 n = max_t(int, parent / speed - 1, 1); 172 173 dev_dbg(spifc->dev, "parent %lu, speed %u, n %d\n", parent, 174 speed, n); 175 176 value = (n << CLOCK_DIV_SHIFT) & CLOCK_DIV_MASK; 177 value |= (n << CLOCK_CNT_LOW_SHIFT) & CLOCK_CNT_LOW_MASK; 178 value |= (((n + 1) / 2 - 1) << CLOCK_CNT_HIGH_SHIFT) & 179 CLOCK_CNT_HIGH_MASK; 180 181 regmap_write(spifc->regmap, REG_CLOCK, value); 182 } 183 184 /** 185 * meson_spifc_txrx() - transfer a chunk of data 186 * @spifc: the Meson SPI device 187 * @xfer: the current SPI transfer 188 * @offset: offset of the data to transfer 189 * @len: length of the data to transfer 190 * @last_xfer: whether this is the last transfer of the message 191 * @last_chunk: whether this is the last chunk of the transfer 192 * Return: 0 on success, a negative value on error 193 */ 194 static int meson_spifc_txrx(struct meson_spifc *spifc, 195 struct spi_transfer *xfer, 196 int offset, int len, bool last_xfer, 197 bool last_chunk) 198 { 199 bool keep_cs = true; 200 int ret; 201 202 if (xfer->tx_buf) 203 meson_spifc_fill_buffer(spifc, xfer->tx_buf + offset, len); 204 205 /* enable DOUT stage */ 206 regmap_update_bits(spifc->regmap, REG_USER, USER_UC_MASK, 207 USER_UC_DOUT_SEL); 208 regmap_write(spifc->regmap, REG_USER1, 209 (8 * len - 1) << USER1_BN_UC_DOUT_SHIFT); 210 211 /* enable data input during DOUT */ 212 regmap_update_bits(spifc->regmap, REG_USER, USER_DIN_EN_MS, 213 USER_DIN_EN_MS); 214 215 if (last_chunk) { 216 if (last_xfer) 217 keep_cs = xfer->cs_change; 218 else 219 keep_cs = !xfer->cs_change; 220 } 221 222 regmap_update_bits(spifc->regmap, REG_USER4, USER4_CS_ACT, 223 keep_cs ? USER4_CS_ACT : 0); 224 225 /* clear transition done bit */ 226 regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_TRST_DONE, 0); 227 /* start transfer */ 228 regmap_update_bits(spifc->regmap, REG_CMD, CMD_USER, CMD_USER); 229 230 ret = meson_spifc_wait_ready(spifc); 231 232 if (!ret && xfer->rx_buf) 233 meson_spifc_drain_buffer(spifc, xfer->rx_buf + offset, len); 234 235 return ret; 236 } 237 238 /** 239 * meson_spifc_transfer_one() - perform a single transfer 240 * @master: the SPI master 241 * @spi: the SPI device 242 * @xfer: the current SPI transfer 243 * Return: 0 on success, a negative value on error 244 */ 245 static int meson_spifc_transfer_one(struct spi_master *master, 246 struct spi_device *spi, 247 struct spi_transfer *xfer) 248 { 249 struct meson_spifc *spifc = spi_master_get_devdata(master); 250 int len, done = 0, ret = 0; 251 252 meson_spifc_setup_speed(spifc, xfer->speed_hz); 253 254 regmap_update_bits(spifc->regmap, REG_CTRL, CTRL_ENABLE_AHB, 0); 255 256 while (done < xfer->len && !ret) { 257 len = min_t(int, xfer->len - done, SPIFC_BUFFER_SIZE); 258 ret = meson_spifc_txrx(spifc, xfer, done, len, 259 spi_transfer_is_last(master, xfer), 260 done + len >= xfer->len); 261 done += len; 262 } 263 264 regmap_update_bits(spifc->regmap, REG_CTRL, CTRL_ENABLE_AHB, 265 CTRL_ENABLE_AHB); 266 267 return ret; 268 } 269 270 /** 271 * meson_spifc_hw_init() - reset and initialize the SPI controller 272 * @spifc: the Meson SPI device 273 */ 274 static void meson_spifc_hw_init(struct meson_spifc *spifc) 275 { 276 /* reset device */ 277 regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_SW_RST, 278 SLAVE_SW_RST); 279 /* disable compatible mode */ 280 regmap_update_bits(spifc->regmap, REG_USER, USER_CMP_MODE, 0); 281 /* set master mode */ 282 regmap_update_bits(spifc->regmap, REG_SLAVE, SLAVE_OP_MODE, 0); 283 } 284 285 static int meson_spifc_probe(struct platform_device *pdev) 286 { 287 struct spi_master *master; 288 struct meson_spifc *spifc; 289 void __iomem *base; 290 unsigned int rate; 291 int ret = 0; 292 293 master = spi_alloc_master(&pdev->dev, sizeof(struct meson_spifc)); 294 if (!master) 295 return -ENOMEM; 296 297 platform_set_drvdata(pdev, master); 298 299 spifc = spi_master_get_devdata(master); 300 spifc->dev = &pdev->dev; 301 302 base = devm_platform_ioremap_resource(pdev, 0); 303 if (IS_ERR(base)) { 304 ret = PTR_ERR(base); 305 goto out_err; 306 } 307 308 spifc->regmap = devm_regmap_init_mmio(spifc->dev, base, 309 &spifc_regmap_config); 310 if (IS_ERR(spifc->regmap)) { 311 ret = PTR_ERR(spifc->regmap); 312 goto out_err; 313 } 314 315 spifc->clk = devm_clk_get(spifc->dev, NULL); 316 if (IS_ERR(spifc->clk)) { 317 dev_err(spifc->dev, "missing clock\n"); 318 ret = PTR_ERR(spifc->clk); 319 goto out_err; 320 } 321 322 ret = clk_prepare_enable(spifc->clk); 323 if (ret) { 324 dev_err(spifc->dev, "can't prepare clock\n"); 325 goto out_err; 326 } 327 328 rate = clk_get_rate(spifc->clk); 329 330 master->num_chipselect = 1; 331 master->dev.of_node = pdev->dev.of_node; 332 master->bits_per_word_mask = SPI_BPW_MASK(8); 333 master->auto_runtime_pm = true; 334 master->transfer_one = meson_spifc_transfer_one; 335 master->min_speed_hz = rate >> 6; 336 master->max_speed_hz = rate >> 1; 337 338 meson_spifc_hw_init(spifc); 339 340 pm_runtime_set_active(spifc->dev); 341 pm_runtime_enable(spifc->dev); 342 343 ret = devm_spi_register_master(spifc->dev, master); 344 if (ret) { 345 dev_err(spifc->dev, "failed to register spi master\n"); 346 goto out_clk; 347 } 348 349 return 0; 350 out_clk: 351 clk_disable_unprepare(spifc->clk); 352 pm_runtime_disable(spifc->dev); 353 out_err: 354 spi_master_put(master); 355 return ret; 356 } 357 358 static void meson_spifc_remove(struct platform_device *pdev) 359 { 360 struct spi_master *master = platform_get_drvdata(pdev); 361 struct meson_spifc *spifc = spi_master_get_devdata(master); 362 363 pm_runtime_get_sync(&pdev->dev); 364 clk_disable_unprepare(spifc->clk); 365 pm_runtime_disable(&pdev->dev); 366 } 367 368 #ifdef CONFIG_PM_SLEEP 369 static int meson_spifc_suspend(struct device *dev) 370 { 371 struct spi_master *master = dev_get_drvdata(dev); 372 struct meson_spifc *spifc = spi_master_get_devdata(master); 373 int ret; 374 375 ret = spi_master_suspend(master); 376 if (ret) 377 return ret; 378 379 if (!pm_runtime_suspended(dev)) 380 clk_disable_unprepare(spifc->clk); 381 382 return 0; 383 } 384 385 static int meson_spifc_resume(struct device *dev) 386 { 387 struct spi_master *master = dev_get_drvdata(dev); 388 struct meson_spifc *spifc = spi_master_get_devdata(master); 389 int ret; 390 391 if (!pm_runtime_suspended(dev)) { 392 ret = clk_prepare_enable(spifc->clk); 393 if (ret) 394 return ret; 395 } 396 397 meson_spifc_hw_init(spifc); 398 399 ret = spi_master_resume(master); 400 if (ret) 401 clk_disable_unprepare(spifc->clk); 402 403 return ret; 404 } 405 #endif /* CONFIG_PM_SLEEP */ 406 407 #ifdef CONFIG_PM 408 static int meson_spifc_runtime_suspend(struct device *dev) 409 { 410 struct spi_master *master = dev_get_drvdata(dev); 411 struct meson_spifc *spifc = spi_master_get_devdata(master); 412 413 clk_disable_unprepare(spifc->clk); 414 415 return 0; 416 } 417 418 static int meson_spifc_runtime_resume(struct device *dev) 419 { 420 struct spi_master *master = dev_get_drvdata(dev); 421 struct meson_spifc *spifc = spi_master_get_devdata(master); 422 423 return clk_prepare_enable(spifc->clk); 424 } 425 #endif /* CONFIG_PM */ 426 427 static const struct dev_pm_ops meson_spifc_pm_ops = { 428 SET_SYSTEM_SLEEP_PM_OPS(meson_spifc_suspend, meson_spifc_resume) 429 SET_RUNTIME_PM_OPS(meson_spifc_runtime_suspend, 430 meson_spifc_runtime_resume, 431 NULL) 432 }; 433 434 static const struct of_device_id meson_spifc_dt_match[] = { 435 { .compatible = "amlogic,meson6-spifc", }, 436 { .compatible = "amlogic,meson-gxbb-spifc", }, 437 { }, 438 }; 439 MODULE_DEVICE_TABLE(of, meson_spifc_dt_match); 440 441 static struct platform_driver meson_spifc_driver = { 442 .probe = meson_spifc_probe, 443 .remove_new = meson_spifc_remove, 444 .driver = { 445 .name = "meson-spifc", 446 .of_match_table = of_match_ptr(meson_spifc_dt_match), 447 .pm = &meson_spifc_pm_ops, 448 }, 449 }; 450 451 module_platform_driver(meson_spifc_driver); 452 453 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); 454 MODULE_DESCRIPTION("Amlogic Meson SPIFC driver"); 455 MODULE_LICENSE("GPL v2"); 456