blob: 08c37ca4ab4eff980fc785835667552a2ca60091 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass18530302013-03-19 04:58:56 +00002/*
3 * Copyright (c) 2011-12 The Chromium OS Authors.
4 *
Simon Glass18530302013-03-19 04:58:56 +00005 * This file is derived from the flashrom project.
6 */
Bin Meng9eb43392016-02-01 01:40:36 -08007
Simon Glassa5506622019-12-06 21:42:41 -07008#define LOG_CATEGORY UCLASS_SPI
9
Simon Glass18530302013-03-19 04:58:56 +000010#include <common.h>
Simon Glassb47aa262019-12-06 21:42:40 -070011#include <div64.h>
Simon Glassba457562015-03-26 09:29:26 -060012#include <dm.h>
Simon Glass5093bad2015-01-27 22:13:43 -070013#include <errno.h>
Simon Glass18530302013-03-19 04:58:56 +000014#include <malloc.h>
Simon Glassf2b85ab2016-01-18 20:19:21 -070015#include <pch.h>
Simon Glass18530302013-03-19 04:58:56 +000016#include <pci.h>
17#include <pci_ids.h>
Simon Glassf2b85ab2016-01-18 20:19:21 -070018#include <spi.h>
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +020019#include <spi-mem.h>
Simon Glassb47aa262019-12-06 21:42:40 -070020#include <asm/io.h>
Simon Glass18530302013-03-19 04:58:56 +000021
22#include "ich.h"
23
Simon Glassfffe25d2016-01-18 20:19:20 -070024#ifdef DEBUG_TRACE
25#define debug_trace(fmt, args...) debug(fmt, ##args)
26#else
27#define debug_trace(x, args...)
28#endif
29
Simon Glass75214b02019-12-06 21:42:42 -070030struct ich_spi_platdata {
31 enum ich_version ich_version; /* Controller version, 7 or 9 */
32 bool lockdown; /* lock down controller settings? */
33 ulong mmio_base; /* Base of MMIO registers */
34};
35
Simon Glassba457562015-03-26 09:29:26 -060036static u8 ich_readb(struct ich_spi_priv *priv, int reg)
Simon Glass18530302013-03-19 04:58:56 +000037{
Simon Glassba457562015-03-26 09:29:26 -060038 u8 value = readb(priv->base + reg);
Simon Glass18530302013-03-19 04:58:56 +000039
Simon Glassfffe25d2016-01-18 20:19:20 -070040 debug_trace("read %2.2x from %4.4x\n", value, reg);
Simon Glass18530302013-03-19 04:58:56 +000041
42 return value;
43}
44
Simon Glassba457562015-03-26 09:29:26 -060045static u16 ich_readw(struct ich_spi_priv *priv, int reg)
Simon Glass18530302013-03-19 04:58:56 +000046{
Simon Glassba457562015-03-26 09:29:26 -060047 u16 value = readw(priv->base + reg);
Simon Glass18530302013-03-19 04:58:56 +000048
Simon Glassfffe25d2016-01-18 20:19:20 -070049 debug_trace("read %4.4x from %4.4x\n", value, reg);
Simon Glass18530302013-03-19 04:58:56 +000050
51 return value;
52}
53
Simon Glassba457562015-03-26 09:29:26 -060054static u32 ich_readl(struct ich_spi_priv *priv, int reg)
Simon Glass18530302013-03-19 04:58:56 +000055{
Simon Glassba457562015-03-26 09:29:26 -060056 u32 value = readl(priv->base + reg);
Simon Glass18530302013-03-19 04:58:56 +000057
Simon Glassfffe25d2016-01-18 20:19:20 -070058 debug_trace("read %8.8x from %4.4x\n", value, reg);
Simon Glass18530302013-03-19 04:58:56 +000059
60 return value;
61}
62
Simon Glassba457562015-03-26 09:29:26 -060063static void ich_writeb(struct ich_spi_priv *priv, u8 value, int reg)
Simon Glass18530302013-03-19 04:58:56 +000064{
Simon Glassba457562015-03-26 09:29:26 -060065 writeb(value, priv->base + reg);
Simon Glassfffe25d2016-01-18 20:19:20 -070066 debug_trace("wrote %2.2x to %4.4x\n", value, reg);
Simon Glass18530302013-03-19 04:58:56 +000067}
68
Simon Glassba457562015-03-26 09:29:26 -060069static void ich_writew(struct ich_spi_priv *priv, u16 value, int reg)
Simon Glass18530302013-03-19 04:58:56 +000070{
Simon Glassba457562015-03-26 09:29:26 -060071 writew(value, priv->base + reg);
Simon Glassfffe25d2016-01-18 20:19:20 -070072 debug_trace("wrote %4.4x to %4.4x\n", value, reg);
Simon Glass18530302013-03-19 04:58:56 +000073}
74
Simon Glassba457562015-03-26 09:29:26 -060075static void ich_writel(struct ich_spi_priv *priv, u32 value, int reg)
Simon Glass18530302013-03-19 04:58:56 +000076{
Simon Glassba457562015-03-26 09:29:26 -060077 writel(value, priv->base + reg);
Simon Glassfffe25d2016-01-18 20:19:20 -070078 debug_trace("wrote %8.8x to %4.4x\n", value, reg);
Simon Glass18530302013-03-19 04:58:56 +000079}
80
Simon Glassba457562015-03-26 09:29:26 -060081static void write_reg(struct ich_spi_priv *priv, const void *value,
82 int dest_reg, uint32_t size)
Simon Glass18530302013-03-19 04:58:56 +000083{
Simon Glassba457562015-03-26 09:29:26 -060084 memcpy_toio(priv->base + dest_reg, value, size);
Simon Glass18530302013-03-19 04:58:56 +000085}
86
Simon Glassba457562015-03-26 09:29:26 -060087static void read_reg(struct ich_spi_priv *priv, int src_reg, void *value,
88 uint32_t size)
Simon Glass18530302013-03-19 04:58:56 +000089{
Simon Glassba457562015-03-26 09:29:26 -060090 memcpy_fromio(value, priv->base + src_reg, size);
Simon Glass18530302013-03-19 04:58:56 +000091}
92
Simon Glassba457562015-03-26 09:29:26 -060093static void ich_set_bbar(struct ich_spi_priv *ctlr, uint32_t minaddr)
Simon Glass18530302013-03-19 04:58:56 +000094{
95 const uint32_t bbar_mask = 0x00ffff00;
96 uint32_t ichspi_bbar;
97
98 minaddr &= bbar_mask;
Simon Glassba457562015-03-26 09:29:26 -060099 ichspi_bbar = ich_readl(ctlr, ctlr->bbar) & ~bbar_mask;
Simon Glass18530302013-03-19 04:58:56 +0000100 ichspi_bbar |= minaddr;
Simon Glassba457562015-03-26 09:29:26 -0600101 ich_writel(ctlr, ichspi_bbar, ctlr->bbar);
Simon Glass18530302013-03-19 04:58:56 +0000102}
103
Simon Glass18530302013-03-19 04:58:56 +0000104/* @return 1 if the SPI flash supports the 33MHz speed */
Simon Glassa5506622019-12-06 21:42:41 -0700105static bool ich9_can_do_33mhz(struct udevice *dev)
Simon Glass18530302013-03-19 04:58:56 +0000106{
Simon Glass17e75442019-12-06 21:42:38 -0700107 struct ich_spi_priv *priv = dev_get_priv(dev);
Simon Glass18530302013-03-19 04:58:56 +0000108 u32 fdod, speed;
109
110 /* Observe SPI Descriptor Component Section 0 */
Simon Glass17e75442019-12-06 21:42:38 -0700111 dm_pci_write_config32(priv->pch, 0xb0, 0x1000);
Simon Glass18530302013-03-19 04:58:56 +0000112
113 /* Extract the Write/Erase SPI Frequency from descriptor */
Simon Glass17e75442019-12-06 21:42:38 -0700114 dm_pci_read_config32(priv->pch, 0xb4, &fdod);
Simon Glass18530302013-03-19 04:58:56 +0000115
116 /* Bits 23:21 have the fast read clock frequency, 0=20MHz, 1=33MHz */
117 speed = (fdod >> 21) & 7;
118
119 return speed == 1;
120}
121
Bin Mengab201072017-10-18 18:20:57 -0700122static void spi_lock_down(struct ich_spi_platdata *plat, void *sbase)
123{
124 if (plat->ich_version == ICHV_7) {
125 struct ich7_spi_regs *ich7_spi = sbase;
126
127 setbits_le16(&ich7_spi->spis, SPIS_LOCK);
128 } else if (plat->ich_version == ICHV_9) {
129 struct ich9_spi_regs *ich9_spi = sbase;
130
131 setbits_le16(&ich9_spi->hsfs, HSFS_FLOCKDN);
132 }
133}
134
Bin Meng3e791412017-08-15 22:38:29 -0700135static bool spi_lock_status(struct ich_spi_platdata *plat, void *sbase)
136{
137 int lock = 0;
138
139 if (plat->ich_version == ICHV_7) {
140 struct ich7_spi_regs *ich7_spi = sbase;
141
142 lock = readw(&ich7_spi->spis) & SPIS_LOCK;
143 } else if (plat->ich_version == ICHV_9) {
144 struct ich9_spi_regs *ich9_spi = sbase;
145
146 lock = readw(&ich9_spi->hsfs) & HSFS_FLOCKDN;
147 }
148
149 return lock != 0;
150}
151
Bin Meng3e791412017-08-15 22:38:29 -0700152static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans,
153 bool lock)
Simon Glass18530302013-03-19 04:58:56 +0000154{
155 uint16_t optypes;
Simon Glassba457562015-03-26 09:29:26 -0600156 uint8_t opmenu[ctlr->menubytes];
Simon Glass18530302013-03-19 04:58:56 +0000157
Bin Meng3e791412017-08-15 22:38:29 -0700158 if (!lock) {
Simon Glass18530302013-03-19 04:58:56 +0000159 /* The lock is off, so just use index 0. */
Simon Glassba457562015-03-26 09:29:26 -0600160 ich_writeb(ctlr, trans->opcode, ctlr->opmenu);
161 optypes = ich_readw(ctlr, ctlr->optype);
Simon Glass18530302013-03-19 04:58:56 +0000162 optypes = (optypes & 0xfffc) | (trans->type & 0x3);
Simon Glassba457562015-03-26 09:29:26 -0600163 ich_writew(ctlr, optypes, ctlr->optype);
Simon Glass18530302013-03-19 04:58:56 +0000164 return 0;
165 } else {
166 /* The lock is on. See if what we need is on the menu. */
167 uint8_t optype;
168 uint16_t opcode_index;
169
170 /* Write Enable is handled as atomic prefix */
171 if (trans->opcode == SPI_OPCODE_WREN)
172 return 0;
173
Simon Glassba457562015-03-26 09:29:26 -0600174 read_reg(ctlr, ctlr->opmenu, opmenu, sizeof(opmenu));
175 for (opcode_index = 0; opcode_index < ctlr->menubytes;
Simon Glass18530302013-03-19 04:58:56 +0000176 opcode_index++) {
177 if (opmenu[opcode_index] == trans->opcode)
178 break;
179 }
180
Simon Glassba457562015-03-26 09:29:26 -0600181 if (opcode_index == ctlr->menubytes) {
Simon Glassa5506622019-12-06 21:42:41 -0700182 debug("ICH SPI: Opcode %x not found\n", trans->opcode);
Simon Glassba457562015-03-26 09:29:26 -0600183 return -EINVAL;
Simon Glass18530302013-03-19 04:58:56 +0000184 }
185
Simon Glassba457562015-03-26 09:29:26 -0600186 optypes = ich_readw(ctlr, ctlr->optype);
Simon Glass18530302013-03-19 04:58:56 +0000187 optype = (optypes >> (opcode_index * 2)) & 0x3;
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200188
Simon Glass18530302013-03-19 04:58:56 +0000189 if (optype != trans->type) {
Simon Glassa5506622019-12-06 21:42:41 -0700190 debug("ICH SPI: Transaction doesn't fit type %d\n",
191 optype);
Simon Glassba457562015-03-26 09:29:26 -0600192 return -ENOSPC;
Simon Glass18530302013-03-19 04:58:56 +0000193 }
194 return opcode_index;
195 }
196}
197
Simon Glass18530302013-03-19 04:58:56 +0000198/*
199 * Wait for up to 6s til status register bit(s) turn 1 (in case wait_til_set
York Sun472d5462013-04-01 11:29:11 -0700200 * below is true) or 0. In case the wait was for the bit(s) to set - write
Simon Glass18530302013-03-19 04:58:56 +0000201 * those bits back, which would cause resetting them.
202 *
203 * Return the last read status value on success or -1 on failure.
204 */
Simon Glassba457562015-03-26 09:29:26 -0600205static int ich_status_poll(struct ich_spi_priv *ctlr, u16 bitmask,
206 int wait_til_set)
Simon Glass18530302013-03-19 04:58:56 +0000207{
208 int timeout = 600000; /* This will result in 6s */
209 u16 status = 0;
210
211 while (timeout--) {
Simon Glassba457562015-03-26 09:29:26 -0600212 status = ich_readw(ctlr, ctlr->status);
Simon Glass18530302013-03-19 04:58:56 +0000213 if (wait_til_set ^ ((status & bitmask) == 0)) {
Simon Glassba457562015-03-26 09:29:26 -0600214 if (wait_til_set) {
215 ich_writew(ctlr, status & bitmask,
216 ctlr->status);
217 }
Simon Glass18530302013-03-19 04:58:56 +0000218 return status;
219 }
220 udelay(10);
221 }
Simon Glassa5506622019-12-06 21:42:41 -0700222 debug("ICH SPI: SCIP timeout, read %x, expected %x, wts %x %x\n",
223 status, bitmask, wait_til_set, status & bitmask);
Simon Glass18530302013-03-19 04:58:56 +0000224
Simon Glassba457562015-03-26 09:29:26 -0600225 return -ETIMEDOUT;
Simon Glass18530302013-03-19 04:58:56 +0000226}
227
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200228static void ich_spi_config_opcode(struct udevice *dev)
Bin Mengb42711f2017-08-15 22:38:30 -0700229{
230 struct ich_spi_priv *ctlr = dev_get_priv(dev);
231
232 /*
233 * PREOP, OPTYPE, OPMENU1/OPMENU2 registers can be locked down
234 * to prevent accidental or intentional writes. Before they get
235 * locked down, these registers should be initialized properly.
236 */
237 ich_writew(ctlr, SPI_OPPREFIX, ctlr->preop);
238 ich_writew(ctlr, SPI_OPTYPE, ctlr->optype);
239 ich_writel(ctlr, SPI_OPMENU_LOWER, ctlr->opmenu);
240 ich_writel(ctlr, SPI_OPMENU_UPPER, ctlr->opmenu + sizeof(u32));
241}
242
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200243static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
Simon Glass18530302013-03-19 04:58:56 +0000244{
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200245 struct udevice *bus = dev_get_parent(slave->dev);
Simon Glasse1e332c2015-07-03 18:28:21 -0600246 struct ich_spi_platdata *plat = dev_get_platdata(bus);
Simon Glassba457562015-03-26 09:29:26 -0600247 struct ich_spi_priv *ctlr = dev_get_priv(bus);
Simon Glass18530302013-03-19 04:58:56 +0000248 uint16_t control;
249 int16_t opcode_index;
250 int with_address;
251 int status;
Simon Glassba457562015-03-26 09:29:26 -0600252 struct spi_trans *trans = &ctlr->trans;
Bin Meng3e791412017-08-15 22:38:29 -0700253 bool lock = spi_lock_status(plat, ctlr->base);
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200254 int ret = 0;
Simon Glass18530302013-03-19 04:58:56 +0000255
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200256 trans->in = NULL;
257 trans->out = NULL;
258 trans->type = 0xFF;
Simon Glass18530302013-03-19 04:58:56 +0000259
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200260 if (op->data.nbytes) {
261 if (op->data.dir == SPI_MEM_DATA_IN) {
262 trans->in = op->data.buf.in;
263 trans->bytesin = op->data.nbytes;
264 } else {
265 trans->out = op->data.buf.out;
266 trans->bytesout = op->data.nbytes;
Simon Glass18530302013-03-19 04:58:56 +0000267 }
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200268 }
269
270 if (trans->opcode != op->cmd.opcode)
271 trans->opcode = op->cmd.opcode;
272
273 if (lock && trans->opcode == SPI_OPCODE_WRDIS)
Simon Glass18530302013-03-19 04:58:56 +0000274 return 0;
Simon Glass18530302013-03-19 04:58:56 +0000275
276 if (trans->opcode == SPI_OPCODE_WREN) {
277 /*
278 * Treat Write Enable as Atomic Pre-Op if possible
279 * in order to prevent the Management Engine from
280 * issuing a transaction between WREN and DATA.
281 */
Bin Meng3e791412017-08-15 22:38:29 -0700282 if (!lock)
Simon Glassba457562015-03-26 09:29:26 -0600283 ich_writew(ctlr, trans->opcode, ctlr->preop);
Simon Glass18530302013-03-19 04:58:56 +0000284 return 0;
285 }
286
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200287 ret = ich_status_poll(ctlr, SPIS_SCIP, 0);
288 if (ret < 0)
289 return ret;
290
291 if (plat->ich_version == ICHV_7)
292 ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
293 else
294 ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
295
296 /* Try to guess spi transaction type */
297 if (op->data.dir == SPI_MEM_DATA_OUT) {
298 if (op->addr.nbytes)
299 trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
300 else
301 trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
302 } else {
303 if (op->addr.nbytes)
304 trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
305 else
306 trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
307 }
308 /* Special erase case handling */
309 if (op->addr.nbytes && !op->data.buswidth)
310 trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
311
312 opcode_index = spi_setup_opcode(ctlr, trans, lock);
313 if (opcode_index < 0)
314 return -EINVAL;
315
316 if (op->addr.nbytes) {
317 trans->offset = op->addr.val;
318 with_address = 1;
319 }
320
Simon Glassba457562015-03-26 09:29:26 -0600321 if (ctlr->speed && ctlr->max_speed >= 33000000) {
Simon Glass18530302013-03-19 04:58:56 +0000322 int byte;
323
Simon Glassba457562015-03-26 09:29:26 -0600324 byte = ich_readb(ctlr, ctlr->speed);
325 if (ctlr->cur_speed >= 33000000)
Simon Glass18530302013-03-19 04:58:56 +0000326 byte |= SSFC_SCF_33MHZ;
327 else
328 byte &= ~SSFC_SCF_33MHZ;
Simon Glassba457562015-03-26 09:29:26 -0600329 ich_writeb(ctlr, byte, ctlr->speed);
Simon Glass18530302013-03-19 04:58:56 +0000330 }
331
Simon Glass18530302013-03-19 04:58:56 +0000332 /* Preset control fields */
Simon Glass18530302013-03-19 04:58:56 +0000333 control = SPIC_SCGO | ((opcode_index & 0x07) << 4);
334
335 /* Issue atomic preop cycle if needed */
Simon Glassba457562015-03-26 09:29:26 -0600336 if (ich_readw(ctlr, ctlr->preop))
Simon Glass18530302013-03-19 04:58:56 +0000337 control |= SPIC_ACS;
338
339 if (!trans->bytesout && !trans->bytesin) {
340 /* SPI addresses are 24 bit only */
Simon Glassba457562015-03-26 09:29:26 -0600341 if (with_address) {
342 ich_writel(ctlr, trans->offset & 0x00FFFFFF,
343 ctlr->addr);
344 }
Simon Glass18530302013-03-19 04:58:56 +0000345 /*
346 * This is a 'no data' command (like Write Enable), its
347 * bitesout size was 1, decremented to zero while executing
348 * spi_setup_opcode() above. Tell the chip to send the
349 * command.
350 */
Simon Glassba457562015-03-26 09:29:26 -0600351 ich_writew(ctlr, control, ctlr->control);
Simon Glass18530302013-03-19 04:58:56 +0000352
353 /* wait for the result */
Simon Glassba457562015-03-26 09:29:26 -0600354 status = ich_status_poll(ctlr, SPIS_CDS | SPIS_FCERR, 1);
355 if (status < 0)
356 return status;
Simon Glass18530302013-03-19 04:58:56 +0000357
358 if (status & SPIS_FCERR) {
359 debug("ICH SPI: Command transaction error\n");
Simon Glassba457562015-03-26 09:29:26 -0600360 return -EIO;
Simon Glass18530302013-03-19 04:58:56 +0000361 }
362
363 return 0;
364 }
365
Simon Glass18530302013-03-19 04:58:56 +0000366 while (trans->bytesout || trans->bytesin) {
367 uint32_t data_length;
Simon Glass18530302013-03-19 04:58:56 +0000368
369 /* SPI addresses are 24 bit only */
Simon Glassba457562015-03-26 09:29:26 -0600370 ich_writel(ctlr, trans->offset & 0x00FFFFFF, ctlr->addr);
Simon Glass18530302013-03-19 04:58:56 +0000371
372 if (trans->bytesout)
Simon Glassba457562015-03-26 09:29:26 -0600373 data_length = min(trans->bytesout, ctlr->databytes);
Simon Glass18530302013-03-19 04:58:56 +0000374 else
Simon Glassba457562015-03-26 09:29:26 -0600375 data_length = min(trans->bytesin, ctlr->databytes);
Simon Glass18530302013-03-19 04:58:56 +0000376
377 /* Program data into FDATA0 to N */
378 if (trans->bytesout) {
Simon Glassba457562015-03-26 09:29:26 -0600379 write_reg(ctlr, trans->out, ctlr->data, data_length);
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200380 trans->bytesout -= data_length;
Simon Glass18530302013-03-19 04:58:56 +0000381 }
382
383 /* Add proper control fields' values */
Simon Glassba457562015-03-26 09:29:26 -0600384 control &= ~((ctlr->databytes - 1) << 8);
Simon Glass18530302013-03-19 04:58:56 +0000385 control |= SPIC_DS;
386 control |= (data_length - 1) << 8;
387
388 /* write it */
Simon Glassba457562015-03-26 09:29:26 -0600389 ich_writew(ctlr, control, ctlr->control);
Simon Glass18530302013-03-19 04:58:56 +0000390
Bin Meng9eb43392016-02-01 01:40:36 -0800391 /* Wait for Cycle Done Status or Flash Cycle Error */
Simon Glassba457562015-03-26 09:29:26 -0600392 status = ich_status_poll(ctlr, SPIS_CDS | SPIS_FCERR, 1);
393 if (status < 0)
394 return status;
Simon Glass18530302013-03-19 04:58:56 +0000395
396 if (status & SPIS_FCERR) {
Simon Glass5d4a7572015-06-07 08:50:33 -0600397 debug("ICH SPI: Data transaction error %x\n", status);
Simon Glassba457562015-03-26 09:29:26 -0600398 return -EIO;
Simon Glass18530302013-03-19 04:58:56 +0000399 }
400
401 if (trans->bytesin) {
Simon Glassba457562015-03-26 09:29:26 -0600402 read_reg(ctlr, ctlr->data, trans->in, data_length);
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200403 trans->bytesin -= data_length;
Simon Glass18530302013-03-19 04:58:56 +0000404 }
405 }
406
407 /* Clear atomic preop now that xfer is done */
Bin Mengd2ca80c2017-08-26 19:22:59 -0700408 if (!lock)
409 ich_writew(ctlr, 0, ctlr->preop);
Simon Glass18530302013-03-19 04:58:56 +0000410
411 return 0;
412}
413
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200414static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
415{
416 unsigned int page_offset;
417 int addr = op->addr.val;
418 unsigned int byte_count = op->data.nbytes;
419
420 if (hweight32(ICH_BOUNDARY) == 1) {
421 page_offset = addr & (ICH_BOUNDARY - 1);
422 } else {
423 u64 aux = addr;
424
425 page_offset = do_div(aux, ICH_BOUNDARY);
426 }
427
428 if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) {
429 op->data.nbytes = min(ICH_BOUNDARY - page_offset,
430 slave->max_read_size);
431 } else if (slave->max_write_size) {
432 op->data.nbytes = min(ICH_BOUNDARY - page_offset,
433 slave->max_write_size);
434 }
435
436 op->data.nbytes = min(op->data.nbytes, byte_count);
437
438 return 0;
439}
440
Simon Glass17e75442019-12-06 21:42:38 -0700441static int ich_protect_lockdown(struct udevice *dev)
442{
443 struct ich_spi_platdata *plat = dev_get_platdata(dev);
444 struct ich_spi_priv *priv = dev_get_priv(dev);
445 int ret = -ENOSYS;
446
447 /* Disable the BIOS write protect so write commands are allowed */
448 if (priv->pch)
449 ret = pch_set_spi_protect(priv->pch, false);
450 if (ret == -ENOSYS) {
451 u8 bios_cntl;
452
453 bios_cntl = ich_readb(priv, priv->bcr);
454 bios_cntl &= ~BIT(5); /* clear Enable InSMM_STS (EISS) */
455 bios_cntl |= 1; /* Write Protect Disable (WPD) */
456 ich_writeb(priv, bios_cntl, priv->bcr);
457 } else if (ret) {
458 debug("%s: Failed to disable write-protect: err=%d\n",
459 __func__, ret);
460 return ret;
461 }
462
463 /* Lock down SPI controller settings if required */
464 if (plat->lockdown) {
465 ich_spi_config_opcode(dev);
466 spi_lock_down(plat, priv->base);
467 }
468
469 return 0;
470}
471
Simon Glass674990c2019-12-06 21:42:37 -0700472static int ich_init_controller(struct udevice *dev,
473 struct ich_spi_platdata *plat,
474 struct ich_spi_priv *ctlr)
475{
Simon Glass75214b02019-12-06 21:42:42 -0700476 ctlr->base = (void *)plat->mmio_base;
Simon Glass674990c2019-12-06 21:42:37 -0700477 if (plat->ich_version == ICHV_7) {
Simon Glass75214b02019-12-06 21:42:42 -0700478 struct ich7_spi_regs *ich7_spi = ctlr->base;
Simon Glass674990c2019-12-06 21:42:37 -0700479
480 ctlr->opmenu = offsetof(struct ich7_spi_regs, opmenu);
481 ctlr->menubytes = sizeof(ich7_spi->opmenu);
482 ctlr->optype = offsetof(struct ich7_spi_regs, optype);
483 ctlr->addr = offsetof(struct ich7_spi_regs, spia);
484 ctlr->data = offsetof(struct ich7_spi_regs, spid);
485 ctlr->databytes = sizeof(ich7_spi->spid);
486 ctlr->status = offsetof(struct ich7_spi_regs, spis);
487 ctlr->control = offsetof(struct ich7_spi_regs, spic);
488 ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
489 ctlr->preop = offsetof(struct ich7_spi_regs, preop);
Simon Glass674990c2019-12-06 21:42:37 -0700490 } else if (plat->ich_version == ICHV_9) {
Simon Glass75214b02019-12-06 21:42:42 -0700491 struct ich9_spi_regs *ich9_spi = ctlr->base;
Simon Glass674990c2019-12-06 21:42:37 -0700492
493 ctlr->opmenu = offsetof(struct ich9_spi_regs, opmenu);
494 ctlr->menubytes = sizeof(ich9_spi->opmenu);
495 ctlr->optype = offsetof(struct ich9_spi_regs, optype);
496 ctlr->addr = offsetof(struct ich9_spi_regs, faddr);
497 ctlr->data = offsetof(struct ich9_spi_regs, fdata);
498 ctlr->databytes = sizeof(ich9_spi->fdata);
499 ctlr->status = offsetof(struct ich9_spi_regs, ssfs);
500 ctlr->control = offsetof(struct ich9_spi_regs, ssfc);
501 ctlr->speed = ctlr->control + 2;
502 ctlr->bbar = offsetof(struct ich9_spi_regs, bbar);
503 ctlr->preop = offsetof(struct ich9_spi_regs, preop);
504 ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
505 ctlr->pr = &ich9_spi->pr[0];
Simon Glass674990c2019-12-06 21:42:37 -0700506 } else {
507 debug("ICH SPI: Unrecognised ICH version %d\n",
508 plat->ich_version);
509 return -EINVAL;
510 }
511
512 /* Work out the maximum speed we can support */
513 ctlr->max_speed = 20000000;
514 if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev))
515 ctlr->max_speed = 33000000;
Simon Glass75214b02019-12-06 21:42:42 -0700516 debug("ICH SPI: Version ID %d detected at %lx, speed %ld\n",
517 plat->ich_version, plat->mmio_base, ctlr->max_speed);
Simon Glass674990c2019-12-06 21:42:37 -0700518
519 ich_set_bbar(ctlr, 0);
520
521 return 0;
522}
523
Simon Glassf2b85ab2016-01-18 20:19:21 -0700524static int ich_spi_probe(struct udevice *dev)
Simon Glassba457562015-03-26 09:29:26 -0600525{
Simon Glassf2b85ab2016-01-18 20:19:21 -0700526 struct ich_spi_platdata *plat = dev_get_platdata(dev);
527 struct ich_spi_priv *priv = dev_get_priv(dev);
Simon Glassba457562015-03-26 09:29:26 -0600528 int ret;
529
Simon Glassf2b85ab2016-01-18 20:19:21 -0700530 ret = ich_init_controller(dev, plat, priv);
Simon Glassba457562015-03-26 09:29:26 -0600531 if (ret)
532 return ret;
Simon Glassba457562015-03-26 09:29:26 -0600533
Simon Glass17e75442019-12-06 21:42:38 -0700534 ret = ich_protect_lockdown(dev);
535 if (ret)
536 return ret;
Bin Mengab201072017-10-18 18:20:57 -0700537
Simon Glassba457562015-03-26 09:29:26 -0600538 priv->cur_speed = priv->max_speed;
539
540 return 0;
541}
542
Stefan Roese4759dff2017-04-24 09:48:04 +0200543static int ich_spi_remove(struct udevice *bus)
544{
Stefan Roese4759dff2017-04-24 09:48:04 +0200545 /*
546 * Configure SPI controller so that the Linux MTD driver can fully
547 * access the SPI NOR chip
548 */
Bin Mengb42711f2017-08-15 22:38:30 -0700549 ich_spi_config_opcode(bus);
Stefan Roese4759dff2017-04-24 09:48:04 +0200550
551 return 0;
552}
553
Simon Glassba457562015-03-26 09:29:26 -0600554static int ich_spi_set_speed(struct udevice *bus, uint speed)
555{
556 struct ich_spi_priv *priv = dev_get_priv(bus);
557
558 priv->cur_speed = speed;
559
560 return 0;
561}
562
563static int ich_spi_set_mode(struct udevice *bus, uint mode)
564{
565 debug("%s: mode=%d\n", __func__, mode);
566
567 return 0;
568}
569
570static int ich_spi_child_pre_probe(struct udevice *dev)
571{
572 struct udevice *bus = dev_get_parent(dev);
573 struct ich_spi_platdata *plat = dev_get_platdata(bus);
574 struct ich_spi_priv *priv = dev_get_priv(bus);
Simon Glassbcbe3d12015-09-28 23:32:01 -0600575 struct spi_slave *slave = dev_get_parent_priv(dev);
Simon Glassba457562015-03-26 09:29:26 -0600576
577 /*
578 * Yes this controller can only write a small number of bytes at
579 * once! The limit is typically 64 bytes.
580 */
581 slave->max_write_size = priv->databytes;
582 /*
583 * ICH 7 SPI controller only supports array read command
584 * and byte program command for SST flash
585 */
Jagan Teki08fe9c22016-08-08 17:12:12 +0530586 if (plat->ich_version == ICHV_7)
587 slave->mode = SPI_RX_SLOW | SPI_TX_BYTE;
Simon Glassba457562015-03-26 09:29:26 -0600588
589 return 0;
590}
591
Bin Meng1f9eb592016-02-01 01:40:37 -0800592static int ich_spi_ofdata_to_platdata(struct udevice *dev)
593{
594 struct ich_spi_platdata *plat = dev_get_platdata(dev);
Simon Glass17e75442019-12-06 21:42:38 -0700595 struct ich_spi_priv *priv = dev_get_priv(dev);
Bin Meng1f9eb592016-02-01 01:40:37 -0800596
Simon Glass17e75442019-12-06 21:42:38 -0700597 /* Find a PCH if there is one */
598 uclass_first_device(UCLASS_PCH, &priv->pch);
599 if (!priv->pch)
600 priv->pch = dev_get_parent(dev);
601
Simon Glass702b28a2019-12-06 21:42:39 -0700602 plat->ich_version = dev_get_driver_data(dev);
603 plat->lockdown = dev_read_bool(dev, "intel,spi-lock-down");
Bin Meng1f9eb592016-02-01 01:40:37 -0800604
Simon Glass75214b02019-12-06 21:42:42 -0700605 pch_get_spi_base(priv->pch, &plat->mmio_base);
606
Simon Glass702b28a2019-12-06 21:42:39 -0700607 return 0;
Bin Meng1f9eb592016-02-01 01:40:37 -0800608}
609
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200610static const struct spi_controller_mem_ops ich_controller_mem_ops = {
611 .adjust_op_size = ich_spi_adjust_size,
612 .supports_op = NULL,
613 .exec_op = ich_spi_exec_op,
614};
615
Simon Glassba457562015-03-26 09:29:26 -0600616static const struct dm_spi_ops ich_spi_ops = {
Simon Glassccdabd82019-12-06 21:42:35 -0700617 /* xfer is not supported */
Simon Glassba457562015-03-26 09:29:26 -0600618 .set_speed = ich_spi_set_speed,
619 .set_mode = ich_spi_set_mode,
Bernhard Messerklinger0709ddb2019-08-02 08:38:34 +0200620 .mem_ops = &ich_controller_mem_ops,
Simon Glassba457562015-03-26 09:29:26 -0600621 /*
622 * cs_info is not needed, since we require all chip selects to be
623 * in the device tree explicitly
624 */
625};
626
627static const struct udevice_id ich_spi_ids[] = {
Simon Glass702b28a2019-12-06 21:42:39 -0700628 { .compatible = "intel,ich7-spi", ICHV_7 },
629 { .compatible = "intel,ich9-spi", ICHV_9 },
Simon Glassba457562015-03-26 09:29:26 -0600630 { }
631};
632
633U_BOOT_DRIVER(ich_spi) = {
634 .name = "ich_spi",
635 .id = UCLASS_SPI,
636 .of_match = ich_spi_ids,
637 .ops = &ich_spi_ops,
Bin Meng1f9eb592016-02-01 01:40:37 -0800638 .ofdata_to_platdata = ich_spi_ofdata_to_platdata,
Simon Glassba457562015-03-26 09:29:26 -0600639 .platdata_auto_alloc_size = sizeof(struct ich_spi_platdata),
640 .priv_auto_alloc_size = sizeof(struct ich_spi_priv),
641 .child_pre_probe = ich_spi_child_pre_probe,
642 .probe = ich_spi_probe,
Stefan Roese4759dff2017-04-24 09:48:04 +0200643 .remove = ich_spi_remove,
644 .flags = DM_FLAG_OS_PREPARE,
Simon Glassba457562015-03-26 09:29:26 -0600645};