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 <arch/io.h>
4 #include <stdint.h>
5 #include "smbus.h"
6 #include <console/console.h>
7 
8 static int smbus_wait_until_ready(u32 smbus_io_base)
9 {
10  u32 loops;
11 
12  loops = SMBUS_TIMEOUT;
13  do {
14  u8 val;
15  val = inb(smbus_io_base + SMBHSTSTAT);
16  val &= 0x1f;
17  if (val == 0) { /* ready now */
18  return 0;
19  }
20  outb(val, smbus_io_base + SMBHSTSTAT);
21  } while (--loops);
22 
23  return -2; /* time out */
24 }
25 
26 static int smbus_wait_until_done(u32 smbus_io_base)
27 {
28  u32 loops;
29 
30  loops = SMBUS_TIMEOUT;
31  do {
32  u8 val;
33 
34  val = inb(smbus_io_base + SMBHSTSTAT);
35  val &= 0x1f; /* mask off reserved bits */
36  if (val & 0x1c) {
37  return -5; /* error */
38  }
39  if (val == 0x02) {
40  outb(val, smbus_io_base + SMBHSTSTAT); /* clear status */
41  return 0;
42  }
43  } while (--loops);
44 
45  return -3; /* timeout */
46 }
47 
48 int do_smbus_recv_byte(u32 smbus_io_base, u32 device)
49 {
50  u8 byte;
51 
52  if (smbus_wait_until_ready(smbus_io_base) < 0) {
53  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - smbus not ready.\n", __func__);
54  return -2; /* not ready */
55  }
56 
57  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
58  /* set the device I'm talking to */
59  outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
60 
61  byte = inb(smbus_io_base + SMBHSTCTRL);
62  byte &= 0xe3; /* Clear [4:2] */
63  byte |= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */
64  outb(byte, smbus_io_base + SMBHSTCTRL);
65 
66  /* poll for transaction completion */
67  if (smbus_wait_until_done(smbus_io_base) < 0) {
68  return -3; /* timeout or error */
69  }
70 
71  /* read results of transaction */
72  byte = inb(smbus_io_base + SMBHSTCMD);
73 
74  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
75  return byte;
76 }
77 
78 int do_smbus_send_byte(u32 smbus_io_base, u32 device, u8 val)
79 {
80  u8 byte;
81 
82  if (smbus_wait_until_ready(smbus_io_base) < 0) {
83  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - smbus not ready.\n", __func__);
84  return -2; /* not ready */
85  }
86 
87  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
88  /* set the command... */
89  outb(val, smbus_io_base + SMBHSTCMD);
90 
91  /* set the device I'm talking to */
92  outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
93 
94  byte = inb(smbus_io_base + SMBHSTCTRL);
95  byte &= 0xe3; /* Clear [4:2] */
96  byte |= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */
97  outb(byte, smbus_io_base + SMBHSTCTRL);
98 
99  /* poll for transaction completion */
100  if (smbus_wait_until_done(smbus_io_base) < 0) {
101  return -3; /* timeout or error */
102  }
103 
104  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
105  return 0;
106 }
107 
109 {
110  u8 byte;
111 
112  if (smbus_wait_until_ready(smbus_io_base) < 0) {
113  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - smbus not ready.\n", __func__);
114  return -2; /* not ready */
115  }
116 
117  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
118  /* set the command/address... */
119  outb(address & 0xff, smbus_io_base + SMBHSTCMD);
120 
121  /* set the device I'm talking to */
122  outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
123 
124  byte = inb(smbus_io_base + SMBHSTCTRL);
125  byte &= 0xe3; /* Clear [4:2] */
126  byte |= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */
127  outb(byte, smbus_io_base + SMBHSTCTRL);
128 
129  /* poll for transaction completion */
130  if (smbus_wait_until_done(smbus_io_base) < 0) {
131  return -3; /* timeout or error */
132  }
133 
134  /* read results of transaction */
135  byte = inb(smbus_io_base + SMBHSTDAT0);
136 
137  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
138  return byte;
139 }
140 
142 {
143  u8 byte;
144 
145  if (smbus_wait_until_ready(smbus_io_base) < 0) {
146  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - smbus not ready.\n", __func__);
147  return -2; /* not ready */
148  }
149 
150  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
151  /* set the command/address... */
152  outb(address & 0xff, smbus_io_base + SMBHSTCMD);
153 
154  /* set the device I'm talking to */
155  outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
156 
157  /* output value */
158  outb(val, smbus_io_base + SMBHSTDAT0);
159 
160  byte = inb(smbus_io_base + SMBHSTCTRL);
161  byte &= 0xe3; /* Clear [4:2] */
162  byte |= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */
163  outb(byte, smbus_io_base + SMBHSTCTRL);
164 
165  /* poll for transaction completion */
166  if (smbus_wait_until_done(smbus_io_base) < 0) {
167  return -3; /* timeout or error */
168  }
169 
170  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
171  return 0;
172 }
173 
174 void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val)
175 {
176  u32 tmp;
177 
178  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
179  outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX);
180  tmp = inl(AB_DATA);
181  /* rpr 4.2
182  * For certain revisions of the chip, the ABCFG registers,
183  * with an address of 0x100NN (where 'N' is any hexadecimal
184  * number), require an extra programming step.*/
185  outl(0, AB_INDX);
186 
187  tmp &= ~mask;
188  tmp |= val;
189 
190  /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<29 | reg_addr); */
191  outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX); /* probably we don't have to do it again. */
192  outl(tmp, AB_DATA);
193  outl(0, AB_INDX);
194  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
195 }
196 
197 void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val)
198 {
199  u32 tmp;
200 
201  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
202  outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX);
203  tmp = inl(AB_DATA);
204  /* rpr 4.2
205  * For certain revisions of the chip, the ABCFG registers,
206  * with an address of 0x100NN (where 'N' is any hexadecimal
207  * number), require an extra programming step.*/
208  outl(0, AB_INDX);
209 
210  tmp &= ~mask;
211  tmp |= val;
212 
213  //printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<29 | (port&3) << 24 | reg_addr);
214  outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX); /* probably we don't have to do it again. */
215  outl(tmp, AB_DATA);
216  outl(0, AB_INDX);
217  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
218 }
219 
220 /* space = 0: AX_INDXC, AX_DATAC
221  * space = 1: AX_INDXP, AX_DATAP
222  */
223 void alink_ax_indx(u32 space /*c or p? */, u32 axindc, u32 mask, u32 val)
224 {
225  u32 tmp;
226 
227  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
228  /* read axindc to tmp */
229  outl(space << 29 | space << 3 | 0x30, AB_INDX);
230  outl(axindc, AB_DATA);
231  outl(0, AB_INDX);
232  outl(space << 29 | space << 3 | 0x34, AB_INDX);
233  tmp = inl(AB_DATA);
234  outl(0, AB_INDX);
235 
236  tmp &= ~mask;
237  tmp |= val;
238 
239  /* write tmp */
240  outl(space << 29 | space << 3 | 0x30, AB_INDX);
241  outl(axindc, AB_DATA);
242  outl(0, AB_INDX);
243  outl(space << 29 | space << 3 | 0x34, AB_INDX);
244  outl(tmp, AB_DATA);
245  outl(0, AB_INDX);
246  printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
247 }
#define printk(level,...)
Definition: stdlib.h:16
u8 inb(u16 port)
void outb(u8 val, u16 port)
u32 inl(u16 port)
void outl(u32 val, u16 port)
uint64_t address
Definition: fw_cfg_if.h:0
port
Definition: i915.h:29
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define SMBHSTADDR
Definition: smbus.h:39
#define SMBHSTCTRL
Definition: smbus.h:26
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
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 const int mask[4]
Definition: gpio.c:308
void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val)
Definition: smbus.c:185
void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val)
Definition: smbus.c:164
void alink_ax_indx(u32 space, u32 axindc, u32 mask, u32 val)
Definition: smbus.c:209
static int smbus_wait_until_ready(u32 smbus_io_base)
Definition: smbus.c:8
static int smbus_wait_until_done(u32 smbus_io_base)
Definition: smbus.c:26
#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
uint8_t u8
Definition: stdint.h:45
Definition: device.h:107
u8 val
Definition: sys.c:300