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 <device/mmio.h>
4 #include <console/console.h>
5 #include <spi_flash.h>
6 #include <spi-generic.h>
7 #include <device/device.h>
8 #include <device/pci.h>
9 #include <device/pci_ops.h>
10 #include <types.h>
11 
12 #include "SBPLATFORM.h"
13 #include <vendorcode/amd/cimx/sb800/ECfan.h>
14 
15 #define AMD_SB_SPI_TX_LEN 8
16 
18 
19 static void reset_internal_fifo_pointer(void)
20 {
21  do {
22  write8((void *)(spibar + 2),
23  read8((void *)(spibar + 2)) | 0x10);
24  } while (read8((void *)(spibar + 0xD)) & 0x7);
25 }
26 
27 static void execute_command(void)
28 {
29  write8((void *)(spibar + 2), read8((void *)(spibar + 2)) | 1);
30 
31  while ((read8((void *)(spibar + 2)) & 1) &&
32  (read8((void *)(spibar+3)) & 0x80));
33 }
34 
35 void spi_init(void)
36 {
37  struct device *dev;
38 
39  dev = pcidev_on_root(0x14, 3);
40  spibar = pci_read_config32(dev, 0xA0) & ~0x1F;
41 }
42 
43 static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
44  size_t bytesout, void *din, size_t bytesin)
45 {
46  /* First byte is cmd which can not be sent through FIFO. */
47  u8 cmd = *(u8 *)dout++;
48  u8 readoffby1;
49  u8 readwrite;
50  size_t count;
51 
52  bytesout--;
53 
54  /*
55  * Check if this is a write command attempting to transfer more bytes
56  * than the controller can handle. Iterations for writes are not
57  * supported here because each SPI write command needs to be preceded
58  * and followed by other SPI commands, and this sequence is controlled
59  * by the SPI chip driver.
60  */
61  if (bytesout > AMD_SB_SPI_TX_LEN) {
62  printk(BIOS_DEBUG, "FCH SPI: Too much to write. Does your SPI chip driver use"
63  " spi_crop_chunk()?\n");
64  return -1;
65  }
66 
67  readoffby1 = bytesout ? 0 : 1;
68 
69  readwrite = (bytesin + readoffby1) << 4 | bytesout;
70  write8((void *)(spibar + 1), readwrite);
71  write8((void *)(spibar + 0), cmd);
72 
74  for (count = 0; count < bytesout; count++, dout++) {
75  write8((void *)(spibar + 0x0C), *(u8 *)dout);
76  }
77 
80 
82  /* Skip the bytes we sent. */
83  for (count = 0; count < bytesout; count++) {
84  read8((void *)(spibar + 0x0C));
85  }
86 
88  for (count = 0; count < bytesin; count++, din++) {
89  *(u8 *)din = read8((void *)(spibar + 0x0C));
90  }
91 
92  return 0;
93 }
94 
95 static void ImcSleep(void)
96 {
97  u8 cmd_val = 0x96; /* Kick off IMC Mailbox command 96 */
98  u8 reg0_val = 0; /* clear response register */
99  u8 reg1_val = 0xB4; /* request ownership flag */
100 
101  WriteECmsg (MSG_REG0, AccWidthUint8, &reg0_val);
102  WriteECmsg (MSG_REG1, AccWidthUint8, &reg1_val);
103  WriteECmsg (MSG_SYS_TO_IMC, AccWidthUint8, &cmd_val);
104 
105  WaitForEcLDN9MailboxCmdAck();
106 }
107 
108 static void ImcWakeup(void)
109 {
110  u8 cmd_val = 0x96; /* Kick off IMC Mailbox command 96 */
111  u8 reg0_val = 0; /* clear response register */
112  u8 reg1_val = 0xB5; /* release ownership flag */
113 
114  WriteECmsg (MSG_REG0, AccWidthUint8, &reg0_val);
115  WriteECmsg (MSG_REG1, AccWidthUint8, &reg1_val);
116  WriteECmsg (MSG_SYS_TO_IMC, AccWidthUint8, &cmd_val);
117 
118  WaitForEcLDN9MailboxCmdAck();
119 }
120 
121 int chipset_volatile_group_begin(const struct spi_flash *flash)
122 {
123  if (!CONFIG(SB800_IMC_FWM))
124  return 0;
125 
126  ImcSleep();
127  return 0;
128 }
129 
130 int chipset_volatile_group_end(const struct spi_flash *flash)
131 {
132  if (!CONFIG(SB800_IMC_FWM))
133  return 0;
134 
135  ImcWakeup();
136  return 0;
137 }
138 
139 static int xfer_vectors(const struct spi_slave *slave,
140  struct spi_op vectors[], size_t count)
141 {
143 }
144 
145 static const struct spi_ctrlr spi_ctrlr = {
147  .max_xfer_size = AMD_SB_SPI_TX_LEN,
148  .flags = SPI_CNTRLR_DEDUCT_CMD_LEN,
149 };
150 
151 const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
152  {
153  .ctrlr = &spi_ctrlr,
154  .bus_start = 0,
155  .bus_end = 0,
156  },
157 };
158 
@ AccWidthUint8
Definition: AmdSbLib.h:136
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
int chipset_volatile_group_begin(const struct spi_flash *flash)
Definition: spi.c:132
int chipset_volatile_group_end(const struct spi_flash *flash)
Definition: spi.c:141
static uintptr_t spibar
Definition: spi.c:17
static void ImcWakeup(void)
Definition: spi.c:108
static int xfer_vectors(const struct spi_slave *slave, struct spi_op vectors[], size_t count)
Definition: spi.c:139
static void ImcSleep(void)
Definition: spi.c:95
static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout, void *din, size_t bytesin)
Definition: spi.c:43
#define AMD_SB_SPI_TX_LEN
Definition: spi.c:15
static void execute_command(void)
Definition: spi.c:27
static void reset_internal_fifo_pointer(void)
Definition: spi.c:19
@ 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
unsigned long uintptr_t
Definition: stdint.h:21
uint8_t u8
Definition: stdint.h:45
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
#define count