1 /*
2  * Interface for NOR flash driver whose high address lines are latched
3  *
4  * Copyright © 2000 Nicolas Pitre <nico@cam.org>
5  * Copyright © 2005-2008 Analog Devices Inc.
6  * Copyright © 2008 MontaVista Software, Inc. <source@mvista.com>
7  *
8  * This file is licensed under the terms of the GNU General Public License
9  * version 2. This program is licensed "as is" without any warranty of any
10  * kind, whether express or implied.
11  */
12 
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/mtd/mtd.h>
17 #include <linux/mtd/map.h>
18 #include <linux/mtd/partitions.h>
19 #include <linux/platform_device.h>
20 #include <linux/mtd/latch-addr-flash.h>
21 #include <linux/slab.h>
22 
23 #define DRIVER_NAME "latch-addr-flash"
24 
25 struct latch_addr_flash_info {
26 	struct mtd_info		*mtd;
27 	struct map_info		map;
28 	struct resource		*res;
29 
30 	void			(*set_window)(unsigned long offset, void *data);
31 	void			*data;
32 
33 	/* cache; could be found out of res */
34 	unsigned long		win_mask;
35 
36 	spinlock_t		lock;
37 };
38 
lf_read(struct map_info * map,unsigned long ofs)39 static map_word lf_read(struct map_info *map, unsigned long ofs)
40 {
41 	struct latch_addr_flash_info *info;
42 	map_word datum;
43 
44 	info = (struct latch_addr_flash_info *)map->map_priv_1;
45 
46 	spin_lock(&info->lock);
47 
48 	info->set_window(ofs, info->data);
49 	datum = inline_map_read(map, info->win_mask & ofs);
50 
51 	spin_unlock(&info->lock);
52 
53 	return datum;
54 }
55 
lf_write(struct map_info * map,map_word datum,unsigned long ofs)56 static void lf_write(struct map_info *map, map_word datum, unsigned long ofs)
57 {
58 	struct latch_addr_flash_info *info;
59 
60 	info = (struct latch_addr_flash_info *)map->map_priv_1;
61 
62 	spin_lock(&info->lock);
63 
64 	info->set_window(ofs, info->data);
65 	inline_map_write(map, datum, info->win_mask & ofs);
66 
67 	spin_unlock(&info->lock);
68 }
69 
lf_copy_from(struct map_info * map,void * to,unsigned long from,ssize_t len)70 static void lf_copy_from(struct map_info *map, void *to,
71 		unsigned long from, ssize_t len)
72 {
73 	struct latch_addr_flash_info *info =
74 		(struct latch_addr_flash_info *) map->map_priv_1;
75 	unsigned n;
76 
77 	while (len > 0) {
78 		n = info->win_mask + 1 - (from & info->win_mask);
79 		if (n > len)
80 			n = len;
81 
82 		spin_lock(&info->lock);
83 
84 		info->set_window(from, info->data);
85 		memcpy_fromio(to, map->virt + (from & info->win_mask), n);
86 
87 		spin_unlock(&info->lock);
88 
89 		to += n;
90 		from += n;
91 		len -= n;
92 	}
93 }
94 
95 static char *rom_probe_types[] = { "cfi_probe", NULL };
96 
latch_addr_flash_remove(struct platform_device * dev)97 static int latch_addr_flash_remove(struct platform_device *dev)
98 {
99 	struct latch_addr_flash_info *info;
100 	struct latch_addr_flash_data *latch_addr_data;
101 
102 	info = platform_get_drvdata(dev);
103 	if (info == NULL)
104 		return 0;
105 	platform_set_drvdata(dev, NULL);
106 
107 	latch_addr_data = dev->dev.platform_data;
108 
109 	if (info->mtd != NULL) {
110 		mtd_device_unregister(info->mtd);
111 		map_destroy(info->mtd);
112 	}
113 
114 	if (info->map.virt != NULL)
115 		iounmap(info->map.virt);
116 
117 	if (info->res != NULL)
118 		release_mem_region(info->res->start, resource_size(info->res));
119 
120 	kfree(info);
121 
122 	if (latch_addr_data->done)
123 		latch_addr_data->done(latch_addr_data->data);
124 
125 	return 0;
126 }
127 
latch_addr_flash_probe(struct platform_device * dev)128 static int __devinit latch_addr_flash_probe(struct platform_device *dev)
129 {
130 	struct latch_addr_flash_data *latch_addr_data;
131 	struct latch_addr_flash_info *info;
132 	resource_size_t win_base = dev->resource->start;
133 	resource_size_t win_size = resource_size(dev->resource);
134 	char **probe_type;
135 	int chipsel;
136 	int err;
137 
138 	latch_addr_data = dev->dev.platform_data;
139 	if (latch_addr_data == NULL)
140 		return -ENODEV;
141 
142 	pr_notice("latch-addr platform flash device: %#llx byte "
143 		  "window at %#.8llx\n",
144 		  (unsigned long long)win_size, (unsigned long long)win_base);
145 
146 	chipsel = dev->id;
147 
148 	if (latch_addr_data->init) {
149 		err = latch_addr_data->init(latch_addr_data->data, chipsel);
150 		if (err != 0)
151 			return err;
152 	}
153 
154 	info = kzalloc(sizeof(struct latch_addr_flash_info), GFP_KERNEL);
155 	if (info == NULL) {
156 		err = -ENOMEM;
157 		goto done;
158 	}
159 
160 	platform_set_drvdata(dev, info);
161 
162 	info->res = request_mem_region(win_base, win_size, DRIVER_NAME);
163 	if (info->res == NULL) {
164 		dev_err(&dev->dev, "Could not reserve memory region\n");
165 		err = -EBUSY;
166 		goto free_info;
167 	}
168 
169 	info->map.name		= DRIVER_NAME;
170 	info->map.size		= latch_addr_data->size;
171 	info->map.bankwidth	= latch_addr_data->width;
172 
173 	info->map.phys		= NO_XIP;
174 	info->map.virt		= ioremap(win_base, win_size);
175 	if (!info->map.virt) {
176 		err = -ENOMEM;
177 		goto free_res;
178 	}
179 
180 	info->map.map_priv_1	= (unsigned long)info;
181 
182 	info->map.read		= lf_read;
183 	info->map.copy_from	= lf_copy_from;
184 	info->map.write		= lf_write;
185 	info->set_window	= latch_addr_data->set_window;
186 	info->data		= latch_addr_data->data;
187 	info->win_mask		= win_size - 1;
188 
189 	spin_lock_init(&info->lock);
190 
191 	for (probe_type = rom_probe_types; !info->mtd && *probe_type;
192 		probe_type++)
193 		info->mtd = do_map_probe(*probe_type, &info->map);
194 
195 	if (info->mtd == NULL) {
196 		dev_err(&dev->dev, "map_probe failed\n");
197 		err = -ENODEV;
198 		goto iounmap;
199 	}
200 	info->mtd->owner = THIS_MODULE;
201 
202 	mtd_device_parse_register(info->mtd, NULL, 0,
203 			latch_addr_data->parts, latch_addr_data->nr_parts);
204 	return 0;
205 
206 iounmap:
207 	iounmap(info->map.virt);
208 free_res:
209 	release_mem_region(info->res->start, resource_size(info->res));
210 free_info:
211 	kfree(info);
212 done:
213 	if (latch_addr_data->done)
214 		latch_addr_data->done(latch_addr_data->data);
215 	return err;
216 }
217 
218 static struct platform_driver latch_addr_flash_driver = {
219 	.probe		= latch_addr_flash_probe,
220 	.remove		= __devexit_p(latch_addr_flash_remove),
221 	.driver		= {
222 		.name	= DRIVER_NAME,
223 	},
224 };
225 
226 module_platform_driver(latch_addr_flash_driver);
227 
228 MODULE_AUTHOR("David Griego <dgriego@mvista.com>");
229 MODULE_DESCRIPTION("MTD map driver for flashes addressed physically with upper "
230 		"address lines being set board specifically");
231 MODULE_LICENSE("GPL v2");
232