nicintel_spi.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * This file is part of the flashrom project.
  3. *
  4. * Copyright (C) 2010 Carl-Daniel Hailfinger
  5. * Copyright (C) 2010 Idwer Vollering
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; version 2 of the License.
  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. * Datasheets:
  22. * PCI/PCI-X Family of Gigabit Ethernet Controllers Software Developer's Manual
  23. * 82540EP/EM, 82541xx, 82544GC/EI, 82545GM/EM, 82546GB/EB, and 82547xx
  24. * http://www.intel.com/content/www/us/en/ethernet-controllers/pci-pci-x-family-gbe-controllers-software-dev-manual.html
  25. *
  26. * PCIe GbE Controllers Open Source Software Developer's Manual
  27. * http://www.intel.com/content/www/us/en/ethernet-controllers/pcie-gbe-controllers-open-source-manual.html
  28. *
  29. * Intel 82574 Gigabit Ethernet Controller Family Datasheet
  30. * http://www.intel.com/content/www/us/en/ethernet-controllers/82574l-gbe-controller-datasheet.html
  31. *
  32. * Intel 82599 10 GbE Controller Datasheet (331520)
  33. * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82599-10-gbe-controller-datasheet.pdf
  34. */
  35. #include <stdlib.h>
  36. #include <unistd.h>
  37. #include "flash.h"
  38. #include "programmer.h"
  39. #include "hwaccess.h"
  40. #define PCI_VENDOR_ID_INTEL 0x8086
  41. #define MEMMAP_SIZE getpagesize()
  42. /* EEPROM/Flash Control & Data Register */
  43. #define EECD 0x10
  44. /* Flash Access Register */
  45. #define FLA 0x1c
  46. /*
  47. * Register bits of EECD.
  48. * Table 13-6
  49. *
  50. * Bit 04, 05: FWE (Flash Write Enable Control)
  51. * 00b = not allowed (on some cards this sends an erase command if bit 31 (FL_ER) of FLA is set)
  52. * 01b = flash writes disabled
  53. * 10b = flash writes enabled
  54. * 11b = not allowed
  55. */
  56. #define FLASH_WRITES_DISABLED 0x10 /* FWE: 10000b */
  57. #define FLASH_WRITES_ENABLED 0x20 /* FWE: 100000b */
  58. /* Flash Access register bits
  59. * Table 13-9
  60. */
  61. #define FL_SCK 0
  62. #define FL_CS 1
  63. #define FL_SI 2
  64. #define FL_SO 3
  65. #define FL_REQ 4
  66. #define FL_GNT 5
  67. /* Currently unused */
  68. // #define FL_BUSY 30
  69. // #define FL_ER 31
  70. uint8_t *nicintel_spibar;
  71. const struct dev_entry nics_intel_spi[] = {
  72. {PCI_VENDOR_ID_INTEL, 0x105e, OK, "Intel", "82571EB Gigabit Ethernet Controller"},
  73. {PCI_VENDOR_ID_INTEL, 0x1076, OK, "Intel", "82541GI Gigabit Ethernet Controller"},
  74. {PCI_VENDOR_ID_INTEL, 0x107c, OK, "Intel", "82541PI Gigabit Ethernet Controller"},
  75. {PCI_VENDOR_ID_INTEL, 0x10b9, OK, "Intel", "82572EI Gigabit Ethernet Controller"},
  76. {PCI_VENDOR_ID_INTEL, 0x10d3, OK, "Intel", "82574L Gigabit Ethernet Controller"},
  77. {PCI_VENDOR_ID_INTEL, 0x10d8, NT, "Intel", "82599 10 Gigabit Unprogrammed Network Controller"},
  78. {PCI_VENDOR_ID_INTEL, 0x10f7, NT, "Intel", "82599 10 Gigabit KX4 Dual Port Network Controller"},
  79. {PCI_VENDOR_ID_INTEL, 0x10f8, NT, "Intel", "82599 10 Gigabit Dual Port Backplane Controller"},
  80. {PCI_VENDOR_ID_INTEL, 0x10f9, NT, "Intel", "82599 10 Gigabit CX4 Dual Port Network Controller"},
  81. {PCI_VENDOR_ID_INTEL, 0x10fb, NT, "Intel", "82599 10-Gigabit SFI/SFP+ Network Controller"},
  82. {PCI_VENDOR_ID_INTEL, 0x10fc, OK, "Intel", "82599 10 Gigabit XAUI/BX4 Dual Port Network Controller"},
  83. {PCI_VENDOR_ID_INTEL, 0x1517, NT, "Intel", "82599 10 Gigabit KR Network Controller"},
  84. {PCI_VENDOR_ID_INTEL, 0x151c, NT, "Intel", "82599 10 Gigabit TN Network Controller"},
  85. {PCI_VENDOR_ID_INTEL, 0x1529, NT, "Intel", "82599 10 Gigabit Dual Port Network Controller with FCoE"},
  86. {PCI_VENDOR_ID_INTEL, 0x152a, NT, "Intel", "82599 10 Gigabit Dual Port Backplane Controller with FCoE"},
  87. {PCI_VENDOR_ID_INTEL, 0x1557, NT, "Intel", "82599 10 Gigabit SFI Network Controller"},
  88. {0},
  89. };
  90. static void nicintel_request_spibus(void)
  91. {
  92. uint32_t tmp;
  93. tmp = pci_mmio_readl(nicintel_spibar + FLA);
  94. tmp |= 1 << FL_REQ;
  95. pci_mmio_writel(tmp, nicintel_spibar + FLA);
  96. /* Wait until we are allowed to use the SPI bus. */
  97. while (!(pci_mmio_readl(nicintel_spibar + FLA) & (1 << FL_GNT))) ;
  98. }
  99. static void nicintel_release_spibus(void)
  100. {
  101. uint32_t tmp;
  102. tmp = pci_mmio_readl(nicintel_spibar + FLA);
  103. tmp &= ~(1 << FL_REQ);
  104. pci_mmio_writel(tmp, nicintel_spibar + FLA);
  105. }
  106. static void nicintel_bitbang_set_cs(int val)
  107. {
  108. uint32_t tmp;
  109. tmp = pci_mmio_readl(nicintel_spibar + FLA);
  110. tmp &= ~(1 << FL_CS);
  111. tmp |= (val << FL_CS);
  112. pci_mmio_writel(tmp, nicintel_spibar + FLA);
  113. }
  114. static void nicintel_bitbang_set_sck(int val)
  115. {
  116. uint32_t tmp;
  117. tmp = pci_mmio_readl(nicintel_spibar + FLA);
  118. tmp &= ~(1 << FL_SCK);
  119. tmp |= (val << FL_SCK);
  120. pci_mmio_writel(tmp, nicintel_spibar + FLA);
  121. }
  122. static void nicintel_bitbang_set_mosi(int val)
  123. {
  124. uint32_t tmp;
  125. tmp = pci_mmio_readl(nicintel_spibar + FLA);
  126. tmp &= ~(1 << FL_SI);
  127. tmp |= (val << FL_SI);
  128. pci_mmio_writel(tmp, nicintel_spibar + FLA);
  129. }
  130. static int nicintel_bitbang_get_miso(void)
  131. {
  132. uint32_t tmp;
  133. tmp = pci_mmio_readl(nicintel_spibar + FLA);
  134. tmp = (tmp >> FL_SO) & 0x1;
  135. return tmp;
  136. }
  137. static const struct bitbang_spi_master bitbang_spi_master_nicintel = {
  138. .type = BITBANG_SPI_MASTER_NICINTEL,
  139. .set_cs = nicintel_bitbang_set_cs,
  140. .set_sck = nicintel_bitbang_set_sck,
  141. .set_mosi = nicintel_bitbang_set_mosi,
  142. .get_miso = nicintel_bitbang_get_miso,
  143. .request_bus = nicintel_request_spibus,
  144. .release_bus = nicintel_release_spibus,
  145. .half_period = 1,
  146. };
  147. static int nicintel_spi_shutdown(void *data)
  148. {
  149. uint32_t tmp;
  150. /* Disable writes manually. See the comment about EECD in nicintel_spi_init() for details. */
  151. tmp = pci_mmio_readl(nicintel_spibar + EECD);
  152. tmp &= ~FLASH_WRITES_ENABLED;
  153. tmp |= FLASH_WRITES_DISABLED;
  154. pci_mmio_writel(tmp, nicintel_spibar + EECD);
  155. return 0;
  156. }
  157. int nicintel_spi_init(void)
  158. {
  159. struct pci_dev *dev = NULL;
  160. uint32_t tmp;
  161. if (rget_io_perms())
  162. return 1;
  163. dev = pcidev_init(nics_intel_spi, PCI_BASE_ADDRESS_0);
  164. if (!dev)
  165. return 1;
  166. uint32_t io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0);
  167. if (!io_base_addr)
  168. return 1;
  169. if (dev->device_id < 0x10d8) {
  170. nicintel_spibar = rphysmap("Intel Gigabit NIC w/ SPI flash", io_base_addr,
  171. MEMMAP_SIZE);
  172. } else {
  173. nicintel_spibar = rphysmap("Intel 10 Gigabit NIC w/ SPI flash", io_base_addr + 0x10000,
  174. MEMMAP_SIZE);
  175. }
  176. if (nicintel_spibar == ERROR_PTR)
  177. return 1;
  178. /* Automatic restore of EECD on shutdown is not possible because EECD
  179. * does not only contain FLASH_WRITES_DISABLED|FLASH_WRITES_ENABLED,
  180. * but other bits with side effects as well. Those other bits must be
  181. * left untouched.
  182. */
  183. tmp = pci_mmio_readl(nicintel_spibar + EECD);
  184. tmp &= ~FLASH_WRITES_DISABLED;
  185. tmp |= FLASH_WRITES_ENABLED;
  186. pci_mmio_writel(tmp, nicintel_spibar + EECD);
  187. /* test if FWE is really set to allow writes */
  188. tmp = pci_mmio_readl(nicintel_spibar + EECD);
  189. if ( (tmp & FLASH_WRITES_DISABLED) || !(tmp & FLASH_WRITES_ENABLED) ) {
  190. msg_perr("Enabling flash write access failed.\n");
  191. return 1;
  192. }
  193. if (register_shutdown(nicintel_spi_shutdown, NULL))
  194. return 1;
  195. if (register_spi_bitbang_master(&bitbang_spi_master_nicintel))
  196. return 1;
  197. return 0;
  198. }