el_srom.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. * (C) Copyright 2002 ELTEC Elektronik AG
  3. * Frank Gottschling <fgottschling@eltec.de>
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #include <common.h>
  24. #include "srom.h"
  25. /*----------------------------------------------------------------------------*/
  26. /*
  27. * START sequence
  28. * _ _________
  29. * SCLK _> \____
  30. * _ ____
  31. * SDIO _> \_________
  32. * : : :
  33. */
  34. static void eepStart (void)
  35. {
  36. out8(I2C_BUS_DAT, 0x60); /* SCLK = high SDIO = high */
  37. out8(I2C_BUS_DIR, 0x60); /* set output direction for SCLK/SDIO */
  38. udelay(10);
  39. out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = low */
  40. udelay(10);
  41. out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = low */
  42. udelay(10);
  43. }
  44. /*----------------------------------------------------------------------------*/
  45. /*
  46. * STOP sequence
  47. * _______
  48. * SCLK _____/
  49. * _ ___
  50. * SDIO _>_______/
  51. * : : :
  52. */
  53. static void eepStop (void)
  54. {
  55. out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = low */
  56. out8(I2C_BUS_DIR, 0x60); /* set output direction for SCLK/SDIO */
  57. udelay(10);
  58. out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = low */
  59. udelay(10);
  60. out8(I2C_BUS_DAT, 0x60); /* SCLK = high SDIO = high */
  61. udelay(10);
  62. out8(I2C_BUS_DIR, 0x00); /* reset to input direction */
  63. }
  64. /*----------------------------------------------------------------------------*/
  65. /*
  66. * Read one byte from EEPROM
  67. * ___ ___ ___ ___ ___ ___ ___ ___
  68. * SCLK ___/ \___/ \___/ \___/ \___/ \___/ \___/ \___/ \
  69. * _________________________________________________________________
  70. * SDIO > ^ ^ ^ ^ ^ ^ ^ ^
  71. * : : : : : : : : : : : : : : : : :
  72. */
  73. static unsigned char eepReadByte (void)
  74. {
  75. register unsigned char buf = 0x00;
  76. register int i;
  77. out8(I2C_BUS_DIR, 0x40);
  78. for (i = 0; i < 8; i++)
  79. {
  80. out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */
  81. udelay(10);
  82. out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = high */
  83. udelay(15);
  84. buf <<= 1;
  85. buf = (in8(I2C_BUS_DAT) & 0x20) ? (buf | 0x01) : (buf & 0xFE);
  86. out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */
  87. udelay(10);
  88. }
  89. return(buf);
  90. }
  91. /*----------------------------------------------------------------------------*/
  92. /*
  93. * Write one byte to EEPROM
  94. * ___ ___ ___ ___ ___ ___ ___ ___
  95. * SCLK __/ \___/ \___/ \___/ \___/ \___/ \___/ \___/ \__
  96. * _______ _______ _______ _______ _______ _______ _______ ________
  97. * SDIO X_______X_______X_______X_______X_______X_______X_______X________
  98. * : 7 : 6 : 5 : 4 : 3 : 2 : 1 : 0
  99. */
  100. static void eepWriteByte (register unsigned char buf)
  101. {
  102. register int i;
  103. (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = data */
  104. out8(I2C_BUS_DIR, 0x60);
  105. for (i = 7; i >= 0; i--)
  106. {
  107. (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK=low SDIO=data */
  108. udelay(10);
  109. (buf & 0x80) ? out8(I2C_BUS_DAT, 0x60) : out8(I2C_BUS_DAT, 0x40); /* SCLK=high SDIO=data */
  110. udelay(15);
  111. (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK=low SDIO=data */
  112. udelay(10);
  113. buf <<= 1;
  114. }
  115. }
  116. /*----------------------------------------------------------------------------*/
  117. /*
  118. * Read data acknowledge of EEPROM
  119. * _______
  120. * SCLK ____/ \___
  121. * _______________
  122. * SDIO >
  123. * : : ^ :
  124. */
  125. static int eepReadAck (void)
  126. {
  127. int retval;
  128. out8(I2C_BUS_DIR, 0x40);
  129. out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */
  130. udelay(10);
  131. out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = high */
  132. udelay(10);
  133. retval = (in8(I2C_BUS_DAT) & 0x20) ? ERROR : 0;
  134. udelay(10);
  135. out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */
  136. udelay(10);
  137. return(retval);
  138. }
  139. /*----------------------------------------------------------------------------*/
  140. /*
  141. * Write data acknowledge to EEPROM
  142. * _______
  143. * SCLK ____/ \___
  144. *
  145. * SDIO >_______________
  146. * : : :
  147. */
  148. static void eepWriteAck (unsigned char ack)
  149. {
  150. ack ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = ack */
  151. out8(I2C_BUS_DIR, 0x60);
  152. udelay(10);
  153. ack ? out8(I2C_BUS_DAT, 0x60) : out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = ack */
  154. udelay(15);
  155. ack ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = ack */
  156. udelay(10);
  157. }
  158. /*----------------------------------------------------------------------------*/
  159. /*
  160. * Read bytes from EEPROM
  161. */
  162. int el_srom_load (addr, buf, cnt, device, block)
  163. unsigned char addr;
  164. unsigned char *buf;
  165. int cnt;
  166. unsigned char device;
  167. unsigned char block;
  168. {
  169. register int i;
  170. for (i=0;i<cnt;i++)
  171. {
  172. eepStart();
  173. eepWriteByte(0xA0 | device | block);
  174. if (eepReadAck() == ERROR)
  175. {
  176. eepStop();
  177. return(ERROR);
  178. }
  179. eepWriteByte(addr++);
  180. if (eepReadAck() == ERROR)
  181. {
  182. eepStop();
  183. return(ERROR);
  184. }
  185. eepStart();
  186. eepWriteByte(0xA1 | device | block);
  187. if (eepReadAck() == ERROR)
  188. {
  189. eepStop();
  190. return(ERROR);
  191. }
  192. *buf++ = eepReadByte();
  193. eepWriteAck(1);
  194. eepStop();
  195. if ((addr == 0) && (i != (cnt-1))) /* is it the same block ? */
  196. {
  197. if (block == FIRST_BLOCK)
  198. block = SECOND_BLOCK;
  199. else
  200. return(ERROR);
  201. }
  202. }
  203. return(cnt);
  204. }
  205. /*----------------------------------------------------------------------------*/
  206. /*
  207. *
  208. * Write bytes to EEPROM
  209. *
  210. */
  211. int el_srom_store (addr, buf, cnt, device, block)
  212. unsigned char addr, *buf, device, block;
  213. int cnt;
  214. {
  215. register int i, retVal;
  216. for (i=0;i<cnt;i++)
  217. {
  218. retVal = ERROR;
  219. do
  220. {
  221. eepStart();
  222. eepWriteByte(0xA0 | device | block);
  223. if ((retVal = eepReadAck()) == ERROR)
  224. eepStop();
  225. } while (retVal == ERROR);
  226. eepWriteByte(addr++);
  227. if (eepReadAck() == ERROR) return(ERROR);
  228. if ((addr == 0) && (i != (cnt-1))) /* is it the same block ? */
  229. {
  230. if (block == FIRST_BLOCK)
  231. block = SECOND_BLOCK;
  232. else
  233. return(ERROR);
  234. }
  235. eepWriteByte(*buf++);
  236. if (eepReadAck() == ERROR)
  237. return(ERROR);
  238. eepStop();
  239. }
  240. return(cnt);
  241. }
  242. /*----------------------------------------------------------------------------*/
  243. /*
  244. * calculate checksum for ELTEC revision srom
  245. */
  246. unsigned long el_srom_checksum (ptr, size)
  247. register unsigned char *ptr;
  248. unsigned long size;
  249. {
  250. u_long f, accu = 0;
  251. u_int i;
  252. u_char byte;
  253. for (; size; size--)
  254. {
  255. byte = *ptr++;
  256. for (i = 8; i; i--)
  257. {
  258. f = ((byte & 1) ^ (accu & 1)) ? 0x84083001 : 0;
  259. accu >>= 1; accu ^= f;
  260. byte >>= 1;
  261. }
  262. }
  263. return(accu);
  264. }
  265. /*----------------------------------------------------------------------------*/