blob: 8e675c3a2940f06fae70951d639c20b7f4438d2c [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.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
hailfinger82e7ddb2008-05-16 12:55:55 +000024 */
25
stefanctfa66c622011-08-09 01:49:34 +000026#if defined(__i386__) || defined(__x86_64__)
hailfinger324a9cc2010-05-26 01:45:41 +000027
hailfinger82e7ddb2008-05-16 12:55:55 +000028#include <string.h>
stefanct3d3b6ee2011-10-20 12:57:14 +000029#include <stdlib.h>
hailfinger82e7ddb2008-05-16 12:55:55 +000030#include "flash.h"
hailfinger428f6852010-07-27 22:41:39 +000031#include "programmer.h"
hailfinger82e7ddb2008-05-16 12:55:55 +000032#include "spi.h"
David Hendricksce6b2fa2011-07-11 22:12:43 -070033#include "ich_descriptors.h"
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +053034#include "chipdrivers.h"
hailfinger82e7ddb2008-05-16 12:55:55 +000035
stepandbd3af12008-06-27 16:28:34 +000036/* ICH9 controller register definition */
stefanctc274c862011-06-11 09:53:22 +000037#define ICH9_REG_HSFS 0x04 /* 16 Bits Hardware Sequencing Flash Status */
38#define HSFS_FDONE_OFF 0 /* 0: Flash Cycle Done */
39#define HSFS_FDONE (0x1 << HSFS_FDONE_OFF)
40#define HSFS_FCERR_OFF 1 /* 1: Flash Cycle Error */
41#define HSFS_FCERR (0x1 << HSFS_FCERR_OFF)
42#define HSFS_AEL_OFF 2 /* 2: Access Error Log */
43#define HSFS_AEL (0x1 << HSFS_AEL_OFF)
44#define HSFS_BERASE_OFF 3 /* 3-4: Block/Sector Erase Size */
45#define HSFS_BERASE (0x3 << HSFS_BERASE_OFF)
46#define HSFS_SCIP_OFF 5 /* 5: SPI Cycle In Progress */
47#define HSFS_SCIP (0x1 << HSFS_SCIP_OFF)
48 /* 6-12: reserved */
49#define HSFS_FDOPSS_OFF 13 /* 13: Flash Descriptor Override Pin-Strap Status */
50#define HSFS_FDOPSS (0x1 << HSFS_FDOPSS_OFF)
51#define HSFS_FDV_OFF 14 /* 14: Flash Descriptor Valid */
52#define HSFS_FDV (0x1 << HSFS_FDV_OFF)
53#define HSFS_FLOCKDN_OFF 15 /* 15: Flash Configuration Lock-Down */
54#define HSFS_FLOCKDN (0x1 << HSFS_FLOCKDN_OFF)
55
56#define ICH9_REG_HSFC 0x06 /* 16 Bits Hardware Sequencing Flash Control */
57#define HSFC_FGO_OFF 0 /* 0: Flash Cycle Go */
58#define HSFC_FGO (0x1 << HSFC_FGO_OFF)
59#define HSFC_FCYCLE_OFF 1 /* 1-2: FLASH Cycle */
60#define HSFC_FCYCLE (0x3 << HSFC_FCYCLE_OFF)
61 /* 3-7: reserved */
62#define HSFC_FDBC_OFF 8 /* 8-13: Flash Data Byte Count */
63#define HSFC_FDBC (0x3f << HSFC_FDBC_OFF)
64 /* 14: reserved */
65#define HSFC_SME_OFF 15 /* 15: SPI SMI# Enable */
66#define HSFC_SME (0x1 << HSFC_SME_OFF)
67
stefanct707f13b2011-05-19 02:58:17 +000068#define ICH9_REG_FADDR 0x08 /* 32 Bits */
69#define ICH9_REG_FDATA0 0x10 /* 64 Bytes */
stepandbd3af12008-06-27 16:28:34 +000070
stefanct24bda702011-06-12 08:14:10 +000071#define ICH9_REG_FRAP 0x50 /* 32 Bytes Flash Region Access Permissions */
72#define ICH9_REG_FREG0 0x54 /* 32 Bytes Flash Region 0 */
73
74#define ICH9_REG_PR0 0x74 /* 32 Bytes Protected Range 0 */
stefanct7ab834a2011-09-17 21:21:48 +000075#define PR_WP_OFF 31 /* 31: write protection enable */
76#define PR_RP_OFF 15 /* 15: read protection enable */
stefanct24bda702011-06-12 08:14:10 +000077
stefanct707f13b2011-05-19 02:58:17 +000078#define ICH9_REG_SSFS 0x90 /* 08 Bits */
stefanct04009ff2011-06-11 09:53:09 +000079#define SSFS_SCIP_OFF 0 /* SPI Cycle In Progress */
80#define SSFS_SCIP (0x1 << SSFS_SCIP_OFF)
81#define SSFS_FDONE_OFF 2 /* Cycle Done Status */
82#define SSFS_FDONE (0x1 << SSFS_FDONE_OFF)
83#define SSFS_FCERR_OFF 3 /* Flash Cycle Error */
84#define SSFS_FCERR (0x1 << SSFS_FCERR_OFF)
85#define SSFS_AEL_OFF 4 /* Access Error Log */
86#define SSFS_AEL (0x1 << SSFS_AEL_OFF)
stefanct707f13b2011-05-19 02:58:17 +000087/* The following bits are reserved in SSFS: 1,5-7. */
hailfinger01d05912011-03-17 00:10:25 +000088#define SSFS_RESERVED_MASK 0x000000e2
stepandbd3af12008-06-27 16:28:34 +000089
stefanct707f13b2011-05-19 02:58:17 +000090#define ICH9_REG_SSFC 0x91 /* 24 Bits */
stefanct707f13b2011-05-19 02:58:17 +000091/* We combine SSFS and SSFC to one 32-bit word,
stefanct04009ff2011-06-11 09:53:09 +000092 * therefore SSFC bits are off by 8. */
93 /* 0: reserved */
94#define SSFC_SCGO_OFF (1 + 8) /* 1: SPI Cycle Go */
95#define SSFC_SCGO (0x1 << SSFC_SCGO_OFF)
96#define SSFC_ACS_OFF (2 + 8) /* 2: Atomic Cycle Sequence */
97#define SSFC_ACS (0x1 << SSFC_ACS_OFF)
98#define SSFC_SPOP_OFF (3 + 8) /* 3: Sequence Prefix Opcode Pointer */
99#define SSFC_SPOP (0x1 << SSFC_SPOP_OFF)
100#define SSFC_COP_OFF (4 + 8) /* 4-6: Cycle Opcode Pointer */
101#define SSFC_COP (0x7 << SSFC_COP_OFF)
102 /* 7: reserved */
103#define SSFC_DBC_OFF (8 + 8) /* 8-13: Data Byte Count */
104#define SSFC_DBC (0x3f << SSFC_DBC_OFF)
105#define SSFC_DS_OFF (14 + 8) /* 14: Data Cycle */
106#define SSFC_DS (0x1 << SSFC_DS_OFF)
107#define SSFC_SME_OFF (15 + 8) /* 15: SPI SMI# Enable */
108#define SSFC_SME (0x1 << SSFC_SME_OFF)
109#define SSFC_SCF_OFF (16 + 8) /* 16-18: SPI Cycle Frequency */
110#define SSFC_SCF (0x7 << SSFC_SCF_OFF)
111#define SSFC_SCF_20MHZ 0x00000000
112#define SSFC_SCF_33MHZ 0x01000000
113 /* 19-23: reserved */
hailfinger01d05912011-03-17 00:10:25 +0000114#define SSFC_RESERVED_MASK 0xf8008100
stepandbd3af12008-06-27 16:28:34 +0000115
stefanct707f13b2011-05-19 02:58:17 +0000116#define ICH9_REG_PREOP 0x94 /* 16 Bits */
117#define ICH9_REG_OPTYPE 0x96 /* 16 Bits */
118#define ICH9_REG_OPMENU 0x98 /* 64 Bits */
hailfinger82e7ddb2008-05-16 12:55:55 +0000119
stefanct24bda702011-06-12 08:14:10 +0000120#define ICH9_REG_BBAR 0xA0 /* 32 Bits BIOS Base Address Configuration */
121#define BBAR_MASK 0x00ffff00 /* 8-23: Bottom of System Flash */
122
stefanct1fc3a732011-09-15 23:52:55 +0000123#define ICH8_REG_VSCC 0xC1 /* 32 Bits Vendor Specific Component Capabilities */
David Hendricksce6b2fa2011-07-11 22:12:43 -0700124#define ICH9_REG_LVSCC 0xC4 /* 32 Bits Host Lower Vendor Specific Component Capabilities */
125#define ICH9_REG_UVSCC 0xC8 /* 32 Bits Host Upper Vendor Specific Component Capabilities */
126/* The individual fields of the VSCC registers are defined in the file
stefanct1fc3a732011-09-15 23:52:55 +0000127 * ich_descriptors.h. The reason is that the same layout is also used in the
128 * flash descriptor to define the properties of the different flash chips
129 * supported. The BIOS (or the ME?) is responsible to populate the ICH registers
130 * with the information from the descriptor on startup depending on the actual
131 * chip(s) detected. */
David Hendricksce6b2fa2011-07-11 22:12:43 -0700132
stefanctd68db982011-07-01 00:39:16 +0000133#define ICH9_REG_FPB 0xD0 /* 32 Bits Flash Partition Boundary */
134#define FPB_FPBA_OFF 0 /* 0-12: Block/Sector Erase Size */
135#define FPB_FPBA (0x1FFF << FPB_FPBA_OFF)
136
David Hendricks210975e2015-08-25 21:36:13 +0000137// ICH9R SPI commands
138#define SPI_OPCODE_TYPE_READ_NO_ADDRESS 0
139#define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS 1
140#define SPI_OPCODE_TYPE_READ_WITH_ADDRESS 2
141#define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS 3
142
stepandbd3af12008-06-27 16:28:34 +0000143// ICH7 registers
stefanct707f13b2011-05-19 02:58:17 +0000144#define ICH7_REG_SPIS 0x00 /* 16 Bits */
hailfinger01d05912011-03-17 00:10:25 +0000145#define SPIS_SCIP 0x0001
146#define SPIS_GRANT 0x0002
147#define SPIS_CDS 0x0004
148#define SPIS_FCERR 0x0008
149#define SPIS_RESERVED_MASK 0x7ff0
stepandbd3af12008-06-27 16:28:34 +0000150
ruik9bc51c02008-06-30 21:38:30 +0000151/* VIA SPI is compatible with ICH7, but maxdata
152 to transfer is 16 bytes.
153
154 DATA byte count on ICH7 is 8:13, on VIA 8:11
155
156 bit 12 is port select CS0 CS1
157 bit 13 is FAST READ enable
158 bit 7 is used with fast read and one shot controls CS de-assert?
159*/
160
stefanct707f13b2011-05-19 02:58:17 +0000161#define ICH7_REG_SPIC 0x02 /* 16 Bits */
162#define SPIC_SCGO 0x0002
163#define SPIC_ACS 0x0004
164#define SPIC_SPOP 0x0008
165#define SPIC_DS 0x4000
stepandbd3af12008-06-27 16:28:34 +0000166
stefanct707f13b2011-05-19 02:58:17 +0000167#define ICH7_REG_SPIA 0x04 /* 32 Bits */
168#define ICH7_REG_SPID0 0x08 /* 64 Bytes */
169#define ICH7_REG_PREOP 0x54 /* 16 Bits */
170#define ICH7_REG_OPTYPE 0x56 /* 16 Bits */
171#define ICH7_REG_OPMENU 0x58 /* 64 Bits */
stepandbd3af12008-06-27 16:28:34 +0000172
David Hendricks7be91492016-12-27 18:43:45 -0800173/* Sunrise Point (100-series PCH) */
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +0530174/* 32 Bits Hardware Sequencing Flash Status */
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +0530175#define PCH100_REG_HSFSC 0x04
David Hendricks7be91492016-12-27 18:43:45 -0800176/* Status bits */
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +0530177#define HSFSC_FDONE_OFF 0 /* 0: Flash Cycle Done */
178#define HSFSC_FDONE (0x1 << HSFSC_FDONE_OFF)
179#define HSFSC_FCERR_OFF 1 /* 1: Flash Cycle Error */
180#define HSFSC_FCERR (0x1 << HSFSC_FCERR_OFF)
181#define HSFSC_AEL_OFF 2 /* 2: Access Error Log */
182#define HSFSC_AEL (0x1 << HSFSC_AEL_OFF)
183#define HSFSC_SCIP_OFF 5 /* 5: SPI Cycle In Progress */
184#define HSFSC_SCIP (0x1 << HSFSC_SCIP_OFF)
185 /* 6-10: reserved */
186/* 11: Flash Configuration Lock-Down WRSDIS */
187#define HSFSC_WRSDIS_OFF 11
188#define HSFSC_WRSDIS (0x1 << HSFSC_WRSDIS_OFF)
189#define HSFSC_PRR34LCKDN_OFF 12
190#define HSFSC_PRR34LCKDN (0x1 << HSFSC_PRR34LCKDN_OFF)
191/* 13: Flash Descriptor Override Pin-Strap Status */
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +0530192#define HSFSC_FDOPSS_OFF 13
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +0530193#define HSFSC_FDOPSS (0x1 << HSFSC_FDOPSS_OFF)
194#define HSFSC_FDV_OFF 14 /* 14: Flash Descriptor Valid */
195#define HSFSC_FDV (0x1 << HSFSC_FDV_OFF)
196#define HSFSC_FLOCKDN_OFF 15 /* 11: Flash Configuration Lock-Down */
197#define HSFSC_FLOCKDN (0x1 << HSFSC_FLOCKDN_OFF)
David Hendricks7be91492016-12-27 18:43:45 -0800198/* Control bits */
199#define HSFSC_FGO_OFF 16 /* 0: Flash Cycle Go */
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +0530200#define HSFSC_FGO (0x1 << HSFSC_FGO_OFF)
David Hendricks7be91492016-12-27 18:43:45 -0800201#define HSFSC_FCYCLE_OFF 17 /* 17-20: FLASH Cycle */
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +0530202#define HSFSC_FCYCLE (0xf << HSFSC_FCYCLE_OFF)
David Hendricks7be91492016-12-27 18:43:45 -0800203#define HSFSC_FDBC_OFF 24 /* 24-29 : Flash Data Byte Count */
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +0530204#define HSFSC_FDBC (0x3f << HSFSC_FDBC_OFF)
205
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +0530206#define PCH100_REG_FADDR 0x08 /* 32 Bits */
207#define PCH100_REG_FDATA0 0x10 /* 64 Bytes */
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +0530208
209#define PCH100_REG_FPR0 0x84 /* 32 Bytes Protected Range 0 */
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +0530210#define PCH100_WP_OFF 31 /* 31: write protection enable */
211#define PCH100_RP_OFF 15 /* 15: read protection enable */
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +0530212
213/* The minimum erase block size in PCH which is 4k
214* 256,
215* 4 * 1024,
216* 8 * 1024,
217* 64 * 1024
218*/
219#define ERASE_BLOCK_SIZE 1
Ramya Vijaykumar71d69ad2015-10-01 11:26:40 +0530220#define HWSEQ_READ 0
221#define HWSEQ_WRITE 1
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +0530222
stepane1a13b92008-12-08 18:16:58 +0000223/* ICH SPI configuration lock-down. May be set during chipset enabling. */
mkarcher74d30132010-07-22 18:04:15 +0000224static int ichspi_lock = 0;
stepane1a13b92008-12-08 18:16:58 +0000225
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +0530226enum ich_chipset ich_generation = CHIPSET_ICH_UNKNOWN;
hailfingerb767c122010-05-28 15:53:08 +0000227uint32_t ichspi_bbar = 0;
228
mkarcher74d30132010-07-22 18:04:15 +0000229static void *ich_spibar = NULL;
hailfinger1ff33dc2010-07-03 11:02:10 +0000230
David Hendricks210975e2015-08-25 21:36:13 +0000231typedef struct _OPCODE {
232 uint8_t opcode; //This commands spi opcode
233 uint8_t spi_type; //This commands spi type
234 uint8_t atomic; //Use preop: (0: none, 1: preop0, 2: preop1
235} OPCODE;
236
hailfinger82e32492010-02-11 11:28:37 +0000237/* Suggested opcode definition:
hailfinger82e7ddb2008-05-16 12:55:55 +0000238 * Preop 1: Write Enable
239 * Preop 2: Write Status register enable
240 *
241 * OP 0: Write address
242 * OP 1: Read Address
243 * OP 2: ERASE block
244 * OP 3: Read Status register
245 * OP 4: Read ID
246 * OP 5: Write Status register
hailfinger82e32492010-02-11 11:28:37 +0000247 * OP 6: chip private (read JEDEC id)
hailfinger82e7ddb2008-05-16 12:55:55 +0000248 * OP 7: Chip erase
249 */
250typedef struct _OPCODES {
251 uint8_t preop[2];
252 OPCODE opcode[8];
253} OPCODES;
254
stepan8f46dd62008-06-27 15:18:20 +0000255static OPCODES *curopcodes = NULL;
hailfinger82e7ddb2008-05-16 12:55:55 +0000256
257/* HW access functions */
uweabe92a52009-05-16 22:36:00 +0000258static uint32_t REGREAD32(int X)
hailfinger82e7ddb2008-05-16 12:55:55 +0000259{
hailfinger1ff33dc2010-07-03 11:02:10 +0000260 return mmio_readl(ich_spibar + X);
stepandbd3af12008-06-27 16:28:34 +0000261}
262
uweabe92a52009-05-16 22:36:00 +0000263static uint16_t REGREAD16(int X)
stepandbd3af12008-06-27 16:28:34 +0000264{
hailfinger1ff33dc2010-07-03 11:02:10 +0000265 return mmio_readw(ich_spibar + X);
hailfinger82e7ddb2008-05-16 12:55:55 +0000266}
267
hailfinger01d05912011-03-17 00:10:25 +0000268static uint16_t REGREAD8(int X)
269{
270 return mmio_readb(ich_spibar + X);
271}
272
stefanct15f3b932011-07-01 00:39:01 +0000273#define REGWRITE32(off, val) mmio_writel(val, ich_spibar+(off))
274#define REGWRITE16(off, val) mmio_writew(val, ich_spibar+(off))
275#define REGWRITE8(off, val) mmio_writeb(val, ich_spibar+(off))
hailfinger82e7ddb2008-05-16 12:55:55 +0000276
hailfinger82e7ddb2008-05-16 12:55:55 +0000277/* Common SPI functions */
uweabe92a52009-05-16 22:36:00 +0000278static int find_opcode(OPCODES *op, uint8_t opcode);
279static int find_preop(OPCODES *op, uint8_t preop);
stuge7a651552008-12-15 02:32:11 +0000280static int generate_opcodes(OPCODES * op);
hailfinger1e2e3442011-05-03 21:49:41 +0000281static int program_opcodes(OPCODES *op, int enable_undo);
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700282static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset,
stepan8f46dd62008-06-27 15:18:20 +0000283 uint8_t datalength, uint8_t * data);
hailfinger82e7ddb2008-05-16 12:55:55 +0000284
stuge7a651552008-12-15 02:32:11 +0000285/* for pairing opcodes with their required preop */
286struct preop_opcode_pair {
287 uint8_t preop;
288 uint8_t opcode;
289};
290
hailfinger82e32492010-02-11 11:28:37 +0000291/* List of opcodes which need preopcodes and matching preopcodes. Unused. */
hailfinger1ff33dc2010-07-03 11:02:10 +0000292const struct preop_opcode_pair pops[] = {
stuge7a651552008-12-15 02:32:11 +0000293 {JEDEC_WREN, JEDEC_BYTE_PROGRAM},
294 {JEDEC_WREN, JEDEC_SE}, /* sector erase */
295 {JEDEC_WREN, JEDEC_BE_52}, /* block erase */
296 {JEDEC_WREN, JEDEC_BE_D8}, /* block erase */
297 {JEDEC_WREN, JEDEC_CE_60}, /* chip erase */
298 {JEDEC_WREN, JEDEC_CE_C7}, /* chip erase */
hailfinger82e32492010-02-11 11:28:37 +0000299 /* FIXME: WRSR requires either EWSR or WREN depending on chip type. */
300 {JEDEC_WREN, JEDEC_WRSR},
stuge7a651552008-12-15 02:32:11 +0000301 {JEDEC_EWSR, JEDEC_WRSR},
302 {0,}
303};
304
hailfinger82e32492010-02-11 11:28:37 +0000305/* Reasonable default configuration. Needs ad-hoc modifications if we
306 * encounter unlisted opcodes. Fun.
307 */
hailfinger1ff33dc2010-07-03 11:02:10 +0000308static OPCODES O_ST_M25P = {
hailfinger82e7ddb2008-05-16 12:55:55 +0000309 {
310 JEDEC_WREN,
hailfinger82e32492010-02-11 11:28:37 +0000311 JEDEC_EWSR,
312 },
hailfinger82e7ddb2008-05-16 12:55:55 +0000313 {
hailfinger82e32492010-02-11 11:28:37 +0000314 {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Write Byte
stepan8f46dd62008-06-27 15:18:20 +0000315 {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data
David Hendricks813dd7a2010-08-26 21:27:17 -0700316 {JEDEC_SE, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Erase Sector
stepan8f46dd62008-06-27 15:18:20 +0000317 {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read Device Status Reg
hailfingere092f842009-05-26 21:25:08 +0000318 {JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Electronic Manufacturer Signature
hailfinger82e32492010-02-11 11:28:37 +0000319 {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Write Status Register
stepan8f46dd62008-06-27 15:18:20 +0000320 {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read JDEC ID
hailfinger82e32492010-02-11 11:28:37 +0000321 {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Bulk erase
322 }
hailfinger82e7ddb2008-05-16 12:55:55 +0000323};
324
hailfinger4c973122010-10-05 22:06:05 +0000325/* List of opcodes with their corresponding spi_type
326 * It is used to reprogram the chipset OPCODE table on-the-fly if an opcode
327 * is needed which is currently not in the chipset OPCODE table
328 */
329static OPCODE POSSIBLE_OPCODES[] = {
330 {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Write Byte
331 {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data
332 {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Erase Sector
333 {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read Device Status Reg
334 {JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Electronic Manufacturer Signature
335 {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Write Status Register
336 {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read JDEC ID
337 {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Bulk erase
338 {JEDEC_SE, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Sector erase
339 {JEDEC_BE_52, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Block erase
340 {JEDEC_AAI_WORD_PROGRAM, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Auto Address Increment
341};
342
hailfinger1ff33dc2010-07-03 11:02:10 +0000343static OPCODES O_EXISTING = {};
stepane1a13b92008-12-08 18:16:58 +0000344
stefancte4d1ef52011-06-11 09:53:16 +0000345/* pretty printing functions */
David Hendricksce6b2fa2011-07-11 22:12:43 -0700346static void prettyprint_opcodes(OPCODES *ops)
stefancte4d1ef52011-06-11 09:53:16 +0000347{
stefanct0aaebc42011-09-17 19:53:11 +0000348 OPCODE oc;
349 const char *t;
350 const char *a;
351 uint8_t i;
352 static const char *const spi_type[4] = {
353 "read w/o addr",
354 "write w/o addr",
355 "read w/ addr",
356 "write w/ addr"
357 };
358 static const char *const atomic_type[3] = {
359 "none",
360 " 0 ",
361 " 1 "
362 };
363
364 if (ops == NULL)
stefancte4d1ef52011-06-11 09:53:16 +0000365 return;
366
stefanct0aaebc42011-09-17 19:53:11 +0000367 msg_pdbg2(" OP Type Pre-OP\n");
stefancte4d1ef52011-06-11 09:53:16 +0000368 for (i = 0; i < 8; i++) {
369 oc = ops->opcode[i];
stefanct0aaebc42011-09-17 19:53:11 +0000370 t = (oc.spi_type > 3) ? "invalid" : spi_type[oc.spi_type];
371 a = (oc.atomic > 2) ? "invalid" : atomic_type[oc.atomic];
372 msg_pdbg2("op[%d]: 0x%02x, %s, %s\n", i, oc.opcode, t, a);
stefancte4d1ef52011-06-11 09:53:16 +0000373 }
stefanct0aaebc42011-09-17 19:53:11 +0000374 msg_pdbg2("Pre-OP 0: 0x%02x, Pre-OP 1: 0x%02x\n", ops->preop[0],
375 ops->preop[1]);
stefancte4d1ef52011-06-11 09:53:16 +0000376}
377
stefanct1fc3a732011-09-15 23:52:55 +0000378#define pprint_reg(reg, bit, val, sep) msg_pdbg("%s=%d" sep, #bit, (val & reg##_##bit)>>reg##_##bit##_OFF)
379
stefanctc274c862011-06-11 09:53:22 +0000380static void prettyprint_ich9_reg_hsfs(uint16_t reg_val)
381{
382 msg_pdbg("HSFS: ");
383 pprint_reg(HSFS, FDONE, reg_val, ", ");
384 pprint_reg(HSFS, FCERR, reg_val, ", ");
385 pprint_reg(HSFS, AEL, reg_val, ", ");
386 pprint_reg(HSFS, BERASE, reg_val, ", ");
387 pprint_reg(HSFS, SCIP, reg_val, ", ");
388 pprint_reg(HSFS, FDOPSS, reg_val, ", ");
389 pprint_reg(HSFS, FDV, reg_val, ", ");
390 pprint_reg(HSFS, FLOCKDN, reg_val, "\n");
391}
392
393static void prettyprint_ich9_reg_hsfc(uint16_t reg_val)
394{
395 msg_pdbg("HSFC: ");
396 pprint_reg(HSFC, FGO, reg_val, ", ");
397 pprint_reg(HSFC, FCYCLE, reg_val, ", ");
398 pprint_reg(HSFC, FDBC, reg_val, ", ");
399 pprint_reg(HSFC, SME, reg_val, "\n");
400}
401
stefancte4d1ef52011-06-11 09:53:16 +0000402static void prettyprint_ich9_reg_ssfs(uint32_t reg_val)
403{
404 msg_pdbg("SSFS: ");
405 pprint_reg(SSFS, SCIP, reg_val, ", ");
406 pprint_reg(SSFS, FDONE, reg_val, ", ");
407 pprint_reg(SSFS, FCERR, reg_val, ", ");
408 pprint_reg(SSFS, AEL, reg_val, "\n");
409}
410
411static void prettyprint_ich9_reg_ssfc(uint32_t reg_val)
412{
413 msg_pdbg("SSFC: ");
414 pprint_reg(SSFC, SCGO, reg_val, ", ");
415 pprint_reg(SSFC, ACS, reg_val, ", ");
416 pprint_reg(SSFC, SPOP, reg_val, ", ");
417 pprint_reg(SSFC, COP, reg_val, ", ");
418 pprint_reg(SSFC, DBC, reg_val, ", ");
419 pprint_reg(SSFC, SME, reg_val, ", ");
420 pprint_reg(SSFC, SCF, reg_val, "\n");
421}
422
hailfinger4c973122010-10-05 22:06:05 +0000423static uint8_t lookup_spi_type(uint8_t opcode)
424{
425 int a;
426
uwe8d342eb2011-07-28 08:13:25 +0000427 for (a = 0; a < ARRAY_SIZE(POSSIBLE_OPCODES); a++) {
hailfinger4c973122010-10-05 22:06:05 +0000428 if (POSSIBLE_OPCODES[a].opcode == opcode)
429 return POSSIBLE_OPCODES[a].spi_type;
430 }
431
432 return 0xFF;
433}
434
435static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, unsigned int readcnt)
436{
437 uint8_t spi_type;
438
439 spi_type = lookup_spi_type(opcode);
440 if (spi_type > 3) {
441 /* Try to guess spi type from read/write sizes.
442 * The following valid writecnt/readcnt combinations exist:
443 * writecnt = 4, readcnt >= 0
444 * writecnt = 1, readcnt >= 0
445 * writecnt >= 4, readcnt = 0
446 * writecnt >= 1, readcnt = 0
447 * writecnt >= 1 is guaranteed for all commands.
448 */
449 if (readcnt == 0)
450 /* if readcnt=0 and writecount >= 4, we don't know if it is WRITE_NO_ADDRESS
451 * or WRITE_WITH_ADDRESS. But if we use WRITE_NO_ADDRESS and the first 3 data
452 * bytes are actual the address, they go to the bus anyhow
453 */
454 spi_type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
455 else if (writecnt == 1) // and readcnt is > 0
456 spi_type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
457 else if (writecnt == 4) // and readcnt is > 0
458 spi_type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
459 // else we have an invalid case, will be handled below
460 }
461 if (spi_type <= 3) {
462 int oppos=2; // use original JEDEC_BE_D8 offset
463 curopcodes->opcode[oppos].opcode = opcode;
464 curopcodes->opcode[oppos].spi_type = spi_type;
hailfinger1e2e3442011-05-03 21:49:41 +0000465 program_opcodes(curopcodes, 0);
hailfinger4c973122010-10-05 22:06:05 +0000466 oppos = find_opcode(curopcodes, opcode);
467 msg_pdbg ("on-the-fly OPCODE (0x%02X) re-programmed, op-pos=%d\n", opcode, oppos);
468 return oppos;
469 }
470 return -1;
471}
472
uweabe92a52009-05-16 22:36:00 +0000473static int find_opcode(OPCODES *op, uint8_t opcode)
stepane1a13b92008-12-08 18:16:58 +0000474{
475 int a;
476
stefanct83d99e82011-11-08 10:55:54 +0000477 if (op == NULL) {
478 msg_perr("\n%s: null OPCODES pointer!\n", __func__);
479 return -1;
480 }
481
stepane1a13b92008-12-08 18:16:58 +0000482 for (a = 0; a < 8; a++) {
483 if (op->opcode[a].opcode == opcode)
484 return a;
485 }
486
487 return -1;
488}
489
uweabe92a52009-05-16 22:36:00 +0000490static int find_preop(OPCODES *op, uint8_t preop)
stepane1a13b92008-12-08 18:16:58 +0000491{
492 int a;
493
stefanct83d99e82011-11-08 10:55:54 +0000494 if (op == NULL) {
495 msg_perr("\n%s: null OPCODES pointer!\n", __func__);
496 return -1;
497 }
498
stepane1a13b92008-12-08 18:16:58 +0000499 for (a = 0; a < 2; a++) {
500 if (op->preop[a] == preop)
501 return a;
502 }
503
504 return -1;
505}
506
hailfinger82e32492010-02-11 11:28:37 +0000507/* Create a struct OPCODES based on what we find in the locked down chipset. */
stuge7a651552008-12-15 02:32:11 +0000508static int generate_opcodes(OPCODES * op)
stepane1a13b92008-12-08 18:16:58 +0000509{
hailfinger82e32492010-02-11 11:28:37 +0000510 int a;
stepane1a13b92008-12-08 18:16:58 +0000511 uint16_t preop, optype;
512 uint32_t opmenu[2];
stepane1a13b92008-12-08 18:16:58 +0000513
514 if (op == NULL) {
snelsone42c3802010-05-07 20:09:04 +0000515 msg_perr("\n%s: null OPCODES pointer!\n", __func__);
stepane1a13b92008-12-08 18:16:58 +0000516 return -1;
517 }
518
stefanctc035c192011-11-06 23:51:09 +0000519 switch (ich_generation) {
520 case CHIPSET_ICH7:
stepane1a13b92008-12-08 18:16:58 +0000521 preop = REGREAD16(ICH7_REG_PREOP);
522 optype = REGREAD16(ICH7_REG_OPTYPE);
523 opmenu[0] = REGREAD32(ICH7_REG_OPMENU);
524 opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4);
525 break;
stefanctc035c192011-11-06 23:51:09 +0000526 case CHIPSET_ICH8:
527 default: /* Future version might behave the same */
stepane1a13b92008-12-08 18:16:58 +0000528 preop = REGREAD16(ICH9_REG_PREOP);
529 optype = REGREAD16(ICH9_REG_OPTYPE);
530 opmenu[0] = REGREAD32(ICH9_REG_OPMENU);
531 opmenu[1] = REGREAD32(ICH9_REG_OPMENU + 4);
532 break;
stepane1a13b92008-12-08 18:16:58 +0000533 }
534
535 op->preop[0] = (uint8_t) preop;
536 op->preop[1] = (uint8_t) (preop >> 8);
537
538 for (a = 0; a < 8; a++) {
539 op->opcode[a].spi_type = (uint8_t) (optype & 0x3);
540 optype >>= 2;
541 }
542
543 for (a = 0; a < 4; a++) {
544 op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff);
545 opmenu[0] >>= 8;
546 }
547
548 for (a = 4; a < 8; a++) {
549 op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff);
550 opmenu[1] >>= 8;
551 }
552
hailfinger82e32492010-02-11 11:28:37 +0000553 /* No preopcodes used by default. */
554 for (a = 0; a < 8; a++)
stepane1a13b92008-12-08 18:16:58 +0000555 op->opcode[a].atomic = 0;
556
stepane1a13b92008-12-08 18:16:58 +0000557 return 0;
558}
559
hailfinger1e2e3442011-05-03 21:49:41 +0000560static int program_opcodes(OPCODES *op, int enable_undo)
hailfinger82e7ddb2008-05-16 12:55:55 +0000561{
562 uint8_t a;
stepan3bdf6182008-06-30 23:45:22 +0000563 uint16_t preop, optype;
564 uint32_t opmenu[2];
hailfinger82e7ddb2008-05-16 12:55:55 +0000565
566 /* Program Prefix Opcodes */
hailfinger82e7ddb2008-05-16 12:55:55 +0000567 /* 0:7 Prefix Opcode 1 */
stepan3bdf6182008-06-30 23:45:22 +0000568 preop = (op->preop[0]);
hailfinger82e7ddb2008-05-16 12:55:55 +0000569 /* 8:16 Prefix Opcode 2 */
stepan3bdf6182008-06-30 23:45:22 +0000570 preop |= ((uint16_t) op->preop[1]) << 8;
uwefa98ca12008-10-18 21:14:13 +0000571
stepandbd3af12008-06-27 16:28:34 +0000572 /* Program Opcode Types 0 - 7 */
stepan3bdf6182008-06-30 23:45:22 +0000573 optype = 0;
hailfinger82e7ddb2008-05-16 12:55:55 +0000574 for (a = 0; a < 8; a++) {
stepan3bdf6182008-06-30 23:45:22 +0000575 optype |= ((uint16_t) op->opcode[a].spi_type) << (a * 2);
hailfinger82e7ddb2008-05-16 12:55:55 +0000576 }
uwefa98ca12008-10-18 21:14:13 +0000577
stepandbd3af12008-06-27 16:28:34 +0000578 /* Program Allowable Opcodes 0 - 3 */
stepan3bdf6182008-06-30 23:45:22 +0000579 opmenu[0] = 0;
hailfinger82e7ddb2008-05-16 12:55:55 +0000580 for (a = 0; a < 4; a++) {
stepan3bdf6182008-06-30 23:45:22 +0000581 opmenu[0] |= ((uint32_t) op->opcode[a].opcode) << (a * 8);
hailfinger82e7ddb2008-05-16 12:55:55 +0000582 }
stepandbd3af12008-06-27 16:28:34 +0000583
hailfinger82e7ddb2008-05-16 12:55:55 +0000584 /*Program Allowable Opcodes 4 - 7 */
stepan3bdf6182008-06-30 23:45:22 +0000585 opmenu[1] = 0;
hailfinger82e7ddb2008-05-16 12:55:55 +0000586 for (a = 4; a < 8; a++) {
stepan3bdf6182008-06-30 23:45:22 +0000587 opmenu[1] |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8);
hailfinger82e7ddb2008-05-16 12:55:55 +0000588 }
stepandbd3af12008-06-27 16:28:34 +0000589
snelsone42c3802010-05-07 20:09:04 +0000590 msg_pdbg("\n%s: preop=%04x optype=%04x opmenu=%08x%08x\n", __func__, preop, optype, opmenu[0], opmenu[1]);
stefanctc035c192011-11-06 23:51:09 +0000591 switch (ich_generation) {
592 case CHIPSET_ICH7:
hailfinger1e2e3442011-05-03 21:49:41 +0000593 /* Register undo only for enable_undo=1, i.e. first call. */
594 if (enable_undo) {
595 rmmio_valw(ich_spibar + ICH7_REG_PREOP);
596 rmmio_valw(ich_spibar + ICH7_REG_OPTYPE);
597 rmmio_vall(ich_spibar + ICH7_REG_OPMENU);
598 rmmio_vall(ich_spibar + ICH7_REG_OPMENU + 4);
599 }
600 mmio_writew(preop, ich_spibar + ICH7_REG_PREOP);
601 mmio_writew(optype, ich_spibar + ICH7_REG_OPTYPE);
602 mmio_writel(opmenu[0], ich_spibar + ICH7_REG_OPMENU);
603 mmio_writel(opmenu[1], ich_spibar + ICH7_REG_OPMENU + 4);
stepan3bdf6182008-06-30 23:45:22 +0000604 break;
stefanctc035c192011-11-06 23:51:09 +0000605 case CHIPSET_ICH8:
606 default: /* Future version might behave the same */
hailfinger1e2e3442011-05-03 21:49:41 +0000607 /* Register undo only for enable_undo=1, i.e. first call. */
608 if (enable_undo) {
609 rmmio_valw(ich_spibar + ICH9_REG_PREOP);
610 rmmio_valw(ich_spibar + ICH9_REG_OPTYPE);
611 rmmio_vall(ich_spibar + ICH9_REG_OPMENU);
612 rmmio_vall(ich_spibar + ICH9_REG_OPMENU + 4);
613 }
614 mmio_writew(preop, ich_spibar + ICH9_REG_PREOP);
615 mmio_writew(optype, ich_spibar + ICH9_REG_OPTYPE);
616 mmio_writel(opmenu[0], ich_spibar + ICH9_REG_OPMENU);
617 mmio_writel(opmenu[1], ich_spibar + ICH9_REG_OPMENU + 4);
stepan3bdf6182008-06-30 23:45:22 +0000618 break;
stepandbd3af12008-06-27 16:28:34 +0000619 }
hailfinger82e7ddb2008-05-16 12:55:55 +0000620
621 return 0;
622}
623
hailfingerb767c122010-05-28 15:53:08 +0000624/*
stefanct83d99e82011-11-08 10:55:54 +0000625 * Returns -1 if at least one mandatory opcode is inaccessible, 0 otherwise.
626 * FIXME: this should also check for
627 * - at least one probing opcode (RDID (incl. AT25F variants?), REMS, RES?)
628 * - at least one erasing opcode (lots.)
629 * - at least one program opcode (BYTE_PROGRAM, AAI_WORD_PROGRAM, ...?)
630 * - necessary preops? (EWSR, WREN, ...?)
631 */
632static int ich_missing_opcodes()
633{
634 uint8_t ops[] = {
635 JEDEC_READ,
636 JEDEC_RDSR,
637 0
638 };
639 int i = 0;
640 while (ops[i] != 0) {
641 msg_pspew("checking for opcode 0x%02x\n", ops[i]);
642 if (find_opcode(curopcodes, ops[i]) == -1)
643 return -1;
644 i++;
645 }
646 return 0;
647}
648
649/*
hailfingerb767c122010-05-28 15:53:08 +0000650 * Try to set BBAR (BIOS Base Address Register), but read back the value in case
651 * it didn't stick.
652 */
stefanctc035c192011-11-06 23:51:09 +0000653static void ich_set_bbar(uint32_t min_addr)
hailfingerb767c122010-05-28 15:53:08 +0000654{
stefanctebf900c2011-07-01 00:39:09 +0000655 int bbar_off;
stefanct3a716ba2011-09-17 21:21:42 +0000656 switch (ich_generation) {
stefanctc035c192011-11-06 23:51:09 +0000657 case CHIPSET_ICH7:
stefanctebf900c2011-07-01 00:39:09 +0000658 bbar_off = 0x50;
hailfingerb767c122010-05-28 15:53:08 +0000659 break;
stefanctc035c192011-11-06 23:51:09 +0000660 case CHIPSET_ICH8:
stefanct3a716ba2011-09-17 21:21:42 +0000661 msg_perr("BBAR offset is unknown on ICH8!\n");
662 return;
stefanctc035c192011-11-06 23:51:09 +0000663 case CHIPSET_ICH9:
stefanct3a716ba2011-09-17 21:21:42 +0000664 default: /* Future version might behave the same */
stefanctebf900c2011-07-01 00:39:09 +0000665 bbar_off = ICH9_REG_BBAR;
hailfingerb767c122010-05-28 15:53:08 +0000666 break;
hailfingerb767c122010-05-28 15:53:08 +0000667 }
David Hendricks7be91492016-12-27 18:43:45 -0800668
stefanctebf900c2011-07-01 00:39:09 +0000669 ichspi_bbar = mmio_readl(ich_spibar + bbar_off) & ~BBAR_MASK;
670 if (ichspi_bbar) {
671 msg_pdbg("Reserved bits in BBAR not zero: 0x%08x\n",
672 ichspi_bbar);
673 }
674 min_addr &= BBAR_MASK;
675 ichspi_bbar |= min_addr;
676 rmmio_writel(ichspi_bbar, ich_spibar + bbar_off);
677 ichspi_bbar = mmio_readl(ich_spibar + bbar_off) & BBAR_MASK;
678
679 /* We don't have any option except complaining. And if the write
680 * failed, the restore will fail as well, so no problem there.
681 */
682 if (ichspi_bbar != min_addr)
stefanct3a716ba2011-09-17 21:21:42 +0000683 msg_perr("Setting BBAR to 0x%08x failed! New value: 0x%08x.\n",
684 min_addr, ichspi_bbar);
hailfingerb767c122010-05-28 15:53:08 +0000685}
686
stefanctfa66c622011-08-09 01:49:34 +0000687/* Read len bytes from the fdata/spid register into the data array.
688 *
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100689 * Note that using len > spi_master->max_data_read will return garbage or
stefanctfa66c622011-08-09 01:49:34 +0000690 * may even crash.
691 */
David Hendricks1db25572011-07-11 22:07:58 -0700692 static void ich_read_data(uint8_t *data, int len, int reg0_off)
693 {
stefanctfa66c622011-08-09 01:49:34 +0000694 int i;
David Hendricks1db25572011-07-11 22:07:58 -0700695 uint32_t temp32 = 0;
696
stefanctfa66c622011-08-09 01:49:34 +0000697 for (i = 0; i < len; i++) {
698 if ((i % 4) == 0)
699 temp32 = REGREAD32(reg0_off + i);
David Hendricks1db25572011-07-11 22:07:58 -0700700
stefanctfa66c622011-08-09 01:49:34 +0000701 data[i] = (temp32 >> ((i % 4) * 8)) & 0xff;
David Hendricks1db25572011-07-11 22:07:58 -0700702 }
703}
704
stefanctfa66c622011-08-09 01:49:34 +0000705/* Fill len bytes from the data array into the fdata/spid registers.
706 *
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100707 * Note that using len > spi_master->max_data_write will trash the registers
stefanctfa66c622011-08-09 01:49:34 +0000708 * following the data registers.
709 */
710static void ich_fill_data(const uint8_t *data, int len, int reg0_off)
David Hendricks1db25572011-07-11 22:07:58 -0700711{
712 uint32_t temp32 = 0;
stefanctfa66c622011-08-09 01:49:34 +0000713 int i;
David Hendricks1db25572011-07-11 22:07:58 -0700714
715 if (len <= 0)
stefanctfa66c622011-08-09 01:49:34 +0000716 return;
David Hendricks1db25572011-07-11 22:07:58 -0700717
stefanctfa66c622011-08-09 01:49:34 +0000718 for (i = 0; i < len; i++) {
719 if ((i % 4) == 0)
David Hendricks1db25572011-07-11 22:07:58 -0700720 temp32 = 0;
David Hendricks1db25572011-07-11 22:07:58 -0700721
stefanctfa66c622011-08-09 01:49:34 +0000722 temp32 |= ((uint32_t) data[i]) << ((i % 4) * 8);
David Hendricks1db25572011-07-11 22:07:58 -0700723
stefanctfa66c622011-08-09 01:49:34 +0000724 if ((i % 4) == 3) /* 32 bits are full, write them to regs. */
725 REGWRITE32(reg0_off + (i - (i % 4)), temp32);
David Hendricks1db25572011-07-11 22:07:58 -0700726 }
stefanctfa66c622011-08-09 01:49:34 +0000727 i--;
728 if ((i % 4) != 3) /* Write remaining data to regs. */
729 REGWRITE32(reg0_off + (i - (i % 4)), temp32);
David Hendricks1db25572011-07-11 22:07:58 -0700730}
731
stuge7a651552008-12-15 02:32:11 +0000732/* This function generates OPCODES from or programs OPCODES to ICH according to
733 * the chipset's SPI configuration lock.
stepane1a13b92008-12-08 18:16:58 +0000734 *
stuge7a651552008-12-15 02:32:11 +0000735 * It should be called before ICH sends any spi command.
stepane1a13b92008-12-08 18:16:58 +0000736 */
mkarcher74d30132010-07-22 18:04:15 +0000737static int ich_init_opcodes(void)
stepane1a13b92008-12-08 18:16:58 +0000738{
739 int rc = 0;
740 OPCODES *curopcodes_done;
741
742 if (curopcodes)
743 return 0;
744
745 if (ichspi_lock) {
hailfingerb767c122010-05-28 15:53:08 +0000746 msg_pdbg("Reading OPCODES... ");
stepane1a13b92008-12-08 18:16:58 +0000747 curopcodes_done = &O_EXISTING;
stuge7a651552008-12-15 02:32:11 +0000748 rc = generate_opcodes(curopcodes_done);
stepane1a13b92008-12-08 18:16:58 +0000749 } else {
snelsone42c3802010-05-07 20:09:04 +0000750 msg_pdbg("Programming OPCODES... ");
stepane1a13b92008-12-08 18:16:58 +0000751 curopcodes_done = &O_ST_M25P;
hailfinger1e2e3442011-05-03 21:49:41 +0000752 rc = program_opcodes(curopcodes_done, 1);
stepane1a13b92008-12-08 18:16:58 +0000753 }
754
755 if (rc) {
756 curopcodes = NULL;
snelsone42c3802010-05-07 20:09:04 +0000757 msg_perr("failed\n");
stepane1a13b92008-12-08 18:16:58 +0000758 return 1;
759 } else {
760 curopcodes = curopcodes_done;
snelsone42c3802010-05-07 20:09:04 +0000761 msg_pdbg("done\n");
David Hendricksce6b2fa2011-07-11 22:12:43 -0700762 prettyprint_opcodes(curopcodes);
stepane1a13b92008-12-08 18:16:58 +0000763 return 0;
764 }
765}
766
stepan82c65bd2008-11-02 19:51:50 +0000767static int ich7_run_opcode(OPCODE op, uint32_t offset,
ruik9bc51c02008-06-30 21:38:30 +0000768 uint8_t datalength, uint8_t * data, int maxdata)
hailfinger82e7ddb2008-05-16 12:55:55 +0000769{
770 int write_cmd = 0;
stepandbd3af12008-06-27 16:28:34 +0000771 int timeout;
David Hendricks1db25572011-07-11 22:07:58 -0700772 uint32_t temp32;
stepandbd3af12008-06-27 16:28:34 +0000773 uint16_t temp16;
stepan82c65bd2008-11-02 19:51:50 +0000774 uint64_t opmenu;
775 int opcode_index;
hailfinger82e7ddb2008-05-16 12:55:55 +0000776
777 /* Is it a write command? */
778 if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
779 || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
780 write_cmd = 1;
781 }
782
hailfinger01d05912011-03-17 00:10:25 +0000783 timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
784 while ((REGREAD16(ICH7_REG_SPIS) & SPIS_SCIP) && --timeout) {
785 programmer_delay(10);
786 }
787 if (!timeout) {
788 msg_perr("Error: SCIP never cleared!\n");
789 return 1;
790 }
791
stefancte5e09892011-07-01 00:39:23 +0000792 /* Program offset in flash into SPIA while preserving reserved bits. */
793 temp32 = REGREAD32(ICH7_REG_SPIA) & ~0x00FFFFFF;
794 REGWRITE32(ICH7_REG_SPIA, (offset & 0x00FFFFFF) | temp32);
hailfinger82e7ddb2008-05-16 12:55:55 +0000795
stefancte5e09892011-07-01 00:39:23 +0000796 /* Program data into SPID0 to N */
David Hendricks1db25572011-07-11 22:07:58 -0700797 if (write_cmd && (datalength != 0))
798 ich_fill_data(data, datalength, ICH7_REG_SPID0);
stepandbd3af12008-06-27 16:28:34 +0000799
800 /* Assemble SPIS */
hailfinger01d05912011-03-17 00:10:25 +0000801 temp16 = REGREAD16(ICH7_REG_SPIS);
802 /* keep reserved bits */
803 temp16 &= SPIS_RESERVED_MASK;
stepandbd3af12008-06-27 16:28:34 +0000804 /* clear error status registers */
stefanct04009ff2011-06-11 09:53:09 +0000805 temp16 |= (SPIS_CDS | SPIS_FCERR);
stepandbd3af12008-06-27 16:28:34 +0000806 REGWRITE16(ICH7_REG_SPIS, temp16);
807
808 /* Assemble SPIC */
809 temp16 = 0;
810
811 if (datalength != 0) {
812 temp16 |= SPIC_DS;
ruik9bc51c02008-06-30 21:38:30 +0000813 temp16 |= ((uint32_t) ((datalength - 1) & (maxdata - 1))) << 8;
stepandbd3af12008-06-27 16:28:34 +0000814 }
815
816 /* Select opcode */
stepan82c65bd2008-11-02 19:51:50 +0000817 opmenu = REGREAD32(ICH7_REG_OPMENU);
818 opmenu |= ((uint64_t)REGREAD32(ICH7_REG_OPMENU + 4)) << 32;
819
uwe5e931bc2009-04-15 10:52:49 +0000820 for (opcode_index = 0; opcode_index < 8; opcode_index++) {
821 if ((opmenu & 0xff) == op.opcode) {
stepan82c65bd2008-11-02 19:51:50 +0000822 break;
823 }
824 opmenu >>= 8;
825 }
826 if (opcode_index == 8) {
snelsone42c3802010-05-07 20:09:04 +0000827 msg_pdbg("Opcode %x not found.\n", op.opcode);
stepan82c65bd2008-11-02 19:51:50 +0000828 return 1;
829 }
830 temp16 |= ((uint16_t) (opcode_index & 0x07)) << 4;
stepandbd3af12008-06-27 16:28:34 +0000831
mkarcher15b92fe2011-04-29 22:11:36 +0000832 timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
833 /* Handle Atomic. Atomic commands include three steps:
834 - sending the preop (mainly EWSR or WREN)
835 - sending the main command
836 - waiting for the busy bit (WIP) to be cleared
837 This means the timeout must be sufficient for chip erase
838 of slow high-capacity chips.
stefanct707f13b2011-05-19 02:58:17 +0000839 */
hailfinger82e32492010-02-11 11:28:37 +0000840 switch (op.atomic) {
841 case 2:
842 /* Select second preop. */
843 temp16 |= SPIC_SPOP;
844 /* And fall through. */
845 case 1:
846 /* Atomic command (preop+op) */
stepandbd3af12008-06-27 16:28:34 +0000847 temp16 |= SPIC_ACS;
mkarcher15b92fe2011-04-29 22:11:36 +0000848 timeout = 100 * 1000 * 60; /* 60 seconds */
hailfinger82e32492010-02-11 11:28:37 +0000849 break;
stepandbd3af12008-06-27 16:28:34 +0000850 }
851
852 /* Start */
853 temp16 |= SPIC_SCGO;
854
855 /* write it */
856 REGWRITE16(ICH7_REG_SPIC, temp16);
857
Louis Yung-Chieh Lod2129f12011-03-16 14:53:12 +0800858 /* Original timeout is 60 minutes, which is too excessive.
859 * Reduce to 30 secs for chip full erase (around 10 secs).
860 * We also exit the loop if the error bit is set.
861 */
862 timeout = 100 * 1000 * 30;
hailfinger01d05912011-03-17 00:10:25 +0000863 while (((REGREAD16(ICH7_REG_SPIS) & (SPIS_CDS | SPIS_FCERR)) == 0) &&
864 --timeout) {
hailfingere5829f62009-06-05 17:48:08 +0000865 programmer_delay(10);
Louis Yung-Chieh Lod2129f12011-03-16 14:53:12 +0800866 if (REGREAD16(ICH7_REG_SPIS) & SPIS_FCERR)
867 break; /* Transaction error */
stepandbd3af12008-06-27 16:28:34 +0000868 }
869 if (!timeout) {
hailfinger01d05912011-03-17 00:10:25 +0000870 msg_perr("timeout, ICH7_REG_SPIS=0x%04x\n",
871 REGREAD16(ICH7_REG_SPIS));
872 return 1;
stepandbd3af12008-06-27 16:28:34 +0000873 }
874
snelsone42c3802010-05-07 20:09:04 +0000875 /* FIXME: make sure we do not needlessly cause transaction errors. */
hailfinger01d05912011-03-17 00:10:25 +0000876 temp16 = REGREAD16(ICH7_REG_SPIS);
877 if (temp16 & SPIS_FCERR) {
mkarcherdb7751e2011-04-29 23:53:09 +0000878 msg_perr("Transaction error!\n");
hailfinger01d05912011-03-17 00:10:25 +0000879 /* keep reserved bits */
880 temp16 &= SPIS_RESERVED_MASK;
881 REGWRITE16(ICH7_REG_SPIS, temp16 | SPIS_FCERR);
stepandbd3af12008-06-27 16:28:34 +0000882 return 1;
883 }
884
stefanctfa66c622011-08-09 01:49:34 +0000885 if ((!write_cmd) && (datalength != 0))
David Hendricks1db25572011-07-11 22:07:58 -0700886 ich_read_data(data, datalength, ICH7_REG_SPID0);
stepandbd3af12008-06-27 16:28:34 +0000887
888 return 0;
889}
890
stepan82c65bd2008-11-02 19:51:50 +0000891static int ich9_run_opcode(OPCODE op, uint32_t offset,
stepandbd3af12008-06-27 16:28:34 +0000892 uint8_t datalength, uint8_t * data)
893{
894 int write_cmd = 0;
stepan3bdf6182008-06-30 23:45:22 +0000895 int timeout;
stepandbd3af12008-06-27 16:28:34 +0000896 uint32_t temp32;
stepan82c65bd2008-11-02 19:51:50 +0000897 uint64_t opmenu;
898 int opcode_index;
stepandbd3af12008-06-27 16:28:34 +0000899
900 /* Is it a write command? */
901 if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
902 || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
903 write_cmd = 1;
904 }
905
hailfinger01d05912011-03-17 00:10:25 +0000906 timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
907 while ((REGREAD8(ICH9_REG_SSFS) & SSFS_SCIP) && --timeout) {
908 programmer_delay(10);
909 }
910 if (!timeout) {
911 msg_perr("Error: SCIP never cleared!\n");
912 return 1;
913 }
914
stefancte5e09892011-07-01 00:39:23 +0000915 /* Program offset in flash into FADDR while preserve the reserved bits
916 * and clearing the 25. address bit which is only useable in hwseq. */
917 temp32 = REGREAD32(ICH9_REG_FADDR) & ~0x01FFFFFF;
918 REGWRITE32(ICH9_REG_FADDR, (offset & 0x00FFFFFF) | temp32);
stepandbd3af12008-06-27 16:28:34 +0000919
920 /* Program data into FDATA0 to N */
David Hendricks1db25572011-07-11 22:07:58 -0700921 if (write_cmd && (datalength != 0))
922 ich_fill_data(data, datalength, ICH9_REG_FDATA0);
hailfinger82e7ddb2008-05-16 12:55:55 +0000923
924 /* Assemble SSFS + SSFC */
mkarcher08c34112010-08-11 21:06:10 +0000925 temp32 = REGREAD32(ICH9_REG_SSFS);
stefanct707f13b2011-05-19 02:58:17 +0000926 /* Keep reserved bits only */
hailfinger01d05912011-03-17 00:10:25 +0000927 temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK;
stefanct04009ff2011-06-11 09:53:09 +0000928 /* Clear cycle done and cycle error status registers */
929 temp32 |= (SSFS_FDONE | SSFS_FCERR);
hailfinger01d05912011-03-17 00:10:25 +0000930 REGWRITE32(ICH9_REG_SSFS, temp32);
931
uwe3a3ab2f2010-03-25 23:18:41 +0000932 /* Use 20 MHz */
hailfinger82e7ddb2008-05-16 12:55:55 +0000933 temp32 |= SSFC_SCF_20MHZ;
934
stefanct707f13b2011-05-19 02:58:17 +0000935 /* Set data byte count (DBC) and data cycle bit (DS) */
hailfinger82e7ddb2008-05-16 12:55:55 +0000936 if (datalength != 0) {
937 uint32_t datatemp;
938 temp32 |= SSFC_DS;
stefanct04009ff2011-06-11 09:53:09 +0000939 datatemp = ((((uint32_t)datalength - 1) << SSFC_DBC_OFF) &
940 SSFC_DBC);
hailfinger82e7ddb2008-05-16 12:55:55 +0000941 temp32 |= datatemp;
942 }
943
944 /* Select opcode */
stepan82c65bd2008-11-02 19:51:50 +0000945 opmenu = REGREAD32(ICH9_REG_OPMENU);
946 opmenu |= ((uint64_t)REGREAD32(ICH9_REG_OPMENU + 4)) << 32;
947
uwe5e931bc2009-04-15 10:52:49 +0000948 for (opcode_index = 0; opcode_index < 8; opcode_index++) {
949 if ((opmenu & 0xff) == op.opcode) {
stepan82c65bd2008-11-02 19:51:50 +0000950 break;
951 }
952 opmenu >>= 8;
953 }
954 if (opcode_index == 8) {
snelsone42c3802010-05-07 20:09:04 +0000955 msg_pdbg("Opcode %x not found.\n", op.opcode);
stepan82c65bd2008-11-02 19:51:50 +0000956 return 1;
957 }
958 temp32 |= ((uint32_t) (opcode_index & 0x07)) << (8 + 4);
hailfinger82e7ddb2008-05-16 12:55:55 +0000959
mkarcher15b92fe2011-04-29 22:11:36 +0000960 timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
961 /* Handle Atomic. Atomic commands include three steps:
962 - sending the preop (mainly EWSR or WREN)
963 - sending the main command
964 - waiting for the busy bit (WIP) to be cleared
965 This means the timeout must be sufficient for chip erase
966 of slow high-capacity chips.
stefanct707f13b2011-05-19 02:58:17 +0000967 */
hailfinger82e32492010-02-11 11:28:37 +0000968 switch (op.atomic) {
969 case 2:
970 /* Select second preop. */
971 temp32 |= SSFC_SPOP;
972 /* And fall through. */
973 case 1:
974 /* Atomic command (preop+op) */
hailfinger82e7ddb2008-05-16 12:55:55 +0000975 temp32 |= SSFC_ACS;
mkarcher15b92fe2011-04-29 22:11:36 +0000976 timeout = 100 * 1000 * 60; /* 60 seconds */
hailfinger82e32492010-02-11 11:28:37 +0000977 break;
hailfinger82e7ddb2008-05-16 12:55:55 +0000978 }
979
980 /* Start */
981 temp32 |= SSFC_SCGO;
982
983 /* write it */
stepandbd3af12008-06-27 16:28:34 +0000984 REGWRITE32(ICH9_REG_SSFS, temp32);
hailfinger82e7ddb2008-05-16 12:55:55 +0000985
hailfinger01d05912011-03-17 00:10:25 +0000986 /* Wait for Cycle Done Status or Flash Cycle Error. */
stefanct04009ff2011-06-11 09:53:09 +0000987 while (((REGREAD32(ICH9_REG_SSFS) & (SSFS_FDONE | SSFS_FCERR)) == 0) &&
hailfinger01d05912011-03-17 00:10:25 +0000988 --timeout) {
hailfingere5829f62009-06-05 17:48:08 +0000989 programmer_delay(10);
stepan3bdf6182008-06-30 23:45:22 +0000990 }
991 if (!timeout) {
hailfinger01d05912011-03-17 00:10:25 +0000992 msg_perr("timeout, ICH9_REG_SSFS=0x%08x\n",
993 REGREAD32(ICH9_REG_SSFS));
994 return 1;
hailfinger82e7ddb2008-05-16 12:55:55 +0000995 }
996
snelsone42c3802010-05-07 20:09:04 +0000997 /* FIXME make sure we do not needlessly cause transaction errors. */
hailfinger01d05912011-03-17 00:10:25 +0000998 temp32 = REGREAD32(ICH9_REG_SSFS);
999 if (temp32 & SSFS_FCERR) {
mkarcherdb7751e2011-04-29 23:53:09 +00001000 msg_perr("Transaction error!\n");
stefancte4d1ef52011-06-11 09:53:16 +00001001 prettyprint_ich9_reg_ssfs(temp32);
1002 prettyprint_ich9_reg_ssfc(temp32);
hailfinger01d05912011-03-17 00:10:25 +00001003 /* keep reserved bits */
1004 temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK;
1005 /* Clear the transaction error. */
1006 REGWRITE32(ICH9_REG_SSFS, temp32 | SSFS_FCERR);
hailfinger82e7ddb2008-05-16 12:55:55 +00001007 return 1;
1008 }
1009
stefanctfa66c622011-08-09 01:49:34 +00001010 if ((!write_cmd) && (datalength != 0))
David Hendricks1db25572011-07-11 22:07:58 -07001011 ich_read_data(data, datalength, ICH9_REG_FDATA0);
hailfinger82e7ddb2008-05-16 12:55:55 +00001012
1013 return 0;
1014}
1015
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001016static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset,
stepandbd3af12008-06-27 16:28:34 +00001017 uint8_t datalength, uint8_t * data)
1018{
stefanct689eb6c2011-06-11 19:44:31 +00001019 /* max_data_read == max_data_write for all Intel/VIA SPI masters */
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01001020 uint8_t maxlength = spi_master->max_data_read;
stefanct689eb6c2011-06-11 19:44:31 +00001021
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01001022 if (spi_master->type == SPI_CONTROLLER_NONE) {
snelsone42c3802010-05-07 20:09:04 +00001023 msg_perr("%s: unsupported chipset\n", __func__);
stefanct689eb6c2011-06-11 19:44:31 +00001024 return -1;
stepan3bdf6182008-06-30 23:45:22 +00001025 }
stepandbd3af12008-06-27 16:28:34 +00001026
stefanct689eb6c2011-06-11 19:44:31 +00001027 if (datalength > maxlength) {
1028 msg_perr("%s: Internal command size error for "
1029 "opcode 0x%02x, got datalength=%i, want <=%i\n",
1030 __func__, op.opcode, datalength, maxlength);
1031 return SPI_INVALID_LENGTH;
1032 }
1033
stefanctc035c192011-11-06 23:51:09 +00001034 switch (ich_generation) {
1035 case CHIPSET_ICH7:
stefanct689eb6c2011-06-11 19:44:31 +00001036 return ich7_run_opcode(op, offset, datalength, data, maxlength);
stefanctc035c192011-11-06 23:51:09 +00001037 case CHIPSET_ICH8:
1038 default: /* Future version might behave the same */
stefanct689eb6c2011-06-11 19:44:31 +00001039 return ich9_run_opcode(op, offset, datalength, data);
stefanct689eb6c2011-06-11 19:44:31 +00001040 }
stepandbd3af12008-06-27 16:28:34 +00001041}
1042
David Hendricks1ed1d352011-11-23 17:54:37 -08001043#define DEFAULT_NUM_FD_REGIONS 5
1044static int num_fd_regions;
1045
1046const char *const region_names[] = {
1047 "Flash Descriptor", "BIOS", "Management Engine",
1048 "Gigabit Ethernet", "Platform Data"
1049};
1050
1051enum fd_access_level {
1052 FD_REGION_LOCKED,
1053 FD_REGION_READ_ONLY,
1054 FD_REGION_WRITE_ONLY,
1055 FD_REGION_READ_WRITE,
1056};
1057
1058struct fd_region_permission {
1059 enum fd_access_level level;
1060 const char *name;
1061} fd_region_permissions[] = {
1062 /* order corresponds to FRAP bitfield */
1063 { FD_REGION_LOCKED, "locked" },
1064 { FD_REGION_READ_ONLY, "read-only" },
1065 { FD_REGION_WRITE_ONLY, "write-only" },
1066 { FD_REGION_READ_WRITE, "read-write" },
1067};
1068
1069/* FIXME: Replace usage of access_names with the region_access struct */
1070const char *const access_names[4] = {
1071 "locked", "read-only", "write-only", "read-write"
1072};
1073
1074struct fd_region {
1075 const char *name;
1076 struct fd_region_permission *permission;
1077 uint32_t base;
1078 uint32_t limit;
1079} fd_regions[] = {
1080 /* order corresponds to flash descriptor */
1081 { .name = "Flash Descriptor" },
1082 { .name = "BIOS" },
1083 { .name = "Management Engine" },
1084 { .name = "Gigabit Ethernet" },
1085 { .name = "Platform Data" },
1086};
1087
Ramya Vijaykumar71d69ad2015-10-01 11:26:40 +05301088static int check_fd_permissions_hwseq(int op_type, uint32_t addr, int count)
1089{
1090 int i;
1091 int ret = 0;
1092
1093 /* check flash descriptor permissions (if present) */
1094 for (i = 0; i < num_fd_regions; i++) {
1095 const char *name = fd_regions[i].name;
1096 enum fd_access_level level;
1097
1098 if ((addr + count - 1 < fd_regions[i].base) ||
1099 (addr > fd_regions[i].limit))
1100 continue;
1101
1102 if (!fd_regions[i].permission) {
1103 msg_perr("No permissions set for flash region %s\n",
1104 fd_regions[i].name);
1105 break;
1106 }
1107 level = fd_regions[i].permission->level;
1108
1109 if (op_type == HWSEQ_READ) {
1110 if (level != FD_REGION_READ_ONLY &&
1111 level != FD_REGION_READ_WRITE) {
1112 msg_pspew("%s: Cannot read address 0x%08x in "
1113 "region %s\n", __func__, addr, name);
1114 ret = SPI_ACCESS_DENIED;
1115 }
1116 } else if (op_type == HWSEQ_WRITE) {
1117 if (level != FD_REGION_WRITE_ONLY &&
1118 level != FD_REGION_READ_WRITE) {
1119 msg_pspew("%s: Cannot write to address 0x%08x "
1120 "in region %s\n", __func__, addr, name);
1121 ret = SPI_ACCESS_DENIED;
1122 }
1123 }
1124 break;
1125 }
1126
Furquan Shaikh4290f8d2016-07-12 13:13:44 -07001127 if (i == num_fd_regions) {
1128 msg_pspew("%s: Address not covered by any descriptor 0x%06x\n",
1129 __func__, addr);
1130 ret = SPI_ACCESS_DENIED;
1131 }
1132
Ramya Vijaykumar71d69ad2015-10-01 11:26:40 +05301133 return ret;
1134}
1135
David Hendricks210975e2015-08-25 21:36:13 +00001136static int check_fd_permissions(OPCODE *opcode, uint32_t addr, int count)
David Hendricks1ed1d352011-11-23 17:54:37 -08001137{
1138 int i;
1139 uint8_t type = opcode->spi_type;
1140 int ret = 0;
1141
1142 /* check flash descriptor permissions (if present) */
1143 for (i = 0; i < num_fd_regions; i++) {
1144 const char *name = fd_regions[i].name;
1145 enum fd_access_level level;
1146
1147 if ((addr + count - 1 < fd_regions[i].base) ||
David Hendricks210975e2015-08-25 21:36:13 +00001148 (addr > fd_regions[i].limit))
David Hendricks1ed1d352011-11-23 17:54:37 -08001149 continue;
1150
1151 if (!fd_regions[i].permission) {
1152 msg_perr("No permissions set for flash region %s\n",
1153 fd_regions[i].name);
1154 break;
1155 }
1156
1157 level = fd_regions[i].permission->level;
1158
1159 if (type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS) {
1160 if (level != FD_REGION_READ_ONLY &&
1161 level != FD_REGION_READ_WRITE) {
1162 msg_pspew("%s: Cannot read address 0x%08x in "
1163 "region %s\n", __func__,addr,name);
1164 ret = SPI_ACCESS_DENIED;
1165 }
1166 } else if (type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
1167 if (level != FD_REGION_WRITE_ONLY &&
1168 level != FD_REGION_READ_WRITE) {
1169 msg_pspew("%s: Cannot write to address 0x%08x in"
1170 "region %s\n", __func__,addr,name);
1171 ret = SPI_ACCESS_DENIED;
1172 }
1173 }
1174 break;
1175 }
1176
1177 return ret;
1178}
1179
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001180static int ich_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
stepan8f46dd62008-06-27 15:18:20 +00001181 const unsigned char *writearr, unsigned char *readarr)
hailfinger82e7ddb2008-05-16 12:55:55 +00001182{
hailfinger9c290a72009-07-14 10:26:56 +00001183 int result;
hailfinger82e7ddb2008-05-16 12:55:55 +00001184 int opcode_index = -1;
1185 const unsigned char cmd = *writearr;
1186 OPCODE *opcode;
1187 uint32_t addr = 0;
1188 uint8_t *data;
1189 int count;
1190
hailfinger82e7ddb2008-05-16 12:55:55 +00001191 /* find cmd in opcodes-table */
hailfinger82e32492010-02-11 11:28:37 +00001192 opcode_index = find_opcode(curopcodes, cmd);
hailfinger82e7ddb2008-05-16 12:55:55 +00001193 if (opcode_index == -1) {
hailfinger4c973122010-10-05 22:06:05 +00001194 if (!ichspi_lock)
1195 opcode_index = reprogram_opcode_on_the_fly(cmd, writecnt, readcnt);
1196 if (opcode_index == -1) {
stefanct9e6b98a2011-05-28 02:37:14 +00001197 msg_pdbg("Invalid OPCODE 0x%02x, will not execute.\n",
1198 cmd);
hailfinger4c973122010-10-05 22:06:05 +00001199 return SPI_INVALID_OPCODE;
1200 }
hailfinger82e7ddb2008-05-16 12:55:55 +00001201 }
1202
1203 opcode = &(curopcodes->opcode[opcode_index]);
1204
hailfinger82e32492010-02-11 11:28:37 +00001205 /* The following valid writecnt/readcnt combinations exist:
1206 * writecnt = 4, readcnt >= 0
1207 * writecnt = 1, readcnt >= 0
1208 * writecnt >= 4, readcnt = 0
1209 * writecnt >= 1, readcnt = 0
1210 * writecnt >= 1 is guaranteed for all commands.
1211 */
1212 if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS) &&
1213 (writecnt != 4)) {
snelsone42c3802010-05-07 20:09:04 +00001214 msg_perr("%s: Internal command size error for opcode "
hailfinger82e32492010-02-11 11:28:37 +00001215 "0x%02x, got writecnt=%i, want =4\n", __func__, cmd,
1216 writecnt);
1217 return SPI_INVALID_LENGTH;
1218 }
1219 if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_NO_ADDRESS) &&
1220 (writecnt != 1)) {
snelsone42c3802010-05-07 20:09:04 +00001221 msg_perr("%s: Internal command size error for opcode "
hailfinger82e32492010-02-11 11:28:37 +00001222 "0x%02x, got writecnt=%i, want =1\n", __func__, cmd,
1223 writecnt);
1224 return SPI_INVALID_LENGTH;
1225 }
1226 if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) &&
1227 (writecnt < 4)) {
snelsone42c3802010-05-07 20:09:04 +00001228 msg_perr("%s: Internal command size error for opcode "
hailfinger82e32492010-02-11 11:28:37 +00001229 "0x%02x, got writecnt=%i, want >=4\n", __func__, cmd,
1230 writecnt);
1231 return SPI_INVALID_LENGTH;
1232 }
1233 if (((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
1234 (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)) &&
1235 (readcnt)) {
snelsone42c3802010-05-07 20:09:04 +00001236 msg_perr("%s: Internal command size error for opcode "
hailfinger82e32492010-02-11 11:28:37 +00001237 "0x%02x, got readcnt=%i, want =0\n", __func__, cmd,
1238 readcnt);
1239 return SPI_INVALID_LENGTH;
1240 }
1241
stefanct689eb6c2011-06-11 19:44:31 +00001242 /* Translate read/write array/count.
1243 * The maximum data length is identical for the maximum read length and
1244 * for the maximum write length excluding opcode and address. Opcode and
1245 * address are stored in separate registers, not in the data registers
1246 * and are thus not counted towards data length. The only exception
1247 * applies if the opcode definition (un)intentionally classifies said
1248 * opcode incorrectly as non-address opcode or vice versa. */
hailfinger82e7ddb2008-05-16 12:55:55 +00001249 if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) {
stepan8f46dd62008-06-27 15:18:20 +00001250 data = (uint8_t *) (writearr + 1);
1251 count = writecnt - 1;
1252 } else if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
1253 data = (uint8_t *) (writearr + 4);
1254 count = writecnt - 4;
1255 } else {
1256 data = (uint8_t *) readarr;
hailfinger82e7ddb2008-05-16 12:55:55 +00001257 count = readcnt;
1258 }
stepan8f46dd62008-06-27 15:18:20 +00001259
David Hendricks1ed1d352011-11-23 17:54:37 -08001260 /* if opcode-type requires an address */
1261 if (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS ||
1262 opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
1263 addr = (writearr[1] << 16) |
1264 (writearr[2] << 8) | (writearr[3] << 0);
1265 if (addr < ichspi_bbar) {
1266 msg_perr("%s: Address 0x%06x below allowed "
1267 "range 0x%06x-0xffffff\n", __func__,
1268 addr, ichspi_bbar);
1269 return SPI_INVALID_ADDRESS;
1270 }
1271 if (num_fd_regions > 0) {
1272 result = check_fd_permissions(opcode, addr, count);
1273 if (result)
1274 return result;
1275 }
1276 }
1277
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001278 result = run_opcode(flash, *opcode, addr, count, data);
hailfinger9c290a72009-07-14 10:26:56 +00001279 if (result) {
mkarcherdb7751e2011-04-29 23:53:09 +00001280 msg_pdbg("Running OPCODE 0x%02x failed ", opcode->opcode);
1281 if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
1282 (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS)) {
1283 msg_pdbg("at address 0x%06x ", addr);
1284 }
1285 msg_pdbg("(payload length was %d).\n", count);
1286
1287 /* Print out the data array if it contains data to write.
1288 * Errors are detected before the received data is read back into
1289 * the array so it won't make sense to print it then. */
1290 if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
1291 (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)) {
1292 int i;
1293 msg_pspew("The data was:\n");
stefanctd0064e12011-11-08 11:55:24 +00001294 for (i = 0; i < count; i++){
mkarcherdb7751e2011-04-29 23:53:09 +00001295 msg_pspew("%3d: 0x%02x\n", i, data[i]);
1296 }
1297 }
hailfinger82e7ddb2008-05-16 12:55:55 +00001298 }
1299
hailfinger9c290a72009-07-14 10:26:56 +00001300 return result;
hailfinger82e7ddb2008-05-16 12:55:55 +00001301}
hailfinger948b81f2009-07-22 15:36:50 +00001302
stefanct83d99e82011-11-08 10:55:54 +00001303static struct hwseq_data {
1304 uint32_t size_comp0;
1305 uint32_t size_comp1;
1306} hwseq_data;
1307
stefanct3d3b6ee2011-10-20 12:57:14 +00001308/* Sets FLA in FADDR to (addr & 0x01FFFFFF) without touching other bits. */
David Hendricks07af3a42011-07-11 22:13:02 -07001309static void ich_hwseq_set_addr(uint32_t addr)
1310{
1311 uint32_t addr_old = REGREAD32(ICH9_REG_FADDR) & ~0x01FFFFFF;
1312 REGWRITE32(ICH9_REG_FADDR, (addr & 0x01FFFFFF) | addr_old);
1313}
1314
1315/* Sets FADDR.FLA to 'addr' and returns the erase block size in bytes
stefanct3d3b6ee2011-10-20 12:57:14 +00001316 * of the block containing this address. May return nonsense if the address is
1317 * not valid. The erase block size for a specific address depends on the flash
1318 * partition layout as specified by FPB and the partition properties as defined
1319 * by UVSCC and LVSCC respectively. An alternative to implement this method
1320 * would be by querying FPB and the respective VSCC register directly.
1321 */
David Hendricks07af3a42011-07-11 22:13:02 -07001322static uint32_t ich_hwseq_get_erase_block_size(unsigned int addr)
1323{
1324 uint8_t enc_berase;
Vadim Bendeburya6f9c4a2013-09-19 14:38:34 -07001325 static const uint32_t dec_berase[4] = {
David Hendricks07af3a42011-07-11 22:13:02 -07001326 256,
1327 4 * 1024,
1328 8 * 1024,
1329 64 * 1024
1330 };
1331
1332 ich_hwseq_set_addr(addr);
1333 enc_berase = (REGREAD16(ICH9_REG_HSFS) & HSFS_BERASE) >>
1334 HSFS_BERASE_OFF;
1335 return dec_berase[enc_berase];
1336}
1337
stefanct3d3b6ee2011-10-20 12:57:14 +00001338/* Polls for Cycle Done Status, Flash Cycle Error or timeout in 8 us intervals.
David Hendricks07af3a42011-07-11 22:13:02 -07001339 Resets all error flags in HSFS.
1340 Returns 0 if the cycle completes successfully without errors within
1341 timeout us, 1 on errors. */
1342static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout,
1343 unsigned int len)
1344{
1345 uint16_t hsfs;
1346 uint32_t addr;
1347
stefanct3d3b6ee2011-10-20 12:57:14 +00001348 timeout /= 8; /* scale timeout duration to counter */
David Hendricks07af3a42011-07-11 22:13:02 -07001349 while ((((hsfs = REGREAD16(ICH9_REG_HSFS)) &
1350 (HSFS_FDONE | HSFS_FCERR)) == 0) &&
1351 --timeout) {
stefanct3d3b6ee2011-10-20 12:57:14 +00001352 programmer_delay(8);
David Hendricks07af3a42011-07-11 22:13:02 -07001353 }
1354 REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
1355 if (!timeout) {
1356 addr = REGREAD32(ICH9_REG_FADDR) & 0x01FFFFFF;
1357 msg_perr("Timeout error between offset 0x%08x and "
stefanct83d99e82011-11-08 10:55:54 +00001358 "0x%08x (= 0x%08x + %d)!\n",
1359 addr, addr + len - 1, addr, len - 1);
David Hendricks07af3a42011-07-11 22:13:02 -07001360 prettyprint_ich9_reg_hsfs(hsfs);
1361 prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC));
1362 return 1;
1363 }
1364
1365 if (hsfs & HSFS_FCERR) {
1366 addr = REGREAD32(ICH9_REG_FADDR) & 0x01FFFFFF;
1367 msg_perr("Transaction error between offset 0x%08x and "
stefanct83d99e82011-11-08 10:55:54 +00001368 "0x%08x (= 0x%08x + %d)!\n",
stefanct3d3b6ee2011-10-20 12:57:14 +00001369 addr, addr + len - 1, addr, len - 1);
David Hendricks07af3a42011-07-11 22:13:02 -07001370 prettyprint_ich9_reg_hsfs(hsfs);
1371 prettyprint_ich9_reg_hsfc(REGREAD16(ICH9_REG_HSFC));
1372 return 1;
1373 }
1374 return 0;
1375}
stefanct83d99e82011-11-08 10:55:54 +00001376
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001377int ich_hwseq_probe(struct flashctx *flash)
stefanct83d99e82011-11-08 10:55:54 +00001378{
1379 uint32_t total_size, boundary;
1380 uint32_t erase_size_low, size_low, erase_size_high, size_high;
1381 struct block_eraser *eraser;
1382
1383 total_size = hwseq_data.size_comp0 + hwseq_data.size_comp1;
1384 msg_cdbg("Found %d attached SPI flash chip",
1385 (hwseq_data.size_comp1 != 0) ? 2 : 1);
1386 if (hwseq_data.size_comp1 != 0)
1387 msg_cdbg("s with a combined");
1388 else
1389 msg_cdbg(" with a");
1390 msg_cdbg(" density of %d kB.\n", total_size / 1024);
Patrick Georgif3fa2992017-02-02 16:24:44 +01001391 flash->chip->total_size = total_size / 1024;
stefanct83d99e82011-11-08 10:55:54 +00001392
Patrick Georgif3fa2992017-02-02 16:24:44 +01001393 eraser = &(flash->chip->block_erasers[0]);
stefanct83d99e82011-11-08 10:55:54 +00001394 boundary = (REGREAD32(ICH9_REG_FPB) & FPB_FPBA) << 12;
1395 size_high = total_size - boundary;
1396 erase_size_high = ich_hwseq_get_erase_block_size(boundary);
1397
1398 if (boundary == 0) {
1399 msg_cdbg("There is only one partition containing the whole "
1400 "address space (0x%06x - 0x%06x).\n", 0, size_high-1);
1401 eraser->eraseblocks[0].size = erase_size_high;
1402 eraser->eraseblocks[0].count = size_high / erase_size_high;
1403 msg_cdbg("There are %d erase blocks with %d B each.\n",
1404 size_high / erase_size_high, erase_size_high);
1405 } else {
1406 msg_cdbg("The flash address space (0x%06x - 0x%06x) is divided "
1407 "at address 0x%06x in two partitions.\n",
1408 0, size_high-1, boundary);
1409 size_low = total_size - size_high;
1410 erase_size_low = ich_hwseq_get_erase_block_size(0);
1411
1412 eraser->eraseblocks[0].size = erase_size_low;
1413 eraser->eraseblocks[0].count = size_low / erase_size_low;
1414 msg_cdbg("The first partition ranges from 0x%06x to 0x%06x.\n",
1415 0, size_low-1);
1416 msg_cdbg("In that range are %d erase blocks with %d B each.\n",
1417 size_low / erase_size_low, erase_size_low);
1418
1419 eraser->eraseblocks[1].size = erase_size_high;
1420 eraser->eraseblocks[1].count = size_high / erase_size_high;
1421 msg_cdbg("The second partition ranges from 0x%06x to 0x%06x.\n",
1422 boundary, size_high-1);
1423 msg_cdbg("In that range are %d erase blocks with %d B each.\n",
1424 size_high / erase_size_high, erase_size_high);
1425 }
stefanct83d99e82011-11-08 10:55:54 +00001426 return 1;
1427}
1428
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001429int ich_hwseq_block_erase(struct flashctx *flash,
stefanct83d99e82011-11-08 10:55:54 +00001430 unsigned int addr,
1431 unsigned int len)
1432{
1433 uint32_t erase_block;
1434 uint16_t hsfc;
1435 uint32_t timeout = 5000 * 1000; /* 5 s for max 64 kB */
1436
1437 erase_block = ich_hwseq_get_erase_block_size(addr);
1438 if (len != erase_block) {
1439 msg_cerr("Erase block size for address 0x%06x is %d B, "
1440 "but requested erase block size is %d B. "
1441 "Not erasing anything.\n", addr, erase_block, len);
1442 return -1;
1443 }
1444
1445 /* Although the hardware supports this (it would erase the whole block
1446 * containing the address) we play safe here. */
1447 if (addr % erase_block != 0) {
1448 msg_cerr("Erase address 0x%06x is not aligned to the erase "
1449 "block boundary (any multiple of %d). "
1450 "Not erasing anything.\n", addr, erase_block);
1451 return -1;
1452 }
1453
Patrick Georgif3fa2992017-02-02 16:24:44 +01001454 if (addr + len > flash->chip->total_size * 1024) {
stefanct83d99e82011-11-08 10:55:54 +00001455 msg_perr("Request to erase some inaccessible memory address(es)"
1456 " (addr=0x%x, len=%d). "
1457 "Not erasing anything.\n", addr, len);
1458 return -1;
1459 }
1460
David Hendricksc1044262016-11-02 13:33:57 -07001461 msg_pspew("Erasing %d bytes starting at 0x%06x.\n", len, addr);
stefanct83d99e82011-11-08 10:55:54 +00001462
1463 /* make sure FDONE, FCERR, AEL are cleared by writing 1 to them */
1464 REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
1465
1466 hsfc = REGREAD16(ICH9_REG_HSFC);
1467 hsfc &= ~HSFC_FCYCLE; /* clear operation */
1468 hsfc |= (0x3 << HSFC_FCYCLE_OFF); /* set erase operation */
1469 hsfc |= HSFC_FGO; /* start */
David Hendricksc1044262016-11-02 13:33:57 -07001470 msg_pspew("HSFC used for block erasing: ");
stefanct83d99e82011-11-08 10:55:54 +00001471 prettyprint_ich9_reg_hsfc(hsfc);
1472 REGWRITE16(ICH9_REG_HSFC, hsfc);
1473
1474 if (ich_hwseq_wait_for_cycle_complete(timeout, len))
1475 return -1;
1476 return 0;
1477}
1478
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001479int ich_hwseq_read(struct flashctx *flash, uint8_t *buf, unsigned int addr,
stefanctc5eb8a92011-11-23 09:13:48 +00001480 unsigned int len)
stefanct83d99e82011-11-08 10:55:54 +00001481{
1482 uint16_t hsfc;
1483 uint16_t timeout = 100 * 60;
1484 uint8_t block_len;
1485
Patrick Georgif3fa2992017-02-02 16:24:44 +01001486 if ((addr + len) > (flash->chip->total_size * 1024)) {
stefanct83d99e82011-11-08 10:55:54 +00001487 msg_perr("Request to read from an inaccessible memory address "
1488 "(addr=0x%x, len=%d).\n", addr, len);
1489 return -1;
1490 }
1491
David Hendricksc1044262016-11-02 13:33:57 -07001492 msg_pspew("Reading %d bytes starting at 0x%06x.\n", len, addr);
stefanct83d99e82011-11-08 10:55:54 +00001493 /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
1494 REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
1495
1496 while (len > 0) {
David Hendricksac1d25c2016-08-09 17:00:58 -07001497 block_len = min(len, opaque_programmer->max_data_read);
stefanct83d99e82011-11-08 10:55:54 +00001498 ich_hwseq_set_addr(addr);
1499 hsfc = REGREAD16(ICH9_REG_HSFC);
1500 hsfc &= ~HSFC_FCYCLE; /* set read operation */
1501 hsfc &= ~HSFC_FDBC; /* clear byte count */
1502 /* set byte count */
1503 hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);
1504 hsfc |= HSFC_FGO; /* start */
1505 REGWRITE16(ICH9_REG_HSFC, hsfc);
1506
1507 if (ich_hwseq_wait_for_cycle_complete(timeout, block_len))
1508 return 1;
1509 ich_read_data(buf, block_len, ICH9_REG_FDATA0);
1510 addr += block_len;
1511 buf += block_len;
1512 len -= block_len;
1513 }
1514 return 0;
1515}
1516
Patrick Georgiab8353e2017-02-03 18:32:01 +01001517static int ich_hwseq_write(struct flashctx *flash, const uint8_t *buf, unsigned int addr,
stefanctc5eb8a92011-11-23 09:13:48 +00001518 unsigned int len)
stefanct83d99e82011-11-08 10:55:54 +00001519{
1520 uint16_t hsfc;
1521 uint16_t timeout = 100 * 60;
1522 uint8_t block_len;
1523
Patrick Georgif3fa2992017-02-02 16:24:44 +01001524 if ((addr + len) > (flash->chip->total_size * 1024)) {
stefanct83d99e82011-11-08 10:55:54 +00001525 msg_perr("Request to write to an inaccessible memory address "
1526 "(addr=0x%x, len=%d).\n", addr, len);
1527 return -1;
1528 }
1529
David Hendricksc1044262016-11-02 13:33:57 -07001530 msg_pspew("Writing %d bytes starting at 0x%06x.\n", len, addr);
stefanct83d99e82011-11-08 10:55:54 +00001531 /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
1532 REGWRITE16(ICH9_REG_HSFS, REGREAD16(ICH9_REG_HSFS));
1533
1534 while (len > 0) {
1535 ich_hwseq_set_addr(addr);
David Hendricksac1d25c2016-08-09 17:00:58 -07001536 block_len = min(len, opaque_programmer->max_data_write);
stefanct83d99e82011-11-08 10:55:54 +00001537 ich_fill_data(buf, block_len, ICH9_REG_FDATA0);
1538 hsfc = REGREAD16(ICH9_REG_HSFC);
1539 hsfc &= ~HSFC_FCYCLE; /* clear operation */
1540 hsfc |= (0x2 << HSFC_FCYCLE_OFF); /* set write operation */
1541 hsfc &= ~HSFC_FDBC; /* clear byte count */
1542 /* set byte count */
1543 hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);
1544 hsfc |= HSFC_FGO; /* start */
1545 REGWRITE16(ICH9_REG_HSFC, hsfc);
1546
1547 if (ich_hwseq_wait_for_cycle_complete(timeout, block_len))
1548 return -1;
1549 addr += block_len;
1550 buf += block_len;
1551 len -= block_len;
1552 }
1553 return 0;
1554}
David Hendricks07af3a42011-07-11 22:13:02 -07001555
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301556/* Routines for PCH */
1557
1558/* Sets FLA in FADDR to (addr & 0x07FFFFFF) without touching other bits. */
David Hendricks7be91492016-12-27 18:43:45 -08001559static void pch100_hwseq_set_addr(uint32_t addr)
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301560{
1561 uint32_t addr_old = REGREAD32(PCH100_REG_FADDR) & ~0x07FFFFFF;
1562 REGWRITE32(PCH100_REG_FADDR, (addr & 0x07FFFFFF) | addr_old);
1563}
1564
1565/* Sets FADDR.FLA to 'addr' and returns the erase block size in bytes
1566 * of the block containing this address. May return nonsense if the address is
1567 * not valid. The erase block size for a specific address depends on the flash
1568 * partition layout as specified by FPB and the partition properties as defined
1569 * by UVSCC and LVSCC respectively. An alternative to implement this method
1570 * would be by querying FPB and the respective VSCC register directly.
1571 */
David Hendricks7be91492016-12-27 18:43:45 -08001572static uint32_t pch100_hwseq_get_erase_block_size(unsigned int addr)
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301573{
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301574 static const uint32_t dec_berase[4] = {
1575 256,
1576 4 * 1024,
1577 8 * 1024,
1578 64 * 1024
1579 };
David Hendricks7be91492016-12-27 18:43:45 -08001580 pch100_hwseq_set_addr(addr);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301581 return dec_berase[ERASE_BLOCK_SIZE];
1582}
1583
1584/* Polls for Cycle Done Status, Flash Cycle Error or timeout in 8 us intervals.
1585 Resets all error flags in HSFS.
1586 Returns 0 if the cycle completes successfully without errors within
1587 timeout us, 1 on errors. */
David Hendricks7be91492016-12-27 18:43:45 -08001588static int pch100_hwseq_wait_for_cycle_complete(unsigned int timeout,
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301589 unsigned int len)
1590{
David Hendricks7be91492016-12-27 18:43:45 -08001591 uint32_t hsfs, addr;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301592
1593 timeout /= 8; /* scale timeout duration to counter */
David Hendricks7be91492016-12-27 18:43:45 -08001594 while ((((hsfs = REGREAD32(PCH100_REG_HSFSC)) &
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301595 (HSFSC_FDONE | HSFSC_FCERR)) == 0) &&
1596 --timeout) {
1597 programmer_delay(8);
1598 }
David Hendricks7be91492016-12-27 18:43:45 -08001599 REGWRITE32(PCH100_REG_HSFSC, REGREAD32(PCH100_REG_HSFSC));
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301600 if (!timeout) {
1601 addr = REGREAD32(PCH100_REG_FADDR) & 0x07FFFFFF;
1602 msg_perr("Timeout error between offset 0x%08x and "
1603 "0x%08x (= 0x%08x + %d)!\n",
1604 addr, addr + len - 1, addr, len - 1);
1605 return 1;
1606 }
1607
1608 if (hsfs & HSFSC_FCERR) {
1609 addr = REGREAD32(PCH100_REG_FADDR) & 0x07FFFFFF;
1610 msg_perr("Transaction error between offset 0x%08x and "
Furquan Shaikh44088752016-07-11 22:48:08 -07001611 "0x%08x (= 0x%08x + %d)\n",
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301612 addr, addr + len - 1, addr, len - 1);
1613 return 1;
1614 }
1615 return 0;
1616}
1617
David Hendricks6c21ad72016-12-22 16:02:59 -08001618static int pch_hwseq_get_flash_id(struct flashctx *flash)
1619{
David Hendricks7be91492016-12-27 18:43:45 -08001620 uint32_t hsfsc, data, mfg_id, model_id;
David Hendricks6c21ad72016-12-22 16:02:59 -08001621 const struct flashchip *entry;
Furquan Shaikh81d6d142017-04-06 23:43:36 -07001622 const int len = sizeof(data);
David Hendricks6c21ad72016-12-22 16:02:59 -08001623
1624 /* make sure FDONE, FCERR, & AEL are cleared */
1625 REGWRITE32(PCH100_REG_HSFSC, REGREAD32(PCH100_REG_HSFSC));
1626
1627 /* Set RDID as flash cycle and FGO */
David Hendricks7be91492016-12-27 18:43:45 -08001628 hsfsc = REGREAD32(PCH100_REG_HSFSC);
David Hendricks6c21ad72016-12-22 16:02:59 -08001629 hsfsc &= ~HSFSC_FCYCLE;
Furquan Shaikh81d6d142017-04-06 23:43:36 -07001630 hsfsc &= ~HSFSC_FDBC;
1631 hsfsc |= ((len - 1) << HSFSC_FDBC_OFF) & HSFSC_FDBC;
David Hendricks6c21ad72016-12-22 16:02:59 -08001632 hsfsc |= (0x6 << HSFSC_FCYCLE_OFF) | HSFSC_FGO;
David Hendricks7be91492016-12-27 18:43:45 -08001633 REGWRITE32(PCH100_REG_HSFSC, hsfsc);
David Hendricks6c21ad72016-12-22 16:02:59 -08001634 /* poll for 100ms */
Furquan Shaikh81d6d142017-04-06 23:43:36 -07001635 if (pch100_hwseq_wait_for_cycle_complete(100 * 1000, len)) {
David Hendricks6c21ad72016-12-22 16:02:59 -08001636 msg_perr("Timed out waiting for RDID to complete.\n");
1637 return 0;
1638 }
1639
1640 /*
1641 * Data will appear in reverse order:
1642 * Byte 0: Manufacturer ID
1643 * Byte 1: Model ID (MSB)
1644 * Byte 2: Model ID (LSB)
1645 */
Furquan Shaikh81d6d142017-04-06 23:43:36 -07001646 ich_read_data((uint8_t *)&data, len, PCH100_REG_FDATA0);
David Hendricks6c21ad72016-12-22 16:02:59 -08001647 mfg_id = data & 0xff;
1648 model_id = (data & 0xff00) | ((data >> 16) & 0xff);
1649
1650 entry = flash_id_to_entry(mfg_id, model_id);
1651 if (entry == NULL) {
1652 msg_perr("Unable to identify chip, mfg_id: 0x%02x, "
1653 "model_id: 0x%02x\n", mfg_id, model_id);
1654 return 0;
1655 } else {
1656 msg_pdbg("Chip identified: %s\n", entry->name);
1657 /* Update informational flash chip entries only */
Patrick Georgif3fa2992017-02-02 16:24:44 +01001658 flash->chip->vendor = entry->vendor;
1659 flash->chip->name = entry->name;
1660 flash->chip->manufacture_id = entry->manufacture_id;
1661 flash->chip->model_id = entry->model_id;
David Hendricks6c21ad72016-12-22 16:02:59 -08001662 /* total_size read from flash descriptor */
Patrick Georgif3fa2992017-02-02 16:24:44 +01001663 flash->chip->page_size = entry->page_size;
1664 flash->chip->feature_bits = entry->feature_bits;
1665 flash->chip->tested = entry->tested;
David Hendricks6c21ad72016-12-22 16:02:59 -08001666 }
1667
1668 return 1;
1669}
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301670
David Hendricks7be91492016-12-27 18:43:45 -08001671int pch100_hwseq_probe(struct flashctx *flash)
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301672{
1673 uint32_t total_size, boundary = 0; /*There are no partitions in flash*/
David Hendricks0c93af02015-08-15 16:50:10 -07001674 uint32_t erase_size_high, size_high;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301675 struct block_eraser *eraser;
1676
David Hendricks6c21ad72016-12-22 16:02:59 -08001677 if (pch_hwseq_get_flash_id(flash) != 1) {
1678 msg_perr("Unable to read flash chip ID\n");
1679 return 0;
1680 }
1681
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301682 total_size = hwseq_data.size_comp0 + hwseq_data.size_comp1;
1683 msg_cdbg("Found %d attached SPI flash chip",
1684 (hwseq_data.size_comp1 != 0) ? 2 : 1);
1685 if (hwseq_data.size_comp1 != 0)
1686 msg_cdbg("s with a combined");
1687 else
1688 msg_cdbg(" with a");
1689 msg_cdbg(" density of %d kB.\n", total_size / 1024);
Patrick Georgif3fa2992017-02-02 16:24:44 +01001690 flash->chip->total_size = total_size / 1024;
1691 eraser = &(flash->chip->block_erasers[0]);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301692 size_high = total_size - boundary;
David Hendricks7be91492016-12-27 18:43:45 -08001693 erase_size_high = pch100_hwseq_get_erase_block_size(boundary);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301694 eraser->eraseblocks[0].size = erase_size_high;
1695 eraser->eraseblocks[0].count = size_high / erase_size_high;
1696 msg_cdbg("There are %d erase blocks with %d B each.\n",
1697 size_high / erase_size_high, erase_size_high);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301698 return 1;
1699}
1700
David Hendricks7be91492016-12-27 18:43:45 -08001701int pch100_hwseq_block_erase(struct flashctx *flash,
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301702 unsigned int addr,
1703 unsigned int len)
1704{
1705 uint32_t erase_block;
David Hendricks7be91492016-12-27 18:43:45 -08001706 uint32_t hsfc;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301707 uint32_t timeout = 5000 * 1000; /* 5 s for max 64 kB */
Ramya Vijaykumar71d69ad2015-10-01 11:26:40 +05301708 int result;
1709 int op_type;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301710
David Hendricks7be91492016-12-27 18:43:45 -08001711 erase_block = pch100_hwseq_get_erase_block_size(addr);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301712 if (len != erase_block) {
1713 msg_cerr("Erase block size for address 0x%06x is %d B, "
1714 "but requested erase block size is %d B. "
1715 "Not erasing anything.\n", addr, erase_block, len);
1716 return -1;
1717 }
1718
1719 /* Although the hardware supports this (it would erase the whole block
1720 * containing the address) we play safe here. */
1721 if (addr % erase_block != 0) {
1722 msg_cerr("Erase address 0x%06x is not aligned to the erase "
1723 "block boundary (any multiple of %d). "
1724 "Not erasing anything.\n", addr, erase_block);
1725 return -1;
1726 }
1727
Patrick Georgif3fa2992017-02-02 16:24:44 +01001728 if (addr + len > flash->chip->total_size * 1024) {
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301729 msg_perr("Request to erase some inaccessible memory address(es)"
1730 " (addr=0x%x, len=%d). "
1731 "Not erasing anything.\n", addr, len);
1732 return -1;
1733 }
1734
Ramya Vijaykumar71d69ad2015-10-01 11:26:40 +05301735 /* Check flash region permissions before erasing */
1736 op_type = HWSEQ_WRITE;
1737 result = check_fd_permissions_hwseq(op_type, addr, len);
1738 if (result)
1739 return result;
1740
David Hendricksc1044262016-11-02 13:33:57 -07001741 msg_pspew("Erasing %d bytes starting at 0x%06x.\n", len, addr);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301742
1743 /* make sure FDONE, FCERR, AEL are cleared by writing 1 to them */
David Hendricks7be91492016-12-27 18:43:45 -08001744 REGWRITE32(PCH100_REG_HSFSC, REGREAD32(PCH100_REG_HSFSC));
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301745
David Hendricks7be91492016-12-27 18:43:45 -08001746 hsfc = REGREAD32(PCH100_REG_HSFSC);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301747 hsfc &= ~HSFSC_FCYCLE; /* clear operation */
1748 hsfc |= (0x3 << HSFSC_FCYCLE_OFF); /* set erase operation */
1749 hsfc |= HSFSC_FGO; /* start */
David Hendricksc1044262016-11-02 13:33:57 -07001750 msg_pspew("HSFC used for block erasing: ");
David Hendricks7be91492016-12-27 18:43:45 -08001751 REGWRITE32(PCH100_REG_HSFSC, hsfc);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301752
David Hendricks7be91492016-12-27 18:43:45 -08001753 if (pch100_hwseq_wait_for_cycle_complete(timeout, len))
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301754 return -1;
1755 return 0;
1756}
1757
David Hendricks7be91492016-12-27 18:43:45 -08001758int pch100_hwseq_read(struct flashctx *flash, uint8_t *buf, unsigned int addr,
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301759 unsigned int len)
1760{
David Hendricks7be91492016-12-27 18:43:45 -08001761 uint32_t hsfc;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301762 uint16_t timeout = 100 * 60;
1763 uint8_t block_len;
Ramya Vijaykumar6037fbc2016-01-18 11:36:22 +05301764 int result = 0, chunk_status = 0;
Ramya Vijaykumar71d69ad2015-10-01 11:26:40 +05301765 int op_type;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301766
Patrick Georgif3fa2992017-02-02 16:24:44 +01001767 if ((addr + len) > (flash->chip->total_size * 1024)) {
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301768 msg_perr("Request to read from an inaccessible memory address "
1769 "(addr=0x%x, len=%d).\n", addr, len);
1770 return -1;
1771 }
1772
David Hendricksc1044262016-11-02 13:33:57 -07001773 msg_pspew("Reading %d bytes starting at 0x%06x.\n", len, addr);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301774 /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
1775
David Hendricks7be91492016-12-27 18:43:45 -08001776 REGWRITE32(PCH100_REG_HSFSC, REGREAD32(PCH100_REG_HSFSC));
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301777
1778 while (len > 0) {
David Hendricksac1d25c2016-08-09 17:00:58 -07001779 block_len = min(len, opaque_programmer->max_data_read);
Ramya Vijaykumar71d69ad2015-10-01 11:26:40 +05301780 /* Check flash region permissions before reading */
1781 op_type = HWSEQ_READ;
Ramya Vijaykumar6037fbc2016-01-18 11:36:22 +05301782 chunk_status = check_fd_permissions_hwseq(op_type,
1783 addr, block_len);
1784 if (chunk_status) {
1785 if (ignore_error(chunk_status)) {
1786 /* fill this chunk with 0xff bytes and
1787 * inform the caller about the error */
1788 memset(buf, 0xff, block_len);
1789 result = chunk_status;
1790 } else {
1791 return chunk_status;
1792 }
1793 } else {
David Hendricks7be91492016-12-27 18:43:45 -08001794 pch100_hwseq_set_addr(addr);
1795 hsfc = REGREAD32(PCH100_REG_HSFSC);
Ramya Vijaykumar6037fbc2016-01-18 11:36:22 +05301796 hsfc &= ~HSFSC_FCYCLE; /* set read operation */
Ramya Vijaykumar6037fbc2016-01-18 11:36:22 +05301797 hsfc &= ~HSFSC_FDBC; /* clear byte count */
1798 /* set byte count */
1799 hsfc |= (((block_len - 1) << HSFSC_FDBC_OFF) & HSFSC_FDBC);
1800 hsfc |= HSFSC_FGO; /* start */
David Hendricks7be91492016-12-27 18:43:45 -08001801 REGWRITE32(PCH100_REG_HSFSC, hsfc);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301802
David Hendricks7be91492016-12-27 18:43:45 -08001803 if (pch100_hwseq_wait_for_cycle_complete(timeout, block_len))
Ramya Vijaykumar6037fbc2016-01-18 11:36:22 +05301804 return 1;
1805 ich_read_data(buf, block_len, PCH100_REG_FDATA0);
1806 }
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301807 addr += block_len;
1808 buf += block_len;
1809 len -= block_len;
1810 }
Ramya Vijaykumar6037fbc2016-01-18 11:36:22 +05301811 return result;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301812}
1813
David Hendricks7be91492016-12-27 18:43:45 -08001814uint8_t pch100_hwseq_read_status(const struct flashctx *flash)
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301815{
David Hendricks7be91492016-12-27 18:43:45 -08001816 uint32_t hsfc;
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301817 uint16_t timeout = 100 * 60;
1818 int len = 1;
1819 uint8_t buf;
1820
1821 msg_pdbg("Reading Status register\n");
1822
1823 /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
David Hendricks7be91492016-12-27 18:43:45 -08001824 REGWRITE32(PCH100_REG_HSFSC, REGREAD32(PCH100_REG_HSFSC));
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301825
David Hendricks7be91492016-12-27 18:43:45 -08001826 hsfc = REGREAD32(PCH100_REG_HSFSC);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301827 hsfc &= ~HSFSC_FCYCLE; /* set read operation */
1828
1829 /* read status register */
1830 hsfc |= (0x8 << HSFSC_FCYCLE_OFF);
1831
1832 hsfc &= ~HSFSC_FDBC; /* clear byte count */
1833 /* set byte count */
1834 hsfc |= (((len - 1) << HSFSC_FDBC_OFF) & HSFSC_FDBC);
1835 hsfc |= HSFSC_FGO; /* start */
David Hendricks7be91492016-12-27 18:43:45 -08001836 REGWRITE32(PCH100_REG_HSFSC, hsfc);
1837 if (pch100_hwseq_wait_for_cycle_complete(timeout, len)) {
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301838 msg_perr("Reading Status register failed\n!!");
1839 return -1;
1840 }
1841 ich_read_data(&buf, len, PCH100_REG_FDATA0);
1842 return buf;
1843}
1844
David Hendricks7be91492016-12-27 18:43:45 -08001845int pch100_hwseq_write(struct flashctx *flash, const uint8_t *buf, unsigned int addr,
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301846 unsigned int len)
1847{
David Hendricks7be91492016-12-27 18:43:45 -08001848 uint32_t hsfc;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301849 uint16_t timeout = 100 * 60;
1850 uint8_t block_len;
Ramya Vijaykumar71d69ad2015-10-01 11:26:40 +05301851 int result;
1852 int op_type;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301853
Patrick Georgif3fa2992017-02-02 16:24:44 +01001854 if ((addr + len) > (flash->chip->total_size * 1024)) {
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301855 msg_perr("Request to write to an inaccessible memory address "
1856 "(addr=0x%x, len=%d).\n", addr, len);
1857 return -1;
1858 }
1859
David Hendricksc1044262016-11-02 13:33:57 -07001860 msg_pspew("Writing %d bytes starting at 0x%06x.\n", len, addr);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301861 /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
David Hendricks7be91492016-12-27 18:43:45 -08001862 REGWRITE32(PCH100_REG_HSFSC, REGREAD32(PCH100_REG_HSFSC));
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301863
1864 while (len > 0) {
David Hendricks7be91492016-12-27 18:43:45 -08001865 pch100_hwseq_set_addr(addr);
David Hendricksac1d25c2016-08-09 17:00:58 -07001866 block_len = min(len, opaque_programmer->max_data_write);
Ramya Vijaykumar71d69ad2015-10-01 11:26:40 +05301867 /* Check flash region permissions before writing */
1868 op_type = HWSEQ_WRITE;
1869 result = check_fd_permissions_hwseq(op_type, addr, block_len);
1870 if (result)
1871 return result;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301872 ich_fill_data(buf, block_len, PCH100_REG_FDATA0);
David Hendricks7be91492016-12-27 18:43:45 -08001873 hsfc = REGREAD32(PCH100_REG_HSFSC);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301874 hsfc &= ~HSFSC_FCYCLE; /* clear operation */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301875 /* set write operation */
1876 hsfc |= (0x2 << HSFSC_FCYCLE_OFF);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301877 hsfc &= ~HSFSC_FDBC; /* clear byte count */
1878 /* set byte count */
1879 hsfc |= (((block_len - 1) << HSFSC_FDBC_OFF) & HSFSC_FDBC);
1880 hsfc |= HSFSC_FGO; /* start */
David Hendricks7be91492016-12-27 18:43:45 -08001881 REGWRITE32(PCH100_REG_HSFSC, hsfc);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301882
David Hendricks7be91492016-12-27 18:43:45 -08001883 if (pch100_hwseq_wait_for_cycle_complete(timeout, block_len))
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05301884 return -1;
1885 addr += block_len;
1886 buf += block_len;
1887 len -= block_len;
1888 }
1889 return 0;
1890}
1891
David Hendricks7be91492016-12-27 18:43:45 -08001892int pch100_hwseq_write_status(const struct flashctx *flash, int status)
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301893{
David Hendricks7be91492016-12-27 18:43:45 -08001894 uint32_t hsfc;
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301895 uint16_t timeout = 100 * 60;
1896 int len = 1;
1897 uint8_t buf = status;
1898
1899 msg_pdbg("Writing status register\n");
1900
1901 /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
David Hendricks7be91492016-12-27 18:43:45 -08001902 REGWRITE32(PCH100_REG_HSFSC, REGREAD32(PCH100_REG_HSFSC));
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301903
1904 ich_fill_data(&buf, len, PCH100_REG_FDATA0);
David Hendricks7be91492016-12-27 18:43:45 -08001905 hsfc = REGREAD32(PCH100_REG_HSFSC);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301906 hsfc &= ~HSFSC_FCYCLE; /* clear operation */
1907
1908 /* write status register */
1909 hsfc |= (0x7 << HSFSC_FCYCLE_OFF);
1910 hsfc &= ~HSFSC_FDBC; /* clear byte count */
1911
1912 /* set byte count */
1913 hsfc |= (((len - 1) << HSFSC_FDBC_OFF) & HSFSC_FDBC);
1914 hsfc |= HSFSC_FGO; /* start */
David Hendricks7be91492016-12-27 18:43:45 -08001915 REGWRITE32(PCH100_REG_HSFSC, hsfc);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301916
David Hendricks7be91492016-12-27 18:43:45 -08001917 if (pch100_hwseq_wait_for_cycle_complete(timeout, len)) {
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301918 msg_perr("Writing Status register failed\n!!");
1919 return -1;
1920 }
1921 return 0;
1922}
1923
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001924static int ich_spi_send_multicommand(const struct flashctx *flash, struct spi_command *cmds)
hailfinger948b81f2009-07-22 15:36:50 +00001925{
1926 int ret = 0;
hailfinger82e32492010-02-11 11:28:37 +00001927 int i;
hailfingerbb092112009-09-18 15:50:56 +00001928 int oppos, preoppos;
1929 for (; (cmds->writecnt || cmds->readcnt) && !ret; cmds++) {
hailfingerbb092112009-09-18 15:50:56 +00001930 if ((cmds + 1)->writecnt || (cmds + 1)->readcnt) {
hailfinger82e32492010-02-11 11:28:37 +00001931 /* Next command is valid. */
hailfingerbb092112009-09-18 15:50:56 +00001932 preoppos = find_preop(curopcodes, cmds->writearr[0]);
1933 oppos = find_opcode(curopcodes, (cmds + 1)->writearr[0]);
hailfinger82e32492010-02-11 11:28:37 +00001934 if ((oppos == -1) && (preoppos != -1)) {
1935 /* Current command is listed as preopcode in
1936 * ICH struct OPCODES, but next command is not
1937 * listed as opcode in that struct.
1938 * Check for command sanity, then
1939 * try to reprogram the ICH opcode list.
1940 */
1941 if (find_preop(curopcodes,
1942 (cmds + 1)->writearr[0]) != -1) {
snelsone42c3802010-05-07 20:09:04 +00001943 msg_perr("%s: Two subsequent "
hailfinger82e32492010-02-11 11:28:37 +00001944 "preopcodes 0x%02x and 0x%02x, "
1945 "ignoring the first.\n",
1946 __func__, cmds->writearr[0],
1947 (cmds + 1)->writearr[0]);
1948 continue;
1949 }
1950 /* If the chipset is locked down, we'll fail
1951 * during execution of the next command anyway.
1952 * No need to bother with fixups.
1953 */
1954 if (!ichspi_lock) {
hailfinger4c973122010-10-05 22:06:05 +00001955 oppos = reprogram_opcode_on_the_fly((cmds + 1)->writearr[0], (cmds + 1)->writecnt, (cmds + 1)->readcnt);
1956 if (oppos == -1)
1957 continue;
1958 curopcodes->opcode[oppos].atomic = preoppos + 1;
hailfinger82e32492010-02-11 11:28:37 +00001959 continue;
1960 }
1961 }
1962 if ((oppos != -1) && (preoppos != -1)) {
1963 /* Current command is listed as preopcode in
1964 * ICH struct OPCODES and next command is listed
1965 * as opcode in that struct. Match them up.
1966 */
1967 curopcodes->opcode[oppos].atomic = preoppos + 1;
hailfingerbb092112009-09-18 15:50:56 +00001968 continue;
hailfinger82e32492010-02-11 11:28:37 +00001969 }
1970 /* If none of the above if-statements about oppos or
1971 * preoppos matched, this is a normal opcode.
1972 */
1973 }
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001974 ret = ich_spi_send_command(flash, cmds->writecnt, cmds->readcnt,
hailfingerbb092112009-09-18 15:50:56 +00001975 cmds->writearr, cmds->readarr);
hailfinger82e32492010-02-11 11:28:37 +00001976 /* Reset the type of all opcodes to non-atomic. */
1977 for (i = 0; i < 8; i++)
1978 curopcodes->opcode[i].atomic = 0;
hailfinger948b81f2009-07-22 15:36:50 +00001979 }
1980 return ret;
1981}
hailfinger324a9cc2010-05-26 01:45:41 +00001982
mkarcher74d30132010-07-22 18:04:15 +00001983#define ICH_BMWAG(x) ((x >> 24) & 0xff)
1984#define ICH_BMRAG(x) ((x >> 16) & 0xff)
1985#define ICH_BRWA(x) ((x >> 8) & 0xff)
1986#define ICH_BRRA(x) ((x >> 0) & 0xff)
1987
David Hendricks53540f92016-09-03 00:34:41 +00001988static void do_ich9_spi_frap(uint32_t frap, int i)
mkarcher74d30132010-07-22 18:04:15 +00001989{
mkarcher74d30132010-07-22 18:04:15 +00001990 int rwperms = (((ICH_BRWA(frap) >> i) & 1) << 1) |
1991 (((ICH_BRRA(frap) >> i) & 1) << 0);
stefanct24bda702011-06-12 08:14:10 +00001992 int offset = ICH9_REG_FREG0 + i * 4;
mkarcher74d30132010-07-22 18:04:15 +00001993 uint32_t freg = mmio_readl(ich_spibar + offset);
1994
David Hendricks53540f92016-09-03 00:34:41 +00001995 msg_pdbg("0x%02X: 0x%08x (FREG%i: %s)\n",
1996 offset, freg, i, fd_regions[i].name);
1997
David Hendricks1ed1d352011-11-23 17:54:37 -08001998 fd_regions[i].base = ICH_FREG_BASE(freg);
1999 fd_regions[i].limit = ICH_FREG_LIMIT(freg) | 0x0fff;
2000 fd_regions[i].permission = &fd_region_permissions[rwperms];
2001 if (fd_regions[i].base > fd_regions[i].limit) {
mkarcher74d30132010-07-22 18:04:15 +00002002 /* this FREG is disabled */
David Hendricks53540f92016-09-03 00:34:41 +00002003 msg_pdbg("%s region is unused.\n", region_names[i]);
2004 return;
mkarcher74d30132010-07-22 18:04:15 +00002005 }
David Hendricks53540f92016-09-03 00:34:41 +00002006
2007 msg_pdbg("0x%08x-0x%08x is %s\n", fd_regions[i].base,
2008 fd_regions[i].limit, fd_regions[i].permission->name);
mkarcher74d30132010-07-22 18:04:15 +00002009}
2010
stefanct7ab834a2011-09-17 21:21:48 +00002011 /* In contrast to FRAP and the master section of the descriptor the bits
2012 * in the PR registers have an inverted meaning. The bits in FRAP
2013 * indicate read and write access _grant_. Here they indicate read
2014 * and write _protection_ respectively. If both bits are 0 the address
2015 * bits are ignored.
2016 */
2017#define ICH_PR_PERMS(pr) (((~((pr) >> PR_RP_OFF) & 1) << 0) | \
2018 ((~((pr) >> PR_WP_OFF) & 1) << 1))
2019
David Hendricks53540f92016-09-03 00:34:41 +00002020static void prettyprint_ich9_reg_pr(int i, int chipset)
stefanct7ab834a2011-09-17 21:21:48 +00002021{
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302022 uint8_t off;
2023 switch (chipset) {
2024 case CHIPSET_100_SERIES_SUNRISE_POINT:
Furquan Shaikh44088752016-07-11 22:48:08 -07002025 case CHIPSET_APL:
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302026 off = PCH100_REG_FPR0 + (i * 4);
2027 break;
2028 default:
2029 off = ICH9_REG_PR0 + (i * 4);
2030 break;
2031 }
stefanct7ab834a2011-09-17 21:21:48 +00002032 uint32_t pr = mmio_readl(ich_spibar + off);
David Hendricks53540f92016-09-03 00:34:41 +00002033 int rwperms = ICH_PR_PERMS(pr);
stefanct7ab834a2011-09-17 21:21:48 +00002034
David Hendricks53540f92016-09-03 00:34:41 +00002035 msg_pdbg2("0x%02X: 0x%08x (PR%u", off, pr, i);
2036 if (rwperms != 0x3)
2037 msg_pdbg2(")\n0x%08x-0x%08x is %s\n", ICH_FREG_BASE(pr),
2038 ICH_FREG_LIMIT(pr) | 0x0fff, access_names[rwperms]);
2039 else
2040 msg_pdbg2(", unused)\n");
stefanct7ab834a2011-09-17 21:21:48 +00002041}
2042
stefanctdd95a212011-09-17 22:21:55 +00002043/* Set/Clear the read and write protection enable bits of PR register @i
2044 * according to @read_prot and @write_prot. */
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302045static void ich9_set_pr(int i, int read_prot, int write_prot, int chipset)
stefanctdd95a212011-09-17 22:21:55 +00002046{
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302047 void *addr;
2048 switch (chipset) {
2049 case CHIPSET_100_SERIES_SUNRISE_POINT:
Furquan Shaikh44088752016-07-11 22:48:08 -07002050 case CHIPSET_APL:
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302051 addr = ich_spibar + PCH100_REG_FPR0 + (i * 4);
2052 break;
2053 default:
2054 addr = ich_spibar + ICH9_REG_PR0 + (i * 4);
2055 break;
2056 }
stefanctdd95a212011-09-17 22:21:55 +00002057 uint32_t old = mmio_readl(addr);
2058 uint32_t new;
2059
2060 msg_gspew("PR%u is 0x%08x", i, old);
2061 new = old & ~((1 << PR_RP_OFF) | (1 << PR_WP_OFF));
2062 if (read_prot)
2063 new |= (1 << PR_RP_OFF);
2064 if (write_prot)
2065 new |= (1 << PR_WP_OFF);
2066 if (old == new) {
2067 msg_gspew(" already.\n");
2068 return;
2069 }
2070 msg_gspew(", trying to set it to 0x%08x ", new);
2071 rmmio_writel(new, addr);
2072 msg_gspew("resulted in 0x%08x.\n", mmio_readl(addr));
2073}
2074
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002075static const struct spi_master spi_master_ich7 = {
mkarcherd264e9e2011-05-11 17:07:07 +00002076 .type = SPI_CONTROLLER_ICH7,
2077 .max_data_read = 64,
2078 .max_data_write = 64,
2079 .command = ich_spi_send_command,
2080 .multicommand = ich_spi_send_multicommand,
2081 .read = default_spi_read,
2082 .write_256 = default_spi_write_256,
2083};
2084
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002085static const struct spi_master spi_master_ich9 = {
mkarcherd264e9e2011-05-11 17:07:07 +00002086 .type = SPI_CONTROLLER_ICH9,
2087 .max_data_read = 64,
2088 .max_data_write = 64,
2089 .command = ich_spi_send_command,
2090 .multicommand = ich_spi_send_multicommand,
2091 .read = default_spi_read,
2092 .write_256 = default_spi_write_256,
2093};
2094
David Hendricks7be91492016-12-27 18:43:45 -08002095static struct opaque_programmer opaque_programmer_pch100_hwseq = {
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302096 .max_data_read = 64,
2097 .max_data_write = 64,
David Hendricks7be91492016-12-27 18:43:45 -08002098 .probe = pch100_hwseq_probe,
2099 .read = pch100_hwseq_read,
2100 .write = pch100_hwseq_write,
2101 .read_status = pch100_hwseq_read_status,
2102 .write_status = pch100_hwseq_write_status,
2103 .erase = pch100_hwseq_block_erase,
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302104};
stefanct83d99e82011-11-08 10:55:54 +00002105
Vadim Bendeburya6f9c4a2013-09-19 14:38:34 -07002106static struct opaque_programmer opaque_programmer_ich_hwseq = {
David Hendricks07af3a42011-07-11 22:13:02 -07002107 .max_data_read = 64,
2108 .max_data_write = 64,
stefanct83d99e82011-11-08 10:55:54 +00002109 .probe = ich_hwseq_probe,
David Hendricks07af3a42011-07-11 22:13:02 -07002110 .read = ich_hwseq_read,
stefanct83d99e82011-11-08 10:55:54 +00002111 .write = ich_hwseq_write,
2112 .erase = ich_hwseq_block_erase,
David Hendricks07af3a42011-07-11 22:13:02 -07002113};
2114
mkarcher74d30132010-07-22 18:04:15 +00002115int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
stefanctc035c192011-11-06 23:51:09 +00002116 enum ich_chipset ich_gen)
mkarcher74d30132010-07-22 18:04:15 +00002117{
2118 int i;
2119 uint8_t old, new;
2120 uint16_t spibar_offset, tmp2;
2121 uint32_t tmp;
stefanct83d99e82011-11-08 10:55:54 +00002122 char *arg;
stefanct3d3b6ee2011-10-20 12:57:14 +00002123 int desc_valid = 0;
stefanct83d99e82011-11-08 10:55:54 +00002124 struct ich_descriptors desc = {{ 0 }};
2125 enum ich_spi_mode {
2126 ich_auto,
2127 ich_hwseq,
2128 ich_swseq
2129 } ich_spi_mode = ich_auto;
mkarcher74d30132010-07-22 18:04:15 +00002130
stefanctc035c192011-11-06 23:51:09 +00002131 ich_generation = ich_gen;
2132
mkarcher74d30132010-07-22 18:04:15 +00002133 switch (ich_generation) {
Duncan Lauried59ec692013-11-25 09:40:56 -08002134 case CHIPSET_BAYTRAIL:
2135 spibar_offset = 0;
2136 break;
stefanctc035c192011-11-06 23:51:09 +00002137 case CHIPSET_ICH_UNKNOWN:
stefanct83d99e82011-11-08 10:55:54 +00002138 return ERROR_FATAL;
stefanctc035c192011-11-06 23:51:09 +00002139 case CHIPSET_ICH7:
2140 case CHIPSET_ICH8:
mkarcher74d30132010-07-22 18:04:15 +00002141 spibar_offset = 0x3020;
2142 break;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302143 case CHIPSET_100_SERIES_SUNRISE_POINT:
Furquan Shaikh44088752016-07-11 22:48:08 -07002144 case CHIPSET_APL:
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302145 spibar_offset = 0x0;
2146 break;
stefanctc035c192011-11-06 23:51:09 +00002147 case CHIPSET_ICH9:
mkarcher74d30132010-07-22 18:04:15 +00002148 default: /* Future version might behave the same */
mkarcher74d30132010-07-22 18:04:15 +00002149 spibar_offset = 0x3800;
2150 break;
2151 }
2152
2153 /* SPIBAR is at RCRB+0x3020 for ICH[78] and RCRB+0x3800 for ICH9. */
2154 msg_pdbg("SPIBAR = 0x%x + 0x%04x\n", base, spibar_offset);
2155
2156 /* Assign Virtual Address */
2157 ich_spibar = rcrb + spibar_offset;
2158
David Hendricks07af3a42011-07-11 22:13:02 -07002159 switch (ich_generation) {
stefanctc035c192011-11-06 23:51:09 +00002160 case CHIPSET_ICH7:
mkarcher74d30132010-07-22 18:04:15 +00002161 msg_pdbg("0x00: 0x%04x (SPIS)\n",
2162 mmio_readw(ich_spibar + 0));
2163 msg_pdbg("0x02: 0x%04x (SPIC)\n",
2164 mmio_readw(ich_spibar + 2));
2165 msg_pdbg("0x04: 0x%08x (SPIA)\n",
2166 mmio_readl(ich_spibar + 4));
2167 for (i = 0; i < 8; i++) {
2168 int offs;
2169 offs = 8 + (i * 8);
2170 msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs,
2171 mmio_readl(ich_spibar + offs), i);
2172 msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4,
2173 mmio_readl(ich_spibar + offs + 4), i);
2174 }
2175 ichspi_bbar = mmio_readl(ich_spibar + 0x50);
2176 msg_pdbg("0x50: 0x%08x (BBAR)\n",
2177 ichspi_bbar);
2178 msg_pdbg("0x54: 0x%04x (PREOP)\n",
2179 mmio_readw(ich_spibar + 0x54));
2180 msg_pdbg("0x56: 0x%04x (OPTYPE)\n",
2181 mmio_readw(ich_spibar + 0x56));
2182 msg_pdbg("0x58: 0x%08x (OPMENU)\n",
2183 mmio_readl(ich_spibar + 0x58));
2184 msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n",
2185 mmio_readl(ich_spibar + 0x5c));
stefanctc73c1db2011-07-24 15:34:56 +00002186 for (i = 0; i < 3; i++) {
mkarcher74d30132010-07-22 18:04:15 +00002187 int offs;
2188 offs = 0x60 + (i * 4);
2189 msg_pdbg("0x%02x: 0x%08x (PBR%d)\n", offs,
2190 mmio_readl(ich_spibar + offs), i);
2191 }
mkarcher74d30132010-07-22 18:04:15 +00002192 if (mmio_readw(ich_spibar) & (1 << 15)) {
David Hendricks1433b032011-11-30 15:26:25 -08002193 msg_pdbg("WARNING: SPI Configuration Lockdown activated.\n");
mkarcher74d30132010-07-22 18:04:15 +00002194 ichspi_lock = 1;
2195 }
stefanct4e138892011-11-13 15:17:10 +00002196 ich_init_opcodes();
stefanctc035c192011-11-06 23:51:09 +00002197 ich_set_bbar(0);
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002198 register_spi_master(&spi_master_ich7);
mkarcher74d30132010-07-22 18:04:15 +00002199 break;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302200 case CHIPSET_100_SERIES_SUNRISE_POINT:
Furquan Shaikh44088752016-07-11 22:48:08 -07002201 case CHIPSET_APL:
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302202 arg = extract_programmer_param("ich_spi_mode");
2203 if (arg && !strcmp(arg, "hwseq")) {
2204 ich_spi_mode = ich_hwseq;
2205 msg_pspew("user selected hwseq\n");
2206 } else if (arg && !strcmp(arg, "swseq")) {
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +05302207 /* Swseq not supported in SP */
2208 msg_perr("swseq not supported\n");
2209 free(arg);
2210 return ERROR_FATAL;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302211 } else if (arg && !strcmp(arg, "auto")) {
2212 msg_pspew("user selected auto\n");
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +05302213 /* default mode in SP */
2214 ich_spi_mode = ich_hwseq;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302215 } else if (arg && !strlen(arg)) {
2216 msg_perr("Missing argument for ich_spi_mode.\n");
2217 free(arg);
2218 return ERROR_FATAL;
2219 } else if (arg) {
2220 msg_perr("Unknown argument for ich_spi_mode: %s\n",
2221 arg);
2222 free(arg);
2223 return ERROR_FATAL;
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +05302224 } else {
2225 /* default mode in SP */
2226 ich_spi_mode = ich_hwseq;
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302227 }
2228 free(arg);
2229 tmp = mmio_readl(ich_spibar + PCH100_REG_HSFSC);
David Hendricks7be91492016-12-27 18:43:45 -08002230 msg_pdbg("0x04: 0x%08x (HSFSC)\n", tmp);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302231 if (tmp & HSFSC_FLOCKDN) {
2232 msg_perr("WARNING: SPI Configuration "
2233 "Lockdown activated.\n");
2234 ichspi_lock = 1;
2235 }
2236 if (tmp & HSFSC_FDV)
2237 desc_valid = 1;
2238
2239 if (!(tmp & HSFSC_FDOPSS) && desc_valid)
2240 msg_perr("The Flash Descriptor Security Override "
2241 "Strap-Pin is set. Restrictions implied\n"
2242 "by the FRAP and FREG registers are NOT in "
2243 "effect. Please note that Protected\n"
2244 "Range (PR) restrictions still apply.\n");
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302245
2246 if (desc_valid) {
2247 num_fd_regions = DEFAULT_NUM_FD_REGIONS;
2248 }
2249 tmp = mmio_readl(ich_spibar + PCH100_REG_FADDR);
2250 msg_pdbg("0x08: 0x%08x (FADDR)\n", tmp);
2251 if (desc_valid) {
2252 tmp = mmio_readl(ich_spibar + ICH9_REG_FRAP);
2253 msg_cdbg("0x50: 0x%08x (FRAP)\n", tmp);
2254 msg_cdbg("BMWAG 0x%02x, ", ICH_BMWAG(tmp));
2255 msg_cdbg("BMRAG 0x%02x, ", ICH_BMRAG(tmp));
2256 msg_cdbg("BRWA 0x%02x, ", ICH_BRWA(tmp));
2257 msg_cdbg("BRRA 0x%02x\n", ICH_BRRA(tmp));
2258
2259 /* Decode and print FREGx and FRAP registers */
2260 for (i = 0; i < num_fd_regions; i++)
David Hendricks53540f92016-09-03 00:34:41 +00002261 do_ich9_spi_frap(tmp, i);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302262 }
2263 /* try to disable PR locks before printing them */
2264 if (!ichspi_lock)
2265 for (i = 0; i < num_fd_regions; i++)
2266 ich9_set_pr(i, 0, 0, ich_generation);
2267 for (i = 0; i < num_fd_regions; i++)
David Hendricks53540f92016-09-03 00:34:41 +00002268 prettyprint_ich9_reg_pr(i, ich_generation);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302269 if (desc_valid) {
2270 if (read_ich_descriptors_via_fdo(ich_spibar, &desc,
2271 ich_generation) == ICH_RET_OK)
2272 prettyprint_ich_descriptors(CHIPSET_ICH_UNKNOWN,
2273 &desc);
Duncan Laurie89ee23d2015-05-08 20:27:50 +00002274 } else {
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +05302275 msg_perr("Hardware sequencing was requested "
2276 "but the flash descriptor is not "
2277 "valid. Aborting.\n");
2278 return ERROR_FATAL;
Duncan Laurie89ee23d2015-05-08 20:27:50 +00002279 }
Ramya Vijaykumare6a7ca82015-05-12 14:27:29 +05302280 hwseq_data.size_comp0 = getFCBA_component_density(&desc, 0);
2281 hwseq_data.size_comp1 = getFCBA_component_density(&desc, 1);
David Hendricks7be91492016-12-27 18:43:45 -08002282 register_opaque_programmer(&opaque_programmer_pch100_hwseq);
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302283 break;
stefanctc035c192011-11-06 23:51:09 +00002284 case CHIPSET_ICH8:
David Hendricks07af3a42011-07-11 22:13:02 -07002285 default: /* Future version might behave the same */
stefanct83d99e82011-11-08 10:55:54 +00002286 arg = extract_programmer_param("ich_spi_mode");
2287 if (arg && !strcmp(arg, "hwseq")) {
2288 ich_spi_mode = ich_hwseq;
2289 msg_pspew("user selected hwseq\n");
2290 } else if (arg && !strcmp(arg, "swseq")) {
2291 ich_spi_mode = ich_swseq;
2292 msg_pspew("user selected swseq\n");
2293 } else if (arg && !strcmp(arg, "auto")) {
2294 msg_pspew("user selected auto\n");
2295 ich_spi_mode = ich_auto;
2296 } else if (arg && !strlen(arg)) {
2297 msg_perr("Missing argument for ich_spi_mode.\n");
2298 free(arg);
2299 return ERROR_FATAL;
2300 } else if (arg) {
2301 msg_perr("Unknown argument for ich_spi_mode: %s\n",
2302 arg);
2303 free(arg);
2304 return ERROR_FATAL;
2305 }
2306 free(arg);
2307
stefanct24bda702011-06-12 08:14:10 +00002308 tmp2 = mmio_readw(ich_spibar + ICH9_REG_HSFS);
mkarcher74d30132010-07-22 18:04:15 +00002309 msg_pdbg("0x04: 0x%04x (HSFS)\n", tmp2);
stefanctc274c862011-06-11 09:53:22 +00002310 prettyprint_ich9_reg_hsfs(tmp2);
stefanct24bda702011-06-12 08:14:10 +00002311 if (tmp2 & HSFS_FLOCKDN) {
David Hendricks1433b032011-11-30 15:26:25 -08002312 msg_pdbg("WARNING: SPI Configuration Lockdown activated.\n");
stefanctc274c862011-06-11 09:53:22 +00002313 ichspi_lock = 1;
2314 }
David Hendricksce6b2fa2011-07-11 22:12:43 -07002315 if (tmp2 & HSFS_FDV)
stefanct3d3b6ee2011-10-20 12:57:14 +00002316 desc_valid = 1;
2317 if (!(tmp2 & HSFS_FDOPSS) && desc_valid)
Louis Yung-Chieh Loe500e412012-01-19 15:19:47 +08002318 msg_perr("The Flash Descriptor Security Override "
2319 "Strap-Pin is set. Restrictions implied\n"
2320 "by the FRAP and FREG registers are NOT in "
2321 "effect. Please note that Protected\n"
2322 "Range (PR) restrictions still apply.\n");
stefanct4e138892011-11-13 15:17:10 +00002323 ich_init_opcodes();
stefanctc274c862011-06-11 09:53:22 +00002324
stefanctd0064e12011-11-08 11:55:24 +00002325 if (desc_valid) {
David Hendricks1ed1d352011-11-23 17:54:37 -08002326 num_fd_regions = DEFAULT_NUM_FD_REGIONS;
stefanctd0064e12011-11-08 11:55:24 +00002327 tmp2 = mmio_readw(ich_spibar + ICH9_REG_HSFC);
2328 msg_pdbg("0x06: 0x%04x (HSFC)\n", tmp2);
2329 prettyprint_ich9_reg_hsfc(tmp2);
2330 }
mkarcher74d30132010-07-22 18:04:15 +00002331
stefanct770ff772011-07-07 04:10:57 +00002332 tmp = mmio_readl(ich_spibar + ICH9_REG_FADDR);
2333 msg_pdbg("0x08: 0x%08x (FADDR)\n", tmp);
mkarcher74d30132010-07-22 18:04:15 +00002334
stefanctd0064e12011-11-08 11:55:24 +00002335 if (desc_valid) {
2336 tmp = mmio_readl(ich_spibar + ICH9_REG_FRAP);
2337 msg_pdbg("0x50: 0x%08x (FRAP)\n", tmp);
2338 msg_pdbg("BMWAG 0x%02x, ", ICH_BMWAG(tmp));
2339 msg_pdbg("BMRAG 0x%02x, ", ICH_BMRAG(tmp));
2340 msg_pdbg("BRWA 0x%02x, ", ICH_BRWA(tmp));
2341 msg_pdbg("BRRA 0x%02x\n", ICH_BRRA(tmp));
2342
David Hendricks53540f92016-09-03 00:34:41 +00002343 /* Decode and print FREGx and FRAP registers */
David Hendricks1ed1d352011-11-23 17:54:37 -08002344 for (i = 0; i < num_fd_regions; i++)
David Hendricks53540f92016-09-03 00:34:41 +00002345 do_ich9_spi_frap(tmp, i);
stefanctd0064e12011-11-08 11:55:24 +00002346 }
mkarcher74d30132010-07-22 18:04:15 +00002347
David Hendricks53540f92016-09-03 00:34:41 +00002348 /* try to disable PR locks before printing them */
2349 if (!ichspi_lock)
2350 for (i = 0; i < num_fd_regions; i++)
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302351 ich9_set_pr(i, 0, 0, ich_generation);
David Hendricks53540f92016-09-03 00:34:41 +00002352 for (i = 0; i < num_fd_regions; i++)
2353 prettyprint_ich9_reg_pr(i, ich_generation);
hailfinger01d05912011-03-17 00:10:25 +00002354
stefanct24bda702011-06-12 08:14:10 +00002355 tmp = mmio_readl(ich_spibar + ICH9_REG_SSFS);
hailfinger01d05912011-03-17 00:10:25 +00002356 msg_pdbg("0x90: 0x%02x (SSFS)\n", tmp & 0xff);
stefancte4d1ef52011-06-11 09:53:16 +00002357 prettyprint_ich9_reg_ssfs(tmp);
stefanct24bda702011-06-12 08:14:10 +00002358 if (tmp & SSFS_FCERR) {
hailfinger01d05912011-03-17 00:10:25 +00002359 msg_pdbg("Clearing SSFS.FCERR\n");
stefanct24bda702011-06-12 08:14:10 +00002360 mmio_writeb(SSFS_FCERR, ich_spibar + ICH9_REG_SSFS);
hailfinger01d05912011-03-17 00:10:25 +00002361 }
stefancte4d1ef52011-06-11 09:53:16 +00002362 msg_pdbg("0x91: 0x%06x (SSFC)\n", tmp >> 8);
2363 prettyprint_ich9_reg_ssfc(tmp);
hailfinger01d05912011-03-17 00:10:25 +00002364
mkarcher74d30132010-07-22 18:04:15 +00002365 msg_pdbg("0x94: 0x%04x (PREOP)\n",
stefanct24bda702011-06-12 08:14:10 +00002366 mmio_readw(ich_spibar + ICH9_REG_PREOP));
mkarcher74d30132010-07-22 18:04:15 +00002367 msg_pdbg("0x96: 0x%04x (OPTYPE)\n",
stefanct24bda702011-06-12 08:14:10 +00002368 mmio_readw(ich_spibar + ICH9_REG_OPTYPE));
mkarcher74d30132010-07-22 18:04:15 +00002369 msg_pdbg("0x98: 0x%08x (OPMENU)\n",
stefanct24bda702011-06-12 08:14:10 +00002370 mmio_readl(ich_spibar + ICH9_REG_OPMENU));
mkarcher74d30132010-07-22 18:04:15 +00002371 msg_pdbg("0x9C: 0x%08x (OPMENU+4)\n",
stefanct24bda702011-06-12 08:14:10 +00002372 mmio_readl(ich_spibar + ICH9_REG_OPMENU + 4));
stefanctd0064e12011-11-08 11:55:24 +00002373 if (ich_generation == CHIPSET_ICH8 && desc_valid) {
stefanct1fc3a732011-09-15 23:52:55 +00002374 tmp = mmio_readl(ich_spibar + ICH8_REG_VSCC);
2375 msg_pdbg("0xC1: 0x%08x (VSCC)\n", tmp);
2376 msg_pdbg("VSCC: ");
2377 prettyprint_ich_reg_vscc(tmp, MSG_DEBUG);
2378 } else {
2379 ichspi_bbar = mmio_readl(ich_spibar + ICH9_REG_BBAR);
2380 msg_pdbg("0xA0: 0x%08x (BBAR)\n",
2381 ichspi_bbar);
David Hendricksce6b2fa2011-07-11 22:12:43 -07002382
stefanctd0064e12011-11-08 11:55:24 +00002383 if (desc_valid) {
2384 tmp = mmio_readl(ich_spibar + ICH9_REG_LVSCC);
2385 msg_pdbg("0xC4: 0x%08x (LVSCC)\n", tmp);
2386 msg_pdbg("LVSCC: ");
2387 prettyprint_ich_reg_vscc(tmp, MSG_DEBUG);
David Hendricksce6b2fa2011-07-11 22:12:43 -07002388
stefanctd0064e12011-11-08 11:55:24 +00002389 tmp = mmio_readl(ich_spibar + ICH9_REG_UVSCC);
2390 msg_pdbg("0xC8: 0x%08x (UVSCC)\n", tmp);
2391 msg_pdbg("UVSCC: ");
2392 prettyprint_ich_reg_vscc(tmp, MSG_DEBUG);
David Hendricksce6b2fa2011-07-11 22:12:43 -07002393
stefanctd0064e12011-11-08 11:55:24 +00002394 tmp = mmio_readl(ich_spibar + ICH9_REG_FPB);
2395 msg_pdbg("0xD0: 0x%08x (FPB)\n", tmp);
2396 }
stefanctc035c192011-11-06 23:51:09 +00002397 ich_set_bbar(0);
stefanct1fc3a732011-09-15 23:52:55 +00002398 }
stefanctd68db982011-07-01 00:39:16 +00002399
David Hendricksce6b2fa2011-07-11 22:12:43 -07002400 msg_pdbg("\n");
stefanct3d3b6ee2011-10-20 12:57:14 +00002401 if (desc_valid) {
Ramya Vijaykumara9a64f92015-04-15 15:26:22 +05302402 if (read_ich_descriptors_via_fdo(ich_spibar, &desc,
2403 ich_generation) == ICH_RET_OK)
stefanct1fc3a732011-09-15 23:52:55 +00002404 prettyprint_ich_descriptors(CHIPSET_ICH_UNKNOWN,
2405 &desc);
stefanct83d99e82011-11-08 10:55:54 +00002406 /* If the descriptor is valid and indicates multiple
2407 * flash devices we need to use hwseq to be able to
2408 * access the second flash device.
2409 */
2410 if (ich_spi_mode == ich_auto && desc.content.NC != 0) {
2411 msg_pinfo("Enabling hardware sequencing due to "
2412 "multiple flash chips detected.\n");
2413 ich_spi_mode = ich_hwseq;
2414 }
David Hendricksce6b2fa2011-07-11 22:12:43 -07002415 }
stefanct83d99e82011-11-08 10:55:54 +00002416
2417 if (ich_spi_mode == ich_auto && ichspi_lock &&
2418 ich_missing_opcodes()) {
2419 msg_pinfo("Enabling hardware sequencing because "
2420 "some important opcode is locked.\n");
2421 ich_spi_mode = ich_hwseq;
2422 }
2423
2424 if (ich_spi_mode == ich_hwseq) {
2425 if (!desc_valid) {
2426 msg_perr("Hardware sequencing was requested "
2427 "but the flash descriptor is not "
2428 "valid. Aborting.\n");
2429 return ERROR_FATAL;
2430 }
2431 hwseq_data.size_comp0 = getFCBA_component_density(&desc, 0);
2432 hwseq_data.size_comp1 = getFCBA_component_density(&desc, 1);
2433 register_opaque_programmer(&opaque_programmer_ich_hwseq);
2434 } else {
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002435 register_spi_master(&spi_master_ich9);
stefanct83d99e82011-11-08 10:55:54 +00002436 }
stefanct1fc3a732011-09-15 23:52:55 +00002437 break;
mkarcher74d30132010-07-22 18:04:15 +00002438 }
2439
Duncan Lauried59ec692013-11-25 09:40:56 -08002440 switch (ich_generation) {
2441 case CHIPSET_BAYTRAIL:
mkarcher74d30132010-07-22 18:04:15 +00002442 break;
2443 default:
Furquan Shaikh44088752016-07-11 22:48:08 -07002444 if (ich_generation == CHIPSET_APL)
2445 old = mmio_readb((void *)dev + 0xdc);
2446 else
2447 old = pci_read_byte(dev, 0xdc);
Duncan Lauried59ec692013-11-25 09:40:56 -08002448 msg_pdbg("SPI Read Configuration: ");
2449 new = (old >> 2) & 0x3;
2450 switch (new) {
2451 case 0:
2452 case 1:
2453 case 2:
2454 msg_pdbg("prefetching %sabled, caching %sabled, ",
2455 (new & 0x2) ? "en" : "dis",
2456 (new & 0x1) ? "dis" : "en");
2457 break;
2458 default:
2459 msg_pdbg("invalid prefetching/caching settings, ");
2460 break;
2461 }
mkarcher74d30132010-07-22 18:04:15 +00002462 }
2463 return 0;
2464}
2465
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002466static const struct spi_master spi_master_via = {
mkarcherd264e9e2011-05-11 17:07:07 +00002467 .type = SPI_CONTROLLER_VIA,
2468 .max_data_read = 16,
2469 .max_data_write = 16,
2470 .command = ich_spi_send_command,
2471 .multicommand = ich_spi_send_multicommand,
2472 .read = default_spi_read,
2473 .write_256 = default_spi_write_256,
2474};
2475
mkarcher74d30132010-07-22 18:04:15 +00002476int via_init_spi(struct pci_dev *dev)
2477{
2478 uint32_t mmio_base;
hailfinger8fdd0a82010-11-24 23:37:22 +00002479 int i;
mkarcher74d30132010-07-22 18:04:15 +00002480
2481 mmio_base = (pci_read_long(dev, 0xbc)) << 8;
2482 msg_pdbg("MMIO base at = 0x%x\n", mmio_base);
2483 ich_spibar = physmap("VT8237S MMIO registers", mmio_base, 0x70);
2484
mkarcher74d30132010-07-22 18:04:15 +00002485 /* Not sure if it speaks all these bus protocols. */
hailfinger76bb7e92011-11-09 23:40:00 +00002486 internal_buses_supported = BUS_LPC | BUS_FWH;
stefanctc035c192011-11-06 23:51:09 +00002487 ich_generation = CHIPSET_ICH7;
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01002488 register_spi_master(&spi_master_via);
hailfinger8fdd0a82010-11-24 23:37:22 +00002489
2490 msg_pdbg("0x00: 0x%04x (SPIS)\n", mmio_readw(ich_spibar + 0));
2491 msg_pdbg("0x02: 0x%04x (SPIC)\n", mmio_readw(ich_spibar + 2));
2492 msg_pdbg("0x04: 0x%08x (SPIA)\n", mmio_readl(ich_spibar + 4));
2493 for (i = 0; i < 2; i++) {
2494 int offs;
2495 offs = 8 + (i * 8);
2496 msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs,
2497 mmio_readl(ich_spibar + offs), i);
2498 msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4,
2499 mmio_readl(ich_spibar + offs + 4), i);
2500 }
2501 ichspi_bbar = mmio_readl(ich_spibar + 0x50);
2502 msg_pdbg("0x50: 0x%08x (BBAR)\n", ichspi_bbar);
2503 msg_pdbg("0x54: 0x%04x (PREOP)\n", mmio_readw(ich_spibar + 0x54));
2504 msg_pdbg("0x56: 0x%04x (OPTYPE)\n", mmio_readw(ich_spibar + 0x56));
2505 msg_pdbg("0x58: 0x%08x (OPMENU)\n", mmio_readl(ich_spibar + 0x58));
2506 msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n", mmio_readl(ich_spibar + 0x5c));
2507 for (i = 0; i < 3; i++) {
2508 int offs;
2509 offs = 0x60 + (i * 4);
2510 msg_pdbg("0x%02x: 0x%08x (PBR%d)\n", offs,
2511 mmio_readl(ich_spibar + offs), i);
2512 }
2513 msg_pdbg("0x6c: 0x%04x (CLOCK/DEBUG)\n",
2514 mmio_readw(ich_spibar + 0x6c));
2515 if (mmio_readw(ich_spibar) & (1 << 15)) {
David Hendricks205782d2016-11-23 16:25:48 -08002516 msg_pdbg("WARNING: SPI Configuration Lockdown activated.\n");
hailfinger8fdd0a82010-11-24 23:37:22 +00002517 ichspi_lock = 1;
2518 }
2519
stefanctc035c192011-11-06 23:51:09 +00002520 ich_set_bbar(0);
mkarcher74d30132010-07-22 18:04:15 +00002521 ich_init_opcodes();
2522
2523 return 0;
2524}
2525
hailfinger324a9cc2010-05-26 01:45:41 +00002526#endif