1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/mfd/syscon.h>
4 #include <linux/mod_devicetable.h>
5 #include <linux/module.h>
7 #include <linux/platform_device.h>
8 #include <linux/property.h>
9 #include <linux/regmap.h>
11 #include "led-regfield.h"
14 * Realtek hardware system LED
16 * The switch SoC supports one hardware managed direct LED output
17 * to manage a system LED, with two supported blinking rates.
20 #define RTL838X_REG_LED_GLB_CTRL 0xa000
21 #define RTL839X_REG_LED_GLB_CTRL 0x00e4
22 #define RTL930X_REG_LED_GLB_CTRL 0xcc00
23 #define RTL931X_REG_LED_GLB_CTRL 0x0600
25 static const struct reg_field rtl838x_sys_led_field
= REG_FIELD(RTL838X_REG_LED_GLB_CTRL
, 16, 17);
26 static const struct reg_field rtl839x_sys_led_field
= REG_FIELD(RTL839X_REG_LED_GLB_CTRL
, 15, 16);
27 static const struct reg_field rtl930x_sys_led_field
= REG_FIELD(RTL930X_REG_LED_GLB_CTRL
, 13, 14);
28 static const struct reg_field rtl931x_sys_led_field
= REG_FIELD(RTL931X_REG_LED_GLB_CTRL
, 12, 13);
30 static const struct regfield_led_modes rtl_sys_led_modes
= {
40 static const struct of_device_id of_rtl_sys_led_match
[] = {
42 .compatible
= "realtek,maple-sys-led",
43 .data
= &rtl838x_sys_led_field
,
46 .compatible
= "realtek,cypress-sys-led",
47 .data
= &rtl839x_sys_led_field
,
50 .compatible
= "realtek,longan-sys-led",
51 .data
= &rtl930x_sys_led_field
,
54 .compatible
= "realtek,mango-sys-led",
55 .data
= &rtl931x_sys_led_field
,
59 MODULE_DEVICE_TABLE(of
, of_rtl_sys_led_match
);
61 static int rtl_sys_led_probe(struct platform_device
*pdev
)
63 struct device
*dev
= &pdev
->dev
;
64 struct device_node
*np
= dev
->of_node
;
65 struct led_init_data init_data
= {};
66 const struct reg_field
*field_data
;
67 struct regmap_field
*field
;
68 struct regfield_led
*led
;
72 map
= syscon_node_to_regmap(of_get_parent(dev
->of_node
));
74 return dev_err_probe(dev
, -ENXIO
, "failed to get regmap\n");
76 led
= devm_kzalloc(dev
, sizeof(*led
), GFP_KERNEL
);
80 field_data
= device_get_match_data(dev
);
81 field
= devm_regmap_field_alloc(dev
, map
, *field_data
);
83 return dev_err_probe(dev
, PTR_ERR(field
), "register field allocation failed\n");
85 err
= regfield_led_init(led
, field
, of_fwnode_handle(np
), &rtl_sys_led_modes
);
87 dev_err_probe(dev
, err
, "regfield_led initialisation failed\n");
89 init_data
.fwnode
= of_fwnode_handle(np
);
91 return devm_led_classdev_register_ext(dev
, &led
->cdev
, &init_data
);
94 static struct platform_driver rtl_sys_led_driver
= {
95 .probe
= rtl_sys_led_probe
,
97 .name
= "realtek-sys-led",
98 .of_match_table
= of_rtl_sys_led_match
,
101 module_platform_driver(rtl_sys_led_driver
);
103 MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");
104 MODULE_DESCRIPTION("Realtek switch SoC system LED driver");
105 MODULE_LICENSE("GPL v2");