123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * ARM PL353 SMC driver
- *
- * Copyright (C) 2012 - 2018 Xilinx, Inc
- * Author: Punnaiah Choudary Kalluri <punnaiah@xilinx.com>
- * Author: Naga Sureshkumar Relli <nagasure@xilinx.com>
- */
- #include <linux/clk.h>
- #include <linux/io.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/of_platform.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
- #include <linux/pl353-smc.h>
- #include <linux/amba/bus.h>
- /* Register definitions */
- #define PL353_SMC_MEMC_STATUS_OFFS 0 /* Controller status reg, RO */
- #define PL353_SMC_CFG_CLR_OFFS 0xC /* Clear config reg, WO */
- #define PL353_SMC_DIRECT_CMD_OFFS 0x10 /* Direct command reg, WO */
- #define PL353_SMC_SET_CYCLES_OFFS 0x14 /* Set cycles register, WO */
- #define PL353_SMC_SET_OPMODE_OFFS 0x18 /* Set opmode register, WO */
- #define PL353_SMC_ECC_STATUS_OFFS 0x400 /* ECC status register */
- #define PL353_SMC_ECC_MEMCFG_OFFS 0x404 /* ECC mem config reg */
- #define PL353_SMC_ECC_MEMCMD1_OFFS 0x408 /* ECC mem cmd1 reg */
- #define PL353_SMC_ECC_MEMCMD2_OFFS 0x40C /* ECC mem cmd2 reg */
- #define PL353_SMC_ECC_VALUE0_OFFS 0x418 /* ECC value 0 reg */
- /* Controller status register specific constants */
- #define PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT 6
- /* Clear configuration register specific constants */
- #define PL353_SMC_CFG_CLR_INT_CLR_1 0x10
- #define PL353_SMC_CFG_CLR_ECC_INT_DIS_1 0x40
- #define PL353_SMC_CFG_CLR_INT_DIS_1 0x2
- #define PL353_SMC_CFG_CLR_DEFAULT_MASK (PL353_SMC_CFG_CLR_INT_CLR_1 | \
- PL353_SMC_CFG_CLR_ECC_INT_DIS_1 | \
- PL353_SMC_CFG_CLR_INT_DIS_1)
- /* Set cycles register specific constants */
- #define PL353_SMC_SET_CYCLES_T0_MASK 0xF
- #define PL353_SMC_SET_CYCLES_T0_SHIFT 0
- #define PL353_SMC_SET_CYCLES_T1_MASK 0xF
- #define PL353_SMC_SET_CYCLES_T1_SHIFT 4
- #define PL353_SMC_SET_CYCLES_T2_MASK 0x7
- #define PL353_SMC_SET_CYCLES_T2_SHIFT 8
- #define PL353_SMC_SET_CYCLES_T3_MASK 0x7
- #define PL353_SMC_SET_CYCLES_T3_SHIFT 11
- #define PL353_SMC_SET_CYCLES_T4_MASK 0x7
- #define PL353_SMC_SET_CYCLES_T4_SHIFT 14
- #define PL353_SMC_SET_CYCLES_T5_MASK 0x7
- #define PL353_SMC_SET_CYCLES_T5_SHIFT 17
- #define PL353_SMC_SET_CYCLES_T6_MASK 0xF
- #define PL353_SMC_SET_CYCLES_T6_SHIFT 20
- /* ECC status register specific constants */
- #define PL353_SMC_ECC_STATUS_BUSY BIT(6)
- #define PL353_SMC_ECC_REG_SIZE_OFFS 4
- /* ECC memory config register specific constants */
- #define PL353_SMC_ECC_MEMCFG_MODE_MASK 0xC
- #define PL353_SMC_ECC_MEMCFG_MODE_SHIFT 2
- #define PL353_SMC_ECC_MEMCFG_PGSIZE_MASK 0x3
- #define PL353_SMC_DC_UPT_NAND_REGS ((4 << 23) | /* CS: NAND chip */ \
- (2 << 21)) /* UpdateRegs operation */
- #define PL353_NAND_ECC_CMD1 ((0x80) | /* Write command */ \
- (0 << 8) | /* Read command */ \
- (0x30 << 16) | /* Read End command */ \
- (1 << 24)) /* Read End command calid */
- #define PL353_NAND_ECC_CMD2 ((0x85) | /* Write col change cmd */ \
- (5 << 8) | /* Read col change cmd */ \
- (0xE0 << 16) | /* Read col change end cmd */ \
- (1 << 24)) /* Read col change end cmd valid */
- #define PL353_NAND_ECC_BUSY_TIMEOUT (1 * HZ)
- /**
- * struct pl353_smc_data - Private smc driver structure
- * @memclk: Pointer to the peripheral clock
- * @aclk: Pointer to the APER clock
- */
- struct pl353_smc_data {
- struct clk *memclk;
- struct clk *aclk;
- };
- /* SMC virtual register base */
- static void __iomem *pl353_smc_base;
- /**
- * pl353_smc_set_buswidth - Set memory buswidth
- * @bw: Memory buswidth (8 | 16)
- * Return: 0 on success or negative errno.
- */
- int pl353_smc_set_buswidth(unsigned int bw)
- {
- if (bw != PL353_SMC_MEM_WIDTH_8 && bw != PL353_SMC_MEM_WIDTH_16)
- return -EINVAL;
- writel(bw, pl353_smc_base + PL353_SMC_SET_OPMODE_OFFS);
- writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base +
- PL353_SMC_DIRECT_CMD_OFFS);
- return 0;
- }
- EXPORT_SYMBOL_GPL(pl353_smc_set_buswidth);
- /**
- * pl353_smc_set_cycles - Set memory timing parameters
- * @timings: NAND controller timing parameters
- *
- * Sets NAND chip specific timing parameters.
- */
- void pl353_smc_set_cycles(u32 timings[])
- {
- /*
- * Set write pulse timing. This one is easy to extract:
- *
- * NWE_PULSE = tWP
- */
- timings[0] &= PL353_SMC_SET_CYCLES_T0_MASK;
- timings[1] = (timings[1] & PL353_SMC_SET_CYCLES_T1_MASK) <<
- PL353_SMC_SET_CYCLES_T1_SHIFT;
- timings[2] = (timings[2] & PL353_SMC_SET_CYCLES_T2_MASK) <<
- PL353_SMC_SET_CYCLES_T2_SHIFT;
- timings[3] = (timings[3] & PL353_SMC_SET_CYCLES_T3_MASK) <<
- PL353_SMC_SET_CYCLES_T3_SHIFT;
- timings[4] = (timings[4] & PL353_SMC_SET_CYCLES_T4_MASK) <<
- PL353_SMC_SET_CYCLES_T4_SHIFT;
- timings[5] = (timings[5] & PL353_SMC_SET_CYCLES_T5_MASK) <<
- PL353_SMC_SET_CYCLES_T5_SHIFT;
- timings[6] = (timings[6] & PL353_SMC_SET_CYCLES_T6_MASK) <<
- PL353_SMC_SET_CYCLES_T6_SHIFT;
- timings[0] |= timings[1] | timings[2] | timings[3] |
- timings[4] | timings[5] | timings[6];
- writel(timings[0], pl353_smc_base + PL353_SMC_SET_CYCLES_OFFS);
- writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base +
- PL353_SMC_DIRECT_CMD_OFFS);
- }
- EXPORT_SYMBOL_GPL(pl353_smc_set_cycles);
- /**
- * pl353_smc_ecc_is_busy - Read ecc busy flag
- * Return: the ecc_status bit from the ecc_status register. 1 = busy, 0 = idle
- */
- bool pl353_smc_ecc_is_busy(void)
- {
- return ((readl(pl353_smc_base + PL353_SMC_ECC_STATUS_OFFS) &
- PL353_SMC_ECC_STATUS_BUSY) == PL353_SMC_ECC_STATUS_BUSY);
- }
- EXPORT_SYMBOL_GPL(pl353_smc_ecc_is_busy);
- /**
- * pl353_smc_get_ecc_val - Read ecc_valueN registers
- * @ecc_reg: Index of the ecc_value reg (0..3)
- * Return: the content of the requested ecc_value register.
- *
- * There are four valid ecc_value registers. The argument is truncated to stay
- * within this valid boundary.
- */
- u32 pl353_smc_get_ecc_val(int ecc_reg)
- {
- u32 addr, reg;
- addr = PL353_SMC_ECC_VALUE0_OFFS +
- (ecc_reg * PL353_SMC_ECC_REG_SIZE_OFFS);
- reg = readl(pl353_smc_base + addr);
- return reg;
- }
- EXPORT_SYMBOL_GPL(pl353_smc_get_ecc_val);
- /**
- * pl353_smc_get_nand_int_status_raw - Get NAND interrupt status bit
- * Return: the raw_int_status1 bit from the memc_status register
- */
- int pl353_smc_get_nand_int_status_raw(void)
- {
- u32 reg;
- reg = readl(pl353_smc_base + PL353_SMC_MEMC_STATUS_OFFS);
- reg >>= PL353_SMC_MEMC_STATUS_RAW_INT_1_SHIFT;
- reg &= 1;
- return reg;
- }
- EXPORT_SYMBOL_GPL(pl353_smc_get_nand_int_status_raw);
- /**
- * pl353_smc_clr_nand_int - Clear NAND interrupt
- */
- void pl353_smc_clr_nand_int(void)
- {
- writel(PL353_SMC_CFG_CLR_INT_CLR_1,
- pl353_smc_base + PL353_SMC_CFG_CLR_OFFS);
- }
- EXPORT_SYMBOL_GPL(pl353_smc_clr_nand_int);
- /**
- * pl353_smc_set_ecc_mode - Set SMC ECC mode
- * @mode: ECC mode (BYPASS, APB, MEM)
- * Return: 0 on success or negative errno.
- */
- int pl353_smc_set_ecc_mode(enum pl353_smc_ecc_mode mode)
- {
- u32 reg;
- int ret = 0;
- switch (mode) {
- case PL353_SMC_ECCMODE_BYPASS:
- case PL353_SMC_ECCMODE_APB:
- case PL353_SMC_ECCMODE_MEM:
- reg = readl(pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS);
- reg &= ~PL353_SMC_ECC_MEMCFG_MODE_MASK;
- reg |= mode << PL353_SMC_ECC_MEMCFG_MODE_SHIFT;
- writel(reg, pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS);
- break;
- default:
- ret = -EINVAL;
- }
- return ret;
- }
- EXPORT_SYMBOL_GPL(pl353_smc_set_ecc_mode);
- /**
- * pl353_smc_set_ecc_pg_size - Set SMC ECC page size
- * @pg_sz: ECC page size
- * Return: 0 on success or negative errno.
- */
- int pl353_smc_set_ecc_pg_size(unsigned int pg_sz)
- {
- u32 reg, sz;
- switch (pg_sz) {
- case 0:
- sz = 0;
- break;
- case SZ_512:
- sz = 1;
- break;
- case SZ_1K:
- sz = 2;
- break;
- case SZ_2K:
- sz = 3;
- break;
- default:
- return -EINVAL;
- }
- reg = readl(pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS);
- reg &= ~PL353_SMC_ECC_MEMCFG_PGSIZE_MASK;
- reg |= sz;
- writel(reg, pl353_smc_base + PL353_SMC_ECC_MEMCFG_OFFS);
- return 0;
- }
- EXPORT_SYMBOL_GPL(pl353_smc_set_ecc_pg_size);
- static int __maybe_unused pl353_smc_suspend(struct device *dev)
- {
- struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev);
- clk_disable(pl353_smc->memclk);
- clk_disable(pl353_smc->aclk);
- return 0;
- }
- static int __maybe_unused pl353_smc_resume(struct device *dev)
- {
- int ret;
- struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev);
- ret = clk_enable(pl353_smc->aclk);
- if (ret) {
- dev_err(dev, "Cannot enable axi domain clock.\n");
- return ret;
- }
- ret = clk_enable(pl353_smc->memclk);
- if (ret) {
- dev_err(dev, "Cannot enable memory clock.\n");
- clk_disable(pl353_smc->aclk);
- return ret;
- }
- return ret;
- }
- static struct amba_driver pl353_smc_driver;
- static SIMPLE_DEV_PM_OPS(pl353_smc_dev_pm_ops, pl353_smc_suspend,
- pl353_smc_resume);
- /**
- * pl353_smc_init_nand_interface - Initialize the NAND interface
- * @adev: Pointer to the amba_device struct
- * @nand_node: Pointer to the pl353_nand device_node struct
- */
- static void pl353_smc_init_nand_interface(struct amba_device *adev,
- struct device_node *nand_node)
- {
- unsigned long timeout;
- pl353_smc_set_buswidth(PL353_SMC_MEM_WIDTH_8);
- writel(PL353_SMC_CFG_CLR_INT_CLR_1,
- pl353_smc_base + PL353_SMC_CFG_CLR_OFFS);
- writel(PL353_SMC_DC_UPT_NAND_REGS, pl353_smc_base +
- PL353_SMC_DIRECT_CMD_OFFS);
- timeout = jiffies + PL353_NAND_ECC_BUSY_TIMEOUT;
- /* Wait till the ECC operation is complete */
- do {
- if (pl353_smc_ecc_is_busy())
- cpu_relax();
- else
- break;
- } while (!time_after_eq(jiffies, timeout));
- if (time_after_eq(jiffies, timeout))
- return;
- writel(PL353_NAND_ECC_CMD1,
- pl353_smc_base + PL353_SMC_ECC_MEMCMD1_OFFS);
- writel(PL353_NAND_ECC_CMD2,
- pl353_smc_base + PL353_SMC_ECC_MEMCMD2_OFFS);
- }
- static const struct of_device_id pl353_smc_supported_children[] = {
- {
- .compatible = "cfi-flash"
- },
- {
- .compatible = "arm,pl353-nand-r2p1",
- .data = pl353_smc_init_nand_interface
- },
- {}
- };
- static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id)
- {
- struct pl353_smc_data *pl353_smc;
- struct device_node *child;
- struct resource *res;
- int err;
- struct device_node *of_node = adev->dev.of_node;
- static void (*init)(struct amba_device *adev,
- struct device_node *nand_node);
- const struct of_device_id *match = NULL;
- pl353_smc = devm_kzalloc(&adev->dev, sizeof(*pl353_smc), GFP_KERNEL);
- if (!pl353_smc)
- return -ENOMEM;
- /* Get the NAND controller virtual address */
- res = &adev->res;
- pl353_smc_base = devm_ioremap_resource(&adev->dev, res);
- if (IS_ERR(pl353_smc_base))
- return PTR_ERR(pl353_smc_base);
- pl353_smc->aclk = devm_clk_get(&adev->dev, "apb_pclk");
- if (IS_ERR(pl353_smc->aclk)) {
- dev_err(&adev->dev, "aclk clock not found.\n");
- return PTR_ERR(pl353_smc->aclk);
- }
- pl353_smc->memclk = devm_clk_get(&adev->dev, "memclk");
- if (IS_ERR(pl353_smc->memclk)) {
- dev_err(&adev->dev, "memclk clock not found.\n");
- return PTR_ERR(pl353_smc->memclk);
- }
- err = clk_prepare_enable(pl353_smc->aclk);
- if (err) {
- dev_err(&adev->dev, "Unable to enable AXI clock.\n");
- return err;
- }
- err = clk_prepare_enable(pl353_smc->memclk);
- if (err) {
- dev_err(&adev->dev, "Unable to enable memory clock.\n");
- goto out_clk_dis_aper;
- }
- amba_set_drvdata(adev, pl353_smc);
- /* clear interrupts */
- writel(PL353_SMC_CFG_CLR_DEFAULT_MASK,
- pl353_smc_base + PL353_SMC_CFG_CLR_OFFS);
- /* Find compatible children. Only a single child is supported */
- for_each_available_child_of_node(of_node, child) {
- match = of_match_node(pl353_smc_supported_children, child);
- if (!match) {
- dev_warn(&adev->dev, "unsupported child node\n");
- continue;
- }
- break;
- }
- if (!match) {
- err = -ENODEV;
- dev_err(&adev->dev, "no matching children\n");
- goto out_clk_disable;
- }
- init = match->data;
- if (init)
- init(adev, child);
- of_platform_device_create(child, NULL, &adev->dev);
- return 0;
- out_clk_disable:
- clk_disable_unprepare(pl353_smc->memclk);
- out_clk_dis_aper:
- clk_disable_unprepare(pl353_smc->aclk);
- return err;
- }
- static void pl353_smc_remove(struct amba_device *adev)
- {
- struct pl353_smc_data *pl353_smc = amba_get_drvdata(adev);
- clk_disable_unprepare(pl353_smc->memclk);
- clk_disable_unprepare(pl353_smc->aclk);
- }
- static const struct amba_id pl353_ids[] = {
- {
- .id = 0x00041353,
- .mask = 0x000fffff,
- },
- { 0, 0 },
- };
- MODULE_DEVICE_TABLE(amba, pl353_ids);
- static struct amba_driver pl353_smc_driver = {
- .drv = {
- .owner = THIS_MODULE,
- .name = "pl353-smc",
- .pm = &pl353_smc_dev_pm_ops,
- },
- .id_table = pl353_ids,
- .probe = pl353_smc_probe,
- .remove = pl353_smc_remove,
- };
- module_amba_driver(pl353_smc_driver);
- MODULE_AUTHOR("Xilinx, Inc.");
- MODULE_DESCRIPTION("ARM PL353 SMC Driver");
- MODULE_LICENSE("GPL");
|