1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2014 IBM
7 #include <linux/device.h>
9 #include <linux/kernel.h>
11 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/slab.h>
16 #include <asm/firmware.h>
19 static int i2c_opal_translate_error(int rc
)
26 case OPAL_I2C_ARBT_LOST
:
28 case OPAL_I2C_TIMEOUT
:
30 case OPAL_I2C_NACK_RCVD
:
32 case OPAL_I2C_STOP_ERR
:
39 static int i2c_opal_send_request(u32 bus_id
, struct opal_i2c_request
*req
)
44 token
= opal_async_get_token_interruptible();
46 if (token
!= -ERESTARTSYS
)
47 pr_err("Failed to get the async token\n");
52 rc
= opal_i2c_request(token
, bus_id
, req
);
53 if (rc
!= OPAL_ASYNC_COMPLETION
) {
54 rc
= i2c_opal_translate_error(rc
);
58 rc
= opal_async_wait_response(token
, &msg
);
62 rc
= opal_get_async_rc(msg
);
63 if (rc
!= OPAL_SUCCESS
) {
64 rc
= i2c_opal_translate_error(rc
);
69 opal_async_release_token(token
);
73 static int i2c_opal_xfer(struct i2c_adapter
*adap
, struct i2c_msg
*msgs
,
76 unsigned long opal_id
= (unsigned long)adap
->algo_data
;
77 struct opal_i2c_request req
;
80 /* We only support fairly simple combinations here of one
83 memset(&req
, 0, sizeof(req
));
86 req
.type
= (msgs
[0].flags
& I2C_M_RD
) ?
87 OPAL_I2C_RAW_READ
: OPAL_I2C_RAW_WRITE
;
88 req
.addr
= cpu_to_be16(msgs
[0].addr
);
89 req
.size
= cpu_to_be32(msgs
[0].len
);
90 req
.buffer_ra
= cpu_to_be64(__pa(msgs
[0].buf
));
93 req
.type
= (msgs
[1].flags
& I2C_M_RD
) ?
94 OPAL_I2C_SM_READ
: OPAL_I2C_SM_WRITE
;
95 req
.addr
= cpu_to_be16(msgs
[0].addr
);
96 req
.subaddr_sz
= msgs
[0].len
;
97 for (i
= 0; i
< msgs
[0].len
; i
++)
98 req
.subaddr
= (req
.subaddr
<< 8) | msgs
[0].buf
[i
];
99 req
.subaddr
= cpu_to_be32(req
.subaddr
);
100 req
.size
= cpu_to_be32(msgs
[1].len
);
101 req
.buffer_ra
= cpu_to_be64(__pa(msgs
[1].buf
));
105 rc
= i2c_opal_send_request(opal_id
, &req
);
112 static int i2c_opal_smbus_xfer(struct i2c_adapter
*adap
, u16 addr
,
113 unsigned short flags
, char read_write
,
114 u8 command
, int size
, union i2c_smbus_data
*data
)
116 unsigned long opal_id
= (unsigned long)adap
->algo_data
;
117 struct opal_i2c_request req
;
121 memset(&req
, 0, sizeof(req
));
123 req
.addr
= cpu_to_be16(addr
);
126 req
.buffer_ra
= cpu_to_be64(__pa(&data
->byte
));
127 req
.size
= cpu_to_be32(1);
129 case I2C_SMBUS_QUICK
:
130 req
.type
= (read_write
== I2C_SMBUS_READ
) ?
131 OPAL_I2C_RAW_READ
: OPAL_I2C_RAW_WRITE
;
133 case I2C_SMBUS_BYTE_DATA
:
134 req
.buffer_ra
= cpu_to_be64(__pa(&data
->byte
));
135 req
.size
= cpu_to_be32(1);
136 req
.subaddr
= cpu_to_be32(command
);
138 req
.type
= (read_write
== I2C_SMBUS_READ
) ?
139 OPAL_I2C_SM_READ
: OPAL_I2C_SM_WRITE
;
141 case I2C_SMBUS_WORD_DATA
:
143 local
[0] = data
->word
& 0xff;
144 local
[1] = (data
->word
>> 8) & 0xff;
146 req
.buffer_ra
= cpu_to_be64(__pa(local
));
147 req
.size
= cpu_to_be32(2);
148 req
.subaddr
= cpu_to_be32(command
);
150 req
.type
= (read_write
== I2C_SMBUS_READ
) ?
151 OPAL_I2C_SM_READ
: OPAL_I2C_SM_WRITE
;
153 case I2C_SMBUS_I2C_BLOCK_DATA
:
154 req
.buffer_ra
= cpu_to_be64(__pa(&data
->block
[1]));
155 req
.size
= cpu_to_be32(data
->block
[0]);
156 req
.subaddr
= cpu_to_be32(command
);
158 req
.type
= (read_write
== I2C_SMBUS_READ
) ?
159 OPAL_I2C_SM_READ
: OPAL_I2C_SM_WRITE
;
165 rc
= i2c_opal_send_request(opal_id
, &req
);
166 if (!rc
&& read_write
&& size
== I2C_SMBUS_WORD_DATA
) {
167 data
->word
= ((u16
)local
[1]) << 8;
168 data
->word
|= local
[0];
174 static u32
i2c_opal_func(struct i2c_adapter
*adapter
)
176 return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_QUICK
| I2C_FUNC_SMBUS_BYTE
|
177 I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_WORD_DATA
|
178 I2C_FUNC_SMBUS_I2C_BLOCK
;
181 static const struct i2c_algorithm i2c_opal_algo
= {
182 .xfer
= i2c_opal_xfer
,
183 .smbus_xfer
= i2c_opal_smbus_xfer
,
184 .functionality
= i2c_opal_func
,
188 * For two messages, we basically support simple smbus transactions of a
189 * write-then-anything.
191 static const struct i2c_adapter_quirks i2c_opal_quirks
= {
192 .flags
= I2C_AQ_COMB
| I2C_AQ_COMB_WRITE_FIRST
| I2C_AQ_COMB_SAME_ADDR
,
193 .max_comb_1st_msg_len
= 4,
196 static int i2c_opal_probe(struct platform_device
*pdev
)
198 struct i2c_adapter
*adapter
;
203 if (!pdev
->dev
.of_node
)
206 rc
= of_property_read_u32(pdev
->dev
.of_node
, "ibm,opal-id", &opal_id
);
208 dev_err(&pdev
->dev
, "Missing ibm,opal-id property !\n");
212 adapter
= devm_kzalloc(&pdev
->dev
, sizeof(*adapter
), GFP_KERNEL
);
216 adapter
->algo
= &i2c_opal_algo
;
217 adapter
->algo_data
= (void *)(unsigned long)opal_id
;
218 adapter
->quirks
= &i2c_opal_quirks
;
219 adapter
->dev
.parent
= &pdev
->dev
;
220 adapter
->dev
.of_node
= of_node_get(pdev
->dev
.of_node
);
221 pname
= of_get_property(pdev
->dev
.of_node
, "ibm,port-name", NULL
);
223 strscpy(adapter
->name
, pname
, sizeof(adapter
->name
));
225 strscpy(adapter
->name
, "opal", sizeof(adapter
->name
));
227 platform_set_drvdata(pdev
, adapter
);
228 rc
= i2c_add_adapter(adapter
);
230 dev_err(&pdev
->dev
, "Failed to register the i2c adapter\n");
235 static void i2c_opal_remove(struct platform_device
*pdev
)
237 struct i2c_adapter
*adapter
= platform_get_drvdata(pdev
);
239 i2c_del_adapter(adapter
);
242 static const struct of_device_id i2c_opal_of_match
[] = {
244 .compatible
= "ibm,opal-i2c",
248 MODULE_DEVICE_TABLE(of
, i2c_opal_of_match
);
250 static struct platform_driver i2c_opal_driver
= {
251 .probe
= i2c_opal_probe
,
252 .remove
= i2c_opal_remove
,
255 .of_match_table
= i2c_opal_of_match
,
259 static int __init
i2c_opal_init(void)
261 if (!firmware_has_feature(FW_FEATURE_OPAL
))
264 return platform_driver_register(&i2c_opal_driver
);
266 module_init(i2c_opal_init
);
268 static void __exit
i2c_opal_exit(void)
270 return platform_driver_unregister(&i2c_opal_driver
);
272 module_exit(i2c_opal_exit
);
274 MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>");
275 MODULE_DESCRIPTION("IBM OPAL I2C driver");
276 MODULE_LICENSE("GPL");