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