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/module.h>
11 #include <linux/of_device.h>
12 #include <linux/platform_device.h>
14 #include <linux/mfd/ti-lmu.h>
15 #include <linux/mfd/ti-lmu-register.h>
17 #include <uapi/linux/uleds.h>
19 #define LM36274_MAX_STRINGS 4
20 #define LM36274_BL_EN BIT(4)
24 * @pdev: platform device
25 * @led_dev: led class device
26 * @lmu_data: Register and setting values for common code
27 * @regmap: Devices register map
28 * @dev: Pointer to the devices device struct
29 * @led_sources: The LED strings supported in this array
30 * @num_leds: Number of LED strings are supported in this array
33 struct platform_device
*pdev
;
34 struct led_classdev led_dev
;
35 struct ti_lmu_bank lmu_data
;
36 struct regmap
*regmap
;
39 u32 led_sources
[LM36274_MAX_STRINGS
];
43 static int lm36274_brightness_set(struct led_classdev
*led_cdev
,
44 enum led_brightness brt_val
)
46 struct lm36274
*chip
= container_of(led_cdev
, struct lm36274
, led_dev
);
48 return ti_lmu_common_set_brightness(&chip
->lmu_data
, brt_val
);
51 static int lm36274_init(struct lm36274
*chip
)
56 for (i
= 0; i
< chip
->num_leds
; i
++)
57 enable_val
|= (1 << chip
->led_sources
[i
]);
60 dev_err(chip
->dev
, "No LEDs were enabled\n");
64 enable_val
|= LM36274_BL_EN
;
66 return regmap_write(chip
->regmap
, LM36274_REG_BL_EN
, enable_val
);
69 static int lm36274_parse_dt(struct lm36274
*chip
,
70 struct led_init_data
*init_data
)
72 struct device
*dev
= chip
->dev
;
73 struct fwnode_handle
*child
;
76 /* There should only be 1 node */
77 if (device_get_child_node_count(dev
) != 1)
80 child
= device_get_next_child_node(dev
, NULL
);
82 init_data
->fwnode
= child
;
83 init_data
->devicename
= chip
->pdev
->name
;
84 /* for backwards compatibility when `label` property is not present */
85 init_data
->default_label
= ":";
87 chip
->num_leds
= fwnode_property_count_u32(child
, "led-sources");
88 if (chip
->num_leds
<= 0) {
93 ret
= fwnode_property_read_u32_array(child
, "led-sources",
94 chip
->led_sources
, chip
->num_leds
);
96 dev_err(dev
, "led-sources property missing\n");
102 fwnode_handle_put(child
);
106 static int lm36274_probe(struct platform_device
*pdev
)
108 struct ti_lmu
*lmu
= dev_get_drvdata(pdev
->dev
.parent
);
109 struct led_init_data init_data
= {};
110 struct lm36274
*chip
;
113 chip
= devm_kzalloc(&pdev
->dev
, sizeof(*chip
), GFP_KERNEL
);
118 chip
->dev
= &pdev
->dev
;
119 chip
->regmap
= lmu
->regmap
;
120 platform_set_drvdata(pdev
, chip
);
122 ret
= lm36274_parse_dt(chip
, &init_data
);
124 dev_err(chip
->dev
, "Failed to parse DT node\n");
128 ret
= lm36274_init(chip
);
130 dev_err(chip
->dev
, "Failed to init the device\n");
134 chip
->lmu_data
.regmap
= chip
->regmap
;
135 chip
->lmu_data
.max_brightness
= MAX_BRIGHTNESS_11BIT
;
136 chip
->lmu_data
.msb_brightness_reg
= LM36274_REG_BRT_MSB
;
137 chip
->lmu_data
.lsb_brightness_reg
= LM36274_REG_BRT_LSB
;
139 chip
->led_dev
.max_brightness
= MAX_BRIGHTNESS_11BIT
;
140 chip
->led_dev
.brightness_set_blocking
= lm36274_brightness_set
;
142 ret
= devm_led_classdev_register_ext(chip
->dev
, &chip
->led_dev
,
145 dev_err(chip
->dev
, "Failed to register LED for node %pfw\n",
148 fwnode_handle_put(init_data
.fwnode
);
153 static const struct of_device_id of_lm36274_leds_match
[] = {
154 { .compatible
= "ti,lm36274-backlight", },
157 MODULE_DEVICE_TABLE(of
, of_lm36274_leds_match
);
159 static struct platform_driver lm36274_driver
= {
160 .probe
= lm36274_probe
,
162 .name
= "lm36274-leds",
163 .of_match_table
= of_lm36274_leds_match
,
166 module_platform_driver(lm36274_driver
)
168 MODULE_DESCRIPTION("Texas Instruments LM36274 LED driver");
169 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
170 MODULE_LICENSE("GPL v2");