coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
spi.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdint.h>
4 #include <device/mmio.h>
5 #include <console/console.h>
6 #include <spi_flash.h>
7 #include <spi-generic.h>
8 #include <device/device.h>
9 #include <device/pci.h>
10 #include <device/pci_ops.h>
11 #include <stddef.h>
12 
13 #include <Proc/Fch/FchPlatform.h>
14 
15 #define SPI_REG_OPCODE 0x0
16 #define SPI_REG_CNTRL01 0x1
17 #define SPI_REG_CNTRL02 0x2
18  #define CNTRL02_FIFO_RESET (1 << 4)
19  #define CNTRL02_EXEC_OPCODE (1 << 0)
20 #define SPI_REG_CNTRL03 0x3
21  #define CNTRL03_SPIBUSY (1 << 7)
22 #define SPI_REG_FIFO 0xc
23 #define SPI_REG_CNTRL11 0xd
24  #define CNTRL11_FIFOPTR_MASK 0x07
25 
26 #if CONFIG(SOUTHBRIDGE_AMD_AGESA_YANGTZE)
27 #define AMD_SB_SPI_TX_LEN 64
28 #else
29 #define AMD_SB_SPI_TX_LEN 8
30 #endif
31 
33 
34 static inline uint8_t spi_read(uint8_t reg)
35 {
36  return read8((void *)(spibar + reg));
37 }
38 
39 static inline void spi_write(uint8_t reg, uint8_t val)
40 {
41  write8((void *)(spibar + reg), val);
42 }
43 
44 static void reset_internal_fifo_pointer(void)
45 {
46  uint8_t reg8;
47 
48  do {
49  reg8 = spi_read(SPI_REG_CNTRL02);
50  reg8 |= CNTRL02_FIFO_RESET;
53 }
54 
55 static void execute_command(void)
56 {
57  uint8_t reg8;
58 
59  reg8 = spi_read(SPI_REG_CNTRL02);
60  reg8 |= CNTRL02_EXEC_OPCODE;
62 
65 }
66 
67 void spi_init(void)
68 {
69  struct device *dev;
70 
71  dev = pcidev_on_root(0x14, 3);
72  spibar = pci_read_config32(dev, 0xA0) & ~0x1F;
73 }
74 
75 static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
76  size_t bytesout, void *din, size_t bytesin)
77 {
78  /* First byte is cmd which can not be sent through FIFO. */
79  u8 cmd = *(u8 *)dout++;
80  u8 readoffby1;
81  size_t count;
82 
83  bytesout--;
84 
85  /*
86  * Check if this is a write command attempting to transfer more bytes
87  * than the controller can handle. Iterations for writes are not
88  * supported here because each SPI write command needs to be preceded
89  * and followed by other SPI commands, and this sequence is controlled
90  * by the SPI chip driver.
91  */
92  if (bytesout > AMD_SB_SPI_TX_LEN) {
93  printk(BIOS_DEBUG, "FCH SPI: Too much to write. Does your SPI chip driver use"
94  " spi_crop_chunk()?\n");
95  return -1;
96  }
97 
98  readoffby1 = bytesout ? 0 : 1;
99 
100  if (CONFIG(SOUTHBRIDGE_AMD_AGESA_YANGTZE)) {
101  spi_write(0x1E, 5);
102  spi_write(0x1F, bytesout); /* SpiExtRegIndx [5] - TxByteCount */
103  spi_write(0x1E, 6);
104  spi_write(0x1F, bytesin); /* SpiExtRegIndx [6] - RxByteCount */
105  } else {
106  u8 readwrite = (bytesin + readoffby1) << 4 | bytesout;
107  spi_write(SPI_REG_CNTRL01, readwrite);
108  }
110 
112  for (count = 0; count < bytesout; count++, dout++) {
113  spi_write(SPI_REG_FIFO, *(uint8_t *)dout);
114  }
115 
117  execute_command();
118 
120  /* Skip the bytes we sent. */
121  for (count = 0; count < bytesout; count++) {
123  }
124 
125  for (count = 0; count < bytesin; count++, din++) {
126  *(uint8_t *)din = spi_read(SPI_REG_FIFO);
127  }
128 
129  return 0;
130 }
131 
132 int chipset_volatile_group_begin(const struct spi_flash *flash)
133 {
134  if (!CONFIG(HUDSON_IMC_FWM))
135  return 0;
136 
137  ImcSleep(NULL);
138  return 0;
139 }
140 
141 int chipset_volatile_group_end(const struct spi_flash *flash)
142 {
143  if (!CONFIG(HUDSON_IMC_FWM))
144  return 0;
145 
146  ImcWakeup(NULL);
147  return 0;
148 }
149 
150 static int xfer_vectors(const struct spi_slave *slave,
151  struct spi_op vectors[], size_t count)
152 {
154 }
155 
156 static const struct spi_ctrlr spi_ctrlr = {
158  .max_xfer_size = AMD_SB_SPI_TX_LEN,
159  .flags = SPI_CNTRLR_DEDUCT_CMD_LEN,
160 };
161 
162 const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
163  {
164  .ctrlr = &spi_ctrlr,
165  .bus_start = 0,
166  .bus_end = 0,
167  },
168 };
169 
static void write8(void *addr, uint8_t val)
Definition: mmio.h:30
static uint8_t read8(const void *addr)
Definition: mmio.h:12
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define printk(level,...)
Definition: stdlib.h:16
DEVTREE_CONST struct device * pcidev_on_root(uint8_t dev, uint8_t fn)
Definition: device_const.c:260
@ CONFIG
Definition: dsi_common.h:201
static __always_inline u32 pci_read_config32(const struct device *dev, u16 reg)
Definition: pci_ops.h:58
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
const struct spi_ctrlr_buses spi_ctrlr_bus_map[]
Definition: spi.c:401
void spi_init(void)
Init all SPI controllers with default values and enable all SPI controller.
Definition: spi.c:280
const size_t spi_ctrlr_bus_map_count
Definition: spi.c:408
const struct spi_ctrlr spi_ctrlr
Definition: spi.c:261
#define SPI_REG_OPCODE
Definition: spi.c:15
static uintptr_t spibar
Definition: spi.c:32
#define CNTRL02_EXEC_OPCODE
Definition: spi.c:19
static int xfer_vectors(const struct spi_slave *slave, struct spi_op vectors[], size_t count)
Definition: spi.c:150
int chipset_volatile_group_begin(const struct spi_flash *flash)
Definition: spi.c:132
#define SPI_REG_CNTRL02
Definition: spi.c:17
#define SPI_REG_CNTRL03
Definition: spi.c:20
static void spi_write(uint8_t reg, uint8_t val)
Definition: spi.c:39
#define CNTRL02_FIFO_RESET
Definition: spi.c:18
static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout, void *din, size_t bytesin)
Definition: spi.c:75
#define SPI_REG_FIFO
Definition: spi.c:22
#define SPI_REG_CNTRL11
Definition: spi.c:23
#define CNTRL11_FIFOPTR_MASK
Definition: spi.c:24
int chipset_volatile_group_end(const struct spi_flash *flash)
Definition: spi.c:141
static uint8_t spi_read(uint8_t reg)
Definition: spi.c:34
#define CNTRL03_SPIBUSY
Definition: spi.c:21
#define AMD_SB_SPI_TX_LEN
Definition: spi.c:29
static void execute_command(void)
Definition: spi.c:55
#define SPI_REG_CNTRL01
Definition: spi.c:16
static void reset_internal_fifo_pointer(void)
Definition: spi.c:44
static void ImcWakeup(void)
Definition: spi.c:108
static void ImcSleep(void)
Definition: spi.c:95
@ SPI_CNTRLR_DEDUCT_CMD_LEN
Definition: spi-generic.h:116
int spi_flash_vector_helper(const struct spi_slave *slave, struct spi_op vectors[], size_t count, int(*func)(const struct spi_slave *slave, const void *dout, size_t bytesout, void *din, size_t bytesin))
Definition: spi_flash.c:745
static struct spi_slave slave
Definition: spiconsole.c:7
#define NULL
Definition: stddef.h:19
unsigned long uintptr_t
Definition: stdint.h:21
uint8_t u8
Definition: stdint.h:45
unsigned char uint8_t
Definition: stdint.h:8
Definition: device.h:107
const struct spi_ctrlr * ctrlr
Definition: spi-generic.h:175
int(* xfer_vector)(const struct spi_slave *slave, struct spi_op vectors[], size_t count)
Definition: spi-generic.h:154
u8 val
Definition: sys.c:300
#define count