Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.14-rc7 465 lines 13 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Driver for Amlogic A1 SPI flash controller (SPIFC) 4 * 5 * Copyright (c) 2023, SberDevices. All Rights Reserved. 6 * 7 * Author: Martin Kurbanov <mmkurbanov@sberdevices.ru> 8 */ 9 10#include <linux/bitfield.h> 11#include <linux/clk.h> 12#include <linux/device.h> 13#include <linux/io.h> 14#include <linux/iopoll.h> 15#include <linux/kernel.h> 16#include <linux/module.h> 17#include <linux/of.h> 18#include <linux/platform_device.h> 19#include <linux/pm_runtime.h> 20#include <linux/spi/spi.h> 21#include <linux/spi/spi-mem.h> 22#include <linux/types.h> 23 24#define SPIFC_A1_AHB_CTRL_REG 0x0 25#define SPIFC_A1_AHB_BUS_EN BIT(31) 26 27#define SPIFC_A1_USER_CTRL0_REG 0x200 28#define SPIFC_A1_USER_REQUEST_ENABLE BIT(31) 29#define SPIFC_A1_USER_REQUEST_FINISH BIT(30) 30#define SPIFC_A1_USER_DATA_UPDATED BIT(0) 31 32#define SPIFC_A1_USER_CTRL1_REG 0x204 33#define SPIFC_A1_USER_CMD_ENABLE BIT(30) 34#define SPIFC_A1_USER_CMD_MODE GENMASK(29, 28) 35#define SPIFC_A1_USER_CMD_CODE GENMASK(27, 20) 36#define SPIFC_A1_USER_ADDR_ENABLE BIT(19) 37#define SPIFC_A1_USER_ADDR_MODE GENMASK(18, 17) 38#define SPIFC_A1_USER_ADDR_BYTES GENMASK(16, 15) 39#define SPIFC_A1_USER_DOUT_ENABLE BIT(14) 40#define SPIFC_A1_USER_DOUT_MODE GENMASK(11, 10) 41#define SPIFC_A1_USER_DOUT_BYTES GENMASK(9, 0) 42 43#define SPIFC_A1_USER_CTRL2_REG 0x208 44#define SPIFC_A1_USER_DUMMY_ENABLE BIT(31) 45#define SPIFC_A1_USER_DUMMY_MODE GENMASK(30, 29) 46#define SPIFC_A1_USER_DUMMY_CLK_SYCLES GENMASK(28, 23) 47 48#define SPIFC_A1_USER_CTRL3_REG 0x20c 49#define SPIFC_A1_USER_DIN_ENABLE BIT(31) 50#define SPIFC_A1_USER_DIN_MODE GENMASK(28, 27) 51#define SPIFC_A1_USER_DIN_BYTES GENMASK(25, 16) 52 53#define SPIFC_A1_USER_ADDR_REG 0x210 54 55#define SPIFC_A1_AHB_REQ_CTRL_REG 0x214 56#define SPIFC_A1_AHB_REQ_ENABLE BIT(31) 57 58#define SPIFC_A1_ACTIMING0_REG (0x0088 << 2) 59#define SPIFC_A1_TSLCH GENMASK(31, 30) 60#define SPIFC_A1_TCLSH GENMASK(29, 28) 61#define SPIFC_A1_TSHWL GENMASK(20, 16) 62#define SPIFC_A1_TSHSL2 GENMASK(15, 12) 63#define SPIFC_A1_TSHSL1 GENMASK(11, 8) 64#define SPIFC_A1_TWHSL GENMASK(7, 0) 65 66#define SPIFC_A1_DBUF_CTRL_REG 0x240 67#define SPIFC_A1_DBUF_DIR BIT(31) 68#define SPIFC_A1_DBUF_AUTO_UPDATE_ADDR BIT(30) 69#define SPIFC_A1_DBUF_ADDR GENMASK(7, 0) 70 71#define SPIFC_A1_DBUF_DATA_REG 0x244 72 73#define SPIFC_A1_USER_DBUF_ADDR_REG 0x248 74 75#define SPIFC_A1_BUFFER_SIZE 512U 76 77#define SPIFC_A1_MAX_HZ 200000000 78#define SPIFC_A1_MIN_HZ 1000000 79 80#define SPIFC_A1_USER_CMD(op) ( \ 81 SPIFC_A1_USER_CMD_ENABLE | \ 82 FIELD_PREP(SPIFC_A1_USER_CMD_CODE, (op)->cmd.opcode) | \ 83 FIELD_PREP(SPIFC_A1_USER_CMD_MODE, ilog2((op)->cmd.buswidth))) 84 85#define SPIFC_A1_USER_ADDR(op) ( \ 86 SPIFC_A1_USER_ADDR_ENABLE | \ 87 FIELD_PREP(SPIFC_A1_USER_ADDR_MODE, ilog2((op)->addr.buswidth)) | \ 88 FIELD_PREP(SPIFC_A1_USER_ADDR_BYTES, (op)->addr.nbytes - 1)) 89 90#define SPIFC_A1_USER_DUMMY(op) ( \ 91 SPIFC_A1_USER_DUMMY_ENABLE | \ 92 FIELD_PREP(SPIFC_A1_USER_DUMMY_MODE, ilog2((op)->dummy.buswidth)) | \ 93 FIELD_PREP(SPIFC_A1_USER_DUMMY_CLK_SYCLES, (op)->dummy.nbytes << 3)) 94 95#define SPIFC_A1_TSLCH_VAL FIELD_PREP(SPIFC_A1_TSLCH, 1) 96#define SPIFC_A1_TCLSH_VAL FIELD_PREP(SPIFC_A1_TCLSH, 1) 97#define SPIFC_A1_TSHWL_VAL FIELD_PREP(SPIFC_A1_TSHWL, 7) 98#define SPIFC_A1_TSHSL2_VAL FIELD_PREP(SPIFC_A1_TSHSL2, 7) 99#define SPIFC_A1_TSHSL1_VAL FIELD_PREP(SPIFC_A1_TSHSL1, 7) 100#define SPIFC_A1_TWHSL_VAL FIELD_PREP(SPIFC_A1_TWHSL, 2) 101#define SPIFC_A1_ACTIMING0_VAL (SPIFC_A1_TSLCH_VAL | SPIFC_A1_TCLSH_VAL | \ 102 SPIFC_A1_TSHWL_VAL | SPIFC_A1_TSHSL2_VAL | \ 103 SPIFC_A1_TSHSL1_VAL | SPIFC_A1_TWHSL_VAL) 104 105struct amlogic_spifc_a1 { 106 struct spi_controller *ctrl; 107 struct clk *clk; 108 struct device *dev; 109 void __iomem *base; 110 u32 curr_speed_hz; 111}; 112 113static int amlogic_spifc_a1_request(struct amlogic_spifc_a1 *spifc, bool read) 114{ 115 u32 mask = SPIFC_A1_USER_REQUEST_FINISH | 116 (read ? SPIFC_A1_USER_DATA_UPDATED : 0); 117 u32 val; 118 119 writel(SPIFC_A1_USER_REQUEST_ENABLE, 120 spifc->base + SPIFC_A1_USER_CTRL0_REG); 121 122 return readl_poll_timeout(spifc->base + SPIFC_A1_USER_CTRL0_REG, 123 val, (val & mask) == mask, 0, 124 200 * USEC_PER_MSEC); 125} 126 127static void amlogic_spifc_a1_drain_buffer(struct amlogic_spifc_a1 *spifc, 128 char *buf, u32 len) 129{ 130 u32 data; 131 const u32 count = len / sizeof(data); 132 const u32 pad = len % sizeof(data); 133 134 writel(SPIFC_A1_DBUF_AUTO_UPDATE_ADDR, 135 spifc->base + SPIFC_A1_DBUF_CTRL_REG); 136 ioread32_rep(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count); 137 138 if (pad) { 139 data = readl(spifc->base + SPIFC_A1_DBUF_DATA_REG); 140 memcpy(buf + len - pad, &data, pad); 141 } 142} 143 144static void amlogic_spifc_a1_fill_buffer(struct amlogic_spifc_a1 *spifc, 145 const char *buf, u32 len) 146{ 147 u32 data; 148 const u32 count = len / sizeof(data); 149 const u32 pad = len % sizeof(data); 150 151 writel(SPIFC_A1_DBUF_DIR | SPIFC_A1_DBUF_AUTO_UPDATE_ADDR, 152 spifc->base + SPIFC_A1_DBUF_CTRL_REG); 153 iowrite32_rep(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count); 154 155 if (pad) { 156 memcpy(&data, buf + len - pad, pad); 157 writel(data, spifc->base + SPIFC_A1_DBUF_DATA_REG); 158 } 159} 160 161static void amlogic_spifc_a1_user_init(struct amlogic_spifc_a1 *spifc) 162{ 163 writel(0, spifc->base + SPIFC_A1_USER_CTRL0_REG); 164 writel(0, spifc->base + SPIFC_A1_USER_CTRL1_REG); 165 writel(0, spifc->base + SPIFC_A1_USER_CTRL2_REG); 166 writel(0, spifc->base + SPIFC_A1_USER_CTRL3_REG); 167} 168 169static void amlogic_spifc_a1_set_cmd(struct amlogic_spifc_a1 *spifc, 170 u32 cmd_cfg) 171{ 172 u32 val; 173 174 val = readl(spifc->base + SPIFC_A1_USER_CTRL1_REG); 175 val &= ~(SPIFC_A1_USER_CMD_MODE | SPIFC_A1_USER_CMD_CODE); 176 val |= cmd_cfg; 177 writel(val, spifc->base + SPIFC_A1_USER_CTRL1_REG); 178} 179 180static void amlogic_spifc_a1_set_addr(struct amlogic_spifc_a1 *spifc, u32 addr, 181 u32 addr_cfg) 182{ 183 u32 val; 184 185 writel(addr, spifc->base + SPIFC_A1_USER_ADDR_REG); 186 187 val = readl(spifc->base + SPIFC_A1_USER_CTRL1_REG); 188 val &= ~(SPIFC_A1_USER_ADDR_MODE | SPIFC_A1_USER_ADDR_BYTES); 189 val |= addr_cfg; 190 writel(val, spifc->base + SPIFC_A1_USER_CTRL1_REG); 191} 192 193static void amlogic_spifc_a1_set_dummy(struct amlogic_spifc_a1 *spifc, 194 u32 dummy_cfg) 195{ 196 u32 val = readl(spifc->base + SPIFC_A1_USER_CTRL2_REG); 197 198 val &= ~(SPIFC_A1_USER_DUMMY_MODE | SPIFC_A1_USER_DUMMY_CLK_SYCLES); 199 val |= dummy_cfg; 200 writel(val, spifc->base + SPIFC_A1_USER_CTRL2_REG); 201} 202 203static int amlogic_spifc_a1_read(struct amlogic_spifc_a1 *spifc, void *buf, 204 u32 size, u32 mode) 205{ 206 u32 val = readl(spifc->base + SPIFC_A1_USER_CTRL3_REG); 207 int ret; 208 209 val &= ~(SPIFC_A1_USER_DIN_MODE | SPIFC_A1_USER_DIN_BYTES); 210 val |= SPIFC_A1_USER_DIN_ENABLE; 211 val |= FIELD_PREP(SPIFC_A1_USER_DIN_MODE, mode); 212 val |= FIELD_PREP(SPIFC_A1_USER_DIN_BYTES, size); 213 writel(val, spifc->base + SPIFC_A1_USER_CTRL3_REG); 214 215 ret = amlogic_spifc_a1_request(spifc, true); 216 if (!ret) 217 amlogic_spifc_a1_drain_buffer(spifc, buf, size); 218 219 return ret; 220} 221 222static int amlogic_spifc_a1_write(struct amlogic_spifc_a1 *spifc, 223 const void *buf, u32 size, u32 mode) 224{ 225 u32 val; 226 227 amlogic_spifc_a1_fill_buffer(spifc, buf, size); 228 229 val = readl(spifc->base + SPIFC_A1_USER_CTRL1_REG); 230 val &= ~(SPIFC_A1_USER_DOUT_MODE | SPIFC_A1_USER_DOUT_BYTES); 231 val |= FIELD_PREP(SPIFC_A1_USER_DOUT_MODE, mode); 232 val |= FIELD_PREP(SPIFC_A1_USER_DOUT_BYTES, size); 233 val |= SPIFC_A1_USER_DOUT_ENABLE; 234 writel(val, spifc->base + SPIFC_A1_USER_CTRL1_REG); 235 236 return amlogic_spifc_a1_request(spifc, false); 237} 238 239static int amlogic_spifc_a1_set_freq(struct amlogic_spifc_a1 *spifc, u32 freq) 240{ 241 int ret; 242 243 if (freq == spifc->curr_speed_hz) 244 return 0; 245 246 ret = clk_set_rate(spifc->clk, freq); 247 if (ret) 248 return ret; 249 250 spifc->curr_speed_hz = freq; 251 return 0; 252} 253 254static int amlogic_spifc_a1_exec_op(struct spi_mem *mem, 255 const struct spi_mem_op *op) 256{ 257 struct amlogic_spifc_a1 *spifc = 258 spi_controller_get_devdata(mem->spi->controller); 259 size_t data_size = op->data.nbytes; 260 int ret; 261 262 ret = amlogic_spifc_a1_set_freq(spifc, op->max_freq); 263 if (ret) 264 return ret; 265 266 amlogic_spifc_a1_user_init(spifc); 267 amlogic_spifc_a1_set_cmd(spifc, SPIFC_A1_USER_CMD(op)); 268 269 if (op->addr.nbytes) 270 amlogic_spifc_a1_set_addr(spifc, op->addr.val, 271 SPIFC_A1_USER_ADDR(op)); 272 273 if (op->dummy.nbytes) 274 amlogic_spifc_a1_set_dummy(spifc, SPIFC_A1_USER_DUMMY(op)); 275 276 if (data_size) { 277 u32 mode = ilog2(op->data.buswidth); 278 279 writel(0, spifc->base + SPIFC_A1_USER_DBUF_ADDR_REG); 280 281 if (op->data.dir == SPI_MEM_DATA_IN) 282 ret = amlogic_spifc_a1_read(spifc, op->data.buf.in, 283 data_size, mode); 284 else 285 ret = amlogic_spifc_a1_write(spifc, op->data.buf.out, 286 data_size, mode); 287 } else { 288 ret = amlogic_spifc_a1_request(spifc, false); 289 } 290 291 return ret; 292} 293 294static int amlogic_spifc_a1_adjust_op_size(struct spi_mem *mem, 295 struct spi_mem_op *op) 296{ 297 op->data.nbytes = min(op->data.nbytes, SPIFC_A1_BUFFER_SIZE); 298 return 0; 299} 300 301static void amlogic_spifc_a1_hw_init(struct amlogic_spifc_a1 *spifc) 302{ 303 u32 regv; 304 305 regv = readl(spifc->base + SPIFC_A1_AHB_REQ_CTRL_REG); 306 regv &= ~(SPIFC_A1_AHB_REQ_ENABLE); 307 writel(regv, spifc->base + SPIFC_A1_AHB_REQ_CTRL_REG); 308 309 regv = readl(spifc->base + SPIFC_A1_AHB_CTRL_REG); 310 regv &= ~(SPIFC_A1_AHB_BUS_EN); 311 writel(regv, spifc->base + SPIFC_A1_AHB_CTRL_REG); 312 313 writel(SPIFC_A1_ACTIMING0_VAL, spifc->base + SPIFC_A1_ACTIMING0_REG); 314 315 writel(0, spifc->base + SPIFC_A1_USER_DBUF_ADDR_REG); 316} 317 318static const struct spi_controller_mem_ops amlogic_spifc_a1_mem_ops = { 319 .exec_op = amlogic_spifc_a1_exec_op, 320 .adjust_op_size = amlogic_spifc_a1_adjust_op_size, 321}; 322 323static const struct spi_controller_mem_caps amlogic_spifc_a1_mem_caps = { 324 .per_op_freq = true, 325}; 326 327static int amlogic_spifc_a1_probe(struct platform_device *pdev) 328{ 329 struct spi_controller *ctrl; 330 struct amlogic_spifc_a1 *spifc; 331 int ret; 332 333 ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*spifc)); 334 if (!ctrl) 335 return -ENOMEM; 336 337 spifc = spi_controller_get_devdata(ctrl); 338 platform_set_drvdata(pdev, spifc); 339 340 spifc->dev = &pdev->dev; 341 spifc->ctrl = ctrl; 342 343 spifc->base = devm_platform_ioremap_resource(pdev, 0); 344 if (IS_ERR(spifc->base)) 345 return PTR_ERR(spifc->base); 346 347 spifc->clk = devm_clk_get_enabled(spifc->dev, NULL); 348 if (IS_ERR(spifc->clk)) 349 return dev_err_probe(spifc->dev, PTR_ERR(spifc->clk), 350 "unable to get clock\n"); 351 352 amlogic_spifc_a1_hw_init(spifc); 353 354 pm_runtime_set_autosuspend_delay(spifc->dev, 500); 355 pm_runtime_use_autosuspend(spifc->dev); 356 devm_pm_runtime_enable(spifc->dev); 357 358 ctrl->num_chipselect = 1; 359 ctrl->dev.of_node = pdev->dev.of_node; 360 ctrl->bits_per_word_mask = SPI_BPW_MASK(8); 361 ctrl->auto_runtime_pm = true; 362 ctrl->mem_ops = &amlogic_spifc_a1_mem_ops; 363 ctrl->mem_caps = &amlogic_spifc_a1_mem_caps; 364 ctrl->min_speed_hz = SPIFC_A1_MIN_HZ; 365 ctrl->max_speed_hz = SPIFC_A1_MAX_HZ; 366 ctrl->mode_bits = (SPI_RX_DUAL | SPI_TX_DUAL | 367 SPI_RX_QUAD | SPI_TX_QUAD); 368 369 ret = devm_spi_register_controller(spifc->dev, ctrl); 370 if (ret) 371 return dev_err_probe(spifc->dev, ret, 372 "failed to register spi controller\n"); 373 374 return 0; 375} 376 377#ifdef CONFIG_PM_SLEEP 378static int amlogic_spifc_a1_suspend(struct device *dev) 379{ 380 struct amlogic_spifc_a1 *spifc = dev_get_drvdata(dev); 381 int ret; 382 383 ret = spi_controller_suspend(spifc->ctrl); 384 if (ret) 385 return ret; 386 387 if (!pm_runtime_suspended(dev)) 388 clk_disable_unprepare(spifc->clk); 389 390 return 0; 391} 392 393static int amlogic_spifc_a1_resume(struct device *dev) 394{ 395 struct amlogic_spifc_a1 *spifc = dev_get_drvdata(dev); 396 int ret = 0; 397 398 if (!pm_runtime_suspended(dev)) { 399 ret = clk_prepare_enable(spifc->clk); 400 if (ret) 401 return ret; 402 } 403 404 amlogic_spifc_a1_hw_init(spifc); 405 406 ret = spi_controller_resume(spifc->ctrl); 407 if (ret) 408 clk_disable_unprepare(spifc->clk); 409 410 return ret; 411} 412#endif /* CONFIG_PM_SLEEP */ 413 414#ifdef CONFIG_PM 415static int amlogic_spifc_a1_runtime_suspend(struct device *dev) 416{ 417 struct amlogic_spifc_a1 *spifc = dev_get_drvdata(dev); 418 419 clk_disable_unprepare(spifc->clk); 420 421 return 0; 422} 423 424static int amlogic_spifc_a1_runtime_resume(struct device *dev) 425{ 426 struct amlogic_spifc_a1 *spifc = dev_get_drvdata(dev); 427 int ret; 428 429 ret = clk_prepare_enable(spifc->clk); 430 if (!ret) 431 amlogic_spifc_a1_hw_init(spifc); 432 433 return ret; 434} 435#endif /* CONFIG_PM */ 436 437static const struct dev_pm_ops amlogic_spifc_a1_pm_ops = { 438 SET_SYSTEM_SLEEP_PM_OPS(amlogic_spifc_a1_suspend, 439 amlogic_spifc_a1_resume) 440 SET_RUNTIME_PM_OPS(amlogic_spifc_a1_runtime_suspend, 441 amlogic_spifc_a1_runtime_resume, 442 NULL) 443}; 444 445#ifdef CONFIG_OF 446static const struct of_device_id amlogic_spifc_a1_dt_match[] = { 447 { .compatible = "amlogic,a1-spifc", }, 448 { }, 449}; 450MODULE_DEVICE_TABLE(of, amlogic_spifc_a1_dt_match); 451#endif /* CONFIG_OF */ 452 453static struct platform_driver amlogic_spifc_a1_driver = { 454 .probe = amlogic_spifc_a1_probe, 455 .driver = { 456 .name = "amlogic-spifc-a1", 457 .of_match_table = of_match_ptr(amlogic_spifc_a1_dt_match), 458 .pm = &amlogic_spifc_a1_pm_ops, 459 }, 460}; 461module_platform_driver(amlogic_spifc_a1_driver); 462 463MODULE_AUTHOR("Martin Kurbanov <mmkurbanov@sberdevices.ru>"); 464MODULE_DESCRIPTION("Amlogic A1 SPIFC driver"); 465MODULE_LICENSE("GPL");