blob: 684d527606377e1eba9c4476f0a159fbcf01d713 [file] [log] [blame]
hailfinger82e7ddb2008-05-16 12:55:55 +00001/*
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>
stepandbd3af12008-06-27 16:28:34 +00007 * Copyright (C) 2008 coresystems GmbH <info@coresystems.de>
hailfinger39d159a2010-05-21 23:09:42 +00008 * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
David Hendricksce6b2fa2011-07-11 22:12:43 -07009 * Copyright (C) 2011 Stefan Tauner
hailfinger82e7ddb2008-05-16 12:55:55 +000010 *
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.
hailfinger82e7ddb2008-05-16 12:55:55 +000020 */
21
stefanctfa66c622011-08-09 01:49:34 +000022#if defined(__i386__) || defined(__x86_64__)
hailfinger324a9cc2010-05-26 01:45:41 +000023
hailfinger82e7ddb2008-05-16 12:55:55 +000024#include <string.h>
stefanct3d3b6ee2011-10-20 12:57:14 +000025#include <stdlib.h>
hailfinger82e7ddb2008-05-16 12:55:55 +000026#include "flash.h"
hailfinger428f6852010-07-27 22:41:39 +000027#include "programmer.h"
Mayur Panchalf4796862019-08-05 15:46:12 +100028#include "hwaccess.h"
hailfinger82e7ddb2008-05-16 12:55:55 +000029#include "spi.h"
David Hendricksce6b2fa2011-07-11 22:12:43 -070030#include "ich_descriptors.h"
Edward O'Callaghand13334a2020-07-23 12:51:00 +100031#include "action_descriptor.h"
hailfinger82e7ddb2008-05-16 12:55:55 +000032
Edward O'Callaghan4eac7482020-05-26 21:54:52 +100033/* Apollo Lake */
34#define APL_REG_FREG12 0xe0 /* 32 Bytes Flash Region 12 */
35
Edward O'Callaghanbff65042020-05-18 17:53:07 +100036/* Sunrise Point */
37
38/* Added HSFS Status bits */
39#define HSFS_WRSDIS_OFF 11 /* 11: Flash Configuration Lock-Down */
40#define HSFS_WRSDIS (0x1 << HSFS_WRSDIS_OFF)
41#define HSFS_PRR34_LOCKDN_OFF 12 /* 12: PRR3 PRR4 Lock-Down */
42#define HSFS_PRR34_LOCKDN (0x1 << HSFS_PRR34_LOCKDN_OFF)
43/* HSFS_BERASE vanished */
44
45/*
46 * HSFC and HSFS 16-bit registers are combined into the 32-bit
47 * BIOS_HSFSTS_CTL register in the Sunrise Point datasheet,
48 * however we still treat them separately in order to reuse code.
49 */
50
51/* Changed HSFC Control bits */
52#define PCH100_HSFC_FCYCLE_OFF (17 - 16) /* 1-4: FLASH Cycle */
53#define PCH100_HSFC_FCYCLE (0xf << PCH100_HSFC_FCYCLE_OFF)
54/* New HSFC Control bit */
55#define HSFC_WET_OFF (21 - 16) /* 5: Write Enable Type */
56#define HSFC_WET (0x1 << HSFC_WET_OFF)
57
Edward O'Callaghanc093d682020-05-26 17:53:53 +100058#define PCH100_FADDR_FLA 0x07ffffff
59
Edward O'Callaghan78590d62020-07-04 15:41:20 +100060#define PCH100_REG_DLOCK 0x0c /* 32 Bits Discrete Lock Bits */
61#define DLOCK_BMWAG_LOCKDN_OFF 0
62#define DLOCK_BMWAG_LOCKDN (0x1 << DLOCK_BMWAG_LOCKDN_OFF)
63#define DLOCK_BMRAG_LOCKDN_OFF 1
64#define DLOCK_BMRAG_LOCKDN (0x1 << DLOCK_BMRAG_LOCKDN_OFF)
65#define DLOCK_SBMWAG_LOCKDN_OFF 2
66#define DLOCK_SBMWAG_LOCKDN (0x1 << DLOCK_SBMWAG_LOCKDN_OFF)
67#define DLOCK_SBMRAG_LOCKDN_OFF 3
68#define DLOCK_SBMRAG_LOCKDN (0x1 << DLOCK_SBMRAG_LOCKDN_OFF)
69#define DLOCK_PR0_LOCKDN_OFF 8
70#define DLOCK_PR0_LOCKDN (0x1 << DLOCK_PR0_LOCKDN_OFF)
71#define DLOCK_PR1_LOCKDN_OFF 9
72#define DLOCK_PR1_LOCKDN (0x1 << DLOCK_PR1_LOCKDN_OFF)
73#define DLOCK_PR2_LOCKDN_OFF 10
74#define DLOCK_PR2_LOCKDN (0x1 << DLOCK_PR2_LOCKDN_OFF)
75#define DLOCK_PR3_LOCKDN_OFF 11
76#define DLOCK_PR3_LOCKDN (0x1 << DLOCK_PR3_LOCKDN_OFF)
77#define DLOCK_PR4_LOCKDN_OFF 12
78#define DLOCK_PR4_LOCKDN (0x1 << DLOCK_PR4_LOCKDN_OFF)
79#define DLOCK_SSEQ_LOCKDN_OFF 16
80#define DLOCK_SSEQ_LOCKDN (0x1 << DLOCK_SSEQ_LOCKDN_OFF)
Edward O'Callaghan6be39a82020-05-18 18:02:02 +100081
Edward O'Callaghan0f183122020-08-01 21:17:36 +100082/* Control bits */
83#define HSFSC_FGO_OFF 16 /* 0: Flash Cycle Go */
84#define HSFSC_FGO (0x1 << HSFSC_FGO_OFF)
85#define HSFSC_FCYCLE_OFF 17 /* 17-20: FLASH Cycle */
86#define HSFSC_FCYCLE (0xf << HSFSC_FCYCLE_OFF)
87#define HSFSC_FDBC_OFF 24 /* 24-29 : Flash Data Byte Count */
88#define HSFSC_FDBC (0x3f << HSFSC_FDBC_OFF)
89
Edward O'Callaghan822037f2020-08-01 19:56:11 +100090#define PCH100_REG_FPR0 0x84 /* 32 Bits Protected Range 0 */
91#define PCH100_REG_GPR0 0x98 /* 32 Bits Global Protected Range 0 */
92#define PCH100_REG_HSFSC 0x04
93
Edward O'Callaghan78590d62020-07-04 15:41:20 +100094#define PCH100_REG_SSFSC 0xA0 /* 32 Bits Status (8) + Control (24) */
95#define PCH100_REG_PREOP 0xA4 /* 16 Bits */
96#define PCH100_REG_OPTYPE 0xA6 /* 16 Bits */
97#define PCH100_REG_OPMENU 0xA8 /* 64 Bits */
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +100098
stepandbd3af12008-06-27 16:28:34 +000099/* ICH9 controller register definition */
stefanctc274c862011-06-11 09:53:22 +0000100#define ICH9_REG_HSFS 0x04 /* 16 Bits Hardware Sequencing Flash Status */
101#define HSFS_FDONE_OFF 0 /* 0: Flash Cycle Done */
102#define HSFS_FDONE (0x1 << HSFS_FDONE_OFF)
103#define HSFS_FCERR_OFF 1 /* 1: Flash Cycle Error */
104#define HSFS_FCERR (0x1 << HSFS_FCERR_OFF)
105#define HSFS_AEL_OFF 2 /* 2: Access Error Log */
106#define HSFS_AEL (0x1 << HSFS_AEL_OFF)
107#define HSFS_BERASE_OFF 3 /* 3-4: Block/Sector Erase Size */
108#define HSFS_BERASE (0x3 << HSFS_BERASE_OFF)
109#define HSFS_SCIP_OFF 5 /* 5: SPI Cycle In Progress */
110#define HSFS_SCIP (0x1 << HSFS_SCIP_OFF)
111 /* 6-12: reserved */
112#define HSFS_FDOPSS_OFF 13 /* 13: Flash Descriptor Override Pin-Strap Status */
113#define HSFS_FDOPSS (0x1 << HSFS_FDOPSS_OFF)
114#define HSFS_FDV_OFF 14 /* 14: Flash Descriptor Valid */
115#define HSFS_FDV (0x1 << HSFS_FDV_OFF)
116#define HSFS_FLOCKDN_OFF 15 /* 15: Flash Configuration Lock-Down */
117#define HSFS_FLOCKDN (0x1 << HSFS_FLOCKDN_OFF)
118
119#define ICH9_REG_HSFC 0x06 /* 16 Bits Hardware Sequencing Flash Control */
120#define HSFC_FGO_OFF 0 /* 0: Flash Cycle Go */
121#define HSFC_FGO (0x1 << HSFC_FGO_OFF)
122#define HSFC_FCYCLE_OFF 1 /* 1-2: FLASH Cycle */
123#define HSFC_FCYCLE (0x3 << HSFC_FCYCLE_OFF)
124 /* 3-7: reserved */
125#define HSFC_FDBC_OFF 8 /* 8-13: Flash Data Byte Count */
126#define HSFC_FDBC (0x3f << HSFC_FDBC_OFF)
127 /* 14: reserved */
128#define HSFC_SME_OFF 15 /* 15: SPI SMI# Enable */
129#define HSFC_SME (0x1 << HSFC_SME_OFF)
130
stefanct707f13b2011-05-19 02:58:17 +0000131#define ICH9_REG_FADDR 0x08 /* 32 Bits */
Edward O'Callaghanc093d682020-05-26 17:53:53 +1000132#define ICH9_FADDR_FLA 0x01ffffff
stefanct707f13b2011-05-19 02:58:17 +0000133#define ICH9_REG_FDATA0 0x10 /* 64 Bytes */
stepandbd3af12008-06-27 16:28:34 +0000134
stefanct24bda702011-06-12 08:14:10 +0000135#define ICH9_REG_FRAP 0x50 /* 32 Bytes Flash Region Access Permissions */
136#define ICH9_REG_FREG0 0x54 /* 32 Bytes Flash Region 0 */
137
138#define ICH9_REG_PR0 0x74 /* 32 Bytes Protected Range 0 */
stefanct7ab834a2011-09-17 21:21:48 +0000139#define PR_WP_OFF 31 /* 31: write protection enable */
140#define PR_RP_OFF 15 /* 15: read protection enable */
stefanct24bda702011-06-12 08:14:10 +0000141
stefanct707f13b2011-05-19 02:58:17 +0000142#define ICH9_REG_SSFS 0x90 /* 08 Bits */
stefanct04009ff2011-06-11 09:53:09 +0000143#define SSFS_SCIP_OFF 0 /* SPI Cycle In Progress */
144#define SSFS_SCIP (0x1 << SSFS_SCIP_OFF)
145#define SSFS_FDONE_OFF 2 /* Cycle Done Status */
146#define SSFS_FDONE (0x1 << SSFS_FDONE_OFF)
147#define SSFS_FCERR_OFF 3 /* Flash Cycle Error */
148#define SSFS_FCERR (0x1 << SSFS_FCERR_OFF)
149#define SSFS_AEL_OFF 4 /* Access Error Log */
150#define SSFS_AEL (0x1 << SSFS_AEL_OFF)
stefanct707f13b2011-05-19 02:58:17 +0000151/* The following bits are reserved in SSFS: 1,5-7. */
hailfinger01d05912011-03-17 00:10:25 +0000152#define SSFS_RESERVED_MASK 0x000000e2
stepandbd3af12008-06-27 16:28:34 +0000153
stefanct707f13b2011-05-19 02:58:17 +0000154#define ICH9_REG_SSFC 0x91 /* 24 Bits */
stefanct707f13b2011-05-19 02:58:17 +0000155/* We combine SSFS and SSFC to one 32-bit word,
stefanct04009ff2011-06-11 09:53:09 +0000156 * therefore SSFC bits are off by 8. */
157 /* 0: reserved */
158#define SSFC_SCGO_OFF (1 + 8) /* 1: SPI Cycle Go */
159#define SSFC_SCGO (0x1 << SSFC_SCGO_OFF)
160#define SSFC_ACS_OFF (2 + 8) /* 2: Atomic Cycle Sequence */
161#define SSFC_ACS (0x1 << SSFC_ACS_OFF)
162#define SSFC_SPOP_OFF (3 + 8) /* 3: Sequence Prefix Opcode Pointer */
163#define SSFC_SPOP (0x1 << SSFC_SPOP_OFF)
164#define SSFC_COP_OFF (4 + 8) /* 4-6: Cycle Opcode Pointer */
165#define SSFC_COP (0x7 << SSFC_COP_OFF)
166 /* 7: reserved */
167#define SSFC_DBC_OFF (8 + 8) /* 8-13: Data Byte Count */
168#define SSFC_DBC (0x3f << SSFC_DBC_OFF)
169#define SSFC_DS_OFF (14 + 8) /* 14: Data Cycle */
170#define SSFC_DS (0x1 << SSFC_DS_OFF)
171#define SSFC_SME_OFF (15 + 8) /* 15: SPI SMI# Enable */
172#define SSFC_SME (0x1 << SSFC_SME_OFF)
173#define SSFC_SCF_OFF (16 + 8) /* 16-18: SPI Cycle Frequency */
174#define SSFC_SCF (0x7 << SSFC_SCF_OFF)
175#define SSFC_SCF_20MHZ 0x00000000
176#define SSFC_SCF_33MHZ 0x01000000
177 /* 19-23: reserved */
hailfinger01d05912011-03-17 00:10:25 +0000178#define SSFC_RESERVED_MASK 0xf8008100
stepandbd3af12008-06-27 16:28:34 +0000179
stefanct707f13b2011-05-19 02:58:17 +0000180#define ICH9_REG_PREOP 0x94 /* 16 Bits */
181#define ICH9_REG_OPTYPE 0x96 /* 16 Bits */
182#define ICH9_REG_OPMENU 0x98 /* 64 Bits */
hailfinger82e7ddb2008-05-16 12:55:55 +0000183
stefanct24bda702011-06-12 08:14:10 +0000184#define ICH9_REG_BBAR 0xA0 /* 32 Bits BIOS Base Address Configuration */
185#define BBAR_MASK 0x00ffff00 /* 8-23: Bottom of System Flash */
186
stefanct1fc3a732011-09-15 23:52:55 +0000187#define ICH8_REG_VSCC 0xC1 /* 32 Bits Vendor Specific Component Capabilities */
David Hendricksce6b2fa2011-07-11 22:12:43 -0700188#define ICH9_REG_LVSCC 0xC4 /* 32 Bits Host Lower Vendor Specific Component Capabilities */
189#define ICH9_REG_UVSCC 0xC8 /* 32 Bits Host Upper Vendor Specific Component Capabilities */
190/* The individual fields of the VSCC registers are defined in the file
stefanct1fc3a732011-09-15 23:52:55 +0000191 * ich_descriptors.h. The reason is that the same layout is also used in the
192 * flash descriptor to define the properties of the different flash chips
193 * supported. The BIOS (or the ME?) is responsible to populate the ICH registers
194 * with the information from the descriptor on startup depending on the actual
195 * chip(s) detected. */
David Hendricksce6b2fa2011-07-11 22:12:43 -0700196
stefanctd68db982011-07-01 00:39:16 +0000197#define ICH9_REG_FPB 0xD0 /* 32 Bits Flash Partition Boundary */
198#define FPB_FPBA_OFF 0 /* 0-12: Block/Sector Erase Size */
199#define FPB_FPBA (0x1FFF << FPB_FPBA_OFF)
200
David Hendricks210975e2015-08-25 21:36:13 +0000201// ICH9R SPI commands
202#define SPI_OPCODE_TYPE_READ_NO_ADDRESS 0
203#define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS 1
204#define SPI_OPCODE_TYPE_READ_WITH_ADDRESS 2
205#define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS 3
206
stepandbd3af12008-06-27 16:28:34 +0000207// ICH7 registers
stefanct707f13b2011-05-19 02:58:17 +0000208#define ICH7_REG_SPIS 0x00 /* 16 Bits */
hailfinger01d05912011-03-17 00:10:25 +0000209#define SPIS_SCIP 0x0001
210#define SPIS_GRANT 0x0002
211#define SPIS_CDS 0x0004
212#define SPIS_FCERR 0x0008
213#define SPIS_RESERVED_MASK 0x7ff0
stepandbd3af12008-06-27 16:28:34 +0000214
ruik9bc51c02008-06-30 21:38:30 +0000215/* VIA SPI is compatible with ICH7, but maxdata
216 to transfer is 16 bytes.
217
218 DATA byte count on ICH7 is 8:13, on VIA 8:11
219
220 bit 12 is port select CS0 CS1
221 bit 13 is FAST READ enable
222 bit 7 is used with fast read and one shot controls CS de-assert?
223*/
224
stefanct707f13b2011-05-19 02:58:17 +0000225#define ICH7_REG_SPIC 0x02 /* 16 Bits */
226#define SPIC_SCGO 0x0002
227#define SPIC_ACS 0x0004
228#define SPIC_SPOP 0x0008
229#define SPIC_DS 0x4000
stepandbd3af12008-06-27 16:28:34 +0000230
stefanct707f13b2011-05-19 02:58:17 +0000231#define ICH7_REG_SPIA 0x04 /* 32 Bits */
232#define ICH7_REG_SPID0 0x08 /* 64 Bytes */
233#define ICH7_REG_PREOP 0x54 /* 16 Bits */
234#define ICH7_REG_OPTYPE 0x56 /* 16 Bits */
235#define ICH7_REG_OPMENU 0x58 /* 64 Bits */
stepandbd3af12008-06-27 16:28:34 +0000236
Edward O'Callaghan4eac7482020-05-26 21:54:52 +1000237enum ich_access_protection {
238 NO_PROT = 0,
239 READ_PROT = 1,
240 WRITE_PROT = 2,
241 LOCKED = 3,
242};
243
stepane1a13b92008-12-08 18:16:58 +0000244/* ICH SPI configuration lock-down. May be set during chipset enabling. */
mkarcher74d30132010-07-22 18:04:15 +0000245static int ichspi_lock = 0;
stepane1a13b92008-12-08 18:16:58 +0000246
hailfingerb767c122010-05-28 15:53:08 +0000247uint32_t ichspi_bbar = 0;
248
mkarcher74d30132010-07-22 18:04:15 +0000249static void *ich_spibar = NULL;
hailfinger1ff33dc2010-07-03 11:02:10 +0000250
David Hendricks210975e2015-08-25 21:36:13 +0000251typedef struct _OPCODE {
252 uint8_t opcode; //This commands spi opcode
253 uint8_t spi_type; //This commands spi type
254 uint8_t atomic; //Use preop: (0: none, 1: preop0, 2: preop1
255} OPCODE;
256
hailfinger82e32492010-02-11 11:28:37 +0000257/* Suggested opcode definition:
hailfinger82e7ddb2008-05-16 12:55:55 +0000258 * Preop 1: Write Enable
259 * Preop 2: Write Status register enable
260 *
261 * OP 0: Write address
262 * OP 1: Read Address
263 * OP 2: ERASE block
264 * OP 3: Read Status register
265 * OP 4: Read ID
266 * OP 5: Write Status register
hailfinger82e32492010-02-11 11:28:37 +0000267 * OP 6: chip private (read JEDEC id)
hailfinger82e7ddb2008-05-16 12:55:55 +0000268 * OP 7: Chip erase
269 */
270typedef struct _OPCODES {
271 uint8_t preop[2];
272 OPCODE opcode[8];
273} OPCODES;
274
stepan8f46dd62008-06-27 15:18:20 +0000275static OPCODES *curopcodes = NULL;
hailfinger82e7ddb2008-05-16 12:55:55 +0000276
277/* HW access functions */
uweabe92a52009-05-16 22:36:00 +0000278static uint32_t REGREAD32(int X)
hailfinger82e7ddb2008-05-16 12:55:55 +0000279{
hailfinger1ff33dc2010-07-03 11:02:10 +0000280 return mmio_readl(ich_spibar + X);
stepandbd3af12008-06-27 16:28:34 +0000281}
282
uweabe92a52009-05-16 22:36:00 +0000283static uint16_t REGREAD16(int X)
stepandbd3af12008-06-27 16:28:34 +0000284{
hailfinger1ff33dc2010-07-03 11:02:10 +0000285 return mmio_readw(ich_spibar + X);
hailfinger82e7ddb2008-05-16 12:55:55 +0000286}
287
hailfinger01d05912011-03-17 00:10:25 +0000288static uint16_t REGREAD8(int X)
289{
290 return mmio_readb(ich_spibar + X);
291}
292
stefanct15f3b932011-07-01 00:39:01 +0000293#define REGWRITE32(off, val) mmio_writel(val, ich_spibar+(off))
294#define REGWRITE16(off, val) mmio_writew(val, ich_spibar+(off))
295#define REGWRITE8(off, val) mmio_writeb(val, ich_spibar+(off))
hailfinger82e7ddb2008-05-16 12:55:55 +0000296
hailfinger82e7ddb2008-05-16 12:55:55 +0000297/* Common SPI functions */
uweabe92a52009-05-16 22:36:00 +0000298static int find_opcode(OPCODES *op, uint8_t opcode);
299static int find_preop(OPCODES *op, uint8_t preop);
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +1000300static int generate_opcodes(OPCODES * op, enum ich_chipset ich_gen);
301static int program_opcodes(OPCODES *op, int enable_undo, enum ich_chipset ich_gen);
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700302static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset,
stepan8f46dd62008-06-27 15:18:20 +0000303 uint8_t datalength, uint8_t * data);
hailfinger82e7ddb2008-05-16 12:55:55 +0000304
stuge7a651552008-12-15 02:32:11 +0000305/* for pairing opcodes with their required preop */
306struct preop_opcode_pair {
307 uint8_t preop;
308 uint8_t opcode;
309};
310
hailfinger82e32492010-02-11 11:28:37 +0000311/* List of opcodes which need preopcodes and matching preopcodes. Unused. */
hailfinger1ff33dc2010-07-03 11:02:10 +0000312const struct preop_opcode_pair pops[] = {
stuge7a651552008-12-15 02:32:11 +0000313 {JEDEC_WREN, JEDEC_BYTE_PROGRAM},
314 {JEDEC_WREN, JEDEC_SE}, /* sector erase */
315 {JEDEC_WREN, JEDEC_BE_52}, /* block erase */
316 {JEDEC_WREN, JEDEC_BE_D8}, /* block erase */
317 {JEDEC_WREN, JEDEC_CE_60}, /* chip erase */
318 {JEDEC_WREN, JEDEC_CE_C7}, /* chip erase */
hailfinger82e32492010-02-11 11:28:37 +0000319 /* FIXME: WRSR requires either EWSR or WREN depending on chip type. */
320 {JEDEC_WREN, JEDEC_WRSR},
stuge7a651552008-12-15 02:32:11 +0000321 {JEDEC_EWSR, JEDEC_WRSR},
322 {0,}
323};
324
hailfinger82e32492010-02-11 11:28:37 +0000325/* Reasonable default configuration. Needs ad-hoc modifications if we
326 * encounter unlisted opcodes. Fun.
327 */
hailfinger1ff33dc2010-07-03 11:02:10 +0000328static OPCODES O_ST_M25P = {
hailfinger82e7ddb2008-05-16 12:55:55 +0000329 {
330 JEDEC_WREN,
hailfinger82e32492010-02-11 11:28:37 +0000331 JEDEC_EWSR,
332 },
hailfinger82e7ddb2008-05-16 12:55:55 +0000333 {
hailfinger82e32492010-02-11 11:28:37 +0000334 {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Write Byte
stepan8f46dd62008-06-27 15:18:20 +0000335 {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data
David Hendricks813dd7a2010-08-26 21:27:17 -0700336 {JEDEC_SE, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Erase Sector
stepan8f46dd62008-06-27 15:18:20 +0000337 {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read Device Status Reg
hailfingere092f842009-05-26 21:25:08 +0000338 {JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Electronic Manufacturer Signature
hailfinger82e32492010-02-11 11:28:37 +0000339 {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Write Status Register
stepan8f46dd62008-06-27 15:18:20 +0000340 {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read JDEC ID
hailfinger82e32492010-02-11 11:28:37 +0000341 {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Bulk erase
342 }
hailfinger82e7ddb2008-05-16 12:55:55 +0000343};
344
hailfinger4c973122010-10-05 22:06:05 +0000345/* List of opcodes with their corresponding spi_type
346 * It is used to reprogram the chipset OPCODE table on-the-fly if an opcode
347 * is needed which is currently not in the chipset OPCODE table
348 */
349static OPCODE POSSIBLE_OPCODES[] = {
350 {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Write Byte
351 {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data
352 {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Erase Sector
353 {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read Device Status Reg
354 {JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Electronic Manufacturer Signature
355 {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Write Status Register
356 {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read JDEC ID
357 {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Bulk erase
358 {JEDEC_SE, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Sector erase
359 {JEDEC_BE_52, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Block erase
360 {JEDEC_AAI_WORD_PROGRAM, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Auto Address Increment
361};
362
hailfinger1ff33dc2010-07-03 11:02:10 +0000363static OPCODES O_EXISTING = {};
stepane1a13b92008-12-08 18:16:58 +0000364
stefancte4d1ef52011-06-11 09:53:16 +0000365/* pretty printing functions */
David Hendricksce6b2fa2011-07-11 22:12:43 -0700366static void prettyprint_opcodes(OPCODES *ops)
stefancte4d1ef52011-06-11 09:53:16 +0000367{
stefanct0aaebc42011-09-17 19:53:11 +0000368 OPCODE oc;
369 const char *t;
370 const char *a;
371 uint8_t i;
372 static const char *const spi_type[4] = {
373 "read w/o addr",
374 "write w/o addr",
375 "read w/ addr",
376 "write w/ addr"
377 };
378 static const char *const atomic_type[3] = {
379 "none",
380 " 0 ",
381 " 1 "
382 };
383
384 if (ops == NULL)
stefancte4d1ef52011-06-11 09:53:16 +0000385 return;
386
stefanct0aaebc42011-09-17 19:53:11 +0000387 msg_pdbg2(" OP Type Pre-OP\n");
stefancte4d1ef52011-06-11 09:53:16 +0000388 for (i = 0; i < 8; i++) {
389 oc = ops->opcode[i];
stefanct0aaebc42011-09-17 19:53:11 +0000390 t = (oc.spi_type > 3) ? "invalid" : spi_type[oc.spi_type];
391 a = (oc.atomic > 2) ? "invalid" : atomic_type[oc.atomic];
392 msg_pdbg2("op[%d]: 0x%02x, %s, %s\n", i, oc.opcode, t, a);
stefancte4d1ef52011-06-11 09:53:16 +0000393 }
stefanct0aaebc42011-09-17 19:53:11 +0000394 msg_pdbg2("Pre-OP 0: 0x%02x, Pre-OP 1: 0x%02x\n", ops->preop[0],
395 ops->preop[1]);
stefancte4d1ef52011-06-11 09:53:16 +0000396}
397
Edward O'Callaghanbff65042020-05-18 17:53:07 +1000398#define _pprint_reg(bit, mask, off, val, sep) msg_pdbg("%s=%d" sep, #bit, (val & mask) >> off)
399#define pprint_reg(reg, bit, val, sep) _pprint_reg(bit, reg##_##bit, reg##_##bit##_OFF, val, sep)
stefanct1fc3a732011-09-15 23:52:55 +0000400
Edward O'Callaghanacce4622020-07-16 15:39:19 +1000401static void prettyprint_ich9_reg_hsfs(uint16_t reg_val, enum ich_chipset ich_gen)
stefanctc274c862011-06-11 09:53:22 +0000402{
403 msg_pdbg("HSFS: ");
404 pprint_reg(HSFS, FDONE, reg_val, ", ");
405 pprint_reg(HSFS, FCERR, reg_val, ", ");
406 pprint_reg(HSFS, AEL, reg_val, ", ");
Edward O'Callaghanacce4622020-07-16 15:39:19 +1000407 switch (ich_gen) {
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +1000408 case CHIPSET_100_SERIES_SUNRISE_POINT:
409 case CHIPSET_C620_SERIES_LEWISBURG:
410 case CHIPSET_300_SERIES_CANNON_POINT:
411 break;
412 default:
Edward O'Callaghanbff65042020-05-18 17:53:07 +1000413 pprint_reg(HSFS, BERASE, reg_val, ", ");
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +1000414 break;
Edward O'Callaghanbff65042020-05-18 17:53:07 +1000415 }
stefanctc274c862011-06-11 09:53:22 +0000416 pprint_reg(HSFS, SCIP, reg_val, ", ");
Edward O'Callaghanacce4622020-07-16 15:39:19 +1000417 switch (ich_gen) {
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +1000418 case CHIPSET_100_SERIES_SUNRISE_POINT:
419 case CHIPSET_C620_SERIES_LEWISBURG:
420 case CHIPSET_300_SERIES_CANNON_POINT:
Edward O'Callaghanbff65042020-05-18 17:53:07 +1000421 pprint_reg(HSFS, PRR34_LOCKDN, reg_val, ", ");
422 pprint_reg(HSFS, WRSDIS, reg_val, ", ");
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +1000423 break;
424 default:
425 break;
Edward O'Callaghanbff65042020-05-18 17:53:07 +1000426 }
stefanctc274c862011-06-11 09:53:22 +0000427 pprint_reg(HSFS, FDOPSS, reg_val, ", ");
428 pprint_reg(HSFS, FDV, reg_val, ", ");
429 pprint_reg(HSFS, FLOCKDN, reg_val, "\n");
430}
431
Edward O'Callaghanacce4622020-07-16 15:39:19 +1000432static void prettyprint_ich9_reg_hsfc(uint16_t reg_val, enum ich_chipset ich_gen)
stefanctc274c862011-06-11 09:53:22 +0000433{
434 msg_pdbg("HSFC: ");
435 pprint_reg(HSFC, FGO, reg_val, ", ");
Edward O'Callaghanacce4622020-07-16 15:39:19 +1000436 switch (ich_gen) {
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +1000437 case CHIPSET_100_SERIES_SUNRISE_POINT:
438 case CHIPSET_C620_SERIES_LEWISBURG:
439 case CHIPSET_300_SERIES_CANNON_POINT:
Edward O'Callaghanbff65042020-05-18 17:53:07 +1000440 _pprint_reg(HSFC, PCH100_HSFC_FCYCLE, PCH100_HSFC_FCYCLE_OFF, reg_val, ", ");
441 pprint_reg(HSFC, WET, reg_val, ", ");
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +1000442 break;
443 default:
444 pprint_reg(HSFC, FCYCLE, reg_val, ", ");
445 break;
Edward O'Callaghanbff65042020-05-18 17:53:07 +1000446 }
stefanctc274c862011-06-11 09:53:22 +0000447 pprint_reg(HSFC, FDBC, reg_val, ", ");
448 pprint_reg(HSFC, SME, reg_val, "\n");
449}
450
stefancte4d1ef52011-06-11 09:53:16 +0000451static void prettyprint_ich9_reg_ssfs(uint32_t reg_val)
452{
453 msg_pdbg("SSFS: ");
454 pprint_reg(SSFS, SCIP, reg_val, ", ");
455 pprint_reg(SSFS, FDONE, reg_val, ", ");
456 pprint_reg(SSFS, FCERR, reg_val, ", ");
457 pprint_reg(SSFS, AEL, reg_val, "\n");
458}
459
460static void prettyprint_ich9_reg_ssfc(uint32_t reg_val)
461{
462 msg_pdbg("SSFC: ");
463 pprint_reg(SSFC, SCGO, reg_val, ", ");
464 pprint_reg(SSFC, ACS, reg_val, ", ");
465 pprint_reg(SSFC, SPOP, reg_val, ", ");
466 pprint_reg(SSFC, COP, reg_val, ", ");
467 pprint_reg(SSFC, DBC, reg_val, ", ");
468 pprint_reg(SSFC, SME, reg_val, ", ");
469 pprint_reg(SSFC, SCF, reg_val, "\n");
470}
471
Edward O'Callaghan6be39a82020-05-18 18:02:02 +1000472static void prettyprint_pch100_reg_dlock(const uint32_t reg_val)
473{
474 msg_pdbg("DLOCK: ");
475 pprint_reg(DLOCK, BMWAG_LOCKDN, reg_val, ", ");
476 pprint_reg(DLOCK, BMRAG_LOCKDN, reg_val, ", ");
477 pprint_reg(DLOCK, SBMWAG_LOCKDN, reg_val, ", ");
478 pprint_reg(DLOCK, SBMRAG_LOCKDN, reg_val, ",\n ");
479 pprint_reg(DLOCK, PR0_LOCKDN, reg_val, ", ");
480 pprint_reg(DLOCK, PR1_LOCKDN, reg_val, ", ");
481 pprint_reg(DLOCK, PR2_LOCKDN, reg_val, ", ");
482 pprint_reg(DLOCK, PR3_LOCKDN, reg_val, ", ");
483 pprint_reg(DLOCK, PR4_LOCKDN, reg_val, ",\n ");
484 pprint_reg(DLOCK, SSEQ_LOCKDN, reg_val, "\n");
485}
486
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +1000487static struct {
488 size_t reg_ssfsc;
489 size_t reg_preop;
490 size_t reg_optype;
491 size_t reg_opmenu;
492} swseq_data;
493
hailfinger4c973122010-10-05 22:06:05 +0000494static uint8_t lookup_spi_type(uint8_t opcode)
495{
Edward O'Callaghand757b422020-05-26 21:22:12 +1000496 unsigned int a;
hailfinger4c973122010-10-05 22:06:05 +0000497
uwe8d342eb2011-07-28 08:13:25 +0000498 for (a = 0; a < ARRAY_SIZE(POSSIBLE_OPCODES); a++) {
hailfinger4c973122010-10-05 22:06:05 +0000499 if (POSSIBLE_OPCODES[a].opcode == opcode)
500 return POSSIBLE_OPCODES[a].spi_type;
501 }
502
503 return 0xFF;
504}
505
506static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, unsigned int readcnt)
507{
508 uint8_t spi_type;
509
510 spi_type = lookup_spi_type(opcode);
511 if (spi_type > 3) {
512 /* Try to guess spi type from read/write sizes.
513 * The following valid writecnt/readcnt combinations exist:
514 * writecnt = 4, readcnt >= 0
515 * writecnt = 1, readcnt >= 0
516 * writecnt >= 4, readcnt = 0
517 * writecnt >= 1, readcnt = 0
518 * writecnt >= 1 is guaranteed for all commands.
519 */
520 if (readcnt == 0)
521 /* if readcnt=0 and writecount >= 4, we don't know if it is WRITE_NO_ADDRESS
522 * or WRITE_WITH_ADDRESS. But if we use WRITE_NO_ADDRESS and the first 3 data
523 * bytes are actual the address, they go to the bus anyhow
524 */
525 spi_type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
526 else if (writecnt == 1) // and readcnt is > 0
527 spi_type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
528 else if (writecnt == 4) // and readcnt is > 0
529 spi_type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
Edward O'Callaghan81eb09c2020-05-26 22:07:23 +1000530 else // we have an invalid case
531 return SPI_INVALID_LENGTH;
hailfinger4c973122010-10-05 22:06:05 +0000532 }
Edward O'Callaghan81eb09c2020-05-26 22:07:23 +1000533 int oppos = 2; // use original JEDEC_BE_D8 offset
534 curopcodes->opcode[oppos].opcode = opcode;
535 curopcodes->opcode[oppos].spi_type = spi_type;
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +1000536 program_opcodes(curopcodes, 0, g_ich_generation);
Edward O'Callaghan81eb09c2020-05-26 22:07:23 +1000537 oppos = find_opcode(curopcodes, opcode);
538 msg_pdbg2("on-the-fly OPCODE (0x%02X) re-programmed, op-pos=%d\n", opcode, oppos);
539 return oppos;
hailfinger4c973122010-10-05 22:06:05 +0000540}
541
uweabe92a52009-05-16 22:36:00 +0000542static int find_opcode(OPCODES *op, uint8_t opcode)
stepane1a13b92008-12-08 18:16:58 +0000543{
544 int a;
545
stefanct83d99e82011-11-08 10:55:54 +0000546 if (op == NULL) {
547 msg_perr("\n%s: null OPCODES pointer!\n", __func__);
548 return -1;
549 }
550
stepane1a13b92008-12-08 18:16:58 +0000551 for (a = 0; a < 8; a++) {
552 if (op->opcode[a].opcode == opcode)
553 return a;
554 }
555
556 return -1;
557}
558
uweabe92a52009-05-16 22:36:00 +0000559static int find_preop(OPCODES *op, uint8_t preop)
stepane1a13b92008-12-08 18:16:58 +0000560{
561 int a;
562
stefanct83d99e82011-11-08 10:55:54 +0000563 if (op == NULL) {
564 msg_perr("\n%s: null OPCODES pointer!\n", __func__);
565 return -1;
566 }
567
stepane1a13b92008-12-08 18:16:58 +0000568 for (a = 0; a < 2; a++) {
569 if (op->preop[a] == preop)
570 return a;
571 }
572
573 return -1;
574}
575
hailfinger82e32492010-02-11 11:28:37 +0000576/* Create a struct OPCODES based on what we find in the locked down chipset. */
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +1000577static int generate_opcodes(OPCODES * op, enum ich_chipset ich_gen)
stepane1a13b92008-12-08 18:16:58 +0000578{
hailfinger82e32492010-02-11 11:28:37 +0000579 int a;
stepane1a13b92008-12-08 18:16:58 +0000580 uint16_t preop, optype;
581 uint32_t opmenu[2];
stepane1a13b92008-12-08 18:16:58 +0000582
583 if (op == NULL) {
snelsone42c3802010-05-07 20:09:04 +0000584 msg_perr("\n%s: null OPCODES pointer!\n", __func__);
stepane1a13b92008-12-08 18:16:58 +0000585 return -1;
586 }
587
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +1000588 switch (ich_gen) {
stefanctc035c192011-11-06 23:51:09 +0000589 case CHIPSET_ICH7:
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +1000590 case CHIPSET_TUNNEL_CREEK:
591 case CHIPSET_CENTERTON:
stepane1a13b92008-12-08 18:16:58 +0000592 preop = REGREAD16(ICH7_REG_PREOP);
593 optype = REGREAD16(ICH7_REG_OPTYPE);
594 opmenu[0] = REGREAD32(ICH7_REG_OPMENU);
595 opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4);
596 break;
stefanctc035c192011-11-06 23:51:09 +0000597 case CHIPSET_ICH8:
598 default: /* Future version might behave the same */
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +1000599 preop = REGREAD16(swseq_data.reg_preop);
600 optype = REGREAD16(swseq_data.reg_optype);
601 opmenu[0] = REGREAD32(swseq_data.reg_opmenu);
602 opmenu[1] = REGREAD32(swseq_data.reg_opmenu + 4);
stepane1a13b92008-12-08 18:16:58 +0000603 break;
stepane1a13b92008-12-08 18:16:58 +0000604 }
605
606 op->preop[0] = (uint8_t) preop;
607 op->preop[1] = (uint8_t) (preop >> 8);
608
609 for (a = 0; a < 8; a++) {
610 op->opcode[a].spi_type = (uint8_t) (optype & 0x3);
611 optype >>= 2;
612 }
613
614 for (a = 0; a < 4; a++) {
615 op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff);
616 opmenu[0] >>= 8;
617 }
618
619 for (a = 4; a < 8; a++) {
620 op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff);
621 opmenu[1] >>= 8;
622 }
623
hailfinger82e32492010-02-11 11:28:37 +0000624 /* No preopcodes used by default. */
625 for (a = 0; a < 8; a++)
stepane1a13b92008-12-08 18:16:58 +0000626 op->opcode[a].atomic = 0;
627
stepane1a13b92008-12-08 18:16:58 +0000628 return 0;
629}
630
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +1000631static int program_opcodes(OPCODES *op, int enable_undo, enum ich_chipset ich_gen)
hailfinger82e7ddb2008-05-16 12:55:55 +0000632{
633 uint8_t a;
stepan3bdf6182008-06-30 23:45:22 +0000634 uint16_t preop, optype;
635 uint32_t opmenu[2];
hailfinger82e7ddb2008-05-16 12:55:55 +0000636
637 /* Program Prefix Opcodes */
hailfinger82e7ddb2008-05-16 12:55:55 +0000638 /* 0:7 Prefix Opcode 1 */
stepan3bdf6182008-06-30 23:45:22 +0000639 preop = (op->preop[0]);
hailfinger82e7ddb2008-05-16 12:55:55 +0000640 /* 8:16 Prefix Opcode 2 */
stepan3bdf6182008-06-30 23:45:22 +0000641 preop |= ((uint16_t) op->preop[1]) << 8;
uwefa98ca12008-10-18 21:14:13 +0000642
stepandbd3af12008-06-27 16:28:34 +0000643 /* Program Opcode Types 0 - 7 */
stepan3bdf6182008-06-30 23:45:22 +0000644 optype = 0;
hailfinger82e7ddb2008-05-16 12:55:55 +0000645 for (a = 0; a < 8; a++) {
stepan3bdf6182008-06-30 23:45:22 +0000646 optype |= ((uint16_t) op->opcode[a].spi_type) << (a * 2);
hailfinger82e7ddb2008-05-16 12:55:55 +0000647 }
uwefa98ca12008-10-18 21:14:13 +0000648
stepandbd3af12008-06-27 16:28:34 +0000649 /* Program Allowable Opcodes 0 - 3 */
stepan3bdf6182008-06-30 23:45:22 +0000650 opmenu[0] = 0;
hailfinger82e7ddb2008-05-16 12:55:55 +0000651 for (a = 0; a < 4; a++) {
stepan3bdf6182008-06-30 23:45:22 +0000652 opmenu[0] |= ((uint32_t) op->opcode[a].opcode) << (a * 8);
hailfinger82e7ddb2008-05-16 12:55:55 +0000653 }
stepandbd3af12008-06-27 16:28:34 +0000654
Edward O'Callaghan6f2f8322019-09-06 11:55:24 +1000655 /* Program Allowable Opcodes 4 - 7 */
stepan3bdf6182008-06-30 23:45:22 +0000656 opmenu[1] = 0;
hailfinger82e7ddb2008-05-16 12:55:55 +0000657 for (a = 4; a < 8; a++) {
stepan3bdf6182008-06-30 23:45:22 +0000658 opmenu[1] |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8);
hailfinger82e7ddb2008-05-16 12:55:55 +0000659 }
stepandbd3af12008-06-27 16:28:34 +0000660
Edward O'Callaghand757b422020-05-26 21:22:12 +1000661 msg_pdbg2("\n%s: preop=%04x optype=%04x opmenu=%08x%08x\n", __func__, preop, optype, opmenu[0], opmenu[1]);
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +1000662 switch (ich_gen) {
stefanctc035c192011-11-06 23:51:09 +0000663 case CHIPSET_ICH7:
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +1000664 case CHIPSET_TUNNEL_CREEK:
665 case CHIPSET_CENTERTON:
hailfinger1e2e3442011-05-03 21:49:41 +0000666 /* Register undo only for enable_undo=1, i.e. first call. */
667 if (enable_undo) {
668 rmmio_valw(ich_spibar + ICH7_REG_PREOP);
669 rmmio_valw(ich_spibar + ICH7_REG_OPTYPE);
670 rmmio_vall(ich_spibar + ICH7_REG_OPMENU);
671 rmmio_vall(ich_spibar + ICH7_REG_OPMENU + 4);
672 }
673 mmio_writew(preop, ich_spibar + ICH7_REG_PREOP);
674 mmio_writew(optype, ich_spibar + ICH7_REG_OPTYPE);
675 mmio_writel(opmenu[0], ich_spibar + ICH7_REG_OPMENU);
676 mmio_writel(opmenu[1], ich_spibar + ICH7_REG_OPMENU + 4);
stepan3bdf6182008-06-30 23:45:22 +0000677 break;
stefanctc035c192011-11-06 23:51:09 +0000678 case CHIPSET_ICH8:
679 default: /* Future version might behave the same */
hailfinger1e2e3442011-05-03 21:49:41 +0000680 /* Register undo only for enable_undo=1, i.e. first call. */
681 if (enable_undo) {
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +1000682 rmmio_valw(ich_spibar + swseq_data.reg_preop);
683 rmmio_valw(ich_spibar + swseq_data.reg_optype);
684 rmmio_vall(ich_spibar + swseq_data.reg_opmenu);
685 rmmio_vall(ich_spibar + swseq_data.reg_opmenu + 4);
hailfinger1e2e3442011-05-03 21:49:41 +0000686 }
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +1000687 mmio_writew(preop, ich_spibar + swseq_data.reg_preop);
688 mmio_writew(optype, ich_spibar + swseq_data.reg_optype);
689 mmio_writel(opmenu[0], ich_spibar + swseq_data.reg_opmenu);
690 mmio_writel(opmenu[1], ich_spibar + swseq_data.reg_opmenu + 4);
stepan3bdf6182008-06-30 23:45:22 +0000691 break;
stepandbd3af12008-06-27 16:28:34 +0000692 }
hailfinger82e7ddb2008-05-16 12:55:55 +0000693
694 return 0;
695}
696
hailfingerb767c122010-05-28 15:53:08 +0000697/*
stefanct83d99e82011-11-08 10:55:54 +0000698 * Returns -1 if at least one mandatory opcode is inaccessible, 0 otherwise.
699 * FIXME: this should also check for
700 * - at least one probing opcode (RDID (incl. AT25F variants?), REMS, RES?)
701 * - at least one erasing opcode (lots.)
702 * - at least one program opcode (BYTE_PROGRAM, AAI_WORD_PROGRAM, ...?)
703 * - necessary preops? (EWSR, WREN, ...?)
704 */
Edward O'Callaghand757b422020-05-26 21:22:12 +1000705static int ich_missing_opcodes(void)
stefanct83d99e82011-11-08 10:55:54 +0000706{
707 uint8_t ops[] = {
708 JEDEC_READ,
709 JEDEC_RDSR,
710 0
711 };
712 int i = 0;
713 while (ops[i] != 0) {
714 msg_pspew("checking for opcode 0x%02x\n", ops[i]);
715 if (find_opcode(curopcodes, ops[i]) == -1)
716 return -1;
717 i++;
718 }
719 return 0;
720}
721
722/*
hailfingerb767c122010-05-28 15:53:08 +0000723 * Try to set BBAR (BIOS Base Address Register), but read back the value in case
724 * it didn't stick.
725 */
Edward O'Callaghand22862f2020-07-16 15:37:26 +1000726static void ich_set_bbar(uint32_t min_addr, enum ich_chipset ich_gen)
hailfingerb767c122010-05-28 15:53:08 +0000727{
stefanctebf900c2011-07-01 00:39:09 +0000728 int bbar_off;
Edward O'Callaghand22862f2020-07-16 15:37:26 +1000729 switch (ich_gen) {
stefanctc035c192011-11-06 23:51:09 +0000730 case CHIPSET_ICH7:
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +1000731 case CHIPSET_TUNNEL_CREEK:
732 case CHIPSET_CENTERTON:
stefanctebf900c2011-07-01 00:39:09 +0000733 bbar_off = 0x50;
hailfingerb767c122010-05-28 15:53:08 +0000734 break;
stefanctc035c192011-11-06 23:51:09 +0000735 case CHIPSET_ICH8:
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +1000736 case CHIPSET_BAYTRAIL:
737 msg_pdbg("BBAR offset is unknown!\n");
stefanct3a716ba2011-09-17 21:21:42 +0000738 return;
stefanctc035c192011-11-06 23:51:09 +0000739 case CHIPSET_ICH9:
stefanct3a716ba2011-09-17 21:21:42 +0000740 default: /* Future version might behave the same */
stefanctebf900c2011-07-01 00:39:09 +0000741 bbar_off = ICH9_REG_BBAR;
hailfingerb767c122010-05-28 15:53:08 +0000742 break;
hailfingerb767c122010-05-28 15:53:08 +0000743 }
David Hendricks7be91492016-12-27 18:43:45 -0800744
stefanctebf900c2011-07-01 00:39:09 +0000745 ichspi_bbar = mmio_readl(ich_spibar + bbar_off) & ~BBAR_MASK;
746 if (ichspi_bbar) {
747 msg_pdbg("Reserved bits in BBAR not zero: 0x%08x\n",
748 ichspi_bbar);
749 }
750 min_addr &= BBAR_MASK;
751 ichspi_bbar |= min_addr;
752 rmmio_writel(ichspi_bbar, ich_spibar + bbar_off);
753 ichspi_bbar = mmio_readl(ich_spibar + bbar_off) & BBAR_MASK;
754
755 /* We don't have any option except complaining. And if the write
756 * failed, the restore will fail as well, so no problem there.
757 */
758 if (ichspi_bbar != min_addr)
stefanct3a716ba2011-09-17 21:21:42 +0000759 msg_perr("Setting BBAR to 0x%08x failed! New value: 0x%08x.\n",
760 min_addr, ichspi_bbar);
hailfingerb767c122010-05-28 15:53:08 +0000761}
762
stefanctfa66c622011-08-09 01:49:34 +0000763/* Read len bytes from the fdata/spid register into the data array.
764 *
Edward O'Callaghand757b422020-05-26 21:22:12 +1000765 * Note that using len > flash->mst->spi.max_data_read will return garbage or
stefanctfa66c622011-08-09 01:49:34 +0000766 * may even crash.
767 */
Edward O'Callaghand757b422020-05-26 21:22:12 +1000768static void ich_read_data(uint8_t *data, int len, int reg0_off)
769{
stefanctfa66c622011-08-09 01:49:34 +0000770 int i;
David Hendricks1db25572011-07-11 22:07:58 -0700771 uint32_t temp32 = 0;
772
stefanctfa66c622011-08-09 01:49:34 +0000773 for (i = 0; i < len; i++) {
774 if ((i % 4) == 0)
775 temp32 = REGREAD32(reg0_off + i);
David Hendricks1db25572011-07-11 22:07:58 -0700776
stefanctfa66c622011-08-09 01:49:34 +0000777 data[i] = (temp32 >> ((i % 4) * 8)) & 0xff;
David Hendricks1db25572011-07-11 22:07:58 -0700778 }
779}
780
stefanctfa66c622011-08-09 01:49:34 +0000781/* Fill len bytes from the data array into the fdata/spid registers.
782 *
Edward O'Callaghand757b422020-05-26 21:22:12 +1000783 * Note that using len > flash->mst->spi.max_data_write will trash the registers
stefanctfa66c622011-08-09 01:49:34 +0000784 * following the data registers.
785 */
786static void ich_fill_data(const uint8_t *data, int len, int reg0_off)
David Hendricks1db25572011-07-11 22:07:58 -0700787{
788 uint32_t temp32 = 0;
stefanctfa66c622011-08-09 01:49:34 +0000789 int i;
David Hendricks1db25572011-07-11 22:07:58 -0700790
791 if (len <= 0)
stefanctfa66c622011-08-09 01:49:34 +0000792 return;
David Hendricks1db25572011-07-11 22:07:58 -0700793
stefanctfa66c622011-08-09 01:49:34 +0000794 for (i = 0; i < len; i++) {
795 if ((i % 4) == 0)
David Hendricks1db25572011-07-11 22:07:58 -0700796 temp32 = 0;
David Hendricks1db25572011-07-11 22:07:58 -0700797
stefanctfa66c622011-08-09 01:49:34 +0000798 temp32 |= ((uint32_t) data[i]) << ((i % 4) * 8);
David Hendricks1db25572011-07-11 22:07:58 -0700799
stefanctfa66c622011-08-09 01:49:34 +0000800 if ((i % 4) == 3) /* 32 bits are full, write them to regs. */
801 REGWRITE32(reg0_off + (i - (i % 4)), temp32);
David Hendricks1db25572011-07-11 22:07:58 -0700802 }
stefanctfa66c622011-08-09 01:49:34 +0000803 i--;
804 if ((i % 4) != 3) /* Write remaining data to regs. */
805 REGWRITE32(reg0_off + (i - (i % 4)), temp32);
David Hendricks1db25572011-07-11 22:07:58 -0700806}
807
stuge7a651552008-12-15 02:32:11 +0000808/* This function generates OPCODES from or programs OPCODES to ICH according to
809 * the chipset's SPI configuration lock.
stepane1a13b92008-12-08 18:16:58 +0000810 *
stuge7a651552008-12-15 02:32:11 +0000811 * It should be called before ICH sends any spi command.
stepane1a13b92008-12-08 18:16:58 +0000812 */
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +1000813static int ich_init_opcodes(enum ich_chipset ich_gen)
stepane1a13b92008-12-08 18:16:58 +0000814{
815 int rc = 0;
816 OPCODES *curopcodes_done;
817
818 if (curopcodes)
819 return 0;
820
821 if (ichspi_lock) {
hailfingerb767c122010-05-28 15:53:08 +0000822 msg_pdbg("Reading OPCODES... ");
stepane1a13b92008-12-08 18:16:58 +0000823 curopcodes_done = &O_EXISTING;
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +1000824 rc = generate_opcodes(curopcodes_done, ich_gen);
stepane1a13b92008-12-08 18:16:58 +0000825 } else {
snelsone42c3802010-05-07 20:09:04 +0000826 msg_pdbg("Programming OPCODES... ");
stepane1a13b92008-12-08 18:16:58 +0000827 curopcodes_done = &O_ST_M25P;
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +1000828 rc = program_opcodes(curopcodes_done, 1, ich_gen);
stepane1a13b92008-12-08 18:16:58 +0000829 }
830
831 if (rc) {
832 curopcodes = NULL;
snelsone42c3802010-05-07 20:09:04 +0000833 msg_perr("failed\n");
stepane1a13b92008-12-08 18:16:58 +0000834 return 1;
835 } else {
836 curopcodes = curopcodes_done;
snelsone42c3802010-05-07 20:09:04 +0000837 msg_pdbg("done\n");
David Hendricksce6b2fa2011-07-11 22:12:43 -0700838 prettyprint_opcodes(curopcodes);
stepane1a13b92008-12-08 18:16:58 +0000839 return 0;
840 }
841}
842
stepan82c65bd2008-11-02 19:51:50 +0000843static int ich7_run_opcode(OPCODE op, uint32_t offset,
ruik9bc51c02008-06-30 21:38:30 +0000844 uint8_t datalength, uint8_t * data, int maxdata)
hailfinger82e7ddb2008-05-16 12:55:55 +0000845{
846 int write_cmd = 0;
stepandbd3af12008-06-27 16:28:34 +0000847 int timeout;
David Hendricks1db25572011-07-11 22:07:58 -0700848 uint32_t temp32;
stepandbd3af12008-06-27 16:28:34 +0000849 uint16_t temp16;
stepan82c65bd2008-11-02 19:51:50 +0000850 uint64_t opmenu;
851 int opcode_index;
hailfinger82e7ddb2008-05-16 12:55:55 +0000852
853 /* Is it a write command? */
854 if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
855 || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
856 write_cmd = 1;
857 }
858
hailfinger01d05912011-03-17 00:10:25 +0000859 timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
860 while ((REGREAD16(ICH7_REG_SPIS) & SPIS_SCIP) && --timeout) {
861 programmer_delay(10);
862 }
863 if (!timeout) {
864 msg_perr("Error: SCIP never cleared!\n");
865 return 1;
866 }
867
stefancte5e09892011-07-01 00:39:23 +0000868 /* Program offset in flash into SPIA while preserving reserved bits. */
869 temp32 = REGREAD32(ICH7_REG_SPIA) & ~0x00FFFFFF;
870 REGWRITE32(ICH7_REG_SPIA, (offset & 0x00FFFFFF) | temp32);
hailfinger82e7ddb2008-05-16 12:55:55 +0000871
stefancte5e09892011-07-01 00:39:23 +0000872 /* Program data into SPID0 to N */
David Hendricks1db25572011-07-11 22:07:58 -0700873 if (write_cmd && (datalength != 0))
874 ich_fill_data(data, datalength, ICH7_REG_SPID0);
stepandbd3af12008-06-27 16:28:34 +0000875
876 /* Assemble SPIS */
hailfinger01d05912011-03-17 00:10:25 +0000877 temp16 = REGREAD16(ICH7_REG_SPIS);
878 /* keep reserved bits */
879 temp16 &= SPIS_RESERVED_MASK;
stepandbd3af12008-06-27 16:28:34 +0000880 /* clear error status registers */
stefanct04009ff2011-06-11 09:53:09 +0000881 temp16 |= (SPIS_CDS | SPIS_FCERR);
stepandbd3af12008-06-27 16:28:34 +0000882 REGWRITE16(ICH7_REG_SPIS, temp16);
883
884 /* Assemble SPIC */
885 temp16 = 0;
886
887 if (datalength != 0) {
888 temp16 |= SPIC_DS;
ruik9bc51c02008-06-30 21:38:30 +0000889 temp16 |= ((uint32_t) ((datalength - 1) & (maxdata - 1))) << 8;
stepandbd3af12008-06-27 16:28:34 +0000890 }
891
892 /* Select opcode */
stepan82c65bd2008-11-02 19:51:50 +0000893 opmenu = REGREAD32(ICH7_REG_OPMENU);
894 opmenu |= ((uint64_t)REGREAD32(ICH7_REG_OPMENU + 4)) << 32;
895
uwe5e931bc2009-04-15 10:52:49 +0000896 for (opcode_index = 0; opcode_index < 8; opcode_index++) {
897 if ((opmenu & 0xff) == op.opcode) {
stepan82c65bd2008-11-02 19:51:50 +0000898 break;
899 }
900 opmenu >>= 8;
901 }
902 if (opcode_index == 8) {
snelsone42c3802010-05-07 20:09:04 +0000903 msg_pdbg("Opcode %x not found.\n", op.opcode);
stepan82c65bd2008-11-02 19:51:50 +0000904 return 1;
905 }
906 temp16 |= ((uint16_t) (opcode_index & 0x07)) << 4;
stepandbd3af12008-06-27 16:28:34 +0000907
mkarcher15b92fe2011-04-29 22:11:36 +0000908 timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
909 /* Handle Atomic. Atomic commands include three steps:
910 - sending the preop (mainly EWSR or WREN)
911 - sending the main command
912 - waiting for the busy bit (WIP) to be cleared
913 This means the timeout must be sufficient for chip erase
914 of slow high-capacity chips.
stefanct707f13b2011-05-19 02:58:17 +0000915 */
hailfinger82e32492010-02-11 11:28:37 +0000916 switch (op.atomic) {
917 case 2:
918 /* Select second preop. */
919 temp16 |= SPIC_SPOP;
Edward O'Callaghand757b422020-05-26 21:22:12 +1000920 /* Fall through. */
hailfinger82e32492010-02-11 11:28:37 +0000921 case 1:
922 /* Atomic command (preop+op) */
stepandbd3af12008-06-27 16:28:34 +0000923 temp16 |= SPIC_ACS;
mkarcher15b92fe2011-04-29 22:11:36 +0000924 timeout = 100 * 1000 * 60; /* 60 seconds */
hailfinger82e32492010-02-11 11:28:37 +0000925 break;
stepandbd3af12008-06-27 16:28:34 +0000926 }
927
928 /* Start */
929 temp16 |= SPIC_SCGO;
930
931 /* write it */
932 REGWRITE16(ICH7_REG_SPIC, temp16);
933
Louis Yung-Chieh Lod2129f12011-03-16 14:53:12 +0800934 /* Original timeout is 60 minutes, which is too excessive.
935 * Reduce to 30 secs for chip full erase (around 10 secs).
936 * We also exit the loop if the error bit is set.
937 */
938 timeout = 100 * 1000 * 30;
Edward O'Callaghand757b422020-05-26 21:22:12 +1000939 /* Wait for Cycle Done Status or Flash Cycle Error. */
hailfinger01d05912011-03-17 00:10:25 +0000940 while (((REGREAD16(ICH7_REG_SPIS) & (SPIS_CDS | SPIS_FCERR)) == 0) &&
941 --timeout) {
hailfingere5829f62009-06-05 17:48:08 +0000942 programmer_delay(10);
Louis Yung-Chieh Lod2129f12011-03-16 14:53:12 +0800943 if (REGREAD16(ICH7_REG_SPIS) & SPIS_FCERR)
944 break; /* Transaction error */
stepandbd3af12008-06-27 16:28:34 +0000945 }
946 if (!timeout) {
hailfinger01d05912011-03-17 00:10:25 +0000947 msg_perr("timeout, ICH7_REG_SPIS=0x%04x\n",
948 REGREAD16(ICH7_REG_SPIS));
949 return 1;
stepandbd3af12008-06-27 16:28:34 +0000950 }
951
snelsone42c3802010-05-07 20:09:04 +0000952 /* FIXME: make sure we do not needlessly cause transaction errors. */
hailfinger01d05912011-03-17 00:10:25 +0000953 temp16 = REGREAD16(ICH7_REG_SPIS);
954 if (temp16 & SPIS_FCERR) {
mkarcherdb7751e2011-04-29 23:53:09 +0000955 msg_perr("Transaction error!\n");
hailfinger01d05912011-03-17 00:10:25 +0000956 /* keep reserved bits */
957 temp16 &= SPIS_RESERVED_MASK;
958 REGWRITE16(ICH7_REG_SPIS, temp16 | SPIS_FCERR);
stepandbd3af12008-06-27 16:28:34 +0000959 return 1;
960 }
961
stefanctfa66c622011-08-09 01:49:34 +0000962 if ((!write_cmd) && (datalength != 0))
David Hendricks1db25572011-07-11 22:07:58 -0700963 ich_read_data(data, datalength, ICH7_REG_SPID0);
stepandbd3af12008-06-27 16:28:34 +0000964
965 return 0;
966}
967
stepan82c65bd2008-11-02 19:51:50 +0000968static int ich9_run_opcode(OPCODE op, uint32_t offset,
stepandbd3af12008-06-27 16:28:34 +0000969 uint8_t datalength, uint8_t * data)
970{
971 int write_cmd = 0;
stepan3bdf6182008-06-30 23:45:22 +0000972 int timeout;
stepandbd3af12008-06-27 16:28:34 +0000973 uint32_t temp32;
stepan82c65bd2008-11-02 19:51:50 +0000974 uint64_t opmenu;
975 int opcode_index;
stepandbd3af12008-06-27 16:28:34 +0000976
977 /* Is it a write command? */
978 if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
979 || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
980 write_cmd = 1;
981 }
982
hailfinger01d05912011-03-17 00:10:25 +0000983 timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +1000984 while ((REGREAD8(swseq_data.reg_ssfsc) & SSFS_SCIP) && --timeout) {
hailfinger01d05912011-03-17 00:10:25 +0000985 programmer_delay(10);
986 }
987 if (!timeout) {
988 msg_perr("Error: SCIP never cleared!\n");
989 return 1;
990 }
991
stefancte5e09892011-07-01 00:39:23 +0000992 /* Program offset in flash into FADDR while preserve the reserved bits
993 * and clearing the 25. address bit which is only useable in hwseq. */
994 temp32 = REGREAD32(ICH9_REG_FADDR) & ~0x01FFFFFF;
995 REGWRITE32(ICH9_REG_FADDR, (offset & 0x00FFFFFF) | temp32);
stepandbd3af12008-06-27 16:28:34 +0000996
997 /* Program data into FDATA0 to N */
David Hendricks1db25572011-07-11 22:07:58 -0700998 if (write_cmd && (datalength != 0))
999 ich_fill_data(data, datalength, ICH9_REG_FDATA0);
hailfinger82e7ddb2008-05-16 12:55:55 +00001000
1001 /* Assemble SSFS + SSFC */
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10001002 temp32 = REGREAD32(swseq_data.reg_ssfsc);
stefanct707f13b2011-05-19 02:58:17 +00001003 /* Keep reserved bits only */
hailfinger01d05912011-03-17 00:10:25 +00001004 temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK;
stefanct04009ff2011-06-11 09:53:09 +00001005 /* Clear cycle done and cycle error status registers */
1006 temp32 |= (SSFS_FDONE | SSFS_FCERR);
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10001007 REGWRITE32(swseq_data.reg_ssfsc, temp32);
hailfinger01d05912011-03-17 00:10:25 +00001008
uwe3a3ab2f2010-03-25 23:18:41 +00001009 /* Use 20 MHz */
hailfinger82e7ddb2008-05-16 12:55:55 +00001010 temp32 |= SSFC_SCF_20MHZ;
1011
stefanct707f13b2011-05-19 02:58:17 +00001012 /* Set data byte count (DBC) and data cycle bit (DS) */
hailfinger82e7ddb2008-05-16 12:55:55 +00001013 if (datalength != 0) {
1014 uint32_t datatemp;
1015 temp32 |= SSFC_DS;
stefanct04009ff2011-06-11 09:53:09 +00001016 datatemp = ((((uint32_t)datalength - 1) << SSFC_DBC_OFF) &
1017 SSFC_DBC);
hailfinger82e7ddb2008-05-16 12:55:55 +00001018 temp32 |= datatemp;
1019 }
1020
1021 /* Select opcode */
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10001022 opmenu = REGREAD32(swseq_data.reg_opmenu);
1023 opmenu |= ((uint64_t)REGREAD32(swseq_data.reg_opmenu + 4)) << 32;
stepan82c65bd2008-11-02 19:51:50 +00001024
uwe5e931bc2009-04-15 10:52:49 +00001025 for (opcode_index = 0; opcode_index < 8; opcode_index++) {
1026 if ((opmenu & 0xff) == op.opcode) {
stepan82c65bd2008-11-02 19:51:50 +00001027 break;
1028 }
1029 opmenu >>= 8;
1030 }
1031 if (opcode_index == 8) {
snelsone42c3802010-05-07 20:09:04 +00001032 msg_pdbg("Opcode %x not found.\n", op.opcode);
stepan82c65bd2008-11-02 19:51:50 +00001033 return 1;
1034 }
1035 temp32 |= ((uint32_t) (opcode_index & 0x07)) << (8 + 4);
hailfinger82e7ddb2008-05-16 12:55:55 +00001036
mkarcher15b92fe2011-04-29 22:11:36 +00001037 timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
1038 /* Handle Atomic. Atomic commands include three steps:
1039 - sending the preop (mainly EWSR or WREN)
1040 - sending the main command
1041 - waiting for the busy bit (WIP) to be cleared
1042 This means the timeout must be sufficient for chip erase
1043 of slow high-capacity chips.
stefanct707f13b2011-05-19 02:58:17 +00001044 */
hailfinger82e32492010-02-11 11:28:37 +00001045 switch (op.atomic) {
1046 case 2:
1047 /* Select second preop. */
1048 temp32 |= SSFC_SPOP;
Edward O'Callaghand757b422020-05-26 21:22:12 +10001049 /* Fall through. */
hailfinger82e32492010-02-11 11:28:37 +00001050 case 1:
1051 /* Atomic command (preop+op) */
hailfinger82e7ddb2008-05-16 12:55:55 +00001052 temp32 |= SSFC_ACS;
mkarcher15b92fe2011-04-29 22:11:36 +00001053 timeout = 100 * 1000 * 60; /* 60 seconds */
hailfinger82e32492010-02-11 11:28:37 +00001054 break;
hailfinger82e7ddb2008-05-16 12:55:55 +00001055 }
1056
1057 /* Start */
1058 temp32 |= SSFC_SCGO;
1059
1060 /* write it */
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10001061 REGWRITE32(swseq_data.reg_ssfsc, temp32);
hailfinger82e7ddb2008-05-16 12:55:55 +00001062
hailfinger01d05912011-03-17 00:10:25 +00001063 /* Wait for Cycle Done Status or Flash Cycle Error. */
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10001064 while (((REGREAD32(swseq_data.reg_ssfsc) & (SSFS_FDONE | SSFS_FCERR)) == 0) &&
hailfinger01d05912011-03-17 00:10:25 +00001065 --timeout) {
hailfingere5829f62009-06-05 17:48:08 +00001066 programmer_delay(10);
stepan3bdf6182008-06-30 23:45:22 +00001067 }
1068 if (!timeout) {
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10001069 msg_perr("timeout, REG_SSFS=0x%08x\n",
1070 REGREAD32(swseq_data.reg_ssfsc));
hailfinger01d05912011-03-17 00:10:25 +00001071 return 1;
hailfinger82e7ddb2008-05-16 12:55:55 +00001072 }
1073
snelsone42c3802010-05-07 20:09:04 +00001074 /* FIXME make sure we do not needlessly cause transaction errors. */
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10001075 temp32 = REGREAD32(swseq_data.reg_ssfsc);
hailfinger01d05912011-03-17 00:10:25 +00001076 if (temp32 & SSFS_FCERR) {
mkarcherdb7751e2011-04-29 23:53:09 +00001077 msg_perr("Transaction error!\n");
stefancte4d1ef52011-06-11 09:53:16 +00001078 prettyprint_ich9_reg_ssfs(temp32);
1079 prettyprint_ich9_reg_ssfc(temp32);
hailfinger01d05912011-03-17 00:10:25 +00001080 /* keep reserved bits */
1081 temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK;
1082 /* Clear the transaction error. */
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10001083 REGWRITE32(swseq_data.reg_ssfsc, temp32 | SSFS_FCERR);
hailfinger82e7ddb2008-05-16 12:55:55 +00001084 return 1;
1085 }
1086
stefanctfa66c622011-08-09 01:49:34 +00001087 if ((!write_cmd) && (datalength != 0))
David Hendricks1db25572011-07-11 22:07:58 -07001088 ich_read_data(data, datalength, ICH9_REG_FDATA0);
hailfinger82e7ddb2008-05-16 12:55:55 +00001089
1090 return 0;
1091}
1092
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001093static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset,
stepandbd3af12008-06-27 16:28:34 +00001094 uint8_t datalength, uint8_t * data)
1095{
stefanct689eb6c2011-06-11 19:44:31 +00001096 /* max_data_read == max_data_write for all Intel/VIA SPI masters */
Edward O'Callaghanc66827e2020-10-09 12:22:04 +11001097 uint8_t maxlength = flash->mst->spi.max_data_read;
stefanct689eb6c2011-06-11 19:44:31 +00001098
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +10001099 if (g_ich_generation == CHIPSET_ICH_UNKNOWN) {
1100 msg_perr("%s: unsupported chipset\n", __func__);
1101 return -1;
1102 }
1103
stefanct689eb6c2011-06-11 19:44:31 +00001104 if (datalength > maxlength) {
1105 msg_perr("%s: Internal command size error for "
1106 "opcode 0x%02x, got datalength=%i, want <=%i\n",
1107 __func__, op.opcode, datalength, maxlength);
1108 return SPI_INVALID_LENGTH;
1109 }
1110
Edward O'Callaghane3e30562019-09-03 13:10:58 +10001111 switch (g_ich_generation) {
stefanctc035c192011-11-06 23:51:09 +00001112 case CHIPSET_ICH7:
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +10001113 case CHIPSET_TUNNEL_CREEK:
1114 case CHIPSET_CENTERTON:
stefanct689eb6c2011-06-11 19:44:31 +00001115 return ich7_run_opcode(op, offset, datalength, data, maxlength);
stefanctc035c192011-11-06 23:51:09 +00001116 case CHIPSET_ICH8:
1117 default: /* Future version might behave the same */
stefanct689eb6c2011-06-11 19:44:31 +00001118 return ich9_run_opcode(op, offset, datalength, data);
stefanct689eb6c2011-06-11 19:44:31 +00001119 }
stepandbd3af12008-06-27 16:28:34 +00001120}
1121
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001122#define DEFAULT_NUM_FD_REGIONS 5
Furquan Shaikh5c100f22018-11-05 21:35:11 -08001123
1124/*
1125 * APL/GLK have the Device Expansion region as well. Hence, the number of
1126 * regions is 6.
1127 */
1128#define APL_GLK_NUM_FD_REGIONS 6
Bora Guvendikc34416b2019-01-07 16:10:48 -08001129
1130/*
1131 * Sunrisepoint have reserved regions and a region for Embedded Controller.
1132 * Hence, the number of regions is 9.
1133 */
1134#define SUNRISEPOINT_NUM_FD_REGIONS 9
1135
1136#define EMBEDDED_CONTROLLER_REGION 8
1137
David Hendricks1ed1d352011-11-23 17:54:37 -08001138static int num_fd_regions;
1139
David Hendricks1ed1d352011-11-23 17:54:37 -08001140enum fd_access_level {
1141 FD_REGION_LOCKED,
1142 FD_REGION_READ_ONLY,
1143 FD_REGION_WRITE_ONLY,
1144 FD_REGION_READ_WRITE,
1145};
1146
1147struct fd_region_permission {
1148 enum fd_access_level level;
1149 const char *name;
1150} fd_region_permissions[] = {
1151 /* order corresponds to FRAP bitfield */
1152 { FD_REGION_LOCKED, "locked" },
1153 { FD_REGION_READ_ONLY, "read-only" },
1154 { FD_REGION_WRITE_ONLY, "write-only" },
1155 { FD_REGION_READ_WRITE, "read-write" },
1156};
1157
David Hendricks1ed1d352011-11-23 17:54:37 -08001158struct fd_region {
1159 const char *name;
1160 struct fd_region_permission *permission;
1161 uint32_t base;
1162 uint32_t limit;
1163} fd_regions[] = {
1164 /* order corresponds to flash descriptor */
1165 { .name = "Flash Descriptor" },
1166 { .name = "BIOS" },
1167 { .name = "Management Engine" },
1168 { .name = "Gigabit Ethernet" },
1169 { .name = "Platform Data" },
Furquan Shaikh5c100f22018-11-05 21:35:11 -08001170 { .name = "Device Expansion" },
Bora Guvendikc34416b2019-01-07 16:10:48 -08001171 { .name = "Reserved 1" },
1172 { .name = "Reserved 2" },
1173 { .name = "Embedded Controller" },
Edward O'Callaghand7b95f22020-08-07 23:51:23 +10001174 { .name = "unknown" },
1175 { .name = "IE" },
1176 { .name = "10GbE" },
1177 { .name = "unknown" },
1178 { .name = "unknown" },
1179 { .name = "unknown" },
1180 { .name = "unknown" },
David Hendricks1ed1d352011-11-23 17:54:37 -08001181};
1182
Edward O'Callaghan69c3a0d2020-07-23 10:41:41 +10001183static int check_fd_permissions(OPCODE *opcode, int type, uint32_t addr, int count)
Ramya Vijaykumar71d69ad2015-10-01 11:26:40 +05301184{
1185 int i;
Edward O'Callaghan69c3a0d2020-07-23 10:41:41 +10001186 uint8_t op_type = opcode ? opcode->spi_type : type;
Edward O'Callaghand1dff072020-08-01 19:34:48 +10001187 int op_type_r = opcode ? SPI_OPCODE_TYPE_READ_WITH_ADDRESS : SPI_OPCODE_TYPE_READ_NO_ADDRESS;
1188 int op_type_w = opcode ? SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS : SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
David Hendricks1ed1d352011-11-23 17:54:37 -08001189 int ret = 0;
1190
1191 /* check flash descriptor permissions (if present) */
1192 for (i = 0; i < num_fd_regions; i++) {
1193 const char *name = fd_regions[i].name;
1194 enum fd_access_level level;
Edward O'Callaghan90de5fe2020-07-23 11:03:42 +10001195 uint32_t base = fd_regions[i].base;
1196 uint32_t limit = fd_regions[i].limit;
David Hendricks1ed1d352011-11-23 17:54:37 -08001197
Edward O'Callaghan90de5fe2020-07-23 11:03:42 +10001198 if ((addr + count - 1 < base) || (addr > limit))
David Hendricks1ed1d352011-11-23 17:54:37 -08001199 continue;
1200
1201 if (!fd_regions[i].permission) {
Edward O'Callaghan90de5fe2020-07-23 11:03:42 +10001202 msg_perr("No permissions set for flash region %s\n", name);
David Hendricks1ed1d352011-11-23 17:54:37 -08001203 break;
1204 }
David Hendricks1ed1d352011-11-23 17:54:37 -08001205 level = fd_regions[i].permission->level;
1206
Edward O'Callaghan69c3a0d2020-07-23 10:41:41 +10001207 if (op_type == op_type_r) {
David Hendricks1ed1d352011-11-23 17:54:37 -08001208 if (level != FD_REGION_READ_ONLY &&
1209 level != FD_REGION_READ_WRITE) {
1210 msg_pspew("%s: Cannot read address 0x%08x in "
1211 "region %s\n", __func__,addr,name);
1212 ret = SPI_ACCESS_DENIED;
1213 }
Edward O'Callaghan69c3a0d2020-07-23 10:41:41 +10001214 } else if (op_type == op_type_w) {
David Hendricks1ed1d352011-11-23 17:54:37 -08001215 if (level != FD_REGION_WRITE_ONLY &&
1216 level != FD_REGION_READ_WRITE) {
1217 msg_pspew("%s: Cannot write to address 0x%08x in"
1218 "region %s\n", __func__,addr,name);
1219 ret = SPI_ACCESS_DENIED;
1220 }
1221 }
1222 break;
1223 }
1224
Edward O'Callaghan93efced2020-11-04 16:31:26 +11001225 if ((i == num_fd_regions) && !opcode) { // FIXME(b/171892105).
Edward O'Callaghan69c3a0d2020-07-23 10:41:41 +10001226 msg_pspew("%s: Address not covered by any descriptor 0x%06x\n",
1227 __func__, addr);
1228 ret = SPI_ACCESS_DENIED;
1229 }
1230
David Hendricks1ed1d352011-11-23 17:54:37 -08001231 return ret;
1232}
1233
Edward O'Callaghand757b422020-05-26 21:22:12 +10001234static int ich_spi_send_command(const struct flashctx *flash, unsigned int writecnt,
1235 unsigned int readcnt,
1236 const unsigned char *writearr,
1237 unsigned char *readarr)
hailfinger82e7ddb2008-05-16 12:55:55 +00001238{
hailfinger9c290a72009-07-14 10:26:56 +00001239 int result;
hailfinger82e7ddb2008-05-16 12:55:55 +00001240 int opcode_index = -1;
1241 const unsigned char cmd = *writearr;
1242 OPCODE *opcode;
1243 uint32_t addr = 0;
1244 uint8_t *data;
1245 int count;
1246
hailfinger82e7ddb2008-05-16 12:55:55 +00001247 /* find cmd in opcodes-table */
hailfinger82e32492010-02-11 11:28:37 +00001248 opcode_index = find_opcode(curopcodes, cmd);
hailfinger82e7ddb2008-05-16 12:55:55 +00001249 if (opcode_index == -1) {
hailfinger4c973122010-10-05 22:06:05 +00001250 if (!ichspi_lock)
1251 opcode_index = reprogram_opcode_on_the_fly(cmd, writecnt, readcnt);
Edward O'Callaghan81eb09c2020-05-26 22:07:23 +10001252 if (opcode_index == SPI_INVALID_LENGTH) {
1253 msg_pdbg("OPCODE 0x%02x has unsupported length, will not execute.\n", cmd);
1254 return SPI_INVALID_LENGTH;
1255 } else if (opcode_index == -1) {
1256 msg_pdbg("Invalid OPCODE 0x%02x, will not execute.\n",
1257 cmd);
hailfinger4c973122010-10-05 22:06:05 +00001258 return SPI_INVALID_OPCODE;
1259 }
hailfinger82e7ddb2008-05-16 12:55:55 +00001260 }
1261
Edward O'Callaghand13334a2020-07-23 12:51:00 +10001262 if (is_dry_run())
Vadim Bendebury066143d2018-07-16 18:20:33 -07001263 return 0;
1264
hailfinger82e7ddb2008-05-16 12:55:55 +00001265 opcode = &(curopcodes->opcode[opcode_index]);
1266
hailfinger82e32492010-02-11 11:28:37 +00001267 /* The following valid writecnt/readcnt combinations exist:
1268 * writecnt = 4, readcnt >= 0
1269 * writecnt = 1, readcnt >= 0
1270 * writecnt >= 4, readcnt = 0
1271 * writecnt >= 1, readcnt = 0
1272 * writecnt >= 1 is guaranteed for all commands.
1273 */
1274 if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS) &&
1275 (writecnt != 4)) {
snelsone42c3802010-05-07 20:09:04 +00001276 msg_perr("%s: Internal command size error for opcode "
hailfinger82e32492010-02-11 11:28:37 +00001277 "0x%02x, got writecnt=%i, want =4\n", __func__, cmd,
1278 writecnt);
1279 return SPI_INVALID_LENGTH;
1280 }
1281 if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_NO_ADDRESS) &&
1282 (writecnt != 1)) {
snelsone42c3802010-05-07 20:09:04 +00001283 msg_perr("%s: Internal command size error for opcode "
hailfinger82e32492010-02-11 11:28:37 +00001284 "0x%02x, got writecnt=%i, want =1\n", __func__, cmd,
1285 writecnt);
1286 return SPI_INVALID_LENGTH;
1287 }
1288 if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) &&
1289 (writecnt < 4)) {
snelsone42c3802010-05-07 20:09:04 +00001290 msg_perr("%s: Internal command size error for opcode "
hailfinger82e32492010-02-11 11:28:37 +00001291 "0x%02x, got writecnt=%i, want >=4\n", __func__, cmd,
1292 writecnt);
1293 return SPI_INVALID_LENGTH;
1294 }
1295 if (((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
1296 (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)) &&
1297 (readcnt)) {
snelsone42c3802010-05-07 20:09:04 +00001298 msg_perr("%s: Internal command size error for opcode "
hailfinger82e32492010-02-11 11:28:37 +00001299 "0x%02x, got readcnt=%i, want =0\n", __func__, cmd,
1300 readcnt);
1301 return SPI_INVALID_LENGTH;
1302 }
1303
stefanct689eb6c2011-06-11 19:44:31 +00001304 /* Translate read/write array/count.
1305 * The maximum data length is identical for the maximum read length and
1306 * for the maximum write length excluding opcode and address. Opcode and
1307 * address are stored in separate registers, not in the data registers
1308 * and are thus not counted towards data length. The only exception
1309 * applies if the opcode definition (un)intentionally classifies said
1310 * opcode incorrectly as non-address opcode or vice versa. */
hailfinger82e7ddb2008-05-16 12:55:55 +00001311 if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) {
stepan8f46dd62008-06-27 15:18:20 +00001312 data = (uint8_t *) (writearr + 1);
1313 count = writecnt - 1;
1314 } else if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
1315 data = (uint8_t *) (writearr + 4);
1316 count = writecnt - 4;
1317 } else {
1318 data = (uint8_t *) readarr;
hailfinger82e7ddb2008-05-16 12:55:55 +00001319 count = readcnt;
1320 }
stepan8f46dd62008-06-27 15:18:20 +00001321
David Hendricks1ed1d352011-11-23 17:54:37 -08001322 /* if opcode-type requires an address */
Edward O'Callaghandfb71542020-05-14 18:41:42 +10001323 if (cmd == JEDEC_REMS || cmd == JEDEC_RES) {
1324 addr = ichspi_bbar;
1325 } else if (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS ||
David Hendricks1ed1d352011-11-23 17:54:37 -08001326 opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
Edward O'Callaghandfb71542020-05-14 18:41:42 +10001327 /* BBAR may cut part of the chip off at the lower end. */
1328 const uint32_t valid_base = ichspi_bbar & ((flash->chip->total_size * 1024) - 1);
1329 const uint32_t addr_offset = ichspi_bbar - valid_base;
1330 /* Highest address we can program is (2^24 - 1). */
1331 const uint32_t valid_end = (1 << 24) - addr_offset;
1332
Edward O'Callaghan03c389d2020-07-08 23:07:24 +10001333 addr = writearr[1] << 16 | writearr[2] << 8 | writearr[3];
Edward O'Callaghandfb71542020-05-14 18:41:42 +10001334 const uint32_t addr_end = addr + count;
1335
1336 if (addr < valid_base ||
1337 addr_end < addr || /* integer overflow check */
1338 addr_end > valid_end) {
Edward O'Callaghand757b422020-05-26 21:22:12 +10001339 msg_perr("%s: Addressed region 0x%06x-0x%06x not in allowed range 0x%06x-0x%06x\n",
1340 __func__, addr, addr_end - 1, valid_base, valid_end - 1);
1341 return SPI_INVALID_ADDRESS;
David Hendricks1ed1d352011-11-23 17:54:37 -08001342 }
Edward O'Callaghandfb71542020-05-14 18:41:42 +10001343 addr += addr_offset;
1344
David Hendricks1ed1d352011-11-23 17:54:37 -08001345 if (num_fd_regions > 0) {
Edward O'Callaghan69c3a0d2020-07-23 10:41:41 +10001346 result = check_fd_permissions(opcode, 0, addr, count);
David Hendricks1ed1d352011-11-23 17:54:37 -08001347 if (result)
1348 return result;
1349 }
1350 }
1351
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001352 result = run_opcode(flash, *opcode, addr, count, data);
hailfinger9c290a72009-07-14 10:26:56 +00001353 if (result) {
mkarcherdb7751e2011-04-29 23:53:09 +00001354 msg_pdbg("Running OPCODE 0x%02x failed ", opcode->opcode);
1355 if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
1356 (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS)) {
1357 msg_pdbg("at address 0x%06x ", addr);
1358 }
1359 msg_pdbg("(payload length was %d).\n", count);
1360
1361 /* Print out the data array if it contains data to write.
1362 * Errors are detected before the received data is read back into
1363 * the array so it won't make sense to print it then. */
1364 if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
1365 (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)) {
1366 int i;
1367 msg_pspew("The data was:\n");
stefanctd0064e12011-11-08 11:55:24 +00001368 for (i = 0; i < count; i++){
mkarcherdb7751e2011-04-29 23:53:09 +00001369 msg_pspew("%3d: 0x%02x\n", i, data[i]);
1370 }
1371 }
hailfinger82e7ddb2008-05-16 12:55:55 +00001372 }
1373
hailfinger9c290a72009-07-14 10:26:56 +00001374 return result;
hailfinger82e7ddb2008-05-16 12:55:55 +00001375}
hailfinger948b81f2009-07-22 15:36:50 +00001376
stefanct83d99e82011-11-08 10:55:54 +00001377static struct hwseq_data {
1378 uint32_t size_comp0;
1379 uint32_t size_comp1;
Edward O'Callaghanc093d682020-05-26 17:53:53 +10001380 uint32_t addr_mask;
1381 bool only_4k;
1382 uint32_t hsfc_fcycle;
stefanct83d99e82011-11-08 10:55:54 +00001383} hwseq_data;
1384
Edward O'Callaghanc093d682020-05-26 17:53:53 +10001385/* Sets FLA in FADDR to (addr & hwseq_data.addr_mask) without touching other bits. */
David Hendricks07af3a42011-07-11 22:13:02 -07001386static void ich_hwseq_set_addr(uint32_t addr)
1387{
Edward O'Callaghanc093d682020-05-26 17:53:53 +10001388 uint32_t addr_old = REGREAD32(ICH9_REG_FADDR) & ~hwseq_data.addr_mask;
1389 REGWRITE32(ICH9_REG_FADDR, (addr & hwseq_data.addr_mask) | addr_old);
David Hendricks07af3a42011-07-11 22:13:02 -07001390}
1391
Edward O'Callaghand36b6e32020-08-07 21:07:25 +10001392int ich_hwseq_check_access(const struct flashctx *flash, unsigned int start,
1393 unsigned int len, int read)
1394{
1395 return check_fd_permissions(NULL, read ? SPI_OPCODE_TYPE_READ_NO_ADDRESS: SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, start, len);
1396}
1397
David Hendricks07af3a42011-07-11 22:13:02 -07001398/* Sets FADDR.FLA to 'addr' and returns the erase block size in bytes
stefanct3d3b6ee2011-10-20 12:57:14 +00001399 * of the block containing this address. May return nonsense if the address is
1400 * not valid. The erase block size for a specific address depends on the flash
1401 * partition layout as specified by FPB and the partition properties as defined
1402 * by UVSCC and LVSCC respectively. An alternative to implement this method
1403 * would be by querying FPB and the respective VSCC register directly.
1404 */
David Hendricks07af3a42011-07-11 22:13:02 -07001405static uint32_t ich_hwseq_get_erase_block_size(unsigned int addr)
1406{
1407 uint8_t enc_berase;
Vadim Bendeburya6f9c4a2013-09-19 14:38:34 -07001408 static const uint32_t dec_berase[4] = {
David Hendricks07af3a42011-07-11 22:13:02 -07001409 256,
1410 4 * 1024,
1411 8 * 1024,
1412 64 * 1024
1413 };
1414
Edward O'Callaghanc093d682020-05-26 17:53:53 +10001415 if (hwseq_data.only_4k) {
1416 return 4 * 1024;
1417 }
1418
David Hendricks07af3a42011-07-11 22:13:02 -07001419 ich_hwseq_set_addr(addr);
Edward O'Callaghanc093d682020-05-26 17:53:53 +10001420 enc_berase = (REGREAD16(ICH9_REG_HSFS) & HSFS_BERASE) >> HSFS_BERASE_OFF;
David Hendricks07af3a42011-07-11 22:13:02 -07001421 return dec_berase[enc_berase];
1422}
1423
stefanct3d3b6ee2011-10-20 12:57:14 +00001424/* Polls for Cycle Done Status, Flash Cycle Error or timeout in 8 us intervals.
David Hendricks07af3a42011-07-11 22:13:02 -07001425 Resets all error flags in HSFS.
1426 Returns 0 if the cycle completes successfully without errors within
1427 timeout us, 1 on errors. */
1428static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout,
Edward O'Callaghanacce4622020-07-16 15:39:19 +10001429 unsigned int len,
1430 enum ich_chipset ich_gen)
David Hendricks07af3a42011-07-11 22:13:02 -07001431{
1432 uint16_t hsfs;
1433 uint32_t addr;
1434
stefanct3d3b6ee2011-10-20 12:57:14 +00001435 timeout /= 8; /* scale timeout duration to counter */
David Hendricks07af3a42011-07-11 22:13:02 -07001436 while ((((hsfs = REGREAD16(ICH9_REG_HSFS)) &
1437 (HSFS_FDONE | HSFS_FCERR)) == 0) &&
1438 --timeout) {
stefanct3d3b6ee2011-10-20 12:57:14 +00001439 programmer_delay(8);
David Hendricks07af3a42011-07-11 22:13:02 -07001440 }
1441 REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
1442 if (!timeout) {
Edward O'Callaghanc093d682020-05-26 17:53:53 +10001443 addr = REGREAD32(ICH9_REG_FADDR) & hwseq_data.addr_mask;
David Hendricks07af3a42011-07-11 22:13:02 -07001444 msg_perr("Timeout error between offset 0x%08x and "
stefanct83d99e82011-11-08 10:55:54 +00001445 "0x%08x (= 0x%08x + %d)!\n",
1446 addr, addr + len - 1, addr, len - 1);
Edward O'Callaghanacce4622020-07-16 15:39:19 +10001447 prettyprint_ich9_reg_hsfs(hsfs, ich_gen);
1448 prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC), ich_gen);
David Hendricks07af3a42011-07-11 22:13:02 -07001449 return 1;
1450 }
1451
1452 if (hsfs & HSFS_FCERR) {
Edward O'Callaghanc093d682020-05-26 17:53:53 +10001453 addr = REGREAD32(ICH9_REG_FADDR) & hwseq_data.addr_mask;
David Hendricks07af3a42011-07-11 22:13:02 -07001454 msg_perr("Transaction error between offset 0x%08x and "
stefanct83d99e82011-11-08 10:55:54 +00001455 "0x%08x (= 0x%08x + %d)!\n",
stefanct3d3b6ee2011-10-20 12:57:14 +00001456 addr, addr + len - 1, addr, len - 1);
Edward O'Callaghanacce4622020-07-16 15:39:19 +10001457 prettyprint_ich9_reg_hsfs(hsfs, ich_gen);
1458 prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC), ich_gen);
David Hendricks07af3a42011-07-11 22:13:02 -07001459 return 1;
1460 }
1461 return 0;
1462}
stefanct83d99e82011-11-08 10:55:54 +00001463
Edward O'Callaghan52261e42020-11-13 00:59:07 +11001464static int ich_hwseq_get_flash_id(struct flashctx *flash, enum ich_chipset ich_gen)
Edward O'Callaghan0f183122020-08-01 21:17:36 +10001465{
1466 uint32_t hsfsc, data, mfg_id, model_id;
1467 const struct flashchip *entry;
1468 const int len = sizeof(data);
1469
1470 /* make sure FDONE, FCERR, & AEL are cleared */
1471 REGWRITE32(ICH9_REG_HSFS, REGREAD32(ICH9_REG_HSFS));
1472
1473 /* Set RDID as flash cycle and FGO */
1474 hsfsc = REGREAD32(ICH9_REG_HSFS);
1475 hsfsc &= ~HSFSC_FCYCLE;
1476 hsfsc &= ~HSFSC_FDBC;
1477 hsfsc |= ((len - 1) << HSFSC_FDBC_OFF) & HSFSC_FDBC;
1478 hsfsc |= (0x6 << HSFSC_FCYCLE_OFF) | HSFSC_FGO;
1479 REGWRITE32(ICH9_REG_HSFS, hsfsc);
1480 /* poll for 100ms */
Edward O'Callaghan52261e42020-11-13 00:59:07 +11001481 if (ich_hwseq_wait_for_cycle_complete(100 * 1000, len, ich_gen)) {
Edward O'Callaghan0f183122020-08-01 21:17:36 +10001482 msg_perr("Timed out waiting for RDID to complete.\n");
1483 return 0;
1484 }
1485
1486 /*
1487 * Data will appear in reverse order:
1488 * Byte 0: Manufacturer ID
1489 * Byte 1: Model ID (MSB)
1490 * Byte 2: Model ID (LSB)
1491 */
1492 ich_read_data((uint8_t *)&data, len, ICH9_REG_FDATA0);
1493 mfg_id = data & 0xff;
1494 model_id = (data & 0xff00) | ((data >> 16) & 0xff);
1495
1496 entry = flash_id_to_entry(mfg_id, model_id);
1497 if (entry == NULL) {
1498 msg_perr("Unable to identify chip, mfg_id: 0x%02x, "
1499 "model_id: 0x%02x\n", mfg_id, model_id);
1500 return 0;
1501 } else {
1502 msg_pdbg("Chip identified: %s\n", entry->name);
1503 /* Update informational flash chip entries only */
1504 flash->chip->vendor = entry->vendor;
1505 flash->chip->name = entry->name;
1506 flash->chip->manufacture_id = entry->manufacture_id;
1507 flash->chip->model_id = entry->model_id;
1508 /* total_size read from flash descriptor */
1509 flash->chip->page_size = entry->page_size;
1510 flash->chip->feature_bits = entry->feature_bits;
1511 flash->chip->tested = entry->tested;
1512 flash->chip->wp = entry->wp;
1513 }
1514
1515 return 1;
1516}
1517
Edward O'Callaghan3fd6e002020-08-07 20:48:24 +10001518uint8_t ich_hwseq_read_status(const struct flashctx *flash)
1519{
1520 uint32_t hsfc;
1521 uint32_t timeout = 5000 * 1000;
1522 int len = 1;
1523 uint8_t buf;
1524
1525 msg_pdbg("Reading Status register\n");
1526
1527 /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
1528 REGWRITE32(ICH9_REG_HSFS, REGREAD32(ICH9_REG_HSFS));
1529
1530 hsfc = REGREAD32(ICH9_REG_HSFS);
1531 hsfc &= ~HSFSC_FCYCLE; /* set read operation */
1532
1533 /* read status register */
1534 hsfc |= (0x8 << HSFSC_FCYCLE_OFF);
1535
1536 hsfc &= ~HSFSC_FDBC; /* clear byte count */
1537 /* set byte count */
1538 hsfc |= (((len - 1) << HSFSC_FDBC_OFF) & HSFSC_FDBC);
1539 hsfc |= HSFSC_FGO; /* start */
1540 REGWRITE32(ICH9_REG_HSFS, hsfc);
Edward O'Callaghanacce4622020-07-16 15:39:19 +10001541 if (ich_hwseq_wait_for_cycle_complete(timeout, len, g_ich_generation)) {
Edward O'Callaghan3fd6e002020-08-07 20:48:24 +10001542 msg_perr("Reading Status register failed\n!!");
1543 return -1;
1544 }
1545 ich_read_data(&buf, len, ICH9_REG_FDATA0);
1546 return buf;
1547}
1548
1549int ich_hwseq_write_status(const struct flashctx *flash, int status)
1550{
1551 uint32_t hsfc;
1552 uint32_t timeout = 5000 * 1000;
1553 int len = 1;
1554 uint8_t buf = status;
1555
1556 msg_pdbg("Writing status register\n");
1557
1558 /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
1559 REGWRITE32(ICH9_REG_HSFS, REGREAD32(ICH9_REG_HSFS));
1560
1561 ich_fill_data(&buf, len, ICH9_REG_FDATA0);
1562 hsfc = REGREAD32(ICH9_REG_HSFS);
1563 hsfc &= ~HSFSC_FCYCLE; /* clear operation */
1564
1565 /* write status register */
1566 hsfc |= (0x7 << HSFSC_FCYCLE_OFF);
1567 hsfc &= ~HSFSC_FDBC; /* clear byte count */
1568
1569 /* set byte count */
1570 hsfc |= (((len - 1) << HSFSC_FDBC_OFF) & HSFSC_FDBC);
1571 hsfc |= HSFSC_FGO; /* start */
1572 REGWRITE32(ICH9_REG_HSFS, hsfc);
1573
Edward O'Callaghanacce4622020-07-16 15:39:19 +10001574 if (ich_hwseq_wait_for_cycle_complete(timeout, len, g_ich_generation)) {
Edward O'Callaghan3fd6e002020-08-07 20:48:24 +10001575 msg_perr("Writing Status register failed\n!!");
1576 return -1;
1577 }
1578 return 0;
1579}
1580
Edward O'Callaghand757b422020-05-26 21:22:12 +10001581static int ich_hwseq_probe(struct flashctx *flash)
stefanct83d99e82011-11-08 10:55:54 +00001582{
1583 uint32_t total_size, boundary;
1584 uint32_t erase_size_low, size_low, erase_size_high, size_high;
1585 struct block_eraser *eraser;
1586
Edward O'Callaghan52261e42020-11-13 00:59:07 +11001587 if (ich_hwseq_get_flash_id(flash, g_ich_generation) != 1) {
Edward O'Callaghan0f183122020-08-01 21:17:36 +10001588 msg_perr("Unable to read flash chip ID\n");
1589 return 0;
1590 }
1591
stefanct83d99e82011-11-08 10:55:54 +00001592 total_size = hwseq_data.size_comp0 + hwseq_data.size_comp1;
Edward O'Callaghan59919f92019-09-09 00:15:08 +10001593 msg_cdbg("Hardware sequencing reports %d attached SPI flash chip",
stefanct83d99e82011-11-08 10:55:54 +00001594 (hwseq_data.size_comp1 != 0) ? 2 : 1);
1595 if (hwseq_data.size_comp1 != 0)
1596 msg_cdbg("s with a combined");
1597 else
1598 msg_cdbg(" with a");
1599 msg_cdbg(" density of %d kB.\n", total_size / 1024);
Patrick Georgif3fa2992017-02-02 16:24:44 +01001600 flash->chip->total_size = total_size / 1024;
stefanct83d99e82011-11-08 10:55:54 +00001601
Patrick Georgif3fa2992017-02-02 16:24:44 +01001602 eraser = &(flash->chip->block_erasers[0]);
Edward O'Callaghanc093d682020-05-26 17:53:53 +10001603 if (!hwseq_data.only_4k)
1604 boundary = (REGREAD32(ICH9_REG_FPB) & FPB_FPBA) << 12;
1605 else
1606 boundary = 0;
stefanct83d99e82011-11-08 10:55:54 +00001607 size_high = total_size - boundary;
1608 erase_size_high = ich_hwseq_get_erase_block_size(boundary);
1609
1610 if (boundary == 0) {
Edward O'Callaghan59919f92019-09-09 00:15:08 +10001611 msg_cdbg2("There is only one partition containing the whole "
stefanct83d99e82011-11-08 10:55:54 +00001612 "address space (0x%06x - 0x%06x).\n", 0, size_high-1);
1613 eraser->eraseblocks[0].size = erase_size_high;
1614 eraser->eraseblocks[0].count = size_high / erase_size_high;
Edward O'Callaghan59919f92019-09-09 00:15:08 +10001615 msg_cdbg2("There are %d erase blocks with %d B each.\n",
stefanct83d99e82011-11-08 10:55:54 +00001616 size_high / erase_size_high, erase_size_high);
1617 } else {
Edward O'Callaghan59919f92019-09-09 00:15:08 +10001618 msg_cdbg2("The flash address space (0x%06x - 0x%06x) is divided "
stefanct83d99e82011-11-08 10:55:54 +00001619 "at address 0x%06x in two partitions.\n",
Edward O'Callaghan13e6abd2020-05-26 22:15:22 +10001620 0, total_size-1, boundary);
stefanct83d99e82011-11-08 10:55:54 +00001621 size_low = total_size - size_high;
1622 erase_size_low = ich_hwseq_get_erase_block_size(0);
1623
1624 eraser->eraseblocks[0].size = erase_size_low;
1625 eraser->eraseblocks[0].count = size_low / erase_size_low;
1626 msg_cdbg("The first partition ranges from 0x%06x to 0x%06x.\n",
1627 0, size_low-1);
1628 msg_cdbg("In that range are %d erase blocks with %d B each.\n",
1629 size_low / erase_size_low, erase_size_low);
1630
1631 eraser->eraseblocks[1].size = erase_size_high;
1632 eraser->eraseblocks[1].count = size_high / erase_size_high;
1633 msg_cdbg("The second partition ranges from 0x%06x to 0x%06x.\n",
Edward O'Callaghan13e6abd2020-05-26 22:15:22 +10001634 boundary, total_size-1);
stefanct83d99e82011-11-08 10:55:54 +00001635 msg_cdbg("In that range are %d erase blocks with %d B each.\n",
1636 size_high / erase_size_high, erase_size_high);
1637 }
Edward O'Callaghan53f03f02020-05-27 14:16:28 +10001638 flash->chip->tested = TEST_OK_PREW;
stefanct83d99e82011-11-08 10:55:54 +00001639 return 1;
1640}
1641
Edward O'Callaghand757b422020-05-26 21:22:12 +10001642static int ich_hwseq_block_erase(struct flashctx *flash, unsigned int addr,
1643 unsigned int len)
stefanct83d99e82011-11-08 10:55:54 +00001644{
1645 uint32_t erase_block;
1646 uint16_t hsfc;
1647 uint32_t timeout = 5000 * 1000; /* 5 s for max 64 kB */
Edward O'Callaghan94967cc2020-08-07 20:19:15 +10001648 int result = 0;
stefanct83d99e82011-11-08 10:55:54 +00001649
Edward O'Callaghand13334a2020-07-23 12:51:00 +10001650 if (is_dry_run())
Vadim Bendebury066143d2018-07-16 18:20:33 -07001651 return 0;
1652
stefanct83d99e82011-11-08 10:55:54 +00001653 erase_block = ich_hwseq_get_erase_block_size(addr);
1654 if (len != erase_block) {
1655 msg_cerr("Erase block size for address 0x%06x is %d B, "
1656 "but requested erase block size is %d B. "
1657 "Not erasing anything.\n", addr, erase_block, len);
1658 return -1;
1659 }
1660
1661 /* Although the hardware supports this (it would erase the whole block
1662 * containing the address) we play safe here. */
1663 if (addr % erase_block != 0) {
1664 msg_cerr("Erase address 0x%06x is not aligned to the erase "
1665 "block boundary (any multiple of %d). "
1666 "Not erasing anything.\n", addr, erase_block);
1667 return -1;
1668 }
1669
Patrick Georgif3fa2992017-02-02 16:24:44 +01001670 if (addr + len > flash->chip->total_size * 1024) {
stefanct83d99e82011-11-08 10:55:54 +00001671 msg_perr("Request to erase some inaccessible memory address(es)"
1672 " (addr=0x%x, len=%d). "
1673 "Not erasing anything.\n", addr, len);
1674 return -1;
1675 }
1676
Edward O'Callaghan94967cc2020-08-07 20:19:15 +10001677 /* Check flash region permissions before erasing */
1678 result = check_fd_permissions(NULL, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, addr, len);
1679 if (result)
1680 return result;
1681
Edward O'Callaghan59919f92019-09-09 00:15:08 +10001682 msg_pdbg("Erasing %d bytes starting at 0x%06x.\n", len, addr);
Edward O'Callaghan434a9902020-05-26 22:19:04 +10001683 ich_hwseq_set_addr(addr);
stefanct83d99e82011-11-08 10:55:54 +00001684
1685 /* make sure FDONE, FCERR, AEL are cleared by writing 1 to them */
1686 REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
1687
1688 hsfc = REGREAD16(ICH9_REG_HSFC);
Edward O'Callaghanc093d682020-05-26 17:53:53 +10001689 hsfc &= ~hwseq_data.hsfc_fcycle; /* clear operation */
stefanct83d99e82011-11-08 10:55:54 +00001690 hsfc |= (0x3 << HSFC_FCYCLE_OFF); /* set erase operation */
1691 hsfc |= HSFC_FGO; /* start */
Edward O'Callaghan59919f92019-09-09 00:15:08 +10001692 msg_pdbg("HSFC used for block erasing: ");
Edward O'Callaghanacce4622020-07-16 15:39:19 +10001693 prettyprint_ich9_reg_hsfc(hsfc, g_ich_generation);
stefanct83d99e82011-11-08 10:55:54 +00001694 REGWRITE16(ICH9_REG_HSFC, hsfc);
1695
Edward O'Callaghanacce4622020-07-16 15:39:19 +10001696 if (ich_hwseq_wait_for_cycle_complete(timeout, len, g_ich_generation))
stefanct83d99e82011-11-08 10:55:54 +00001697 return -1;
Edward O'Callaghan94967cc2020-08-07 20:19:15 +10001698
1699 return result;
stefanct83d99e82011-11-08 10:55:54 +00001700}
1701
Edward O'Callaghand757b422020-05-26 21:22:12 +10001702static int ich_hwseq_read(struct flashctx *flash, uint8_t *buf,
1703 unsigned int addr, unsigned int len)
stefanct83d99e82011-11-08 10:55:54 +00001704{
1705 uint16_t hsfc;
1706 uint16_t timeout = 100 * 60;
1707 uint8_t block_len;
Edward O'Callaghan94967cc2020-08-07 20:19:15 +10001708 int result = 0, chunk_status = 0;
stefanct83d99e82011-11-08 10:55:54 +00001709
Edward O'Callaghan03c389d2020-07-08 23:07:24 +10001710 if (addr + len > flash->chip->total_size * 1024) {
stefanct83d99e82011-11-08 10:55:54 +00001711 msg_perr("Request to read from an inaccessible memory address "
1712 "(addr=0x%x, len=%d).\n", addr, len);
1713 return -1;
1714 }
1715
Edward O'Callaghan59919f92019-09-09 00:15:08 +10001716 msg_pdbg("Reading %d bytes starting at 0x%06x.\n", len, addr);
stefanct83d99e82011-11-08 10:55:54 +00001717 /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
1718 REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
1719
1720 while (len > 0) {
Edward O'Callaghan434a9902020-05-26 22:19:04 +10001721 /* Obey programmer limit... */
Edward O'Callaghanc66827e2020-10-09 12:22:04 +11001722 block_len = min(len, flash->mst->opaque.max_data_read);
Edward O'Callaghan434a9902020-05-26 22:19:04 +10001723 /* as well as flash chip page borders as demanded in the Intel datasheets. */
1724 block_len = min(block_len, 256 - (addr & 0xFF));
1725
Edward O'Callaghan94967cc2020-08-07 20:19:15 +10001726 /* Check flash region permissions before reading */
1727 chunk_status = check_fd_permissions(NULL, SPI_OPCODE_TYPE_READ_NO_ADDRESS, addr, block_len);
1728 if (chunk_status) {
1729 if (ignore_error(chunk_status)) {
1730 /* fill this chunk with 0xff bytes and
1731 * inform the caller about the error */
1732 memset(buf, 0xff, block_len);
1733 result = chunk_status;
1734 } else {
1735 return chunk_status;
1736 }
1737 } else {
1738 ich_hwseq_set_addr(addr);
1739 hsfc = REGREAD16(ICH9_REG_HSFC);
1740 hsfc &= ~hwseq_data.hsfc_fcycle; /* set read operation */
1741 hsfc &= ~HSFC_FDBC; /* clear byte count */
1742 /* set byte count */
1743 hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);
1744 hsfc |= HSFC_FGO; /* start */
1745 REGWRITE16(ICH9_REG_HSFC, hsfc);
stefanct83d99e82011-11-08 10:55:54 +00001746
Edward O'Callaghanacce4622020-07-16 15:39:19 +10001747 if (ich_hwseq_wait_for_cycle_complete(timeout, block_len, g_ich_generation))
Edward O'Callaghan94967cc2020-08-07 20:19:15 +10001748 return 1;
1749 ich_read_data(buf, block_len, ICH9_REG_FDATA0);
1750 }
stefanct83d99e82011-11-08 10:55:54 +00001751 addr += block_len;
1752 buf += block_len;
1753 len -= block_len;
1754 }
Edward O'Callaghan94967cc2020-08-07 20:19:15 +10001755 return result;
stefanct83d99e82011-11-08 10:55:54 +00001756}
1757
Edward O'Callaghand757b422020-05-26 21:22:12 +10001758static int ich_hwseq_write(struct flashctx *flash, const uint8_t *buf, unsigned int addr, unsigned int len)
stefanct83d99e82011-11-08 10:55:54 +00001759{
1760 uint16_t hsfc;
1761 uint16_t timeout = 100 * 60;
1762 uint8_t block_len;
Edward O'Callaghan94967cc2020-08-07 20:19:15 +10001763 int result = 0;
stefanct83d99e82011-11-08 10:55:54 +00001764
Edward O'Callaghan03c389d2020-07-08 23:07:24 +10001765 if (addr + len > flash->chip->total_size * 1024) {
stefanct83d99e82011-11-08 10:55:54 +00001766 msg_perr("Request to write to an inaccessible memory address "
1767 "(addr=0x%x, len=%d).\n", addr, len);
1768 return -1;
1769 }
1770
Edward O'Callaghan59919f92019-09-09 00:15:08 +10001771 msg_pdbg("Writing %d bytes starting at 0x%06x.\n", len, addr);
stefanct83d99e82011-11-08 10:55:54 +00001772 /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
1773 REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
1774
1775 while (len > 0) {
1776 ich_hwseq_set_addr(addr);
Edward O'Callaghan434a9902020-05-26 22:19:04 +10001777 /* Obey programmer limit... */
Edward O'Callaghanc66827e2020-10-09 12:22:04 +11001778 block_len = min(len, flash->mst->opaque.max_data_write);
Edward O'Callaghan434a9902020-05-26 22:19:04 +10001779 /* as well as flash chip page borders as demanded in the Intel datasheets. */
1780 block_len = min(block_len, 256 - (addr & 0xFF));
Edward O'Callaghan94967cc2020-08-07 20:19:15 +10001781 /* Check flash region permissions before writing */
1782 result = check_fd_permissions(NULL, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, addr, block_len);
1783 if (result)
1784 return result;
stefanct83d99e82011-11-08 10:55:54 +00001785 ich_fill_data(buf, block_len, ICH9_REG_FDATA0);
1786 hsfc = REGREAD16(ICH9_REG_HSFC);
Edward O'Callaghanc093d682020-05-26 17:53:53 +10001787 hsfc &= ~hwseq_data.hsfc_fcycle; /* clear operation */
stefanct83d99e82011-11-08 10:55:54 +00001788 hsfc |= (0x2 << HSFC_FCYCLE_OFF); /* set write operation */
1789 hsfc &= ~HSFC_FDBC; /* clear byte count */
1790 /* set byte count */
1791 hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);
1792 hsfc |= HSFC_FGO; /* start */
1793 REGWRITE16(ICH9_REG_HSFC, hsfc);
1794
Edward O'Callaghanacce4622020-07-16 15:39:19 +10001795 if (ich_hwseq_wait_for_cycle_complete(timeout, block_len, g_ich_generation))
stefanct83d99e82011-11-08 10:55:54 +00001796 return -1;
1797 addr += block_len;
1798 buf += block_len;
1799 len -= block_len;
1800 }
Edward O'Callaghan94967cc2020-08-07 20:19:15 +10001801
1802 return result;
stefanct83d99e82011-11-08 10:55:54 +00001803}
David Hendricks07af3a42011-07-11 22:13:02 -07001804
Edward O'Callaghand757b422020-05-26 21:22:12 +10001805static int ich_spi_send_multicommand(const struct flashctx *flash,
1806 struct spi_command *cmds)
hailfinger948b81f2009-07-22 15:36:50 +00001807{
1808 int ret = 0;
hailfinger82e32492010-02-11 11:28:37 +00001809 int i;
hailfingerbb092112009-09-18 15:50:56 +00001810 int oppos, preoppos;
1811 for (; (cmds->writecnt || cmds->readcnt) && !ret; cmds++) {
hailfingerbb092112009-09-18 15:50:56 +00001812 if ((cmds + 1)->writecnt || (cmds + 1)->readcnt) {
hailfinger82e32492010-02-11 11:28:37 +00001813 /* Next command is valid. */
hailfingerbb092112009-09-18 15:50:56 +00001814 preoppos = find_preop(curopcodes, cmds->writearr[0]);
1815 oppos = find_opcode(curopcodes, (cmds + 1)->writearr[0]);
hailfinger82e32492010-02-11 11:28:37 +00001816 if ((oppos == -1) && (preoppos != -1)) {
1817 /* Current command is listed as preopcode in
1818 * ICH struct OPCODES, but next command is not
1819 * listed as opcode in that struct.
1820 * Check for command sanity, then
1821 * try to reprogram the ICH opcode list.
1822 */
1823 if (find_preop(curopcodes,
1824 (cmds + 1)->writearr[0]) != -1) {
snelsone42c3802010-05-07 20:09:04 +00001825 msg_perr("%s: Two subsequent "
hailfinger82e32492010-02-11 11:28:37 +00001826 "preopcodes 0x%02x and 0x%02x, "
1827 "ignoring the first.\n",
1828 __func__, cmds->writearr[0],
1829 (cmds + 1)->writearr[0]);
1830 continue;
1831 }
1832 /* If the chipset is locked down, we'll fail
1833 * during execution of the next command anyway.
1834 * No need to bother with fixups.
1835 */
1836 if (!ichspi_lock) {
hailfinger4c973122010-10-05 22:06:05 +00001837 oppos = reprogram_opcode_on_the_fly((cmds + 1)->writearr[0], (cmds + 1)->writecnt, (cmds + 1)->readcnt);
1838 if (oppos == -1)
1839 continue;
1840 curopcodes->opcode[oppos].atomic = preoppos + 1;
hailfinger82e32492010-02-11 11:28:37 +00001841 continue;
1842 }
1843 }
1844 if ((oppos != -1) && (preoppos != -1)) {
1845 /* Current command is listed as preopcode in
1846 * ICH struct OPCODES and next command is listed
1847 * as opcode in that struct. Match them up.
1848 */
1849 curopcodes->opcode[oppos].atomic = preoppos + 1;
hailfingerbb092112009-09-18 15:50:56 +00001850 continue;
hailfinger82e32492010-02-11 11:28:37 +00001851 }
1852 /* If none of the above if-statements about oppos or
1853 * preoppos matched, this is a normal opcode.
1854 */
1855 }
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001856 ret = ich_spi_send_command(flash, cmds->writecnt, cmds->readcnt,
hailfingerbb092112009-09-18 15:50:56 +00001857 cmds->writearr, cmds->readarr);
hailfinger82e32492010-02-11 11:28:37 +00001858 /* Reset the type of all opcodes to non-atomic. */
1859 for (i = 0; i < 8; i++)
1860 curopcodes->opcode[i].atomic = 0;
hailfinger948b81f2009-07-22 15:36:50 +00001861 }
1862 return ret;
1863}
hailfinger324a9cc2010-05-26 01:45:41 +00001864
mkarcher74d30132010-07-22 18:04:15 +00001865#define ICH_BMWAG(x) ((x >> 24) & 0xff)
1866#define ICH_BMRAG(x) ((x >> 16) & 0xff)
1867#define ICH_BRWA(x) ((x >> 8) & 0xff)
1868#define ICH_BRRA(x) ((x >> 0) & 0xff)
1869
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001870static const enum ich_access_protection access_perms_to_protection[] = {
1871 LOCKED, WRITE_PROT, READ_PROT, NO_PROT
1872};
1873static const char *const access_names[] = {
1874 "locked", "read-only", "write-only", "read-write"
1875};
1876
1877static enum ich_access_protection ich9_handle_frap(uint32_t frap, unsigned int i)
mkarcher74d30132010-07-22 18:04:15 +00001878{
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001879 const int rwperms_unknown = ARRAY_SIZE(access_names);
1880 static const char *const region_names[] = {
1881 "Flash Descriptor", "BIOS", "Management Engine",
1882 "Gigabit Ethernet", "Platform Data", "Device Expansion",
1883 "BIOS2", "unknown", "EC/BMC",
1884 };
1885 const char *const region_name = i < ARRAY_SIZE(region_names) ? region_names[i] : "unknown";
1886
1887 uint32_t base, limit;
1888 int rwperms;
1889 const int offset = i < 12
1890 ? ICH9_REG_FREG0 + i * 4
1891 : APL_REG_FREG12 + (i - 12) * 4;
mkarcher74d30132010-07-22 18:04:15 +00001892 uint32_t freg = mmio_readl(ich_spibar + offset);
1893
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001894 if (i < 8) {
1895 rwperms = (((ICH_BRWA(frap) >> i) & 1) << 1) |
1896 (((ICH_BRRA(frap) >> i) & 1) << 0);
1897 } else {
1898 /* Datasheets don't define any access bits for regions > 7. We
1899 can't rely on the actual descriptor settings either as there
1900 are several overrides for them (those by other masters are
1901 not even readable by us, *shrug*). */
1902 rwperms = rwperms_unknown;
1903 }
David Hendricks53540f92016-09-03 00:34:41 +00001904
Bora Guvendikc34416b2019-01-07 16:10:48 -08001905 /*
1906 * Get Region 0 - 7 Permission bits, region 8 and above don't have
1907 * bits to indicate permissions in Flash Region Access Permissions
1908 * register.
1909 */
Duncan Lauriea62ff822019-04-25 12:12:20 -07001910 if ( i >= EMBEDDED_CONTROLLER_REGION ) {
1911 /*
1912 * Use Flash Descriptor Observe register to determine if
1913 * the EC region can be written by the BIOS master.
1914 */
Bora Guvendikc34416b2019-01-07 16:10:48 -08001915 rwperms = FD_REGION_READ_WRITE;
Duncan Lauriea62ff822019-04-25 12:12:20 -07001916 if (i == EMBEDDED_CONTROLLER_REGION &&
Edward O'Callaghane3e30562019-09-03 13:10:58 +10001917 g_ich_generation >= CHIPSET_100_SERIES_SUNRISE_POINT) {
Duncan Lauriea62ff822019-04-25 12:12:20 -07001918 struct ich_descriptors desc = {{ 0 }};
Duncan Laurieb2d845b2019-05-28 10:10:03 -07001919 /* Region is RW if flash descriptor override is set */
1920 freg = mmio_readl(ich_spibar + PCH100_REG_HSFSC);
Edward O'Callaghanf58c0e62020-08-01 20:58:18 +10001921 if ((freg & HSFS_FDV) && !(freg & HSFS_FDOPSS))
Duncan Laurieb2d845b2019-05-28 10:10:03 -07001922 rwperms = FD_REGION_READ_WRITE;
Edward O'Callaghan4b90b622020-05-18 16:20:56 +10001923 else if (read_ich_descriptors_via_fdo(g_ich_generation, ich_spibar, &desc) == ICH_RET_OK) {
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +10001924 const struct ich_desc_master *const mstr = &desc.master;
1925#define BIT(x) (1<<(x))
1926 int bios_ec_r = mstr->mstr[i].read & BIT(16); /* BIOS_EC_r in PCH100+ */
1927 int bios_ec_w = mstr->mstr[i].write & BIT(28); /* BIOS_EC_w in PCH100+ */
1928 if (bios_ec_r && bios_ec_w)
Duncan Lauriea62ff822019-04-25 12:12:20 -07001929 rwperms = FD_REGION_READ_WRITE;
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +10001930 else if (bios_ec_r && !bios_ec_w)
Duncan Lauriea62ff822019-04-25 12:12:20 -07001931 rwperms = FD_REGION_READ_ONLY;
Edward O'Callaghanaef44cb2020-07-03 15:31:14 +10001932 else if (!bios_ec_r && bios_ec_w)
Duncan Lauriea62ff822019-04-25 12:12:20 -07001933 rwperms = FD_REGION_WRITE_ONLY;
1934 else
1935 rwperms = FD_REGION_LOCKED;
1936 }
1937 }
1938 }
Bora Guvendikc34416b2019-01-07 16:10:48 -08001939
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001940 base = ICH_FREG_BASE(freg);
1941 limit = ICH_FREG_LIMIT(freg);
1942
1943 /* HACK to support check_fd_permissions() */
1944 fd_regions[i].base = base;
1945 fd_regions[i].limit = limit | 0x0fff;
David Hendricks1ed1d352011-11-23 17:54:37 -08001946 fd_regions[i].permission = &fd_region_permissions[rwperms];
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001947
1948 if (base > limit || (freg == 0 && i > 0)) {
mkarcher74d30132010-07-22 18:04:15 +00001949 /* this FREG is disabled */
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001950 msg_pdbg2("0x%02X: 0x%08x FREG%u: %s region is unused.\n",
1951 offset, freg, i, region_name);
1952 return NO_PROT;
1953 }
1954 msg_pdbg("0x%02X: 0x%08x ", offset, freg);
1955 if (rwperms == 0x3) {
1956 msg_pdbg("FREG%u: %s region (0x%08x-0x%08x) is %s.\n", i,
1957 region_name, base, limit, access_names[rwperms]);
1958 return NO_PROT;
1959 }
1960 if (rwperms == rwperms_unknown) {
1961 msg_pdbg("FREG%u: %s region (0x%08x-0x%08x) has unknown permissions.\n",
1962 i, region_name, base, limit);
1963 return NO_PROT;
mkarcher74d30132010-07-22 18:04:15 +00001964 }
David Hendricks53540f92016-09-03 00:34:41 +00001965
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001966 msg_pinfo("FREG%u: %s region (0x%08x-0x%08x) is %s.\n", i,
1967 region_name, base, limit, access_names[rwperms]);
1968 return access_perms_to_protection[rwperms];
mkarcher74d30132010-07-22 18:04:15 +00001969}
1970
stefanct7ab834a2011-09-17 21:21:48 +00001971 /* In contrast to FRAP and the master section of the descriptor the bits
1972 * in the PR registers have an inverted meaning. The bits in FRAP
1973 * indicate read and write access _grant_. Here they indicate read
1974 * and write _protection_ respectively. If both bits are 0 the address
1975 * bits are ignored.
1976 */
1977#define ICH_PR_PERMS(pr) (((~((pr) >> PR_RP_OFF) & 1) << 0) | \
1978 ((~((pr) >> PR_WP_OFF) & 1) << 1))
1979
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001980static enum ich_access_protection ich9_handle_pr(const size_t reg_pr0, unsigned int i)
stefanct7ab834a2011-09-17 21:21:48 +00001981{
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001982 uint8_t off = reg_pr0 + (i * 4);
Jack Rosenthal47a3cc92020-07-28 10:20:02 -06001983 uint32_t pr = mmio_readl(ich_spibar + off);
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001984 unsigned int rwperms = ICH_PR_PERMS(pr);
Edward O'Callaghan34b4b112020-05-26 21:54:52 +10001985
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10001986 /* From 5 on we have GPR registers and start from 0 again. */
1987 const char *const prefix = i >= 5 ? "G" : "";
1988 if (i >= 5)
1989 i -= 5;
1990
1991 if (rwperms == 0x3) {
1992 msg_pdbg2("0x%02X: 0x%08x (%sPR%u is unused)\n", off, pr, prefix, i);
1993 return NO_PROT;
1994 }
1995
1996 msg_pdbg("0x%02X: 0x%08x ", off, pr);
1997 msg_pwarn("%sPR%u: Warning: 0x%08x-0x%08x is %s.\n", prefix, i, ICH_FREG_BASE(pr),
1998 ICH_FREG_LIMIT(pr), access_names[rwperms]);
1999 return access_perms_to_protection[rwperms];
stefanct7ab834a2011-09-17 21:21:48 +00002000}
2001
stefanctdd95a212011-09-17 22:21:55 +00002002/* Set/Clear the read and write protection enable bits of PR register @i
2003 * according to @read_prot and @write_prot. */
Edward O'Callaghancdd87bb2020-05-18 15:32:08 +10002004static void ich9_set_pr(const size_t reg_pr0, int i, int read_prot, int write_prot)
stefanctdd95a212011-09-17 22:21:55 +00002005{
Edward O'Callaghancdd87bb2020-05-18 15:32:08 +10002006 void *addr = ich_spibar + reg_pr0 + (i * 4);
stefanctdd95a212011-09-17 22:21:55 +00002007 uint32_t old = mmio_readl(addr);
2008 uint32_t new;
2009
2010 msg_gspew("PR%u is 0x%08x", i, old);
2011 new = old & ~((1 << PR_RP_OFF) | (1 << PR_WP_OFF));
2012 if (read_prot)
2013 new |= (1 << PR_RP_OFF);
2014 if (write_prot)
2015 new |= (1 << PR_WP_OFF);
2016 if (old == new) {
2017 msg_gspew(" already.\n");
2018 return;
2019 }
2020 msg_gspew(", trying to set it to 0x%08x ", new);
2021 rmmio_writel(new, addr);
2022 msg_gspew("resulted in 0x%08x.\n", mmio_readl(addr));
2023}
2024
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002025static const struct spi_master spi_master_ich7 = {
mkarcherd264e9e2011-05-11 17:07:07 +00002026 .max_data_read = 64,
2027 .max_data_write = 64,
2028 .command = ich_spi_send_command,
2029 .multicommand = ich_spi_send_multicommand,
2030 .read = default_spi_read,
2031 .write_256 = default_spi_write_256,
Edward O'Callaghaneeaac6b2020-10-12 19:51:56 +11002032 .write_aai = default_spi_write_aai,
mkarcherd264e9e2011-05-11 17:07:07 +00002033};
2034
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002035static const struct spi_master spi_master_ich9 = {
mkarcherd264e9e2011-05-11 17:07:07 +00002036 .max_data_read = 64,
2037 .max_data_write = 64,
2038 .command = ich_spi_send_command,
2039 .multicommand = ich_spi_send_multicommand,
2040 .read = default_spi_read,
2041 .write_256 = default_spi_write_256,
Edward O'Callaghaneeaac6b2020-10-12 19:51:56 +11002042 .write_aai = default_spi_write_aai,
mkarcherd264e9e2011-05-11 17:07:07 +00002043};
2044
Edward O'Callaghanabd30192019-05-14 15:58:19 +10002045static struct opaque_master opaque_master_ich_hwseq = {
David Hendricks07af3a42011-07-11 22:13:02 -07002046 .max_data_read = 64,
2047 .max_data_write = 64,
stefanct83d99e82011-11-08 10:55:54 +00002048 .probe = ich_hwseq_probe,
David Hendricks07af3a42011-07-11 22:13:02 -07002049 .read = ich_hwseq_read,
stefanct83d99e82011-11-08 10:55:54 +00002050 .write = ich_hwseq_write,
2051 .erase = ich_hwseq_block_erase,
Edward O'Callaghand36b6e32020-08-07 21:07:25 +10002052 .check_access = ich_hwseq_check_access,
Edward O'Callaghan3fd6e002020-08-07 20:48:24 +10002053 .read_status = ich_hwseq_read_status,
2054 .write_status = ich_hwseq_write_status,
David Hendricks07af3a42011-07-11 22:13:02 -07002055};
2056
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002057int ich_init_spi(void *spibar, enum ich_chipset ich_gen)
mkarcher74d30132010-07-22 18:04:15 +00002058{
Edward O'Callaghand757b422020-05-26 21:22:12 +10002059 unsigned int i;
Edward O'Callaghan6f2f8322019-09-06 11:55:24 +10002060 uint16_t tmp2;
mkarcher74d30132010-07-22 18:04:15 +00002061 uint32_t tmp;
stefanct83d99e82011-11-08 10:55:54 +00002062 char *arg;
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10002063 int ich_spi_rw_restricted = 0;
stefanct3d3b6ee2011-10-20 12:57:14 +00002064 int desc_valid = 0;
Richard Hughes16eb3512019-01-02 21:11:08 +00002065 struct ich_descriptors desc;
stefanct83d99e82011-11-08 10:55:54 +00002066 enum ich_spi_mode {
2067 ich_auto,
2068 ich_hwseq,
2069 ich_swseq
2070 } ich_spi_mode = ich_auto;
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10002071 size_t num_freg, num_pr, reg_pr0;
stefanctc035c192011-11-06 23:51:09 +00002072
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002073 g_ich_generation = ich_gen;
Edward O'Callaghan6f2f8322019-09-06 11:55:24 +10002074 ich_spibar = spibar;
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +10002075
Richard Hughes16eb3512019-01-02 21:11:08 +00002076 memset(&desc, 0x00, sizeof(struct ich_descriptors));
mkarcher74d30132010-07-22 18:04:15 +00002077
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10002078 /* Moving registers / bits */
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002079 switch (ich_gen) {
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +10002080 case CHIPSET_100_SERIES_SUNRISE_POINT:
2081 case CHIPSET_C620_SERIES_LEWISBURG:
2082 case CHIPSET_300_SERIES_CANNON_POINT:
2083 case CHIPSET_APOLLO_LAKE:
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10002084 num_pr = 6; /* Includes GPR0 */
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +10002085 reg_pr0 = PCH100_REG_FPR0;
2086 swseq_data.reg_ssfsc = PCH100_REG_SSFSC;
2087 swseq_data.reg_preop = PCH100_REG_PREOP;
2088 swseq_data.reg_optype = PCH100_REG_OPTYPE;
2089 swseq_data.reg_opmenu = PCH100_REG_OPMENU;
2090 hwseq_data.addr_mask = PCH100_FADDR_FLA;
2091 hwseq_data.only_4k = true;
2092 hwseq_data.hsfc_fcycle = PCH100_HSFC_FCYCLE;
2093 break;
2094 default:
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10002095 num_pr = 5;
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +10002096 reg_pr0 = ICH9_REG_PR0;
2097 swseq_data.reg_ssfsc = ICH9_REG_SSFS;
2098 swseq_data.reg_preop = ICH9_REG_PREOP;
2099 swseq_data.reg_optype = ICH9_REG_OPTYPE;
2100 swseq_data.reg_opmenu = ICH9_REG_OPMENU;
2101 hwseq_data.addr_mask = ICH9_FADDR_FLA;
2102 hwseq_data.only_4k = false;
2103 hwseq_data.hsfc_fcycle = HSFC_FCYCLE;
2104 break;
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10002105 }
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002106 switch (ich_gen) {
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10002107 case CHIPSET_100_SERIES_SUNRISE_POINT:
2108 num_freg = 10;
2109 break;
2110 case CHIPSET_C620_SERIES_LEWISBURG:
2111 num_freg = 12; /* 12 MMIO regs, but 16 regions in FD spec */
2112 break;
2113 case CHIPSET_300_SERIES_CANNON_POINT:
2114 case CHIPSET_APOLLO_LAKE:
2115 num_freg = 16;
2116 break;
2117 default:
2118 num_freg = 5;
2119 break;
2120 }
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10002121
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002122 switch (ich_gen) {
stefanctc035c192011-11-06 23:51:09 +00002123 case CHIPSET_ICH7:
Edward O'Callaghanc8e0a112020-05-26 21:38:37 +10002124 case CHIPSET_TUNNEL_CREEK:
2125 case CHIPSET_CENTERTON:
mkarcher74d30132010-07-22 18:04:15 +00002126 msg_pdbg("0x00: 0x%04x (SPIS)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002127 mmio_readw(spibar + 0));
mkarcher74d30132010-07-22 18:04:15 +00002128 msg_pdbg("0x02: 0x%04x (SPIC)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002129 mmio_readw(spibar + 2));
mkarcher74d30132010-07-22 18:04:15 +00002130 msg_pdbg("0x04: 0x%08x (SPIA)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002131 mmio_readl(spibar + 4));
2132 ichspi_bbar = mmio_readl(spibar + 0x50);
mkarcher74d30132010-07-22 18:04:15 +00002133 msg_pdbg("0x50: 0x%08x (BBAR)\n",
2134 ichspi_bbar);
2135 msg_pdbg("0x54: 0x%04x (PREOP)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002136 mmio_readw(spibar + 0x54));
mkarcher74d30132010-07-22 18:04:15 +00002137 msg_pdbg("0x56: 0x%04x (OPTYPE)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002138 mmio_readw(spibar + 0x56));
mkarcher74d30132010-07-22 18:04:15 +00002139 msg_pdbg("0x58: 0x%08x (OPMENU)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002140 mmio_readl(spibar + 0x58));
mkarcher74d30132010-07-22 18:04:15 +00002141 msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002142 mmio_readl(spibar + 0x5c));
stefanctc73c1db2011-07-24 15:34:56 +00002143 for (i = 0; i < 3; i++) {
mkarcher74d30132010-07-22 18:04:15 +00002144 int offs;
2145 offs = 0x60 + (i * 4);
Edward O'Callaghan59919f92019-09-09 00:15:08 +10002146 msg_pdbg("0x%02x: 0x%08x (PBR%u)\n", offs,
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002147 mmio_readl(spibar + offs), i);
mkarcher74d30132010-07-22 18:04:15 +00002148 }
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002149 if (mmio_readw(spibar) & (1 << 15)) {
Edward O'Callaghan59919f92019-09-09 00:15:08 +10002150 msg_pwarn("WARNING: SPI Configuration Lockdown activated.\n");
mkarcher74d30132010-07-22 18:04:15 +00002151 ichspi_lock = 1;
2152 }
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +10002153 ich_init_opcodes(ich_gen);
Edward O'Callaghand22862f2020-07-16 15:37:26 +10002154 ich_set_bbar(0, ich_gen);
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002155 register_spi_master(&spi_master_ich7);
mkarcher74d30132010-07-22 18:04:15 +00002156 break;
stefanctc035c192011-11-06 23:51:09 +00002157 case CHIPSET_ICH8:
David Hendricks07af3a42011-07-11 22:13:02 -07002158 default: /* Future version might behave the same */
stefanct83d99e82011-11-08 10:55:54 +00002159 arg = extract_programmer_param("ich_spi_mode");
2160 if (arg && !strcmp(arg, "hwseq")) {
2161 ich_spi_mode = ich_hwseq;
2162 msg_pspew("user selected hwseq\n");
2163 } else if (arg && !strcmp(arg, "swseq")) {
2164 ich_spi_mode = ich_swseq;
2165 msg_pspew("user selected swseq\n");
2166 } else if (arg && !strcmp(arg, "auto")) {
2167 msg_pspew("user selected auto\n");
2168 ich_spi_mode = ich_auto;
2169 } else if (arg && !strlen(arg)) {
2170 msg_perr("Missing argument for ich_spi_mode.\n");
2171 free(arg);
2172 return ERROR_FATAL;
2173 } else if (arg) {
2174 msg_perr("Unknown argument for ich_spi_mode: %s\n",
2175 arg);
2176 free(arg);
2177 return ERROR_FATAL;
2178 }
2179 free(arg);
2180
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002181 tmp2 = mmio_readw(spibar + ICH9_REG_HSFS);
mkarcher74d30132010-07-22 18:04:15 +00002182 msg_pdbg("0x04: 0x%04x (HSFS)\n", tmp2);
Edward O'Callaghanacce4622020-07-16 15:39:19 +10002183 prettyprint_ich9_reg_hsfs(tmp2, ich_gen);
stefanct24bda702011-06-12 08:14:10 +00002184 if (tmp2 & HSFS_FLOCKDN) {
Edward O'Callaghan59919f92019-09-09 00:15:08 +10002185 msg_pinfo("SPI Configuration is locked down.\n");
stefanctc274c862011-06-11 09:53:22 +00002186 ichspi_lock = 1;
2187 }
David Hendricksce6b2fa2011-07-11 22:12:43 -07002188 if (tmp2 & HSFS_FDV)
stefanct3d3b6ee2011-10-20 12:57:14 +00002189 desc_valid = 1;
2190 if (!(tmp2 & HSFS_FDOPSS) && desc_valid)
Edward O'Callaghan130cade2020-07-30 15:42:35 +10002191 msg_pinfo("The Flash Descriptor Override Strap-Pin is set. Restrictions implied by\n"
2192 "the Master Section of the flash descriptor are NOT in effect. Please note\n"
2193 "that Protected Range (PR) restrictions still apply.\n");
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +10002194 ich_init_opcodes(ich_gen);
stefanctc274c862011-06-11 09:53:22 +00002195
stefanctd0064e12011-11-08 11:55:24 +00002196 if (desc_valid) {
Jack Rosenthal47a3cc92020-07-28 10:20:02 -06002197 num_fd_regions = DEFAULT_NUM_FD_REGIONS;
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002198 tmp2 = mmio_readw(spibar + ICH9_REG_HSFC);
stefanctd0064e12011-11-08 11:55:24 +00002199 msg_pdbg("0x06: 0x%04x (HSFC)\n", tmp2);
Edward O'Callaghanacce4622020-07-16 15:39:19 +10002200 prettyprint_ich9_reg_hsfc(tmp2, ich_gen);
stefanctd0064e12011-11-08 11:55:24 +00002201 }
mkarcher74d30132010-07-22 18:04:15 +00002202
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002203 tmp = mmio_readl(spibar + ICH9_REG_FADDR);
Edward O'Callaghan59919f92019-09-09 00:15:08 +10002204 msg_pdbg2("0x08: 0x%08x (FADDR)\n", tmp);
mkarcher74d30132010-07-22 18:04:15 +00002205
Edward O'Callaghan843cc8d2020-07-09 10:13:11 +10002206 switch (ich_gen) {
2207 case CHIPSET_100_SERIES_SUNRISE_POINT:
2208 case CHIPSET_C620_SERIES_LEWISBURG:
2209 case CHIPSET_300_SERIES_CANNON_POINT:
2210 case CHIPSET_APOLLO_LAKE:
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002211 tmp = mmio_readl(spibar + PCH100_REG_DLOCK);
Edward O'Callaghan843cc8d2020-07-09 10:13:11 +10002212 msg_pdbg("0x0c: 0x%08x (DLOCK)\n", tmp);
2213 prettyprint_pch100_reg_dlock(tmp);
2214 break;
2215 default:
2216 break;
2217 }
2218
stefanctd0064e12011-11-08 11:55:24 +00002219 if (desc_valid) {
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002220 tmp = mmio_readl(spibar + ICH9_REG_FRAP);
stefanctd0064e12011-11-08 11:55:24 +00002221 msg_pdbg("0x50: 0x%08x (FRAP)\n", tmp);
2222 msg_pdbg("BMWAG 0x%02x, ", ICH_BMWAG(tmp));
2223 msg_pdbg("BMRAG 0x%02x, ", ICH_BMRAG(tmp));
2224 msg_pdbg("BRWA 0x%02x, ", ICH_BRWA(tmp));
2225 msg_pdbg("BRRA 0x%02x\n", ICH_BRRA(tmp));
2226
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10002227 /* Handle FREGx and FRAP registers */
2228 for (i = 0; i < num_freg; i++)
2229 ich_spi_rw_restricted |= ich9_handle_frap(tmp, i);
2230 if (ich_spi_rw_restricted)
2231 msg_pinfo("Not all flash regions are freely accessible by flashrom. This is "
2232 "most likely\ndue to an active ME. Please see "
2233 "https://flashrom.org/ME for details.\n");
stefanctd0064e12011-11-08 11:55:24 +00002234 }
mkarcher74d30132010-07-22 18:04:15 +00002235
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10002236 /* Handle PR registers */
2237 for (i = 0; i < num_pr; i++) {
2238 /* if not locked down try to disable PR locks first */
2239 if (!ichspi_lock)
Edward O'Callaghancdd87bb2020-05-18 15:32:08 +10002240 ich9_set_pr(reg_pr0, i, 0, 0);
Edward O'Callaghan4eac7482020-05-26 21:54:52 +10002241 ich_spi_rw_restricted |= ich9_handle_pr(reg_pr0, i);
2242 }
2243
2244 switch (ich_spi_rw_restricted) {
2245 case WRITE_PROT:
2246 msg_pwarn("At least some flash regions are write protected. For write operations,\n"
2247 "you should use a flash layout and include only writable regions. See\n"
2248 "manpage for more details.\n");
2249 break;
2250 case READ_PROT:
2251 case LOCKED:
2252 msg_pwarn("At least some flash regions are read protected. You have to use a flash\n"
2253 "layout and include only accessible regions. For write operations, you'll\n"
2254 "additionally need the --noverify-all switch. See manpage for more details.\n"
2255 );
2256 break;
2257 }
hailfinger01d05912011-03-17 00:10:25 +00002258
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002259 tmp = mmio_readl(spibar + swseq_data.reg_ssfsc);
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10002260 msg_pdbg("0x%zx: 0x%02x (SSFS)\n", swseq_data.reg_ssfsc, tmp & 0xff);
stefancte4d1ef52011-06-11 09:53:16 +00002261 prettyprint_ich9_reg_ssfs(tmp);
stefanct24bda702011-06-12 08:14:10 +00002262 if (tmp & SSFS_FCERR) {
hailfinger01d05912011-03-17 00:10:25 +00002263 msg_pdbg("Clearing SSFS.FCERR\n");
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002264 mmio_writeb(SSFS_FCERR, spibar + swseq_data.reg_ssfsc);
hailfinger01d05912011-03-17 00:10:25 +00002265 }
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10002266 msg_pdbg("0x%zx: 0x%06x (SSFC)\n", swseq_data.reg_ssfsc + 1, tmp >> 8);
stefancte4d1ef52011-06-11 09:53:16 +00002267 prettyprint_ich9_reg_ssfc(tmp);
hailfinger01d05912011-03-17 00:10:25 +00002268
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10002269 msg_pdbg("0x%zx: 0x%04x (PREOP)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002270 swseq_data.reg_preop, mmio_readw(spibar + swseq_data.reg_preop));
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10002271 msg_pdbg("0x%zx: 0x%04x (OPTYPE)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002272 swseq_data.reg_optype, mmio_readw(spibar + swseq_data.reg_optype));
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10002273 msg_pdbg("0x%zx: 0x%08x (OPMENU)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002274 swseq_data.reg_opmenu, mmio_readl(spibar + swseq_data.reg_opmenu));
Edward O'Callaghan9c34b3c2020-05-18 19:02:13 +10002275 msg_pdbg("0x%zx: 0x%08x (OPMENU+4)\n",
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002276 swseq_data.reg_opmenu + 4, mmio_readl(spibar + swseq_data.reg_opmenu + 4));
David Hendricksce6b2fa2011-07-11 22:12:43 -07002277
Edward O'Callaghan469a5d72020-05-27 14:05:46 +10002278 if (desc_valid) {
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002279 switch (ich_gen) {
Edward O'Callaghan469a5d72020-05-27 14:05:46 +10002280 case CHIPSET_ICH8:
2281 case CHIPSET_100_SERIES_SUNRISE_POINT:
2282 case CHIPSET_C620_SERIES_LEWISBURG:
2283 case CHIPSET_300_SERIES_CANNON_POINT:
2284 case CHIPSET_APOLLO_LAKE:
2285 case CHIPSET_BAYTRAIL:
2286 break;
2287 default:
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002288 ichspi_bbar = mmio_readl(spibar + ICH9_REG_BBAR);
Edward O'Callaghan469a5d72020-05-27 14:05:46 +10002289 msg_pdbg("0x%x: 0x%08x (BBAR)\n", ICH9_REG_BBAR, ichspi_bbar);
Edward O'Callaghand22862f2020-07-16 15:37:26 +10002290 ich_set_bbar(0, ich_gen);
Edward O'Callaghan469a5d72020-05-27 14:05:46 +10002291 break;
2292 }
2293
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002294 if (ich_gen == CHIPSET_ICH8) {
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002295 tmp = mmio_readl(spibar + ICH8_REG_VSCC);
Edward O'Callaghan469a5d72020-05-27 14:05:46 +10002296 msg_pdbg("0x%x: 0x%08x (VSCC)\n", ICH8_REG_VSCC, tmp);
2297 msg_pdbg("VSCC: ");
2298 prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, true);
2299 } else {
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002300 tmp = mmio_readl(spibar + ICH9_REG_LVSCC);
Edward O'Callaghand757b422020-05-26 21:22:12 +10002301 msg_pdbg("0x%x: 0x%08x (LVSCC)\n", ICH9_REG_LVSCC, tmp);
stefanctd0064e12011-11-08 11:55:24 +00002302 msg_pdbg("LVSCC: ");
Edward O'Callaghand757b422020-05-26 21:22:12 +10002303 prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, true);
David Hendricksce6b2fa2011-07-11 22:12:43 -07002304
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002305 tmp = mmio_readl(spibar + ICH9_REG_UVSCC);
Edward O'Callaghand757b422020-05-26 21:22:12 +10002306 msg_pdbg("0x%x: 0x%08x (UVSCC)\n", ICH9_REG_UVSCC, tmp);
stefanctd0064e12011-11-08 11:55:24 +00002307 msg_pdbg("UVSCC: ");
Edward O'Callaghand757b422020-05-26 21:22:12 +10002308 prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, false);
Edward O'Callaghan469a5d72020-05-27 14:05:46 +10002309 }
David Hendricksce6b2fa2011-07-11 22:12:43 -07002310
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002311 switch (ich_gen) {
Edward O'Callaghan469a5d72020-05-27 14:05:46 +10002312 case CHIPSET_ICH8:
2313 case CHIPSET_100_SERIES_SUNRISE_POINT:
2314 case CHIPSET_C620_SERIES_LEWISBURG:
2315 case CHIPSET_300_SERIES_CANNON_POINT:
2316 case CHIPSET_APOLLO_LAKE:
2317 break;
2318 default:
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002319 tmp = mmio_readl(spibar + ICH9_REG_FPB);
Edward O'Callaghand757b422020-05-26 21:22:12 +10002320 msg_pdbg("0x%x: 0x%08x (FPB)\n", ICH9_REG_FPB, tmp);
Edward O'Callaghan469a5d72020-05-27 14:05:46 +10002321 break;
stefanctd0064e12011-11-08 11:55:24 +00002322 }
stefanctd68db982011-07-01 00:39:16 +00002323
Edward O'Callaghan1f11b162020-07-16 17:14:01 +10002324 if (read_ich_descriptors_via_fdo(ich_gen, spibar, &desc) == ICH_RET_OK)
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002325 prettyprint_ich_descriptors(ich_gen, &desc);
Edward O'Callaghand757b422020-05-26 21:22:12 +10002326
stefanct83d99e82011-11-08 10:55:54 +00002327 /* If the descriptor is valid and indicates multiple
2328 * flash devices we need to use hwseq to be able to
2329 * access the second flash device.
2330 */
2331 if (ich_spi_mode == ich_auto && desc.content.NC != 0) {
2332 msg_pinfo("Enabling hardware sequencing due to "
2333 "multiple flash chips detected.\n");
2334 ich_spi_mode = ich_hwseq;
2335 }
David Hendricksce6b2fa2011-07-11 22:12:43 -07002336 }
stefanct83d99e82011-11-08 10:55:54 +00002337
2338 if (ich_spi_mode == ich_auto && ichspi_lock &&
2339 ich_missing_opcodes()) {
2340 msg_pinfo("Enabling hardware sequencing because "
2341 "some important opcode is locked.\n");
2342 ich_spi_mode = ich_hwseq;
2343 }
2344
Edward O'Callaghan0c1a3c92020-08-03 15:01:03 +10002345 if (ich_spi_mode == ich_auto) {
2346 switch(ich_gen) {
2347 case CHIPSET_100_SERIES_SUNRISE_POINT:
2348 case CHIPSET_300_SERIES_CANNON_POINT:
2349 case CHIPSET_APOLLO_LAKE:
2350 msg_pdbg("Enabling hardware sequencing by default "
2351 "for 100+ series PCH.\n");
2352 ich_spi_mode = ich_hwseq;
2353 break;
2354 default:
2355 break;
2356 }
2357 }
2358
Edward O'Callaghanea6ab742020-08-03 15:13:59 +10002359 switch(ich_gen) {
2360 case CHIPSET_APOLLO_LAKE:
2361 num_fd_regions = APL_GLK_NUM_FD_REGIONS;
2362 break;
2363 case CHIPSET_100_SERIES_SUNRISE_POINT:
2364 num_fd_regions = SUNRISEPOINT_NUM_FD_REGIONS;
2365 break;
2366 default:
2367 num_fd_regions = DEFAULT_NUM_FD_REGIONS;
2368 break;
2369 }
2370
stefanct83d99e82011-11-08 10:55:54 +00002371 if (ich_spi_mode == ich_hwseq) {
2372 if (!desc_valid) {
2373 msg_perr("Hardware sequencing was requested "
2374 "but the flash descriptor is not "
2375 "valid. Aborting.\n");
2376 return ERROR_FATAL;
2377 }
Edward O'Callaghane0845d72020-07-05 13:28:03 +10002378
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002379 int tmpi = getFCBA_component_density(ich_gen, &desc, 0);
Edward O'Callaghane0845d72020-07-05 13:28:03 +10002380 if (tmpi < 0) {
2381 msg_perr("Could not determine density of flash component %d.\n", 0);
2382 return ERROR_FATAL;
2383 }
2384 hwseq_data.size_comp0 = tmpi;
2385
Edward O'Callaghan397256f2020-07-09 09:59:32 +10002386 tmpi = getFCBA_component_density(ich_gen, &desc, 1);
Edward O'Callaghane0845d72020-07-05 13:28:03 +10002387 if (tmpi < 0) {
2388 msg_perr("Could not determine density of flash component %d.\n", 1);
2389 return ERROR_FATAL;
2390 }
2391 hwseq_data.size_comp1 = tmpi;
2392
Edward O'Callaghanabd30192019-05-14 15:58:19 +10002393 register_opaque_master(&opaque_master_ich_hwseq);
stefanct83d99e82011-11-08 10:55:54 +00002394 } else {
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002395 register_spi_master(&spi_master_ich9);
stefanct83d99e82011-11-08 10:55:54 +00002396 }
stefanct1fc3a732011-09-15 23:52:55 +00002397 break;
mkarcher74d30132010-07-22 18:04:15 +00002398 }
2399
mkarcher74d30132010-07-22 18:04:15 +00002400 return 0;
2401}
2402
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002403static const struct spi_master spi_master_via = {
mkarcherd264e9e2011-05-11 17:07:07 +00002404 .max_data_read = 16,
2405 .max_data_write = 16,
2406 .command = ich_spi_send_command,
2407 .multicommand = ich_spi_send_multicommand,
2408 .read = default_spi_read,
2409 .write_256 = default_spi_write_256,
Edward O'Callaghaneeaac6b2020-10-12 19:51:56 +11002410 .write_aai = default_spi_write_aai,
mkarcherd264e9e2011-05-11 17:07:07 +00002411};
2412
Edward O'Callaghan3300e4e2019-10-03 13:20:09 +10002413int via_init_spi(uint32_t mmio_base)
mkarcher74d30132010-07-22 18:04:15 +00002414{
hailfinger8fdd0a82010-11-24 23:37:22 +00002415 int i;
mkarcher74d30132010-07-22 18:04:15 +00002416
Edward O'Callaghand757b422020-05-26 21:22:12 +10002417 ich_spibar = rphysmap("VIA SPI MMIO registers", mmio_base, 0x70);
Edward O'Callaghanb9370cc2019-10-03 13:08:49 +10002418 if (ich_spibar == ERROR_PTR)
2419 return ERROR_FATAL;
Edward O'Callaghand757b422020-05-26 21:22:12 +10002420 /* Do we really need no write enable? Like the LPC one at D17F0 0x40 */
mkarcher74d30132010-07-22 18:04:15 +00002421
mkarcher74d30132010-07-22 18:04:15 +00002422 /* Not sure if it speaks all these bus protocols. */
Edward O'Callaghan26bf5c42019-08-02 23:28:03 +10002423 internal_buses_supported &= BUS_LPC | BUS_FWH;
Edward O'Callaghane3e30562019-09-03 13:10:58 +10002424 g_ich_generation = CHIPSET_ICH7;
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002425 register_spi_master(&spi_master_via);
hailfinger8fdd0a82010-11-24 23:37:22 +00002426
2427 msg_pdbg("0x00: 0x%04x (SPIS)\n", mmio_readw(ich_spibar + 0));
2428 msg_pdbg("0x02: 0x%04x (SPIC)\n", mmio_readw(ich_spibar + 2));
2429 msg_pdbg("0x04: 0x%08x (SPIA)\n", mmio_readl(ich_spibar + 4));
2430 for (i = 0; i < 2; i++) {
2431 int offs;
2432 offs = 8 + (i * 8);
2433 msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs,
2434 mmio_readl(ich_spibar + offs), i);
2435 msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4,
2436 mmio_readl(ich_spibar + offs + 4), i);
2437 }
2438 ichspi_bbar = mmio_readl(ich_spibar + 0x50);
2439 msg_pdbg("0x50: 0x%08x (BBAR)\n", ichspi_bbar);
2440 msg_pdbg("0x54: 0x%04x (PREOP)\n", mmio_readw(ich_spibar + 0x54));
2441 msg_pdbg("0x56: 0x%04x (OPTYPE)\n", mmio_readw(ich_spibar + 0x56));
2442 msg_pdbg("0x58: 0x%08x (OPMENU)\n", mmio_readl(ich_spibar + 0x58));
2443 msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n", mmio_readl(ich_spibar + 0x5c));
2444 for (i = 0; i < 3; i++) {
2445 int offs;
2446 offs = 0x60 + (i * 4);
2447 msg_pdbg("0x%02x: 0x%08x (PBR%d)\n", offs,
2448 mmio_readl(ich_spibar + offs), i);
2449 }
2450 msg_pdbg("0x6c: 0x%04x (CLOCK/DEBUG)\n",
2451 mmio_readw(ich_spibar + 0x6c));
2452 if (mmio_readw(ich_spibar) & (1 << 15)) {
Edward O'Callaghan59919f92019-09-09 00:15:08 +10002453 msg_pwarn("Warning: SPI Configuration Lockdown activated.\n");
hailfinger8fdd0a82010-11-24 23:37:22 +00002454 ichspi_lock = 1;
2455 }
2456
Edward O'Callaghand22862f2020-07-16 15:37:26 +10002457 ich_set_bbar(0, g_ich_generation);
Edward O'Callaghan6884e4f2020-07-16 15:35:00 +10002458 ich_init_opcodes(g_ich_generation);
mkarcher74d30132010-07-22 18:04:15 +00002459
2460 return 0;
2461}
2462
hailfinger324a9cc2010-05-26 01:45:41 +00002463#endif