blob: 50c77cf0b00e9dd75d9b0d74f3c3faa4fadb6ca2 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Frank Vibrans63e62b02011-02-14 18:38:14 +00002
Frank Vibrans63e62b02011-02-14 18:38:14 +00003#include <arch/io.h>
Elyes Haouas2a6cc952022-02-11 22:32:44 +01004#include <stdint.h>
Frank Vibrans63e62b02011-02-14 18:38:14 +00005#include "smbus.h"
Elyes Haouas2a6cc952022-02-11 22:32:44 +01006#include <console/console.h>
Frank Vibrans63e62b02011-02-14 18:38:14 +00007
Frank Vibrans63e62b02011-02-14 18:38:14 +00008static 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
26static 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
48int 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) {
Elyes Haouas2a6cc952022-02-11 22:32:44 +010053 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - smbus not ready.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +000054 return -2; /* not ready */
55 }
56
Elyes Haouas2a6cc952022-02-11 22:32:44 +010057 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
Jonathan Neuschäfer70903772017-09-23 21:39:02 +020058 /* set the device I'm talking to */
Frank Vibrans63e62b02011-02-14 18:38:14 +000059 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
Elyes Haouas2a6cc952022-02-11 22:32:44 +010074 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +000075 return byte;
76}
77
78int 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) {
Elyes Haouas2a6cc952022-02-11 22:32:44 +010083 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - smbus not ready.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +000084 return -2; /* not ready */
85 }
86
Elyes Haouas2a6cc952022-02-11 22:32:44 +010087 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +000088 /* set the command... */
89 outb(val, smbus_io_base + SMBHSTCMD);
90
Jonathan Neuschäfer70903772017-09-23 21:39:02 +020091 /* set the device I'm talking to */
Frank Vibrans63e62b02011-02-14 18:38:14 +000092 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
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100104 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000105 return 0;
106}
107
108int do_smbus_read_byte(u32 smbus_io_base, u32 device, u32 address)
109{
110 u8 byte;
111
112 if (smbus_wait_until_ready(smbus_io_base) < 0) {
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100113 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - smbus not ready.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000114 return -2; /* not ready */
115 }
116
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100117 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000118 /* set the command/address... */
119 outb(address & 0xff, smbus_io_base + SMBHSTCMD);
120
Jonathan Neuschäfer70903772017-09-23 21:39:02 +0200121 /* set the device I'm talking to */
Frank Vibrans63e62b02011-02-14 18:38:14 +0000122 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
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100137 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000138 return byte;
139}
140
141int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address, u8 val)
142{
143 u8 byte;
144
145 if (smbus_wait_until_ready(smbus_io_base) < 0) {
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100146 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - smbus not ready.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000147 return -2; /* not ready */
148 }
149
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100150 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000151 /* set the command/address... */
152 outb(address & 0xff, smbus_io_base + SMBHSTCMD);
153
Jonathan Neuschäfer70903772017-09-23 21:39:02 +0200154 /* set the device I'm talking to */
Frank Vibrans63e62b02011-02-14 18:38:14 +0000155 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
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100170 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000171 return 0;
172}
173
174void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val)
175{
176 u32 tmp;
177
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100178 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000179 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); */
Martin Roth3c3a50c2014-12-16 20:50:26 -0700191 outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX); /* probably we don't have to do it again. */
Frank Vibrans63e62b02011-02-14 18:38:14 +0000192 outl(tmp, AB_DATA);
193 outl(0, AB_INDX);
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100194 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000195}
196
197void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val)
198{
199 u32 tmp;
200
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100201 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000202 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);
Martin Roth3c3a50c2014-12-16 20:50:26 -0700214 outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX); /* probably we don't have to do it again. */
Frank Vibrans63e62b02011-02-14 18:38:14 +0000215 outl(tmp, AB_DATA);
216 outl(0, AB_INDX);
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100217 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000218}
219
220/* space = 0: AX_INDXC, AX_DATAC
221 * space = 1: AX_INDXP, AX_DATAP
222 */
Elyes HAOUASa342f392018-10-17 10:56:26 +0200223void alink_ax_indx(u32 space /*c or p? */, u32 axindc, u32 mask, u32 val)
Frank Vibrans63e62b02011-02-14 18:38:14 +0000224{
225 u32 tmp;
226
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100227 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - Start.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000228 /* 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);
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100246 printk(BIOS_DEBUG, "SB800 - smbus.c - %s - End.\n", __func__);
Frank Vibrans63e62b02011-02-14 18:38:14 +0000247}