82802ab.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * This file is part of the flashrom project.
  3. *
  4. * Copyright (C) 2000 Silicon Integrated System Corporation
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /*
  21. * Datasheet:
  22. * - Name: Intel 82802AB/82802AC Firmware Hub (FWH)
  23. * - URL: http://www.intel.com/design/chipsets/datashts/290658.htm
  24. * - PDF: http://download.intel.com/design/chipsets/datashts/29065804.pdf
  25. * - Order number: 290658-004
  26. */
  27. #include "flash.h"
  28. #include "chipdrivers.h"
  29. void print_status_82802ab(uint8_t status)
  30. {
  31. msg_cdbg("%s", status & 0x80 ? "Ready:" : "Busy:");
  32. msg_cdbg("%s", status & 0x40 ? "BE SUSPEND:" : "BE RUN/FINISH:");
  33. msg_cdbg("%s", status & 0x20 ? "BE ERROR:" : "BE OK:");
  34. msg_cdbg("%s", status & 0x10 ? "PROG ERR:" : "PROG OK:");
  35. msg_cdbg("%s", status & 0x8 ? "VP ERR:" : "VPP OK:");
  36. msg_cdbg("%s", status & 0x4 ? "PROG SUSPEND:" : "PROG RUN/FINISH:");
  37. msg_cdbg("%s", status & 0x2 ? "WP|TBL#|WP#,ABORT:" : "UNLOCK:");
  38. }
  39. int probe_82802ab(struct flashctx *flash)
  40. {
  41. chipaddr bios = flash->virtual_memory;
  42. uint8_t id1, id2, flashcontent1, flashcontent2;
  43. int shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED) ? 1 : 0;
  44. /* Reset to get a clean state */
  45. chip_writeb(flash, 0xFF, bios);
  46. programmer_delay(10);
  47. /* Enter ID mode */
  48. chip_writeb(flash, 0x90, bios);
  49. programmer_delay(10);
  50. id1 = chip_readb(flash, bios + (0x00 << shifted));
  51. id2 = chip_readb(flash, bios + (0x01 << shifted));
  52. /* Leave ID mode */
  53. chip_writeb(flash, 0xFF, bios);
  54. programmer_delay(10);
  55. msg_cdbg("%s: id1 0x%02x, id2 0x%02x", __func__, id1, id2);
  56. if (!oddparity(id1))
  57. msg_cdbg(", id1 parity violation");
  58. /*
  59. * Read the product ID location again. We should now see normal
  60. * flash contents.
  61. */
  62. flashcontent1 = chip_readb(flash, bios + (0x00 << shifted));
  63. flashcontent2 = chip_readb(flash, bios + (0x01 << shifted));
  64. if (id1 == flashcontent1)
  65. msg_cdbg(", id1 is normal flash content");
  66. if (id2 == flashcontent2)
  67. msg_cdbg(", id2 is normal flash content");
  68. msg_cdbg("\n");
  69. if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id)
  70. return 0;
  71. return 1;
  72. }
  73. /* FIXME: needs timeout */
  74. uint8_t wait_82802ab(struct flashctx *flash)
  75. {
  76. uint8_t status;
  77. chipaddr bios = flash->virtual_memory;
  78. chip_writeb(flash, 0x70, bios);
  79. if ((chip_readb(flash, bios) & 0x80) == 0) { // it's busy
  80. while ((chip_readb(flash, bios) & 0x80) == 0) ;
  81. }
  82. status = chip_readb(flash, bios);
  83. /* Reset to get a clean state */
  84. chip_writeb(flash, 0xFF, bios);
  85. return status;
  86. }
  87. int erase_block_82802ab(struct flashctx *flash, unsigned int page,
  88. unsigned int pagesize)
  89. {
  90. chipaddr bios = flash->virtual_memory;
  91. uint8_t status;
  92. // clear status register
  93. chip_writeb(flash, 0x50, bios + page);
  94. // now start it
  95. chip_writeb(flash, 0x20, bios + page);
  96. chip_writeb(flash, 0xd0, bios + page);
  97. programmer_delay(10);
  98. // now let's see what the register is
  99. status = wait_82802ab(flash);
  100. print_status_82802ab(status);
  101. /* FIXME: Check the status register for errors. */
  102. return 0;
  103. }
  104. /* chunksize is 1 */
  105. int write_82802ab(struct flashctx *flash, const uint8_t *src, unsigned int start, unsigned int len)
  106. {
  107. int i;
  108. chipaddr dst = flash->virtual_memory + start;
  109. for (i = 0; i < len; i++) {
  110. /* transfer data from source to destination */
  111. chip_writeb(flash, 0x40, dst);
  112. chip_writeb(flash, *src++, dst++);
  113. wait_82802ab(flash);
  114. }
  115. /* FIXME: Ignore errors for now. */
  116. return 0;
  117. }
  118. int unlock_28f004s5(struct flashctx *flash)
  119. {
  120. chipaddr bios = flash->virtual_memory;
  121. uint8_t mcfg, bcfg, need_unlock = 0, can_unlock = 0;
  122. int i;
  123. /* Clear status register */
  124. chip_writeb(flash, 0x50, bios);
  125. /* Read identifier codes */
  126. chip_writeb(flash, 0x90, bios);
  127. /* Read master lock-bit */
  128. mcfg = chip_readb(flash, bios + 0x3);
  129. msg_cdbg("master lock is ");
  130. if (mcfg) {
  131. msg_cdbg("locked!\n");
  132. } else {
  133. msg_cdbg("unlocked!\n");
  134. can_unlock = 1;
  135. }
  136. /* Read block lock-bits */
  137. for (i = 0; i < flash->chip->total_size * 1024; i+= (64 * 1024)) {
  138. bcfg = chip_readb(flash, bios + i + 2); // read block lock config
  139. msg_cdbg("block lock at %06x is %slocked!\n", i, bcfg ? "" : "un");
  140. if (bcfg) {
  141. need_unlock = 1;
  142. }
  143. }
  144. /* Reset chip */
  145. chip_writeb(flash, 0xFF, bios);
  146. /* Unlock: clear block lock-bits, if needed */
  147. if (can_unlock && need_unlock) {
  148. msg_cdbg("Unlock: ");
  149. chip_writeb(flash, 0x60, bios);
  150. chip_writeb(flash, 0xD0, bios);
  151. chip_writeb(flash, 0xFF, bios);
  152. msg_cdbg("Done!\n");
  153. }
  154. /* Error: master locked or a block is locked */
  155. if (!can_unlock && need_unlock) {
  156. msg_cerr("At least one block is locked and lockdown is active!\n");
  157. return -1;
  158. }
  159. return 0;
  160. }
  161. int unlock_lh28f008bjt(struct flashctx *flash)
  162. {
  163. chipaddr bios = flash->virtual_memory;
  164. uint8_t mcfg, bcfg;
  165. uint8_t need_unlock = 0, can_unlock = 0;
  166. int i;
  167. /* Wait if chip is busy */
  168. wait_82802ab(flash);
  169. /* Read identifier codes */
  170. chip_writeb(flash, 0x90, bios);
  171. /* Read master lock-bit */
  172. mcfg = chip_readb(flash, bios + 0x3);
  173. msg_cdbg("master lock is ");
  174. if (mcfg) {
  175. msg_cdbg("locked!\n");
  176. } else {
  177. msg_cdbg("unlocked!\n");
  178. can_unlock = 1;
  179. }
  180. /* Read block lock-bits, 8 * 8 KB + 15 * 64 KB */
  181. for (i = 0; i < flash->chip->total_size * 1024;
  182. i += (i >= (64 * 1024) ? 64 * 1024 : 8 * 1024)) {
  183. bcfg = chip_readb(flash, bios + i + 2); /* read block lock config */
  184. msg_cdbg("block lock at %06x is %slocked!\n", i,
  185. bcfg ? "" : "un");
  186. if (bcfg)
  187. need_unlock = 1;
  188. }
  189. /* Reset chip */
  190. chip_writeb(flash, 0xFF, bios);
  191. /* Unlock: clear block lock-bits, if needed */
  192. if (can_unlock && need_unlock) {
  193. msg_cdbg("Unlock: ");
  194. chip_writeb(flash, 0x60, bios);
  195. chip_writeb(flash, 0xD0, bios);
  196. chip_writeb(flash, 0xFF, bios);
  197. wait_82802ab(flash);
  198. msg_cdbg("Done!\n");
  199. }
  200. /* Error: master locked or a block is locked */
  201. if (!can_unlock && need_unlock) {
  202. msg_cerr("At least one block is locked and lockdown is active!\n");
  203. return -1;
  204. }
  205. return 0;
  206. }