Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
[linux-2.6] / arch / mips / tx4938 / toshiba_rbtx4938 / spi_eeprom.c
1 /*
2  * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
3  * Copyright (C) 2000-2001 Toshiba Corporation
4  *
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.
9  *
10  * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
11  */
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>
18
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
26
27 #define ATMEL_SR_BSY    0x01
28 #define ATMEL_SR_WEN    0x02
29 #define ATMEL_SR_BP0    0x04
30 #define ATMEL_SR_BP1    0x08
31
32 DEFINE_SPINLOCK(spi_eeprom_lock);
33
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 */
42
43 };
44 static inline int
45 spi_eeprom_io(int chipid,
46               unsigned char **inbufs, unsigned int *incounts,
47               unsigned char **outbufs, unsigned int *outcounts)
48 {
49         return txx9_spi_io(chipid, &seeprom_dev_desc,
50                            inbufs, incounts, outbufs, outcounts, 0);
51 }
52
53 int spi_eeprom_write_enable(int chipid, int enable)
54 {
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;
68 }
69
70 static int spi_eeprom_read_status_nolock(int chipid)
71 {
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];
88 }
89
90 int spi_eeprom_read_status(int chipid)
91 {
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;
98 }
99
100 int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len)
101 {
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;
122 }
123
124 int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len)
125 {
126         unsigned char inbuf[2];
127         unsigned char *inbufs[2];
128         unsigned int incounts[3];
129         unsigned long flags;
130         int i, stat;
131
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;
142
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;
154
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);
163         }
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;
171 }
172
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)
177 {
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;
182 }
183
184 static int spi_eeprom_write_proc(struct file *file, const char *buffer,
185                                  unsigned long count, void *data)
186 {
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;
199                 }
200                 buffer += len;
201                 file->f_pos += len;
202         }
203         return count;
204 }
205
206 __init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid)
207 {
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;
216         }
217 }
218 #endif /* CONFIG_PROC_FS */