1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 #include <linux/delay.h>
4 #include <linux/i2c.h>
5 #include <linux/module.h>
6 #include <linux/of.h>
7 #include <linux/pse-pd/pse.h>
8
9 #include "realtek-pse-mcu.h"
10
11 /*
12 * The core has already waited RTPSE_MCU_RESPONSE_MS before calling us, so
13 * the response is normally ready on the very first read. For commands the
14 * MCU produces more slowly, keep polling at the typical response cadence
15 * up to the worst-case ceiling.
16 */
17 #define RTPSE_MCU_I2C_RETRY_MS RTPSE_MCU_RESPONSE_MS
18 #define RTPSE_MCU_I2C_MAX_TRIES (RTPSE_MCU_RESPONSE_MAX_MS / RTPSE_MCU_I2C_RETRY_MS)
19
rtpse_mcu_i2c_smbus_send(struct rtpse_mcu_ctrl * pse,const struct rtpse_mcu_msg * req)20 static int rtpse_mcu_i2c_smbus_send(struct rtpse_mcu_ctrl *pse, const struct rtpse_mcu_msg *req)
21 {
22 struct i2c_client *client = to_i2c_client(pse->dev);
23
24 /* Send opcode as SMBus command byte; remaining 11 bytes as block data */
25 return i2c_smbus_write_i2c_block_data(client, req->opcode, RTPSE_MCU_MSG_SIZE - 1,
26 (const u8 *)req + 1);
27 }
28
rtpse_mcu_i2c_smbus_recv(struct rtpse_mcu_ctrl * pse,const struct rtpse_mcu_msg * req,struct rtpse_mcu_msg * resp)29 static int rtpse_mcu_i2c_smbus_recv(struct rtpse_mcu_ctrl *pse, const struct rtpse_mcu_msg *req,
30 struct rtpse_mcu_msg *resp)
31 {
32 struct i2c_client *client = to_i2c_client(pse->dev);
33 int tries, ret;
34
35 for (tries = 0; tries < RTPSE_MCU_I2C_MAX_TRIES; tries++) {
36 if (tries > 0)
37 msleep(RTPSE_MCU_I2C_RETRY_MS);
38
39 /* MCU needs 0x00 as command byte for read */
40 ret = i2c_smbus_read_i2c_block_data(client, 0x00,
41 RTPSE_MCU_MSG_SIZE,
42 (u8 *)resp);
43 if (ret < 0)
44 return ret;
45 if (ret == RTPSE_MCU_MSG_SIZE && rtpse_mcu_resp_is_final(req, resp))
46 return 0;
47 }
48
49 return -ETIMEDOUT;
50 }
51
52 static const struct rtpse_mcu_transport_ops rtpse_mcu_i2c_smbus_ops = {
53 .send = rtpse_mcu_i2c_smbus_send,
54 .recv = rtpse_mcu_i2c_smbus_recv,
55 };
56
rtpse_mcu_i2c_native_send(struct rtpse_mcu_ctrl * pse,const struct rtpse_mcu_msg * req)57 static int rtpse_mcu_i2c_native_send(struct rtpse_mcu_ctrl *pse, const struct rtpse_mcu_msg *req)
58 {
59 struct i2c_client *client = to_i2c_client(pse->dev);
60 int ret;
61
62 ret = i2c_master_send(client, (const u8 *)req, RTPSE_MCU_MSG_SIZE);
63 if (ret < 0)
64 return ret;
65 return ret == RTPSE_MCU_MSG_SIZE ? 0 : -EIO;
66 }
67
rtpse_mcu_i2c_native_recv(struct rtpse_mcu_ctrl * pse,const struct rtpse_mcu_msg * req,struct rtpse_mcu_msg * resp)68 static int rtpse_mcu_i2c_native_recv(struct rtpse_mcu_ctrl *pse, const struct rtpse_mcu_msg *req,
69 struct rtpse_mcu_msg *resp)
70 {
71 struct i2c_client *client = to_i2c_client(pse->dev);
72 int tries, ret;
73
74 for (tries = 0; tries < RTPSE_MCU_I2C_MAX_TRIES; tries++) {
75 if (tries > 0)
76 msleep(RTPSE_MCU_I2C_RETRY_MS);
77
78 ret = i2c_master_recv(client, (u8 *)resp, RTPSE_MCU_MSG_SIZE);
79 if (ret < 0)
80 return ret;
81 if (ret == RTPSE_MCU_MSG_SIZE && rtpse_mcu_resp_is_final(req, resp))
82 return 0;
83 }
84
85 return -ETIMEDOUT;
86 }
87
88 static const struct rtpse_mcu_transport_ops rtpse_mcu_i2c_native_ops = {
89 .send = rtpse_mcu_i2c_native_send,
90 .recv = rtpse_mcu_i2c_native_recv,
91 };
92
rtpse_mcu_i2c_probe(struct i2c_client * client)93 static int rtpse_mcu_i2c_probe(struct i2c_client *client)
94 {
95 struct device *dev = &client->dev;
96 const struct rtpse_mcu_match_data *match;
97 struct rtpse_mcu_ctrl *pse;
98 bool use_native;
99
100 match = device_get_match_data(dev);
101 if (!match)
102 return dev_err_probe(dev, -ENODEV, "missing match data\n");
103
104 /* The framing (raw I2C vs SMBus) is carried by the match data. */
105 use_native = match->native_i2c;
106 if (use_native) {
107 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
108 return dev_err_probe(dev, -EOPNOTSUPP,
109 "plain-I2C MCU protocol requires I2C-capable adapter\n");
110 } else {
111 if (!i2c_check_functionality(client->adapter,
112 I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
113 I2C_FUNC_SMBUS_READ_I2C_BLOCK))
114 return dev_err_probe(dev, -EOPNOTSUPP,
115 "SMBus MCU protocol requires SMBus I2C-block support\n");
116 }
117
118 pse = devm_kzalloc(dev, sizeof(*pse), GFP_KERNEL);
119 if (!pse)
120 return -ENOMEM;
121
122 pse->dev = dev;
123 pse->pcdev.owner = THIS_MODULE;
124 pse->transport = use_native ? &rtpse_mcu_i2c_native_ops : &rtpse_mcu_i2c_smbus_ops;
125
126 return rtpse_mcu_register(pse);
127 }
128
129 static const struct of_device_id rtpse_mcu_i2c_of_match[] = {
130 { .compatible = "realtek,pse-mcu-gen1-smbus", .data = &rtpse_mcu_gen1_data },
131 { .compatible = "realtek,pse-mcu-gen2-smbus", .data = &rtpse_mcu_gen2_data },
132 { .compatible = "realtek,pse-mcu-gen2-i2c", .data = &rtpse_mcu_gen2_i2c_data },
133 { /* sentinel */ }
134 };
135 MODULE_DEVICE_TABLE(of, rtpse_mcu_i2c_of_match);
136
137 static struct i2c_driver rtpse_mcu_i2c_driver = {
138 .driver = {
139 .name = "realtek-pse-mcu-i2c",
140 .of_match_table = rtpse_mcu_i2c_of_match,
141 },
142 .probe = rtpse_mcu_i2c_probe,
143 };
144 module_i2c_driver(rtpse_mcu_i2c_driver);
145
146 MODULE_AUTHOR("Jonas Jelonek <jelonek.jonas@gmail.com>");
147 MODULE_DESCRIPTION("Realtek PSE MCU driver (I2C transport)");
148 MODULE_LICENSE("GPL");
149