2 * This file is part of the coreboot project.
4 * Copyright (C) 2012 Google Inc. All rights reserved.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
18 #include <console/console.h>
19 #include <device/pci_ids.h>
20 #include <device/pci_def.h>
24 #define SPI_DELAY 10 /* 10us */
25 #define SPI_RETRY 200000 /* 2s */
27 static int early_spi_read_block(u32 offset
, u8 size
, u8
*buffer
)
29 u32
*ptr32
= (u32
*)buffer
;
32 /* Clear status bits */
33 RCBA16(SPIBAR_HSFS
) |= SPIBAR_HSFS_AEL
| SPIBAR_HSFS_FCERR
|
36 if (RCBA16(SPIBAR_HSFS
) & SPIBAR_HSFS_SCIP
) {
37 printk(BIOS_ERR
, "SPI ERROR: transaction in progress\n");
41 /* Set flash address */
42 RCBA32(SPIBAR_FADDR
) = offset
;
44 /* Setup read transaction */
45 RCBA16(SPIBAR_HSFC
) = SPIBAR_HSFC_BYTE_COUNT(size
) |
46 SPIBAR_HSFC_CYCLE_READ
;
48 /* Start transactinon */
49 RCBA16(SPIBAR_HSFC
) |= SPIBAR_HSFC_GO
;
51 /* Wait for completion */
52 for (i
= 0; i
< SPI_RETRY
; i
++) {
53 if (RCBA16(SPIBAR_HSFS
) & SPIBAR_HSFS_SCIP
) {
54 /* Cycle in progress, wait 1ms */
59 if (RCBA16(SPIBAR_HSFS
) & SPIBAR_HSFS_AEL
) {
60 printk(BIOS_ERR
, "SPI ERROR: Access Error\n");
65 if (RCBA16(SPIBAR_HSFS
) & SPIBAR_HSFS_FCERR
) {
66 printk(BIOS_ERR
, "SPI ERROR: Flash Cycle Error\n");
73 printk(BIOS_ERR
, "SPI ERROR: Timeout\n");
78 for (i
= 0; i
< size
; i
+=sizeof(u32
)) {
80 /* reading >= dword */
81 *ptr32
++ = RCBA32(SPIBAR_FDATA(i
/sizeof(u32
)));
84 u8 j
, *ptr8
= (u8
*)ptr32
;
85 u32 temp
= RCBA32(SPIBAR_FDATA(i
/sizeof(u32
)));
86 for (j
= 0; j
< (size
-i
); j
++) {
87 *ptr8
++ = temp
& 0xff;
96 int early_spi_read(u32 offset
, u32 size
, u8
*buffer
)
101 u8 count
= (size
< 64) ? size
: 64;
102 if (early_spi_read_block(offset
+ current
, count
,
103 buffer
+ current
) < 0)