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