aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/tile/include/hv/drv_srom_intf.h41
-rw-r--r--drivers/char/Kconfig11
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/tile-srom.c481
4 files changed, 535 insertions, 0 deletions
diff --git a/arch/tile/include/hv/drv_srom_intf.h b/arch/tile/include/hv/drv_srom_intf.h
new file mode 100644
index 000000000000..6395faa6d9e6
--- /dev/null
+++ b/arch/tile/include/hv/drv_srom_intf.h
@@ -0,0 +1,41 @@
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
15/**
16 * @file drv_srom_intf.h
17 * Interface definitions for the SPI Flash ROM driver.
18 */
19
20#ifndef _SYS_HV_INCLUDE_DRV_SROM_INTF_H
21#define _SYS_HV_INCLUDE_DRV_SROM_INTF_H
22
23/** Read this offset to get the total device size. */
24#define SROM_TOTAL_SIZE_OFF 0xF0000000
25
26/** Read this offset to get the device sector size. */
27#define SROM_SECTOR_SIZE_OFF 0xF0000004
28
29/** Read this offset to get the device page size. */
30#define SROM_PAGE_SIZE_OFF 0xF0000008
31
32/** Write this offset to flush any pending writes. */
33#define SROM_FLUSH_OFF 0xF1000000
34
35/** Write this offset, plus the byte offset of the start of a sector, to
36 * erase a sector. Any write data is ignored, but there must be at least
37 * one byte of write data. Only applies when the driver is in MTD mode.
38 */
39#define SROM_ERASE_OFF 0xF2000000
40
41#endif /* _SYS_HV_INCLUDE_DRV_SROM_INTF_H */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 49502bc5360a..423fd56bf612 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -616,5 +616,16 @@ config MSM_SMD_PKT
616 Enables userspace clients to read and write to some packet SMD 616 Enables userspace clients to read and write to some packet SMD
617 ports via device interface for MSM chipset. 617 ports via device interface for MSM chipset.
618 618
619config TILE_SROM
620 bool "Character-device access via hypervisor to the Tilera SPI ROM"
621 depends on TILE
622 default y
623 ---help---
624 This device provides character-level read-write access
625 to the SROM, typically via the "0", "1", and "2" devices
626 in /dev/srom/. The Tilera hypervisor makes the flash
627 device appear much like a simple EEPROM, and knows
628 how to partition a single ROM for multiple purposes.
629
619endmenu 630endmenu
620 631
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7a00672bd85d..32762ba769c2 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -63,3 +63,5 @@ obj-$(CONFIG_RAMOOPS) += ramoops.o
63 63
64obj-$(CONFIG_JS_RTC) += js-rtc.o 64obj-$(CONFIG_JS_RTC) += js-rtc.o
65js-rtc-y = rtc.o 65js-rtc-y = rtc.o
66
67obj-$(CONFIG_TILE_SROM) += tile-srom.o
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
new file mode 100644
index 000000000000..cf3ee008dca2
--- /dev/null
+++ b/drivers/char/tile-srom.c
@@ -0,0 +1,481 @@
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
65struct 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
73static int srom_major; /* Dynamic major by default */
74module_param(srom_major, int, 0);
75MODULE_AUTHOR("Tilera Corporation");
76MODULE_LICENSE("GPL");
77
78static int srom_devs; /* Number of SROM partitions */
79static struct cdev srom_cdev;
80static struct class *srom_class;
81static struct srom_dev *srom_devices;
82
83/*
84 * Handle calling the hypervisor and managing EAGAIN/EBUSY.
85 */
86
87static 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
107static 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}