Naga Sureshkumar Relli | fee10bd | 2018-12-06 18:17:34 +0530 | [diff] [blame^] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * ARM PL353 SMC driver |
| 4 | * |
| 5 | * Copyright (C) 2012 - 2018 Xilinx, Inc |
| 6 | * Author: Punnaiah Choudary Kalluri <punnaiah@xilinx.com> |
| 7 | * Author: Naga Sureshkumar Relli <nagasure@xilinx.com> |
| 8 | */ |
| 9 | |
| 10 | #include <linux/clk.h> |
| 11 | #include <linux/io.h> |
| 12 | #include <linux/kernel.h> |
| 13 | #include <linux/module.h> |
| 14 | #include <linux/of_platform.h> |
| 15 | #include <linux/platform_device.h> |
| 16 | #include <linux/slab.h> |
| 17 | #include <linux/pl353-smc.h> |
| 18 | #include <linux/amba/bus.h> |
| 19 | |
| 20 | /* Register definitions */ |
| 21 | #define PL353_SMC_MEMC_STATUS_OFFS 0 /* Controller status reg, RO */ |
| 22 | #define PL353_SMC_CFG_CLR_OFFS 0xC /* Clear config reg, WO */ |
| 23 | #define PL353_SMC_DIRECT_CMD_OFFS 0x10 /* Direct command reg, WO */ |
| 24 | #define PL353_SMC_SET_CYCLES_OFFS 0x14 /* Set cycles register, WO */ |
| 25 | #define PL353_SMC_SET_OPMODE_OFFS 0x18 /* Set opmode register, WO */ |
| 26 | #define PL353_SMC_ECC_STATUS_OFFS 0x400 /* ECC status register */ |
| 27 | #define PL353_SMC_ECC_MEMCFG_OFFS 0x404 /* ECC mem config reg */ |
| 28 | #define PL353_SMC_ECC_MEMCMD1_OFFS 0x408 /* ECC mem cmd1 reg */ |
| 29 | #define PL353_SMC_ECC_MEMCMD2_OFFS 0x40C /* ECC mem cmd2 reg */ |
| 30 | #define PL353_SMC_ECC_VALUE0_OFFS 0x418 /* ECC value 0 reg */ |
| 31 | |
| 32 | /* Controller status register specific constants */ |
| 33 | #define PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT 6 |
| 34 | |
| 35 | /* Clear configuration register specific constants */ |
| 36 | #define PL353_SMC_CFG_CLR_INT_CLR_1 0x10 |
| 37 | #define PL353_SMC_CFG_CLR_ECC_INT_DIS_1 0x40 |
| 38 | #define PL353_SMC_CFG_CLR_INT_DIS_1 0x2 |
| 39 | #define PL353_SMC_CFG_CLR_DEFAULT_MASK (PL353_SMC_CFG_CLR_INT_CLR_1 | \ |
| 40 | PL353_SMC_CFG_CLR_ECC_INT_DIS_1 | \ |
| 41 | PL353_SMC_CFG_CLR_INT_DIS_1) |
| 42 | |
| 43 | /* Set cycles register specific constants */ |
| 44 | #define PL353_SMC_SET_CYCLES_T0_MASK 0xF |
| 45 | #define PL353_SMC_SET_CYCLES_T0_SHIFT 0 |
| 46 | #define PL353_SMC_SET_CYCLES_T1_MASK 0xF |
| 47 | #define PL353_SMC_SET_CYCLES_T1_SHIFT 4 |
| 48 | #define PL353_SMC_SET_CYCLES_T2_MASK 0x7 |
| 49 | #define PL353_SMC_SET_CYCLES_T2_SHIFT 8 |
| 50 | #define PL353_SMC_SET_CYCLES_T3_MASK 0x7 |
| 51 | #define PL353_SMC_SET_CYCLES_T3_SHIFT 11 |
| 52 | #define PL353_SMC_SET_CYCLES_T4_MASK 0x7 |
| 53 | #define PL353_SMC_SET_CYCLES_T4_SHIFT 14 |
| 54 | #define PL353_SMC_SET_CYCLES_T5_MASK 0x7 |
| 55 | #define PL353_SMC_SET_CYCLES_T5_SHIFT 17 |
| 56 | #define PL353_SMC_SET_CYCLES_T6_MASK 0xF |
| 57 | #define PL353_SMC_SET_CYCLES_T6_SHIFT 20 |
| 58 | |
| 59 | /* ECC status register specific constants */ |
| 60 | #define PL353_SMC_ECC_STATUS_BUSY BIT(6) |
| 61 | #define PL353_SMC_ECC_REG_SIZE_OFFS 4 |
| 62 | |
| 63 | /* ECC memory config register specific constants */ |
| 64 | #define PL353_SMC_ECC_MEMCFG_MODE_MASK 0xC |
| 65 | #define PL353_SMC_ECC_MEMCFG_MODE_SHIFT 2 |
| 66 | #define PL353_SMC_ECC_MEMCFG_PGSIZE_MASK 0xC |
| 67 | |
| 68 | #define PL353_SMC_DC_UPT_NAND_REGS ((4 << 23) | /* CS: NAND chip */ \ |
| 69 | (2 << 21)) /* UpdateRegs operation */ |
| 70 | |
| 71 | #define PL353_NAND_ECC_CMD1 ((0x80) | /* Write command */ \ |
| 72 | (0 << 8) | /* Read command */ \ |
| 73 | (0x30 << 16) | /* Read End command */ \ |
| 74 | (1 << 24)) /* Read End command calid */ |
| 75 | |
| 76 | #define PL353_NAND_ECC_CMD2 ((0x85) | /* Write col change cmd */ \ |
| 77 | (5 << 8) | /* Read col change cmd */ \ |
| 78 | (0xE0 << 16) | /* Read col change end cmd */ \ |
| 79 | (1 << 24)) /* Read col change end cmd valid */ |
| 80 | #define PL353_NAND_ECC_BUSY_TIMEOUT (1 * HZ) |
| 81 | /** |
| 82 | * struct pl353_smc_data - Private smc driver structure |
| 83 | * @memclk: Pointer to the peripheral clock |
| 84 | * @aclk: Pointer to the APER clock |
| 85 | */ |
| 86 | struct pl353_smc_data { |
| 87 | struct clk *memclk; |
| 88 | struct clk *aclk; |
| 89 | }; |
| 90 | |
| 91 | /* SMC virtual register base */ |
| 92 | static void __iomem *pl353_smc_base; |
| 93 | |
| 94 | /** |
| 95 | * pl353_smc_set_buswidth - Set memory buswidth |
| 96 | * @bw: Memory buswidth (8 | 16) |
| 97 | * Return: 0 on success or negative errno. |
| 98 | */ |
| 99 | int pl353_smc_set_buswidth(unsigned int bw) |
| 100 | { |
| 101 | if (bw != PL353_SMC_MEM_WIDTH_8 && bw != PL353_SMC_MEM_WIDTH_16) |
| 102 | return -EINVAL; |
| 103 | |
| 104 | writel(bw, pl353_smc_base + PL353_SMC_SET_OPMODE_OFFS); |
| 105 | writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base + |
| 106 | PL353_SMC_DIRECT_CMD_OFFS); |
| 107 | |
| 108 | return 0; |
| 109 | } |
| 110 | EXPORT_SYMBOL_GPL(pl353_smc_set_buswidth); |
| 111 | |
| 112 | /** |
| 113 | * pl353_smc_set_cycles - Set memory timing parameters |
| 114 | * @timings: NAND controller timing parameters |
| 115 | * |
| 116 | * Sets NAND chip specific timing parameters. |
| 117 | */ |
| 118 | void pl353_smc_set_cycles(u32 timings[]) |
| 119 | { |
| 120 | /* |
| 121 | * Set write pulse timing. This one is easy to extract: |
| 122 | * |
| 123 | * NWE_PULSE = tWP |
| 124 | */ |
| 125 | timings[0] &= PL353_SMC_SET_CYCLES_T0_MASK; |
| 126 | timings[1] = (timings[1] & PL353_SMC_SET_CYCLES_T1_MASK) << |
| 127 | PL353_SMC_SET_CYCLES_T1_SHIFT; |
| 128 | timings[2] = (timings[2] & PL353_SMC_SET_CYCLES_T2_MASK) << |
| 129 | PL353_SMC_SET_CYCLES_T2_SHIFT; |
| 130 | timings[3] = (timings[3] & PL353_SMC_SET_CYCLES_T3_MASK) << |
| 131 | PL353_SMC_SET_CYCLES_T3_SHIFT; |
| 132 | timings[4] = (timings[4] & PL353_SMC_SET_CYCLES_T4_MASK) << |
| 133 | PL353_SMC_SET_CYCLES_T4_SHIFT; |
| 134 | timings[5] = (timings[5] & PL353_SMC_SET_CYCLES_T5_MASK) << |
| 135 | PL353_SMC_SET_CYCLES_T5_SHIFT; |
| 136 | timings[6] = (timings[6] & PL353_SMC_SET_CYCLES_T6_MASK) << |
| 137 | PL353_SMC_SET_CYCLES_T6_SHIFT; |
| 138 | timings[0] |= timings[1] | timings[2] | timings[3] | |
| 139 | timings[4] | timings[5] | timings[6]; |
| 140 | |
| 141 | writel(timings[0], pl353_smc_base + PL353_SMC_SET_CYCLES_OFFS); |
| 142 | writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base + |
| 143 | PL353_SMC_DIRECT_CMD_OFFS); |
| 144 | } |
| 145 | EXPORT_SYMBOL_GPL(pl353_smc_set_cycles); |
| 146 | |
| 147 | /** |
| 148 | * pl353_smc_ecc_is_busy - Read ecc busy flag |
| 149 | * Return: the ecc_status bit from the ecc_status register. 1 = busy, 0 = idle |
| 150 | */ |
| 151 | bool pl353_smc_ecc_is_busy(void) |
| 152 | { |
| 153 | return ((readl(pl353_smc_base + PL353_SMC_ECC_STATUS_OFFS) & |
| 154 | PL353_SMC_ECC_STATUS_BUSY) == PL353_SMC_ECC_STATUS_BUSY); |
| 155 | } |
| 156 | EXPORT_SYMBOL_GPL(pl353_smc_ecc_is_busy); |
| 157 | |
| 158 | /** |
| 159 | * pl353_smc_get_ecc_val - Read ecc_valueN registers |
| 160 | * @ecc_reg: Index of the ecc_value reg (0..3) |
| 161 | * Return: the content of the requested ecc_value register. |
| 162 | * |
| 163 | * There are four valid ecc_value registers. The argument is truncated to stay |
| 164 | * within this valid boundary. |
| 165 | */ |
| 166 | u32 pl353_smc_get_ecc_val(int ecc_reg) |
| 167 | { |
| 168 | u32 addr, reg; |
| 169 | |
| 170 | addr = PL353_SMC_ECC_VALUE0_OFFS + |
| 171 | (ecc_reg * PL353_SMC_ECC_REG_SIZE_OFFS); |
| 172 | reg = readl(pl353_smc_base + addr); |
| 173 | |
| 174 | return reg; |
| 175 | } |
| 176 | EXPORT_SYMBOL_GPL(pl353_smc_get_ecc_val); |
| 177 | |
| 178 | /** |
| 179 | * pl353_smc_get_nand_int_status_raw - Get NAND interrupt status bit |
| 180 | * Return: the raw_int_status1 bit from the memc_status register |
| 181 | */ |
| 182 | int pl353_smc_get_nand_int_status_raw(void) |
| 183 | { |
| 184 | u32 reg; |
| 185 | |
| 186 | reg = readl(pl353_smc_base + PL353_SMC_MEMC_STATUS_OFFS); |
| 187 | reg >>= PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT; |
| 188 | reg &= 1; |
| 189 | |
| 190 | return reg; |
| 191 | } |
| 192 | EXPORT_SYMBOL_GPL(pl353_smc_get_nand_int_status_raw); |
| 193 | |
| 194 | /** |
| 195 | * pl353_smc_clr_nand_int - Clear NAND interrupt |
| 196 | */ |
| 197 | void pl353_smc_clr_nand_int(void) |
| 198 | { |
| 199 | writel(PL353_SMC_CFG_CLR_INT_CLR_1, |
| 200 | pl353_smc_base + PL353_SMC_CFG_CLR_OFFS); |
| 201 | } |
| 202 | EXPORT_SYMBOL_GPL(pl353_smc_clr_nand_int); |
| 203 | |
| 204 | /** |
| 205 | * pl353_smc_set_ecc_mode - Set SMC ECC mode |
| 206 | * @mode: ECC mode (BYPASS, APB, MEM) |
| 207 | * Return: 0 on success or negative errno. |
| 208 | */ |
| 209 | int pl353_smc_set_ecc_mode(enum pl353_smc_ecc_mode mode) |
| 210 | { |
| 211 | u32 reg; |
| 212 | int ret = 0; |
| 213 | |
| 214 | switch (mode) { |
| 215 | case PL353_SMC_ECCMODE_BYPASS: |
| 216 | case PL353_SMC_ECCMODE_APB: |
| 217 | case PL353_SMC_ECCMODE_MEM: |
| 218 | |
| 219 | reg = readl(pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS); |
| 220 | reg &= ~PL353_SMC_ECC_MEMCFG_MODE_MASK; |
| 221 | reg |= mode << PL353_SMC_ECC_MEMCFG_MODE_SHIFT; |
| 222 | writel(reg, pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS); |
| 223 | |
| 224 | break; |
| 225 | default: |
| 226 | ret = -EINVAL; |
| 227 | } |
| 228 | |
| 229 | return ret; |
| 230 | } |
| 231 | EXPORT_SYMBOL_GPL(pl353_smc_set_ecc_mode); |
| 232 | |
| 233 | /** |
| 234 | * pl353_smc_set_ecc_pg_size - Set SMC ECC page size |
| 235 | * @pg_sz: ECC page size |
| 236 | * Return: 0 on success or negative errno. |
| 237 | */ |
| 238 | int pl353_smc_set_ecc_pg_size(unsigned int pg_sz) |
| 239 | { |
| 240 | u32 reg, sz; |
| 241 | |
| 242 | switch (pg_sz) { |
| 243 | case 0: |
| 244 | sz = 0; |
| 245 | break; |
| 246 | case SZ_512: |
| 247 | sz = 1; |
| 248 | break; |
| 249 | case SZ_1K: |
| 250 | sz = 2; |
| 251 | break; |
| 252 | case SZ_2K: |
| 253 | sz = 3; |
| 254 | break; |
| 255 | default: |
| 256 | return -EINVAL; |
| 257 | } |
| 258 | |
| 259 | reg = readl(pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS); |
| 260 | reg &= ~PL353_SMC_ECC_MEMCFG_PGSIZE_MASK; |
| 261 | reg |= sz; |
| 262 | writel(reg, pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS); |
| 263 | |
| 264 | return 0; |
| 265 | } |
| 266 | EXPORT_SYMBOL_GPL(pl353_smc_set_ecc_pg_size); |
| 267 | |
| 268 | static int __maybe_unused pl353_smc_suspend(struct device *dev) |
| 269 | { |
| 270 | struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev); |
| 271 | |
| 272 | clk_disable(pl353_smc->memclk); |
| 273 | clk_disable(pl353_smc->aclk); |
| 274 | |
| 275 | return 0; |
| 276 | } |
| 277 | |
| 278 | static int __maybe_unused pl353_smc_resume(struct device *dev) |
| 279 | { |
| 280 | int ret; |
| 281 | struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev); |
| 282 | |
| 283 | ret = clk_enable(pl353_smc->aclk); |
| 284 | if (ret) { |
| 285 | dev_err(dev, "Cannot enable axi domain clock.\n"); |
| 286 | return ret; |
| 287 | } |
| 288 | |
| 289 | ret = clk_enable(pl353_smc->memclk); |
| 290 | if (ret) { |
| 291 | dev_err(dev, "Cannot enable memory clock.\n"); |
| 292 | clk_disable(pl353_smc->aclk); |
| 293 | return ret; |
| 294 | } |
| 295 | |
| 296 | return ret; |
| 297 | } |
| 298 | |
| 299 | static struct amba_driver pl353_smc_driver; |
| 300 | |
| 301 | static SIMPLE_DEV_PM_OPS(pl353_smc_dev_pm_ops, pl353_smc_suspend, |
| 302 | pl353_smc_resume); |
| 303 | |
| 304 | /** |
| 305 | * pl353_smc_init_nand_interface - Initialize the NAND interface |
| 306 | * @adev: Pointer to the amba_device struct |
| 307 | * @nand_node: Pointer to the pl353_nand device_node struct |
| 308 | */ |
| 309 | static void pl353_smc_init_nand_interface(struct amba_device *adev, |
| 310 | struct device_node *nand_node) |
| 311 | { |
| 312 | unsigned long timeout; |
| 313 | |
| 314 | pl353_smc_set_buswidth(PL353_SMC_MEM_WIDTH_8); |
| 315 | writel(PL353_SMC_CFG_CLR_INT_CLR_1, |
| 316 | pl353_smc_base + PL353_SMC_CFG_CLR_OFFS); |
| 317 | writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base + |
| 318 | PL353_SMC_DIRECT_CMD_OFFS); |
| 319 | |
| 320 | timeout = jiffies + PL353_NAND_ECC_BUSY_TIMEOUT; |
| 321 | /* Wait till the ECC operation is complete */ |
| 322 | do { |
| 323 | if (pl353_smc_ecc_is_busy()) |
| 324 | cpu_relax(); |
| 325 | else |
| 326 | break; |
| 327 | } while (!time_after_eq(jiffies, timeout)); |
| 328 | |
| 329 | if (time_after_eq(jiffies, timeout)) |
| 330 | return; |
| 331 | |
| 332 | writel(PL353_NAND_ECC_CMD1, |
| 333 | pl353_smc_base + PL353_SMC_ECC_MEMCMD1_OFFS); |
| 334 | writel(PL353_NAND_ECC_CMD2, |
| 335 | pl353_smc_base + PL353_SMC_ECC_MEMCMD2_OFFS); |
| 336 | } |
| 337 | |
| 338 | static const struct of_device_id pl353_smc_supported_children[] = { |
| 339 | { |
| 340 | .compatible = "cfi-flash" |
| 341 | }, |
| 342 | { |
| 343 | .compatible = "arm,pl353-nand-r2p1", |
| 344 | .data = pl353_smc_init_nand_interface |
| 345 | }, |
| 346 | {} |
| 347 | }; |
| 348 | |
| 349 | static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id) |
| 350 | { |
| 351 | struct pl353_smc_data *pl353_smc; |
| 352 | struct device_node *child; |
| 353 | struct resource *res; |
| 354 | int err; |
| 355 | struct device_node *of_node = adev->dev.of_node; |
| 356 | static void (*init)(struct amba_device *adev, |
| 357 | struct device_node *nand_node); |
| 358 | const struct of_device_id *match = NULL; |
| 359 | |
| 360 | pl353_smc = devm_kzalloc(&adev->dev, sizeof(*pl353_smc), GFP_KERNEL); |
| 361 | if (!pl353_smc) |
| 362 | return -ENOMEM; |
| 363 | |
| 364 | /* Get the NAND controller virtual address */ |
| 365 | res = &adev->res; |
| 366 | pl353_smc_base = devm_ioremap_resource(&adev->dev, res); |
| 367 | if (IS_ERR(pl353_smc_base)) |
| 368 | return PTR_ERR(pl353_smc_base); |
| 369 | |
| 370 | pl353_smc->aclk = devm_clk_get(&adev->dev, "apb_pclk"); |
| 371 | if (IS_ERR(pl353_smc->aclk)) { |
| 372 | dev_err(&adev->dev, "aclk clock not found.\n"); |
| 373 | return PTR_ERR(pl353_smc->aclk); |
| 374 | } |
| 375 | |
| 376 | pl353_smc->memclk = devm_clk_get(&adev->dev, "memclk"); |
| 377 | if (IS_ERR(pl353_smc->memclk)) { |
| 378 | dev_err(&adev->dev, "memclk clock not found.\n"); |
| 379 | return PTR_ERR(pl353_smc->memclk); |
| 380 | } |
| 381 | |
| 382 | err = clk_prepare_enable(pl353_smc->aclk); |
| 383 | if (err) { |
| 384 | dev_err(&adev->dev, "Unable to enable AXI clock.\n"); |
| 385 | return err; |
| 386 | } |
| 387 | |
| 388 | err = clk_prepare_enable(pl353_smc->memclk); |
| 389 | if (err) { |
| 390 | dev_err(&adev->dev, "Unable to enable memory clock.\n"); |
| 391 | goto out_clk_dis_aper; |
| 392 | } |
| 393 | |
| 394 | amba_set_drvdata(adev, pl353_smc); |
| 395 | |
| 396 | /* clear interrupts */ |
| 397 | writel(PL353_SMC_CFG_CLR_DEFAULT_MASK, |
| 398 | pl353_smc_base + PL353_SMC_CFG_CLR_OFFS); |
| 399 | |
| 400 | /* Find compatible children. Only a single child is supported */ |
| 401 | for_each_available_child_of_node(of_node, child) { |
| 402 | match = of_match_node(pl353_smc_supported_children, child); |
| 403 | if (!match) { |
| 404 | dev_warn(&adev->dev, "unsupported child node\n"); |
| 405 | continue; |
| 406 | } |
| 407 | break; |
| 408 | } |
| 409 | if (!match) { |
| 410 | dev_err(&adev->dev, "no matching children\n"); |
| 411 | goto out_clk_disable; |
| 412 | } |
| 413 | |
| 414 | init = match->data; |
| 415 | if (init) |
| 416 | init(adev, child); |
| 417 | of_platform_device_create(child, NULL, &adev->dev); |
| 418 | |
| 419 | return 0; |
| 420 | |
| 421 | out_clk_disable: |
| 422 | clk_disable_unprepare(pl353_smc->memclk); |
| 423 | out_clk_dis_aper: |
| 424 | clk_disable_unprepare(pl353_smc->aclk); |
| 425 | |
| 426 | return err; |
| 427 | } |
| 428 | |
| 429 | static int pl353_smc_remove(struct amba_device *adev) |
| 430 | { |
| 431 | struct pl353_smc_data *pl353_smc = amba_get_drvdata(adev); |
| 432 | |
| 433 | clk_disable_unprepare(pl353_smc->memclk); |
| 434 | clk_disable_unprepare(pl353_smc->aclk); |
| 435 | |
| 436 | return 0; |
| 437 | } |
| 438 | |
| 439 | static const struct amba_id pl353_ids[] = { |
| 440 | { |
| 441 | .id = 0x00041353, |
| 442 | .mask = 0x000fffff, |
| 443 | }, |
| 444 | { 0, 0 }, |
| 445 | }; |
| 446 | MODULE_DEVICE_TABLE(amba, pl353_ids); |
| 447 | |
| 448 | static struct amba_driver pl353_smc_driver = { |
| 449 | .drv = { |
| 450 | .owner = THIS_MODULE, |
| 451 | .name = "pl353-smc", |
| 452 | .pm = &pl353_smc_dev_pm_ops, |
| 453 | }, |
| 454 | .id_table = pl353_ids, |
| 455 | .probe = pl353_smc_probe, |
| 456 | .remove = pl353_smc_remove, |
| 457 | }; |
| 458 | |
| 459 | module_amba_driver(pl353_smc_driver); |
| 460 | |
| 461 | MODULE_AUTHOR("Xilinx, Inc."); |
| 462 | MODULE_DESCRIPTION("ARM PL353 SMC Driver"); |
| 463 | MODULE_LICENSE("GPL"); |