Implement device tree support to lm3560 and make some
minor style adjustmets.
Svyatoslav Ryhel (2):
dt-bindings: media: i2c: add lm3560 binding
media: lm3560: convent to OF
.../bindings/media/i2c/ti,lm3560.yaml | 130 ++++++++++++++++++
drivers/media/i2c/lm3560.c | 128 ++++++++++++-----
2 files changed, 223 insertions(+), 35 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/i2c/ti,lm3560.yaml
--
2.37.2
Signed-off-by: Svyatoslav Ryhel <[email protected]>
---
.../bindings/media/i2c/ti,lm3560.yaml | 130 ++++++++++++++++++
1 file changed, 130 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/i2c/ti,lm3560.yaml
diff --git a/Documentation/devicetree/bindings/media/i2c/ti,lm3560.yaml b/Documentation/devicetree/bindings/media/i2c/ti,lm3560.yaml
new file mode 100644
index 000000000000..b3c2ccb83a30
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ti,lm3560.yaml
@@ -0,0 +1,130 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ti,lm3560.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI LM3560 Synchronous Boost Flash Driver
+
+maintainers:
+ - Daniel Jeong <[email protected]>
+ - Ldd-Mlp <[email protected]>
+
+description: |
+ The LM3560 is a 2-MHz fixed frequency synchronous boost
+ converter with two 1000-mA constant current drivers for
+ high-current white LEDs. The dual highside current sources
+ allow for grounded cathode LED operation and can be tied
+ together for providing flash currents at up to 2 A through
+ a single LED. An adaptive regulation method ensures the
+ current for each LED remains in regulation and maximizes
+ efficiency.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - ti,lm3559
+ - ti,lm3560
+
+ reg:
+ maxItems: 1
+
+ enable-gpios:
+ maxItems: 1
+
+ ti,peak-current:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 0x20, 0x40, 0x60]
+ default: 0x60
+ description: |
+ Peak current can be set to 4 values 1.6A (0x00),
+ 2.3A (0x20), 3.0A (0x40) and 3.6A (0x60).
+
+ ti,max-flash-timeout:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 32
+ maximum: 1024
+ default: 1024
+ description: |
+ Maximum flash timeout in ms with step 32ms.
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - '#address-cells'
+ - '#size-cells'
+
+patternProperties:
+ "^led@[01]$":
+ type: object
+ description: |
+ Properties for a connected LEDs.
+ properties:
+ reg:
+ minimum: 0
+ maximum: 1
+
+ ti,max-flash-current:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 62500
+ maximum: 1000000
+ default: 1000000
+ description: |
+ Maximum current in flash mode in uA with step 62500uA.
+
+ ti,max-torch-current:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 31250
+ maximum: 250000
+ default: 250000
+ description: |
+ Maximum current in tourch mode in uA with step 31250uA.
+
+ required:
+ - reg
+
+ additionalProperties: false
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ flash-led@53 {
+ compatible = "ti,lm3559";
+ reg = <0x53>;
+
+ enable-gpios = <&gpio 219 GPIO_ACTIVE_HIGH>;
+
+ ti,peak-current = <0>;
+ ti,max-flash-timeout = <1024>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+
+ ti,max-flash-current = <562500>;
+ ti,max-torch-current = <156250>;
+ };
+
+ led@1 {
+ reg = <1>;
+
+ ti,max-flash-current = <562500>;
+ ti,max-torch-current = <156250>;
+ };
+ };
+ };
+...
--
2.37.2
If no pdata is available, try to read from device tree.
Signed-off-by: Svyatoslav Ryhel <[email protected]>
---
drivers/media/i2c/lm3560.c | 128 +++++++++++++++++++++++++++----------
1 file changed, 93 insertions(+), 35 deletions(-)
diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
index 5ef613604be7..5541051616b7 100644
--- a/drivers/media/i2c/lm3560.c
+++ b/drivers/media/i2c/lm3560.c
@@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/mutex.h>
@@ -22,16 +23,16 @@
/* registers definitions */
#define REG_ENABLE 0x10
-#define REG_TORCH_BR 0xa0
-#define REG_FLASH_BR 0xb0
-#define REG_FLASH_TOUT 0xc0
+#define REG_TORCH_BR 0xa0
+#define REG_FLASH_BR 0xb0
+#define REG_FLASH_TOUT 0xc0
#define REG_FLAG 0xd0
#define REG_CONFIG1 0xe0
/* fault mask */
-#define FAULT_TIMEOUT (1<<0)
-#define FAULT_OVERTEMP (1<<1)
-#define FAULT_SHORT_CIRCUIT (1<<2)
+#define FAULT_TIMEOUT BIT(0)
+#define FAULT_OVERTEMP BIT(1)
+#define FAULT_SHORT_CIRCUIT BIT(2)
enum led_enable {
MODE_SHDN = 0x0,
@@ -54,6 +55,7 @@ struct lm3560_flash {
struct device *dev;
struct lm3560_platform_data *pdata;
struct regmap *regmap;
+ struct gpio_desc *hwen_gpio;
struct mutex lock;
enum v4l2_flash_led_mode led_mode;
@@ -356,12 +358,19 @@ static int lm3560_subdev_init(struct lm3560_flash *flash,
flash->subdev_led[led_no].flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
strscpy(flash->subdev_led[led_no].name, led_name,
sizeof(flash->subdev_led[led_no].name));
+
rval = lm3560_init_controls(flash, led_no);
- if (rval)
+ if (rval) {
+ dev_err(flash->dev, "failed to init controls: %d\n", rval);
goto err_out;
+ }
+
rval = media_entity_pads_init(&flash->subdev_led[led_no].entity, 0, NULL);
- if (rval < 0)
+ if (rval < 0) {
+ dev_err(flash->dev, "failed to init media entity pads: %d\n", rval);
goto err_out;
+ }
+
flash->subdev_led[led_no].entity.function = MEDIA_ENT_F_FLASH;
return rval;
@@ -391,6 +400,49 @@ static int lm3560_init_device(struct lm3560_flash *flash)
return rval;
}
+static int lm3560_of_probe(struct lm3560_flash *flash)
+{
+ struct lm3560_platform_data *pdata;
+ struct fwnode_handle *node;
+ int ret, reg;
+
+ pdata = devm_kzalloc(flash->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENODEV;
+
+ ret = device_property_read_u32(flash->dev,
+ "ti,peak-current", &pdata->peak);
+ if (ret)
+ pdata->peak = LM3560_PEAK_3600mA;
+
+ ret = device_property_read_u32(flash->dev,
+ "ti,max-flash-timeout",
+ &pdata->max_flash_timeout);
+ if (ret)
+ pdata->max_flash_timeout = LM3560_FLASH_TOUT_MAX;
+
+ device_for_each_child_node(flash->dev, node) {
+ fwnode_property_read_u32(node, "reg", ®);
+
+ if (reg == LM3560_LED0 || reg == LM3560_LED1) {
+ ret = device_property_read_u32(flash->dev,
+ "ti,max-flash-current",
+ &pdata->max_flash_brt[reg]);
+ if (ret)
+ pdata->max_flash_brt[reg] = LM3560_FLASH_TOUT_MAX;
+
+ ret = device_property_read_u32(flash->dev,
+ "ti,max-torch-current",
+ &pdata->max_torch_brt[reg]);
+ if (ret)
+ pdata->max_torch_brt[reg] = LM3560_TORCH_BRT_MAX;
+ }
+ }
+ flash->pdata = pdata;
+
+ return 0;
+}
+
static int lm3560_probe(struct i2c_client *client)
{
struct lm3560_flash *flash;
@@ -398,44 +450,41 @@ static int lm3560_probe(struct i2c_client *client)
int rval;
flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
- if (flash == NULL)
+ if (!flash)
return -ENOMEM;
flash->regmap = devm_regmap_init_i2c(client, &lm3560_regmap);
- if (IS_ERR(flash->regmap)) {
- rval = PTR_ERR(flash->regmap);
- return rval;
- }
+ if (IS_ERR(flash->regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(flash->regmap),
+ "failed to init regmap\n");
- /* if there is no platform data, use chip default value */
- if (pdata == NULL) {
- pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
- if (pdata == NULL)
- return -ENODEV;
- pdata->peak = LM3560_PEAK_3600mA;
- pdata->max_flash_timeout = LM3560_FLASH_TOUT_MAX;
- /* led 1 */
- pdata->max_flash_brt[LM3560_LED0] = LM3560_FLASH_BRT_MAX;
- pdata->max_torch_brt[LM3560_LED0] = LM3560_TORCH_BRT_MAX;
- /* led 2 */
- pdata->max_flash_brt[LM3560_LED1] = LM3560_FLASH_BRT_MAX;
- pdata->max_torch_brt[LM3560_LED1] = LM3560_TORCH_BRT_MAX;
- }
- flash->pdata = pdata;
flash->dev = &client->dev;
mutex_init(&flash->lock);
+ /* if there is no platform data, try to read from device tree */
+ if (!pdata)
+ lm3560_of_probe(flash);
+
+ flash->hwen_gpio = devm_gpiod_get_optional(flash->dev, "enable",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(flash->hwen_gpio))
+ return dev_err_probe(&client->dev, PTR_ERR(flash->hwen_gpio),
+ "failed to get hwen gpio\n");
+
rval = lm3560_subdev_init(flash, LM3560_LED0, "lm3560-led0");
if (rval < 0)
- return rval;
+ return dev_err_probe(&client->dev, rval,
+ "failed to init led0 subdev\n");
rval = lm3560_subdev_init(flash, LM3560_LED1, "lm3560-led1");
if (rval < 0)
- return rval;
+ return dev_err_probe(&client->dev, rval,
+ "failed to init led1 subdev\n");
rval = lm3560_init_device(flash);
if (rval < 0)
- return rval;
+ return dev_err_probe(&client->dev, rval,
+ "failed to init device\n");
i2c_set_clientdata(client, flash);
@@ -452,21 +501,30 @@ static void lm3560_remove(struct i2c_client *client)
v4l2_ctrl_handler_free(&flash->ctrls_led[i]);
media_entity_cleanup(&flash->subdev_led[i].entity);
}
+
+ gpiod_set_value_cansleep(flash->hwen_gpio, 0);
}
+static const struct of_device_id lm3560_match[] = {
+ { .compatible = "ti,lm3559" },
+ { .compatible = "ti,lm3560" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lm3560_match);
+
static const struct i2c_device_id lm3560_id_table[] = {
{LM3559_NAME, 0},
{LM3560_NAME, 0},
{}
};
-
MODULE_DEVICE_TABLE(i2c, lm3560_id_table);
static struct i2c_driver lm3560_i2c_driver = {
.driver = {
- .name = LM3560_NAME,
- .pm = NULL,
- },
+ .name = LM3560_NAME,
+ .pm = NULL,
+ .of_match_table = lm3560_match,
+ },
.probe_new = lm3560_probe,
.remove = lm3560_remove,
.id_table = lm3560_id_table,
--
2.37.2
On Wed, 08 Mar 2023 11:52:08 +0200, Svyatoslav Ryhel wrote:
> Signed-off-by: Svyatoslav Ryhel <[email protected]>
> ---
> .../bindings/media/i2c/ti,lm3560.yaml | 130 ++++++++++++++++++
> 1 file changed, 130 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/i2c/ti,lm3560.yaml
>
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
dtschema/dtc warnings/errors:
Error: Documentation/devicetree/bindings/media/i2c/ti,lm3560.example.dts:26.43-44 syntax error
FATAL ERROR: Unable to parse input tree
make[1]: *** [scripts/Makefile.lib:419: Documentation/devicetree/bindings/media/i2c/ti,lm3560.example.dtb] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1512: dt_binding_check] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/[email protected]
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
On Wed, Mar 08, 2023 at 11:52:08AM +0200, Svyatoslav Ryhel wrote:
> Signed-off-by: Svyatoslav Ryhel <[email protected]>
> ---
> .../bindings/media/i2c/ti,lm3560.yaml | 130 ++++++++++++++++++
> 1 file changed, 130 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/i2c/ti,lm3560.yaml
>
> diff --git a/Documentation/devicetree/bindings/media/i2c/ti,lm3560.yaml b/Documentation/devicetree/bindings/media/i2c/ti,lm3560.yaml
> new file mode 100644
> index 000000000000..b3c2ccb83a30
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/i2c/ti,lm3560.yaml
> @@ -0,0 +1,130 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/i2c/ti,lm3560.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: TI LM3560 Synchronous Boost Flash Driver
> +
> +maintainers:
> + - Daniel Jeong <[email protected]>
> + - Ldd-Mlp <[email protected]>
> +
> +description: |
> + The LM3560 is a 2-MHz fixed frequency synchronous boost
> + converter with two 1000-mA constant current drivers for
> + high-current white LEDs. The dual highside current sources
> + allow for grounded cathode LED operation and can be tied
> + together for providing flash currents at up to 2 A through
> + a single LED. An adaptive regulation method ensures the
> + current for each LED remains in regulation and maximizes
> + efficiency.
> +
> +properties:
> + compatible:
> + items:
> + - enum:
> + - ti,lm3559
> + - ti,lm3560
> +
> + reg:
> + maxItems: 1
> +
> + enable-gpios:
> + maxItems: 1
> +
> + ti,peak-current:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + enum: [0, 0x20, 0x40, 0x60]
> + default: 0x60
> + description: |
> + Peak current can be set to 4 values 1.6A (0x00),
> + 2.3A (0x20), 3.0A (0x40) and 3.6A (0x60).
Pretty sure we have common properties for this.
> +
> + ti,max-flash-timeout:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + minimum: 32
> + maximum: 1024
> + default: 1024
> + description: |
> + Maximum flash timeout in ms with step 32ms.
And this too.
> +
> + '#address-cells':
> + const: 1
> +
> + '#size-cells':
> + const: 0
> +
> +required:
> + - compatible
> + - reg
> + - '#address-cells'
> + - '#size-cells'
> +
> +patternProperties:
> + "^led@[01]$":
> + type: object
> + description: |
> + Properties for a connected LEDs.
> + properties:
> + reg:
> + minimum: 0
> + maximum: 1
> +
> + ti,max-flash-current:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + minimum: 62500
> + maximum: 1000000
> + default: 1000000
> + description: |
> + Maximum current in flash mode in uA with step 62500uA.
Or maybe it's these per LED settings that are common.
BTW, anything with units, should have a standard unit suffix.
> +
> + ti,max-torch-current:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + minimum: 31250
> + maximum: 250000
> + default: 250000
> + description: |
> + Maximum current in tourch mode in uA with step 31250uA.
> +
> + required:
> + - reg
> +
> + additionalProperties: false
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + flash-led@53 {
led-controller@53
> + compatible = "ti,lm3559";
> + reg = <0x53>;
> +
> + enable-gpios = <&gpio 219 GPIO_ACTIVE_HIGH>;
> +
> + ti,peak-current = <0>;
> + ti,max-flash-timeout = <1024>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + led@0 {
> + reg = <0>;
> +
> + ti,max-flash-current = <562500>;
> + ti,max-torch-current = <156250>;
> + };
> +
> + led@1 {
> + reg = <1>;
> +
> + ti,max-flash-current = <562500>;
> + ti,max-torch-current = <156250>;
> + };
> + };
> + };
> +...
> --
> 2.37.2
>
Hi Svyatoslav,
Thanks for the patch.
On Wed, Mar 08, 2023 at 11:52:09AM +0200, Svyatoslav Ryhel wrote:
> If no pdata is available, try to read from device tree.
I think platform data support could be even dropped these days. But it
should probably be a separate patch. I think either before or after this
one would be fine.
>
> Signed-off-by: Svyatoslav Ryhel <[email protected]>
> ---
> drivers/media/i2c/lm3560.c | 128 +++++++++++++++++++++++++++----------
> 1 file changed, 93 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c
> index 5ef613604be7..5541051616b7 100644
> --- a/drivers/media/i2c/lm3560.c
> +++ b/drivers/media/i2c/lm3560.c
> @@ -11,6 +11,7 @@
>
> #include <linux/delay.h>
> #include <linux/module.h>
> +#include <linux/gpio.h>
> #include <linux/i2c.h>
> #include <linux/slab.h>
> #include <linux/mutex.h>
> @@ -22,16 +23,16 @@
>
> /* registers definitions */
> #define REG_ENABLE 0x10
> -#define REG_TORCH_BR 0xa0
> -#define REG_FLASH_BR 0xb0
> -#define REG_FLASH_TOUT 0xc0
> +#define REG_TORCH_BR 0xa0
> +#define REG_FLASH_BR 0xb0
> +#define REG_FLASH_TOUT 0xc0
> #define REG_FLAG 0xd0
> #define REG_CONFIG1 0xe0
>
> /* fault mask */
> -#define FAULT_TIMEOUT (1<<0)
> -#define FAULT_OVERTEMP (1<<1)
> -#define FAULT_SHORT_CIRCUIT (1<<2)
> +#define FAULT_TIMEOUT BIT(0)
> +#define FAULT_OVERTEMP BIT(1)
> +#define FAULT_SHORT_CIRCUIT BIT(2)
>
> enum led_enable {
> MODE_SHDN = 0x0,
> @@ -54,6 +55,7 @@ struct lm3560_flash {
> struct device *dev;
> struct lm3560_platform_data *pdata;
> struct regmap *regmap;
> + struct gpio_desc *hwen_gpio;
> struct mutex lock;
>
> enum v4l2_flash_led_mode led_mode;
> @@ -356,12 +358,19 @@ static int lm3560_subdev_init(struct lm3560_flash *flash,
> flash->subdev_led[led_no].flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> strscpy(flash->subdev_led[led_no].name, led_name,
> sizeof(flash->subdev_led[led_no].name));
> +
> rval = lm3560_init_controls(flash, led_no);
> - if (rval)
> + if (rval) {
> + dev_err(flash->dev, "failed to init controls: %d\n", rval);
> goto err_out;
> + }
> +
> rval = media_entity_pads_init(&flash->subdev_led[led_no].entity, 0, NULL);
> - if (rval < 0)
> + if (rval < 0) {
> + dev_err(flash->dev, "failed to init media entity pads: %d\n", rval);
> goto err_out;
> + }
> +
> flash->subdev_led[led_no].entity.function = MEDIA_ENT_F_FLASH;
>
> return rval;
> @@ -391,6 +400,49 @@ static int lm3560_init_device(struct lm3560_flash *flash)
> return rval;
> }
>
> +static int lm3560_of_probe(struct lm3560_flash *flash)
> +{
> + struct lm3560_platform_data *pdata;
> + struct fwnode_handle *node;
> + int ret, reg;
> +
> + pdata = devm_kzalloc(flash->dev, sizeof(*pdata), GFP_KERNEL);
> + if (!pdata)
> + return -ENODEV;
> +
> + ret = device_property_read_u32(flash->dev,
> + "ti,peak-current", &pdata->peak);
> + if (ret)
> + pdata->peak = LM3560_PEAK_3600mA;
> +
> + ret = device_property_read_u32(flash->dev,
> + "ti,max-flash-timeout",
> + &pdata->max_flash_timeout);
> + if (ret)
> + pdata->max_flash_timeout = LM3560_FLASH_TOUT_MAX;
> +
> + device_for_each_child_node(flash->dev, node) {
> + fwnode_property_read_u32(node, "reg", ®);
> +
> + if (reg == LM3560_LED0 || reg == LM3560_LED1) {
> + ret = device_property_read_u32(flash->dev,
> + "ti,max-flash-current",
> + &pdata->max_flash_brt[reg]);
> + if (ret)
> + pdata->max_flash_brt[reg] = LM3560_FLASH_TOUT_MAX;
> +
> + ret = device_property_read_u32(flash->dev,
> + "ti,max-torch-current",
> + &pdata->max_torch_brt[reg]);
> + if (ret)
> + pdata->max_torch_brt[reg] = LM3560_TORCH_BRT_MAX;
> + }
> + }
> + flash->pdata = pdata;
> +
> + return 0;
> +}
> +
> static int lm3560_probe(struct i2c_client *client)
> {
> struct lm3560_flash *flash;
> @@ -398,44 +450,41 @@ static int lm3560_probe(struct i2c_client *client)
> int rval;
>
> flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
> - if (flash == NULL)
> + if (!flash)
> return -ENOMEM;
>
> flash->regmap = devm_regmap_init_i2c(client, &lm3560_regmap);
> - if (IS_ERR(flash->regmap)) {
> - rval = PTR_ERR(flash->regmap);
> - return rval;
> - }
> + if (IS_ERR(flash->regmap))
> + return dev_err_probe(&client->dev, PTR_ERR(flash->regmap),
> + "failed to init regmap\n");
>
> - /* if there is no platform data, use chip default value */
> - if (pdata == NULL) {
> - pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
> - if (pdata == NULL)
> - return -ENODEV;
> - pdata->peak = LM3560_PEAK_3600mA;
> - pdata->max_flash_timeout = LM3560_FLASH_TOUT_MAX;
> - /* led 1 */
> - pdata->max_flash_brt[LM3560_LED0] = LM3560_FLASH_BRT_MAX;
> - pdata->max_torch_brt[LM3560_LED0] = LM3560_TORCH_BRT_MAX;
> - /* led 2 */
> - pdata->max_flash_brt[LM3560_LED1] = LM3560_FLASH_BRT_MAX;
> - pdata->max_torch_brt[LM3560_LED1] = LM3560_TORCH_BRT_MAX;
> - }
> - flash->pdata = pdata;
> flash->dev = &client->dev;
> mutex_init(&flash->lock);
>
> + /* if there is no platform data, try to read from device tree */
> + if (!pdata)
> + lm3560_of_probe(flash);
> +
> + flash->hwen_gpio = devm_gpiod_get_optional(flash->dev, "enable",
> + GPIOD_OUT_HIGH);
> + if (IS_ERR(flash->hwen_gpio))
> + return dev_err_probe(&client->dev, PTR_ERR(flash->hwen_gpio),
> + "failed to get hwen gpio\n");
> +
> rval = lm3560_subdev_init(flash, LM3560_LED0, "lm3560-led0");
> if (rval < 0)
> - return rval;
> + return dev_err_probe(&client->dev, rval,
> + "failed to init led0 subdev\n");
>
> rval = lm3560_subdev_init(flash, LM3560_LED1, "lm3560-led1");
> if (rval < 0)
> - return rval;
> + return dev_err_probe(&client->dev, rval,
> + "failed to init led1 subdev\n");
>
> rval = lm3560_init_device(flash);
> if (rval < 0)
> - return rval;
> + return dev_err_probe(&client->dev, rval,
> + "failed to init device\n");
>
> i2c_set_clientdata(client, flash);
>
> @@ -452,21 +501,30 @@ static void lm3560_remove(struct i2c_client *client)
> v4l2_ctrl_handler_free(&flash->ctrls_led[i]);
> media_entity_cleanup(&flash->subdev_led[i].entity);
> }
> +
> + gpiod_set_value_cansleep(flash->hwen_gpio, 0);
> }
>
> +static const struct of_device_id lm3560_match[] = {
> + { .compatible = "ti,lm3559" },
> + { .compatible = "ti,lm3560" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, lm3560_match);
> +
> static const struct i2c_device_id lm3560_id_table[] = {
> {LM3559_NAME, 0},
> {LM3560_NAME, 0},
> {}
> };
> -
> MODULE_DEVICE_TABLE(i2c, lm3560_id_table);
>
> static struct i2c_driver lm3560_i2c_driver = {
> .driver = {
> - .name = LM3560_NAME,
> - .pm = NULL,
> - },
> + .name = LM3560_NAME,
> + .pm = NULL,
> + .of_match_table = lm3560_match,
> + },
> .probe_new = lm3560_probe,
> .remove = lm3560_remove,
> .id_table = lm3560_id_table,
--
Kind regards,
Sakari Ailus