blob: 4fb68d425da7570fb483e13755f1f206d1617ba7 [file] [log] [blame]
Angel Ponsae593872020-04-04 18:50:57 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Martin Roth5c354b92019-04-22 14:55:16 -06002
Martin Roth5c354b92019-04-22 14:55:16 -06003#include <stdint.h>
4#include <console/console.h>
Aaron Durbin7cd39d22020-01-28 11:12:34 -07005#include <device/smbus_host.h>
Martin Roth5c354b92019-04-22 14:55:16 -06006#include <amdblocks/acpimmio.h>
Kyösti Mälkki5b672d52019-11-25 21:23:37 +02007#include <amdblocks/acpimmio_map.h>
Felix Held875e5aa2020-12-01 00:34:11 +01008#include <amdblocks/smbus.h>
Martin Roth5c354b92019-04-22 14:55:16 -06009
Aaron Durbinc3488982020-01-28 11:00:51 -070010/*
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
Aaron Durbin7cd39d22020-01-28 11:12:34 -070016static u8 controller_read8(uintptr_t base, u8 reg)
Martin Roth5c354b92019-04-22 14:55:16 -060017{
18 switch (base) {
19 case ACPIMMIO_SMBUS_BASE:
20 return smbus_read8(reg);
21 case ACPIMMIO_ASF_BASE:
22 return asf_read8(reg);
23 default:
Aaron Durbin7cd39d22020-01-28 11:12:34 -070024 printk(BIOS_ERR, "Error attempting to read SMBus at address 0x%lx\n",
Martin Roth5c354b92019-04-22 14:55:16 -060025 base);
26 }
27 return 0xff;
28}
29
Aaron Durbin7cd39d22020-01-28 11:12:34 -070030static void controller_write8(uintptr_t base, u8 reg, u8 val)
Martin Roth5c354b92019-04-22 14:55:16 -060031{
32 switch (base) {
33 case ACPIMMIO_SMBUS_BASE:
34 smbus_write8(reg, val);
35 break;
36 case ACPIMMIO_ASF_BASE:
37 asf_write8(reg, val);
38 break;
39 default:
Aaron Durbin7cd39d22020-01-28 11:12:34 -070040 printk(BIOS_ERR, "Error attempting to write SMBus at address 0x%lx\n",
Martin Roth5c354b92019-04-22 14:55:16 -060041 base);
42 }
43}
44
Aaron Durbin7cd39d22020-01-28 11:12:34 -070045static int smbus_wait_until_ready(uintptr_t mmio)
Martin Roth5c354b92019-04-22 14:55:16 -060046{
47 u32 loops;
48 loops = SMBUS_TIMEOUT;
49 do {
50 u8 val;
51 val = controller_read8(mmio, SMBHSTSTAT);
52 val &= SMBHST_STAT_VAL_BITS;
53 if (val == 0) { /* ready now */
54 return 0;
55 }
56 controller_write8(mmio, SMBHSTSTAT, val);
57 } while (--loops);
58 return -2; /* time out */
59}
60
Aaron Durbin7cd39d22020-01-28 11:12:34 -070061static int smbus_wait_until_done(uintptr_t mmio)
Martin Roth5c354b92019-04-22 14:55:16 -060062{
63 u32 loops;
64 loops = SMBUS_TIMEOUT;
65 do {
66 u8 val;
67
68 val = controller_read8(mmio, SMBHSTSTAT);
69 val &= SMBHST_STAT_VAL_BITS; /* mask off reserved bits */
70 if (val & SMBHST_STAT_ERROR_BITS)
71 return -5; /* error */
Felix Heldf42da172020-12-01 21:29:59 +010072 /* check IRQ status bit to see if the last host command is completed */
73 if (val == SMBHST_STAT_INTERRUPT) {
Martin Roth5c354b92019-04-22 14:55:16 -060074 controller_write8(mmio, SMBHSTSTAT, val); /* clr sts */
75 return 0;
76 }
77 } while (--loops);
78 return -3; /* timeout */
79}
80
Aaron Durbin7cd39d22020-01-28 11:12:34 -070081int do_smbus_recv_byte(uintptr_t mmio, u8 device)
Martin Roth5c354b92019-04-22 14:55:16 -060082{
83 u8 byte;
84
85 if (smbus_wait_until_ready(mmio) < 0)
86 return -2; /* not ready */
87
88 /* set the device I'm talking to */
89 controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1);
90
91 byte = controller_read8(mmio, SMBHSTCTRL);
92 byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
93 byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */
94 controller_write8(mmio, SMBHSTCTRL, byte);
95
96 /* poll for transaction completion */
97 if (smbus_wait_until_done(mmio) < 0)
98 return -3; /* timeout or error */
99
100 /* read results of transaction */
101 byte = controller_read8(mmio, SMBHSTDAT0);
102
103 return byte;
104}
105
Aaron Durbin7cd39d22020-01-28 11:12:34 -0700106int do_smbus_send_byte(uintptr_t mmio, u8 device, u8 val)
Martin Roth5c354b92019-04-22 14:55:16 -0600107{
108 u8 byte;
109
110 if (smbus_wait_until_ready(mmio) < 0)
111 return -2; /* not ready */
112
113 /* set the command... */
114 controller_write8(mmio, SMBHSTDAT0, val);
115
116 /* set the device I'm talking to */
117 controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0);
118
119 byte = controller_read8(mmio, SMBHSTCTRL);
120 byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
121 byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BTE_RW; /* set mode, start */
122 controller_write8(mmio, SMBHSTCTRL, byte);
123
124 /* poll for transaction completion */
125 if (smbus_wait_until_done(mmio) < 0)
126 return -3; /* timeout or error */
127
128 return 0;
129}
130
Aaron Durbin7cd39d22020-01-28 11:12:34 -0700131int do_smbus_read_byte(uintptr_t mmio, u8 device, u8 address)
Martin Roth5c354b92019-04-22 14:55:16 -0600132{
133 u8 byte;
134
135 if (smbus_wait_until_ready(mmio) < 0)
136 return -2; /* not ready */
137
138 /* set the command/address... */
139 controller_write8(mmio, SMBHSTCMD, address & 0xff);
140
141 /* set the device I'm talking to */
142 controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 1);
143
144 byte = controller_read8(mmio, SMBHSTCTRL);
145 byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
146 byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */
147 controller_write8(mmio, SMBHSTCTRL, byte);
148
149 /* poll for transaction completion */
150 if (smbus_wait_until_done(mmio) < 0)
151 return -3; /* timeout or error */
152
153 /* read results of transaction */
154 byte = controller_read8(mmio, SMBHSTDAT0);
155
156 return byte;
157}
158
Aaron Durbin7cd39d22020-01-28 11:12:34 -0700159int do_smbus_write_byte(uintptr_t mmio, u8 device, u8 address, u8 val)
Martin Roth5c354b92019-04-22 14:55:16 -0600160{
161 u8 byte;
162
163 if (smbus_wait_until_ready(mmio) < 0)
164 return -2; /* not ready */
165
166 /* set the command/address... */
167 controller_write8(mmio, SMBHSTCMD, address & 0xff);
168
169 /* set the device I'm talking to */
170 controller_write8(mmio, SMBHSTADDR, ((device & 0x7f) << 1) | 0);
171
172 /* output value */
173 controller_write8(mmio, SMBHSTDAT0, val);
174
175 byte = controller_read8(mmio, SMBHSTCTRL);
176 byte &= ~SMBHST_CTRL_MODE_BITS; /* Clear [4:2] */
177 byte |= SMBHST_CTRL_STRT | SMBHST_CTRL_BDT_RW; /* set mode, start */
178 controller_write8(mmio, SMBHSTCTRL, byte);
179
180 /* poll for transaction completion */
181 if (smbus_wait_until_done(mmio) < 0)
182 return -3; /* timeout or error */
183
184 return 0;
185}