638 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Kinetic KTD2026/7 RGB/White LED driver with I2C interface4 *5 * Copyright 2023 André Apitzsch <git@apitzsch.eu>6 *7 * Datasheet: https://www.kinet-ic.com/uploads/KTD2026-7-04h.pdf8 */9 10#include <linux/i2c.h>11#include <linux/led-class-multicolor.h>12#include <linux/module.h>13#include <linux/mutex.h>14#include <linux/of.h>15#include <linux/of_device.h>16#include <linux/regmap.h>17#include <linux/regulator/consumer.h>18 19#define KTD2026_NUM_LEDS 320#define KTD2027_NUM_LEDS 421#define KTD202X_MAX_LEDS 422 23/* Register bank */24#define KTD202X_REG_RESET_CONTROL 0x0025#define KTD202X_REG_FLASH_PERIOD 0x0126#define KTD202X_REG_PWM1_TIMER 0x0227#define KTD202X_REG_PWM2_TIMER 0x0328#define KTD202X_REG_CHANNEL_CTRL 0x0429#define KTD202X_REG_TRISE_FALL 0x0530#define KTD202X_REG_LED_IOUT(x) (0x06 + (x))31 32/* Register 0 */33#define KTD202X_TIMER_SLOT_CONTROL_TSLOT1 0x0034#define KTD202X_TIMER_SLOT_CONTROL_TSLOT2 0x0135#define KTD202X_TIMER_SLOT_CONTROL_TSLOT3 0x0236#define KTD202X_TIMER_SLOT_CONTROL_TSLOT4 0x0337#define KTD202X_RSTR_RESET 0x0738 39#define KTD202X_ENABLE_CTRL_WAKE 0x00 /* SCL High & SDA High */40#define KTD202X_ENABLE_CTRL_SLEEP 0x08 /* SCL High & SDA Toggling */41 42#define KTD202X_TRISE_FALL_SCALE_NORMAL 0x0043#define KTD202X_TRISE_FALL_SCALE_SLOW_X2 0x2044#define KTD202X_TRISE_FALL_SCALE_SLOW_X4 0x4045#define KTD202X_TRISE_FALL_SCALE_FAST_X8 0x6046 47/* Register 1 */48#define KTD202X_FLASH_PERIOD_256_MS_LOG_RAMP 0x0049 50/* Register 2-3 */51#define KTD202X_FLASH_ON_TIME_0_4_PERCENT 0x0152 53/* Register 4 */54#define KTD202X_CHANNEL_CTRL_MASK(x) (BIT(2 * (x)) | BIT(2 * (x) + 1))55#define KTD202X_CHANNEL_CTRL_OFF 0x0056#define KTD202X_CHANNEL_CTRL_ON(x) BIT(2 * (x))57#define KTD202X_CHANNEL_CTRL_PWM1(x) BIT(2 * (x) + 1)58#define KTD202X_CHANNEL_CTRL_PWM2(x) (BIT(2 * (x)) | BIT(2 * (x) + 1))59 60/* Register 5 */61#define KTD202X_RAMP_TIMES_2_MS 0x0062 63/* Register 6-9 */64#define KTD202X_LED_CURRENT_10_mA 0x4f65 66#define KTD202X_FLASH_PERIOD_MIN_MS 25667#define KTD202X_FLASH_PERIOD_STEP_MS 12868#define KTD202X_FLASH_PERIOD_MAX_STEPS 12669#define KTD202X_FLASH_ON_MAX 25670 71#define KTD202X_MAX_BRIGHTNESS 19272 73static const struct reg_default ktd202x_reg_defaults[] = {74 { KTD202X_REG_RESET_CONTROL, KTD202X_TIMER_SLOT_CONTROL_TSLOT1 |75 KTD202X_ENABLE_CTRL_WAKE | KTD202X_TRISE_FALL_SCALE_NORMAL },76 { KTD202X_REG_FLASH_PERIOD, KTD202X_FLASH_PERIOD_256_MS_LOG_RAMP },77 { KTD202X_REG_PWM1_TIMER, KTD202X_FLASH_ON_TIME_0_4_PERCENT },78 { KTD202X_REG_PWM2_TIMER, KTD202X_FLASH_ON_TIME_0_4_PERCENT },79 { KTD202X_REG_CHANNEL_CTRL, KTD202X_CHANNEL_CTRL_OFF },80 { KTD202X_REG_TRISE_FALL, KTD202X_RAMP_TIMES_2_MS },81 { KTD202X_REG_LED_IOUT(0), KTD202X_LED_CURRENT_10_mA },82 { KTD202X_REG_LED_IOUT(1), KTD202X_LED_CURRENT_10_mA },83 { KTD202X_REG_LED_IOUT(2), KTD202X_LED_CURRENT_10_mA },84 { KTD202X_REG_LED_IOUT(3), KTD202X_LED_CURRENT_10_mA },85};86 87struct ktd202x_led {88 struct ktd202x *chip;89 union {90 struct led_classdev cdev;91 struct led_classdev_mc mcdev;92 };93 u32 index;94};95 96struct ktd202x {97 struct mutex mutex;98 struct regulator_bulk_data regulators[2];99 struct device *dev;100 struct regmap *regmap;101 bool enabled;102 unsigned long num_leds;103 struct ktd202x_led leds[] __counted_by(num_leds);104};105 106static int ktd202x_chip_disable(struct ktd202x *chip)107{108 int ret;109 110 if (!chip->enabled)111 return 0;112 113 regmap_write(chip->regmap, KTD202X_REG_RESET_CONTROL, KTD202X_ENABLE_CTRL_SLEEP);114 115 ret = regulator_bulk_disable(ARRAY_SIZE(chip->regulators), chip->regulators);116 if (ret) {117 dev_err(chip->dev, "Failed to disable regulators: %d\n", ret);118 return ret;119 }120 121 chip->enabled = false;122 return 0;123}124 125static int ktd202x_chip_enable(struct ktd202x *chip)126{127 int ret;128 129 if (chip->enabled)130 return 0;131 132 ret = regulator_bulk_enable(ARRAY_SIZE(chip->regulators), chip->regulators);133 if (ret) {134 dev_err(chip->dev, "Failed to enable regulators: %d\n", ret);135 return ret;136 }137 chip->enabled = true;138 139 ret = regmap_write(chip->regmap, KTD202X_REG_RESET_CONTROL, KTD202X_ENABLE_CTRL_WAKE);140 141 if (ret) {142 dev_err(chip->dev, "Failed to enable the chip: %d\n", ret);143 ktd202x_chip_disable(chip);144 }145 146 return ret;147}148 149static bool ktd202x_chip_in_use(struct ktd202x *chip)150{151 int i;152 153 for (i = 0; i < chip->num_leds; i++) {154 if (chip->leds[i].cdev.brightness)155 return true;156 }157 158 return false;159}160 161static int ktd202x_brightness_set(struct ktd202x_led *led,162 struct mc_subled *subleds,163 unsigned int num_channels)164{165 bool mode_blink = false;166 int channel;167 int state;168 int ret;169 int i;170 171 if (ktd202x_chip_in_use(led->chip)) {172 ret = ktd202x_chip_enable(led->chip);173 if (ret)174 return ret;175 }176 177 ret = regmap_read(led->chip->regmap, KTD202X_REG_CHANNEL_CTRL, &state);178 if (ret)179 return ret;180 181 /*182 * In multicolor case, assume blink mode if PWM is set for at least one183 * channel because another channel cannot be in state ON at the same time184 */185 for (i = 0; i < num_channels; i++) {186 int channel_state;187 188 channel = subleds[i].channel;189 channel_state = (state >> 2 * channel) & KTD202X_CHANNEL_CTRL_MASK(0);190 if (channel_state == KTD202X_CHANNEL_CTRL_OFF)191 continue;192 mode_blink = channel_state == KTD202X_CHANNEL_CTRL_PWM1(0);193 break;194 }195 196 for (i = 0; i < num_channels; i++) {197 enum led_brightness brightness;198 int mode;199 200 brightness = subleds[i].brightness;201 channel = subleds[i].channel;202 203 if (brightness) {204 /* Register expects brightness between 0 and MAX_BRIGHTNESS - 1 */205 ret = regmap_write(led->chip->regmap, KTD202X_REG_LED_IOUT(channel),206 brightness - 1);207 if (ret)208 return ret;209 210 if (mode_blink)211 mode = KTD202X_CHANNEL_CTRL_PWM1(channel);212 else213 mode = KTD202X_CHANNEL_CTRL_ON(channel);214 } else {215 mode = KTD202X_CHANNEL_CTRL_OFF;216 }217 ret = regmap_update_bits(led->chip->regmap, KTD202X_REG_CHANNEL_CTRL,218 KTD202X_CHANNEL_CTRL_MASK(channel), mode);219 if (ret)220 return ret;221 }222 223 if (!ktd202x_chip_in_use(led->chip))224 return ktd202x_chip_disable(led->chip);225 226 return 0;227}228 229static int ktd202x_brightness_single_set(struct led_classdev *cdev,230 enum led_brightness value)231{232 struct ktd202x_led *led = container_of(cdev, struct ktd202x_led, cdev);233 struct mc_subled info;234 int ret;235 236 cdev->brightness = value;237 238 mutex_lock(&led->chip->mutex);239 240 info.brightness = value;241 info.channel = led->index;242 ret = ktd202x_brightness_set(led, &info, 1);243 244 mutex_unlock(&led->chip->mutex);245 246 return ret;247}248 249static int ktd202x_brightness_mc_set(struct led_classdev *cdev,250 enum led_brightness value)251{252 struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);253 struct ktd202x_led *led = container_of(mc, struct ktd202x_led, mcdev);254 int ret;255 256 cdev->brightness = value;257 258 mutex_lock(&led->chip->mutex);259 260 led_mc_calc_color_components(mc, value);261 ret = ktd202x_brightness_set(led, mc->subled_info, mc->num_colors);262 263 mutex_unlock(&led->chip->mutex);264 265 return ret;266}267 268static int ktd202x_blink_set(struct ktd202x_led *led, unsigned long *delay_on,269 unsigned long *delay_off, struct mc_subled *subleds,270 unsigned int num_channels)271{272 unsigned long delay_total_ms;273 int ret, num_steps, on;274 u8 ctrl_mask = 0;275 u8 ctrl_pwm1 = 0;276 u8 ctrl_on = 0;277 int i;278 279 mutex_lock(&led->chip->mutex);280 281 for (i = 0; i < num_channels; i++) {282 int channel = subleds[i].channel;283 284 ctrl_mask |= KTD202X_CHANNEL_CTRL_MASK(channel);285 ctrl_on |= KTD202X_CHANNEL_CTRL_ON(channel);286 ctrl_pwm1 |= KTD202X_CHANNEL_CTRL_PWM1(channel);287 }288 289 /* Never off - brightness is already set, disable blinking */290 if (!*delay_off) {291 ret = regmap_update_bits(led->chip->regmap, KTD202X_REG_CHANNEL_CTRL,292 ctrl_mask, ctrl_on);293 goto out;294 }295 296 /* Convert into values the HW will understand. */297 298 /* Integer representation of time of flash period */299 num_steps = (*delay_on + *delay_off - KTD202X_FLASH_PERIOD_MIN_MS) /300 KTD202X_FLASH_PERIOD_STEP_MS;301 num_steps = clamp(num_steps, 0, KTD202X_FLASH_PERIOD_MAX_STEPS);302 303 /* Integer representation of percentage of LED ON time */304 on = (*delay_on * KTD202X_FLASH_ON_MAX) / (*delay_on + *delay_off);305 306 /* Actually used delay_{on,off} values */307 delay_total_ms = num_steps * KTD202X_FLASH_PERIOD_STEP_MS + KTD202X_FLASH_PERIOD_MIN_MS;308 *delay_on = (delay_total_ms * on) / KTD202X_FLASH_ON_MAX;309 *delay_off = delay_total_ms - *delay_on;310 311 /* Set timings */312 ret = regmap_write(led->chip->regmap, KTD202X_REG_FLASH_PERIOD, num_steps);313 if (ret)314 goto out;315 316 ret = regmap_write(led->chip->regmap, KTD202X_REG_PWM1_TIMER, on);317 if (ret)318 goto out;319 320 ret = regmap_update_bits(led->chip->regmap, KTD202X_REG_CHANNEL_CTRL,321 ctrl_mask, ctrl_pwm1);322out:323 mutex_unlock(&led->chip->mutex);324 return ret;325}326 327static int ktd202x_blink_single_set(struct led_classdev *cdev,328 unsigned long *delay_on,329 unsigned long *delay_off)330{331 struct ktd202x_led *led = container_of(cdev, struct ktd202x_led, cdev);332 struct mc_subled info;333 int ret;334 335 if (!cdev->brightness) {336 ret = ktd202x_brightness_single_set(cdev, KTD202X_MAX_BRIGHTNESS);337 if (ret)338 return ret;339 }340 341 /* If no blink specified, default to 1 Hz. */342 if (!*delay_off && !*delay_on) {343 *delay_off = 500;344 *delay_on = 500;345 }346 347 /* Never on - just set to off */348 if (!*delay_on)349 return ktd202x_brightness_single_set(cdev, LED_OFF);350 351 info.channel = led->index;352 353 return ktd202x_blink_set(led, delay_on, delay_off, &info, 1);354}355 356static int ktd202x_blink_mc_set(struct led_classdev *cdev,357 unsigned long *delay_on,358 unsigned long *delay_off)359{360 struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);361 struct ktd202x_led *led = container_of(mc, struct ktd202x_led, mcdev);362 int ret;363 364 if (!cdev->brightness) {365 ret = ktd202x_brightness_mc_set(cdev, KTD202X_MAX_BRIGHTNESS);366 if (ret)367 return ret;368 }369 370 /* If no blink specified, default to 1 Hz. */371 if (!*delay_off && !*delay_on) {372 *delay_off = 500;373 *delay_on = 500;374 }375 376 /* Never on - just set to off */377 if (!*delay_on)378 return ktd202x_brightness_mc_set(cdev, LED_OFF);379 380 return ktd202x_blink_set(led, delay_on, delay_off, mc->subled_info,381 mc->num_colors);382}383 384static int ktd202x_setup_led_rgb(struct ktd202x *chip, struct fwnode_handle *fwnode,385 struct ktd202x_led *led, struct led_init_data *init_data)386{387 struct fwnode_handle *child;388 struct led_classdev *cdev;389 struct mc_subled *info;390 int num_channels;391 int i = 0;392 393 num_channels = 0;394 fwnode_for_each_available_child_node(fwnode, child)395 num_channels++;396 397 if (!num_channels || num_channels > chip->num_leds)398 return -EINVAL;399 400 info = devm_kcalloc(chip->dev, num_channels, sizeof(*info), GFP_KERNEL);401 if (!info)402 return -ENOMEM;403 404 fwnode_for_each_available_child_node(fwnode, child) {405 u32 mono_color;406 u32 reg;407 int ret;408 409 ret = fwnode_property_read_u32(child, "reg", ®);410 if (ret != 0 || reg >= chip->num_leds) {411 dev_err(chip->dev, "invalid 'reg' of %pfw\n", child);412 fwnode_handle_put(child);413 return ret;414 }415 416 ret = fwnode_property_read_u32(child, "color", &mono_color);417 if (ret < 0 && ret != -EINVAL) {418 dev_err(chip->dev, "failed to parse 'color' of %pfw\n", child);419 fwnode_handle_put(child);420 return ret;421 }422 423 info[i].color_index = mono_color;424 info[i].channel = reg;425 info[i].intensity = KTD202X_MAX_BRIGHTNESS;426 i++;427 }428 429 led->mcdev.subled_info = info;430 led->mcdev.num_colors = num_channels;431 432 cdev = &led->mcdev.led_cdev;433 cdev->brightness_set_blocking = ktd202x_brightness_mc_set;434 cdev->blink_set = ktd202x_blink_mc_set;435 436 return devm_led_classdev_multicolor_register_ext(chip->dev, &led->mcdev, init_data);437}438 439static int ktd202x_setup_led_single(struct ktd202x *chip, struct fwnode_handle *fwnode,440 struct ktd202x_led *led, struct led_init_data *init_data)441{442 struct led_classdev *cdev;443 u32 reg;444 int ret;445 446 ret = fwnode_property_read_u32(fwnode, "reg", ®);447 if (ret != 0 || reg >= chip->num_leds) {448 dev_err(chip->dev, "invalid 'reg' of %pfw\n", fwnode);449 return -EINVAL;450 }451 led->index = reg;452 453 cdev = &led->cdev;454 cdev->brightness_set_blocking = ktd202x_brightness_single_set;455 cdev->blink_set = ktd202x_blink_single_set;456 457 return devm_led_classdev_register_ext(chip->dev, &led->cdev, init_data);458}459 460static int ktd202x_add_led(struct ktd202x *chip, struct fwnode_handle *fwnode, unsigned int index)461{462 struct ktd202x_led *led = &chip->leds[index];463 struct led_init_data init_data = {};464 struct led_classdev *cdev;465 u32 color;466 int ret;467 468 /* Color property is optional in single color case */469 ret = fwnode_property_read_u32(fwnode, "color", &color);470 if (ret < 0 && ret != -EINVAL) {471 dev_err(chip->dev, "failed to parse 'color' of %pfw\n", fwnode);472 return ret;473 }474 475 led->chip = chip;476 init_data.fwnode = fwnode;477 478 if (color == LED_COLOR_ID_RGB) {479 cdev = &led->mcdev.led_cdev;480 ret = ktd202x_setup_led_rgb(chip, fwnode, led, &init_data);481 } else {482 cdev = &led->cdev;483 ret = ktd202x_setup_led_single(chip, fwnode, led, &init_data);484 }485 486 if (ret) {487 dev_err(chip->dev, "unable to register %s\n", cdev->name);488 return ret;489 }490 491 cdev->max_brightness = KTD202X_MAX_BRIGHTNESS;492 493 return 0;494}495 496static int ktd202x_probe_fw(struct ktd202x *chip)497{498 struct fwnode_handle *child;499 struct device *dev = chip->dev;500 int count;501 int i = 0;502 503 count = device_get_child_node_count(dev);504 if (!count || count > chip->num_leds)505 return -EINVAL;506 507 regmap_write(chip->regmap, KTD202X_REG_RESET_CONTROL, KTD202X_RSTR_RESET);508 509 /* Allow the device to execute the complete reset */510 usleep_range(200, 300);511 512 device_for_each_child_node(dev, child) {513 int ret = ktd202x_add_led(chip, child, i);514 515 if (ret) {516 fwnode_handle_put(child);517 return ret;518 }519 i++;520 }521 522 return 0;523}524 525static const struct regmap_config ktd202x_regmap_config = {526 .reg_bits = 8,527 .val_bits = 8,528 .max_register = 0x09,529 .cache_type = REGCACHE_FLAT,530 .reg_defaults = ktd202x_reg_defaults,531 .num_reg_defaults = ARRAY_SIZE(ktd202x_reg_defaults),532};533 534static int ktd202x_probe(struct i2c_client *client)535{536 struct device *dev = &client->dev;537 struct ktd202x *chip;538 int count;539 int ret;540 541 count = device_get_child_node_count(dev);542 if (!count || count > KTD202X_MAX_LEDS)543 return dev_err_probe(dev, -EINVAL, "Incorrect number of leds (%d)", count);544 545 chip = devm_kzalloc(dev, struct_size(chip, leds, count), GFP_KERNEL);546 if (!chip)547 return -ENOMEM;548 549 chip->dev = dev;550 i2c_set_clientdata(client, chip);551 552 chip->regmap = devm_regmap_init_i2c(client, &ktd202x_regmap_config);553 if (IS_ERR(chip->regmap)) {554 ret = dev_err_probe(dev, PTR_ERR(chip->regmap),555 "Failed to allocate register map.\n");556 return ret;557 }558 559 ret = devm_mutex_init(dev, &chip->mutex);560 if (ret)561 return ret;562 563 chip->num_leds = (unsigned long)i2c_get_match_data(client);564 565 chip->regulators[0].supply = "vin";566 chip->regulators[1].supply = "vio";567 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(chip->regulators), chip->regulators);568 if (ret < 0) {569 dev_err_probe(dev, ret, "Failed to request regulators.\n");570 return ret;571 }572 573 ret = regulator_bulk_enable(ARRAY_SIZE(chip->regulators), chip->regulators);574 if (ret) {575 dev_err_probe(dev, ret, "Failed to enable regulators.\n");576 return ret;577 }578 579 ret = ktd202x_probe_fw(chip);580 if (ret < 0) {581 regulator_bulk_disable(ARRAY_SIZE(chip->regulators), chip->regulators);582 return ret;583 }584 585 ret = regulator_bulk_disable(ARRAY_SIZE(chip->regulators), chip->regulators);586 if (ret) {587 dev_err_probe(dev, ret, "Failed to disable regulators.\n");588 return ret;589 }590 591 return 0;592}593 594static void ktd202x_remove(struct i2c_client *client)595{596 struct ktd202x *chip = i2c_get_clientdata(client);597 598 ktd202x_chip_disable(chip);599}600 601static void ktd202x_shutdown(struct i2c_client *client)602{603 struct ktd202x *chip = i2c_get_clientdata(client);604 605 /* Reset registers to make sure all LEDs are off before shutdown */606 regmap_write(chip->regmap, KTD202X_REG_RESET_CONTROL, KTD202X_RSTR_RESET);607}608 609static const struct i2c_device_id ktd202x_id[] = {610 {"ktd2026", KTD2026_NUM_LEDS},611 {"ktd2027", KTD2027_NUM_LEDS},612 {}613};614MODULE_DEVICE_TABLE(i2c, ktd202x_id);615 616static const struct of_device_id ktd202x_match_table[] = {617 { .compatible = "kinetic,ktd2026", .data = (void *)KTD2026_NUM_LEDS },618 { .compatible = "kinetic,ktd2027", .data = (void *)KTD2027_NUM_LEDS },619 {}620};621MODULE_DEVICE_TABLE(of, ktd202x_match_table);622 623static struct i2c_driver ktd202x_driver = {624 .driver = {625 .name = "leds-ktd202x",626 .of_match_table = ktd202x_match_table,627 },628 .probe = ktd202x_probe,629 .remove = ktd202x_remove,630 .shutdown = ktd202x_shutdown,631 .id_table = ktd202x_id,632};633module_i2c_driver(ktd202x_driver);634 635MODULE_AUTHOR("André Apitzsch <git@apitzsch.eu>");636MODULE_DESCRIPTION("Kinetic KTD2026/7 LED driver");637MODULE_LICENSE("GPL");638