mediatek: remove "Ralink" from the target name
[openwrt/openwrt.git] / target / linux / lantiq / patches-5.15 / 0160-owrt-lantiq-multiple-flash.patch
1 From ebaae1cd68cd79c7eee67c9c5c0fa45809e84525 Mon Sep 17 00:00:00 2001
2 From: Maikel Bloemendal <openwrt@maikelenyvonne.nl>
3 Date: Fri, 14 Nov 2014 17:06:00 +0000
4 Subject: [PATCH] owrt: lantiq: multiple flash
5
6 Signed-off-by: Maikel Bloemendal <openwrt@maikelenyvonne.nl>
7 ---
8 drivers/mtd/maps/lantiq-flash.c | 168 +++++++++++++++++++++-----------
9 1 file changed, 109 insertions(+), 59 deletions(-)
10
11 --- a/drivers/mtd/maps/lantiq-flash.c
12 +++ b/drivers/mtd/maps/lantiq-flash.c
13 @@ -17,6 +17,7 @@
14 #include <linux/mtd/cfi.h>
15 #include <linux/platform_device.h>
16 #include <linux/mtd/physmap.h>
17 +#include <linux/mtd/concat.h>
18 #include <linux/of.h>
19
20 #include <lantiq_soc.h>
21 @@ -36,13 +37,16 @@ enum {
22 LTQ_NOR_NORMAL
23 };
24
25 +#define MAX_RESOURCES 4
26 +
27 struct ltq_mtd {
28 - struct resource *res;
29 - struct mtd_info *mtd;
30 - struct map_info *map;
31 + struct mtd_info *mtd[MAX_RESOURCES];
32 + struct mtd_info *cmtd;
33 + struct map_info map[MAX_RESOURCES];
34 };
35
36 static const char ltq_map_name[] = "ltq_nor";
37 +static const char * const ltq_probe_types[] = { "cmdlinepart", "ofpart", NULL };
38
39 static map_word
40 ltq_read16(struct map_info *map, unsigned long adr)
41 @@ -106,11 +110,43 @@ ltq_copy_to(struct map_info *map, unsign
42 }
43
44 static int
45 +ltq_mtd_remove(struct platform_device *pdev)
46 +{
47 + struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev);
48 + int i;
49 +
50 + if (ltq_mtd == NULL)
51 + return 0;
52 +
53 + if (ltq_mtd->cmtd) {
54 + mtd_device_unregister(ltq_mtd->cmtd);
55 + if (ltq_mtd->cmtd != ltq_mtd->mtd[0])
56 + mtd_concat_destroy(ltq_mtd->cmtd);
57 + }
58 +
59 + for (i = 0; i < MAX_RESOURCES; i++) {
60 + if (ltq_mtd->mtd[i] != NULL)
61 + map_destroy(ltq_mtd->mtd[i]);
62 + }
63 +
64 + kfree(ltq_mtd);
65 +
66 + return 0;
67 +}
68 +
69 +static int
70 ltq_mtd_probe(struct platform_device *pdev)
71 {
72 struct ltq_mtd *ltq_mtd;
73 struct cfi_private *cfi;
74 - int err;
75 + int err = 0;
76 + int i;
77 + int devices_found = 0;
78 +
79 + static const char *rom_probe_types[] = {
80 + "cfi_probe", "jedec_probe", NULL
81 + };
82 + const char **type;
83
84 ltq_mtd = devm_kzalloc(&pdev->dev, sizeof(struct ltq_mtd), GFP_KERNEL);
85 if (!ltq_mtd)
86 @@ -118,75 +154,89 @@ ltq_mtd_probe(struct platform_device *pd
87
88 platform_set_drvdata(pdev, ltq_mtd);
89
90 - ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
91 - if (!ltq_mtd->res) {
92 - dev_err(&pdev->dev, "failed to get memory resource\n");
93 - return -ENOENT;
94 + for (i = 0; i < pdev->num_resources; i++) {
95 + printk(KERN_NOTICE "lantiq nor flash device: %.8llx at %.8llx\n",
96 + (unsigned long long)resource_size(&pdev->resource[i]),
97 + (unsigned long long)pdev->resource[i].start);
98 +
99 + if (!devm_request_mem_region(&pdev->dev,
100 + pdev->resource[i].start,
101 + resource_size(&pdev->resource[i]),
102 + dev_name(&pdev->dev))) {
103 + dev_err(&pdev->dev, "Could not reserve memory region\n");
104 + return -ENOMEM;
105 + }
106 +
107 + ltq_mtd->map[i].name = ltq_map_name;
108 + ltq_mtd->map[i].bankwidth = 2;
109 + ltq_mtd->map[i].read = ltq_read16;
110 + ltq_mtd->map[i].write = ltq_write16;
111 + ltq_mtd->map[i].copy_from = ltq_copy_from;
112 + ltq_mtd->map[i].copy_to = ltq_copy_to;
113 +
114 + if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL))
115 + ltq_mtd->map[i].phys = NO_XIP;
116 + else
117 + ltq_mtd->map[i].phys = pdev->resource[i].start;
118 + ltq_mtd->map[i].size = resource_size(&pdev->resource[i]);
119 + ltq_mtd->map[i].virt = devm_ioremap(&pdev->dev, pdev->resource[i].start,
120 + ltq_mtd->map[i].size);
121 + if (IS_ERR(ltq_mtd->map[i].virt))
122 + return PTR_ERR(ltq_mtd->map[i].virt);
123 +
124 + if (ltq_mtd->map[i].virt == NULL) {
125 + dev_err(&pdev->dev, "Failed to ioremap flash region\n");
126 + err = PTR_ERR(ltq_mtd->map[i].virt);
127 + goto err_out;
128 + }
129 +
130 + ltq_mtd->map[i].map_priv_1 = LTQ_NOR_PROBING;
131 + for (type = rom_probe_types; !ltq_mtd->mtd[i] && *type; type++)
132 + ltq_mtd->mtd[i] = do_map_probe(*type, &ltq_mtd->map[i]);
133 + ltq_mtd->map[i].map_priv_1 = LTQ_NOR_NORMAL;
134 +
135 + if (!ltq_mtd->mtd[i]) {
136 + dev_err(&pdev->dev, "probing failed\n");
137 + return -ENXIO;
138 + } else {
139 + devices_found++;
140 + }
141 +
142 + ltq_mtd->mtd[i]->owner = THIS_MODULE;
143 + ltq_mtd->mtd[i]->dev.parent = &pdev->dev;
144 +
145 + cfi = ltq_mtd->map[i].fldrv_priv;
146 + cfi->addr_unlock1 ^= 1;
147 + cfi->addr_unlock2 ^= 1;
148 }
149
150 - ltq_mtd->map = devm_kzalloc(&pdev->dev, sizeof(struct map_info),
151 - GFP_KERNEL);
152 - if (!ltq_mtd->map)
153 - return -ENOMEM;
154 -
155 - if (of_find_property(pdev->dev.of_node, "lantiq,noxip", NULL))
156 - ltq_mtd->map->phys = NO_XIP;
157 - else
158 - ltq_mtd->map->phys = ltq_mtd->res->start;
159 - ltq_mtd->res->start;
160 - ltq_mtd->map->size = resource_size(ltq_mtd->res);
161 - ltq_mtd->map->virt = devm_ioremap_resource(&pdev->dev, ltq_mtd->res);
162 - if (IS_ERR(ltq_mtd->map->virt))
163 - return PTR_ERR(ltq_mtd->map->virt);
164 -
165 - ltq_mtd->map->name = ltq_map_name;
166 - ltq_mtd->map->bankwidth = 2;
167 - ltq_mtd->map->read = ltq_read16;
168 - ltq_mtd->map->write = ltq_write16;
169 - ltq_mtd->map->copy_from = ltq_copy_from;
170 - ltq_mtd->map->copy_to = ltq_copy_to;
171 -
172 - ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING;
173 - ltq_mtd->mtd = do_map_probe("cfi_probe", ltq_mtd->map);
174 - ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL;
175 -
176 - if (!ltq_mtd->mtd) {
177 - dev_err(&pdev->dev, "probing failed\n");
178 - return -ENXIO;
179 + if (devices_found == 1) {
180 + ltq_mtd->cmtd = ltq_mtd->mtd[0];
181 + } else if (devices_found > 1) {
182 + /*
183 + * We detected multiple devices. Concatenate them together.
184 + */
185 + ltq_mtd->cmtd = mtd_concat_create(ltq_mtd->mtd, devices_found, dev_name(&pdev->dev));
186 + if (ltq_mtd->cmtd == NULL)
187 + err = -ENXIO;
188 }
189
190 - ltq_mtd->mtd->dev.parent = &pdev->dev;
191 - mtd_set_of_node(ltq_mtd->mtd, pdev->dev.of_node);
192 -
193 - cfi = ltq_mtd->map->fldrv_priv;
194 - cfi->addr_unlock1 ^= 1;
195 - cfi->addr_unlock2 ^= 1;
196 + ltq_mtd->cmtd->dev.parent = &pdev->dev;
197 + mtd_set_of_node(ltq_mtd->cmtd, pdev->dev.of_node);
198
199 - err = mtd_device_register(ltq_mtd->mtd, NULL, 0);
200 + err = mtd_device_register(ltq_mtd->cmtd, NULL, 0);
201 if (err) {
202 dev_err(&pdev->dev, "failed to add partitions\n");
203 - goto err_destroy;
204 + goto err_out;
205 }
206
207 return 0;
208
209 -err_destroy:
210 - map_destroy(ltq_mtd->mtd);
211 +err_out:
212 + ltq_mtd_remove(pdev);
213 return err;
214 }
215
216 -static int
217 -ltq_mtd_remove(struct platform_device *pdev)
218 -{
219 - struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev);
220 -
221 - if (ltq_mtd && ltq_mtd->mtd) {
222 - mtd_device_unregister(ltq_mtd->mtd);
223 - map_destroy(ltq_mtd->mtd);
224 - }
225 - return 0;
226 -}
227 -
228 static const struct of_device_id ltq_mtd_match[] = {
229 { .compatible = "lantiq,nor" },
230 {},