blob: 43f8ca75d3223b72361587a113c91030ca9ccef8 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
zbao246e84b2012-07-13 18:47:03 +08002
Elyes HAOUAS65fa5982014-07-22 23:12:38 +02003#ifndef _HUDSON_SMBUS_C_
4#define _HUDSON_SMBUS_C_
zbao246e84b2012-07-13 18:47:03 +08005
Kyösti Mälkkie132d572019-03-02 19:06:17 +02006#include <arch/io.h>
Paul Menzel883b03f2013-05-06 15:18:57 +02007#include <stdint.h>
zbao246e84b2012-07-13 18:47:03 +08008#include "smbus.h"
9
zbao246e84b2012-07-13 18:47:03 +080010static int smbus_wait_until_ready(u32 smbus_io_base)
11{
12 u32 loops;
Elyes Haouas2a6cc952022-02-11 22:32:44 +010013
zbao246e84b2012-07-13 18:47:03 +080014 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);
Elyes Haouas2a6cc952022-02-11 22:32:44 +010024
zbao246e84b2012-07-13 18:47:03 +080025 return -2; /* time out */
26}
27
28static int smbus_wait_until_done(u32 smbus_io_base)
29{
30 u32 loops;
Elyes Haouas2a6cc952022-02-11 22:32:44 +010031
zbao246e84b2012-07-13 18:47:03 +080032 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);
Elyes Haouas2a6cc952022-02-11 22:32:44 +010046
zbao246e84b2012-07-13 18:47:03 +080047 return -3; /* timeout */
48}
49
50int 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
Jonathan Neuschäfer70903772017-09-23 21:39:02 +020058 /* set the device I'm talking to */
zbao246e84b2012-07-13 18:47:03 +080059 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
77int 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
Jonathan Neuschäfer70903772017-09-23 21:39:02 +020088 /* set the device I'm talking to */
zbao246e84b2012-07-13 18:47:03 +080089 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
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100104int do_smbus_read_byte(u32 smbus_io_base, u32 device, u32 address)
zbao246e84b2012-07-13 18:47:03 +0800105{
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
Jonathan Neuschäfer70903772017-09-23 21:39:02 +0200115 /* set the device I'm talking to */
zbao246e84b2012-07-13 18:47:03 +0800116 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
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100134int do_smbus_write_byte(u32 smbus_io_base, u32 device, u32 address, u8 val)
zbao246e84b2012-07-13 18:47:03 +0800135{
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
Jonathan Neuschäfer70903772017-09-23 21:39:02 +0200145 /* set the device I'm talking to */
zbao246e84b2012-07-13 18:47:03 +0800146 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
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100164void alink_ab_indx(u32 reg_space, u32 reg_addr, u32 mask, u32 val)
zbao246e84b2012-07-13 18:47:03 +0800165{
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
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100185void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port, u32 mask, u32 val)
zbao246e84b2012-07-13 18:47:03 +0800186{
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);
Elyes HAOUAS5bca34192019-12-30 15:13:41 +0100201 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 +0800202 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 */
Elyes Haouas2a6cc952022-02-11 22:32:44 +0100209void alink_ax_indx(u32 space /*c or p? */, u32 axindc, u32 mask, u32 val)
zbao246e84b2012-07-13 18:47:03 +0800210{
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