RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / arch / mips / tx4938 / toshiba_rbtx4938 / spi_eeprom.c
blob89596e62f9096cf5f9313c6d87e121bc58afaa5c
1 /*
2 * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
3 * Copyright (C) 2000-2001 Toshiba Corporation
5 * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
6 * terms of the GNU General Public License version 2. This program is
7 * licensed "as is" without any warranty of any kind, whether express
8 * or implied.
10 * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
12 #include <linux/init.h>
13 #include <linux/delay.h>
14 #include <linux/proc_fs.h>
15 #include <linux/spinlock.h>
16 #include <asm/tx4938/spi.h>
17 #include <asm/tx4938/tx4938.h>
19 /* ATMEL 250x0 instructions */
20 #define ATMEL_WREN 0x06
21 #define ATMEL_WRDI 0x04
22 #define ATMEL_RDSR 0x05
23 #define ATMEL_WRSR 0x01
24 #define ATMEL_READ 0x03
25 #define ATMEL_WRITE 0x02
27 #define ATMEL_SR_BSY 0x01
28 #define ATMEL_SR_WEN 0x02
29 #define ATMEL_SR_BP0 0x04
30 #define ATMEL_SR_BP1 0x08
32 DEFINE_SPINLOCK(spi_eeprom_lock);
34 static struct spi_dev_desc seeprom_dev_desc = {
35 .baud = 1500000, /* 1.5Mbps */
36 .tcss = 1,
37 .tcsh = 1,
38 .tcsr = 1,
39 .byteorder = 1, /* MSB-First */
40 .polarity = 0, /* High-Active */
41 .phase = 0, /* Sample-Then-Shift */
44 static inline int
45 spi_eeprom_io(int chipid,
46 unsigned char **inbufs, unsigned int *incounts,
47 unsigned char **outbufs, unsigned int *outcounts)
49 return txx9_spi_io(chipid, &seeprom_dev_desc,
50 inbufs, incounts, outbufs, outcounts, 0);
53 int spi_eeprom_write_enable(int chipid, int enable)
55 unsigned char inbuf[1];
56 unsigned char *inbufs[1];
57 unsigned int incounts[2];
58 unsigned long flags;
59 int stat;
60 inbuf[0] = enable ? ATMEL_WREN : ATMEL_WRDI;
61 inbufs[0] = inbuf;
62 incounts[0] = sizeof(inbuf);
63 incounts[1] = 0;
64 spin_lock_irqsave(&spi_eeprom_lock, flags);
65 stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
66 spin_unlock_irqrestore(&spi_eeprom_lock, flags);
67 return stat;
70 static int spi_eeprom_read_status_nolock(int chipid)
72 unsigned char inbuf[2], outbuf[2];
73 unsigned char *inbufs[1], *outbufs[1];
74 unsigned int incounts[2], outcounts[2];
75 int stat;
76 inbuf[0] = ATMEL_RDSR;
77 inbuf[1] = 0;
78 inbufs[0] = inbuf;
79 incounts[0] = sizeof(inbuf);
80 incounts[1] = 0;
81 outbufs[0] = outbuf;
82 outcounts[0] = sizeof(outbuf);
83 outcounts[1] = 0;
84 stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
85 if (stat < 0)
86 return stat;
87 return outbuf[1];
90 int spi_eeprom_read_status(int chipid)
92 unsigned long flags;
93 int stat;
94 spin_lock_irqsave(&spi_eeprom_lock, flags);
95 stat = spi_eeprom_read_status_nolock(chipid);
96 spin_unlock_irqrestore(&spi_eeprom_lock, flags);
97 return stat;
100 int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len)
102 unsigned char inbuf[2];
103 unsigned char *inbufs[2], *outbufs[2];
104 unsigned int incounts[2], outcounts[3];
105 unsigned long flags;
106 int stat;
107 inbuf[0] = ATMEL_READ;
108 inbuf[1] = address;
109 inbufs[0] = inbuf;
110 inbufs[1] = NULL;
111 incounts[0] = sizeof(inbuf);
112 incounts[1] = 0;
113 outbufs[0] = NULL;
114 outbufs[1] = buf;
115 outcounts[0] = 2;
116 outcounts[1] = len;
117 outcounts[2] = 0;
118 spin_lock_irqsave(&spi_eeprom_lock, flags);
119 stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
120 spin_unlock_irqrestore(&spi_eeprom_lock, flags);
121 return stat;
124 int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len)
126 unsigned char inbuf[2];
127 unsigned char *inbufs[2];
128 unsigned int incounts[3];
129 unsigned long flags;
130 int i, stat;
132 if (address / 8 != (address + len - 1) / 8)
133 return -EINVAL;
134 stat = spi_eeprom_write_enable(chipid, 1);
135 if (stat < 0)
136 return stat;
137 stat = spi_eeprom_read_status(chipid);
138 if (stat < 0)
139 return stat;
140 if (!(stat & ATMEL_SR_WEN))
141 return -EPERM;
143 inbuf[0] = ATMEL_WRITE;
144 inbuf[1] = address;
145 inbufs[0] = inbuf;
146 inbufs[1] = buf;
147 incounts[0] = sizeof(inbuf);
148 incounts[1] = len;
149 incounts[2] = 0;
150 spin_lock_irqsave(&spi_eeprom_lock, flags);
151 stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
152 if (stat < 0)
153 goto unlock_return;
155 /* write start. max 10ms */
156 for (i = 10; i > 0; i--) {
157 int stat = spi_eeprom_read_status_nolock(chipid);
158 if (stat < 0)
159 goto unlock_return;
160 if (!(stat & ATMEL_SR_BSY))
161 break;
162 mdelay(1);
164 spin_unlock_irqrestore(&spi_eeprom_lock, flags);
165 if (i == 0)
166 return -EIO;
167 return len;
168 unlock_return:
169 spin_unlock_irqrestore(&spi_eeprom_lock, flags);
170 return stat;
173 #ifdef CONFIG_PROC_FS
174 #define MAX_SIZE 0x80 /* for ATMEL 25010 */
175 static int spi_eeprom_read_proc(char *page, char **start, off_t off,
176 int count, int *eof, void *data)
178 unsigned int size = MAX_SIZE;
179 if (spi_eeprom_read((int)data, 0, (unsigned char *)page, size) < 0)
180 size = 0;
181 return size;
184 static int spi_eeprom_write_proc(struct file *file, const char *buffer,
185 unsigned long count, void *data)
187 unsigned int size = MAX_SIZE;
188 int i;
189 if (file->f_pos >= size)
190 return -EIO;
191 if (file->f_pos + count > size)
192 count = size - file->f_pos;
193 for (i = 0; i < count; i += 8) {
194 int len = count - i < 8 ? count - i : 8;
195 if (spi_eeprom_write((int)data, file->f_pos,
196 (unsigned char *)buffer, len) < 0) {
197 count = -EIO;
198 break;
200 buffer += len;
201 file->f_pos += len;
203 return count;
206 __init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid)
208 struct proc_dir_entry *entry;
209 char name[128];
210 sprintf(name, "seeprom-%d", chipid);
211 entry = create_proc_entry(name, 0600, dir);
212 if (entry) {
213 entry->read_proc = spi_eeprom_read_proc;
214 entry->write_proc = spi_eeprom_write_proc;
215 entry->data = (void *)chipid;
218 #endif /* CONFIG_PROC_FS */