1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2006-2007 PA Semi, Inc
4 *
5 * SMBus host driver for PA Semi PWRficient
6 */
7
8 #include <linux/bitfield.h>
9 #include <linux/module.h>
10 #include <linux/pci.h>
11 #include <linux/kernel.h>
12 #include <linux/stddef.h>
13 #include <linux/sched.h>
14 #include <linux/i2c.h>
15 #include <linux/delay.h>
16 #include <linux/slab.h>
17 #include <linux/io.h>
18
19 #include "i2c-pasemi-core.h"
20
21 /* Register offsets */
22 #define REG_MTXFIFO 0x00
23 #define REG_MRXFIFO 0x04
24 #define REG_SMSTA 0x14
25 #define REG_IMASK 0x18
26 #define REG_CTL 0x1c
27 #define REG_REV 0x28
28
29 /* Register defs */
30 #define MTXFIFO_READ BIT(10)
31 #define MTXFIFO_STOP BIT(9)
32 #define MTXFIFO_START BIT(8)
33 #define MTXFIFO_DATA_M GENMASK(7, 0)
34
35 #define MRXFIFO_EMPTY BIT(8)
36 #define MRXFIFO_DATA_M GENMASK(7, 0)
37
38 #define SMSTA_XIP BIT(28)
39 #define SMSTA_XEN BIT(27)
40 #define SMSTA_JMD BIT(25)
41 #define SMSTA_JAM BIT(24)
42 #define SMSTA_MTO BIT(23)
43 #define SMSTA_MTA BIT(22)
44 #define SMSTA_MTN BIT(21)
45 #define SMSTA_MRNE BIT(19)
46 #define SMSTA_MTE BIT(16)
47 #define SMSTA_TOM BIT(6)
48
49 #define CTL_EN BIT(11)
50 #define CTL_MRR BIT(10)
51 #define CTL_MTR BIT(9)
52 #define CTL_UJM BIT(8)
53 #define CTL_CLK_M GENMASK(7, 0)
54
reg_write(struct pasemi_smbus * smbus,int reg,int val)55 static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
56 {
57 dev_dbg(smbus->dev, "smbus write reg %x val %08x\n", reg, val);
58 iowrite32(val, smbus->ioaddr + reg);
59 }
60
reg_read(struct pasemi_smbus * smbus,int reg)61 static inline int reg_read(struct pasemi_smbus *smbus, int reg)
62 {
63 int ret;
64 ret = ioread32(smbus->ioaddr + reg);
65 dev_dbg(smbus->dev, "smbus read reg %x val %08x\n", reg, ret);
66 return ret;
67 }
68
69 #define TXFIFO_WR(smbus, reg) reg_write((smbus), REG_MTXFIFO, (reg))
70 #define RXFIFO_RD(smbus) reg_read((smbus), REG_MRXFIFO)
71
pasemi_reset(struct pasemi_smbus * smbus)72 static void pasemi_reset(struct pasemi_smbus *smbus)
73 {
74 u32 val = (CTL_MTR | CTL_MRR | (smbus->clk_div & CTL_CLK_M));
75
76 if (smbus->hw_rev >= 6)
77 val |= CTL_EN;
78
79 reg_write(smbus, REG_CTL, val);
80 reinit_completion(&smbus->irq_completion);
81 }
82
pasemi_smb_clear(struct pasemi_smbus * smbus)83 static void pasemi_smb_clear(struct pasemi_smbus *smbus)
84 {
85 unsigned int status;
86
87 status = reg_read(smbus, REG_SMSTA);
88 reg_write(smbus, REG_SMSTA, status);
89 }
90
pasemi_smb_waitready(struct pasemi_smbus * smbus)91 static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
92 {
93 int timeout = 100;
94 unsigned int status;
95
96 if (smbus->use_irq) {
97 reinit_completion(&smbus->irq_completion);
98 reg_write(smbus, REG_IMASK, SMSTA_XEN | SMSTA_MTN);
99 wait_for_completion_timeout(&smbus->irq_completion, msecs_to_jiffies(100));
100 reg_write(smbus, REG_IMASK, 0);
101 status = reg_read(smbus, REG_SMSTA);
102 } else {
103 status = reg_read(smbus, REG_SMSTA);
104 while (!(status & SMSTA_XEN) && timeout--) {
105 msleep(1);
106 status = reg_read(smbus, REG_SMSTA);
107 }
108 }
109
110 /* Got NACK? */
111 if (status & SMSTA_MTN)
112 return -ENXIO;
113
114 if (timeout < 0) {
115 dev_warn(smbus->dev, "Timeout, status 0x%08x\n", status);
116 reg_write(smbus, REG_SMSTA, status);
117 return -ETIME;
118 }
119
120 /* Clear XEN */
121 reg_write(smbus, REG_SMSTA, SMSTA_XEN);
122
123 return 0;
124 }
125
pasemi_i2c_xfer_msg(struct i2c_adapter * adapter,struct i2c_msg * msg,int stop)126 static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter,
127 struct i2c_msg *msg, int stop)
128 {
129 struct pasemi_smbus *smbus = adapter->algo_data;
130 int read, i, err;
131 u32 rd;
132
133 read = msg->flags & I2C_M_RD ? 1 : 0;
134
135 TXFIFO_WR(smbus, MTXFIFO_START | i2c_8bit_addr_from_msg(msg));
136
137 if (read) {
138 TXFIFO_WR(smbus, msg->len | MTXFIFO_READ |
139 (stop ? MTXFIFO_STOP : 0));
140
141 err = pasemi_smb_waitready(smbus);
142 if (err)
143 goto reset_out;
144
145 for (i = 0; i < msg->len; i++) {
146 rd = RXFIFO_RD(smbus);
147 if (rd & MRXFIFO_EMPTY) {
148 err = -ENODATA;
149 goto reset_out;
150 }
151 msg->buf[i] = rd & MRXFIFO_DATA_M;
152 }
153 } else {
154 for (i = 0; i < msg->len - 1; i++)
155 TXFIFO_WR(smbus, msg->buf[i]);
156
157 TXFIFO_WR(smbus, msg->buf[msg->len-1] |
158 (stop ? MTXFIFO_STOP : 0));
159
160 if (stop) {
161 err = pasemi_smb_waitready(smbus);
162 if (err)
163 goto reset_out;
164 }
165 }
166
167 return 0;
168
169 reset_out:
170 pasemi_reset(smbus);
171 return err;
172 }
173
pasemi_i2c_xfer(struct i2c_adapter * adapter,struct i2c_msg * msgs,int num)174 static int pasemi_i2c_xfer(struct i2c_adapter *adapter,
175 struct i2c_msg *msgs, int num)
176 {
177 struct pasemi_smbus *smbus = adapter->algo_data;
178 int ret, i;
179
180 pasemi_smb_clear(smbus);
181
182 ret = 0;
183
184 for (i = 0; i < num && !ret; i++)
185 ret = pasemi_i2c_xfer_msg(adapter, &msgs[i], (i == (num - 1)));
186
187 return ret ? ret : num;
188 }
189
pasemi_smb_xfer(struct i2c_adapter * adapter,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data * data)190 static int pasemi_smb_xfer(struct i2c_adapter *adapter,
191 u16 addr, unsigned short flags, char read_write, u8 command,
192 int size, union i2c_smbus_data *data)
193 {
194 struct pasemi_smbus *smbus = adapter->algo_data;
195 unsigned int rd;
196 int read_flag, err;
197 int len = 0, i;
198
199 /* All our ops take 8-bit shifted addresses */
200 addr <<= 1;
201 read_flag = read_write == I2C_SMBUS_READ;
202
203 pasemi_smb_clear(smbus);
204
205 switch (size) {
206 case I2C_SMBUS_QUICK:
207 TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START |
208 MTXFIFO_STOP);
209 break;
210 case I2C_SMBUS_BYTE:
211 TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START);
212 if (read_write)
213 TXFIFO_WR(smbus, 1 | MTXFIFO_STOP | MTXFIFO_READ);
214 else
215 TXFIFO_WR(smbus, MTXFIFO_STOP | command);
216 break;
217 case I2C_SMBUS_BYTE_DATA:
218 TXFIFO_WR(smbus, addr | MTXFIFO_START);
219 TXFIFO_WR(smbus, command);
220 if (read_write) {
221 TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
222 TXFIFO_WR(smbus, 1 | MTXFIFO_READ | MTXFIFO_STOP);
223 } else {
224 TXFIFO_WR(smbus, MTXFIFO_STOP | data->byte);
225 }
226 break;
227 case I2C_SMBUS_WORD_DATA:
228 TXFIFO_WR(smbus, addr | MTXFIFO_START);
229 TXFIFO_WR(smbus, command);
230 if (read_write) {
231 TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
232 TXFIFO_WR(smbus, 2 | MTXFIFO_READ | MTXFIFO_STOP);
233 } else {
234 TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M);
235 TXFIFO_WR(smbus, MTXFIFO_STOP | (data->word >> 8));
236 }
237 break;
238 case I2C_SMBUS_BLOCK_DATA:
239 TXFIFO_WR(smbus, addr | MTXFIFO_START);
240 TXFIFO_WR(smbus, command);
241 if (read_write) {
242 TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
243 TXFIFO_WR(smbus, 1 | MTXFIFO_READ);
244 rd = RXFIFO_RD(smbus);
245 len = min_t(u8, (rd & MRXFIFO_DATA_M),
246 I2C_SMBUS_BLOCK_MAX);
247 TXFIFO_WR(smbus, len | MTXFIFO_READ |
248 MTXFIFO_STOP);
249 } else {
250 len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX);
251 TXFIFO_WR(smbus, len);
252 for (i = 1; i < len; i++)
253 TXFIFO_WR(smbus, data->block[i]);
254 TXFIFO_WR(smbus, data->block[len] | MTXFIFO_STOP);
255 }
256 break;
257 case I2C_SMBUS_PROC_CALL:
258 read_write = I2C_SMBUS_READ;
259 TXFIFO_WR(smbus, addr | MTXFIFO_START);
260 TXFIFO_WR(smbus, command);
261 TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M);
262 TXFIFO_WR(smbus, (data->word >> 8) & MTXFIFO_DATA_M);
263 TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
264 TXFIFO_WR(smbus, 2 | MTXFIFO_STOP | MTXFIFO_READ);
265 break;
266 case I2C_SMBUS_BLOCK_PROC_CALL:
267 len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX - 1);
268 read_write = I2C_SMBUS_READ;
269 TXFIFO_WR(smbus, addr | MTXFIFO_START);
270 TXFIFO_WR(smbus, command);
271 TXFIFO_WR(smbus, len);
272 for (i = 1; i <= len; i++)
273 TXFIFO_WR(smbus, data->block[i]);
274 TXFIFO_WR(smbus, addr | I2C_SMBUS_READ);
275 TXFIFO_WR(smbus, MTXFIFO_READ | 1);
276 rd = RXFIFO_RD(smbus);
277 len = min_t(u8, (rd & MRXFIFO_DATA_M),
278 I2C_SMBUS_BLOCK_MAX - len);
279 TXFIFO_WR(smbus, len | MTXFIFO_READ | MTXFIFO_STOP);
280 break;
281
282 default:
283 dev_warn(&adapter->dev, "Unsupported transaction %d\n", size);
284 return -EINVAL;
285 }
286
287 err = pasemi_smb_waitready(smbus);
288 if (err)
289 goto reset_out;
290
291 if (read_write == I2C_SMBUS_WRITE)
292 return 0;
293
294 switch (size) {
295 case I2C_SMBUS_BYTE:
296 case I2C_SMBUS_BYTE_DATA:
297 rd = RXFIFO_RD(smbus);
298 if (rd & MRXFIFO_EMPTY) {
299 err = -ENODATA;
300 goto reset_out;
301 }
302 data->byte = rd & MRXFIFO_DATA_M;
303 break;
304 case I2C_SMBUS_WORD_DATA:
305 case I2C_SMBUS_PROC_CALL:
306 rd = RXFIFO_RD(smbus);
307 if (rd & MRXFIFO_EMPTY) {
308 err = -ENODATA;
309 goto reset_out;
310 }
311 data->word = rd & MRXFIFO_DATA_M;
312 rd = RXFIFO_RD(smbus);
313 if (rd & MRXFIFO_EMPTY) {
314 err = -ENODATA;
315 goto reset_out;
316 }
317 data->word |= (rd & MRXFIFO_DATA_M) << 8;
318 break;
319 case I2C_SMBUS_BLOCK_DATA:
320 case I2C_SMBUS_BLOCK_PROC_CALL:
321 data->block[0] = len;
322 for (i = 1; i <= len; i ++) {
323 rd = RXFIFO_RD(smbus);
324 if (rd & MRXFIFO_EMPTY) {
325 err = -ENODATA;
326 goto reset_out;
327 }
328 data->block[i] = rd & MRXFIFO_DATA_M;
329 }
330 break;
331 }
332
333 return 0;
334
335 reset_out:
336 pasemi_reset(smbus);
337 return err;
338 }
339
pasemi_smb_func(struct i2c_adapter * adapter)340 static u32 pasemi_smb_func(struct i2c_adapter *adapter)
341 {
342 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
343 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
344 I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL |
345 I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_I2C;
346 }
347
348 static const struct i2c_algorithm smbus_algorithm = {
349 .xfer = pasemi_i2c_xfer,
350 .smbus_xfer = pasemi_smb_xfer,
351 .functionality = pasemi_smb_func,
352 };
353
pasemi_i2c_common_probe(struct pasemi_smbus * smbus)354 int pasemi_i2c_common_probe(struct pasemi_smbus *smbus)
355 {
356 int error;
357
358 smbus->adapter.owner = THIS_MODULE;
359 snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
360 "PA Semi SMBus adapter (%s)", dev_name(smbus->dev));
361 smbus->adapter.algo = &smbus_algorithm;
362 smbus->adapter.algo_data = smbus;
363
364 /* set up the sysfs linkage to our parent device */
365 smbus->adapter.dev.parent = smbus->dev;
366 smbus->use_irq = 0;
367 init_completion(&smbus->irq_completion);
368
369 if (smbus->hw_rev != PASEMI_HW_REV_PCI)
370 smbus->hw_rev = reg_read(smbus, REG_REV);
371
372 reg_write(smbus, REG_IMASK, 0);
373
374 pasemi_reset(smbus);
375
376 error = devm_i2c_add_adapter(smbus->dev, &smbus->adapter);
377 if (error)
378 return error;
379
380 return 0;
381 }
382 EXPORT_SYMBOL_GPL(pasemi_i2c_common_probe);
383
pasemi_irq_handler(int irq,void * dev_id)384 irqreturn_t pasemi_irq_handler(int irq, void *dev_id)
385 {
386 struct pasemi_smbus *smbus = dev_id;
387
388 reg_write(smbus, REG_IMASK, 0);
389 complete(&smbus->irq_completion);
390 return IRQ_HANDLED;
391 }
392 EXPORT_SYMBOL_GPL(pasemi_irq_handler);
393
394 MODULE_LICENSE("GPL");
395 MODULE_AUTHOR("Olof Johansson <olof@lixom.net>");
396 MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver");
397