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 * @device: 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 struct resource *res; 290 void __iomem *base; 291 unsigned int rate; 292 int ret = 0; 293 294 master = spi_alloc_master(&pdev->dev, sizeof(struct meson_spifc)); 295 if (!master) 296 return -ENOMEM; 297 298 platform_set_drvdata(pdev, master); 299 300 spifc = spi_master_get_devdata(master); 301 spifc->dev = &pdev->dev; 302 303 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 304 base = devm_ioremap_resource(spifc->dev, res); 305 if (IS_ERR(base)) { 306 ret = PTR_ERR(base); 307 goto out_err; 308 } 309 310 spifc->regmap = devm_regmap_init_mmio(spifc->dev, base, 311 &spifc_regmap_config); 312 if (IS_ERR(spifc->regmap)) { 313 ret = PTR_ERR(spifc->regmap); 314 goto out_err; 315 } 316 317 spifc->clk = devm_clk_get(spifc->dev, NULL); 318 if (IS_ERR(spifc->clk)) { 319 dev_err(spifc->dev, "missing clock\n"); 320 ret = PTR_ERR(spifc->clk); 321 goto out_err; 322 } 323 324 ret = clk_prepare_enable(spifc->clk); 325 if (ret) { 326 dev_err(spifc->dev, "can't prepare clock\n"); 327 goto out_err; 328 } 329 330 rate = clk_get_rate(spifc->clk); 331 332 master->num_chipselect = 1; 333 master->dev.of_node = pdev->dev.of_node; 334 master->bits_per_word_mask = SPI_BPW_MASK(8); 335 master->auto_runtime_pm = true; 336 master->transfer_one = meson_spifc_transfer_one; 337 master->min_speed_hz = rate >> 6; 338 master->max_speed_hz = rate >> 1; 339 340 meson_spifc_hw_init(spifc); 341 342 pm_runtime_set_active(spifc->dev); 343 pm_runtime_enable(spifc->dev); 344 345 ret = devm_spi_register_master(spifc->dev, master); 346 if (ret) { 347 dev_err(spifc->dev, "failed to register spi master\n"); 348 goto out_clk; 349 } 350 351 return 0; 352 out_clk: 353 clk_disable_unprepare(spifc->clk); 354 out_err: 355 spi_master_put(master); 356 return ret; 357 } 358 359 static int meson_spifc_remove(struct platform_device *pdev) 360 { 361 struct spi_master *master = platform_get_drvdata(pdev); 362 struct meson_spifc *spifc = spi_master_get_devdata(master); 363 364 pm_runtime_get_sync(&pdev->dev); 365 clk_disable_unprepare(spifc->clk); 366 pm_runtime_disable(&pdev->dev); 367 368 return 0; 369 } 370 371 #ifdef CONFIG_PM_SLEEP 372 static int meson_spifc_suspend(struct device *dev) 373 { 374 struct spi_master *master = dev_get_drvdata(dev); 375 struct meson_spifc *spifc = spi_master_get_devdata(master); 376 int ret; 377 378 ret = spi_master_suspend(master); 379 if (ret) 380 return ret; 381 382 if (!pm_runtime_suspended(dev)) 383 clk_disable_unprepare(spifc->clk); 384 385 return 0; 386 } 387 388 static int meson_spifc_resume(struct device *dev) 389 { 390 struct spi_master *master = dev_get_drvdata(dev); 391 struct meson_spifc *spifc = spi_master_get_devdata(master); 392 int ret; 393 394 if (!pm_runtime_suspended(dev)) { 395 ret = clk_prepare_enable(spifc->clk); 396 if (ret) 397 return ret; 398 } 399 400 meson_spifc_hw_init(spifc); 401 402 ret = spi_master_resume(master); 403 if (ret) 404 clk_disable_unprepare(spifc->clk); 405 406 return ret; 407 } 408 #endif /* CONFIG_PM_SLEEP */ 409 410 #ifdef CONFIG_PM 411 static int meson_spifc_runtime_suspend(struct device *dev) 412 { 413 struct spi_master *master = dev_get_drvdata(dev); 414 struct meson_spifc *spifc = spi_master_get_devdata(master); 415 416 clk_disable_unprepare(spifc->clk); 417 418 return 0; 419 } 420 421 static int meson_spifc_runtime_resume(struct device *dev) 422 { 423 struct spi_master *master = dev_get_drvdata(dev); 424 struct meson_spifc *spifc = spi_master_get_devdata(master); 425 426 return clk_prepare_enable(spifc->clk); 427 } 428 #endif /* CONFIG_PM */ 429 430 static const struct dev_pm_ops meson_spifc_pm_ops = { 431 SET_SYSTEM_SLEEP_PM_OPS(meson_spifc_suspend, meson_spifc_resume) 432 SET_RUNTIME_PM_OPS(meson_spifc_runtime_suspend, 433 meson_spifc_runtime_resume, 434 NULL) 435 }; 436 437 static const struct of_device_id meson_spifc_dt_match[] = { 438 { .compatible = "amlogic,meson6-spifc", }, 439 { .compatible = "amlogic,meson-gxbb-spifc", }, 440 { }, 441 }; 442 MODULE_DEVICE_TABLE(of, meson_spifc_dt_match); 443 444 static struct platform_driver meson_spifc_driver = { 445 .probe = meson_spifc_probe, 446 .remove = meson_spifc_remove, 447 .driver = { 448 .name = "meson-spifc", 449 .of_match_table = of_match_ptr(meson_spifc_dt_match), 450 .pm = &meson_spifc_pm_ops, 451 }, 452 }; 453 454 module_platform_driver(meson_spifc_driver); 455 456 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); 457 MODULE_DESCRIPTION("Amlogic Meson SPIFC driver"); 458 MODULE_LICENSE("GPL v2"); 459