1
2
3
4
5
6
7#include <clk.h>
8#include <dm.h>
9#include <dm/device_compat.h>
10#include <linux/bug.h>
11#include <linux/delay.h>
12#include <linux/io.h>
13#include <linux/ioport.h>
14#include <linux/printk.h>
15#include <reset.h>
16
17#include "denali.h"
18
19struct denali_dt_data {
20 unsigned int revision;
21 unsigned int caps;
22 unsigned int oob_skip_bytes;
23 const struct nand_ecc_caps *ecc_caps;
24};
25
26NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps, denali_calc_ecc_bytes,
27 512, 8, 15);
28static const struct denali_dt_data denali_socfpga_data = {
29 .caps = DENALI_CAP_HW_ECC_FIXUP,
30 .oob_skip_bytes = 2,
31 .ecc_caps = &denali_socfpga_ecc_caps,
32};
33
34NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps, denali_calc_ecc_bytes,
35 1024, 8, 16, 24);
36static const struct denali_dt_data denali_uniphier_v5a_data = {
37 .caps = DENALI_CAP_HW_ECC_FIXUP |
38 DENALI_CAP_DMA_64BIT,
39 .oob_skip_bytes = 8,
40 .ecc_caps = &denali_uniphier_v5a_ecc_caps,
41};
42
43NAND_ECC_CAPS_SINGLE(denali_uniphier_v5b_ecc_caps, denali_calc_ecc_bytes,
44 1024, 8, 16);
45static const struct denali_dt_data denali_uniphier_v5b_data = {
46 .revision = 0x0501,
47 .caps = DENALI_CAP_HW_ECC_FIXUP |
48 DENALI_CAP_DMA_64BIT,
49 .oob_skip_bytes = 8,
50 .ecc_caps = &denali_uniphier_v5b_ecc_caps,
51};
52
53static const struct udevice_id denali_nand_dt_ids[] = {
54 {
55 .compatible = "altr,socfpga-denali-nand",
56 .data = (unsigned long)&denali_socfpga_data,
57 },
58 {
59 .compatible = "socionext,uniphier-denali-nand-v5a",
60 .data = (unsigned long)&denali_uniphier_v5a_data,
61 },
62 {
63 .compatible = "socionext,uniphier-denali-nand-v5b",
64 .data = (unsigned long)&denali_uniphier_v5b_data,
65 },
66 { }
67};
68
69static int denali_dt_probe(struct udevice *dev)
70{
71 struct denali_nand_info *denali = dev_get_priv(dev);
72 const struct denali_dt_data *data;
73 struct clk clk, clk_x, clk_ecc;
74 struct reset_ctl_bulk resets;
75 struct resource res;
76 int ret;
77
78 data = (void *)dev_get_driver_data(dev);
79 if (WARN_ON(!data))
80 return -EINVAL;
81
82 denali->revision = data->revision;
83 denali->caps = data->caps;
84 denali->oob_skip_bytes = data->oob_skip_bytes;
85 denali->ecc_caps = data->ecc_caps;
86
87 denali->dev = dev;
88
89 ret = dev_read_resource_byname(dev, "denali_reg", &res);
90 if (ret)
91 return ret;
92
93 denali->reg = devm_ioremap(dev, res.start, resource_size(&res));
94
95 ret = dev_read_resource_byname(dev, "nand_data", &res);
96 if (ret)
97 return ret;
98
99 denali->host = devm_ioremap(dev, res.start, resource_size(&res));
100
101 ret = clk_get_by_name(dev, "nand", &clk);
102 if (ret)
103 ret = clk_get_by_index(dev, 0, &clk);
104 if (ret)
105 clk.dev = NULL;
106
107 ret = clk_get_by_name(dev, "nand_x", &clk_x);
108 if (ret)
109 clk_x.dev = NULL;
110
111 ret = clk_get_by_name(dev, "ecc", &clk_ecc);
112 if (ret)
113 clk_ecc.dev = NULL;
114
115 if (clk.dev) {
116 ret = clk_enable(&clk);
117 if (ret)
118 return ret;
119 }
120
121 if (clk_x.dev) {
122 ret = clk_enable(&clk_x);
123 if (ret)
124 return ret;
125 }
126
127 if (clk_ecc.dev) {
128 ret = clk_enable(&clk_ecc);
129 if (ret)
130 return ret;
131 }
132
133 if (clk_x.dev) {
134 denali->clk_rate = clk_get_rate(&clk);
135 denali->clk_x_rate = clk_get_rate(&clk_x);
136 } else {
137
138
139
140
141 dev_notice(dev,
142 "necessary clock is missing. default clock rates are used.\n");
143 denali->clk_rate = 50000000;
144 denali->clk_x_rate = 200000000;
145 }
146
147 ret = reset_get_bulk(dev, &resets);
148 if (ret) {
149 dev_warn(dev, "Can't get reset: %d\n", ret);
150 } else {
151 reset_assert_bulk(&resets);
152 udelay(2);
153 reset_deassert_bulk(&resets);
154
155
156
157
158
159
160 ret = denali_wait_reset_complete(denali);
161 if (ret) {
162 dev_err(denali->dev, "reset not completed.\n");
163 return ret;
164 }
165 }
166
167 return denali_init(denali);
168}
169
170U_BOOT_DRIVER(denali_nand_dt) = {
171 .name = "denali-nand-dt",
172 .id = UCLASS_MTD,
173 .of_match = denali_nand_dt_ids,
174 .probe = denali_dt_probe,
175 .priv_auto = sizeof(struct denali_nand_info),
176};
177
178void board_nand_init(void)
179{
180 struct udevice *dev;
181 int ret;
182
183 ret = uclass_get_device_by_driver(UCLASS_MTD,
184 DM_DRIVER_GET(denali_nand_dt),
185 &dev);
186 if (ret && ret != -ENODEV)
187 pr_err("Failed to initialize Denali NAND controller. (error %d)\n",
188 ret);
189}
190