Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
atmel_read_eeprom.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003 PMC-Sierra Inc.
3  * Author: Manish Lachwani ([email protected])
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 
38 static void delay(int delay)
39 {
40  while (delay--);
41 }
42 
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 
57 static void send_ack(void)
58 {
59  send_bit(0);
60 }
61 
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 
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 
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 
90 static void do_idle(void)
91 {
92  sda_hi;
93  scl_hi;
94  vcc_off;
95 }
96 
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 
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 
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  */
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 }