1 /*
2  * Copyright 2011 Tilera Corporation. All Rights Reserved.
3  *
4  *   This program is free software; you can redistribute it and/or
5  *   modify it under the terms of the GNU General Public License
6  *   as published by the Free Software Foundation, version 2.
7  *
8  *   This program is distributed in the hope that it will be useful, but
9  *   WITHOUT ANY WARRANTY; without even the implied warranty of
10  *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11  *   NON INFRINGEMENT.  See the GNU General Public License for
12  *   more details.
13  *
14  * SPI Flash ROM driver
15  *
16  * This source code is derived from code provided in "Linux Device
17  * Drivers, Third Edition", by Jonathan Corbet, Alessandro Rubini, and
18  * Greg Kroah-Hartman, published by O'Reilly Media, Inc.
19  */
20 
21 #include <linux/module.h>
22 #include <linux/moduleparam.h>
23 #include <linux/init.h>
24 #include <linux/kernel.h>	/* printk() */
25 #include <linux/slab.h>		/* kmalloc() */
26 #include <linux/fs.h>		/* everything... */
27 #include <linux/errno.h>	/* error codes */
28 #include <linux/types.h>	/* size_t */
29 #include <linux/proc_fs.h>
30 #include <linux/fcntl.h>	/* O_ACCMODE */
31 #include <linux/aio.h>
32 #include <linux/pagemap.h>
33 #include <linux/hugetlb.h>
34 #include <linux/uaccess.h>
35 #include <linux/platform_device.h>
36 #include <hv/hypervisor.h>
37 #include <linux/ioctl.h>
38 #include <linux/cdev.h>
39 #include <linux/delay.h>
40 #include <hv/drv_srom_intf.h>
41 
42 /*
43  * Size of our hypervisor I/O requests.  We break up large transfers
44  * so that we don't spend large uninterrupted spans of time in the
45  * hypervisor.  Erasing an SROM sector takes a significant fraction of
46  * a second, so if we allowed the user to, say, do one I/O to write the
47  * entire ROM, we'd get soft lockup timeouts, or worse.
48  */
49 #define SROM_CHUNK_SIZE ((size_t)4096)
50 
51 /*
52  * When hypervisor is busy (e.g. erasing), poll the status periodically.
53  */
54 
55 /*
56  * Interval to poll the state in msec
57  */
58 #define SROM_WAIT_TRY_INTERVAL 20
59 
60 /*
61  * Maximum times to poll the state
62  */
63 #define SROM_MAX_WAIT_TRY_TIMES 1000
64 
65 struct srom_dev {
66 	int hv_devhdl;			/* Handle for hypervisor device */
67 	u32 total_size;			/* Size of this device */
68 	u32 sector_size;		/* Size of a sector */
69 	u32 page_size;			/* Size of a page */
70 	struct mutex lock;		/* Allow only one accessor at a time */
71 };
72 
73 static int srom_major;			/* Dynamic major by default */
74 module_param(srom_major, int, 0);
75 MODULE_AUTHOR("Tilera Corporation");
76 MODULE_LICENSE("GPL");
77 
78 static int srom_devs;			/* Number of SROM partitions */
79 static struct cdev srom_cdev;
80 static struct class *srom_class;
81 static struct srom_dev *srom_devices;
82 
83 /*
84  * Handle calling the hypervisor and managing EAGAIN/EBUSY.
85  */
86 
_srom_read(int hv_devhdl,void * buf,loff_t off,size_t count)87 static ssize_t _srom_read(int hv_devhdl, void *buf,
88 			  loff_t off, size_t count)
89 {
90 	int retval, retries = SROM_MAX_WAIT_TRY_TIMES;
91 	for (;;) {
92 		retval = hv_dev_pread(hv_devhdl, 0, (HV_VirtAddr)buf,
93 				      count, off);
94 		if (retval >= 0)
95 			return retval;
96 		if (retval == HV_EAGAIN)
97 			continue;
98 		if (retval == HV_EBUSY && --retries > 0) {
99 			msleep(SROM_WAIT_TRY_INTERVAL);
100 			continue;
101 		}
102 		pr_err("_srom_read: error %d\n", retval);
103 		return -EIO;
104 	}
105 }
106 
_srom_write(int hv_devhdl,const void * buf,loff_t off,size_t count)107 static ssize_t _srom_write(int hv_devhdl, const void *buf,
108 			   loff_t off, size_t count)
109 {
110 	int retval, retries = SROM_MAX_WAIT_TRY_TIMES;
111 	for (;;) {
112 		retval = hv_dev_pwrite(hv_devhdl, 0, (HV_VirtAddr)buf,
113 				       count, off);
114 		if (retval >= 0)
115 			return retval;
116 		if (retval == HV_EAGAIN)
117 			continue;
118 		if (retval == HV_EBUSY && --retries > 0) {
119 			msleep(SROM_WAIT_TRY_INTERVAL);
120 			continue;
121 		}
122 		pr_err("_srom_write: error %d\n", retval);
123 		return -EIO;
124 	}
125 }
126 
127 /**
128  * srom_open() - Device open routine.
129  * @inode: Inode for this device.
130  * @filp: File for this specific open of the device.
131  *
132  * Returns zero, or an error code.
133  */
srom_open(struct inode * inode,struct file * filp)134 static int srom_open(struct inode *inode, struct file *filp)
135 {
136 	filp->private_data = &srom_devices[iminor(inode)];
137 	return 0;
138 }
139 
140 
141 /**
142  * srom_release() - Device release routine.
143  * @inode: Inode for this device.
144  * @filp: File for this specific open of the device.
145  *
146  * Returns zero, or an error code.
147  */
srom_release(struct inode * inode,struct file * filp)148 static int srom_release(struct inode *inode, struct file *filp)
149 {
150 	struct srom_dev *srom = filp->private_data;
151 	char dummy;
152 
153 	/* Make sure we've flushed anything written to the ROM. */
154 	mutex_lock(&srom->lock);
155 	if (srom->hv_devhdl >= 0)
156 		_srom_write(srom->hv_devhdl, &dummy, SROM_FLUSH_OFF, 1);
157 	mutex_unlock(&srom->lock);
158 
159 	filp->private_data = NULL;
160 
161 	return 0;
162 }
163 
164 
165 /**
166  * srom_read() - Read data from the device.
167  * @filp: File for this specific open of the device.
168  * @buf: User's data buffer.
169  * @count: Number of bytes requested.
170  * @f_pos: File position.
171  *
172  * Returns number of bytes read, or an error code.
173  */
srom_read(struct file * filp,char __user * buf,size_t count,loff_t * f_pos)174 static ssize_t srom_read(struct file *filp, char __user *buf,
175 			 size_t count, loff_t *f_pos)
176 {
177 	int retval = 0;
178 	void *kernbuf;
179 	struct srom_dev *srom = filp->private_data;
180 
181 	kernbuf = kmalloc(SROM_CHUNK_SIZE, GFP_KERNEL);
182 	if (!kernbuf)
183 		return -ENOMEM;
184 
185 	if (mutex_lock_interruptible(&srom->lock)) {
186 		retval = -ERESTARTSYS;
187 		kfree(kernbuf);
188 		return retval;
189 	}
190 
191 	while (count) {
192 		int hv_retval;
193 		int bytes_this_pass = min(count, SROM_CHUNK_SIZE);
194 
195 		hv_retval = _srom_read(srom->hv_devhdl, kernbuf,
196 				       *f_pos, bytes_this_pass);
197 		if (hv_retval <= 0) {
198 			if (retval == 0)
199 				retval = hv_retval;
200 			break;
201 		}
202 
203 		if (copy_to_user(buf, kernbuf, hv_retval) != 0) {
204 			retval = -EFAULT;
205 			break;
206 		}
207 
208 		retval += hv_retval;
209 		*f_pos += hv_retval;
210 		buf += hv_retval;
211 		count -= hv_retval;
212 	}
213 
214 	mutex_unlock(&srom->lock);
215 	kfree(kernbuf);
216 
217 	return retval;
218 }
219 
220 /**
221  * srom_write() - Write data to the device.
222  * @filp: File for this specific open of the device.
223  * @buf: User's data buffer.
224  * @count: Number of bytes requested.
225  * @f_pos: File position.
226  *
227  * Returns number of bytes written, or an error code.
228  */
srom_write(struct file * filp,const char __user * buf,size_t count,loff_t * f_pos)229 static ssize_t srom_write(struct file *filp, const char __user *buf,
230 			  size_t count, loff_t *f_pos)
231 {
232 	int retval = 0;
233 	void *kernbuf;
234 	struct srom_dev *srom = filp->private_data;
235 
236 	kernbuf = kmalloc(SROM_CHUNK_SIZE, GFP_KERNEL);
237 	if (!kernbuf)
238 		return -ENOMEM;
239 
240 	if (mutex_lock_interruptible(&srom->lock)) {
241 		retval = -ERESTARTSYS;
242 		kfree(kernbuf);
243 		return retval;
244 	}
245 
246 	while (count) {
247 		int hv_retval;
248 		int bytes_this_pass = min(count, SROM_CHUNK_SIZE);
249 
250 		if (copy_from_user(kernbuf, buf, bytes_this_pass) != 0) {
251 			retval = -EFAULT;
252 			break;
253 		}
254 
255 		hv_retval = _srom_write(srom->hv_devhdl, kernbuf,
256 					*f_pos, bytes_this_pass);
257 		if (hv_retval <= 0) {
258 			if (retval == 0)
259 				retval = hv_retval;
260 			break;
261 		}
262 
263 		retval += hv_retval;
264 		*f_pos += hv_retval;
265 		buf += hv_retval;
266 		count -= hv_retval;
267 	}
268 
269 	mutex_unlock(&srom->lock);
270 	kfree(kernbuf);
271 
272 	return retval;
273 }
274 
275 /* Provide our own implementation so we can use srom->total_size. */
srom_llseek(struct file * filp,loff_t offset,int origin)276 loff_t srom_llseek(struct file *filp, loff_t offset, int origin)
277 {
278 	struct srom_dev *srom = filp->private_data;
279 
280 	if (mutex_lock_interruptible(&srom->lock))
281 		return -ERESTARTSYS;
282 
283 	switch (origin) {
284 	case SEEK_END:
285 		offset += srom->total_size;
286 		break;
287 	case SEEK_CUR:
288 		offset += filp->f_pos;
289 		break;
290 	}
291 
292 	if (offset < 0 || offset > srom->total_size) {
293 		offset = -EINVAL;
294 	} else {
295 		filp->f_pos = offset;
296 		filp->f_version = 0;
297 	}
298 
299 	mutex_unlock(&srom->lock);
300 
301 	return offset;
302 }
303 
total_show(struct device * dev,struct device_attribute * attr,char * buf)304 static ssize_t total_show(struct device *dev,
305 			  struct device_attribute *attr, char *buf)
306 {
307 	struct srom_dev *srom = dev_get_drvdata(dev);
308 	return sprintf(buf, "%u\n", srom->total_size);
309 }
310 
sector_show(struct device * dev,struct device_attribute * attr,char * buf)311 static ssize_t sector_show(struct device *dev,
312 			   struct device_attribute *attr, char *buf)
313 {
314 	struct srom_dev *srom = dev_get_drvdata(dev);
315 	return sprintf(buf, "%u\n", srom->sector_size);
316 }
317 
page_show(struct device * dev,struct device_attribute * attr,char * buf)318 static ssize_t page_show(struct device *dev,
319 			 struct device_attribute *attr, char *buf)
320 {
321 	struct srom_dev *srom = dev_get_drvdata(dev);
322 	return sprintf(buf, "%u\n", srom->page_size);
323 }
324 
325 static struct device_attribute srom_dev_attrs[] = {
326 	__ATTR(total_size, S_IRUGO, total_show, NULL),
327 	__ATTR(sector_size, S_IRUGO, sector_show, NULL),
328 	__ATTR(page_size, S_IRUGO, page_show, NULL),
329 	__ATTR_NULL
330 };
331 
srom_devnode(struct device * dev,umode_t * mode)332 static char *srom_devnode(struct device *dev, umode_t *mode)
333 {
334 	*mode = S_IRUGO | S_IWUSR;
335 	return kasprintf(GFP_KERNEL, "srom/%s", dev_name(dev));
336 }
337 
338 /*
339  * The fops
340  */
341 static const struct file_operations srom_fops = {
342 	.owner =     THIS_MODULE,
343 	.llseek =    srom_llseek,
344 	.read =	     srom_read,
345 	.write =     srom_write,
346 	.open =	     srom_open,
347 	.release =   srom_release,
348 };
349 
350 /**
351  * srom_setup_minor() - Initialize per-minor information.
352  * @srom: Per-device SROM state.
353  * @index: Device to set up.
354  */
srom_setup_minor(struct srom_dev * srom,int index)355 static int srom_setup_minor(struct srom_dev *srom, int index)
356 {
357 	struct device *dev;
358 	int devhdl = srom->hv_devhdl;
359 
360 	mutex_init(&srom->lock);
361 
362 	if (_srom_read(devhdl, &srom->total_size,
363 		       SROM_TOTAL_SIZE_OFF, sizeof(srom->total_size)) < 0)
364 		return -EIO;
365 	if (_srom_read(devhdl, &srom->sector_size,
366 		       SROM_SECTOR_SIZE_OFF, sizeof(srom->sector_size)) < 0)
367 		return -EIO;
368 	if (_srom_read(devhdl, &srom->page_size,
369 		       SROM_PAGE_SIZE_OFF, sizeof(srom->page_size)) < 0)
370 		return -EIO;
371 
372 	dev = device_create(srom_class, &platform_bus,
373 			    MKDEV(srom_major, index), srom, "%d", index);
374 	return IS_ERR(dev) ? PTR_ERR(dev) : 0;
375 }
376 
377 /** srom_init() - Initialize the driver's module. */
srom_init(void)378 static int srom_init(void)
379 {
380 	int result, i;
381 	dev_t dev = MKDEV(srom_major, 0);
382 
383 	/*
384 	 * Start with a plausible number of partitions; the krealloc() call
385 	 * below will yield about log(srom_devs) additional allocations.
386 	 */
387 	srom_devices = kzalloc(4 * sizeof(struct srom_dev), GFP_KERNEL);
388 
389 	/* Discover the number of srom partitions. */
390 	for (i = 0; ; i++) {
391 		int devhdl;
392 		char buf[20];
393 		struct srom_dev *new_srom_devices =
394 			krealloc(srom_devices, (i+1) * sizeof(struct srom_dev),
395 				 GFP_KERNEL | __GFP_ZERO);
396 		if (!new_srom_devices) {
397 			result = -ENOMEM;
398 			goto fail_mem;
399 		}
400 		srom_devices = new_srom_devices;
401 		sprintf(buf, "srom/0/%d", i);
402 		devhdl = hv_dev_open((HV_VirtAddr)buf, 0);
403 		if (devhdl < 0) {
404 			if (devhdl != HV_ENODEV)
405 				pr_notice("srom/%d: hv_dev_open failed: %d.\n",
406 					  i, devhdl);
407 			break;
408 		}
409 		srom_devices[i].hv_devhdl = devhdl;
410 	}
411 	srom_devs = i;
412 
413 	/* Bail out early if we have no partitions at all. */
414 	if (srom_devs == 0) {
415 		result = -ENODEV;
416 		goto fail_mem;
417 	}
418 
419 	/* Register our major, and accept a dynamic number. */
420 	if (srom_major)
421 		result = register_chrdev_region(dev, srom_devs, "srom");
422 	else {
423 		result = alloc_chrdev_region(&dev, 0, srom_devs, "srom");
424 		srom_major = MAJOR(dev);
425 	}
426 	if (result < 0)
427 		goto fail_mem;
428 
429 	/* Register a character device. */
430 	cdev_init(&srom_cdev, &srom_fops);
431 	srom_cdev.owner = THIS_MODULE;
432 	srom_cdev.ops = &srom_fops;
433 	result = cdev_add(&srom_cdev, dev, srom_devs);
434 	if (result < 0)
435 		goto fail_chrdev;
436 
437 	/* Create a sysfs class. */
438 	srom_class = class_create(THIS_MODULE, "srom");
439 	if (IS_ERR(srom_class)) {
440 		result = PTR_ERR(srom_class);
441 		goto fail_cdev;
442 	}
443 	srom_class->dev_attrs = srom_dev_attrs;
444 	srom_class->devnode = srom_devnode;
445 
446 	/* Do per-partition initialization */
447 	for (i = 0; i < srom_devs; i++) {
448 		result = srom_setup_minor(srom_devices + i, i);
449 		if (result < 0)
450 			goto fail_class;
451 	}
452 
453 	return 0;
454 
455 fail_class:
456 	for (i = 0; i < srom_devs; i++)
457 		device_destroy(srom_class, MKDEV(srom_major, i));
458 	class_destroy(srom_class);
459 fail_cdev:
460 	cdev_del(&srom_cdev);
461 fail_chrdev:
462 	unregister_chrdev_region(dev, srom_devs);
463 fail_mem:
464 	kfree(srom_devices);
465 	return result;
466 }
467 
468 /** srom_cleanup() - Clean up the driver's module. */
srom_cleanup(void)469 static void srom_cleanup(void)
470 {
471 	int i;
472 	for (i = 0; i < srom_devs; i++)
473 		device_destroy(srom_class, MKDEV(srom_major, i));
474 	class_destroy(srom_class);
475 	cdev_del(&srom_cdev);
476 	unregister_chrdev_region(MKDEV(srom_major, 0), srom_devs);
477 	kfree(srom_devices);
478 }
479 
480 module_init(srom_init);
481 module_exit(srom_cleanup);
482