1 // SPDX-License-Identifier: GPL-2.0-only
3 * Intel La Jolla Cove Adapter USB-I2C driver
5 * Copyright (c) 2021, Intel Corporation.
9 #include <linux/mfd/ljca.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
23 enum i2c_address_mode
{
24 I2C_ADDRESS_MODE_7BIT
,
25 I2C_ADDRESS_MODE_10BIT
,
33 #define DEFAULT_I2C_CONTROLLER_ID 1
34 #define DEFAULT_I2C_CAPACITY 0
35 #define DEFAULT_I2C_INTR_PIN 0
38 #define I2C_SLAVE_TRANSFER_WRITE (0)
39 #define I2C_SLAVE_TRANSFER_READ (1)
42 #define I2C_INIT_FLAG_MODE_MASK (0x1 << 0)
43 #define I2C_INIT_FLAG_MODE_POLLING (0x0 << 0)
44 #define I2C_INIT_FLAG_MODE_INTERRUPT (0x1 << 0)
46 #define I2C_FLAG_ADDR_16BIT (0x1 << 0)
48 #define I2C_INIT_FLAG_FREQ_MASK (0x3 << 1)
49 #define I2C_FLAG_FREQ_100K (0x0 << 1)
50 #define I2C_FLAG_FREQ_400K (0x1 << 1)
51 #define I2C_FLAG_FREQ_1M (0x2 << 1)
57 u16 flag
; /* speed, 8/16bit addr, addr increase, etc */
63 /* I2C raw commands: Init/Start/Read/Write/Stop */
64 struct i2c_rw_packet
{
70 #define LJCA_I2C_MAX_XFER_SIZE 256
71 #define LJCA_I2C_BUF_SIZE \
72 (LJCA_I2C_MAX_XFER_SIZE + sizeof(struct i2c_rw_packet))
75 struct platform_device
*pdev
;
76 struct ljca_i2c_info
*ctr_info
;
77 struct i2c_adapter adap
;
79 u8 obuf
[LJCA_I2C_BUF_SIZE
];
80 u8 ibuf
[LJCA_I2C_BUF_SIZE
];
83 static u8
ljca_i2c_format_slave_addr(u8 slave_addr
, enum i2c_address_mode mode
)
85 if (mode
== I2C_ADDRESS_MODE_7BIT
)
86 return slave_addr
<< 1;
91 static int ljca_i2c_init(struct ljca_i2c_dev
*ljca_i2c
, u8 id
)
93 struct i2c_rw_packet
*w_packet
= (struct i2c_rw_packet
*)ljca_i2c
->obuf
;
95 memset(w_packet
, 0, sizeof(*w_packet
));
97 w_packet
->len
= cpu_to_le16(1);
98 w_packet
->data
[0] = I2C_FLAG_FREQ_400K
;
100 return ljca_transfer(ljca_i2c
->pdev
, I2C_INIT
, w_packet
,
101 sizeof(*w_packet
) + 1, NULL
, NULL
);
104 static int ljca_i2c_start(struct ljca_i2c_dev
*ljca_i2c
, u8 slave_addr
,
107 struct i2c_rw_packet
*w_packet
= (struct i2c_rw_packet
*)ljca_i2c
->obuf
;
108 struct i2c_rw_packet
*r_packet
= (struct i2c_rw_packet
*)ljca_i2c
->ibuf
;
112 memset(w_packet
, 0, sizeof(*w_packet
));
113 w_packet
->id
= ljca_i2c
->ctr_info
->id
;
114 w_packet
->len
= cpu_to_le16(1);
116 ljca_i2c_format_slave_addr(slave_addr
, I2C_ADDRESS_MODE_7BIT
);
117 w_packet
->data
[0] |= (type
== READ_XFER_TYPE
) ?
118 I2C_SLAVE_TRANSFER_READ
:
119 I2C_SLAVE_TRANSFER_WRITE
;
121 ret
= ljca_transfer(ljca_i2c
->pdev
, I2C_START
, w_packet
,
122 sizeof(*w_packet
) + 1, r_packet
, &ibuf_len
);
124 if (ret
|| ibuf_len
< sizeof(*r_packet
))
127 if ((s16
)le16_to_cpu(r_packet
->len
) < 0 ||
128 r_packet
->id
!= w_packet
->id
) {
129 dev_err(&ljca_i2c
->adap
.dev
,
130 "i2c start failed len:%d id:%d %d\n",
131 (s16
)le16_to_cpu(r_packet
->len
), r_packet
->id
,
139 static int ljca_i2c_stop(struct ljca_i2c_dev
*ljca_i2c
, u8 slave_addr
)
141 struct i2c_rw_packet
*w_packet
= (struct i2c_rw_packet
*)ljca_i2c
->obuf
;
142 struct i2c_rw_packet
*r_packet
= (struct i2c_rw_packet
*)ljca_i2c
->ibuf
;
146 memset(w_packet
, 0, sizeof(*w_packet
));
147 w_packet
->id
= ljca_i2c
->ctr_info
->id
;
148 w_packet
->len
= cpu_to_le16(1);
149 w_packet
->data
[0] = 0;
151 ret
= ljca_transfer(ljca_i2c
->pdev
, I2C_STOP
, w_packet
,
152 sizeof(*w_packet
) + 1, r_packet
, &ibuf_len
);
154 if (ret
|| ibuf_len
< sizeof(*r_packet
))
157 if ((s16
)le16_to_cpu(r_packet
->len
) < 0 ||
158 r_packet
->id
!= w_packet
->id
) {
159 dev_err(&ljca_i2c
->adap
.dev
,
160 "i2c stop failed len:%d id:%d %d\n",
161 (s16
)le16_to_cpu(r_packet
->len
), r_packet
->id
,
169 static int ljca_i2c_pure_read(struct ljca_i2c_dev
*ljca_i2c
, u8
*data
, int len
)
171 struct i2c_rw_packet
*w_packet
= (struct i2c_rw_packet
*)ljca_i2c
->obuf
;
172 struct i2c_rw_packet
*r_packet
= (struct i2c_rw_packet
*)ljca_i2c
->ibuf
;
176 if (len
> LJCA_I2C_MAX_XFER_SIZE
)
179 memset(w_packet
, 0, sizeof(*w_packet
));
180 w_packet
->id
= ljca_i2c
->ctr_info
->id
;
181 w_packet
->len
= cpu_to_le16(len
);
182 ret
= ljca_transfer(ljca_i2c
->pdev
, I2C_READ
, w_packet
,
183 sizeof(*w_packet
) + 1, r_packet
, &ibuf_len
);
185 dev_err(&ljca_i2c
->adap
.dev
, "I2C_READ failed ret:%d\n", ret
);
189 if (ibuf_len
< sizeof(*r_packet
))
192 if ((s16
)le16_to_cpu(r_packet
->len
) != len
||
193 r_packet
->id
!= w_packet
->id
) {
194 dev_err(&ljca_i2c
->adap
.dev
,
195 "i2c raw read failed len:%d id:%d %d\n",
196 (s16
)le16_to_cpu(r_packet
->len
), r_packet
->id
,
201 memcpy(data
, r_packet
->data
, len
);
206 static int ljca_i2c_read(struct ljca_i2c_dev
*ljca_i2c
, u8 slave_addr
, u8
*data
,
211 ret
= ljca_i2c_start(ljca_i2c
, slave_addr
, READ_XFER_TYPE
);
215 ret
= ljca_i2c_pure_read(ljca_i2c
, data
, len
);
217 dev_err(&ljca_i2c
->adap
.dev
, "i2c raw read failed ret:%d\n",
223 return ljca_i2c_stop(ljca_i2c
, slave_addr
);
226 static int ljca_i2c_pure_write(struct ljca_i2c_dev
*ljca_i2c
, u8
*data
, u8 len
)
228 struct i2c_rw_packet
*w_packet
= (struct i2c_rw_packet
*)ljca_i2c
->obuf
;
229 struct i2c_rw_packet
*r_packet
= (struct i2c_rw_packet
*)ljca_i2c
->ibuf
;
233 if (len
> LJCA_I2C_MAX_XFER_SIZE
)
236 memset(w_packet
, 0, sizeof(*w_packet
));
237 w_packet
->id
= ljca_i2c
->ctr_info
->id
;
238 w_packet
->len
= cpu_to_le16(len
);
239 memcpy(w_packet
->data
, data
, len
);
241 ret
= ljca_transfer(ljca_i2c
->pdev
, I2C_WRITE
, w_packet
,
242 sizeof(*w_packet
) + w_packet
->len
, r_packet
,
245 if (ret
|| ibuf_len
< sizeof(*r_packet
))
248 if ((s16
)le16_to_cpu(r_packet
->len
) != len
||
249 r_packet
->id
!= w_packet
->id
) {
250 dev_err(&ljca_i2c
->adap
.dev
,
251 "i2c write failed len:%d id:%d/%d\n",
252 (s16
)le16_to_cpu(r_packet
->len
), r_packet
->id
,
260 static int ljca_i2c_write(struct ljca_i2c_dev
*ljca_i2c
, u8 slave_addr
,
268 ret
= ljca_i2c_start(ljca_i2c
, slave_addr
, WRITE_XFER_TYPE
);
272 ret
= ljca_i2c_pure_write(ljca_i2c
, data
, len
);
276 return ljca_i2c_stop(ljca_i2c
, slave_addr
);
279 static int ljca_i2c_xfer(struct i2c_adapter
*adapter
, struct i2c_msg
*msg
,
282 struct ljca_i2c_dev
*ljca_i2c
;
283 struct i2c_msg
*cur_msg
;
286 ljca_i2c
= i2c_get_adapdata(adapter
);
290 for (i
= 0; !ret
&& i
< num
; i
++) {
292 dev_dbg(&adapter
->dev
, "i:%d msg:(%d %d)\n", i
, cur_msg
->flags
,
294 if (cur_msg
->flags
& I2C_M_RD
)
295 ret
= ljca_i2c_read(ljca_i2c
, cur_msg
->addr
,
296 cur_msg
->buf
, cur_msg
->len
);
299 ret
= ljca_i2c_write(ljca_i2c
, cur_msg
->addr
,
300 cur_msg
->buf
, cur_msg
->len
);
309 static u32
ljca_i2c_func(struct i2c_adapter
*adap
)
311 return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_EMUL
;
314 static const struct i2c_adapter_quirks ljca_i2c_quirks
= {
315 .max_read_len
= LJCA_I2C_MAX_XFER_SIZE
,
316 .max_write_len
= LJCA_I2C_MAX_XFER_SIZE
,
319 static const struct i2c_algorithm ljca_i2c_algo
= {
320 .master_xfer
= ljca_i2c_xfer
,
321 .functionality
= ljca_i2c_func
,
324 static int ljca_i2c_probe(struct platform_device
*pdev
)
326 struct ljca_i2c_dev
*ljca_i2c
;
327 struct ljca_platform_data
*pdata
= dev_get_platdata(&pdev
->dev
);
330 ljca_i2c
= devm_kzalloc(&pdev
->dev
, sizeof(*ljca_i2c
), GFP_KERNEL
);
334 ljca_i2c
->pdev
= pdev
;
335 ljca_i2c
->ctr_info
= &pdata
->i2c_info
;
337 ljca_i2c
->adap
.owner
= THIS_MODULE
;
338 ljca_i2c
->adap
.class = I2C_CLASS_HWMON
;
339 ljca_i2c
->adap
.algo
= &ljca_i2c_algo
;
340 ljca_i2c
->adap
.dev
.parent
= &pdev
->dev
;
341 ACPI_COMPANION_SET(&ljca_i2c
->adap
.dev
, ACPI_COMPANION(&pdev
->dev
));
342 ljca_i2c
->adap
.dev
.of_node
= pdev
->dev
.of_node
;
343 i2c_set_adapdata(&ljca_i2c
->adap
, ljca_i2c
);
344 snprintf(ljca_i2c
->adap
.name
, sizeof(ljca_i2c
->adap
.name
), "%s-%s-%d",
345 "ljca-i2c", dev_name(pdev
->dev
.parent
),
346 ljca_i2c
->ctr_info
->id
);
348 platform_set_drvdata(pdev
, ljca_i2c
);
350 ret
= ljca_i2c_init(ljca_i2c
, ljca_i2c
->ctr_info
->id
);
352 dev_err(&pdev
->dev
, "i2c init failed id:%d\n",
353 ljca_i2c
->ctr_info
->id
);
357 return i2c_add_adapter(&ljca_i2c
->adap
);
360 static int ljca_i2c_remove(struct platform_device
*pdev
)
362 struct ljca_i2c_dev
*ljca_i2c
= platform_get_drvdata(pdev
);
364 i2c_del_adapter(&ljca_i2c
->adap
);
369 static struct platform_driver ljca_i2c_driver
= {
370 .driver
.name
= "ljca-i2c",
371 .probe
= ljca_i2c_probe
,
372 .remove
= ljca_i2c_remove
,
375 module_platform_driver(ljca_i2c_driver
);
377 MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>");
378 MODULE_AUTHOR("Zhang Lixu <lixu.zhang@intel.com>");
379 MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB-I2C driver");
380 MODULE_LICENSE("GPL v2");
381 MODULE_ALIAS("platform:ljca-i2c");