1 /*
2  *  Copyright (C) 2003 PMC-Sierra Inc.
3  *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
4  *
5  *  This program is free software; you can redistribute  it and/or modify it
6  *  under  the terms of  the GNU General  Public License as published by the
7  *  Free Software Foundation;  either version 2 of the  License, or (at your
8  *  option) any later version.
9  *
10  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
11  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
12  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
13  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
14  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
16  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
17  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
18  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
19  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20  *
21  *  You should have received a copy of the  GNU General Public License along
22  *  with this program; if not, write  to the Free Software Foundation, Inc.,
23  *  675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25 
26 /*
27  * Description:
28  *
29  * This code reads the ATMEL 24CXX EEPROM. The PMC-Sierra Yosemite board uses the ATMEL
30  * 24C32/24C64 which uses two byte addressing as compared to 24C16. Note that this program
31  * uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are
32  * expected to have a connectivity from the EEPROM to the serial port. This program does
33  * __not__ communicate using the I2C protocol
34  */
35 
36 #include "atmel_read_eeprom.h"
37 
delay(int delay)38 static void delay(int delay)
39 {
40 	while (delay--);
41 }
42 
send_bit(unsigned char bit)43 static void send_bit(unsigned char bit)
44 {
45 	scl_lo;
46 	delay(TXX);
47 	if (bit)
48 		sda_hi;
49 	else
50 		sda_lo;
51 
52 	delay(TXX);
53 	scl_hi;
54 	delay(TXX);
55 }
56 
send_ack(void)57 static void send_ack(void)
58 {
59 	send_bit(0);
60 }
61 
send_byte(unsigned char byte)62 static void send_byte(unsigned char byte)
63 {
64 	int	i = 0;
65 
66 	for (i = 7; i >= 0; i--)
67 		send_bit((byte >> i) & 0x01);
68 }
69 
send_start(void)70 static void send_start(void)
71 {
72 	sda_hi;
73 	delay(TXX);
74 	scl_hi;
75 	delay(TXX);
76 	sda_lo;
77 	delay(TXX);
78 }
79 
send_stop(void)80 static void send_stop(void)
81 {
82 	sda_lo;
83 	delay(TXX);
84 	scl_hi;
85 	delay(TXX);
86 	sda_hi;
87 	delay(TXX);
88 }
89 
do_idle(void)90 static void do_idle(void)
91 {
92 	sda_hi;
93 	scl_hi;
94 	vcc_off;
95 }
96 
recv_bit(void)97 static int recv_bit(void)
98 {
99 	int	status;
100 
101 	scl_lo;
102 	delay(TXX);
103 	sda_hi;
104 	delay(TXX);
105 	scl_hi;
106 	delay(TXX);
107 
108 	return 1;
109 }
110 
recv_byte(void)111 static unsigned char recv_byte(void) {
112         int i;
113         unsigned char byte=0;
114 
115         for (i=7;i>=0;i--)
116                 byte |= (recv_bit() << i);
117 
118         return byte;
119 }
120 
recv_ack(void)121 static int recv_ack(void)
122 {
123 	unsigned int	ack;
124 
125 	ack = (unsigned int)recv_bit();
126 	scl_lo;
127 
128 	if (ack) {
129 		do_idle();
130 		printk(KERN_ERR "Error reading the Atmel 24C32/24C64 EEPROM\n");
131 		return -1;
132 	}
133 
134 	return ack;
135 }
136 
137 /*
138  * This function does the actual read of the EEPROM. It needs the buffer into which the
139  * read data is copied, the size of the EEPROM being read and the buffer size
140  */
read_eeprom(char * buffer,int eeprom_size,int size)141 int read_eeprom(char *buffer, int eeprom_size, int size)
142 {
143 	int	i = 0, err;
144 
145 	send_start();
146 	send_byte(W_HEADER);
147 	recv_ack();
148 
149 	/* EEPROM with size of more than 2K need two byte addressing */
150 	if (eeprom_size > 2048) {
151 		send_byte(0x00);
152 		recv_ack();
153 	}
154 
155 	send_start();
156 	send_byte(R_HEADER);
157 	err = recv_ack();
158 	if (err == -1)
159 		return err;
160 
161 	for (i = 0; i < size; i++) {
162 		*buffer++ = recv_byte();
163 		send_ack();
164 	}
165 
166 	/* Note : We should do some check if the buffer contains correct information */
167 
168 	send_stop();
169 }
170