1 /*
2  * Author: Jon Trulson <jtrulson@ics.com>
3  * Copyright (c) 2015 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <unistd.h>
26 #include <math.h>
27 #include <iostream>
28 #include <string>
29 
30 #include "m24lr64e.h"
31 
32 using namespace upm;
33 using namespace std;
34 
35 
M24LR64E(int bus,AccessMode mode)36 M24LR64E::M24LR64E(int bus, AccessMode mode):
37   m_i2c(bus)
38 {
39   if (mode == USER_MODE)
40     m_addr = M24LR64E_DEFAULT_I2C_ADDR;
41   else
42     m_addr = M24LR64E_DEFAULT_I2C_ADDR_E2;
43 
44   mraa::Result rv;
45   if ( (rv = m_i2c.address(m_addr)) != mraa::SUCCESS)
46     {
47       throw std::runtime_error(std::string(__FUNCTION__) +
48                                ": I2c.address() failed");
49       return;
50     }
51 }
52 
~M24LR64E()53 M24LR64E::~M24LR64E()
54 {
55 }
56 
submitPasswd(uint32_t passwd)57 bool M24LR64E::submitPasswd(uint32_t passwd)
58 {
59   // this device actually uses two bytes to address a register
60   const int pktLen = 11;
61   uint8_t buf[pktLen];
62 
63   buf[0] = 0x09;
64   buf[1] = 0x00;
65 
66   buf[2] = ((passwd >> 24) & 0xff);
67   buf[3] = ((passwd >> 16) & 0xff);
68   buf[4] = ((passwd >> 8) & 0xff);
69   buf[5] = (passwd & 0xff);
70 
71   buf[6] = 0x09;
72 
73   // the password is written twice
74   buf[7] = ((passwd >> 24) & 0xff);
75   buf[8] = ((passwd >> 16) & 0xff);
76   buf[9] = ((passwd >> 8) & 0xff);
77   buf[10] = (passwd & 0xff);
78 
79   if (m_i2c.write(buf, pktLen))
80     {
81       throw std::runtime_error(std::string(__FUNCTION__) +
82                                ": I2c.write() failed");
83       return false;
84     }
85 
86   return true;
87 }
88 
writePasswd(uint32_t passwd)89 bool M24LR64E::writePasswd(uint32_t passwd)
90 {
91   const int pktLen = 11;
92   uint8_t buf[pktLen];
93 
94   buf[0] = 0x09;
95   buf[1] = 0x00;
96 
97   buf[2] = ((passwd >> 24) & 0xff);
98   buf[3] = ((passwd >> 16) & 0xff);
99   buf[4] = ((passwd >> 8) & 0xff);
100   buf[5] = (passwd & 0xff);
101 
102   buf[6] = 0x07;
103 
104   // the password is written twice
105   buf[7] = ((passwd >> 24) & 0xff);
106   buf[8] = ((passwd >> 16) & 0xff);
107   buf[9] = ((passwd >> 8) & 0xff);
108   buf[10] = (passwd & 0xff);
109 
110   if (m_i2c.write(buf, pktLen))
111     {
112       throw std::runtime_error(std::string(__FUNCTION__) +
113                                ": I2c.write() failed");
114       return false;
115     }
116 
117   return true;
118 }
119 
sectorProtectConfig(unsigned int sectorNumber,bool protectEnable,SectorAccessRight accessRight,SectorSelectPassWd passwd)120 void M24LR64E::sectorProtectConfig(unsigned int sectorNumber,
121                                    bool protectEnable,
122                                    SectorAccessRight accessRight,
123                                    SectorSelectPassWd passwd)
124 {
125   if(!protectEnable) {
126     EEPROM_Write_Byte(sectorNumber,0x0);
127   } else {
128     EEPROM_Write_Byte(sectorNumber,
129                       protectEnable | (accessRight<<1) |(passwd<<2));
130   }
131 }
132 
clearSectorProtect(void)133 void M24LR64E::clearSectorProtect(void)
134 {
135   uint8_t buf[64]={0x0};
136   EEPROM_Write_Bytes(0, buf, 64);
137 }
138 
139 
sectorWriteLockBit(unsigned int sectorNumber,bool sockEnable)140 void M24LR64E::sectorWriteLockBit(unsigned int sectorNumber,
141                                   bool sockEnable)
142 {
143   unsigned int sectorAddress = SECTOR_SECURITY_STATUS_BASE_ADDR
144     + (sectorNumber/8);
145   uint8_t sectorBit = sectorNumber % 8;
146   uint8_t preStatus = EEPROM_Read_Byte(sectorAddress);
147 
148   bool status = (preStatus >> sectorBit) & 0x01;
149   if(status != sockEnable) {
150     if(status == true) {
151       writeByte(sectorAddress,preStatus&(~(1<<sectorBit)));
152     } else {
153       writeByte(sectorAddress,preStatus|(1<<sectorBit));
154     }
155   }
156 }
157 
getDSFID()158 uint8_t M24LR64E::getDSFID()
159 {
160   return EEPROM_Read_Byte(DSFID_ADDR);
161 }
162 
getAFI()163 uint8_t M24LR64E::getAFI()
164 {
165   return EEPROM_Read_Byte(AFI_ADDR);
166 }
167 
getUID()168 uint8_t *M24LR64E::getUID()
169 {
170   uint8_t* buffer = new uint8_t[UID_LENGTH];
171   EEPROM_Read_Bytes(UID_ADDR, buffer, UID_LENGTH);
172 
173   return buffer;
174 }
175 
getMemorySize()176 uint32_t M24LR64E::getMemorySize()
177 {
178   uint32_t volume = 0x0;
179   volume = EEPROM_Read_Byte(MEM_SIZE_ADDR);
180   volume = volume<<8|EEPROM_Read_Byte(MEM_SIZE_ADDR+1);
181   volume = volume<<8|EEPROM_Read_Byte(MEM_SIZE_ADDR+2);
182   return volume;
183 }
184 
clearMemory()185 void M24LR64E::clearMemory()
186 {
187   for(int i = 0; i < EEPROM_I2C_LENGTH; i++){
188     writeByte(i,0x0);
189   }
190 }
191 
writeByte(unsigned int address,uint8_t data)192 mraa::Result M24LR64E::writeByte(unsigned int address, uint8_t data)
193 {
194   return EEPROM_Write_Byte(address, data);
195 }
196 
writeBytes(unsigned int address,uint8_t * buffer,int len)197 mraa::Result M24LR64E::writeBytes(unsigned int address, uint8_t* buffer, int len)
198 {
199   return EEPROM_Write_Bytes(address, buffer, len);
200 }
201 
readByte(unsigned int address)202 uint8_t M24LR64E::readByte(unsigned int address)
203 {
204   return EEPROM_Read_Byte(address);
205 }
206 
readBytes(unsigned int address,uint8_t * buffer,int len)207 int M24LR64E::readBytes(unsigned int address, uint8_t* buffer, int len)
208 {
209   return EEPROM_Read_Bytes(address, buffer, len);
210 }
211 
EEPROM_Write_Byte(unsigned int address,uint8_t data)212 mraa::Result M24LR64E::EEPROM_Write_Byte(unsigned int address, uint8_t data)
213 {
214   const int pktLen = 3;
215   uint8_t buf[pktLen];
216   mraa::Result rv;
217 
218   buf[0] = ((address >> 8) & 0xff);
219   buf[1] = (address & 0xff);
220   buf[2] = data;
221 
222   if ((rv = m_i2c.write(buf, pktLen)))
223     throw std::runtime_error(std::string(__FUNCTION__) +
224                              ": I2c.write() failed");
225 
226   usleep(I2C_WRITE_TIME * 1000);
227   return rv;
228 }
229 
EEPROM_Write_Bytes(unsigned int address,uint8_t * data,int len)230 mraa::Result M24LR64E::EEPROM_Write_Bytes(unsigned int address, uint8_t* data,
231                                   int len)
232 {
233   const int pktLen = 2 + len;
234   uint8_t buf[pktLen];
235   mraa::Result rv;
236 
237   buf[0] = ((address >> 8) & 0xff);
238   buf[1] = (address & 0xff);
239 
240   for (int i=0; i<len; i++)
241     buf[2+i] = data[i];
242 
243   if ((rv = m_i2c.write(buf, pktLen)))
244     throw std::runtime_error(std::string(__FUNCTION__) +
245                              ": I2c.write() failed");
246 
247   usleep(I2C_WRITE_TIME * 1000);
248 
249   return rv;
250 }
251 
EEPROM_Read_Byte(unsigned int address)252 uint8_t M24LR64E::EEPROM_Read_Byte(unsigned int address)
253 {
254   const int apktLen = 2;
255   uint8_t abuf[apktLen];
256 
257   abuf[0] = ((address >> 8) & 0xff);
258   abuf[1] = (address & 0xff);
259 
260   if (m_i2c.write(abuf, apktLen))
261     {
262       throw std::runtime_error(std::string(__FUNCTION__) +
263                                ": I2c.write() failed");
264       return 0x00;
265     }
266 
267   const int pktLen = 1;
268   uint8_t buf[apktLen];
269 
270   buf[0] = 0;
271 
272   if (m_i2c.read(buf, pktLen) != pktLen)
273     {
274       throw std::runtime_error(std::string(__FUNCTION__) +
275                                ": I2c.write() failed");
276       return 0x00;
277     }
278 
279   return buf[0];
280 }
281 
EEPROM_Read_Bytes(unsigned int address,uint8_t * buffer,int len)282 int M24LR64E::EEPROM_Read_Bytes(unsigned int address,
283                                          uint8_t* buffer, int len)
284 {
285   const int apktLen = 2;
286   uint8_t abuf[apktLen];
287 
288   abuf[0] = ((address >> 8) & 0xff);
289   abuf[1] = (address & 0xff);
290 
291   if (m_i2c.write(abuf, apktLen))
292     {
293       throw std::runtime_error(std::string(__FUNCTION__) +
294                                ": I2c.write() failed");
295       return false;
296     }
297 
298   int rv = m_i2c.read(buffer, len);
299   if (rv != len)
300     {
301       throw std::runtime_error(std::string(__FUNCTION__) +
302                                ": I2c.read() failed");
303     }
304 
305   return rv;
306 }
307