linux/drivers/leds/leds-lp55xx-common.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * LP5521/LP5523/LP55231/LP5562 Common Driver
   4 *
   5 * Copyright 2012 Texas Instruments
   6 *
   7 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
   8 *
   9 * Derived from leds-lp5521.c, leds-lp5523.c
  10 */
  11
  12#include <linux/clk.h>
  13#include <linux/delay.h>
  14#include <linux/firmware.h>
  15#include <linux/i2c.h>
  16#include <linux/leds.h>
  17#include <linux/module.h>
  18#include <linux/platform_data/leds-lp55xx.h>
  19#include <linux/slab.h>
  20#include <linux/gpio.h>
  21#include <linux/of_gpio.h>
  22
  23#include "leds-lp55xx-common.h"
  24
  25/* External clock rate */
  26#define LP55XX_CLK_32K                  32768
  27
  28static struct lp55xx_led *cdev_to_lp55xx_led(struct led_classdev *cdev)
  29{
  30        return container_of(cdev, struct lp55xx_led, cdev);
  31}
  32
  33static struct lp55xx_led *dev_to_lp55xx_led(struct device *dev)
  34{
  35        return cdev_to_lp55xx_led(dev_get_drvdata(dev));
  36}
  37
  38static void lp55xx_reset_device(struct lp55xx_chip *chip)
  39{
  40        struct lp55xx_device_config *cfg = chip->cfg;
  41        u8 addr = cfg->reset.addr;
  42        u8 val  = cfg->reset.val;
  43
  44        /* no error checking here because no ACK from the device after reset */
  45        lp55xx_write(chip, addr, val);
  46}
  47
  48static int lp55xx_detect_device(struct lp55xx_chip *chip)
  49{
  50        struct lp55xx_device_config *cfg = chip->cfg;
  51        u8 addr = cfg->enable.addr;
  52        u8 val  = cfg->enable.val;
  53        int ret;
  54
  55        ret = lp55xx_write(chip, addr, val);
  56        if (ret)
  57                return ret;
  58
  59        usleep_range(1000, 2000);
  60
  61        ret = lp55xx_read(chip, addr, &val);
  62        if (ret)
  63                return ret;
  64
  65        if (val != cfg->enable.val)
  66                return -ENODEV;
  67
  68        return 0;
  69}
  70
  71static int lp55xx_post_init_device(struct lp55xx_chip *chip)
  72{
  73        struct lp55xx_device_config *cfg = chip->cfg;
  74
  75        if (!cfg->post_init_device)
  76                return 0;
  77
  78        return cfg->post_init_device(chip);
  79}
  80
  81static ssize_t lp55xx_show_current(struct device *dev,
  82                            struct device_attribute *attr,
  83                            char *buf)
  84{
  85        struct lp55xx_led *led = dev_to_lp55xx_led(dev);
  86
  87        return scnprintf(buf, PAGE_SIZE, "%d\n", led->led_current);
  88}
  89
  90static ssize_t lp55xx_store_current(struct device *dev,
  91                             struct device_attribute *attr,
  92                             const char *buf, size_t len)
  93{
  94        struct lp55xx_led *led = dev_to_lp55xx_led(dev);
  95        struct lp55xx_chip *chip = led->chip;
  96        unsigned long curr;
  97
  98        if (kstrtoul(buf, 0, &curr))
  99                return -EINVAL;
 100
 101        if (curr > led->max_current)
 102                return -EINVAL;
 103
 104        if (!chip->cfg->set_led_current)
 105                return len;
 106
 107        mutex_lock(&chip->lock);
 108        chip->cfg->set_led_current(led, (u8)curr);
 109        mutex_unlock(&chip->lock);
 110
 111        return len;
 112}
 113
 114static ssize_t lp55xx_show_max_current(struct device *dev,
 115                            struct device_attribute *attr,
 116                            char *buf)
 117{
 118        struct lp55xx_led *led = dev_to_lp55xx_led(dev);
 119
 120        return scnprintf(buf, PAGE_SIZE, "%d\n", led->max_current);
 121}
 122
 123static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, lp55xx_show_current,
 124                lp55xx_store_current);
 125static DEVICE_ATTR(max_current, S_IRUGO , lp55xx_show_max_current, NULL);
 126
 127static struct attribute *lp55xx_led_attrs[] = {
 128        &dev_attr_led_current.attr,
 129        &dev_attr_max_current.attr,
 130        NULL,
 131};
 132ATTRIBUTE_GROUPS(lp55xx_led);
 133
 134static int lp55xx_set_brightness(struct led_classdev *cdev,
 135                             enum led_brightness brightness)
 136{
 137        struct lp55xx_led *led = cdev_to_lp55xx_led(cdev);
 138        struct lp55xx_device_config *cfg = led->chip->cfg;
 139
 140        led->brightness = (u8)brightness;
 141        return cfg->brightness_fn(led);
 142}
 143
 144static int lp55xx_init_led(struct lp55xx_led *led,
 145                        struct lp55xx_chip *chip, int chan)
 146{
 147        struct lp55xx_platform_data *pdata = chip->pdata;
 148        struct lp55xx_device_config *cfg = chip->cfg;
 149        struct device *dev = &chip->cl->dev;
 150        char name[32];
 151        int ret;
 152        int max_channel = cfg->max_channel;
 153
 154        if (chan >= max_channel) {
 155                dev_err(dev, "invalid channel: %d / %d\n", chan, max_channel);
 156                return -EINVAL;
 157        }
 158
 159        if (pdata->led_config[chan].led_current == 0)
 160                return 0;
 161
 162        led->led_current = pdata->led_config[chan].led_current;
 163        led->max_current = pdata->led_config[chan].max_current;
 164        led->chan_nr = pdata->led_config[chan].chan_nr;
 165        led->cdev.default_trigger = pdata->led_config[chan].default_trigger;
 166
 167        if (led->chan_nr >= max_channel) {
 168                dev_err(dev, "Use channel numbers between 0 and %d\n",
 169                        max_channel - 1);
 170                return -EINVAL;
 171        }
 172
 173        led->cdev.brightness_set_blocking = lp55xx_set_brightness;
 174        led->cdev.groups = lp55xx_led_groups;
 175
 176        if (pdata->led_config[chan].name) {
 177                led->cdev.name = pdata->led_config[chan].name;
 178        } else {
 179                snprintf(name, sizeof(name), "%s:channel%d",
 180                        pdata->label ? : chip->cl->name, chan);
 181                led->cdev.name = name;
 182        }
 183
 184        ret = led_classdev_register(dev, &led->cdev);
 185        if (ret) {
 186                dev_err(dev, "led register err: %d\n", ret);
 187                return ret;
 188        }
 189
 190        return 0;
 191}
 192
 193static void lp55xx_firmware_loaded(const struct firmware *fw, void *context)
 194{
 195        struct lp55xx_chip *chip = context;
 196        struct device *dev = &chip->cl->dev;
 197        enum lp55xx_engine_index idx = chip->engine_idx;
 198
 199        if (!fw) {
 200                dev_err(dev, "firmware request failed\n");
 201                return;
 202        }
 203
 204        /* handling firmware data is chip dependent */
 205        mutex_lock(&chip->lock);
 206
 207        chip->engines[idx - 1].mode = LP55XX_ENGINE_LOAD;
 208        chip->fw = fw;
 209        if (chip->cfg->firmware_cb)
 210                chip->cfg->firmware_cb(chip);
 211
 212        mutex_unlock(&chip->lock);
 213
 214        /* firmware should be released for other channel use */
 215        release_firmware(chip->fw);
 216        chip->fw = NULL;
 217}
 218
 219static int lp55xx_request_firmware(struct lp55xx_chip *chip)
 220{
 221        const char *name = chip->cl->name;
 222        struct device *dev = &chip->cl->dev;
 223
 224        return request_firmware_nowait(THIS_MODULE, false, name, dev,
 225                                GFP_KERNEL, chip, lp55xx_firmware_loaded);
 226}
 227
 228static ssize_t lp55xx_show_engine_select(struct device *dev,
 229                            struct device_attribute *attr,
 230                            char *buf)
 231{
 232        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
 233        struct lp55xx_chip *chip = led->chip;
 234
 235        return sprintf(buf, "%d\n", chip->engine_idx);
 236}
 237
 238static ssize_t lp55xx_store_engine_select(struct device *dev,
 239                             struct device_attribute *attr,
 240                             const char *buf, size_t len)
 241{
 242        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
 243        struct lp55xx_chip *chip = led->chip;
 244        unsigned long val;
 245        int ret;
 246
 247        if (kstrtoul(buf, 0, &val))
 248                return -EINVAL;
 249
 250        /* select the engine to be run */
 251
 252        switch (val) {
 253        case LP55XX_ENGINE_1:
 254        case LP55XX_ENGINE_2:
 255        case LP55XX_ENGINE_3:
 256                mutex_lock(&chip->lock);
 257                chip->engine_idx = val;
 258                ret = lp55xx_request_firmware(chip);
 259                mutex_unlock(&chip->lock);
 260                break;
 261        default:
 262                dev_err(dev, "%lu: invalid engine index. (1, 2, 3)\n", val);
 263                return -EINVAL;
 264        }
 265
 266        if (ret) {
 267                dev_err(dev, "request firmware err: %d\n", ret);
 268                return ret;
 269        }
 270
 271        return len;
 272}
 273
 274static inline void lp55xx_run_engine(struct lp55xx_chip *chip, bool start)
 275{
 276        if (chip->cfg->run_engine)
 277                chip->cfg->run_engine(chip, start);
 278}
 279
 280static ssize_t lp55xx_store_engine_run(struct device *dev,
 281                             struct device_attribute *attr,
 282                             const char *buf, size_t len)
 283{
 284        struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
 285        struct lp55xx_chip *chip = led->chip;
 286        unsigned long val;
 287
 288        if (kstrtoul(buf, 0, &val))
 289                return -EINVAL;
 290
 291        /* run or stop the selected engine */
 292
 293        if (val <= 0) {
 294                lp55xx_run_engine(chip, false);
 295                return len;
 296        }
 297
 298        mutex_lock(&chip->lock);
 299        lp55xx_run_engine(chip, true);
 300        mutex_unlock(&chip->lock);
 301
 302        return len;
 303}
 304
 305static DEVICE_ATTR(select_engine, S_IRUGO | S_IWUSR,
 306                   lp55xx_show_engine_select, lp55xx_store_engine_select);
 307static DEVICE_ATTR(run_engine, S_IWUSR, NULL, lp55xx_store_engine_run);
 308
 309static struct attribute *lp55xx_engine_attributes[] = {
 310        &dev_attr_select_engine.attr,
 311        &dev_attr_run_engine.attr,
 312        NULL,
 313};
 314
 315static const struct attribute_group lp55xx_engine_attr_group = {
 316        .attrs = lp55xx_engine_attributes,
 317};
 318
 319int lp55xx_write(struct lp55xx_chip *chip, u8 reg, u8 val)
 320{
 321        return i2c_smbus_write_byte_data(chip->cl, reg, val);
 322}
 323EXPORT_SYMBOL_GPL(lp55xx_write);
 324
 325int lp55xx_read(struct lp55xx_chip *chip, u8 reg, u8 *val)
 326{
 327        s32 ret;
 328
 329        ret = i2c_smbus_read_byte_data(chip->cl, reg);
 330        if (ret < 0)
 331                return ret;
 332
 333        *val = ret;
 334        return 0;
 335}
 336EXPORT_SYMBOL_GPL(lp55xx_read);
 337
 338int lp55xx_update_bits(struct lp55xx_chip *chip, u8 reg, u8 mask, u8 val)
 339{
 340        int ret;
 341        u8 tmp;
 342
 343        ret = lp55xx_read(chip, reg, &tmp);
 344        if (ret)
 345                return ret;
 346
 347        tmp &= ~mask;
 348        tmp |= val & mask;
 349
 350        return lp55xx_write(chip, reg, tmp);
 351}
 352EXPORT_SYMBOL_GPL(lp55xx_update_bits);
 353
 354bool lp55xx_is_extclk_used(struct lp55xx_chip *chip)
 355{
 356        struct clk *clk;
 357        int err;
 358
 359        clk = devm_clk_get(&chip->cl->dev, "32k_clk");
 360        if (IS_ERR(clk))
 361                goto use_internal_clk;
 362
 363        err = clk_prepare_enable(clk);
 364        if (err)
 365                goto use_internal_clk;
 366
 367        if (clk_get_rate(clk) != LP55XX_CLK_32K) {
 368                clk_disable_unprepare(clk);
 369                goto use_internal_clk;
 370        }
 371
 372        dev_info(&chip->cl->dev, "%dHz external clock used\n",  LP55XX_CLK_32K);
 373
 374        chip->clk = clk;
 375        return true;
 376
 377use_internal_clk:
 378        dev_info(&chip->cl->dev, "internal clock used\n");
 379        return false;
 380}
 381EXPORT_SYMBOL_GPL(lp55xx_is_extclk_used);
 382
 383int lp55xx_init_device(struct lp55xx_chip *chip)
 384{
 385        struct lp55xx_platform_data *pdata;
 386        struct lp55xx_device_config *cfg;
 387        struct device *dev = &chip->cl->dev;
 388        int ret = 0;
 389
 390        WARN_ON(!chip);
 391
 392        pdata = chip->pdata;
 393        cfg = chip->cfg;
 394
 395        if (!pdata || !cfg)
 396                return -EINVAL;
 397
 398        if (gpio_is_valid(pdata->enable_gpio)) {
 399                ret = devm_gpio_request_one(dev, pdata->enable_gpio,
 400                                            GPIOF_DIR_OUT, "lp5523_enable");
 401                if (ret < 0) {
 402                        dev_err(dev, "could not acquire enable gpio (err=%d)\n",
 403                                ret);
 404                        goto err;
 405                }
 406
 407                gpio_set_value(pdata->enable_gpio, 0);
 408                usleep_range(1000, 2000); /* Keep enable down at least 1ms */
 409                gpio_set_value(pdata->enable_gpio, 1);
 410                usleep_range(1000, 2000); /* 500us abs min. */
 411        }
 412
 413        lp55xx_reset_device(chip);
 414
 415        /*
 416         * Exact value is not available. 10 - 20ms
 417         * appears to be enough for reset.
 418         */
 419        usleep_range(10000, 20000);
 420
 421        ret = lp55xx_detect_device(chip);
 422        if (ret) {
 423                dev_err(dev, "device detection err: %d\n", ret);
 424                goto err;
 425        }
 426
 427        /* chip specific initialization */
 428        ret = lp55xx_post_init_device(chip);
 429        if (ret) {
 430                dev_err(dev, "post init device err: %d\n", ret);
 431                goto err_post_init;
 432        }
 433
 434        return 0;
 435
 436err_post_init:
 437        lp55xx_deinit_device(chip);
 438err:
 439        return ret;
 440}
 441EXPORT_SYMBOL_GPL(lp55xx_init_device);
 442
 443void lp55xx_deinit_device(struct lp55xx_chip *chip)
 444{
 445        struct lp55xx_platform_data *pdata = chip->pdata;
 446
 447        if (chip->clk)
 448                clk_disable_unprepare(chip->clk);
 449
 450        if (gpio_is_valid(pdata->enable_gpio))
 451                gpio_set_value(pdata->enable_gpio, 0);
 452}
 453EXPORT_SYMBOL_GPL(lp55xx_deinit_device);
 454
 455int lp55xx_register_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)
 456{
 457        struct lp55xx_platform_data *pdata = chip->pdata;
 458        struct lp55xx_device_config *cfg = chip->cfg;
 459        int num_channels = pdata->num_channels;
 460        struct lp55xx_led *each;
 461        u8 led_current;
 462        int ret;
 463        int i;
 464
 465        if (!cfg->brightness_fn) {
 466                dev_err(&chip->cl->dev, "empty brightness configuration\n");
 467                return -EINVAL;
 468        }
 469
 470        for (i = 0; i < num_channels; i++) {
 471
 472                /* do not initialize channels that are not connected */
 473                if (pdata->led_config[i].led_current == 0)
 474                        continue;
 475
 476                led_current = pdata->led_config[i].led_current;
 477                each = led + i;
 478                ret = lp55xx_init_led(each, chip, i);
 479                if (ret)
 480                        goto err_init_led;
 481
 482                chip->num_leds++;
 483                each->chip = chip;
 484
 485                /* setting led current at each channel */
 486                if (cfg->set_led_current)
 487                        cfg->set_led_current(each, led_current);
 488        }
 489
 490        return 0;
 491
 492err_init_led:
 493        lp55xx_unregister_leds(led, chip);
 494        return ret;
 495}
 496EXPORT_SYMBOL_GPL(lp55xx_register_leds);
 497
 498void lp55xx_unregister_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)
 499{
 500        int i;
 501        struct lp55xx_led *each;
 502
 503        for (i = 0; i < chip->num_leds; i++) {
 504                each = led + i;
 505                led_classdev_unregister(&each->cdev);
 506        }
 507}
 508EXPORT_SYMBOL_GPL(lp55xx_unregister_leds);
 509
 510int lp55xx_register_sysfs(struct lp55xx_chip *chip)
 511{
 512        struct device *dev = &chip->cl->dev;
 513        struct lp55xx_device_config *cfg = chip->cfg;
 514        int ret;
 515
 516        if (!cfg->run_engine || !cfg->firmware_cb)
 517                goto dev_specific_attrs;
 518
 519        ret = sysfs_create_group(&dev->kobj, &lp55xx_engine_attr_group);
 520        if (ret)
 521                return ret;
 522
 523dev_specific_attrs:
 524        return cfg->dev_attr_group ?
 525                sysfs_create_group(&dev->kobj, cfg->dev_attr_group) : 0;
 526}
 527EXPORT_SYMBOL_GPL(lp55xx_register_sysfs);
 528
 529void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)
 530{
 531        struct device *dev = &chip->cl->dev;
 532        struct lp55xx_device_config *cfg = chip->cfg;
 533
 534        if (cfg->dev_attr_group)
 535                sysfs_remove_group(&dev->kobj, cfg->dev_attr_group);
 536
 537        sysfs_remove_group(&dev->kobj, &lp55xx_engine_attr_group);
 538}
 539EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);
 540
 541struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,
 542                                                      struct device_node *np)
 543{
 544        struct device_node *child;
 545        struct lp55xx_platform_data *pdata;
 546        struct lp55xx_led_config *cfg;
 547        int num_channels;
 548        int i = 0;
 549
 550        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 551        if (!pdata)
 552                return ERR_PTR(-ENOMEM);
 553
 554        num_channels = of_get_child_count(np);
 555        if (num_channels == 0) {
 556                dev_err(dev, "no LED channels\n");
 557                return ERR_PTR(-EINVAL);
 558        }
 559
 560        cfg = devm_kcalloc(dev, num_channels, sizeof(*cfg), GFP_KERNEL);
 561        if (!cfg)
 562                return ERR_PTR(-ENOMEM);
 563
 564        pdata->led_config = &cfg[0];
 565        pdata->num_channels = num_channels;
 566
 567        for_each_child_of_node(np, child) {
 568                cfg[i].chan_nr = i;
 569
 570                of_property_read_string(child, "chan-name", &cfg[i].name);
 571                of_property_read_u8(child, "led-cur", &cfg[i].led_current);
 572                of_property_read_u8(child, "max-cur", &cfg[i].max_current);
 573                cfg[i].default_trigger =
 574                        of_get_property(child, "linux,default-trigger", NULL);
 575
 576                i++;
 577        }
 578
 579        of_property_read_string(np, "label", &pdata->label);
 580        of_property_read_u8(np, "clock-mode", &pdata->clock_mode);
 581
 582        pdata->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
 583
 584        /* LP8501 specific */
 585        of_property_read_u8(np, "pwr-sel", (u8 *)&pdata->pwr_sel);
 586
 587        return pdata;
 588}
 589EXPORT_SYMBOL_GPL(lp55xx_of_populate_pdata);
 590
 591MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>");
 592MODULE_DESCRIPTION("LP55xx Common Driver");
 593MODULE_LICENSE("GPL");
 594