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
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 */
40 .byteorder
= 1, /* MSB-First */
41 .polarity
= 0, /* High-Active */
42 .phase
= 0, /* Sample-Then-Shift */
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];
61 inbuf
[0] = enable
? ATMEL_WREN
: ATMEL_WRDI
;
63 incounts
[0] = sizeof(inbuf
);
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
);
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];
77 inbuf
[0] = ATMEL_RDSR
;
80 incounts
[0] = sizeof(inbuf
);
83 outcounts
[0] = sizeof(outbuf
);
85 stat
= spi_eeprom_io(chipid
, inbufs
, incounts
, outbufs
, outcounts
);
91 int spi_eeprom_read_status(int chipid
)
95 spin_lock_irqsave(&spi_eeprom_lock
, flags
);
96 stat
= spi_eeprom_read_status_nolock(chipid
);
97 spin_unlock_irqrestore(&spi_eeprom_lock
, flags
);
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];
108 inbuf
[0] = ATMEL_READ
;
112 incounts
[0] = sizeof(inbuf
);
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
);
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];
133 if (address
/ 8 != (address
+ len
- 1) / 8)
135 stat
= spi_eeprom_write_enable(chipid
, 1);
138 stat
= spi_eeprom_read_status(chipid
);
141 if (!(stat
& ATMEL_SR_WEN
))
144 inbuf
[0] = ATMEL_WRITE
;
148 incounts
[0] = sizeof(inbuf
);
151 spin_lock_irqsave(&spi_eeprom_lock
, flags
);
152 stat
= spi_eeprom_io(chipid
, inbufs
, incounts
, NULL
, NULL
);
156 /* write start. max 10ms */
157 for (i
= 10; i
> 0; i
--) {
158 int stat
= spi_eeprom_read_status_nolock(chipid
);
161 if (!(stat
& ATMEL_SR_BSY
))
165 spin_unlock_irqrestore(&spi_eeprom_lock
, flags
);
170 spin_unlock_irqrestore(&spi_eeprom_lock
, flags
);
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)
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
;
190 if (file
->f_pos
>= size
)
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) {
207 __init
void spi_eeprom_proc_create(struct proc_dir_entry
*dir
, int chipid
)
209 struct proc_dir_entry
*entry
;
211 sprintf(name
, "seeprom-%d", chipid
);
212 entry
= create_proc_entry(name
, 0600, dir
);
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 */