1 // SPDX-License-Identifier: GPL-2.0-only
3 * LED driver for PCA995x I2C LED drivers
5 * Copyright 2011 bct electronic GmbH
6 * Copyright 2013 Qtechnology/AS
8 * Copyright 2023 Marek Vasut
11 #include <linux/i2c.h>
12 #include <linux/leds.h>
13 #include <linux/module.h>
14 #include <linux/mod_devicetable.h>
15 #include <linux/property.h>
16 #include <linux/regmap.h>
18 /* Register definition */
19 #define PCA995X_MODE1 0x00
20 #define PCA995X_MODE2 0x01
21 #define PCA995X_LEDOUT0 0x02
23 /* Auto-increment disabled. Normal mode */
24 #define PCA995X_MODE1_CFG 0x00
26 /* LED select registers determine the source that drives LED outputs */
27 #define PCA995X_LED_OFF 0x0
28 #define PCA995X_LED_ON 0x1
29 #define PCA995X_LED_PWM_MODE 0x2
30 #define PCA995X_LDRX_MASK 0x3
31 #define PCA995X_LDRX_BITS 2
33 #define PCA995X_MAX_OUTPUTS 24
34 #define PCA995X_OUTPUTS_PER_REG 4
36 #define PCA995X_IREFALL_FULL_CFG 0xFF
37 #define PCA995X_IREFALL_HALF_CFG (PCA995X_IREFALL_FULL_CFG / 2)
39 #define ldev_to_led(c) container_of(c, struct pca995x_led, ldev)
41 struct pca995x_chipdef
{
42 unsigned int num_leds
;
47 static const struct pca995x_chipdef pca9952_chipdef
= {
53 static const struct pca995x_chipdef pca9955b_chipdef
= {
59 static const struct pca995x_chipdef pca9956b_chipdef
= {
67 struct led_classdev ldev
;
68 struct pca995x_chip
*chip
;
72 struct regmap
*regmap
;
73 struct pca995x_led leds
[PCA995X_MAX_OUTPUTS
];
74 const struct pca995x_chipdef
*chipdef
;
77 static int pca995x_brightness_set(struct led_classdev
*led_cdev
,
78 enum led_brightness brightness
)
80 struct pca995x_led
*led
= ldev_to_led(led_cdev
);
81 struct pca995x_chip
*chip
= led
->chip
;
82 const struct pca995x_chipdef
*chipdef
= chip
->chipdef
;
83 u8 ledout_addr
, pwmout_addr
;
86 pwmout_addr
= chipdef
->pwm_base
+ led
->led_no
;
87 ledout_addr
= PCA995X_LEDOUT0
+ (led
->led_no
/ PCA995X_OUTPUTS_PER_REG
);
88 shift
= PCA995X_LDRX_BITS
* (led
->led_no
% PCA995X_OUTPUTS_PER_REG
);
92 return regmap_update_bits(chip
->regmap
, ledout_addr
,
93 PCA995X_LDRX_MASK
<< shift
,
94 PCA995X_LED_ON
<< shift
);
96 return regmap_update_bits(chip
->regmap
, ledout_addr
,
97 PCA995X_LDRX_MASK
<< shift
, 0);
99 /* Adjust brightness as per user input by changing individual PWM */
100 ret
= regmap_write(chip
->regmap
, pwmout_addr
, brightness
);
105 * Change LDRx configuration to individual brightness via PWM.
106 * LED will stop blinking if it's doing so.
108 return regmap_update_bits(chip
->regmap
, ledout_addr
,
109 PCA995X_LDRX_MASK
<< shift
,
110 PCA995X_LED_PWM_MODE
<< shift
);
114 static const struct regmap_config pca995x_regmap
= {
117 .max_register
= 0x49,
120 static int pca995x_probe(struct i2c_client
*client
)
122 struct fwnode_handle
*led_fwnodes
[PCA995X_MAX_OUTPUTS
] = { 0 };
123 struct device
*dev
= &client
->dev
;
124 const struct pca995x_chipdef
*chipdef
;
125 struct pca995x_chip
*chip
;
126 struct pca995x_led
*led
;
129 chipdef
= device_get_match_data(&client
->dev
);
131 if (!dev_fwnode(dev
))
134 chip
= devm_kzalloc(dev
, sizeof(*chip
), GFP_KERNEL
);
138 chip
->chipdef
= chipdef
;
139 chip
->regmap
= devm_regmap_init_i2c(client
, &pca995x_regmap
);
140 if (IS_ERR(chip
->regmap
))
141 return PTR_ERR(chip
->regmap
);
143 i2c_set_clientdata(client
, chip
);
145 device_for_each_child_node_scoped(dev
, child
) {
146 ret
= fwnode_property_read_u32(child
, "reg", ®
);
150 if (reg
< 0 || reg
>= PCA995X_MAX_OUTPUTS
|| led_fwnodes
[reg
])
153 led
= &chip
->leds
[reg
];
154 led_fwnodes
[reg
] = fwnode_handle_get(child
);
157 led
->ldev
.brightness_set_blocking
= pca995x_brightness_set
;
158 led
->ldev
.max_brightness
= 255;
161 for (i
= 0; i
< PCA995X_MAX_OUTPUTS
; i
++) {
162 struct led_init_data init_data
= {};
167 init_data
.fwnode
= led_fwnodes
[i
];
169 ret
= devm_led_classdev_register_ext(dev
,
173 for (j
= i
; j
< PCA995X_MAX_OUTPUTS
; j
++)
174 fwnode_handle_put(led_fwnodes
[j
]);
175 return dev_err_probe(dev
, ret
,
176 "Could not register LED %s\n",
177 chip
->leds
[i
].ldev
.name
);
181 /* Disable LED all-call address and set normal mode */
182 ret
= regmap_write(chip
->regmap
, PCA995X_MODE1
, PCA995X_MODE1_CFG
);
186 /* IREF Output current value for all LEDn outputs */
187 return regmap_write(chip
->regmap
, chipdef
->irefall
, PCA995X_IREFALL_HALF_CFG
);
190 static const struct i2c_device_id pca995x_id
[] = {
191 { "pca9952", .driver_data
= (kernel_ulong_t
)&pca9952_chipdef
},
192 { "pca9955b", .driver_data
= (kernel_ulong_t
)&pca9955b_chipdef
},
193 { "pca9956b", .driver_data
= (kernel_ulong_t
)&pca9956b_chipdef
},
196 MODULE_DEVICE_TABLE(i2c
, pca995x_id
);
198 static const struct of_device_id pca995x_of_match
[] = {
199 { .compatible
= "nxp,pca9952", .data
= &pca9952_chipdef
},
200 { .compatible
= "nxp,pca9955b", . data
= &pca9955b_chipdef
},
201 { .compatible
= "nxp,pca9956b", .data
= &pca9956b_chipdef
},
204 MODULE_DEVICE_TABLE(of
, pca995x_of_match
);
206 static struct i2c_driver pca995x_driver
= {
208 .name
= "leds-pca995x",
209 .of_match_table
= pca995x_of_match
,
211 .probe
= pca995x_probe
,
212 .id_table
= pca995x_id
,
214 module_i2c_driver(pca995x_driver
);
216 MODULE_AUTHOR("Isai Gaspar <isaiezequiel.gaspar@nxp.com>");
217 MODULE_DESCRIPTION("PCA995x LED driver");
218 MODULE_LICENSE("GPL");