blob: 1c71c879484a4d059e8b7ea28f05cbb64381e69f [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
zbao246e84b2012-07-13 18:47:03 +08003
Elyes HAOUAS65fa5982014-07-22 23:12:38 +02004#ifndef _HUDSON_SMBUS_C_
5#define _HUDSON_SMBUS_C_
zbao246e84b2012-07-13 18:47:03 +08006
Kyösti Mälkkie132d572019-03-02 19:06:17 +02007#include <arch/io.h>
Paul Menzel883b03f2013-05-06 15:18:57 +02008#include <stdint.h>
zbao246e84b2012-07-13 18:47:03 +08009#include "smbus.h"
10
zbao246e84b2012-07-13 18:47:03 +080011static int smbus_wait_until_ready(u32 smbus_io_base)
12{
13 u32 loops;
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 return -2; /* time out */
25}
26
27static int smbus_wait_until_done(u32 smbus_io_base)
28{
29 u32 loops;
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 return -3; /* timeout */
45}
46
47int do_smbus_recv_byte(u32 smbus_io_base, u32 device)
48{
49 u8 byte;
50
51 if (smbus_wait_until_ready(smbus_io_base) < 0) {
52 return -2; /* not ready */
53 }
54
Jonathan Neuschäfer70903772017-09-23 21:39:02 +020055 /* set the device I'm talking to */
zbao246e84b2012-07-13 18:47:03 +080056 outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
57
58 byte = inb(smbus_io_base + SMBHSTCTRL);
59 byte &= 0xe3; /* Clear [4:2] */
60 byte |= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */
61 outb(byte, smbus_io_base + SMBHSTCTRL);
62
63 /* poll for transaction completion */
64 if (smbus_wait_until_done(smbus_io_base) < 0) {
65 return -3; /* timeout or error */
66 }
67
68 /* read results of transaction */
69 byte = inb(smbus_io_base + SMBHSTCMD);
70
71 return byte;
72}
73
74int do_smbus_send_byte(u32 smbus_io_base, u32 device, u8 val)
75{
76 u8 byte;
77
78 if (smbus_wait_until_ready(smbus_io_base) < 0) {
79 return -2; /* not ready */
80 }
81
82 /* set the command... */
83 outb(val, smbus_io_base + SMBHSTCMD);
84
Jonathan Neuschäfer70903772017-09-23 21:39:02 +020085 /* set the device I'm talking to */
zbao246e84b2012-07-13 18:47:03 +080086 outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
87
88 byte = inb(smbus_io_base + SMBHSTCTRL);
89 byte &= 0xe3; /* Clear [4:2] */
90 byte |= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */
91 outb(byte, smbus_io_base + SMBHSTCTRL);
92
93 /* poll for transaction completion */
94 if (smbus_wait_until_done(smbus_io_base) < 0) {
95 return -3; /* timeout or error */
96 }
97
98 return 0;
99}
100
101int do_smbus_read_byte(u32 smbus_io_base, u32 device,
102 u32 address)
103{
104 u8 byte;
105
106 if (smbus_wait_until_ready(smbus_io_base) < 0) {
107 return -2; /* not ready */
108 }
109
110 /* set the command/address... */
111 outb(address & 0xff, smbus_io_base + SMBHSTCMD);
112
Jonathan Neuschäfer70903772017-09-23 21:39:02 +0200113 /* set the device I'm talking to */
zbao246e84b2012-07-13 18:47:03 +0800114 outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
115
116 byte = inb(smbus_io_base + SMBHSTCTRL);
117 byte &= 0xe3; /* Clear [4:2] */
118 byte |= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */
119 outb(byte, smbus_io_base + SMBHSTCTRL);
120
121 /* poll for transaction completion */
122 if (smbus_wait_until_done(smbus_io_base) < 0) {
123 return -3; /* timeout or error */
124 }
125
126 /* read results of transaction */
127 byte = inb(smbus_io_base + SMBHSTDAT0);
128
129 return byte;
130}
131
132int do_smbus_write_byte(u32 smbus_io_base, u32 device,
133 u32 address, u8 val)
134{
135 u8 byte;
136
137 if (smbus_wait_until_ready(smbus_io_base) < 0) {
138 return -2; /* not ready */
139 }
140
141 /* set the command/address... */
142 outb(address & 0xff, smbus_io_base + SMBHSTCMD);
143
Jonathan Neuschäfer70903772017-09-23 21:39:02 +0200144 /* set the device I'm talking to */
zbao246e84b2012-07-13 18:47:03 +0800145 outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
146
147 /* output value */
148 outb(val, smbus_io_base + SMBHSTDAT0);
149
150 byte = inb(smbus_io_base + SMBHSTCTRL);
151 byte &= 0xe3; /* Clear [4:2] */
152 byte |= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */
153 outb(byte, smbus_io_base + SMBHSTCTRL);
154
155 /* poll for transaction completion */
156 if (smbus_wait_until_done(smbus_io_base) < 0) {
157 return -3; /* timeout or error */
158 }
159
160 return 0;
161}
162
163void alink_ab_indx(u32 reg_space, u32 reg_addr,
164 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); */
Elyes HAOUAS5bca34192019-12-30 15:13:41 +0100180 outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX); /* probably we don't have to do it again. */
zbao246e84b2012-07-13 18:47:03 +0800181 outl(tmp, AB_DATA);
182 outl(0, AB_INDX);
183}
184
185void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port,
186 u32 mask, u32 val)
187{
188 u32 tmp;
189
190 outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX);
191 tmp = inl(AB_DATA);
192 /* rpr 4.2
193 * For certain revisions of the chip, the ABCFG registers,
194 * with an address of 0x100NN (where 'N' is any hexadecimal
195 * number), require an extra programming step.*/
196 outl(0, AB_INDX);
197
198 tmp &= ~mask;
199 tmp |= val;
200
201 //printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<29 | (port&3) << 24 | reg_addr);
Elyes HAOUAS5bca34192019-12-30 15:13:41 +0100202 outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX); /* probably we don't have to do it again. */
zbao246e84b2012-07-13 18:47:03 +0800203 outl(tmp, AB_DATA);
204 outl(0, AB_INDX);
205}
206
207/* space = 0: AX_INDXC, AX_DATAC
208 * space = 1: AX_INDXP, AX_DATAP
209 */
Elyes HAOUASa342f392018-10-17 10:56:26 +0200210void alink_ax_indx(u32 space /*c or p? */, u32 axindc,
zbao246e84b2012-07-13 18:47:03 +0800211 u32 mask, u32 val)
212{
213 u32 tmp;
214
215 /* read axindc to tmp */
216 outl(space << 29 | space << 3 | 0x30, AB_INDX);
217 outl(axindc, AB_DATA);
218 outl(0, AB_INDX);
219 outl(space << 29 | space << 3 | 0x34, AB_INDX);
220 tmp = inl(AB_DATA);
221 outl(0, AB_INDX);
222
223 tmp &= ~mask;
224 tmp |= val;
225
226 /* write tmp */
227 outl(space << 29 | space << 3 | 0x30, AB_INDX);
228 outl(axindc, AB_DATA);
229 outl(0, AB_INDX);
230 outl(space << 29 | space << 3 | 0x34, AB_INDX);
231 outl(tmp, AB_DATA);
232 outl(0, AB_INDX);
233}
234#endif