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