1 // SPDX-License-Identifier: GPL-2.0
2 // TI LM36274 LED chip family driver
3 // Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/
5 #include <linux/bitops.h>
6 #include <linux/device.h>
8 #include <linux/leds.h>
9 #include <linux/leds-ti-lmu-common.h>
10 #include <linux/mod_devicetable.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <linux/property.h>
15 #include <linux/mfd/ti-lmu.h>
16 #include <linux/mfd/ti-lmu-register.h>
18 #include <uapi/linux/uleds.h>
20 #define LM36274_MAX_STRINGS 4
21 #define LM36274_BL_EN BIT(4)
25 * @pdev: platform device
26 * @led_dev: led class device
27 * @lmu_data: Register and setting values for common code
28 * @regmap: Devices register map
29 * @dev: Pointer to the devices device struct
30 * @led_sources: The LED strings supported in this array
31 * @num_leds: Number of LED strings are supported in this array
34 struct platform_device
*pdev
;
35 struct led_classdev led_dev
;
36 struct ti_lmu_bank lmu_data
;
37 struct regmap
*regmap
;
40 u32 led_sources
[LM36274_MAX_STRINGS
];
44 static int lm36274_brightness_set(struct led_classdev
*led_cdev
,
45 enum led_brightness brt_val
)
47 struct lm36274
*chip
= container_of(led_cdev
, struct lm36274
, led_dev
);
49 return ti_lmu_common_set_brightness(&chip
->lmu_data
, brt_val
);
52 static int lm36274_init(struct lm36274
*chip
)
57 for (i
= 0; i
< chip
->num_leds
; i
++)
58 enable_val
|= (1 << chip
->led_sources
[i
]);
61 dev_err(chip
->dev
, "No LEDs were enabled\n");
65 enable_val
|= LM36274_BL_EN
;
67 return regmap_write(chip
->regmap
, LM36274_REG_BL_EN
, enable_val
);
70 static int lm36274_parse_dt(struct lm36274
*chip
,
71 struct led_init_data
*init_data
)
73 struct device
*dev
= chip
->dev
;
74 struct fwnode_handle
*child
;
77 /* There should only be 1 node */
78 if (device_get_child_node_count(dev
) != 1)
81 child
= device_get_next_child_node(dev
, NULL
);
83 init_data
->fwnode
= child
;
84 init_data
->devicename
= chip
->pdev
->name
;
85 /* for backwards compatibility when `label` property is not present */
86 init_data
->default_label
= ":";
88 chip
->num_leds
= fwnode_property_count_u32(child
, "led-sources");
89 if (chip
->num_leds
<= 0) {
94 ret
= fwnode_property_read_u32_array(child
, "led-sources",
95 chip
->led_sources
, chip
->num_leds
);
97 dev_err(dev
, "led-sources property missing\n");
103 fwnode_handle_put(child
);
107 static int lm36274_probe(struct platform_device
*pdev
)
109 struct ti_lmu
*lmu
= dev_get_drvdata(pdev
->dev
.parent
);
110 struct led_init_data init_data
= {};
111 struct lm36274
*chip
;
114 chip
= devm_kzalloc(&pdev
->dev
, sizeof(*chip
), GFP_KERNEL
);
119 chip
->dev
= &pdev
->dev
;
120 chip
->regmap
= lmu
->regmap
;
121 platform_set_drvdata(pdev
, chip
);
123 ret
= lm36274_parse_dt(chip
, &init_data
);
125 dev_err(chip
->dev
, "Failed to parse DT node\n");
129 ret
= lm36274_init(chip
);
131 fwnode_handle_put(init_data
.fwnode
);
132 dev_err(chip
->dev
, "Failed to init the device\n");
136 chip
->lmu_data
.regmap
= chip
->regmap
;
137 chip
->lmu_data
.max_brightness
= MAX_BRIGHTNESS_11BIT
;
138 chip
->lmu_data
.msb_brightness_reg
= LM36274_REG_BRT_MSB
;
139 chip
->lmu_data
.lsb_brightness_reg
= LM36274_REG_BRT_LSB
;
141 chip
->led_dev
.max_brightness
= MAX_BRIGHTNESS_11BIT
;
142 chip
->led_dev
.brightness_set_blocking
= lm36274_brightness_set
;
144 ret
= devm_led_classdev_register_ext(chip
->dev
, &chip
->led_dev
,
147 dev_err(chip
->dev
, "Failed to register LED for node %pfw\n",
150 fwnode_handle_put(init_data
.fwnode
);
155 static const struct of_device_id of_lm36274_leds_match
[] = {
156 { .compatible
= "ti,lm36274-backlight", },
159 MODULE_DEVICE_TABLE(of
, of_lm36274_leds_match
);
161 static struct platform_driver lm36274_driver
= {
162 .probe
= lm36274_probe
,
164 .name
= "lm36274-leds",
165 .of_match_table
= of_lm36274_leds_match
,
168 module_platform_driver(lm36274_driver
)
170 MODULE_DESCRIPTION("Texas Instruments LM36274 LED driver");
171 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
172 MODULE_LICENSE("GPL v2");