Linux 2.6.17.7
[linux/fpc-iii.git] / arch / mips / tx4938 / toshiba_rbtx4938 / spi_eeprom.c
blob951a208ee9b34effe43a823c4225a9ca595d987a
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/config.h>
13 #include <linux/init.h>
14 #include <linux/delay.h>
15 #include <linux/proc_fs.h>
16 #include <linux/spinlock.h>
17 #include <asm/tx4938/spi.h>
18 #include <asm/tx4938/tx4938.h>
20 /* ATMEL 250x0 instructions */
21 #define ATMEL_WREN 0x06
22 #define ATMEL_WRDI 0x04
23 #define ATMEL_RDSR 0x05
24 #define ATMEL_WRSR 0x01
25 #define ATMEL_READ 0x03
26 #define ATMEL_WRITE 0x02
28 #define ATMEL_SR_BSY 0x01
29 #define ATMEL_SR_WEN 0x02
30 #define ATMEL_SR_BP0 0x04
31 #define ATMEL_SR_BP1 0x08
33 DEFINE_SPINLOCK(spi_eeprom_lock);
35 static struct spi_dev_desc seeprom_dev_desc = {
36 .baud = 1500000, /* 1.5Mbps */
37 .tcss = 1,
38 .tcsh = 1,
39 .tcsr = 1,
40 .byteorder = 1, /* MSB-First */
41 .polarity = 0, /* High-Active */
42 .phase = 0, /* Sample-Then-Shift */
45 static inline int
46 spi_eeprom_io(int chipid,
47 unsigned char **inbufs, unsigned int *incounts,
48 unsigned char **outbufs, unsigned int *outcounts)
50 return txx9_spi_io(chipid, &seeprom_dev_desc,
51 inbufs, incounts, outbufs, outcounts, 0);
54 int spi_eeprom_write_enable(int chipid, int enable)
56 unsigned char inbuf[1];
57 unsigned char *inbufs[1];
58 unsigned int incounts[2];
59 unsigned long flags;
60 int stat;
61 inbuf[0] = enable ? ATMEL_WREN : ATMEL_WRDI;
62 inbufs[0] = inbuf;
63 incounts[0] = sizeof(inbuf);
64 incounts[1] = 0;
65 spin_lock_irqsave(&spi_eeprom_lock, flags);
66 stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
67 spin_unlock_irqrestore(&spi_eeprom_lock, flags);
68 return stat;
71 static int spi_eeprom_read_status_nolock(int chipid)
73 unsigned char inbuf[2], outbuf[2];
74 unsigned char *inbufs[1], *outbufs[1];
75 unsigned int incounts[2], outcounts[2];
76 int stat;
77 inbuf[0] = ATMEL_RDSR;
78 inbuf[1] = 0;
79 inbufs[0] = inbuf;
80 incounts[0] = sizeof(inbuf);
81 incounts[1] = 0;
82 outbufs[0] = outbuf;
83 outcounts[0] = sizeof(outbuf);
84 outcounts[1] = 0;
85 stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
86 if (stat < 0)
87 return stat;
88 return outbuf[1];
91 int spi_eeprom_read_status(int chipid)
93 unsigned long flags;
94 int stat;
95 spin_lock_irqsave(&spi_eeprom_lock, flags);
96 stat = spi_eeprom_read_status_nolock(chipid);
97 spin_unlock_irqrestore(&spi_eeprom_lock, flags);
98 return stat;
101 int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len)
103 unsigned char inbuf[2];
104 unsigned char *inbufs[2], *outbufs[2];
105 unsigned int incounts[2], outcounts[3];
106 unsigned long flags;
107 int stat;
108 inbuf[0] = ATMEL_READ;
109 inbuf[1] = address;
110 inbufs[0] = inbuf;
111 inbufs[1] = NULL;
112 incounts[0] = sizeof(inbuf);
113 incounts[1] = 0;
114 outbufs[0] = NULL;
115 outbufs[1] = buf;
116 outcounts[0] = 2;
117 outcounts[1] = len;
118 outcounts[2] = 0;
119 spin_lock_irqsave(&spi_eeprom_lock, flags);
120 stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
121 spin_unlock_irqrestore(&spi_eeprom_lock, flags);
122 return stat;
125 int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len)
127 unsigned char inbuf[2];
128 unsigned char *inbufs[2];
129 unsigned int incounts[3];
130 unsigned long flags;
131 int i, stat;
133 if (address / 8 != (address + len - 1) / 8)
134 return -EINVAL;
135 stat = spi_eeprom_write_enable(chipid, 1);
136 if (stat < 0)
137 return stat;
138 stat = spi_eeprom_read_status(chipid);
139 if (stat < 0)
140 return stat;
141 if (!(stat & ATMEL_SR_WEN))
142 return -EPERM;
144 inbuf[0] = ATMEL_WRITE;
145 inbuf[1] = address;
146 inbufs[0] = inbuf;
147 inbufs[1] = buf;
148 incounts[0] = sizeof(inbuf);
149 incounts[1] = len;
150 incounts[2] = 0;
151 spin_lock_irqsave(&spi_eeprom_lock, flags);
152 stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
153 if (stat < 0)
154 goto unlock_return;
156 /* write start. max 10ms */
157 for (i = 10; i > 0; i--) {
158 int stat = spi_eeprom_read_status_nolock(chipid);
159 if (stat < 0)
160 goto unlock_return;
161 if (!(stat & ATMEL_SR_BSY))
162 break;
163 mdelay(1);
165 spin_unlock_irqrestore(&spi_eeprom_lock, flags);
166 if (i == 0)
167 return -EIO;
168 return len;
169 unlock_return:
170 spin_unlock_irqrestore(&spi_eeprom_lock, flags);
171 return stat;
174 #ifdef CONFIG_PROC_FS
175 #define MAX_SIZE 0x80 /* for ATMEL 25010 */
176 static int spi_eeprom_read_proc(char *page, char **start, off_t off,
177 int count, int *eof, void *data)
179 unsigned int size = MAX_SIZE;
180 if (spi_eeprom_read((int)data, 0, (unsigned char *)page, size) < 0)
181 size = 0;
182 return size;
185 static int spi_eeprom_write_proc(struct file *file, const char *buffer,
186 unsigned long count, void *data)
188 unsigned int size = MAX_SIZE;
189 int i;
190 if (file->f_pos >= size)
191 return -EIO;
192 if (file->f_pos + count > size)
193 count = size - file->f_pos;
194 for (i = 0; i < count; i += 8) {
195 int len = count - i < 8 ? count - i : 8;
196 if (spi_eeprom_write((int)data, file->f_pos,
197 (unsigned char *)buffer, len) < 0) {
198 count = -EIO;
199 break;
201 buffer += len;
202 file->f_pos += len;
204 return count;
207 __init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid)
209 struct proc_dir_entry *entry;
210 char name[128];
211 sprintf(name, "seeprom-%d", chipid);
212 entry = create_proc_entry(name, 0600, dir);
213 if (entry) {
214 entry->read_proc = spi_eeprom_read_proc;
215 entry->write_proc = spi_eeprom_write_proc;
216 entry->data = (void *)chipid;
219 #endif /* CONFIG_PROC_FS */