kernel: add upstream patches for pca955x led driver
These patches are to support the pca955x led with OpenWRT correctly via device tree on linux 5.10. Without these, the new LED function/color/reg features can not be used. Signed-off-by: Chris Blake <chrisrblake93@gmail.com>
This commit is contained in:
parent
2e0afef246
commit
78ecaebdff
5 changed files with 582 additions and 0 deletions
|
@ -0,0 +1,178 @@
|
|||
From 2420ae02ce0a926819ebe18f809a57bff3edeac2 Mon Sep 17 00:00:00 2001
|
||||
From: Eddie James <eajames@linux.ibm.com>
|
||||
Date: Fri, 16 Jul 2021 17:03:27 -0500
|
||||
Subject: [PATCH] leds: pca955x: Clean up code formatting
|
||||
|
||||
Format the code. Add some variables to help shorten lines.
|
||||
|
||||
Signed-off-by: Eddie James <eajames@linux.ibm.com>
|
||||
Signed-off-by: Pavel Machek <pavel@ucw.cz>
|
||||
---
|
||||
drivers/leds/leds-pca955x.c | 63 ++++++++++++++++++-------------------
|
||||
1 file changed, 30 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
|
||||
index 7087ca4592fc96..f0d841cb59fcc8 100644
|
||||
--- a/drivers/leds/leds-pca955x.c
|
||||
+++ b/drivers/leds/leds-pca955x.c
|
||||
@@ -166,11 +166,10 @@ static inline u8 pca955x_ledsel(u8 oldval, int led_num, int state)
|
||||
static int pca955x_write_psc(struct i2c_client *client, int n, u8 val)
|
||||
{
|
||||
struct pca955x *pca955x = i2c_get_clientdata(client);
|
||||
+ u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + (2 * n);
|
||||
int ret;
|
||||
|
||||
- ret = i2c_smbus_write_byte_data(client,
|
||||
- pca95xx_num_input_regs(pca955x->chipdef->bits) + 2*n,
|
||||
- val);
|
||||
+ ret = i2c_smbus_write_byte_data(client, cmd, val);
|
||||
if (ret < 0)
|
||||
dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n",
|
||||
__func__, n, val, ret);
|
||||
@@ -187,11 +186,10 @@ static int pca955x_write_psc(struct i2c_client *client, int n, u8 val)
|
||||
static int pca955x_write_pwm(struct i2c_client *client, int n, u8 val)
|
||||
{
|
||||
struct pca955x *pca955x = i2c_get_clientdata(client);
|
||||
+ u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + (2 * n);
|
||||
int ret;
|
||||
|
||||
- ret = i2c_smbus_write_byte_data(client,
|
||||
- pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + 2*n,
|
||||
- val);
|
||||
+ ret = i2c_smbus_write_byte_data(client, cmd, val);
|
||||
if (ret < 0)
|
||||
dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n",
|
||||
__func__, n, val, ret);
|
||||
@@ -205,11 +203,10 @@ static int pca955x_write_pwm(struct i2c_client *client, int n, u8 val)
|
||||
static int pca955x_write_ls(struct i2c_client *client, int n, u8 val)
|
||||
{
|
||||
struct pca955x *pca955x = i2c_get_clientdata(client);
|
||||
+ u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n;
|
||||
int ret;
|
||||
|
||||
- ret = i2c_smbus_write_byte_data(client,
|
||||
- pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n,
|
||||
- val);
|
||||
+ ret = i2c_smbus_write_byte_data(client, cmd, val);
|
||||
if (ret < 0)
|
||||
dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n",
|
||||
__func__, n, val, ret);
|
||||
@@ -223,10 +220,10 @@ static int pca955x_write_ls(struct i2c_client *client, int n, u8 val)
|
||||
static int pca955x_read_ls(struct i2c_client *client, int n, u8 *val)
|
||||
{
|
||||
struct pca955x *pca955x = i2c_get_clientdata(client);
|
||||
+ u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n;
|
||||
int ret;
|
||||
|
||||
- ret = i2c_smbus_read_byte_data(client,
|
||||
- pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n);
|
||||
+ ret = i2c_smbus_read_byte_data(client, cmd);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "%s: reg 0x%x, err %d\n",
|
||||
__func__, n, ret);
|
||||
@@ -371,6 +368,7 @@ static struct pca955x_platform_data *
|
||||
pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip)
|
||||
{
|
||||
struct pca955x_platform_data *pdata;
|
||||
+ struct pca955x_led *led;
|
||||
struct fwnode_handle *child;
|
||||
int count;
|
||||
|
||||
@@ -401,13 +399,13 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip)
|
||||
if ((res != 0) && is_of_node(child))
|
||||
name = to_of_node(child)->name;
|
||||
|
||||
- snprintf(pdata->leds[reg].name, sizeof(pdata->leds[reg].name),
|
||||
- "%s", name);
|
||||
+ led = &pdata->leds[reg];
|
||||
+ snprintf(led->name, sizeof(led->name), "%s", name);
|
||||
|
||||
- pdata->leds[reg].type = PCA955X_TYPE_LED;
|
||||
- fwnode_property_read_u32(child, "type", &pdata->leds[reg].type);
|
||||
+ led->type = PCA955X_TYPE_LED;
|
||||
+ fwnode_property_read_u32(child, "type", &led->type);
|
||||
fwnode_property_read_string(child, "linux,default-trigger",
|
||||
- &pdata->leds[reg].default_trigger);
|
||||
+ &led->default_trigger);
|
||||
}
|
||||
|
||||
pdata->num_leds = chip->bits;
|
||||
@@ -426,11 +424,12 @@ static const struct of_device_id of_pca955x_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, of_pca955x_match);
|
||||
|
||||
static int pca955x_probe(struct i2c_client *client,
|
||||
- const struct i2c_device_id *id)
|
||||
+ const struct i2c_device_id *id)
|
||||
{
|
||||
struct pca955x *pca955x;
|
||||
struct pca955x_led *pca955x_led;
|
||||
struct pca955x_chipdef *chip;
|
||||
+ struct led_classdev *led;
|
||||
struct i2c_adapter *adapter;
|
||||
int i, err;
|
||||
struct pca955x_platform_data *pdata;
|
||||
@@ -449,13 +448,13 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
if ((client->addr & ~((1 << chip->slv_addr_shift) - 1)) !=
|
||||
chip->slv_addr) {
|
||||
dev_err(&client->dev, "invalid slave address %02x\n",
|
||||
- client->addr);
|
||||
+ client->addr);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "leds-pca955x: Using %s %d-bit LED driver at "
|
||||
- "slave address 0x%02x\n",
|
||||
- client->name, chip->bits, client->addr);
|
||||
+ "slave address 0x%02x\n", client->name, chip->bits,
|
||||
+ client->addr);
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -EIO;
|
||||
@@ -471,8 +470,8 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
if (!pca955x)
|
||||
return -ENOMEM;
|
||||
|
||||
- pca955x->leds = devm_kcalloc(&client->dev,
|
||||
- chip->bits, sizeof(*pca955x_led), GFP_KERNEL);
|
||||
+ pca955x->leds = devm_kcalloc(&client->dev, chip->bits,
|
||||
+ sizeof(*pca955x_led), GFP_KERNEL);
|
||||
if (!pca955x->leds)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -501,27 +500,25 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
*/
|
||||
if (pdata->leds[i].name[0] == '\0')
|
||||
snprintf(pdata->leds[i].name,
|
||||
- sizeof(pdata->leds[i].name), "%d", i);
|
||||
+ sizeof(pdata->leds[i].name), "%d", i);
|
||||
|
||||
- snprintf(pca955x_led->name,
|
||||
- sizeof(pca955x_led->name), "pca955x:%s",
|
||||
- pdata->leds[i].name);
|
||||
+ snprintf(pca955x_led->name, sizeof(pca955x_led->name),
|
||||
+ "pca955x:%s", pdata->leds[i].name);
|
||||
|
||||
+ led = &pca955x_led->led_cdev;
|
||||
if (pdata->leds[i].default_trigger)
|
||||
- pca955x_led->led_cdev.default_trigger =
|
||||
+ led->default_trigger =
|
||||
pdata->leds[i].default_trigger;
|
||||
|
||||
- pca955x_led->led_cdev.name = pca955x_led->name;
|
||||
- pca955x_led->led_cdev.brightness_set_blocking =
|
||||
- pca955x_led_set;
|
||||
+ led->name = pca955x_led->name;
|
||||
+ led->brightness_set_blocking = pca955x_led_set;
|
||||
|
||||
- err = devm_led_classdev_register(&client->dev,
|
||||
- &pca955x_led->led_cdev);
|
||||
+ err = devm_led_classdev_register(&client->dev, led);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Turn off LED */
|
||||
- err = pca955x_led_set(&pca955x_led->led_cdev, LED_OFF);
|
||||
+ err = pca955x_led_set(led, LED_OFF);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
From 7086625fde6538b2c0623eb767ad23c7ac3d7f3a Mon Sep 17 00:00:00 2001
|
||||
From: Eddie James <eajames@linux.ibm.com>
|
||||
Date: Fri, 16 Jul 2021 17:03:28 -0500
|
||||
Subject: [PATCH] leds: pca955x: Add brightness_get function
|
||||
|
||||
Add a function to fetch the state of the hardware LED.
|
||||
|
||||
Signed-off-by: Eddie James <eajames@linux.ibm.com>
|
||||
Signed-off-by: Pavel Machek <pavel@ucw.cz>
|
||||
---
|
||||
drivers/leds/leds-pca955x.c | 52 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 52 insertions(+)
|
||||
|
||||
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
|
||||
index f0d841cb59fcc8..e47ba7c3b7c7d8 100644
|
||||
--- a/drivers/leds/leds-pca955x.c
|
||||
+++ b/drivers/leds/leds-pca955x.c
|
||||
@@ -233,6 +233,57 @@ static int pca955x_read_ls(struct i2c_client *client, int n, u8 *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int pca955x_read_pwm(struct i2c_client *client, int n, u8 *val)
|
||||
+{
|
||||
+ struct pca955x *pca955x = i2c_get_clientdata(client);
|
||||
+ u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + (2 * n);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = i2c_smbus_read_byte_data(client, cmd);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&client->dev, "%s: reg 0x%x, err %d\n",
|
||||
+ __func__, n, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ *val = (u8)ret;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static enum led_brightness pca955x_led_get(struct led_classdev *led_cdev)
|
||||
+{
|
||||
+ struct pca955x_led *pca955x_led = container_of(led_cdev,
|
||||
+ struct pca955x_led,
|
||||
+ led_cdev);
|
||||
+ struct pca955x *pca955x = pca955x_led->pca955x;
|
||||
+ u8 ls, pwm;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = pca955x_read_ls(pca955x->client, pca955x_led->led_num / 4, &ls);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ls = (ls >> ((pca955x_led->led_num % 4) << 1)) & 0x3;
|
||||
+ switch (ls) {
|
||||
+ case PCA955X_LS_LED_ON:
|
||||
+ ret = LED_FULL;
|
||||
+ break;
|
||||
+ case PCA955X_LS_LED_OFF:
|
||||
+ ret = LED_OFF;
|
||||
+ break;
|
||||
+ case PCA955X_LS_BLINK0:
|
||||
+ ret = LED_HALF;
|
||||
+ break;
|
||||
+ case PCA955X_LS_BLINK1:
|
||||
+ ret = pca955x_read_pwm(pca955x->client, 1, &pwm);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ ret = 255 - pwm;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int pca955x_led_set(struct led_classdev *led_cdev,
|
||||
enum led_brightness value)
|
||||
{
|
||||
@@ -512,6 +563,7 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
|
||||
led->name = pca955x_led->name;
|
||||
led->brightness_set_blocking = pca955x_led_set;
|
||||
+ led->brightness_get = pca955x_led_get;
|
||||
|
||||
err = devm_led_classdev_register(&client->dev, led);
|
||||
if (err)
|
|
@ -0,0 +1,119 @@
|
|||
From e46cb6d0c760a5b15e38138845fad99628fafcb8 Mon Sep 17 00:00:00 2001
|
||||
From: Eddie James <eajames@linux.ibm.com>
|
||||
Date: Fri, 16 Jul 2021 17:03:29 -0500
|
||||
Subject: [PATCH] leds: pca955x: Implement the default-state property
|
||||
|
||||
In order to retain the LED state after a system reboot, check the
|
||||
documented default-state device tree property during initialization.
|
||||
Modify the behavior of the probe according to the property.
|
||||
|
||||
Signed-off-by: Eddie James <eajames@linux.ibm.com>
|
||||
Signed-off-by: Pavel Machek <pavel@ucw.cz>
|
||||
---
|
||||
drivers/leds/leds-pca955x.c | 54 +++++++++++++++++++++++++++++++------
|
||||
1 file changed, 46 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
|
||||
index e47ba7c3b7c7d8..fa1d77d86ef67b 100644
|
||||
--- a/drivers/leds/leds-pca955x.c
|
||||
+++ b/drivers/leds/leds-pca955x.c
|
||||
@@ -129,6 +129,7 @@ struct pca955x_led {
|
||||
int led_num; /* 0 .. 15 potentially */
|
||||
char name[32];
|
||||
u32 type;
|
||||
+ int default_state;
|
||||
const char *default_trigger;
|
||||
};
|
||||
|
||||
@@ -439,6 +440,7 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip)
|
||||
|
||||
device_for_each_child_node(&client->dev, child) {
|
||||
const char *name;
|
||||
+ const char *state;
|
||||
u32 reg;
|
||||
int res;
|
||||
|
||||
@@ -457,6 +459,18 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip)
|
||||
fwnode_property_read_u32(child, "type", &led->type);
|
||||
fwnode_property_read_string(child, "linux,default-trigger",
|
||||
&led->default_trigger);
|
||||
+
|
||||
+ if (!fwnode_property_read_string(child, "default-state",
|
||||
+ &state)) {
|
||||
+ if (!strcmp(state, "keep"))
|
||||
+ led->default_state = LEDS_GPIO_DEFSTATE_KEEP;
|
||||
+ else if (!strcmp(state, "on"))
|
||||
+ led->default_state = LEDS_GPIO_DEFSTATE_ON;
|
||||
+ else
|
||||
+ led->default_state = LEDS_GPIO_DEFSTATE_OFF;
|
||||
+ } else {
|
||||
+ led->default_state = LEDS_GPIO_DEFSTATE_OFF;
|
||||
+ }
|
||||
}
|
||||
|
||||
pdata->num_leds = chip->bits;
|
||||
@@ -485,6 +499,7 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
int i, err;
|
||||
struct pca955x_platform_data *pdata;
|
||||
int ngpios = 0;
|
||||
+ bool keep_pwm = false;
|
||||
|
||||
chip = &pca955x_chipdefs[id->driver_data];
|
||||
adapter = client->adapter;
|
||||
@@ -565,14 +580,35 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
led->brightness_set_blocking = pca955x_led_set;
|
||||
led->brightness_get = pca955x_led_get;
|
||||
|
||||
+ if (pdata->leds[i].default_state ==
|
||||
+ LEDS_GPIO_DEFSTATE_OFF) {
|
||||
+ err = pca955x_led_set(led, LED_OFF);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ } else if (pdata->leds[i].default_state ==
|
||||
+ LEDS_GPIO_DEFSTATE_ON) {
|
||||
+ err = pca955x_led_set(led, LED_FULL);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
err = devm_led_classdev_register(&client->dev, led);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- /* Turn off LED */
|
||||
- err = pca955x_led_set(led, LED_OFF);
|
||||
- if (err)
|
||||
- return err;
|
||||
+ /*
|
||||
+ * For default-state == "keep", let the core update the
|
||||
+ * brightness from the hardware, then check the
|
||||
+ * brightness to see if it's using PWM1. If so, PWM1
|
||||
+ * should not be written below.
|
||||
+ */
|
||||
+ if (pdata->leds[i].default_state ==
|
||||
+ LEDS_GPIO_DEFSTATE_KEEP) {
|
||||
+ if (led->brightness != LED_FULL &&
|
||||
+ led->brightness != LED_OFF &&
|
||||
+ led->brightness != LED_HALF)
|
||||
+ keep_pwm = true;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,10 +617,12 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- /* PWM1 is used for variable brightness, default to OFF */
|
||||
- err = pca955x_write_pwm(client, 1, 0);
|
||||
- if (err)
|
||||
- return err;
|
||||
+ if (!keep_pwm) {
|
||||
+ /* PWM1 is used for variable brightness, default to OFF */
|
||||
+ err = pca955x_write_pwm(client, 1, 0);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
/* Set to fast frequency so we do not see flashing */
|
||||
err = pca955x_write_psc(client, 0, 0);
|
|
@ -0,0 +1,138 @@
|
|||
From 7c4815929276b2e223eb6f2e49afe5071d4294a5 Mon Sep 17 00:00:00 2001
|
||||
From: Eddie James <eajames@linux.ibm.com>
|
||||
Date: Fri, 16 Jul 2021 17:03:30 -0500
|
||||
Subject: [PATCH] leds: pca955x: Let the core process the fwnode
|
||||
|
||||
Much of the fwnode processing in the PCA955x driver is now in the
|
||||
LEDs core driver, so pass the fwnode in the init data when
|
||||
registering the LED device. In order to preserve the existing naming
|
||||
scheme, check for an empty name and set it to the LED number.
|
||||
|
||||
Signed-off-by: Eddie James <eajames@linux.ibm.com>
|
||||
Signed-off-by: Pavel Machek <pavel@ucw.cz>
|
||||
---
|
||||
drivers/leds/leds-pca955x.c | 58 +++++++++++++++++++------------------
|
||||
1 file changed, 30 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
|
||||
index fa1d77d86ef67b..a6aa4b9abde8c4 100644
|
||||
--- a/drivers/leds/leds-pca955x.c
|
||||
+++ b/drivers/leds/leds-pca955x.c
|
||||
@@ -127,10 +127,9 @@ struct pca955x_led {
|
||||
struct pca955x *pca955x;
|
||||
struct led_classdev led_cdev;
|
||||
int led_num; /* 0 .. 15 potentially */
|
||||
- char name[32];
|
||||
u32 type;
|
||||
int default_state;
|
||||
- const char *default_trigger;
|
||||
+ struct fwnode_handle *fwnode;
|
||||
};
|
||||
|
||||
struct pca955x_platform_data {
|
||||
@@ -439,7 +438,6 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
device_for_each_child_node(&client->dev, child) {
|
||||
- const char *name;
|
||||
const char *state;
|
||||
u32 reg;
|
||||
int res;
|
||||
@@ -448,17 +446,10 @@ pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip)
|
||||
if ((res != 0) || (reg >= chip->bits))
|
||||
continue;
|
||||
|
||||
- res = fwnode_property_read_string(child, "label", &name);
|
||||
- if ((res != 0) && is_of_node(child))
|
||||
- name = to_of_node(child)->name;
|
||||
-
|
||||
led = &pdata->leds[reg];
|
||||
- snprintf(led->name, sizeof(led->name), "%s", name);
|
||||
-
|
||||
led->type = PCA955X_TYPE_LED;
|
||||
+ led->fwnode = child;
|
||||
fwnode_property_read_u32(child, "type", &led->type);
|
||||
- fwnode_property_read_string(child, "linux,default-trigger",
|
||||
- &led->default_trigger);
|
||||
|
||||
if (!fwnode_property_read_string(child, "default-state",
|
||||
&state)) {
|
||||
@@ -495,11 +486,14 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
struct pca955x_led *pca955x_led;
|
||||
struct pca955x_chipdef *chip;
|
||||
struct led_classdev *led;
|
||||
+ struct led_init_data init_data;
|
||||
struct i2c_adapter *adapter;
|
||||
int i, err;
|
||||
struct pca955x_platform_data *pdata;
|
||||
int ngpios = 0;
|
||||
+ bool set_default_label = false;
|
||||
bool keep_pwm = false;
|
||||
+ char default_label[8];
|
||||
|
||||
chip = &pca955x_chipdefs[id->driver_data];
|
||||
adapter = client->adapter;
|
||||
@@ -547,6 +541,9 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
pca955x->client = client;
|
||||
pca955x->chipdef = chip;
|
||||
|
||||
+ init_data.devname_mandatory = false;
|
||||
+ init_data.devicename = "pca955x";
|
||||
+
|
||||
for (i = 0; i < chip->bits; i++) {
|
||||
pca955x_led = &pca955x->leds[i];
|
||||
pca955x_led->led_num = i;
|
||||
@@ -560,23 +557,7 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
ngpios++;
|
||||
break;
|
||||
case PCA955X_TYPE_LED:
|
||||
- /*
|
||||
- * Platform data can specify LED names and
|
||||
- * default triggers
|
||||
- */
|
||||
- if (pdata->leds[i].name[0] == '\0')
|
||||
- snprintf(pdata->leds[i].name,
|
||||
- sizeof(pdata->leds[i].name), "%d", i);
|
||||
-
|
||||
- snprintf(pca955x_led->name, sizeof(pca955x_led->name),
|
||||
- "pca955x:%s", pdata->leds[i].name);
|
||||
-
|
||||
led = &pca955x_led->led_cdev;
|
||||
- if (pdata->leds[i].default_trigger)
|
||||
- led->default_trigger =
|
||||
- pdata->leds[i].default_trigger;
|
||||
-
|
||||
- led->name = pca955x_led->name;
|
||||
led->brightness_set_blocking = pca955x_led_set;
|
||||
led->brightness_get = pca955x_led_get;
|
||||
|
||||
@@ -592,7 +573,28 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
return err;
|
||||
}
|
||||
|
||||
- err = devm_led_classdev_register(&client->dev, led);
|
||||
+ init_data.fwnode = pdata->leds[i].fwnode;
|
||||
+
|
||||
+ if (is_of_node(init_data.fwnode)) {
|
||||
+ if (to_of_node(init_data.fwnode)->name[0] ==
|
||||
+ '\0')
|
||||
+ set_default_label = true;
|
||||
+ else
|
||||
+ set_default_label = false;
|
||||
+ } else {
|
||||
+ set_default_label = true;
|
||||
+ }
|
||||
+
|
||||
+ if (set_default_label) {
|
||||
+ snprintf(default_label, sizeof(default_label),
|
||||
+ "%d", i);
|
||||
+ init_data.default_label = default_label;
|
||||
+ } else {
|
||||
+ init_data.default_label = NULL;
|
||||
+ }
|
||||
+
|
||||
+ err = devm_led_classdev_register_ext(&client->dev, led,
|
||||
+ &init_data);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
From 239f32b4f161c1584cd4b386d6ab8766432a6ede Mon Sep 17 00:00:00 2001
|
||||
From: Eddie James <eajames@linux.ibm.com>
|
||||
Date: Fri, 16 Jul 2021 17:03:31 -0500
|
||||
Subject: [PATCH] leds: pca955x: Switch to i2c probe_new
|
||||
|
||||
The deprecated i2c probe functionality doesn't work with OF
|
||||
compatible strings, as it only checks for the i2c device id. Switch
|
||||
to the new way of probing and grab the match data to select the
|
||||
chip type.
|
||||
|
||||
Signed-off-by: Eddie James <eajames@linux.ibm.com>
|
||||
Signed-off-by: Pavel Machek <pavel@ucw.cz>
|
||||
---
|
||||
drivers/leds/leds-pca955x.c | 23 +++++++++++++++++++----
|
||||
1 file changed, 19 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
|
||||
index a6aa4b9abde8c4..a6b5699aeae4fe 100644
|
||||
--- a/drivers/leds/leds-pca955x.c
|
||||
+++ b/drivers/leds/leds-pca955x.c
|
||||
@@ -479,8 +479,7 @@ static const struct of_device_id of_pca955x_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_pca955x_match);
|
||||
|
||||
-static int pca955x_probe(struct i2c_client *client,
|
||||
- const struct i2c_device_id *id)
|
||||
+static int pca955x_probe(struct i2c_client *client)
|
||||
{
|
||||
struct pca955x *pca955x;
|
||||
struct pca955x_led *pca955x_led;
|
||||
@@ -494,8 +493,24 @@ static int pca955x_probe(struct i2c_client *client,
|
||||
bool set_default_label = false;
|
||||
bool keep_pwm = false;
|
||||
char default_label[8];
|
||||
+ enum pca955x_type chip_type;
|
||||
+ const void *md = device_get_match_data(&client->dev);
|
||||
|
||||
- chip = &pca955x_chipdefs[id->driver_data];
|
||||
+ if (md) {
|
||||
+ chip_type = (enum pca955x_type)md;
|
||||
+ } else {
|
||||
+ const struct i2c_device_id *id = i2c_match_id(pca955x_id,
|
||||
+ client);
|
||||
+
|
||||
+ if (id) {
|
||||
+ chip_type = (enum pca955x_type)id->driver_data;
|
||||
+ } else {
|
||||
+ dev_err(&client->dev, "unknown chip\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ chip = &pca955x_chipdefs[chip_type];
|
||||
adapter = client->adapter;
|
||||
pdata = dev_get_platdata(&client->dev);
|
||||
if (!pdata) {
|
||||
@@ -670,7 +685,7 @@ static struct i2c_driver pca955x_driver = {
|
||||
.name = "leds-pca955x",
|
||||
.of_match_table = of_pca955x_match,
|
||||
},
|
||||
- .probe = pca955x_probe,
|
||||
+ .probe_new = pca955x_probe,
|
||||
.id_table = pca955x_id,
|
||||
};
|
Loading…
Reference in a new issue