1
2
3
4
5
6
7
8#include <common.h>
9#include <dm.h>
10#include <errno.h>
11#include <malloc.h>
12#include <pch.h>
13#include <pci.h>
14#include <pci_ids.h>
15#include <spi.h>
16#include <asm/io.h>
17#include <spi-mem.h>
18#include <div64.h>
19
20#include "ich.h"
21
22DECLARE_GLOBAL_DATA_PTR;
23
24#ifdef DEBUG_TRACE
25#define debug_trace(fmt, args...) debug(fmt, ##args)
26#else
27#define debug_trace(x, args...)
28#endif
29
30static u8 ich_readb(struct ich_spi_priv *priv, int reg)
31{
32 u8 value = readb(priv->base + reg);
33
34 debug_trace("read %2.2x from %4.4x\n", value, reg);
35
36 return value;
37}
38
39static u16 ich_readw(struct ich_spi_priv *priv, int reg)
40{
41 u16 value = readw(priv->base + reg);
42
43 debug_trace("read %4.4x from %4.4x\n", value, reg);
44
45 return value;
46}
47
48static u32 ich_readl(struct ich_spi_priv *priv, int reg)
49{
50 u32 value = readl(priv->base + reg);
51
52 debug_trace("read %8.8x from %4.4x\n", value, reg);
53
54 return value;
55}
56
57static void ich_writeb(struct ich_spi_priv *priv, u8 value, int reg)
58{
59 writeb(value, priv->base + reg);
60 debug_trace("wrote %2.2x to %4.4x\n", value, reg);
61}
62
63static void ich_writew(struct ich_spi_priv *priv, u16 value, int reg)
64{
65 writew(value, priv->base + reg);
66 debug_trace("wrote %4.4x to %4.4x\n", value, reg);
67}
68
69static void ich_writel(struct ich_spi_priv *priv, u32 value, int reg)
70{
71 writel(value, priv->base + reg);
72 debug_trace("wrote %8.8x to %4.4x\n", value, reg);
73}
74
75static void write_reg(struct ich_spi_priv *priv, const void *value,
76 int dest_reg, uint32_t size)
77{
78 memcpy_toio(priv->base + dest_reg, value, size);
79}
80
81static void read_reg(struct ich_spi_priv *priv, int src_reg, void *value,
82 uint32_t size)
83{
84 memcpy_fromio(value, priv->base + src_reg, size);
85}
86
87static void ich_set_bbar(struct ich_spi_priv *ctlr, uint32_t minaddr)
88{
89 const uint32_t bbar_mask = 0x00ffff00;
90 uint32_t ichspi_bbar;
91
92 minaddr &= bbar_mask;
93 ichspi_bbar = ich_readl(ctlr, ctlr->bbar) & ~bbar_mask;
94 ichspi_bbar |= minaddr;
95 ich_writel(ctlr, ichspi_bbar, ctlr->bbar);
96}
97
98
99static int ich9_can_do_33mhz(struct udevice *dev)
100{
101 u32 fdod, speed;
102
103
104 dm_pci_write_config32(dev->parent, 0xb0, 0x1000);
105
106
107 dm_pci_read_config32(dev->parent, 0xb4, &fdod);
108
109
110 speed = (fdod >> 21) & 7;
111
112 return speed == 1;
113}
114
115static int ich_init_controller(struct udevice *dev,
116 struct ich_spi_platdata *plat,
117 struct ich_spi_priv *ctlr)
118{
119 ulong sbase_addr;
120 void *sbase;
121
122
123 pch_get_spi_base(dev->parent, &sbase_addr);
124 sbase = (void *)sbase_addr;
125 debug("%s: sbase=%p\n", __func__, sbase);
126
127 if (plat->ich_version == ICHV_7) {
128 struct ich7_spi_regs *ich7_spi = sbase;
129
130 ctlr->opmenu = offsetof(struct ich7_spi_regs, opmenu);
131 ctlr->menubytes = sizeof(ich7_spi->opmenu);
132 ctlr->optype = offsetof(struct ich7_spi_regs, optype);
133 ctlr->addr = offsetof(struct ich7_spi_regs, spia);
134 ctlr->data = offsetof(struct ich7_spi_regs, spid);
135 ctlr->databytes = sizeof(ich7_spi->spid);
136 ctlr->status = offsetof(struct ich7_spi_regs, spis);
137 ctlr->control = offsetof(struct ich7_spi_regs, spic);
138 ctlr->bbar = offsetof(struct ich7_spi_regs, bbar);
139 ctlr->preop = offsetof(struct ich7_spi_regs, preop);
140 ctlr->base = ich7_spi;
141 } else if (plat->ich_version == ICHV_9) {
142 struct ich9_spi_regs *ich9_spi = sbase;
143
144 ctlr->opmenu = offsetof(struct ich9_spi_regs, opmenu);
145 ctlr->menubytes = sizeof(ich9_spi->opmenu);
146 ctlr->optype = offsetof(struct ich9_spi_regs, optype);
147 ctlr->addr = offsetof(struct ich9_spi_regs, faddr);
148 ctlr->data = offsetof(struct ich9_spi_regs, fdata);
149 ctlr->databytes = sizeof(ich9_spi->fdata);
150 ctlr->status = offsetof(struct ich9_spi_regs, ssfs);
151 ctlr->control = offsetof(struct ich9_spi_regs, ssfc);
152 ctlr->speed = ctlr->control + 2;
153 ctlr->bbar = offsetof(struct ich9_spi_regs, bbar);
154 ctlr->preop = offsetof(struct ich9_spi_regs, preop);
155 ctlr->bcr = offsetof(struct ich9_spi_regs, bcr);
156 ctlr->pr = &ich9_spi->pr[0];
157 ctlr->base = ich9_spi;
158 } else {
159 debug("ICH SPI: Unrecognised ICH version %d\n",
160 plat->ich_version);
161 return -EINVAL;
162 }
163
164
165 ctlr->max_speed = 20000000;
166 if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev))
167 ctlr->max_speed = 33000000;
168 debug("ICH SPI: Version ID %d detected at %p, speed %ld\n",
169 plat->ich_version, ctlr->base, ctlr->max_speed);
170
171 ich_set_bbar(ctlr, 0);
172
173 return 0;
174}
175
176static void spi_lock_down(struct ich_spi_platdata *plat, void *sbase)
177{
178 if (plat->ich_version == ICHV_7) {
179 struct ich7_spi_regs *ich7_spi = sbase;
180
181 setbits_le16(&ich7_spi->spis, SPIS_LOCK);
182 } else if (plat->ich_version == ICHV_9) {
183 struct ich9_spi_regs *ich9_spi = sbase;
184
185 setbits_le16(&ich9_spi->hsfs, HSFS_FLOCKDN);
186 }
187}
188
189static bool spi_lock_status(struct ich_spi_platdata *plat, void *sbase)
190{
191 int lock = 0;
192
193 if (plat->ich_version == ICHV_7) {
194 struct ich7_spi_regs *ich7_spi = sbase;
195
196 lock = readw(&ich7_spi->spis) & SPIS_LOCK;
197 } else if (plat->ich_version == ICHV_9) {
198 struct ich9_spi_regs *ich9_spi = sbase;
199
200 lock = readw(&ich9_spi->hsfs) & HSFS_FLOCKDN;
201 }
202
203 return lock != 0;
204}
205
206static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans,
207 bool lock)
208{
209 uint16_t optypes;
210 uint8_t opmenu[ctlr->menubytes];
211
212 if (!lock) {
213
214 ich_writeb(ctlr, trans->opcode, ctlr->opmenu);
215 optypes = ich_readw(ctlr, ctlr->optype);
216 optypes = (optypes & 0xfffc) | (trans->type & 0x3);
217 ich_writew(ctlr, optypes, ctlr->optype);
218 return 0;
219 } else {
220
221 uint8_t optype;
222 uint16_t opcode_index;
223
224
225 if (trans->opcode == SPI_OPCODE_WREN)
226 return 0;
227
228 read_reg(ctlr, ctlr->opmenu, opmenu, sizeof(opmenu));
229 for (opcode_index = 0; opcode_index < ctlr->menubytes;
230 opcode_index++) {
231 if (opmenu[opcode_index] == trans->opcode)
232 break;
233 }
234
235 if (opcode_index == ctlr->menubytes) {
236 printf("ICH SPI: Opcode %x not found\n",
237 trans->opcode);
238 return -EINVAL;
239 }
240
241 optypes = ich_readw(ctlr, ctlr->optype);
242 optype = (optypes >> (opcode_index * 2)) & 0x3;
243
244 if (optype != trans->type) {
245 printf("ICH SPI: Transaction doesn't fit type %d\n",
246 optype);
247 return -ENOSPC;
248 }
249 return opcode_index;
250 }
251}
252
253
254
255
256
257
258
259
260static int ich_status_poll(struct ich_spi_priv *ctlr, u16 bitmask,
261 int wait_til_set)
262{
263 int timeout = 600000;
264 u16 status = 0;
265
266 while (timeout--) {
267 status = ich_readw(ctlr, ctlr->status);
268 if (wait_til_set ^ ((status & bitmask) == 0)) {
269 if (wait_til_set) {
270 ich_writew(ctlr, status & bitmask,
271 ctlr->status);
272 }
273 return status;
274 }
275 udelay(10);
276 }
277
278 printf("ICH SPI: SCIP timeout, read %x, expected %x\n",
279 status, bitmask);
280 return -ETIMEDOUT;
281}
282
283static void ich_spi_config_opcode(struct udevice *dev)
284{
285 struct ich_spi_priv *ctlr = dev_get_priv(dev);
286
287
288
289
290
291
292 ich_writew(ctlr, SPI_OPPREFIX, ctlr->preop);
293 ich_writew(ctlr, SPI_OPTYPE, ctlr->optype);
294 ich_writel(ctlr, SPI_OPMENU_LOWER, ctlr->opmenu);
295 ich_writel(ctlr, SPI_OPMENU_UPPER, ctlr->opmenu + sizeof(u32));
296}
297
298static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
299{
300 struct udevice *bus = dev_get_parent(slave->dev);
301 struct ich_spi_platdata *plat = dev_get_platdata(bus);
302 struct ich_spi_priv *ctlr = dev_get_priv(bus);
303 uint16_t control;
304 int16_t opcode_index;
305 int with_address;
306 int status;
307 struct spi_trans *trans = &ctlr->trans;
308 bool lock = spi_lock_status(plat, ctlr->base);
309 int ret = 0;
310
311 trans->in = NULL;
312 trans->out = NULL;
313 trans->type = 0xFF;
314
315 if (op->data.nbytes) {
316 if (op->data.dir == SPI_MEM_DATA_IN) {
317 trans->in = op->data.buf.in;
318 trans->bytesin = op->data.nbytes;
319 } else {
320 trans->out = op->data.buf.out;
321 trans->bytesout = op->data.nbytes;
322 }
323 }
324
325 if (trans->opcode != op->cmd.opcode)
326 trans->opcode = op->cmd.opcode;
327
328 if (lock && trans->opcode == SPI_OPCODE_WRDIS)
329 return 0;
330
331 if (trans->opcode == SPI_OPCODE_WREN) {
332
333
334
335
336
337 if (!lock)
338 ich_writew(ctlr, trans->opcode, ctlr->preop);
339 return 0;
340 }
341
342 ret = ich_status_poll(ctlr, SPIS_SCIP, 0);
343 if (ret < 0)
344 return ret;
345
346 if (plat->ich_version == ICHV_7)
347 ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
348 else
349 ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
350
351
352 if (op->data.dir == SPI_MEM_DATA_OUT) {
353 if (op->addr.nbytes)
354 trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
355 else
356 trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
357 } else {
358 if (op->addr.nbytes)
359 trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
360 else
361 trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
362 }
363
364 if (op->addr.nbytes && !op->data.buswidth)
365 trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
366
367 opcode_index = spi_setup_opcode(ctlr, trans, lock);
368 if (opcode_index < 0)
369 return -EINVAL;
370
371 if (op->addr.nbytes) {
372 trans->offset = op->addr.val;
373 with_address = 1;
374 }
375
376 if (ctlr->speed && ctlr->max_speed >= 33000000) {
377 int byte;
378
379 byte = ich_readb(ctlr, ctlr->speed);
380 if (ctlr->cur_speed >= 33000000)
381 byte |= SSFC_SCF_33MHZ;
382 else
383 byte &= ~SSFC_SCF_33MHZ;
384 ich_writeb(ctlr, byte, ctlr->speed);
385 }
386
387
388 control = SPIC_SCGO | ((opcode_index & 0x07) << 4);
389
390
391 if (ich_readw(ctlr, ctlr->preop))
392 control |= SPIC_ACS;
393
394 if (!trans->bytesout && !trans->bytesin) {
395
396 if (with_address) {
397 ich_writel(ctlr, trans->offset & 0x00FFFFFF,
398 ctlr->addr);
399 }
400
401
402
403
404
405
406 ich_writew(ctlr, control, ctlr->control);
407
408
409 status = ich_status_poll(ctlr, SPIS_CDS | SPIS_FCERR, 1);
410 if (status < 0)
411 return status;
412
413 if (status & SPIS_FCERR) {
414 debug("ICH SPI: Command transaction error\n");
415 return -EIO;
416 }
417
418 return 0;
419 }
420
421 while (trans->bytesout || trans->bytesin) {
422 uint32_t data_length;
423
424
425 ich_writel(ctlr, trans->offset & 0x00FFFFFF, ctlr->addr);
426
427 if (trans->bytesout)
428 data_length = min(trans->bytesout, ctlr->databytes);
429 else
430 data_length = min(trans->bytesin, ctlr->databytes);
431
432
433 if (trans->bytesout) {
434 write_reg(ctlr, trans->out, ctlr->data, data_length);
435 trans->bytesout -= data_length;
436 }
437
438
439 control &= ~((ctlr->databytes - 1) << 8);
440 control |= SPIC_DS;
441 control |= (data_length - 1) << 8;
442
443
444 ich_writew(ctlr, control, ctlr->control);
445
446
447 status = ich_status_poll(ctlr, SPIS_CDS | SPIS_FCERR, 1);
448 if (status < 0)
449 return status;
450
451 if (status & SPIS_FCERR) {
452 debug("ICH SPI: Data transaction error %x\n", status);
453 return -EIO;
454 }
455
456 if (trans->bytesin) {
457 read_reg(ctlr, ctlr->data, trans->in, data_length);
458 trans->bytesin -= data_length;
459 }
460 }
461
462
463 if (!lock)
464 ich_writew(ctlr, 0, ctlr->preop);
465
466 return 0;
467}
468
469static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
470{
471 unsigned int page_offset;
472 int addr = op->addr.val;
473 unsigned int byte_count = op->data.nbytes;
474
475 if (hweight32(ICH_BOUNDARY) == 1) {
476 page_offset = addr & (ICH_BOUNDARY - 1);
477 } else {
478 u64 aux = addr;
479
480 page_offset = do_div(aux, ICH_BOUNDARY);
481 }
482
483 if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) {
484 op->data.nbytes = min(ICH_BOUNDARY - page_offset,
485 slave->max_read_size);
486 } else if (slave->max_write_size) {
487 op->data.nbytes = min(ICH_BOUNDARY - page_offset,
488 slave->max_write_size);
489 }
490
491 op->data.nbytes = min(op->data.nbytes, byte_count);
492
493 return 0;
494}
495
496static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
497 const void *dout, void *din, unsigned long flags)
498{
499 printf("ICH SPI: Only supports memory operations\n");
500 return -1;
501}
502
503static int ich_spi_probe(struct udevice *dev)
504{
505 struct ich_spi_platdata *plat = dev_get_platdata(dev);
506 struct ich_spi_priv *priv = dev_get_priv(dev);
507 uint8_t bios_cntl;
508 int ret;
509
510 ret = ich_init_controller(dev, plat, priv);
511 if (ret)
512 return ret;
513
514 ret = pch_set_spi_protect(dev->parent, false);
515 if (ret == -ENOSYS) {
516 bios_cntl = ich_readb(priv, priv->bcr);
517 bios_cntl &= ~BIT(5);
518 bios_cntl |= 1;
519 ich_writeb(priv, bios_cntl, priv->bcr);
520 } else if (ret) {
521 debug("%s: Failed to disable write-protect: err=%d\n",
522 __func__, ret);
523 return ret;
524 }
525
526
527 if (plat->lockdown) {
528 ich_spi_config_opcode(dev);
529 spi_lock_down(plat, priv->base);
530 }
531
532 priv->cur_speed = priv->max_speed;
533
534 return 0;
535}
536
537static int ich_spi_remove(struct udevice *bus)
538{
539
540
541
542
543 ich_spi_config_opcode(bus);
544
545 return 0;
546}
547
548static int ich_spi_set_speed(struct udevice *bus, uint speed)
549{
550 struct ich_spi_priv *priv = dev_get_priv(bus);
551
552 priv->cur_speed = speed;
553
554 return 0;
555}
556
557static int ich_spi_set_mode(struct udevice *bus, uint mode)
558{
559 debug("%s: mode=%d\n", __func__, mode);
560
561 return 0;
562}
563
564static int ich_spi_child_pre_probe(struct udevice *dev)
565{
566 struct udevice *bus = dev_get_parent(dev);
567 struct ich_spi_platdata *plat = dev_get_platdata(bus);
568 struct ich_spi_priv *priv = dev_get_priv(bus);
569 struct spi_slave *slave = dev_get_parent_priv(dev);
570
571
572
573
574
575 slave->max_write_size = priv->databytes;
576
577
578
579
580 if (plat->ich_version == ICHV_7)
581 slave->mode = SPI_RX_SLOW | SPI_TX_BYTE;
582
583 return 0;
584}
585
586static int ich_spi_ofdata_to_platdata(struct udevice *dev)
587{
588 struct ich_spi_platdata *plat = dev_get_platdata(dev);
589 int node = dev_of_offset(dev);
590 int ret;
591
592 ret = fdt_node_check_compatible(gd->fdt_blob, node, "intel,ich7-spi");
593 if (ret == 0) {
594 plat->ich_version = ICHV_7;
595 } else {
596 ret = fdt_node_check_compatible(gd->fdt_blob, node,
597 "intel,ich9-spi");
598 if (ret == 0)
599 plat->ich_version = ICHV_9;
600 }
601
602 plat->lockdown = fdtdec_get_bool(gd->fdt_blob, node,
603 "intel,spi-lock-down");
604
605 return ret;
606}
607
608static const struct spi_controller_mem_ops ich_controller_mem_ops = {
609 .adjust_op_size = ich_spi_adjust_size,
610 .supports_op = NULL,
611 .exec_op = ich_spi_exec_op,
612};
613
614static const struct dm_spi_ops ich_spi_ops = {
615 .xfer = ich_spi_xfer,
616 .set_speed = ich_spi_set_speed,
617 .set_mode = ich_spi_set_mode,
618 .mem_ops = &ich_controller_mem_ops,
619
620
621
622
623};
624
625static const struct udevice_id ich_spi_ids[] = {
626 { .compatible = "intel,ich7-spi" },
627 { .compatible = "intel,ich9-spi" },
628 { }
629};
630
631U_BOOT_DRIVER(ich_spi) = {
632 .name = "ich_spi",
633 .id = UCLASS_SPI,
634 .of_match = ich_spi_ids,
635 .ops = &ich_spi_ops,
636 .ofdata_to_platdata = ich_spi_ofdata_to_platdata,
637 .platdata_auto_alloc_size = sizeof(struct ich_spi_platdata),
638 .priv_auto_alloc_size = sizeof(struct ich_spi_priv),
639 .child_pre_probe = ich_spi_child_pre_probe,
640 .probe = ich_spi_probe,
641 .remove = ich_spi_remove,
642 .flags = DM_FLAG_OS_PREPARE,
643};
644