239 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * NAND Flash Controller Device Driver for DT4 *5 * Copyright © 2011, Picochip.6 */7 8#include <linux/clk.h>9#include <linux/delay.h>10#include <linux/err.h>11#include <linux/io.h>12#include <linux/ioport.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/of.h>16#include <linux/platform_device.h>17#include <linux/reset.h>18 19#include "denali.h"20 21struct denali_dt {22 struct denali_controller controller;23 struct clk *clk; /* core clock */24 struct clk *clk_x; /* bus interface clock */25 struct clk *clk_ecc; /* ECC circuit clock */26 struct reset_control *rst; /* core reset */27 struct reset_control *rst_reg; /* register reset */28};29 30struct denali_dt_data {31 unsigned int revision;32 unsigned int caps;33 unsigned int oob_skip_bytes;34 const struct nand_ecc_caps *ecc_caps;35};36 37NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps, denali_calc_ecc_bytes,38 512, 8, 15);39static const struct denali_dt_data denali_socfpga_data = {40 .caps = DENALI_CAP_HW_ECC_FIXUP,41 .oob_skip_bytes = 2,42 .ecc_caps = &denali_socfpga_ecc_caps,43};44 45NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps, denali_calc_ecc_bytes,46 1024, 8, 16, 24);47static const struct denali_dt_data denali_uniphier_v5a_data = {48 .caps = DENALI_CAP_HW_ECC_FIXUP |49 DENALI_CAP_DMA_64BIT,50 .oob_skip_bytes = 8,51 .ecc_caps = &denali_uniphier_v5a_ecc_caps,52};53 54NAND_ECC_CAPS_SINGLE(denali_uniphier_v5b_ecc_caps, denali_calc_ecc_bytes,55 1024, 8, 16);56static const struct denali_dt_data denali_uniphier_v5b_data = {57 .revision = 0x0501,58 .caps = DENALI_CAP_HW_ECC_FIXUP |59 DENALI_CAP_DMA_64BIT,60 .oob_skip_bytes = 8,61 .ecc_caps = &denali_uniphier_v5b_ecc_caps,62};63 64static const struct of_device_id denali_nand_dt_ids[] = {65 {66 .compatible = "altr,socfpga-denali-nand",67 .data = &denali_socfpga_data,68 },69 {70 .compatible = "socionext,uniphier-denali-nand-v5a",71 .data = &denali_uniphier_v5a_data,72 },73 {74 .compatible = "socionext,uniphier-denali-nand-v5b",75 .data = &denali_uniphier_v5b_data,76 },77 { /* sentinel */ }78};79MODULE_DEVICE_TABLE(of, denali_nand_dt_ids);80 81static int denali_dt_chip_init(struct denali_controller *denali,82 struct device_node *chip_np)83{84 struct denali_chip *dchip;85 u32 bank;86 int nsels, i, ret;87 88 nsels = of_property_count_u32_elems(chip_np, "reg");89 if (nsels < 0)90 return nsels;91 92 dchip = devm_kzalloc(denali->dev, struct_size(dchip, sels, nsels),93 GFP_KERNEL);94 if (!dchip)95 return -ENOMEM;96 97 dchip->nsels = nsels;98 99 for (i = 0; i < nsels; i++) {100 ret = of_property_read_u32_index(chip_np, "reg", i, &bank);101 if (ret)102 return ret;103 104 dchip->sels[i].bank = bank;105 106 nand_set_flash_node(&dchip->chip, chip_np);107 }108 109 return denali_chip_init(denali, dchip);110}111 112static int denali_dt_probe(struct platform_device *pdev)113{114 struct device *dev = &pdev->dev;115 struct denali_dt *dt;116 const struct denali_dt_data *data;117 struct denali_controller *denali;118 struct device_node *np;119 int ret;120 121 dt = devm_kzalloc(dev, sizeof(*dt), GFP_KERNEL);122 if (!dt)123 return -ENOMEM;124 denali = &dt->controller;125 126 data = of_device_get_match_data(dev);127 if (WARN_ON(!data))128 return -EINVAL;129 130 denali->revision = data->revision;131 denali->caps = data->caps;132 denali->oob_skip_bytes = data->oob_skip_bytes;133 denali->ecc_caps = data->ecc_caps;134 135 denali->dev = dev;136 denali->irq = platform_get_irq(pdev, 0);137 if (denali->irq < 0)138 return denali->irq;139 140 denali->reg = devm_platform_ioremap_resource_byname(pdev, "denali_reg");141 if (IS_ERR(denali->reg))142 return PTR_ERR(denali->reg);143 144 denali->host = devm_platform_ioremap_resource_byname(pdev, "nand_data");145 if (IS_ERR(denali->host))146 return PTR_ERR(denali->host);147 148 dt->clk = devm_clk_get_enabled(dev, "nand");149 if (IS_ERR(dt->clk))150 return PTR_ERR(dt->clk);151 152 dt->clk_x = devm_clk_get_enabled(dev, "nand_x");153 if (IS_ERR(dt->clk_x))154 return PTR_ERR(dt->clk_x);155 156 dt->clk_ecc = devm_clk_get_enabled(dev, "ecc");157 if (IS_ERR(dt->clk_ecc))158 return PTR_ERR(dt->clk_ecc);159 160 dt->rst = devm_reset_control_get_optional_shared(dev, "nand");161 if (IS_ERR(dt->rst))162 return PTR_ERR(dt->rst);163 164 dt->rst_reg = devm_reset_control_get_optional_shared(dev, "reg");165 if (IS_ERR(dt->rst_reg))166 return PTR_ERR(dt->rst_reg);167 168 denali->clk_rate = clk_get_rate(dt->clk);169 denali->clk_x_rate = clk_get_rate(dt->clk_x);170 171 /*172 * Deassert the register reset, and the core reset in this order.173 * Deasserting the core reset while the register reset is asserted174 * will cause unpredictable behavior in the controller.175 */176 ret = reset_control_deassert(dt->rst_reg);177 if (ret)178 return ret;179 180 ret = reset_control_deassert(dt->rst);181 if (ret)182 goto out_assert_rst_reg;183 184 /*185 * When the reset is deasserted, the initialization sequence is kicked186 * (bootstrap process). The driver must wait until it finished.187 * Otherwise, it will result in unpredictable behavior.188 */189 usleep_range(200, 1000);190 191 ret = denali_init(denali);192 if (ret)193 goto out_assert_rst;194 195 for_each_child_of_node(dev->of_node, np) {196 ret = denali_dt_chip_init(denali, np);197 if (ret) {198 of_node_put(np);199 goto out_remove_denali;200 }201 }202 203 platform_set_drvdata(pdev, dt);204 205 return 0;206 207out_remove_denali:208 denali_remove(denali);209out_assert_rst:210 reset_control_assert(dt->rst);211out_assert_rst_reg:212 reset_control_assert(dt->rst_reg);213 214 return ret;215}216 217static void denali_dt_remove(struct platform_device *pdev)218{219 struct denali_dt *dt = platform_get_drvdata(pdev);220 221 denali_remove(&dt->controller);222 reset_control_assert(dt->rst);223 reset_control_assert(dt->rst_reg);224}225 226static struct platform_driver denali_dt_driver = {227 .probe = denali_dt_probe,228 .remove_new = denali_dt_remove,229 .driver = {230 .name = "denali-nand-dt",231 .of_match_table = denali_nand_dt_ids,232 },233};234module_platform_driver(denali_dt_driver);235 236MODULE_LICENSE("GPL v2");237MODULE_AUTHOR("Jamie Iles");238MODULE_DESCRIPTION("DT driver for Denali NAND controller");239