Skip to content

Commit 8799dbf

Browse files
elkablogregkh
authored andcommitted
leds: turris-omnia: Do not use SMBUS calls
[ Upstream commit 6de283b ] The leds-turris-omnia driver uses three function for I2C access: - i2c_smbus_write_byte_data() and i2c_smbus_read_byte_data(), which cause an emulated SMBUS transfer, - i2c_master_send(), which causes an ordinary I2C transfer. The Turris Omnia MCU LED controller is not semantically SMBUS, it operates as a simple I2C bus. It does not implement any of the SMBUS specific features, like PEC, or procedure calls, or anything. Moreover the I2C controller driver also does not implement SMBUS, and so the emulated SMBUS procedure from drivers/i2c/i2c-core-smbus.c is used for the SMBUS calls, which gives an unnecessary overhead. When I first wrote the driver, I was unaware of these facts, and I simply used the first function that worked. Drop the I2C SMBUS calls and instead use simple I2C transfers. Fixes: 089381b ("leds: initial support for Turris Omnia LEDs") Signed-off-by: Marek Behún <kabel@kernel.org> Link: https://lore.kernel.org/r/20230918161104.20860-2-kabel@kernel.org Signed-off-by: Lee Jones <lee@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 1815d40 commit 8799dbf

1 file changed

Lines changed: 42 additions & 12 deletions

File tree

drivers/leds/leds-turris-omnia.c

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/*
33
* CZ.NIC's Turris Omnia LEDs driver
44
*
5-
* 2020 by Marek Behún <kabel@kernel.org>
5+
* 2020, 2023 by Marek Behún <kabel@kernel.org>
66
*/
77

88
#include <linux/i2c.h>
@@ -41,6 +41,37 @@ struct omnia_leds {
4141
struct omnia_led leds[];
4242
};
4343

44+
static int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd, u8 val)
45+
{
46+
u8 buf[2] = { cmd, val };
47+
48+
return i2c_master_send(client, buf, sizeof(buf));
49+
}
50+
51+
static int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd)
52+
{
53+
struct i2c_msg msgs[2];
54+
u8 reply;
55+
int ret;
56+
57+
msgs[0].addr = client->addr;
58+
msgs[0].flags = 0;
59+
msgs[0].len = 1;
60+
msgs[0].buf = &cmd;
61+
msgs[1].addr = client->addr;
62+
msgs[1].flags = I2C_M_RD;
63+
msgs[1].len = 1;
64+
msgs[1].buf = &reply;
65+
66+
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
67+
if (likely(ret == ARRAY_SIZE(msgs)))
68+
return reply;
69+
else if (ret < 0)
70+
return ret;
71+
else
72+
return -EIO;
73+
}
74+
4475
static int omnia_led_brightness_set_blocking(struct led_classdev *cdev,
4576
enum led_brightness brightness)
4677
{
@@ -64,7 +95,7 @@ static int omnia_led_brightness_set_blocking(struct led_classdev *cdev,
6495
if (buf[2] || buf[3] || buf[4])
6596
state |= CMD_LED_STATE_ON;
6697

67-
ret = i2c_smbus_write_byte_data(leds->client, CMD_LED_STATE, state);
98+
ret = omnia_cmd_write_u8(leds->client, CMD_LED_STATE, state);
6899
if (ret >= 0 && (state & CMD_LED_STATE_ON))
69100
ret = i2c_master_send(leds->client, buf, 5);
70101

@@ -114,18 +145,18 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led,
114145
cdev->brightness_set_blocking = omnia_led_brightness_set_blocking;
115146

116147
/* put the LED into software mode */
117-
ret = i2c_smbus_write_byte_data(client, CMD_LED_MODE,
118-
CMD_LED_MODE_LED(led->reg) |
119-
CMD_LED_MODE_USER);
148+
ret = omnia_cmd_write_u8(client, CMD_LED_MODE,
149+
CMD_LED_MODE_LED(led->reg) |
150+
CMD_LED_MODE_USER);
120151
if (ret < 0) {
121152
dev_err(dev, "Cannot set LED %pOF to software mode: %i\n", np,
122153
ret);
123154
return ret;
124155
}
125156

126157
/* disable the LED */
127-
ret = i2c_smbus_write_byte_data(client, CMD_LED_STATE,
128-
CMD_LED_STATE_LED(led->reg));
158+
ret = omnia_cmd_write_u8(client, CMD_LED_STATE,
159+
CMD_LED_STATE_LED(led->reg));
129160
if (ret < 0) {
130161
dev_err(dev, "Cannot set LED %pOF brightness: %i\n", np, ret);
131162
return ret;
@@ -158,7 +189,7 @@ static ssize_t brightness_show(struct device *dev, struct device_attribute *a,
158189
struct i2c_client *client = to_i2c_client(dev);
159190
int ret;
160191

161-
ret = i2c_smbus_read_byte_data(client, CMD_LED_GET_BRIGHTNESS);
192+
ret = omnia_cmd_read_u8(client, CMD_LED_GET_BRIGHTNESS);
162193

163194
if (ret < 0)
164195
return ret;
@@ -179,8 +210,7 @@ static ssize_t brightness_store(struct device *dev, struct device_attribute *a,
179210
if (brightness > 100)
180211
return -EINVAL;
181212

182-
ret = i2c_smbus_write_byte_data(client, CMD_LED_SET_BRIGHTNESS,
183-
(u8)brightness);
213+
ret = omnia_cmd_write_u8(client, CMD_LED_SET_BRIGHTNESS, brightness);
184214

185215
return ret < 0 ? ret : count;
186216
}
@@ -237,8 +267,8 @@ static void omnia_leds_remove(struct i2c_client *client)
237267
u8 buf[5];
238268

239269
/* put all LEDs into default (HW triggered) mode */
240-
i2c_smbus_write_byte_data(client, CMD_LED_MODE,
241-
CMD_LED_MODE_LED(OMNIA_BOARD_LEDS));
270+
omnia_cmd_write_u8(client, CMD_LED_MODE,
271+
CMD_LED_MODE_LED(OMNIA_BOARD_LEDS));
242272

243273
/* set all LEDs color to [255, 255, 255] */
244274
buf[0] = CMD_LED_COLOR;

0 commit comments

Comments
 (0)