coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
smbus.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <inttypes.h>
4 #include <console/console.h>
5 #include <device/smbus_host.h>
6 #include <amdblocks/acpimmio.h>
7 #include <amdblocks/smbus.h>
8 #include <soc/southbridge.h>
9 
10 /*
11  * Between 1-10 seconds, We should never timeout normally
12  * Longer than this is just painful when a timeout condition occurs.
13  */
14 #define SMBUS_TIMEOUT (100 * 1000 * 10)
15 
16 /* FIXME: Passing host base for SMBUS is not long-term solution.
17  It is possible to have multiple buses behind same host. */
18 
19 static u8 controller_read8(const uintptr_t base, const u8 reg)
20 {
21  return read8((void *)(base + reg));
22 }
23 
24 static void controller_write8(const uintptr_t base, const u8 reg, const u8 val)
25 {
26  write8((void *)(base + reg), val);
27 }
28 
30 {
31  if ((mmio != (uintptr_t)acpimmio_smbus) &&
32  (mmio != (uintptr_t)acpimmio_asf)) {
33  printk(BIOS_ERR, "Invalid SMBus or ASF base %#" PRIxPTR "\n", mmio);
34  return -1;
35  }
36 
37  u32 loops;
38  loops = SMBUS_TIMEOUT;
39  do {
40  u8 val;
43  if (val == 0) { /* ready now */
44  return 0;
45  }
47  } while (--loops);
48  return -2; /* time out */
49 }
50 
52 {
53  u32 loops;
54  loops = SMBUS_TIMEOUT;
55  do {
56  u8 val;
57 
59  val &= SMBHST_STAT_VAL_BITS; /* mask off reserved bits */
61  return -5; /* error */
62  /* check IRQ status bit to see if the last host command is completed */
63  if (val == SMBHST_STAT_INTERRUPT) {
64  controller_write8(mmio, SMBHSTSTAT, val); /* clr sts */
65  return 0;
66  }
67  } while (--loops);
68  return -3; /* timeout */
69 }
70 
72 {
73  u8 byte;
74 
75  if (smbus_wait_until_ready(mmio) < 0)
76  return -2; /* not ready */
77 
78  /* set the device I'm talking to */
79  controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1);
80 
81  byte = controller_read8(mmio, SMBHSTCTRL);
82  byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
83  byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */
84  controller_write8(mmio, SMBHSTCTRL, byte);
85 
86  /* poll for transaction completion */
87  if (smbus_wait_until_done(mmio) < 0)
88  return -3; /* timeout or error */
89 
90  /* read results of transaction */
91  byte = controller_read8(mmio, SMBHSTDAT0);
92 
93  return byte;
94 }
95 
97 {
98  u8 byte;
99 
100  if (smbus_wait_until_ready(mmio) < 0)
101  return -2; /* not ready */
102 
103  /* set the command... */
105 
106  /* set the device I'm talking to */
107  controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0);
108 
109  byte = controller_read8(mmio, SMBHSTCTRL);
110  byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
111  byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */
112  controller_write8(mmio, SMBHSTCTRL, byte);
113 
114  /* poll for transaction completion */
115  if (smbus_wait_until_done(mmio) < 0)
116  return -3; /* timeout or error */
117 
118  return 0;
119 }
120 
122 {
123  u8 byte;
124 
125  if (smbus_wait_until_ready(mmio) < 0)
126  return -2; /* not ready */
127 
128  /* set the command/address... */
129  controller_write8(mmio, SMBHSTCMD, address & 0xff);
130 
131  /* set the device I'm talking to */
132  controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1);
133 
134  byte = controller_read8(mmio, SMBHSTCTRL);
135  byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
136  byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */
137  controller_write8(mmio, SMBHSTCTRL, byte);
138 
139  /* poll for transaction completion */
140  if (smbus_wait_until_done(mmio) < 0)
141  return -3; /* timeout or error */
142 
143  /* read results of transaction */
144  byte = controller_read8(mmio, SMBHSTDAT0);
145 
146  return byte;
147 }
148 
150 {
151  u8 byte;
152 
153  if (smbus_wait_until_ready(mmio) < 0)
154  return -2; /* not ready */
155 
156  /* set the command/address... */
157  controller_write8(mmio, SMBHSTCMD, address & 0xff);
158 
159  /* set the device I'm talking to */
160  controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0);
161 
162  /* output value */
164 
165  byte = controller_read8(mmio, SMBHSTCTRL);
166  byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
167  byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */
168  controller_write8(mmio, SMBHSTCTRL, byte);
169 
170  /* poll for transaction completion */
171  if (smbus_wait_until_done(mmio) < 0)
172  return -3; /* timeout or error */
173 
174  return 0;
175 }
uint8_t *MAYBE_CONST acpimmio_smbus
uint8_t *MAYBE_CONST acpimmio_asf
static void write8(void *addr, uint8_t val)
Definition: mmio.h:30
static uint8_t read8(const void *addr)
Definition: mmio.h:12
#define printk(level,...)
Definition: stdlib.h:16
uint64_t address
Definition: fw_cfg_if.h:0
#define PRIxPTR
Definition: inttypes.h:45
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
uintptr_t base
Definition: uart.c:17
#define SMBHST_CTRL_MODE_BITS
Definition: smbus.h:34
#define SMBHSTADDR
Definition: smbus.h:39
#define SMBHST_CTRL_STRT
Definition: smbus.h:28
#define SMBHSTCTRL
Definition: smbus.h:26
#define SMBHST_STAT_ERROR_BITS
Definition: smbus.h:15
#define SMBHST_STAT_INTERRUPT
Definition: smbus.h:11
#define SMBHST_CTRL_BDT_RW
Definition: smbus.h:31
#define SMBHST_STAT_VAL_BITS
Definition: smbus.h:14
#define SMBHST_CTRL_BTE_RW
Definition: smbus.h:30
static u8 controller_read8(const uintptr_t base, const u8 reg)
Definition: smbus.c:19
int do_smbus_recv_byte(uintptr_t mmio, u8 device)
Definition: smbus.c:71
int do_smbus_read_byte(uintptr_t mmio, u8 device, u8 address)
Definition: smbus.c:121
static int smbus_wait_until_ready(uintptr_t mmio)
Definition: smbus.c:29
static int smbus_wait_until_done(uintptr_t mmio)
Definition: smbus.c:51
int do_smbus_write_byte(uintptr_t mmio, u8 device, u8 address, u8 val)
Definition: smbus.c:149
int do_smbus_send_byte(uintptr_t mmio, u8 device, u8 val)
Definition: smbus.c:96
#define SMBUS_TIMEOUT
Definition: smbus.c:14
static void controller_write8(const uintptr_t base, const u8 reg, const u8 val)
Definition: smbus.c:24
#define SMBHSTDAT0
Definition: smbus.c:20
#define SMBHSTSTAT
Definition: smbus.c:16
#define SMBHSTCMD
Definition: smbus.c:18
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
uint8_t u8
Definition: stdint.h:45
Definition: device.h:107
u8 val
Definition: sys.c:300