| 1 | /*␊ |
| 2 | * This file is part of the flashrom project.␊ |
| 3 | *␊ |
| 4 | * Copyright (C) 2008 Stefan Wildemann <stefan.wildemann@kontron.com>␊ |
| 5 | * Copyright (C) 2008 Claus Gindhart <claus.gindhart@kontron.com>␊ |
| 6 | * Copyright (C) 2008 Dominik Geyer <dominik.geyer@kontron.com>␊ |
| 7 | * Copyright (C) 2008 coresystems GmbH <info@coresystems.de>␊ |
| 8 | * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger␊ |
| 9 | * Copyright (C) 2011 Stefan Tauner␊ |
| 10 | *␊ |
| 11 | * This program is free software; you can redistribute it and/or modify␊ |
| 12 | * it under the terms of the GNU General Public License as published by␊ |
| 13 | * the Free Software Foundation; either version 2 of the License, or␊ |
| 14 | * (at your option) any later version.␊ |
| 15 | *␊ |
| 16 | * This program is distributed in the hope that it will be useful,␊ |
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of␊ |
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the␊ |
| 19 | * GNU General Public License for more details.␊ |
| 20 | *␊ |
| 21 | * You should have received a copy of the GNU General Public License␊ |
| 22 | * along with this program; if not, write to the Free Software␊ |
| 23 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA␊ |
| 24 | */␊ |
| 25 | ␊ |
| 26 | #if defined(__i386__) || defined(__x86_64__)␊ |
| 27 | ␊ |
| 28 | #include <string.h>␊ |
| 29 | #include <stdlib.h>␊ |
| 30 | #include "flash.h"␊ |
| 31 | #include "programmer.h"␊ |
| 32 | #include "spi.h"␊ |
| 33 | #include "ich_descriptors.h"␊ |
| 34 | ␊ |
| 35 | /* ICH9 controller register definition */␊ |
| 36 | #define ICH9_REG_HSFS␉␉0x04␉/* 16 Bits Hardware Sequencing Flash Status */␊ |
| 37 | #define HSFS_FDONE_OFF␉␉0␉/* 0: Flash Cycle Done */␊ |
| 38 | #define HSFS_FDONE␉␉(0x1 << HSFS_FDONE_OFF)␊ |
| 39 | #define HSFS_FCERR_OFF␉␉1␉/* 1: Flash Cycle Error */␊ |
| 40 | #define HSFS_FCERR␉␉(0x1 << HSFS_FCERR_OFF)␊ |
| 41 | #define HSFS_AEL_OFF␉␉2␉/* 2: Access Error Log */␊ |
| 42 | #define HSFS_AEL␉␉(0x1 << HSFS_AEL_OFF)␊ |
| 43 | #define HSFS_BERASE_OFF␉␉3␉/* 3-4: Block/Sector Erase Size */␊ |
| 44 | #define HSFS_BERASE␉␉(0x3 << HSFS_BERASE_OFF)␊ |
| 45 | #define HSFS_SCIP_OFF␉␉5␉/* 5: SPI Cycle In Progress */␊ |
| 46 | #define HSFS_SCIP␉␉(0x1 << HSFS_SCIP_OFF)␊ |
| 47 | ␉␉␉␉␉/* 6-12: reserved */␊ |
| 48 | #define HSFS_FDOPSS_OFF␉␉13␉/* 13: Flash Descriptor Override Pin-Strap Status */␊ |
| 49 | #define HSFS_FDOPSS␉␉(0x1 << HSFS_FDOPSS_OFF)␊ |
| 50 | #define HSFS_FDV_OFF␉␉14␉/* 14: Flash Descriptor Valid */␊ |
| 51 | #define HSFS_FDV␉␉(0x1 << HSFS_FDV_OFF)␊ |
| 52 | #define HSFS_FLOCKDN_OFF␉15␉/* 15: Flash Configuration Lock-Down */␊ |
| 53 | #define HSFS_FLOCKDN␉␉(0x1 << HSFS_FLOCKDN_OFF)␊ |
| 54 | ␊ |
| 55 | #define ICH9_REG_HSFC␉␉0x06␉/* 16 Bits Hardware Sequencing Flash Control */␊ |
| 56 | #define HSFC_FGO_OFF␉␉0␉/* 0: Flash Cycle Go */␊ |
| 57 | #define HSFC_FGO␉␉(0x1 << HSFC_FGO_OFF)␊ |
| 58 | #define HSFC_FCYCLE_OFF␉␉1␉/* 1-2: FLASH Cycle */␊ |
| 59 | #define HSFC_FCYCLE␉␉(0x3 << HSFC_FCYCLE_OFF)␊ |
| 60 | ␉␉␉␉␉/* 3-7: reserved */␊ |
| 61 | #define HSFC_FDBC_OFF␉␉8␉/* 8-13: Flash Data Byte Count */␊ |
| 62 | #define HSFC_FDBC␉␉(0x3f << HSFC_FDBC_OFF)␊ |
| 63 | ␉␉␉␉␉/* 14: reserved */␊ |
| 64 | #define HSFC_SME_OFF␉␉15␉/* 15: SPI SMI# Enable */␊ |
| 65 | #define HSFC_SME␉␉(0x1 << HSFC_SME_OFF)␊ |
| 66 | ␊ |
| 67 | #define ICH9_REG_FADDR␉␉0x08␉/* 32 Bits */␊ |
| 68 | #define ICH9_REG_FDATA0␉␉0x10␉/* 64 Bytes */␊ |
| 69 | ␊ |
| 70 | #define ICH9_REG_FRAP␉␉0x50␉/* 32 Bytes Flash Region Access Permissions */␊ |
| 71 | #define ICH9_REG_FREG0␉␉0x54␉/* 32 Bytes Flash Region 0 */␊ |
| 72 | ␊ |
| 73 | #define ICH9_REG_PR0␉␉0x74␉/* 32 Bytes Protected Range 0 */␊ |
| 74 | #define PR_WP_OFF␉␉31␉/* 31: write protection enable */␊ |
| 75 | #define PR_RP_OFF␉␉15␉/* 15: read protection enable */␊ |
| 76 | ␊ |
| 77 | #define ICH9_REG_SSFS␉␉0x90␉/* 08 Bits */␊ |
| 78 | #define SSFS_SCIP_OFF␉␉0␉/* SPI Cycle In Progress */␊ |
| 79 | #define SSFS_SCIP␉␉(0x1 << SSFS_SCIP_OFF)␊ |
| 80 | #define SSFS_FDONE_OFF␉␉2␉/* Cycle Done Status */␊ |
| 81 | #define SSFS_FDONE␉␉(0x1 << SSFS_FDONE_OFF)␊ |
| 82 | #define SSFS_FCERR_OFF␉␉3␉/* Flash Cycle Error */␊ |
| 83 | #define SSFS_FCERR␉␉(0x1 << SSFS_FCERR_OFF)␊ |
| 84 | #define SSFS_AEL_OFF␉␉4␉/* Access Error Log */␊ |
| 85 | #define SSFS_AEL␉␉(0x1 << SSFS_AEL_OFF)␊ |
| 86 | /* The following bits are reserved in SSFS: 1,5-7. */␊ |
| 87 | #define SSFS_RESERVED_MASK␉0x000000e2␊ |
| 88 | ␊ |
| 89 | #define ICH9_REG_SSFC␉␉0x91␉/* 24 Bits */␊ |
| 90 | /* We combine SSFS and SSFC to one 32-bit word,␊ |
| 91 | * therefore SSFC bits are off by 8. */␊ |
| 92 | ␉␉␉␉␉␉/* 0: reserved */␊ |
| 93 | #define SSFC_SCGO_OFF␉␉(1 + 8)␉␉/* 1: SPI Cycle Go */␊ |
| 94 | #define SSFC_SCGO␉␉(0x1 << SSFC_SCGO_OFF)␊ |
| 95 | #define SSFC_ACS_OFF␉␉(2 + 8)␉␉/* 2: Atomic Cycle Sequence */␊ |
| 96 | #define SSFC_ACS␉␉(0x1 << SSFC_ACS_OFF)␊ |
| 97 | #define SSFC_SPOP_OFF␉␉(3 + 8)␉␉/* 3: Sequence Prefix Opcode Pointer */␊ |
| 98 | #define SSFC_SPOP␉␉(0x1 << SSFC_SPOP_OFF)␊ |
| 99 | #define SSFC_COP_OFF␉␉(4 + 8)␉␉/* 4-6: Cycle Opcode Pointer */␊ |
| 100 | #define SSFC_COP␉␉(0x7 << SSFC_COP_OFF)␊ |
| 101 | ␉␉␉␉␉␉/* 7: reserved */␊ |
| 102 | #define SSFC_DBC_OFF␉␉(8 + 8)␉␉/* 8-13: Data Byte Count */␊ |
| 103 | #define SSFC_DBC␉␉(0x3f << SSFC_DBC_OFF)␊ |
| 104 | #define SSFC_DS_OFF␉␉(14 + 8)␉/* 14: Data Cycle */␊ |
| 105 | #define SSFC_DS␉␉␉(0x1 << SSFC_DS_OFF)␊ |
| 106 | #define SSFC_SME_OFF␉␉(15 + 8)␉/* 15: SPI SMI# Enable */␊ |
| 107 | #define SSFC_SME␉␉(0x1 << SSFC_SME_OFF)␊ |
| 108 | #define SSFC_SCF_OFF␉␉(16 + 8)␉/* 16-18: SPI Cycle Frequency */␊ |
| 109 | #define SSFC_SCF␉␉(0x7 << SSFC_SCF_OFF)␊ |
| 110 | #define SSFC_SCF_20MHZ␉␉0x00000000␊ |
| 111 | #define SSFC_SCF_33MHZ␉␉0x01000000␊ |
| 112 | ␉␉␉␉␉␉/* 19-23: reserved */␊ |
| 113 | #define SSFC_RESERVED_MASK␉0xf8008100␊ |
| 114 | ␊ |
| 115 | #define ICH9_REG_PREOP␉␉0x94␉/* 16 Bits */␊ |
| 116 | #define ICH9_REG_OPTYPE␉␉0x96␉/* 16 Bits */␊ |
| 117 | #define ICH9_REG_OPMENU␉␉0x98␉/* 64 Bits */␊ |
| 118 | ␊ |
| 119 | #define ICH9_REG_BBAR␉␉0xA0␉/* 32 Bits BIOS Base Address Configuration */␊ |
| 120 | #define BBAR_MASK␉0x00ffff00␉␉/* 8-23: Bottom of System Flash */␊ |
| 121 | ␊ |
| 122 | #define ICH8_REG_VSCC␉␉0xC1␉/* 32 Bits Vendor Specific Component Capabilities */␊ |
| 123 | #define ICH9_REG_LVSCC␉␉0xC4␉/* 32 Bits Host Lower Vendor Specific Component Capabilities */␊ |
| 124 | #define ICH9_REG_UVSCC␉␉0xC8␉/* 32 Bits Host Upper Vendor Specific Component Capabilities */␊ |
| 125 | /* The individual fields of the VSCC registers are defined in the file␊ |
| 126 | * ich_descriptors.h. The reason is that the same layout is also used in the␊ |
| 127 | * flash descriptor to define the properties of the different flash chips␊ |
| 128 | * supported. The BIOS (or the ME?) is responsible to populate the ICH registers␊ |
| 129 | * with the information from the descriptor on startup depending on the actual␊ |
| 130 | * chip(s) detected. */␊ |
| 131 | ␊ |
| 132 | #define ICH9_REG_FPB␉␉0xD0␉/* 32 Bits Flash Partition Boundary */␊ |
| 133 | #define FPB_FPBA_OFF␉␉0␉/* 0-12: Block/Sector Erase Size */␊ |
| 134 | #define FPB_FPBA␉␉␉(0x1FFF << FPB_FPBA_OFF)␊ |
| 135 | ␊ |
| 136 | // ICH9R SPI commands␊ |
| 137 | #define SPI_OPCODE_TYPE_READ_NO_ADDRESS␉␉0␊ |
| 138 | #define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS␉1␊ |
| 139 | #define SPI_OPCODE_TYPE_READ_WITH_ADDRESS␉2␊ |
| 140 | #define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS␉3␊ |
| 141 | ␊ |
| 142 | // ICH7 registers␊ |
| 143 | #define ICH7_REG_SPIS␉␉0x00␉/* 16 Bits */␊ |
| 144 | #define SPIS_SCIP␉␉0x0001␊ |
| 145 | #define SPIS_GRANT␉␉0x0002␊ |
| 146 | #define SPIS_CDS␉␉0x0004␊ |
| 147 | #define SPIS_FCERR␉␉0x0008␊ |
| 148 | #define SPIS_RESERVED_MASK␉0x7ff0␊ |
| 149 | ␊ |
| 150 | /* VIA SPI is compatible with ICH7, but maxdata␊ |
| 151 | to transfer is 16 bytes.␊ |
| 152 | ␊ |
| 153 | DATA byte count on ICH7 is 8:13, on VIA 8:11␊ |
| 154 | ␊ |
| 155 | bit 12 is port select CS0 CS1␊ |
| 156 | bit 13 is FAST READ enable␊ |
| 157 | bit 7 is used with fast read and one shot controls CS de-assert?␊ |
| 158 | */␊ |
| 159 | ␊ |
| 160 | #define ICH7_REG_SPIC␉␉0x02␉/* 16 Bits */␊ |
| 161 | #define SPIC_SCGO␉␉0x0002␊ |
| 162 | #define SPIC_ACS␉␉0x0004␊ |
| 163 | #define SPIC_SPOP␉␉0x0008␊ |
| 164 | #define SPIC_DS␉␉␉0x4000␊ |
| 165 | ␊ |
| 166 | #define ICH7_REG_SPIA␉␉0x04␉/* 32 Bits */␊ |
| 167 | #define ICH7_REG_SPID0␉␉0x08␉/* 64 Bytes */␊ |
| 168 | #define ICH7_REG_PREOP␉␉0x54␉/* 16 Bits */␊ |
| 169 | #define ICH7_REG_OPTYPE␉␉0x56␉/* 16 Bits */␊ |
| 170 | #define ICH7_REG_OPMENU␉␉0x58␉/* 64 Bits */␊ |
| 171 | ␊ |
| 172 | /* ICH SPI configuration lock-down. May be set during chipset enabling. */␊ |
| 173 | static int ichspi_lock = 0;␊ |
| 174 | ␊ |
| 175 | static enum ich_chipset ich_generation = CHIPSET_ICH_UNKNOWN;␊ |
| 176 | uint32_t ichspi_bbar = 0;␊ |
| 177 | ␊ |
| 178 | static void *ich_spibar = NULL;␊ |
| 179 | ␊ |
| 180 | typedef struct _OPCODE {␊ |
| 181 | ␉uint8_t opcode;␉␉//This commands spi opcode␊ |
| 182 | ␉uint8_t spi_type;␉//This commands spi type␊ |
| 183 | ␉uint8_t atomic;␉␉//Use preop: (0: none, 1: preop0, 2: preop1␊ |
| 184 | } OPCODE;␊ |
| 185 | ␊ |
| 186 | /* Suggested opcode definition:␊ |
| 187 | * Preop 1: Write Enable␊ |
| 188 | * Preop 2: Write Status register enable␊ |
| 189 | *␊ |
| 190 | * OP 0: Write address␊ |
| 191 | * OP 1: Read Address␊ |
| 192 | * OP 2: ERASE block␊ |
| 193 | * OP 3: Read Status register␊ |
| 194 | * OP 4: Read ID␊ |
| 195 | * OP 5: Write Status register␊ |
| 196 | * OP 6: chip private (read JEDEC id)␊ |
| 197 | * OP 7: Chip erase␊ |
| 198 | */␊ |
| 199 | typedef struct _OPCODES {␊ |
| 200 | ␉uint8_t preop[2];␊ |
| 201 | ␉OPCODE opcode[8];␊ |
| 202 | } OPCODES;␊ |
| 203 | ␊ |
| 204 | static OPCODES *curopcodes = NULL;␊ |
| 205 | ␊ |
| 206 | /* HW access functions */␊ |
| 207 | static uint32_t REGREAD32(int X)␊ |
| 208 | {␊ |
| 209 | ␉return mmio_readl(ich_spibar + X);␊ |
| 210 | }␊ |
| 211 | ␊ |
| 212 | static uint16_t REGREAD16(int X)␊ |
| 213 | {␊ |
| 214 | ␉return mmio_readw(ich_spibar + X);␊ |
| 215 | }␊ |
| 216 | ␊ |
| 217 | static uint16_t REGREAD8(int X)␊ |
| 218 | {␊ |
| 219 | ␉return mmio_readb(ich_spibar + X);␊ |
| 220 | }␊ |
| 221 | ␊ |
| 222 | #define REGWRITE32(off, val) mmio_writel(val, ich_spibar+(off))␊ |
| 223 | #define REGWRITE16(off, val) mmio_writew(val, ich_spibar+(off))␊ |
| 224 | #define REGWRITE8(off, val) mmio_writeb(val, ich_spibar+(off))␊ |
| 225 | ␊ |
| 226 | /* Common SPI functions */␊ |
| 227 | static int find_opcode(OPCODES *op, uint8_t opcode);␊ |
| 228 | static int find_preop(OPCODES *op, uint8_t preop);␊ |
| 229 | static int generate_opcodes(OPCODES * op);␊ |
| 230 | static int program_opcodes(OPCODES *op, int enable_undo);␊ |
| 231 | static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset,␊ |
| 232 | ␉␉ uint8_t datalength, uint8_t * data);␊ |
| 233 | ␊ |
| 234 | /* for pairing opcodes with their required preop */␊ |
| 235 | struct preop_opcode_pair {␊ |
| 236 | ␉uint8_t preop;␊ |
| 237 | ␉uint8_t opcode;␊ |
| 238 | };␊ |
| 239 | ␊ |
| 240 | /* List of opcodes which need preopcodes and matching preopcodes. Unused. */␊ |
| 241 | const struct preop_opcode_pair pops[] = {␊ |
| 242 | ␉{JEDEC_WREN, JEDEC_BYTE_PROGRAM},␊ |
| 243 | ␉{JEDEC_WREN, JEDEC_SE}, /* sector erase */␊ |
| 244 | ␉{JEDEC_WREN, JEDEC_BE_52}, /* block erase */␊ |
| 245 | ␉{JEDEC_WREN, JEDEC_BE_D8}, /* block erase */␊ |
| 246 | ␉{JEDEC_WREN, JEDEC_CE_60}, /* chip erase */␊ |
| 247 | ␉{JEDEC_WREN, JEDEC_CE_C7}, /* chip erase */␊ |
| 248 | ␉ /* FIXME: WRSR requires either EWSR or WREN depending on chip type. */␊ |
| 249 | ␉{JEDEC_WREN, JEDEC_WRSR},␊ |
| 250 | ␉{JEDEC_EWSR, JEDEC_WRSR},␊ |
| 251 | ␉{0,}␊ |
| 252 | };␊ |
| 253 | ␊ |
| 254 | /* Reasonable default configuration. Needs ad-hoc modifications if we␊ |
| 255 | * encounter unlisted opcodes. Fun.␊ |
| 256 | */␊ |
| 257 | static OPCODES O_ST_M25P = {␊ |
| 258 | ␉{␊ |
| 259 | ␉ JEDEC_WREN,␊ |
| 260 | ␉ JEDEC_EWSR,␊ |
| 261 | ␉},␊ |
| 262 | ␉{␊ |
| 263 | ␉ {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0},␉// Write Byte␊ |
| 264 | ␉ {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0},␉// Read Data␊ |
| 265 | ␉ {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0},␉// Erase Sector␊ |
| 266 | ␉ {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0},␉// Read Device Status Reg␊ |
| 267 | ␉ {JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0},␉// Read Electronic Manufacturer Signature␊ |
| 268 | ␉ {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0},␉// Write Status Register␊ |
| 269 | ␉ {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0},␉// Read JDEC ID␊ |
| 270 | ␉ {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0},␉// Bulk erase␊ |
| 271 | ␉}␊ |
| 272 | };␊ |
| 273 | ␊ |
| 274 | /* List of opcodes with their corresponding spi_type␊ |
| 275 | * It is used to reprogram the chipset OPCODE table on-the-fly if an opcode␊ |
| 276 | * is needed which is currently not in the chipset OPCODE table␊ |
| 277 | */␊ |
| 278 | static OPCODE POSSIBLE_OPCODES[] = {␊ |
| 279 | ␉ {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0},␉// Write Byte␊ |
| 280 | ␉ {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0},␉// Read Data␊ |
| 281 | ␉ {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0},␉// Erase Sector␊ |
| 282 | ␉ {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0},␉// Read Device Status Reg␊ |
| 283 | ␉ {JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0},␉// Read Electronic Manufacturer Signature␊ |
| 284 | ␉ {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0},␉// Write Status Register␊ |
| 285 | ␉ {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0},␉// Read JDEC ID␊ |
| 286 | ␉ {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0},␉// Bulk erase␊ |
| 287 | ␉ {JEDEC_SE, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0},␉// Sector erase␊ |
| 288 | ␉ {JEDEC_BE_52, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0},␉// Block erase␊ |
| 289 | ␉ {JEDEC_AAI_WORD_PROGRAM, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0},␉// Auto Address Increment␊ |
| 290 | };␊ |
| 291 | ␊ |
| 292 | static OPCODES O_EXISTING = {};␊ |
| 293 | ␊ |
| 294 | /* pretty printing functions */␊ |
| 295 | static void prettyprint_opcodes(OPCODES *ops)␊ |
| 296 | {␊ |
| 297 | ␉OPCODE oc;␊ |
| 298 | ␉const char *t;␊ |
| 299 | ␉const char *a;␊ |
| 300 | ␉uint8_t i;␊ |
| 301 | ␉static const char *const spi_type[4] = {␊ |
| 302 | ␉␉"read w/o addr",␊ |
| 303 | ␉␉"write w/o addr",␊ |
| 304 | ␉␉"read w/ addr",␊ |
| 305 | ␉␉"write w/ addr"␊ |
| 306 | ␉};␊ |
| 307 | ␉static const char *const atomic_type[3] = {␊ |
| 308 | ␉␉"none",␊ |
| 309 | ␉␉" 0 ",␊ |
| 310 | ␉␉" 1 "␊ |
| 311 | ␉};␊ |
| 312 | ␊ |
| 313 | ␉if (ops == NULL)␊ |
| 314 | ␉␉return;␊ |
| 315 | ␊ |
| 316 | ␉msg_pdbg2(" OP Type Pre-OP\n");␊ |
| 317 | ␉for (i = 0; i < 8; i++) {␊ |
| 318 | ␉␉oc = ops->opcode[i];␊ |
| 319 | ␉␉t = (oc.spi_type > 3) ? "invalid" : spi_type[oc.spi_type];␊ |
| 320 | ␉␉a = (oc.atomic > 2) ? "invalid" : atomic_type[oc.atomic];␊ |
| 321 | ␉␉msg_pdbg2("op[%d]: 0x%02x, %s, %s\n", i, oc.opcode, t, a);␊ |
| 322 | ␉}␊ |
| 323 | ␉msg_pdbg2("Pre-OP 0: 0x%02x, Pre-OP 1: 0x%02x\n", ops->preop[0],␊ |
| 324 | ␉␉ ops->preop[1]);␊ |
| 325 | }␊ |
| 326 | ␊ |
| 327 | #define pprint_reg(reg, bit, val, sep) msg_pdbg("%s=%d" sep, #bit, (val & reg##_##bit)>>reg##_##bit##_OFF)␊ |
| 328 | ␊ |
| 329 | static void prettyprint_ich9_reg_hsfs(uint16_t reg_val)␊ |
| 330 | {␊ |
| 331 | ␉msg_pdbg("HSFS: ");␊ |
| 332 | ␉pprint_reg(HSFS, FDONE, reg_val, ", ");␊ |
| 333 | ␉pprint_reg(HSFS, FCERR, reg_val, ", ");␊ |
| 334 | ␉pprint_reg(HSFS, AEL, reg_val, ", ");␊ |
| 335 | ␉pprint_reg(HSFS, BERASE, reg_val, ", ");␊ |
| 336 | ␉pprint_reg(HSFS, SCIP, reg_val, ", ");␊ |
| 337 | ␉pprint_reg(HSFS, FDOPSS, reg_val, ", ");␊ |
| 338 | ␉pprint_reg(HSFS, FDV, reg_val, ", ");␊ |
| 339 | ␉pprint_reg(HSFS, FLOCKDN, reg_val, "\n");␊ |
| 340 | }␊ |
| 341 | ␊ |
| 342 | static void prettyprint_ich9_reg_hsfc(uint16_t reg_val)␊ |
| 343 | {␊ |
| 344 | ␉msg_pdbg("HSFC: ");␊ |
| 345 | ␉pprint_reg(HSFC, FGO, reg_val, ", ");␊ |
| 346 | ␉pprint_reg(HSFC, FCYCLE, reg_val, ", ");␊ |
| 347 | ␉pprint_reg(HSFC, FDBC, reg_val, ", ");␊ |
| 348 | ␉pprint_reg(HSFC, SME, reg_val, "\n");␊ |
| 349 | }␊ |
| 350 | ␊ |
| 351 | static void prettyprint_ich9_reg_ssfs(uint32_t reg_val)␊ |
| 352 | {␊ |
| 353 | ␉msg_pdbg("SSFS: ");␊ |
| 354 | ␉pprint_reg(SSFS, SCIP, reg_val, ", ");␊ |
| 355 | ␉pprint_reg(SSFS, FDONE, reg_val, ", ");␊ |
| 356 | ␉pprint_reg(SSFS, FCERR, reg_val, ", ");␊ |
| 357 | ␉pprint_reg(SSFS, AEL, reg_val, "\n");␊ |
| 358 | }␊ |
| 359 | ␊ |
| 360 | static void prettyprint_ich9_reg_ssfc(uint32_t reg_val)␊ |
| 361 | {␊ |
| 362 | ␉msg_pdbg("SSFC: ");␊ |
| 363 | ␉pprint_reg(SSFC, SCGO, reg_val, ", ");␊ |
| 364 | ␉pprint_reg(SSFC, ACS, reg_val, ", ");␊ |
| 365 | ␉pprint_reg(SSFC, SPOP, reg_val, ", ");␊ |
| 366 | ␉pprint_reg(SSFC, COP, reg_val, ", ");␊ |
| 367 | ␉pprint_reg(SSFC, DBC, reg_val, ", ");␊ |
| 368 | ␉pprint_reg(SSFC, SME, reg_val, ", ");␊ |
| 369 | ␉pprint_reg(SSFC, SCF, reg_val, "\n");␊ |
| 370 | }␊ |
| 371 | ␊ |
| 372 | static uint8_t lookup_spi_type(uint8_t opcode)␊ |
| 373 | {␊ |
| 374 | ␉int a;␊ |
| 375 | ␊ |
| 376 | ␉for (a = 0; a < ARRAY_SIZE(POSSIBLE_OPCODES); a++) {␊ |
| 377 | ␉␉if (POSSIBLE_OPCODES[a].opcode == opcode)␊ |
| 378 | ␉␉␉return POSSIBLE_OPCODES[a].spi_type;␊ |
| 379 | ␉}␊ |
| 380 | ␊ |
| 381 | ␉return 0xFF;␊ |
| 382 | }␊ |
| 383 | ␊ |
| 384 | static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, unsigned int readcnt)␊ |
| 385 | {␊ |
| 386 | ␉uint8_t spi_type;␊ |
| 387 | ␊ |
| 388 | ␉spi_type = lookup_spi_type(opcode);␊ |
| 389 | ␉if (spi_type > 3) {␊ |
| 390 | ␉␉/* Try to guess spi type from read/write sizes.␊ |
| 391 | ␉␉ * The following valid writecnt/readcnt combinations exist:␊ |
| 392 | ␉␉ * writecnt = 4, readcnt >= 0␊ |
| 393 | ␉␉ * writecnt = 1, readcnt >= 0␊ |
| 394 | ␉␉ * writecnt >= 4, readcnt = 0␊ |
| 395 | ␉␉ * writecnt >= 1, readcnt = 0␊ |
| 396 | ␉␉ * writecnt >= 1 is guaranteed for all commands.␊ |
| 397 | ␉␉ */␊ |
| 398 | ␉␉if (readcnt == 0)␊ |
| 399 | ␉␉␉/* if readcnt=0 and writecount >= 4, we don't know if it is WRITE_NO_ADDRESS␊ |
| 400 | ␉␉␉ * or WRITE_WITH_ADDRESS. But if we use WRITE_NO_ADDRESS and the first 3 data␊ |
| 401 | ␉␉␉ * bytes are actual the address, they go to the bus anyhow␊ |
| 402 | ␉␉␉ */␊ |
| 403 | ␉␉␉spi_type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;␊ |
| 404 | ␉␉else if (writecnt == 1) // and readcnt is > 0␊ |
| 405 | ␉␉␉spi_type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;␊ |
| 406 | ␉␉else if (writecnt == 4) // and readcnt is > 0␊ |
| 407 | ␉␉␉spi_type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;␊ |
| 408 | ␉␉// else we have an invalid case, will be handled below␊ |
| 409 | ␉}␊ |
| 410 | ␉if (spi_type <= 3) {␊ |
| 411 | ␉␉int oppos=2;␉// use original JEDEC_BE_D8 offset␊ |
| 412 | ␉␉curopcodes->opcode[oppos].opcode = opcode;␊ |
| 413 | ␉␉curopcodes->opcode[oppos].spi_type = spi_type;␊ |
| 414 | ␉␉program_opcodes(curopcodes, 0);␊ |
| 415 | ␉␉oppos = find_opcode(curopcodes, opcode);␊ |
| 416 | ␉␉msg_pdbg ("on-the-fly OPCODE (0x%02X) re-programmed, op-pos=%d\n", opcode, oppos);␊ |
| 417 | ␉␉return oppos;␊ |
| 418 | ␉}␊ |
| 419 | ␉return -1;␊ |
| 420 | }␊ |
| 421 | ␊ |
| 422 | static int find_opcode(OPCODES *op, uint8_t opcode)␊ |
| 423 | {␊ |
| 424 | ␉int a;␊ |
| 425 | ␊ |
| 426 | ␉if (op == NULL) {␊ |
| 427 | ␉␉msg_perr("\n%s: null OPCODES pointer!\n", __func__);␊ |
| 428 | ␉␉return -1;␊ |
| 429 | ␉}␊ |
| 430 | ␊ |
| 431 | ␉for (a = 0; a < 8; a++) {␊ |
| 432 | ␉␉if (op->opcode[a].opcode == opcode)␊ |
| 433 | ␉␉␉return a;␊ |
| 434 | ␉}␊ |
| 435 | ␊ |
| 436 | ␉return -1;␊ |
| 437 | }␊ |
| 438 | ␊ |
| 439 | static int find_preop(OPCODES *op, uint8_t preop)␊ |
| 440 | {␊ |
| 441 | ␉int a;␊ |
| 442 | ␊ |
| 443 | ␉if (op == NULL) {␊ |
| 444 | ␉␉msg_perr("\n%s: null OPCODES pointer!\n", __func__);␊ |
| 445 | ␉␉return -1;␊ |
| 446 | ␉}␊ |
| 447 | ␊ |
| 448 | ␉for (a = 0; a < 2; a++) {␊ |
| 449 | ␉␉if (op->preop[a] == preop)␊ |
| 450 | ␉␉␉return a;␊ |
| 451 | ␉}␊ |
| 452 | ␊ |
| 453 | ␉return -1;␊ |
| 454 | }␊ |
| 455 | ␊ |
| 456 | /* Create a struct OPCODES based on what we find in the locked down chipset. */␊ |
| 457 | static int generate_opcodes(OPCODES * op)␊ |
| 458 | {␊ |
| 459 | ␉int a;␊ |
| 460 | ␉uint16_t preop, optype;␊ |
| 461 | ␉uint32_t opmenu[2];␊ |
| 462 | ␊ |
| 463 | ␉if (op == NULL) {␊ |
| 464 | ␉␉msg_perr("\n%s: null OPCODES pointer!\n", __func__);␊ |
| 465 | ␉␉return -1;␊ |
| 466 | ␉}␊ |
| 467 | ␊ |
| 468 | ␉switch (ich_generation) {␊ |
| 469 | ␉case CHIPSET_ICH7:␊ |
| 470 | ␉␉preop = REGREAD16(ICH7_REG_PREOP);␊ |
| 471 | ␉␉optype = REGREAD16(ICH7_REG_OPTYPE);␊ |
| 472 | ␉␉opmenu[0] = REGREAD32(ICH7_REG_OPMENU);␊ |
| 473 | ␉␉opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4);␊ |
| 474 | ␉␉break;␊ |
| 475 | ␉case CHIPSET_ICH8:␊ |
| 476 | ␉default:␉␉/* Future version might behave the same */␊ |
| 477 | ␉␉preop = REGREAD16(ICH9_REG_PREOP);␊ |
| 478 | ␉␉optype = REGREAD16(ICH9_REG_OPTYPE);␊ |
| 479 | ␉␉opmenu[0] = REGREAD32(ICH9_REG_OPMENU);␊ |
| 480 | ␉␉opmenu[1] = REGREAD32(ICH9_REG_OPMENU + 4);␊ |
| 481 | ␉␉break;␊ |
| 482 | ␉}␊ |
| 483 | ␊ |
| 484 | ␉op->preop[0] = (uint8_t) preop;␊ |
| 485 | ␉op->preop[1] = (uint8_t) (preop >> 8);␊ |
| 486 | ␊ |
| 487 | ␉for (a = 0; a < 8; a++) {␊ |
| 488 | ␉␉op->opcode[a].spi_type = (uint8_t) (optype & 0x3);␊ |
| 489 | ␉␉optype >>= 2;␊ |
| 490 | ␉}␊ |
| 491 | ␊ |
| 492 | ␉for (a = 0; a < 4; a++) {␊ |
| 493 | ␉␉op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff);␊ |
| 494 | ␉␉opmenu[0] >>= 8;␊ |
| 495 | ␉}␊ |
| 496 | ␊ |
| 497 | ␉for (a = 4; a < 8; a++) {␊ |
| 498 | ␉␉op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff);␊ |
| 499 | ␉␉opmenu[1] >>= 8;␊ |
| 500 | ␉}␊ |
| 501 | ␊ |
| 502 | ␉/* No preopcodes used by default. */␊ |
| 503 | ␉for (a = 0; a < 8; a++)␊ |
| 504 | ␉␉op->opcode[a].atomic = 0;␊ |
| 505 | ␊ |
| 506 | ␉return 0;␊ |
| 507 | }␊ |
| 508 | ␊ |
| 509 | static int program_opcodes(OPCODES *op, int enable_undo)␊ |
| 510 | {␊ |
| 511 | ␉uint8_t a;␊ |
| 512 | ␉uint16_t preop, optype;␊ |
| 513 | ␉uint32_t opmenu[2];␊ |
| 514 | ␊ |
| 515 | ␉/* Program Prefix Opcodes */␊ |
| 516 | ␉/* 0:7 Prefix Opcode 1 */␊ |
| 517 | ␉preop = (op->preop[0]);␊ |
| 518 | ␉/* 8:16 Prefix Opcode 2 */␊ |
| 519 | ␉preop |= ((uint16_t) op->preop[1]) << 8;␊ |
| 520 | ␊ |
| 521 | ␉/* Program Opcode Types 0 - 7 */␊ |
| 522 | ␉optype = 0;␊ |
| 523 | ␉for (a = 0; a < 8; a++) {␊ |
| 524 | ␉␉optype |= ((uint16_t) op->opcode[a].spi_type) << (a * 2);␊ |
| 525 | ␉}␊ |
| 526 | ␊ |
| 527 | ␉/* Program Allowable Opcodes 0 - 3 */␊ |
| 528 | ␉opmenu[0] = 0;␊ |
| 529 | ␉for (a = 0; a < 4; a++) {␊ |
| 530 | ␉␉opmenu[0] |= ((uint32_t) op->opcode[a].opcode) << (a * 8);␊ |
| 531 | ␉}␊ |
| 532 | ␊ |
| 533 | ␉/*Program Allowable Opcodes 4 - 7 */␊ |
| 534 | ␉opmenu[1] = 0;␊ |
| 535 | ␉for (a = 4; a < 8; a++) {␊ |
| 536 | ␉␉opmenu[1] |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8);␊ |
| 537 | ␉}␊ |
| 538 | ␊ |
| 539 | ␉msg_pdbg("\n%s: preop=%04x optype=%04x opmenu=%08x%08x\n", __func__, preop, optype, opmenu[0], opmenu[1]);␊ |
| 540 | ␉switch (ich_generation) {␊ |
| 541 | ␉case CHIPSET_ICH7:␊ |
| 542 | ␉␉/* Register undo only for enable_undo=1, i.e. first call. */␊ |
| 543 | ␉␉if (enable_undo) {␊ |
| 544 | ␉␉␉rmmio_valw(ich_spibar + ICH7_REG_PREOP);␊ |
| 545 | ␉␉␉rmmio_valw(ich_spibar + ICH7_REG_OPTYPE);␊ |
| 546 | ␉␉␉rmmio_vall(ich_spibar + ICH7_REG_OPMENU);␊ |
| 547 | ␉␉␉rmmio_vall(ich_spibar + ICH7_REG_OPMENU + 4);␊ |
| 548 | ␉␉}␊ |
| 549 | ␉␉mmio_writew(preop, ich_spibar + ICH7_REG_PREOP);␊ |
| 550 | ␉␉mmio_writew(optype, ich_spibar + ICH7_REG_OPTYPE);␊ |
| 551 | ␉␉mmio_writel(opmenu[0], ich_spibar + ICH7_REG_OPMENU);␊ |
| 552 | ␉␉mmio_writel(opmenu[1], ich_spibar + ICH7_REG_OPMENU + 4);␊ |
| 553 | ␉␉break;␊ |
| 554 | ␉case CHIPSET_ICH8:␊ |
| 555 | ␉default:␉␉/* Future version might behave the same */␊ |
| 556 | ␉␉/* Register undo only for enable_undo=1, i.e. first call. */␊ |
| 557 | ␉␉if (enable_undo) {␊ |
| 558 | ␉␉␉rmmio_valw(ich_spibar + ICH9_REG_PREOP);␊ |
| 559 | ␉␉␉rmmio_valw(ich_spibar + ICH9_REG_OPTYPE);␊ |
| 560 | ␉␉␉rmmio_vall(ich_spibar + ICH9_REG_OPMENU);␊ |
| 561 | ␉␉␉rmmio_vall(ich_spibar + ICH9_REG_OPMENU + 4);␊ |
| 562 | ␉␉}␊ |
| 563 | ␉␉mmio_writew(preop, ich_spibar + ICH9_REG_PREOP);␊ |
| 564 | ␉␉mmio_writew(optype, ich_spibar + ICH9_REG_OPTYPE);␊ |
| 565 | ␉␉mmio_writel(opmenu[0], ich_spibar + ICH9_REG_OPMENU);␊ |
| 566 | ␉␉mmio_writel(opmenu[1], ich_spibar + ICH9_REG_OPMENU + 4);␊ |
| 567 | ␉␉break;␊ |
| 568 | ␉}␊ |
| 569 | ␊ |
| 570 | ␉return 0;␊ |
| 571 | }␊ |
| 572 | ␊ |
| 573 | /*␊ |
| 574 | * Returns -1 if at least one mandatory opcode is inaccessible, 0 otherwise.␊ |
| 575 | * FIXME: this should also check for␊ |
| 576 | * - at least one probing opcode (RDID (incl. AT25F variants?), REMS, RES?)␊ |
| 577 | * - at least one erasing opcode (lots.)␊ |
| 578 | * - at least one program opcode (BYTE_PROGRAM, AAI_WORD_PROGRAM, ...?)␊ |
| 579 | * - necessary preops? (EWSR, WREN, ...?)␊ |
| 580 | */␊ |
| 581 | static int ich_missing_opcodes()␊ |
| 582 | {␊ |
| 583 | ␉uint8_t ops[] = {␊ |
| 584 | ␉␉JEDEC_READ,␊ |
| 585 | ␉␉JEDEC_RDSR,␊ |
| 586 | ␉␉0␊ |
| 587 | ␉};␊ |
| 588 | ␉int i = 0;␊ |
| 589 | ␉while (ops[i] != 0) {␊ |
| 590 | ␉␉msg_pspew("checking for opcode 0x%02x\n", ops[i]);␊ |
| 591 | ␉␉if (find_opcode(curopcodes, ops[i]) == -1)␊ |
| 592 | ␉␉␉return -1;␊ |
| 593 | ␉␉i++;␊ |
| 594 | ␉}␊ |
| 595 | ␉return 0;␊ |
| 596 | }␊ |
| 597 | ␊ |
| 598 | /*␊ |
| 599 | * Try to set BBAR (BIOS Base Address Register), but read back the value in case␊ |
| 600 | * it didn't stick.␊ |
| 601 | */␊ |
| 602 | static void ich_set_bbar(uint32_t min_addr)␊ |
| 603 | {␊ |
| 604 | ␉int bbar_off;␊ |
| 605 | ␉switch (ich_generation) {␊ |
| 606 | ␉case CHIPSET_ICH7:␊ |
| 607 | ␉␉bbar_off = 0x50;␊ |
| 608 | ␉␉break;␊ |
| 609 | ␉case CHIPSET_ICH8:␊ |
| 610 | ␉␉msg_perr("BBAR offset is unknown on ICH8!\n");␊ |
| 611 | ␉␉return;␊ |
| 612 | ␉case CHIPSET_ICH9:␊ |
| 613 | ␉default:␉␉/* Future version might behave the same */␊ |
| 614 | ␉␉bbar_off = ICH9_REG_BBAR;␊ |
| 615 | ␉␉break;␊ |
| 616 | ␉}␊ |
| 617 | ␉␊ |
| 618 | ␉ichspi_bbar = mmio_readl(ich_spibar + bbar_off) & ~BBAR_MASK;␊ |
| 619 | ␉if (ichspi_bbar) {␊ |
| 620 | ␉␉msg_pdbg("Reserved bits in BBAR not zero: 0x%08x\n",␊ |
| 621 | ␉␉␉ ichspi_bbar);␊ |
| 622 | ␉}␊ |
| 623 | ␉min_addr &= BBAR_MASK;␊ |
| 624 | ␉ichspi_bbar |= min_addr;␊ |
| 625 | ␉rmmio_writel(ichspi_bbar, ich_spibar + bbar_off);␊ |
| 626 | ␉ichspi_bbar = mmio_readl(ich_spibar + bbar_off) & BBAR_MASK;␊ |
| 627 | ␊ |
| 628 | ␉/* We don't have any option except complaining. And if the write␊ |
| 629 | ␉ * failed, the restore will fail as well, so no problem there.␊ |
| 630 | ␉ */␊ |
| 631 | ␉if (ichspi_bbar != min_addr)␊ |
| 632 | ␉␉msg_perr("Setting BBAR to 0x%08x failed! New value: 0x%08x.\n",␊ |
| 633 | ␉␉␉ min_addr, ichspi_bbar);␊ |
| 634 | }␊ |
| 635 | ␊ |
| 636 | /* Read len bytes from the fdata/spid register into the data array.␊ |
| 637 | *␊ |
| 638 | * Note that using len > flash->pgm->spi.max_data_read will return garbage or␊ |
| 639 | * may even crash.␊ |
| 640 | */␊ |
| 641 | static void ich_read_data(uint8_t *data, int len, int reg0_off)␊ |
| 642 | {␊ |
| 643 | ␉int i;␊ |
| 644 | ␉uint32_t temp32 = 0;␊ |
| 645 | ␊ |
| 646 | ␉for (i = 0; i < len; i++) {␊ |
| 647 | ␉␉if ((i % 4) == 0)␊ |
| 648 | ␉␉␉temp32 = REGREAD32(reg0_off + i);␊ |
| 649 | ␊ |
| 650 | ␉␉data[i] = (temp32 >> ((i % 4) * 8)) & 0xff;␊ |
| 651 | ␉}␊ |
| 652 | }␊ |
| 653 | ␊ |
| 654 | /* Fill len bytes from the data array into the fdata/spid registers.␊ |
| 655 | *␊ |
| 656 | * Note that using len > flash->pgm->spi.max_data_write will trash the registers␊ |
| 657 | * following the data registers.␊ |
| 658 | */␊ |
| 659 | static void ich_fill_data(const uint8_t *data, int len, int reg0_off)␊ |
| 660 | {␊ |
| 661 | ␉uint32_t temp32 = 0;␊ |
| 662 | ␉int i;␊ |
| 663 | ␊ |
| 664 | ␉if (len <= 0)␊ |
| 665 | ␉␉return;␊ |
| 666 | ␊ |
| 667 | ␉for (i = 0; i < len; i++) {␊ |
| 668 | ␉␉if ((i % 4) == 0)␊ |
| 669 | ␉␉␉temp32 = 0;␊ |
| 670 | ␊ |
| 671 | ␉␉temp32 |= ((uint32_t) data[i]) << ((i % 4) * 8);␊ |
| 672 | ␊ |
| 673 | ␉␉if ((i % 4) == 3) /* 32 bits are full, write them to regs. */␊ |
| 674 | ␉␉␉REGWRITE32(reg0_off + (i - (i % 4)), temp32);␊ |
| 675 | ␉}␊ |
| 676 | ␉i--;␊ |
| 677 | ␉if ((i % 4) != 3) /* Write remaining data to regs. */␊ |
| 678 | ␉␉REGWRITE32(reg0_off + (i - (i % 4)), temp32);␊ |
| 679 | }␊ |
| 680 | ␊ |
| 681 | /* This function generates OPCODES from or programs OPCODES to ICH according to␊ |
| 682 | * the chipset's SPI configuration lock.␊ |
| 683 | *␊ |
| 684 | * It should be called before ICH sends any spi command.␊ |
| 685 | */␊ |
| 686 | static int ich_init_opcodes(void)␊ |
| 687 | {␊ |
| 688 | ␉int rc = 0;␊ |
| 689 | ␉OPCODES *curopcodes_done;␊ |
| 690 | ␊ |
| 691 | ␉if (curopcodes)␊ |
| 692 | ␉␉return 0;␊ |
| 693 | ␊ |
| 694 | ␉if (ichspi_lock) {␊ |
| 695 | ␉␉msg_pdbg("Reading OPCODES... ");␊ |
| 696 | ␉␉curopcodes_done = &O_EXISTING;␊ |
| 697 | ␉␉rc = generate_opcodes(curopcodes_done);␊ |
| 698 | ␉} else {␊ |
| 699 | ␉␉msg_pdbg("Programming OPCODES... ");␊ |
| 700 | ␉␉curopcodes_done = &O_ST_M25P;␊ |
| 701 | ␉␉rc = program_opcodes(curopcodes_done, 1);␊ |
| 702 | ␉}␊ |
| 703 | ␊ |
| 704 | ␉if (rc) {␊ |
| 705 | ␉␉curopcodes = NULL;␊ |
| 706 | ␉␉msg_perr("failed\n");␊ |
| 707 | ␉␉return 1;␊ |
| 708 | ␉} else {␊ |
| 709 | ␉␉curopcodes = curopcodes_done;␊ |
| 710 | ␉␉msg_pdbg("done\n");␊ |
| 711 | ␉␉prettyprint_opcodes(curopcodes);␊ |
| 712 | ␉␉return 0;␊ |
| 713 | ␉}␊ |
| 714 | }␊ |
| 715 | ␊ |
| 716 | static int ich7_run_opcode(OPCODE op, uint32_t offset,␊ |
| 717 | ␉␉␉ uint8_t datalength, uint8_t * data, int maxdata)␊ |
| 718 | {␊ |
| 719 | ␉int write_cmd = 0;␊ |
| 720 | ␉int timeout;␊ |
| 721 | ␉uint32_t temp32;␊ |
| 722 | ␉uint16_t temp16;␊ |
| 723 | ␉uint64_t opmenu;␊ |
| 724 | ␉int opcode_index;␊ |
| 725 | ␊ |
| 726 | ␉/* Is it a write command? */␊ |
| 727 | ␉if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)␊ |
| 728 | ␉ || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {␊ |
| 729 | ␉␉write_cmd = 1;␊ |
| 730 | ␉}␊ |
| 731 | ␊ |
| 732 | ␉timeout = 100 * 60;␉/* 60 ms are 9.6 million cycles at 16 MHz. */␊ |
| 733 | ␉while ((REGREAD16(ICH7_REG_SPIS) & SPIS_SCIP) && --timeout) {␊ |
| 734 | ␉␉programmer_delay(10);␊ |
| 735 | ␉}␊ |
| 736 | ␉if (!timeout) {␊ |
| 737 | ␉␉msg_perr("Error: SCIP never cleared!\n");␊ |
| 738 | ␉␉return 1;␊ |
| 739 | ␉}␊ |
| 740 | ␊ |
| 741 | ␉/* Program offset in flash into SPIA while preserving reserved bits. */␊ |
| 742 | ␉temp32 = REGREAD32(ICH7_REG_SPIA) & ~0x00FFFFFF;␊ |
| 743 | ␉REGWRITE32(ICH7_REG_SPIA, (offset & 0x00FFFFFF) | temp32);␊ |
| 744 | ␊ |
| 745 | ␉/* Program data into SPID0 to N */␊ |
| 746 | ␉if (write_cmd && (datalength != 0))␊ |
| 747 | ␉␉ich_fill_data(data, datalength, ICH7_REG_SPID0);␊ |
| 748 | ␊ |
| 749 | ␉/* Assemble SPIS */␊ |
| 750 | ␉temp16 = REGREAD16(ICH7_REG_SPIS);␊ |
| 751 | ␉/* keep reserved bits */␊ |
| 752 | ␉temp16 &= SPIS_RESERVED_MASK;␊ |
| 753 | ␉/* clear error status registers */␊ |
| 754 | ␉temp16 |= (SPIS_CDS | SPIS_FCERR);␊ |
| 755 | ␉REGWRITE16(ICH7_REG_SPIS, temp16);␊ |
| 756 | ␊ |
| 757 | ␉/* Assemble SPIC */␊ |
| 758 | ␉temp16 = 0;␊ |
| 759 | ␊ |
| 760 | ␉if (datalength != 0) {␊ |
| 761 | ␉␉temp16 |= SPIC_DS;␊ |
| 762 | ␉␉temp16 |= ((uint32_t) ((datalength - 1) & (maxdata - 1))) << 8;␊ |
| 763 | ␉}␊ |
| 764 | ␊ |
| 765 | ␉/* Select opcode */␊ |
| 766 | ␉opmenu = REGREAD32(ICH7_REG_OPMENU);␊ |
| 767 | ␉opmenu |= ((uint64_t)REGREAD32(ICH7_REG_OPMENU + 4)) << 32;␊ |
| 768 | ␊ |
| 769 | ␉for (opcode_index = 0; opcode_index < 8; opcode_index++) {␊ |
| 770 | ␉␉if ((opmenu & 0xff) == op.opcode) {␊ |
| 771 | ␉␉␉break;␊ |
| 772 | ␉␉}␊ |
| 773 | ␉␉opmenu >>= 8;␊ |
| 774 | ␉}␊ |
| 775 | ␉if (opcode_index == 8) {␊ |
| 776 | ␉␉msg_pdbg("Opcode %x not found.\n", op.opcode);␊ |
| 777 | ␉␉return 1;␊ |
| 778 | ␉}␊ |
| 779 | ␉temp16 |= ((uint16_t) (opcode_index & 0x07)) << 4;␊ |
| 780 | ␊ |
| 781 | ␉timeout = 100 * 60;␉/* 60 ms are 9.6 million cycles at 16 MHz. */␊ |
| 782 | ␉/* Handle Atomic. Atomic commands include three steps:␊ |
| 783 | ␉ - sending the preop (mainly EWSR or WREN)␊ |
| 784 | ␉ - sending the main command␊ |
| 785 | ␉ - waiting for the busy bit (WIP) to be cleared␊ |
| 786 | ␉ This means the timeout must be sufficient for chip erase␊ |
| 787 | ␉ of slow high-capacity chips.␊ |
| 788 | ␉ */␊ |
| 789 | ␉switch (op.atomic) {␊ |
| 790 | ␉case 2:␊ |
| 791 | ␉␉/* Select second preop. */␊ |
| 792 | ␉␉temp16 |= SPIC_SPOP;␊ |
| 793 | ␉␉/* And fall through. */␊ |
| 794 | ␉case 1:␊ |
| 795 | ␉␉/* Atomic command (preop+op) */␊ |
| 796 | ␉␉temp16 |= SPIC_ACS;␊ |
| 797 | ␉␉timeout = 100 * 1000 * 60;␉/* 60 seconds */␊ |
| 798 | ␉␉break;␊ |
| 799 | ␉}␊ |
| 800 | ␊ |
| 801 | ␉/* Start */␊ |
| 802 | ␉temp16 |= SPIC_SCGO;␊ |
| 803 | ␊ |
| 804 | ␉/* write it */␊ |
| 805 | ␉REGWRITE16(ICH7_REG_SPIC, temp16);␊ |
| 806 | ␊ |
| 807 | ␉/* Wait for Cycle Done Status or Flash Cycle Error. */␊ |
| 808 | ␉while (((REGREAD16(ICH7_REG_SPIS) & (SPIS_CDS | SPIS_FCERR)) == 0) &&␊ |
| 809 | ␉ --timeout) {␊ |
| 810 | ␉␉programmer_delay(10);␊ |
| 811 | ␉}␊ |
| 812 | ␉if (!timeout) {␊ |
| 813 | ␉␉msg_perr("timeout, ICH7_REG_SPIS=0x%04x\n",␊ |
| 814 | ␉␉␉ REGREAD16(ICH7_REG_SPIS));␊ |
| 815 | ␉␉return 1;␊ |
| 816 | ␉}␊ |
| 817 | ␊ |
| 818 | ␉/* FIXME: make sure we do not needlessly cause transaction errors. */␊ |
| 819 | ␉temp16 = REGREAD16(ICH7_REG_SPIS);␊ |
| 820 | ␉if (temp16 & SPIS_FCERR) {␊ |
| 821 | ␉␉msg_perr("Transaction error!\n");␊ |
| 822 | ␉␉/* keep reserved bits */␊ |
| 823 | ␉␉temp16 &= SPIS_RESERVED_MASK;␊ |
| 824 | ␉␉REGWRITE16(ICH7_REG_SPIS, temp16 | SPIS_FCERR);␊ |
| 825 | ␉␉return 1;␊ |
| 826 | ␉}␊ |
| 827 | ␊ |
| 828 | ␉if ((!write_cmd) && (datalength != 0))␊ |
| 829 | ␉␉ich_read_data(data, datalength, ICH7_REG_SPID0);␊ |
| 830 | ␊ |
| 831 | ␉return 0;␊ |
| 832 | }␊ |
| 833 | ␊ |
| 834 | static int ich9_run_opcode(OPCODE op, uint32_t offset,␊ |
| 835 | ␉␉␉ uint8_t datalength, uint8_t * data)␊ |
| 836 | {␊ |
| 837 | ␉int write_cmd = 0;␊ |
| 838 | ␉int timeout;␊ |
| 839 | ␉uint32_t temp32;␊ |
| 840 | ␉uint64_t opmenu;␊ |
| 841 | ␉int opcode_index;␊ |
| 842 | ␊ |
| 843 | ␉/* Is it a write command? */␊ |
| 844 | ␉if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)␊ |
| 845 | ␉ || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {␊ |
| 846 | ␉␉write_cmd = 1;␊ |
| 847 | ␉}␊ |
| 848 | ␊ |
| 849 | ␉timeout = 100 * 60;␉/* 60 ms are 9.6 million cycles at 16 MHz. */␊ |
| 850 | ␉while ((REGREAD8(ICH9_REG_SSFS) & SSFS_SCIP) && --timeout) {␊ |
| 851 | ␉␉programmer_delay(10);␊ |
| 852 | ␉}␊ |
| 853 | ␉if (!timeout) {␊ |
| 854 | ␉␉msg_perr("Error: SCIP never cleared!\n");␊ |
| 855 | ␉␉return 1;␊ |
| 856 | ␉}␊ |
| 857 | ␊ |
| 858 | ␉/* Program offset in flash into FADDR while preserve the reserved bits␊ |
| 859 | ␉ * and clearing the 25. address bit which is only useable in hwseq. */␊ |
| 860 | ␉temp32 = REGREAD32(ICH9_REG_FADDR) & ~0x01FFFFFF;␊ |
| 861 | ␉REGWRITE32(ICH9_REG_FADDR, (offset & 0x00FFFFFF) | temp32);␊ |
| 862 | ␊ |
| 863 | ␉/* Program data into FDATA0 to N */␊ |
| 864 | ␉if (write_cmd && (datalength != 0))␊ |
| 865 | ␉␉ich_fill_data(data, datalength, ICH9_REG_FDATA0);␊ |
| 866 | ␊ |
| 867 | ␉/* Assemble SSFS + SSFC */␊ |
| 868 | ␉temp32 = REGREAD32(ICH9_REG_SSFS);␊ |
| 869 | ␉/* Keep reserved bits only */␊ |
| 870 | ␉temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK;␊ |
| 871 | ␉/* Clear cycle done and cycle error status registers */␊ |
| 872 | ␉temp32 |= (SSFS_FDONE | SSFS_FCERR);␊ |
| 873 | ␉REGWRITE32(ICH9_REG_SSFS, temp32);␊ |
| 874 | ␊ |
| 875 | ␉/* Use 20 MHz */␊ |
| 876 | ␉temp32 |= SSFC_SCF_20MHZ;␊ |
| 877 | ␊ |
| 878 | ␉/* Set data byte count (DBC) and data cycle bit (DS) */␊ |
| 879 | ␉if (datalength != 0) {␊ |
| 880 | ␉␉uint32_t datatemp;␊ |
| 881 | ␉␉temp32 |= SSFC_DS;␊ |
| 882 | ␉␉datatemp = ((((uint32_t)datalength - 1) << SSFC_DBC_OFF) &␊ |
| 883 | ␉␉␉ SSFC_DBC);␊ |
| 884 | ␉␉temp32 |= datatemp;␊ |
| 885 | ␉}␊ |
| 886 | ␊ |
| 887 | ␉/* Select opcode */␊ |
| 888 | ␉opmenu = REGREAD32(ICH9_REG_OPMENU);␊ |
| 889 | ␉opmenu |= ((uint64_t)REGREAD32(ICH9_REG_OPMENU + 4)) << 32;␊ |
| 890 | ␊ |
| 891 | ␉for (opcode_index = 0; opcode_index < 8; opcode_index++) {␊ |
| 892 | ␉␉if ((opmenu & 0xff) == op.opcode) {␊ |
| 893 | ␉␉␉break;␊ |
| 894 | ␉␉}␊ |
| 895 | ␉␉opmenu >>= 8;␊ |
| 896 | ␉}␊ |
| 897 | ␉if (opcode_index == 8) {␊ |
| 898 | ␉␉msg_pdbg("Opcode %x not found.\n", op.opcode);␊ |
| 899 | ␉␉return 1;␊ |
| 900 | ␉}␊ |
| 901 | ␉temp32 |= ((uint32_t) (opcode_index & 0x07)) << (8 + 4);␊ |
| 902 | ␊ |
| 903 | ␉timeout = 100 * 60;␉/* 60 ms are 9.6 million cycles at 16 MHz. */␊ |
| 904 | ␉/* Handle Atomic. Atomic commands include three steps:␊ |
| 905 | ␉ - sending the preop (mainly EWSR or WREN)␊ |
| 906 | ␉ - sending the main command␊ |
| 907 | ␉ - waiting for the busy bit (WIP) to be cleared␊ |
| 908 | ␉ This means the timeout must be sufficient for chip erase␊ |
| 909 | ␉ of slow high-capacity chips.␊ |
| 910 | ␉ */␊ |
| 911 | ␉switch (op.atomic) {␊ |
| 912 | ␉case 2:␊ |
| 913 | ␉␉/* Select second preop. */␊ |
| 914 | ␉␉temp32 |= SSFC_SPOP;␊ |
| 915 | ␉␉/* And fall through. */␊ |
| 916 | ␉case 1:␊ |
| 917 | ␉␉/* Atomic command (preop+op) */␊ |
| 918 | ␉␉temp32 |= SSFC_ACS;␊ |
| 919 | ␉␉timeout = 100 * 1000 * 60;␉/* 60 seconds */␊ |
| 920 | ␉␉break;␊ |
| 921 | ␉}␊ |
| 922 | ␊ |
| 923 | ␉/* Start */␊ |
| 924 | ␉temp32 |= SSFC_SCGO;␊ |
| 925 | ␊ |
| 926 | ␉/* write it */␊ |
| 927 | ␉REGWRITE32(ICH9_REG_SSFS, temp32);␊ |
| 928 | ␊ |
| 929 | ␉/* Wait for Cycle Done Status or Flash Cycle Error. */␊ |
| 930 | ␉while (((REGREAD32(ICH9_REG_SSFS) & (SSFS_FDONE | SSFS_FCERR)) == 0) &&␊ |
| 931 | ␉ --timeout) {␊ |
| 932 | ␉␉programmer_delay(10);␊ |
| 933 | ␉}␊ |
| 934 | ␉if (!timeout) {␊ |
| 935 | ␉␉msg_perr("timeout, ICH9_REG_SSFS=0x%08x\n",␊ |
| 936 | ␉␉␉ REGREAD32(ICH9_REG_SSFS));␊ |
| 937 | ␉␉return 1;␊ |
| 938 | ␉}␊ |
| 939 | ␊ |
| 940 | ␉/* FIXME make sure we do not needlessly cause transaction errors. */␊ |
| 941 | ␉temp32 = REGREAD32(ICH9_REG_SSFS);␊ |
| 942 | ␉if (temp32 & SSFS_FCERR) {␊ |
| 943 | ␉␉msg_perr("Transaction error!\n");␊ |
| 944 | ␉␉prettyprint_ich9_reg_ssfs(temp32);␊ |
| 945 | ␉␉prettyprint_ich9_reg_ssfc(temp32);␊ |
| 946 | ␉␉/* keep reserved bits */␊ |
| 947 | ␉␉temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK;␊ |
| 948 | ␉␉/* Clear the transaction error. */␊ |
| 949 | ␉␉REGWRITE32(ICH9_REG_SSFS, temp32 | SSFS_FCERR);␊ |
| 950 | ␉␉return 1;␊ |
| 951 | ␉}␊ |
| 952 | ␊ |
| 953 | ␉if ((!write_cmd) && (datalength != 0))␊ |
| 954 | ␉␉ich_read_data(data, datalength, ICH9_REG_FDATA0);␊ |
| 955 | ␊ |
| 956 | ␉return 0;␊ |
| 957 | }␊ |
| 958 | ␊ |
| 959 | static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset,␊ |
| 960 | ␉␉ uint8_t datalength, uint8_t * data)␊ |
| 961 | {␊ |
| 962 | ␉/* max_data_read == max_data_write for all Intel/VIA SPI masters */␊ |
| 963 | ␉uint8_t maxlength = flash->pgm->spi.max_data_read;␊ |
| 964 | ␊ |
| 965 | ␉if (ich_generation == CHIPSET_ICH_UNKNOWN) {␊ |
| 966 | ␉␉msg_perr("%s: unsupported chipset\n", __func__);␊ |
| 967 | ␉␉return -1;␊ |
| 968 | ␉}␊ |
| 969 | ␊ |
| 970 | ␉if (datalength > maxlength) {␊ |
| 971 | ␉␉msg_perr("%s: Internal command size error for "␊ |
| 972 | ␉␉␉"opcode 0x%02x, got datalength=%i, want <=%i\n",␊ |
| 973 | ␉␉␉__func__, op.opcode, datalength, maxlength);␊ |
| 974 | ␉␉return SPI_INVALID_LENGTH;␊ |
| 975 | ␉}␊ |
| 976 | ␊ |
| 977 | ␉switch (ich_generation) {␊ |
| 978 | ␉case CHIPSET_ICH7:␊ |
| 979 | ␉␉return ich7_run_opcode(op, offset, datalength, data, maxlength);␊ |
| 980 | ␉case CHIPSET_ICH8:␊ |
| 981 | ␉default:␉␉/* Future version might behave the same */␊ |
| 982 | ␉␉return ich9_run_opcode(op, offset, datalength, data);␊ |
| 983 | ␉}␊ |
| 984 | }␊ |
| 985 | ␊ |
| 986 | static int ich_spi_send_command(struct flashctx *flash, unsigned int writecnt,␊ |
| 987 | ␉␉␉␉unsigned int readcnt,␊ |
| 988 | ␉␉␉␉const unsigned char *writearr,␊ |
| 989 | ␉␉␉␉unsigned char *readarr)␊ |
| 990 | {␊ |
| 991 | ␉int result;␊ |
| 992 | ␉int opcode_index = -1;␊ |
| 993 | ␉const unsigned char cmd = *writearr;␊ |
| 994 | ␉OPCODE *opcode;␊ |
| 995 | ␉uint32_t addr = 0;␊ |
| 996 | ␉uint8_t *data;␊ |
| 997 | ␉int count;␊ |
| 998 | ␊ |
| 999 | ␉/* find cmd in opcodes-table */␊ |
| 1000 | ␉opcode_index = find_opcode(curopcodes, cmd);␊ |
| 1001 | ␉if (opcode_index == -1) {␊ |
| 1002 | ␉␉if (!ichspi_lock)␊ |
| 1003 | ␉␉␉opcode_index = reprogram_opcode_on_the_fly(cmd, writecnt, readcnt);␊ |
| 1004 | ␉␉if (opcode_index == -1) {␊ |
| 1005 | ␉␉␉msg_pdbg("Invalid OPCODE 0x%02x, will not execute.\n",␊ |
| 1006 | ␉␉␉␉ cmd);␊ |
| 1007 | ␉␉␉return SPI_INVALID_OPCODE;␊ |
| 1008 | ␉␉}␊ |
| 1009 | ␉}␊ |
| 1010 | ␊ |
| 1011 | ␉opcode = &(curopcodes->opcode[opcode_index]);␊ |
| 1012 | ␊ |
| 1013 | ␉/* The following valid writecnt/readcnt combinations exist:␊ |
| 1014 | ␉ * writecnt = 4, readcnt >= 0␊ |
| 1015 | ␉ * writecnt = 1, readcnt >= 0␊ |
| 1016 | ␉ * writecnt >= 4, readcnt = 0␊ |
| 1017 | ␉ * writecnt >= 1, readcnt = 0␊ |
| 1018 | ␉ * writecnt >= 1 is guaranteed for all commands.␊ |
| 1019 | ␉ */␊ |
| 1020 | ␉if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS) &&␊ |
| 1021 | ␉ (writecnt != 4)) {␊ |
| 1022 | ␉␉msg_perr("%s: Internal command size error for opcode "␊ |
| 1023 | ␉␉␉"0x%02x, got writecnt=%i, want =4\n", __func__, cmd,␊ |
| 1024 | ␉␉␉writecnt);␊ |
| 1025 | ␉␉return SPI_INVALID_LENGTH;␊ |
| 1026 | ␉}␊ |
| 1027 | ␉if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_NO_ADDRESS) &&␊ |
| 1028 | ␉ (writecnt != 1)) {␊ |
| 1029 | ␉␉msg_perr("%s: Internal command size error for opcode "␊ |
| 1030 | ␉␉␉"0x%02x, got writecnt=%i, want =1\n", __func__, cmd,␊ |
| 1031 | ␉␉␉writecnt);␊ |
| 1032 | ␉␉return SPI_INVALID_LENGTH;␊ |
| 1033 | ␉}␊ |
| 1034 | ␉if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) &&␊ |
| 1035 | ␉ (writecnt < 4)) {␊ |
| 1036 | ␉␉msg_perr("%s: Internal command size error for opcode "␊ |
| 1037 | ␉␉␉"0x%02x, got writecnt=%i, want >=4\n", __func__, cmd,␊ |
| 1038 | ␉␉␉writecnt);␊ |
| 1039 | ␉␉return SPI_INVALID_LENGTH;␊ |
| 1040 | ␉}␊ |
| 1041 | ␉if (((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||␊ |
| 1042 | ␉ (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)) &&␊ |
| 1043 | ␉ (readcnt)) {␊ |
| 1044 | ␉␉msg_perr("%s: Internal command size error for opcode "␊ |
| 1045 | ␉␉␉"0x%02x, got readcnt=%i, want =0\n", __func__, cmd,␊ |
| 1046 | ␉␉␉readcnt);␊ |
| 1047 | ␉␉return SPI_INVALID_LENGTH;␊ |
| 1048 | ␉}␊ |
| 1049 | ␊ |
| 1050 | ␉/* if opcode-type requires an address */␊ |
| 1051 | ␉if (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS ||␊ |
| 1052 | ␉ opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {␊ |
| 1053 | ␉␉addr = (writearr[1] << 16) |␊ |
| 1054 | ␉␉ (writearr[2] << 8) | (writearr[3] << 0);␊ |
| 1055 | ␉␉if (addr < ichspi_bbar) {␊ |
| 1056 | ␉␉␉msg_perr("%s: Address 0x%06x below allowed "␊ |
| 1057 | ␉␉␉␉ "range 0x%06x-0xffffff\n", __func__,␊ |
| 1058 | ␉␉␉␉ addr, ichspi_bbar);␊ |
| 1059 | ␉␉␉return SPI_INVALID_ADDRESS;␊ |
| 1060 | ␉␉}␊ |
| 1061 | ␉}␊ |
| 1062 | ␊ |
| 1063 | ␉/* Translate read/write array/count.␊ |
| 1064 | ␉ * The maximum data length is identical for the maximum read length and␊ |
| 1065 | ␉ * for the maximum write length excluding opcode and address. Opcode and␊ |
| 1066 | ␉ * address are stored in separate registers, not in the data registers␊ |
| 1067 | ␉ * and are thus not counted towards data length. The only exception␊ |
| 1068 | ␉ * applies if the opcode definition (un)intentionally classifies said␊ |
| 1069 | ␉ * opcode incorrectly as non-address opcode or vice versa. */␊ |
| 1070 | ␉if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) {␊ |
| 1071 | ␉␉data = (uint8_t *) (writearr + 1);␊ |
| 1072 | ␉␉count = writecnt - 1;␊ |
| 1073 | ␉} else if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {␊ |
| 1074 | ␉␉data = (uint8_t *) (writearr + 4);␊ |
| 1075 | ␉␉count = writecnt - 4;␊ |
| 1076 | ␉} else {␊ |
| 1077 | ␉␉data = (uint8_t *) readarr;␊ |
| 1078 | ␉␉count = readcnt;␊ |
| 1079 | ␉}␊ |
| 1080 | ␊ |
| 1081 | ␉result = run_opcode(flash, *opcode, addr, count, data);␊ |
| 1082 | ␉if (result) {␊ |
| 1083 | ␉␉msg_pdbg("Running OPCODE 0x%02x failed ", opcode->opcode);␊ |
| 1084 | ␉␉if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||␊ |
| 1085 | ␉␉ (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS)) {␊ |
| 1086 | ␉␉␉msg_pdbg("at address 0x%06x ", addr);␊ |
| 1087 | ␉␉}␊ |
| 1088 | ␉␉msg_pdbg("(payload length was %d).\n", count);␊ |
| 1089 | ␊ |
| 1090 | ␉␉/* Print out the data array if it contains data to write.␊ |
| 1091 | ␉␉ * Errors are detected before the received data is read back into␊ |
| 1092 | ␉␉ * the array so it won't make sense to print it then. */␊ |
| 1093 | ␉␉if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||␊ |
| 1094 | ␉␉ (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)) {␊ |
| 1095 | ␉␉␉int i;␊ |
| 1096 | ␉␉␉msg_pspew("The data was:\n");␊ |
| 1097 | ␉␉␉for (i = 0; i < count; i++){␊ |
| 1098 | ␉␉␉␉msg_pspew("%3d: 0x%02x\n", i, data[i]);␊ |
| 1099 | ␉␉␉}␊ |
| 1100 | ␉␉}␊ |
| 1101 | ␉}␊ |
| 1102 | ␊ |
| 1103 | ␉return result;␊ |
| 1104 | }␊ |
| 1105 | ␊ |
| 1106 | static struct hwseq_data {␊ |
| 1107 | ␉uint32_t size_comp0;␊ |
| 1108 | ␉uint32_t size_comp1;␊ |
| 1109 | } hwseq_data;␊ |
| 1110 | ␊ |
| 1111 | /* Sets FLA in FADDR to (addr & 0x01FFFFFF) without touching other bits. */␊ |
| 1112 | static void ich_hwseq_set_addr(uint32_t addr)␊ |
| 1113 | {␊ |
| 1114 | ␉uint32_t addr_old = REGREAD32(ICH9_REG_FADDR) & ~0x01FFFFFF;␊ |
| 1115 | ␉REGWRITE32(ICH9_REG_FADDR, (addr & 0x01FFFFFF) | addr_old);␊ |
| 1116 | }␊ |
| 1117 | ␊ |
| 1118 | /* Sets FADDR.FLA to 'addr' and returns the erase block size in bytes␊ |
| 1119 | * of the block containing this address. May return nonsense if the address is␊ |
| 1120 | * not valid. The erase block size for a specific address depends on the flash␊ |
| 1121 | * partition layout as specified by FPB and the partition properties as defined␊ |
| 1122 | * by UVSCC and LVSCC respectively. An alternative to implement this method␊ |
| 1123 | * would be by querying FPB and the respective VSCC register directly.␊ |
| 1124 | */␊ |
| 1125 | static uint32_t ich_hwseq_get_erase_block_size(unsigned int addr)␊ |
| 1126 | {␊ |
| 1127 | ␉uint8_t enc_berase;␊ |
| 1128 | ␉static const uint32_t const dec_berase[4] = {␊ |
| 1129 | ␉␉256,␊ |
| 1130 | ␉␉4 * 1024,␊ |
| 1131 | ␉␉8 * 1024,␊ |
| 1132 | ␉␉64 * 1024␊ |
| 1133 | ␉};␊ |
| 1134 | ␊ |
| 1135 | ␉ich_hwseq_set_addr(addr);␊ |
| 1136 | ␉enc_berase = (REGREAD16(ICH9_REG_HSFS) & HSFS_BERASE) >>␊ |
| 1137 | ␉␉ HSFS_BERASE_OFF;␊ |
| 1138 | ␉return dec_berase[enc_berase];␊ |
| 1139 | }␊ |
| 1140 | ␊ |
| 1141 | /* Polls for Cycle Done Status, Flash Cycle Error or timeout in 8 us intervals.␊ |
| 1142 | Resets all error flags in HSFS.␊ |
| 1143 | Returns 0 if the cycle completes successfully without errors within␊ |
| 1144 | timeout us, 1 on errors. */␊ |
| 1145 | static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout,␊ |
| 1146 | ␉␉␉␉␉ unsigned int len)␊ |
| 1147 | {␊ |
| 1148 | ␉uint16_t hsfs;␊ |
| 1149 | ␉uint32_t addr;␊ |
| 1150 | ␊ |
| 1151 | ␉timeout /= 8; /* scale timeout duration to counter */␊ |
| 1152 | ␉while ((((hsfs = REGREAD16(ICH9_REG_HSFS)) &␊ |
| 1153 | ␉␉ (HSFS_FDONE | HSFS_FCERR)) == 0) &&␊ |
| 1154 | ␉ --timeout) {␊ |
| 1155 | ␉␉programmer_delay(8);␊ |
| 1156 | ␉}␊ |
| 1157 | ␉REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));␊ |
| 1158 | ␉if (!timeout) {␊ |
| 1159 | ␉␉addr = REGREAD32(ICH9_REG_FADDR) & 0x01FFFFFF;␊ |
| 1160 | ␉␉msg_perr("Timeout error between offset 0x%08x and "␊ |
| 1161 | ␉␉␉ "0x%08x (= 0x%08x + %d)!\n",␊ |
| 1162 | ␉␉␉ addr, addr + len - 1, addr, len - 1);␊ |
| 1163 | ␉␉prettyprint_ich9_reg_hsfs(hsfs);␊ |
| 1164 | ␉␉prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC));␊ |
| 1165 | ␉␉return 1;␊ |
| 1166 | ␉}␊ |
| 1167 | ␊ |
| 1168 | ␉if (hsfs & HSFS_FCERR) {␊ |
| 1169 | ␉␉addr = REGREAD32(ICH9_REG_FADDR) & 0x01FFFFFF;␊ |
| 1170 | ␉␉msg_perr("Transaction error between offset 0x%08x and "␊ |
| 1171 | ␉␉␉ "0x%08x (= 0x%08x + %d)!\n",␊ |
| 1172 | ␉␉␉ addr, addr + len - 1, addr, len - 1);␊ |
| 1173 | ␉␉prettyprint_ich9_reg_hsfs(hsfs);␊ |
| 1174 | ␉␉prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC));␊ |
| 1175 | ␉␉return 1;␊ |
| 1176 | ␉}␊ |
| 1177 | ␉return 0;␊ |
| 1178 | }␊ |
| 1179 | ␊ |
| 1180 | static int ich_hwseq_probe(struct flashctx *flash)␊ |
| 1181 | {␊ |
| 1182 | ␉uint32_t total_size, boundary;␊ |
| 1183 | ␉uint32_t erase_size_low, size_low, erase_size_high, size_high;␊ |
| 1184 | ␉struct block_eraser *eraser;␊ |
| 1185 | ␊ |
| 1186 | ␉total_size = hwseq_data.size_comp0 + hwseq_data.size_comp1;␊ |
| 1187 | ␉msg_cdbg("Found %d attached SPI flash chip",␊ |
| 1188 | ␉␉ (hwseq_data.size_comp1 != 0) ? 2 : 1);␊ |
| 1189 | ␉if (hwseq_data.size_comp1 != 0)␊ |
| 1190 | ␉␉msg_cdbg("s with a combined");␊ |
| 1191 | ␉else␊ |
| 1192 | ␉␉msg_cdbg(" with a");␊ |
| 1193 | ␉msg_cdbg(" density of %d kB.\n", total_size / 1024);␊ |
| 1194 | ␉flash->total_size = total_size / 1024;␊ |
| 1195 | ␊ |
| 1196 | ␉eraser = &(flash->block_erasers[0]);␊ |
| 1197 | ␉boundary = (REGREAD32(ICH9_REG_FPB) & FPB_FPBA) << 12;␊ |
| 1198 | ␉size_high = total_size - boundary;␊ |
| 1199 | ␉erase_size_high = ich_hwseq_get_erase_block_size(boundary);␊ |
| 1200 | ␊ |
| 1201 | ␉if (boundary == 0) {␊ |
| 1202 | ␉␉msg_cdbg("There is only one partition containing the whole "␊ |
| 1203 | ␉␉␉ "address space (0x%06x - 0x%06x).\n", 0, size_high-1);␊ |
| 1204 | ␉␉eraser->eraseblocks[0].size = erase_size_high;␊ |
| 1205 | ␉␉eraser->eraseblocks[0].count = size_high / erase_size_high;␊ |
| 1206 | ␉␉msg_cdbg("There are %d erase blocks with %d B each.\n",␊ |
| 1207 | ␉␉␉ size_high / erase_size_high, erase_size_high);␊ |
| 1208 | ␉} else {␊ |
| 1209 | ␉␉msg_cdbg("The flash address space (0x%06x - 0x%06x) is divided "␊ |
| 1210 | ␉␉␉ "at address 0x%06x in two partitions.\n",␊ |
| 1211 | ␉␉␉ 0, size_high-1, boundary);␊ |
| 1212 | ␉␉size_low = total_size - size_high;␊ |
| 1213 | ␉␉erase_size_low = ich_hwseq_get_erase_block_size(0);␊ |
| 1214 | ␊ |
| 1215 | ␉␉eraser->eraseblocks[0].size = erase_size_low;␊ |
| 1216 | ␉␉eraser->eraseblocks[0].count = size_low / erase_size_low;␊ |
| 1217 | ␉␉msg_cdbg("The first partition ranges from 0x%06x to 0x%06x.\n",␊ |
| 1218 | ␉␉␉ 0, size_low-1);␊ |
| 1219 | ␉␉msg_cdbg("In that range are %d erase blocks with %d B each.\n",␊ |
| 1220 | ␉␉␉ size_low / erase_size_low, erase_size_low);␊ |
| 1221 | ␊ |
| 1222 | ␉␉eraser->eraseblocks[1].size = erase_size_high;␊ |
| 1223 | ␉␉eraser->eraseblocks[1].count = size_high / erase_size_high;␊ |
| 1224 | ␉␉msg_cdbg("The second partition ranges from 0x%06x to 0x%06x.\n",␊ |
| 1225 | ␉␉␉ boundary, size_high-1);␊ |
| 1226 | ␉␉msg_cdbg("In that range are %d erase blocks with %d B each.\n",␊ |
| 1227 | ␉␉␉ size_high / erase_size_high, erase_size_high);␊ |
| 1228 | ␉}␊ |
| 1229 | ␉flash->tested = TEST_OK_PREW;␊ |
| 1230 | ␉return 1;␊ |
| 1231 | }␊ |
| 1232 | ␊ |
| 1233 | static int ich_hwseq_block_erase(struct flashctx *flash, unsigned int addr,␊ |
| 1234 | ␉␉␉␉ unsigned int len)␊ |
| 1235 | {␊ |
| 1236 | ␉uint32_t erase_block;␊ |
| 1237 | ␉uint16_t hsfc;␊ |
| 1238 | ␉uint32_t timeout = 5000 * 1000; /* 5 s for max 64 kB */␊ |
| 1239 | ␊ |
| 1240 | ␉erase_block = ich_hwseq_get_erase_block_size(addr);␊ |
| 1241 | ␉if (len != erase_block) {␊ |
| 1242 | ␉␉msg_cerr("Erase block size for address 0x%06x is %d B, "␊ |
| 1243 | ␉␉␉ "but requested erase block size is %d B. "␊ |
| 1244 | ␉␉␉ "Not erasing anything.\n", addr, erase_block, len);␊ |
| 1245 | ␉␉return -1;␊ |
| 1246 | ␉}␊ |
| 1247 | ␊ |
| 1248 | ␉/* Although the hardware supports this (it would erase the whole block␊ |
| 1249 | ␉ * containing the address) we play safe here. */␊ |
| 1250 | ␉if (addr % erase_block != 0) {␊ |
| 1251 | ␉␉msg_cerr("Erase address 0x%06x is not aligned to the erase "␊ |
| 1252 | ␉␉␉ "block boundary (any multiple of %d). "␊ |
| 1253 | ␉␉␉ "Not erasing anything.\n", addr, erase_block);␊ |
| 1254 | ␉␉return -1;␊ |
| 1255 | ␉}␊ |
| 1256 | ␊ |
| 1257 | ␉if (addr + len > flash->total_size * 1024) {␊ |
| 1258 | ␉␉msg_perr("Request to erase some inaccessible memory address(es)"␊ |
| 1259 | ␉␉␉ " (addr=0x%x, len=%d). "␊ |
| 1260 | ␉␉␉ "Not erasing anything.\n", addr, len);␊ |
| 1261 | ␉␉return -1;␊ |
| 1262 | ␉}␊ |
| 1263 | ␊ |
| 1264 | ␉msg_pdbg("Erasing %d bytes starting at 0x%06x.\n", len, addr);␊ |
| 1265 | ␊ |
| 1266 | ␉/* make sure FDONE, FCERR, AEL are cleared by writing 1 to them */␊ |
| 1267 | ␉REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));␊ |
| 1268 | ␊ |
| 1269 | ␉hsfc = REGREAD16(ICH9_REG_HSFC);␊ |
| 1270 | ␉hsfc &= ~HSFC_FCYCLE; /* clear operation */␊ |
| 1271 | ␉hsfc |= (0x3 << HSFC_FCYCLE_OFF); /* set erase operation */␊ |
| 1272 | ␉hsfc |= HSFC_FGO; /* start */␊ |
| 1273 | ␉msg_pdbg("HSFC used for block erasing: ");␊ |
| 1274 | ␉prettyprint_ich9_reg_hsfc(hsfc);␊ |
| 1275 | ␉REGWRITE16(ICH9_REG_HSFC, hsfc);␊ |
| 1276 | ␊ |
| 1277 | ␉if (ich_hwseq_wait_for_cycle_complete(timeout, len))␊ |
| 1278 | ␉␉return -1;␊ |
| 1279 | ␉return 0;␊ |
| 1280 | }␊ |
| 1281 | ␊ |
| 1282 | static int ich_hwseq_read(struct flashctx *flash, uint8_t *buf,␊ |
| 1283 | ␉␉␉ unsigned int addr, unsigned int len)␊ |
| 1284 | {␊ |
| 1285 | ␉uint16_t hsfc;␊ |
| 1286 | ␉uint16_t timeout = 100 * 60;␊ |
| 1287 | ␉uint8_t block_len;␊ |
| 1288 | ␊ |
| 1289 | ␉if (addr < 0 || addr + len > flash->total_size * 1024) {␊ |
| 1290 | ␉␉msg_perr("Request to read from an inaccessible memory address "␊ |
| 1291 | ␉␉␉ "(addr=0x%x, len=%d).\n", addr, len);␊ |
| 1292 | ␉␉return -1;␊ |
| 1293 | ␉}␊ |
| 1294 | ␊ |
| 1295 | ␉msg_pdbg("Reading %d bytes starting at 0x%06x.\n", len, addr);␊ |
| 1296 | ␉/* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */␊ |
| 1297 | ␉REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));␊ |
| 1298 | ␊ |
| 1299 | ␉while (len > 0) {␊ |
| 1300 | ␉␉block_len = min(len, flash->pgm->opaque.max_data_read);␊ |
| 1301 | ␉␉ich_hwseq_set_addr(addr);␊ |
| 1302 | ␉␉hsfc = REGREAD16(ICH9_REG_HSFC);␊ |
| 1303 | ␉␉hsfc &= ~HSFC_FCYCLE; /* set read operation */␊ |
| 1304 | ␉␉hsfc &= ~HSFC_FDBC; /* clear byte count */␊ |
| 1305 | ␉␉/* set byte count */␊ |
| 1306 | ␉␉hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);␊ |
| 1307 | ␉␉hsfc |= HSFC_FGO; /* start */␊ |
| 1308 | ␉␉REGWRITE16(ICH9_REG_HSFC, hsfc);␊ |
| 1309 | ␊ |
| 1310 | ␉␉if (ich_hwseq_wait_for_cycle_complete(timeout, block_len))␊ |
| 1311 | ␉␉␉return 1;␊ |
| 1312 | ␉␉ich_read_data(buf, block_len, ICH9_REG_FDATA0);␊ |
| 1313 | ␉␉addr += block_len;␊ |
| 1314 | ␉␉buf += block_len;␊ |
| 1315 | ␉␉len -= block_len;␊ |
| 1316 | ␉}␊ |
| 1317 | ␉return 0;␊ |
| 1318 | }␊ |
| 1319 | ␊ |
| 1320 | static int ich_hwseq_write(struct flashctx *flash, uint8_t *buf,␊ |
| 1321 | ␉␉␉ unsigned int addr, unsigned int len)␊ |
| 1322 | {␊ |
| 1323 | ␉uint16_t hsfc;␊ |
| 1324 | ␉uint16_t timeout = 100 * 60;␊ |
| 1325 | ␉uint8_t block_len;␊ |
| 1326 | ␊ |
| 1327 | ␉if (addr < 0 || addr + len > flash->total_size * 1024) {␊ |
| 1328 | ␉␉msg_perr("Request to write to an inaccessible memory address "␊ |
| 1329 | ␉␉␉ "(addr=0x%x, len=%d).\n", addr, len);␊ |
| 1330 | ␉␉return -1;␊ |
| 1331 | ␉}␊ |
| 1332 | ␊ |
| 1333 | ␉msg_pdbg("Writing %d bytes starting at 0x%06x.\n", len, addr);␊ |
| 1334 | ␉/* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */␊ |
| 1335 | ␉REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));␊ |
| 1336 | ␊ |
| 1337 | ␉while (len > 0) {␊ |
| 1338 | ␉␉ich_hwseq_set_addr(addr);␊ |
| 1339 | ␉␉block_len = min(len, flash->pgm->opaque.max_data_write);␊ |
| 1340 | ␉␉ich_fill_data(buf, block_len, ICH9_REG_FDATA0);␊ |
| 1341 | ␉␉hsfc = REGREAD16(ICH9_REG_HSFC);␊ |
| 1342 | ␉␉hsfc &= ~HSFC_FCYCLE; /* clear operation */␊ |
| 1343 | ␉␉hsfc |= (0x2 << HSFC_FCYCLE_OFF); /* set write operation */␊ |
| 1344 | ␉␉hsfc &= ~HSFC_FDBC; /* clear byte count */␊ |
| 1345 | ␉␉/* set byte count */␊ |
| 1346 | ␉␉hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);␊ |
| 1347 | ␉␉hsfc |= HSFC_FGO; /* start */␊ |
| 1348 | ␉␉REGWRITE16(ICH9_REG_HSFC, hsfc);␊ |
| 1349 | ␊ |
| 1350 | ␉␉if (ich_hwseq_wait_for_cycle_complete(timeout, block_len))␊ |
| 1351 | ␉␉␉return -1;␊ |
| 1352 | ␉␉addr += block_len;␊ |
| 1353 | ␉␉buf += block_len;␊ |
| 1354 | ␉␉len -= block_len;␊ |
| 1355 | ␉}␊ |
| 1356 | ␉return 0;␊ |
| 1357 | }␊ |
| 1358 | ␊ |
| 1359 | static int ich_spi_send_multicommand(struct flashctx *flash,␊ |
| 1360 | ␉␉␉␉ struct spi_command *cmds)␊ |
| 1361 | {␊ |
| 1362 | ␉int ret = 0;␊ |
| 1363 | ␉int i;␊ |
| 1364 | ␉int oppos, preoppos;␊ |
| 1365 | ␉for (; (cmds->writecnt || cmds->readcnt) && !ret; cmds++) {␊ |
| 1366 | ␉␉if ((cmds + 1)->writecnt || (cmds + 1)->readcnt) {␊ |
| 1367 | ␉␉␉/* Next command is valid. */␊ |
| 1368 | ␉␉␉preoppos = find_preop(curopcodes, cmds->writearr[0]);␊ |
| 1369 | ␉␉␉oppos = find_opcode(curopcodes, (cmds + 1)->writearr[0]);␊ |
| 1370 | ␉␉␉if ((oppos == -1) && (preoppos != -1)) {␊ |
| 1371 | ␉␉␉␉/* Current command is listed as preopcode in␊ |
| 1372 | ␉␉␉␉ * ICH struct OPCODES, but next command is not␊ |
| 1373 | ␉␉␉␉ * listed as opcode in that struct.␊ |
| 1374 | ␉␉␉␉ * Check for command sanity, then␊ |
| 1375 | ␉␉␉␉ * try to reprogram the ICH opcode list.␊ |
| 1376 | ␉␉␉␉ */␊ |
| 1377 | ␉␉␉␉if (find_preop(curopcodes,␊ |
| 1378 | ␉␉␉␉␉ (cmds + 1)->writearr[0]) != -1) {␊ |
| 1379 | ␉␉␉␉␉msg_perr("%s: Two subsequent "␊ |
| 1380 | ␉␉␉␉␉␉"preopcodes 0x%02x and 0x%02x, "␊ |
| 1381 | ␉␉␉␉␉␉"ignoring the first.\n",␊ |
| 1382 | ␉␉␉␉␉␉__func__, cmds->writearr[0],␊ |
| 1383 | ␉␉␉␉␉␉(cmds + 1)->writearr[0]);␊ |
| 1384 | ␉␉␉␉␉continue;␊ |
| 1385 | ␉␉␉␉}␊ |
| 1386 | ␉␉␉␉/* If the chipset is locked down, we'll fail␊ |
| 1387 | ␉␉␉␉ * during execution of the next command anyway.␊ |
| 1388 | ␉␉␉␉ * No need to bother with fixups.␊ |
| 1389 | ␉␉␉␉ */␊ |
| 1390 | ␉␉␉␉if (!ichspi_lock) {␊ |
| 1391 | ␉␉␉␉␉oppos = reprogram_opcode_on_the_fly((cmds + 1)->writearr[0], (cmds + 1)->writecnt, (cmds + 1)->readcnt);␊ |
| 1392 | ␉␉␉␉␉if (oppos == -1)␊ |
| 1393 | ␉␉␉␉␉␉continue;␊ |
| 1394 | ␉␉␉␉␉curopcodes->opcode[oppos].atomic = preoppos + 1;␊ |
| 1395 | ␉␉␉␉␉continue;␊ |
| 1396 | ␉␉␉␉}␊ |
| 1397 | ␉␉␉}␊ |
| 1398 | ␉␉␉if ((oppos != -1) && (preoppos != -1)) {␊ |
| 1399 | ␉␉␉␉/* Current command is listed as preopcode in␊ |
| 1400 | ␉␉␉␉ * ICH struct OPCODES and next command is listed␊ |
| 1401 | ␉␉␉␉ * as opcode in that struct. Match them up.␊ |
| 1402 | ␉␉␉␉ */␊ |
| 1403 | ␉␉␉␉curopcodes->opcode[oppos].atomic = preoppos + 1;␊ |
| 1404 | ␉␉␉␉continue;␊ |
| 1405 | ␉␉␉}␊ |
| 1406 | ␉␉␉/* If none of the above if-statements about oppos or␊ |
| 1407 | ␉␉␉ * preoppos matched, this is a normal opcode.␊ |
| 1408 | ␉␉␉ */␊ |
| 1409 | ␉␉}␊ |
| 1410 | ␉␉ret = ich_spi_send_command(flash, cmds->writecnt, cmds->readcnt,␊ |
| 1411 | ␉␉␉␉␉ cmds->writearr, cmds->readarr);␊ |
| 1412 | ␉␉/* Reset the type of all opcodes to non-atomic. */␊ |
| 1413 | ␉␉for (i = 0; i < 8; i++)␊ |
| 1414 | ␉␉␉curopcodes->opcode[i].atomic = 0;␊ |
| 1415 | ␉}␊ |
| 1416 | ␉return ret;␊ |
| 1417 | }␊ |
| 1418 | ␊ |
| 1419 | #define ICH_BMWAG(x) ((x >> 24) & 0xff)␊ |
| 1420 | #define ICH_BMRAG(x) ((x >> 16) & 0xff)␊ |
| 1421 | #define ICH_BRWA(x) ((x >> 8) & 0xff)␊ |
| 1422 | #define ICH_BRRA(x) ((x >> 0) & 0xff)␊ |
| 1423 | ␊ |
| 1424 | static void do_ich9_spi_frap(uint32_t frap, int i)␊ |
| 1425 | {␊ |
| 1426 | ␉static const char *const access_names[4] = {␊ |
| 1427 | ␉␉"locked", "read-only", "write-only", "read-write"␊ |
| 1428 | ␉};␊ |
| 1429 | ␉static const char *const region_names[5] = {␊ |
| 1430 | ␉␉"Flash Descriptor", "BIOS", "Management Engine",␊ |
| 1431 | ␉␉"Gigabit Ethernet", "Platform Data"␊ |
| 1432 | ␉};␊ |
| 1433 | ␉uint32_t base, limit;␊ |
| 1434 | ␉int rwperms = (((ICH_BRWA(frap) >> i) & 1) << 1) |␊ |
| 1435 | ␉␉ (((ICH_BRRA(frap) >> i) & 1) << 0);␊ |
| 1436 | ␉int offset = ICH9_REG_FREG0 + i * 4;␊ |
| 1437 | ␉uint32_t freg = mmio_readl(ich_spibar + offset);␊ |
| 1438 | ␊ |
| 1439 | ␉msg_pdbg("0x%02X: 0x%08x (FREG%i: %s)\n",␊ |
| 1440 | ␉␉ offset, freg, i, region_names[i]);␊ |
| 1441 | ␊ |
| 1442 | ␉base = ICH_FREG_BASE(freg);␊ |
| 1443 | ␉limit = ICH_FREG_LIMIT(freg);␊ |
| 1444 | ␉if (base > limit) {␊ |
| 1445 | ␉␉/* this FREG is disabled */␊ |
| 1446 | ␉␉msg_pdbg("%s region is unused.\n", region_names[i]);␊ |
| 1447 | ␉␉return;␊ |
| 1448 | ␉}␊ |
| 1449 | ␊ |
| 1450 | ␉msg_pdbg("0x%08x-0x%08x is %s\n", base, (limit | 0x0fff),␊ |
| 1451 | ␉␉ access_names[rwperms]);␊ |
| 1452 | }␊ |
| 1453 | ␊ |
| 1454 | ␉/* In contrast to FRAP and the master section of the descriptor the bits␊ |
| 1455 | ␉ * in the PR registers have an inverted meaning. The bits in FRAP␊ |
| 1456 | ␉ * indicate read and write access _grant_. Here they indicate read␊ |
| 1457 | ␉ * and write _protection_ respectively. If both bits are 0 the address␊ |
| 1458 | ␉ * bits are ignored.␊ |
| 1459 | ␉ */␊ |
| 1460 | #define ICH_PR_PERMS(pr)␉(((~((pr) >> PR_RP_OFF) & 1) << 0) | \␊ |
| 1461 | ␉␉␉␉ ((~((pr) >> PR_WP_OFF) & 1) << 1))␊ |
| 1462 | ␊ |
| 1463 | static void prettyprint_ich9_reg_pr(int i)␊ |
| 1464 | {␊ |
| 1465 | ␉static const char *const access_names[4] = {␊ |
| 1466 | ␉␉"locked", "read-only", "write-only", "read-write"␊ |
| 1467 | ␉};␊ |
| 1468 | ␉uint8_t off = ICH9_REG_PR0 + (i * 4);␊ |
| 1469 | ␉uint32_t pr = mmio_readl(ich_spibar + off);␊ |
| 1470 | ␉int rwperms = ICH_PR_PERMS(pr);␊ |
| 1471 | ␊ |
| 1472 | ␉msg_pdbg2("0x%02X: 0x%08x (PR%u", off, pr, i);␊ |
| 1473 | ␉if (rwperms != 0x3)␊ |
| 1474 | ␉␉msg_pdbg2(")\n0x%08x-0x%08x is %s\n", ICH_FREG_BASE(pr),␊ |
| 1475 | ␉␉␉ ICH_FREG_LIMIT(pr) | 0x0fff, access_names[rwperms]);␊ |
| 1476 | ␉else␊ |
| 1477 | ␉␉msg_pdbg2(", unused)\n");␊ |
| 1478 | }␊ |
| 1479 | ␊ |
| 1480 | /* Set/Clear the read and write protection enable bits of PR register @i␊ |
| 1481 | * according to @read_prot and @write_prot. */␊ |
| 1482 | static void ich9_set_pr(int i, int read_prot, int write_prot)␊ |
| 1483 | {␊ |
| 1484 | ␉void *addr = ich_spibar + ICH9_REG_PR0 + (i * 4);␊ |
| 1485 | ␉uint32_t old = mmio_readl(addr);␊ |
| 1486 | ␉uint32_t new;␊ |
| 1487 | ␊ |
| 1488 | ␉msg_gspew("PR%u is 0x%08x", i, old);␊ |
| 1489 | ␉new = old & ~((1 << PR_RP_OFF) | (1 << PR_WP_OFF));␊ |
| 1490 | ␉if (read_prot)␊ |
| 1491 | ␉␉new |= (1 << PR_RP_OFF);␊ |
| 1492 | ␉if (write_prot)␊ |
| 1493 | ␉␉new |= (1 << PR_WP_OFF);␊ |
| 1494 | ␉if (old == new) {␊ |
| 1495 | ␉␉msg_gspew(" already.\n");␊ |
| 1496 | ␉␉return;␊ |
| 1497 | ␉}␊ |
| 1498 | ␉msg_gspew(", trying to set it to 0x%08x ", new);␊ |
| 1499 | ␉rmmio_writel(new, addr);␊ |
| 1500 | ␉msg_gspew("resulted in 0x%08x.\n", mmio_readl(addr));␊ |
| 1501 | }␊ |
| 1502 | ␊ |
| 1503 | static const struct spi_programmer spi_programmer_ich7 = {␊ |
| 1504 | ␉.type = SPI_CONTROLLER_ICH7,␊ |
| 1505 | ␉.max_data_read = 64,␊ |
| 1506 | ␉.max_data_write = 64,␊ |
| 1507 | ␉.command = ich_spi_send_command,␊ |
| 1508 | ␉.multicommand = ich_spi_send_multicommand,␊ |
| 1509 | ␉.read = default_spi_read,␊ |
| 1510 | ␉.write_256 = default_spi_write_256,␊ |
| 1511 | };␊ |
| 1512 | ␊ |
| 1513 | static const struct spi_programmer spi_programmer_ich9 = {␊ |
| 1514 | ␉.type = SPI_CONTROLLER_ICH9,␊ |
| 1515 | ␉.max_data_read = 64,␊ |
| 1516 | ␉.max_data_write = 64,␊ |
| 1517 | ␉.command = ich_spi_send_command,␊ |
| 1518 | ␉.multicommand = ich_spi_send_multicommand,␊ |
| 1519 | ␉.read = default_spi_read,␊ |
| 1520 | ␉.write_256 = default_spi_write_256,␊ |
| 1521 | };␊ |
| 1522 | ␊ |
| 1523 | static const struct opaque_programmer opaque_programmer_ich_hwseq = {␊ |
| 1524 | ␉.max_data_read = 64,␊ |
| 1525 | ␉.max_data_write = 64,␊ |
| 1526 | ␉.probe = ich_hwseq_probe,␊ |
| 1527 | ␉.read = ich_hwseq_read,␊ |
| 1528 | ␉.write = ich_hwseq_write,␊ |
| 1529 | ␉.erase = ich_hwseq_block_erase,␊ |
| 1530 | };␊ |
| 1531 | ␊ |
| 1532 | int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,␊ |
| 1533 | ␉␉ enum ich_chipset ich_gen)␊ |
| 1534 | {␊ |
| 1535 | ␉int i;␊ |
| 1536 | ␉uint8_t old, new;␊ |
| 1537 | ␉uint16_t spibar_offset, tmp2;␊ |
| 1538 | ␉uint32_t tmp;␊ |
| 1539 | ␉char *arg;␊ |
| 1540 | ␉int desc_valid = 0;␊ |
| 1541 | ␉struct ich_descriptors desc = {{ 0 }};␊ |
| 1542 | ␉enum ich_spi_mode {␊ |
| 1543 | ␉␉ich_auto,␊ |
| 1544 | ␉␉ich_hwseq,␊ |
| 1545 | ␉␉ich_swseq␊ |
| 1546 | ␉} ich_spi_mode = ich_auto;␊ |
| 1547 | ␊ |
| 1548 | ␉ich_generation = ich_gen;␊ |
| 1549 | ␊ |
| 1550 | ␉switch (ich_generation) {␊ |
| 1551 | ␉case CHIPSET_ICH_UNKNOWN:␊ |
| 1552 | ␉␉return ERROR_FATAL;␊ |
| 1553 | ␉case CHIPSET_ICH7:␊ |
| 1554 | ␉case CHIPSET_ICH8:␊ |
| 1555 | ␉␉spibar_offset = 0x3020;␊ |
| 1556 | ␉␉break;␊ |
| 1557 | ␉case CHIPSET_ICH9:␊ |
| 1558 | ␉default:␉␉/* Future version might behave the same */␊ |
| 1559 | ␉␉spibar_offset = 0x3800;␊ |
| 1560 | ␉␉break;␊ |
| 1561 | ␉}␊ |
| 1562 | ␊ |
| 1563 | ␉/* SPIBAR is at RCRB+0x3020 for ICH[78] and RCRB+0x3800 for ICH9. */␊ |
| 1564 | ␉msg_pdbg("SPIBAR = 0x%x + 0x%04x\n", base, spibar_offset);␊ |
| 1565 | ␊ |
| 1566 | ␉/* Assign Virtual Address */␊ |
| 1567 | ␉ich_spibar = rcrb + spibar_offset;␊ |
| 1568 | ␊ |
| 1569 | ␉switch (ich_generation) {␊ |
| 1570 | ␉case CHIPSET_ICH7:␊ |
| 1571 | ␉␉msg_pdbg("0x00: 0x%04x (SPIS)\n",␊ |
| 1572 | ␉␉␉ mmio_readw(ich_spibar + 0));␊ |
| 1573 | ␉␉msg_pdbg("0x02: 0x%04x (SPIC)\n",␊ |
| 1574 | ␉␉␉ mmio_readw(ich_spibar + 2));␊ |
| 1575 | ␉␉msg_pdbg("0x04: 0x%08x (SPIA)\n",␊ |
| 1576 | ␉␉␉ mmio_readl(ich_spibar + 4));␊ |
| 1577 | ␉␉for (i = 0; i < 8; i++) {␊ |
| 1578 | ␉␉␉int offs;␊ |
| 1579 | ␉␉␉offs = 8 + (i * 8);␊ |
| 1580 | ␉␉␉msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs,␊ |
| 1581 | ␉␉␉␉ mmio_readl(ich_spibar + offs), i);␊ |
| 1582 | ␉␉␉msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4,␊ |
| 1583 | ␉␉␉␉ mmio_readl(ich_spibar + offs + 4), i);␊ |
| 1584 | ␉␉}␊ |
| 1585 | ␉␉ichspi_bbar = mmio_readl(ich_spibar + 0x50);␊ |
| 1586 | ␉␉msg_pdbg("0x50: 0x%08x (BBAR)\n",␊ |
| 1587 | ␉␉␉ ichspi_bbar);␊ |
| 1588 | ␉␉msg_pdbg("0x54: 0x%04x (PREOP)\n",␊ |
| 1589 | ␉␉␉ mmio_readw(ich_spibar + 0x54));␊ |
| 1590 | ␉␉msg_pdbg("0x56: 0x%04x (OPTYPE)\n",␊ |
| 1591 | ␉␉␉ mmio_readw(ich_spibar + 0x56));␊ |
| 1592 | ␉␉msg_pdbg("0x58: 0x%08x (OPMENU)\n",␊ |
| 1593 | ␉␉␉ mmio_readl(ich_spibar + 0x58));␊ |
| 1594 | ␉␉msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n",␊ |
| 1595 | ␉␉␉ mmio_readl(ich_spibar + 0x5c));␊ |
| 1596 | ␉␉for (i = 0; i < 3; i++) {␊ |
| 1597 | ␉␉␉int offs;␊ |
| 1598 | ␉␉␉offs = 0x60 + (i * 4);␊ |
| 1599 | ␉␉␉msg_pdbg("0x%02x: 0x%08x (PBR%d)\n", offs,␊ |
| 1600 | ␉␉␉␉ mmio_readl(ich_spibar + offs), i);␊ |
| 1601 | ␉␉}␊ |
| 1602 | ␉␉if (mmio_readw(ich_spibar) & (1 << 15)) {␊ |
| 1603 | ␉␉␉msg_pinfo("WARNING: SPI Configuration Lockdown activated.\n");␊ |
| 1604 | ␉␉␉ichspi_lock = 1;␊ |
| 1605 | ␉␉}␊ |
| 1606 | ␉␉ich_init_opcodes();␊ |
| 1607 | ␉␉ich_set_bbar(0);␊ |
| 1608 | ␉␉register_spi_programmer(&spi_programmer_ich7);␊ |
| 1609 | ␉␉break;␊ |
| 1610 | ␉case CHIPSET_ICH8:␊ |
| 1611 | ␉default:␉␉/* Future version might behave the same */␊ |
| 1612 | ␉␉arg = extract_programmer_param("ich_spi_mode");␊ |
| 1613 | ␉␉if (arg && !strcmp(arg, "hwseq")) {␊ |
| 1614 | ␉␉␉ich_spi_mode = ich_hwseq;␊ |
| 1615 | ␉␉␉msg_pspew("user selected hwseq\n");␊ |
| 1616 | ␉␉} else if (arg && !strcmp(arg, "swseq")) {␊ |
| 1617 | ␉␉␉ich_spi_mode = ich_swseq;␊ |
| 1618 | ␉␉␉msg_pspew("user selected swseq\n");␊ |
| 1619 | ␉␉} else if (arg && !strcmp(arg, "auto")) {␊ |
| 1620 | ␉␉␉msg_pspew("user selected auto\n");␊ |
| 1621 | ␉␉␉ich_spi_mode = ich_auto;␊ |
| 1622 | ␉␉} else if (arg && !strlen(arg)) {␊ |
| 1623 | ␉␉␉msg_perr("Missing argument for ich_spi_mode.\n");␊ |
| 1624 | ␉␉␉free(arg);␊ |
| 1625 | ␉␉␉return ERROR_FATAL;␊ |
| 1626 | ␉␉} else if (arg) {␊ |
| 1627 | ␉␉␉msg_perr("Unknown argument for ich_spi_mode: %s\n",␊ |
| 1628 | ␉␉␉␉ arg);␊ |
| 1629 | ␉␉␉free(arg);␊ |
| 1630 | ␉␉␉return ERROR_FATAL;␊ |
| 1631 | ␉␉}␊ |
| 1632 | ␉␉free(arg);␊ |
| 1633 | ␊ |
| 1634 | ␉␉tmp2 = mmio_readw(ich_spibar + ICH9_REG_HSFS);␊ |
| 1635 | ␉␉msg_pdbg("0x04: 0x%04x (HSFS)\n", tmp2);␊ |
| 1636 | ␉␉prettyprint_ich9_reg_hsfs(tmp2);␊ |
| 1637 | ␉␉if (tmp2 & HSFS_FLOCKDN) {␊ |
| 1638 | ␉␉␉msg_pinfo("WARNING: SPI Configuration Lockdown activated.\n");␊ |
| 1639 | ␉␉␉ichspi_lock = 1;␊ |
| 1640 | ␉␉}␊ |
| 1641 | ␉␉if (tmp2 & HSFS_FDV)␊ |
| 1642 | ␉␉␉desc_valid = 1;␊ |
| 1643 | ␉␉if (!(tmp2 & HSFS_FDOPSS) && desc_valid)␊ |
| 1644 | ␉␉␉msg_pinfo("The Flash Descriptor Security Override "␊ |
| 1645 | ␉␉␉␉ "Strap-Pin is set. Restrictions implied\n"␊ |
| 1646 | ␉␉␉␉ "by the FRAP and FREG registers are NOT in "␊ |
| 1647 | ␉␉␉␉ "effect. Please note that Protected\n"␊ |
| 1648 | ␉␉␉␉ "Range (PR) restrictions still apply.\n");␊ |
| 1649 | ␉␉ich_init_opcodes();␊ |
| 1650 | ␊ |
| 1651 | ␉␉if (desc_valid) {␊ |
| 1652 | ␉␉␉tmp2 = mmio_readw(ich_spibar + ICH9_REG_HSFC);␊ |
| 1653 | ␉␉␉msg_pdbg("0x06: 0x%04x (HSFC)\n", tmp2);␊ |
| 1654 | ␉␉␉prettyprint_ich9_reg_hsfc(tmp2);␊ |
| 1655 | ␉␉}␊ |
| 1656 | ␊ |
| 1657 | ␉␉tmp = mmio_readl(ich_spibar + ICH9_REG_FADDR);␊ |
| 1658 | ␉␉msg_pdbg("0x08: 0x%08x (FADDR)\n", tmp);␊ |
| 1659 | ␊ |
| 1660 | ␉␉if (desc_valid) {␊ |
| 1661 | ␉␉␉tmp = mmio_readl(ich_spibar + ICH9_REG_FRAP);␊ |
| 1662 | ␉␉␉msg_pdbg("0x50: 0x%08x (FRAP)\n", tmp);␊ |
| 1663 | ␉␉␉msg_pdbg("BMWAG 0x%02x, ", ICH_BMWAG(tmp));␊ |
| 1664 | ␉␉␉msg_pdbg("BMRAG 0x%02x, ", ICH_BMRAG(tmp));␊ |
| 1665 | ␉␉␉msg_pdbg("BRWA 0x%02x, ", ICH_BRWA(tmp));␊ |
| 1666 | ␉␉␉msg_pdbg("BRRA 0x%02x\n", ICH_BRRA(tmp));␊ |
| 1667 | ␊ |
| 1668 | ␉␉␉/* Decode and print FREGx and FRAP registers */␊ |
| 1669 | ␉␉␉for (i = 0; i < 5; i++)␊ |
| 1670 | ␉␉␉␉do_ich9_spi_frap(tmp, i);␊ |
| 1671 | ␉␉}␊ |
| 1672 | ␊ |
| 1673 | ␉␉/* try to disable PR locks before printing them */␊ |
| 1674 | ␉␉if (!ichspi_lock)␊ |
| 1675 | ␉␉␉for (i = 0; i < 5; i++)␊ |
| 1676 | ␉␉␉␉ich9_set_pr(i, 0, 0);␊ |
| 1677 | ␉␉for (i = 0; i < 5; i++)␊ |
| 1678 | ␉␉␉prettyprint_ich9_reg_pr(i);␊ |
| 1679 | ␊ |
| 1680 | ␉␉tmp = mmio_readl(ich_spibar + ICH9_REG_SSFS);␊ |
| 1681 | ␉␉msg_pdbg("0x90: 0x%02x (SSFS)\n", tmp & 0xff);␊ |
| 1682 | ␉␉prettyprint_ich9_reg_ssfs(tmp);␊ |
| 1683 | ␉␉if (tmp & SSFS_FCERR) {␊ |
| 1684 | ␉␉␉msg_pdbg("Clearing SSFS.FCERR\n");␊ |
| 1685 | ␉␉␉mmio_writeb(SSFS_FCERR, ich_spibar + ICH9_REG_SSFS);␊ |
| 1686 | ␉␉}␊ |
| 1687 | ␉␉msg_pdbg("0x91: 0x%06x (SSFC)\n", tmp >> 8);␊ |
| 1688 | ␉␉prettyprint_ich9_reg_ssfc(tmp);␊ |
| 1689 | ␊ |
| 1690 | ␉␉msg_pdbg("0x94: 0x%04x (PREOP)\n",␊ |
| 1691 | ␉␉␉ mmio_readw(ich_spibar + ICH9_REG_PREOP));␊ |
| 1692 | ␉␉msg_pdbg("0x96: 0x%04x (OPTYPE)\n",␊ |
| 1693 | ␉␉␉ mmio_readw(ich_spibar + ICH9_REG_OPTYPE));␊ |
| 1694 | ␉␉msg_pdbg("0x98: 0x%08x (OPMENU)\n",␊ |
| 1695 | ␉␉␉ mmio_readl(ich_spibar + ICH9_REG_OPMENU));␊ |
| 1696 | ␉␉msg_pdbg("0x9C: 0x%08x (OPMENU+4)\n",␊ |
| 1697 | ␉␉␉ mmio_readl(ich_spibar + ICH9_REG_OPMENU + 4));␊ |
| 1698 | ␉␉if (ich_generation == CHIPSET_ICH8 && desc_valid) {␊ |
| 1699 | ␉␉␉tmp = mmio_readl(ich_spibar + ICH8_REG_VSCC);␊ |
| 1700 | ␉␉␉msg_pdbg("0xC1: 0x%08x (VSCC)\n", tmp);␊ |
| 1701 | ␉␉␉msg_pdbg("VSCC: ");␊ |
| 1702 | ␉␉␉prettyprint_ich_reg_vscc(tmp, MSG_DEBUG);␊ |
| 1703 | ␉␉} else {␊ |
| 1704 | ␉␉␉ichspi_bbar = mmio_readl(ich_spibar + ICH9_REG_BBAR);␊ |
| 1705 | ␉␉␉msg_pdbg("0xA0: 0x%08x (BBAR)\n",␊ |
| 1706 | ␉␉␉␉ ichspi_bbar);␊ |
| 1707 | ␊ |
| 1708 | ␉␉␉if (desc_valid) {␊ |
| 1709 | ␉␉␉␉tmp = mmio_readl(ich_spibar + ICH9_REG_LVSCC);␊ |
| 1710 | ␉␉␉␉msg_pdbg("0xC4: 0x%08x (LVSCC)\n", tmp);␊ |
| 1711 | ␉␉␉␉msg_pdbg("LVSCC: ");␊ |
| 1712 | ␉␉␉␉prettyprint_ich_reg_vscc(tmp, MSG_DEBUG);␊ |
| 1713 | ␊ |
| 1714 | ␉␉␉␉tmp = mmio_readl(ich_spibar + ICH9_REG_UVSCC);␊ |
| 1715 | ␉␉␉␉msg_pdbg("0xC8: 0x%08x (UVSCC)\n", tmp);␊ |
| 1716 | ␉␉␉␉msg_pdbg("UVSCC: ");␊ |
| 1717 | ␉␉␉␉prettyprint_ich_reg_vscc(tmp, MSG_DEBUG);␊ |
| 1718 | ␊ |
| 1719 | ␉␉␉␉tmp = mmio_readl(ich_spibar + ICH9_REG_FPB);␊ |
| 1720 | ␉␉␉␉msg_pdbg("0xD0: 0x%08x (FPB)\n", tmp);␊ |
| 1721 | ␉␉␉}␊ |
| 1722 | ␉␉␉ich_set_bbar(0);␊ |
| 1723 | ␉␉}␊ |
| 1724 | ␊ |
| 1725 | ␉␉msg_pdbg("\n");␊ |
| 1726 | ␉␉if (desc_valid) {␊ |
| 1727 | ␉␉␉if (read_ich_descriptors_via_fdo(ich_spibar, &desc) ==␊ |
| 1728 | ␉␉␉ ICH_RET_OK)␊ |
| 1729 | ␉␉␉␉prettyprint_ich_descriptors(CHIPSET_ICH_UNKNOWN,␊ |
| 1730 | ␉␉␉␉␉␉␉ &desc);␊ |
| 1731 | ␉␉␉/* If the descriptor is valid and indicates multiple␊ |
| 1732 | ␉␉␉ * flash devices we need to use hwseq to be able to␊ |
| 1733 | ␉␉␉ * access the second flash device.␊ |
| 1734 | ␉␉␉ */␊ |
| 1735 | ␉␉␉if (ich_spi_mode == ich_auto && desc.content.NC != 0) {␊ |
| 1736 | ␉␉␉␉msg_pinfo("Enabling hardware sequencing due to "␊ |
| 1737 | ␉␉␉␉␉ "multiple flash chips detected.\n");␊ |
| 1738 | ␉␉␉␉ich_spi_mode = ich_hwseq;␊ |
| 1739 | ␉␉␉}␊ |
| 1740 | ␉␉}␊ |
| 1741 | ␊ |
| 1742 | ␉␉if (ich_spi_mode == ich_auto && ichspi_lock &&␊ |
| 1743 | ␉␉ ich_missing_opcodes()) {␊ |
| 1744 | ␉␉␉msg_pinfo("Enabling hardware sequencing because "␊ |
| 1745 | ␉␉␉␉ "some important opcode is locked.\n");␊ |
| 1746 | ␉␉␉ich_spi_mode = ich_hwseq;␊ |
| 1747 | ␉␉}␊ |
| 1748 | ␊ |
| 1749 | ␉␉if (ich_spi_mode == ich_hwseq) {␊ |
| 1750 | ␉␉␉if (!desc_valid) {␊ |
| 1751 | ␉␉␉␉msg_perr("Hardware sequencing was requested "␊ |
| 1752 | ␉␉␉␉␉ "but the flash descriptor is not "␊ |
| 1753 | ␉␉␉␉␉ "valid. Aborting.\n");␊ |
| 1754 | ␉␉␉␉return ERROR_FATAL;␊ |
| 1755 | ␉␉␉}␊ |
| 1756 | ␉␉␉hwseq_data.size_comp0 = getFCBA_component_density(&desc, 0);␊ |
| 1757 | ␉␉␉hwseq_data.size_comp1 = getFCBA_component_density(&desc, 1);␊ |
| 1758 | ␉␉␉register_opaque_programmer(&opaque_programmer_ich_hwseq);␊ |
| 1759 | ␉␉} else {␊ |
| 1760 | ␉␉␉register_spi_programmer(&spi_programmer_ich9);␊ |
| 1761 | ␉␉}␊ |
| 1762 | ␉␉break;␊ |
| 1763 | ␉}␊ |
| 1764 | ␊ |
| 1765 | ␉old = pci_read_byte(dev, 0xdc);␊ |
| 1766 | ␉msg_pdbg("SPI Read Configuration: ");␊ |
| 1767 | ␉new = (old >> 2) & 0x3;␊ |
| 1768 | ␉switch (new) {␊ |
| 1769 | ␉case 0:␊ |
| 1770 | ␉case 1:␊ |
| 1771 | ␉case 2:␊ |
| 1772 | ␉␉msg_pdbg("prefetching %sabled, caching %sabled, ",␊ |
| 1773 | ␉␉␉ (new & 0x2) ? "en" : "dis",␊ |
| 1774 | ␉␉␉ (new & 0x1) ? "dis" : "en");␊ |
| 1775 | ␉␉break;␊ |
| 1776 | ␉default:␊ |
| 1777 | ␉␉msg_pdbg("invalid prefetching/caching settings, ");␊ |
| 1778 | ␉␉break;␊ |
| 1779 | ␉}␊ |
| 1780 | ␉return 0;␊ |
| 1781 | }␊ |
| 1782 | ␊ |
| 1783 | static const struct spi_programmer spi_programmer_via = {␊ |
| 1784 | ␉.type = SPI_CONTROLLER_VIA,␊ |
| 1785 | ␉.max_data_read = 16,␊ |
| 1786 | ␉.max_data_write = 16,␊ |
| 1787 | ␉.command = ich_spi_send_command,␊ |
| 1788 | ␉.multicommand = ich_spi_send_multicommand,␊ |
| 1789 | ␉.read = default_spi_read,␊ |
| 1790 | ␉.write_256 = default_spi_write_256,␊ |
| 1791 | };␊ |
| 1792 | ␊ |
| 1793 | int via_init_spi(struct pci_dev *dev)␊ |
| 1794 | {␊ |
| 1795 | ␉uint32_t mmio_base;␊ |
| 1796 | ␉int i;␊ |
| 1797 | ␊ |
| 1798 | ␉mmio_base = (pci_read_long(dev, 0xbc)) << 8;␊ |
| 1799 | ␉msg_pdbg("MMIO base at = 0x%x\n", mmio_base);␊ |
| 1800 | ␉ich_spibar = physmap("VT8237S MMIO registers", mmio_base, 0x70);␊ |
| 1801 | ␊ |
| 1802 | ␉/* Not sure if it speaks all these bus protocols. */␊ |
| 1803 | ␉internal_buses_supported = BUS_LPC | BUS_FWH;␊ |
| 1804 | ␉ich_generation = CHIPSET_ICH7;␊ |
| 1805 | ␉register_spi_programmer(&spi_programmer_via);␊ |
| 1806 | ␊ |
| 1807 | ␉msg_pdbg("0x00: 0x%04x (SPIS)\n", mmio_readw(ich_spibar + 0));␊ |
| 1808 | ␉msg_pdbg("0x02: 0x%04x (SPIC)\n", mmio_readw(ich_spibar + 2));␊ |
| 1809 | ␉msg_pdbg("0x04: 0x%08x (SPIA)\n", mmio_readl(ich_spibar + 4));␊ |
| 1810 | ␉for (i = 0; i < 2; i++) {␊ |
| 1811 | ␉␉int offs;␊ |
| 1812 | ␉␉offs = 8 + (i * 8);␊ |
| 1813 | ␉␉msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs,␊ |
| 1814 | ␉␉␉ mmio_readl(ich_spibar + offs), i);␊ |
| 1815 | ␉␉msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4,␊ |
| 1816 | ␉␉␉ mmio_readl(ich_spibar + offs + 4), i);␊ |
| 1817 | ␉}␊ |
| 1818 | ␉ichspi_bbar = mmio_readl(ich_spibar + 0x50);␊ |
| 1819 | ␉msg_pdbg("0x50: 0x%08x (BBAR)\n", ichspi_bbar);␊ |
| 1820 | ␉msg_pdbg("0x54: 0x%04x (PREOP)\n", mmio_readw(ich_spibar + 0x54));␊ |
| 1821 | ␉msg_pdbg("0x56: 0x%04x (OPTYPE)\n", mmio_readw(ich_spibar + 0x56));␊ |
| 1822 | ␉msg_pdbg("0x58: 0x%08x (OPMENU)\n", mmio_readl(ich_spibar + 0x58));␊ |
| 1823 | ␉msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n", mmio_readl(ich_spibar + 0x5c));␊ |
| 1824 | ␉for (i = 0; i < 3; i++) {␊ |
| 1825 | ␉␉int offs;␊ |
| 1826 | ␉␉offs = 0x60 + (i * 4);␊ |
| 1827 | ␉␉msg_pdbg("0x%02x: 0x%08x (PBR%d)\n", offs,␊ |
| 1828 | ␉␉␉ mmio_readl(ich_spibar + offs), i);␊ |
| 1829 | ␉}␊ |
| 1830 | ␉msg_pdbg("0x6c: 0x%04x (CLOCK/DEBUG)\n",␊ |
| 1831 | ␉␉ mmio_readw(ich_spibar + 0x6c));␊ |
| 1832 | ␉if (mmio_readw(ich_spibar) & (1 << 15)) {␊ |
| 1833 | ␉␉msg_pinfo("WARNING: SPI Configuration Lockdown activated.\n");␊ |
| 1834 | ␉␉ichspi_lock = 1;␊ |
| 1835 | ␉}␊ |
| 1836 | ␊ |
| 1837 | ␉ich_set_bbar(0);␊ |
| 1838 | ␉ich_init_opcodes();␊ |
| 1839 | ␊ |
| 1840 | ␉return 0;␊ |
| 1841 | }␊ |
| 1842 | ␊ |
| 1843 | #endif␊ |
| 1844 | |