* [PATCH 2/4] leds: lm3692x: Change DT calls to fwnode calls
2018-07-02 18:12 [PATCH 1/4] leds: lm3692x: Update license header to SPDX Dan Murphy
@ 2018-07-02 18:12 ` Dan Murphy
2018-07-02 18:12 ` [PATCH 3/4] dt: bindings: lm3692x: Update binding for LED sync control Dan Murphy
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Dan Murphy @ 2018-07-02 18:12 UTC (permalink / raw)
To: robh+dt, mark.rutland, jacek.anaszewski, andy.shevchenko
Cc: devicetree, linux-kernel, linux-leds, Dan Murphy
Update the code to use the fwnode calls as opposed
to ARM DT node api's.
This allows the device to be used with either DT
configurations or ACPI definitions.
Signed-off-by: Dan Murphy <dmurphy@ti.com>
---
drivers/leds/leds-lm3692x.c | 38 ++++++++++++++++++++-----------------
1 file changed, 21 insertions(+), 17 deletions(-)
diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c
index 1a06d8c97789..ade4abfceb46 100644
--- a/drivers/leds/leds-lm3692x.c
+++ b/drivers/leds/leds-lm3692x.c
@@ -267,30 +267,15 @@ static int lm3692x_init(struct lm3692x_led *led)
static int lm3692x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int ret;
+ struct fwnode_handle *child = NULL;
struct lm3692x_led *led;
- struct device_node *np = client->dev.of_node;
- struct device_node *child_node;
const char *name;
+ int ret;
led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
- for_each_available_child_of_node(np, child_node) {
- led->led_dev.default_trigger = of_get_property(child_node,
- "linux,default-trigger",
- NULL);
-
- ret = of_property_read_string(child_node, "label", &name);
- if (!ret)
- snprintf(led->label, sizeof(led->label),
- "%s:%s", id->name, name);
- else
- snprintf(led->label, sizeof(led->label),
- "%s::backlight_cluster", id->name);
- };
-
led->enable_gpio = devm_gpiod_get_optional(&client->dev,
"enable", GPIOD_OUT_LOW);
if (IS_ERR(led->enable_gpio)) {
@@ -323,6 +308,25 @@ static int lm3692x_probe(struct i2c_client *client,
if (ret)
return ret;
+ child = device_get_next_child_node(&led->client->dev, child);
+ if (!child) {
+ dev_err(&led->client->dev, "No LED Child node\n");
+ return ret;
+ }
+
+ fwnode_property_read_string(child, "linux,default-trigger",
+ &led->led_dev.default_trigger);
+
+ ret = fwnode_property_read_string(child, "label", &name);
+ if (ret)
+ snprintf(led->label, sizeof(led->label),
+ "%s::", led->client->name);
+ else
+ snprintf(led->label, sizeof(led->label),
+ "%s:%s", led->client->name, name);
+
+ led->led_dev.dev->of_node = to_of_node(child);
+
ret = devm_led_classdev_register(&client->dev, &led->led_dev);
if (ret) {
dev_err(&client->dev, "led register err: %d\n", ret);
--
2.17.0.582.gccdcbd54c
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/4] leds: lm3692x: Support LED sync configuration
2018-07-02 18:12 [PATCH 1/4] leds: lm3692x: Update license header to SPDX Dan Murphy
2018-07-02 18:12 ` [PATCH 2/4] leds: lm3692x: Change DT calls to fwnode calls Dan Murphy
2018-07-02 18:12 ` [PATCH 3/4] dt: bindings: lm3692x: Update binding for LED sync control Dan Murphy
@ 2018-07-02 18:12 ` Dan Murphy
2018-07-03 20:56 ` [PATCH 1/4] leds: lm3692x: Update license header to SPDX Jacek Anaszewski
3 siblings, 0 replies; 6+ messages in thread
From: Dan Murphy @ 2018-07-02 18:12 UTC (permalink / raw)
To: robh+dt, mark.rutland, jacek.anaszewski, andy.shevchenko
Cc: devicetree, linux-kernel, linux-leds, Dan Murphy
The LM36922 has one output but can sync current to 2 LED
strings. The user may only use one sync so the other
syncs need to be disabled.
The LM36923 has 3 LED syncs.
Signed-off-by: Dan Murphy <dmurphy@ti.com>
---
drivers/leds/leds-lm3692x.c | 158 +++++++++++++++++++++++++++---------
1 file changed, 120 insertions(+), 38 deletions(-)
diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c
index ade4abfceb46..06f0ad954b55 100644
--- a/drivers/leds/leds-lm3692x.c
+++ b/drivers/leds/leds-lm3692x.c
@@ -15,6 +15,9 @@
#include <linux/slab.h>
#include <uapi/linux/uleds.h>
+#define LM36922_MODEL 0
+#define LM36923_MODEL 1
+
#define LM3692X_REV 0x0
#define LM3692X_RESET 0x1
#define LM3692X_EN 0x10
@@ -33,6 +36,9 @@
#define LM3692X_DEVICE_EN BIT(0)
#define LM3692X_LED1_EN BIT(1)
#define LM3692X_LED2_EN BIT(2)
+#define LM36923_LED3_EN BIT(3)
+#define LM3692X_ENABLE_MASK (LM3692X_DEVICE_EN | LM3692X_LED1_EN | \
+ LM3692X_LED2_EN | LM36923_LED3_EN)
/* Brightness Control Bits */
#define LM3692X_BL_ADJ_POL BIT(0)
@@ -98,6 +104,8 @@
* @enable_gpio - VDDIO/EN gpio to enable communication interface
* @regulator - LED supply regulator pointer
* @label - LED label
+ * @led_enable - LED sync to be enabled
+ * @model_id - Current device model ID enumerated
*/
struct lm3692x_led {
struct mutex lock;
@@ -107,6 +115,8 @@ struct lm3692x_led {
struct gpio_desc *enable_gpio;
struct regulator *regulator;
char label[LED_MAX_NAME_SIZE];
+ int led_enable;
+ int model_id;
};
static const struct reg_default lm3692x_reg_defs[] = {
@@ -189,6 +199,7 @@ static int lm3692x_brightness_set(struct led_classdev *led_cdev,
static int lm3692x_init(struct lm3692x_led *led)
{
+ int enable_state;
int ret;
if (led->regulator) {
@@ -215,9 +226,25 @@ static int lm3692x_init(struct lm3692x_led *led)
/*
* For glitch free operation, the following data should
- * only be written while device enable bit is 0
+ * only be written while LEDx enable bits are 0 and the device enable
+ * bit is set to 1.
* per Section 7.5.14 of the data sheet
*/
+ ret = regmap_write(led->regmap, LM3692X_EN, LM3692X_DEVICE_EN);
+ if (ret)
+ goto out;
+
+ /* Set the brightness to 0 so when enabled the LEDs do not come
+ * on with full brightness.
+ */
+ ret = regmap_write(led->regmap, LM3692X_BRT_MSB, 0);
+ if (ret)
+ goto out;
+
+ ret = regmap_write(led->regmap, LM3692X_BRT_LSB, 0);
+ if (ret)
+ goto out;
+
ret = regmap_write(led->regmap, LM3692X_PWM_CTRL,
LM3692X_PWM_FILTER_100 | LM3692X_PWM_SAMP_24MHZ);
if (ret)
@@ -247,6 +274,38 @@ static int lm3692x_init(struct lm3692x_led *led)
if (ret)
goto out;
+ switch (led->led_enable) {
+ case 0:
+ default:
+ if (led->model_id == LM36923_MODEL)
+ enable_state = LM3692X_LED1_EN | LM3692X_LED2_EN |
+ LM36923_LED3_EN;
+ else
+ enable_state = LM3692X_LED1_EN | LM3692X_LED2_EN;
+
+ break;
+ case 1:
+ enable_state = LM3692X_LED1_EN;
+ break;
+ case 2:
+ enable_state = LM3692X_LED2_EN;
+ break;
+
+ case 3:
+ if (led->model_id == LM36923_MODEL) {
+ enable_state = LM36923_LED3_EN;
+ break;
+ }
+
+ ret = -EINVAL;
+ dev_err(&led->client->dev,
+ "LED3 sync not available on this device\n");
+ goto out;
+ }
+
+ ret = regmap_update_bits(led->regmap, LM3692X_EN, LM3692X_ENABLE_MASK,
+ enable_state | LM3692X_DEVICE_EN);
+
return ret;
out:
dev_err(&led->client->dev, "Fail writing initialization values\n");
@@ -263,55 +322,29 @@ static int lm3692x_init(struct lm3692x_led *led)
return ret;
}
-
-static int lm3692x_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int lm3692x_probe_dt(struct lm3692x_led *led)
{
struct fwnode_handle *child = NULL;
- struct lm3692x_led *led;
const char *name;
int ret;
- led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
- if (!led)
- return -ENOMEM;
-
- led->enable_gpio = devm_gpiod_get_optional(&client->dev,
+ led->enable_gpio = devm_gpiod_get_optional(&led->client->dev,
"enable", GPIOD_OUT_LOW);
if (IS_ERR(led->enable_gpio)) {
ret = PTR_ERR(led->enable_gpio);
- dev_err(&client->dev, "Failed to get enable gpio: %d\n", ret);
+ dev_err(&led->client->dev, "Failed to get enable gpio: %d\n",
+ ret);
return ret;
}
- led->regulator = devm_regulator_get(&client->dev, "vled");
+ led->regulator = devm_regulator_get(&led->client->dev, "vled");
if (IS_ERR(led->regulator))
led->regulator = NULL;
- led->client = client;
- led->led_dev.name = led->label;
- led->led_dev.brightness_set_blocking = lm3692x_brightness_set;
-
- mutex_init(&led->lock);
-
- i2c_set_clientdata(client, led);
-
- led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config);
- if (IS_ERR(led->regmap)) {
- ret = PTR_ERR(led->regmap);
- dev_err(&client->dev, "Failed to allocate register map: %d\n",
- ret);
- return ret;
- }
-
- ret = lm3692x_init(led);
- if (ret)
- return ret;
-
child = device_get_next_child_node(&led->client->dev, child);
if (!child) {
dev_err(&led->client->dev, "No LED Child node\n");
- return ret;
+ return -ENODEV;
}
fwnode_property_read_string(child, "linux,default-trigger",
@@ -325,14 +358,57 @@ static int lm3692x_probe(struct i2c_client *client,
snprintf(led->label, sizeof(led->label),
"%s:%s", led->client->name, name);
- led->led_dev.dev->of_node = to_of_node(child);
+ ret = fwnode_property_read_u32(child, "reg", &led->led_enable);
+ if (ret) {
+ dev_err(&led->client->dev, "reg DT property missing\n");
+ return ret;
+ }
+
+ led->led_dev.name = led->label;
- ret = devm_led_classdev_register(&client->dev, &led->led_dev);
+ ret = devm_led_classdev_register(&led->client->dev, &led->led_dev);
if (ret) {
- dev_err(&client->dev, "led register err: %d\n", ret);
+ dev_err(&led->client->dev, "led register err: %d\n", ret);
+ return ret;
+ }
+
+ led->led_dev.dev->of_node = to_of_node(child);
+
+ return 0;
+}
+
+static int lm3692x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct lm3692x_led *led;
+ int ret;
+
+ led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL);
+ if (!led)
+ return -ENOMEM;
+
+ mutex_init(&led->lock);
+ led->client = client;
+ led->led_dev.brightness_set_blocking = lm3692x_brightness_set;
+ led->model_id = id->driver_data;
+ i2c_set_clientdata(client, led);
+
+ led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config);
+ if (IS_ERR(led->regmap)) {
+ ret = PTR_ERR(led->regmap);
+ dev_err(&client->dev, "Failed to allocate register map: %d\n",
+ ret);
return ret;
}
+ ret = lm3692x_probe_dt(led);
+ if (ret)
+ return ret;
+
+ ret = lm3692x_init(led);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -341,6 +417,12 @@ static int lm3692x_remove(struct i2c_client *client)
struct lm3692x_led *led = i2c_get_clientdata(client);
int ret;
+ ret = regmap_update_bits(led->regmap, LM3692X_EN, LM3692X_DEVICE_EN, 0);
+ if (ret) {
+ dev_err(&led->client->dev, "Failed to disable regulator\n");
+ return ret;
+ }
+
if (led->enable_gpio)
gpiod_direction_output(led->enable_gpio, 0);
@@ -357,8 +439,8 @@ static int lm3692x_remove(struct i2c_client *client)
}
static const struct i2c_device_id lm3692x_id[] = {
- { "lm36922", 0 },
- { "lm36923", 1 },
+ { "lm36922", LM36922_MODEL },
+ { "lm36923", LM36923_MODEL },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm3692x_id);
--
2.17.0.582.gccdcbd54c
^ permalink raw reply related [flat|nested] 6+ messages in thread