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