linux/drivers/leds/leds-lp8501.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * TI LP8501 9 channel LED Driver
   4 *
   5 * Copyright (C) 2013 Texas Instruments
   6 *
   7 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
   8 */
   9
  10#include <linux/delay.h>
  11#include <linux/firmware.h>
  12#include <linux/i2c.h>
  13#include <linux/init.h>
  14#include <linux/leds.h>
  15#include <linux/module.h>
  16#include <linux/mutex.h>
  17#include <linux/of.h>
  18#include <linux/platform_data/leds-lp55xx.h>
  19#include <linux/slab.h>
  20
  21#include "leds-lp55xx-common.h"
  22
  23#define LP8501_PROGRAM_LENGTH           32
  24#define LP8501_MAX_LEDS                 9
  25
  26/* Registers */
  27#define LP8501_REG_ENABLE               0x00
  28#define LP8501_ENABLE                   BIT(6)
  29#define LP8501_EXEC_M                   0x3F
  30#define LP8501_EXEC_ENG1_M              0x30
  31#define LP8501_EXEC_ENG2_M              0x0C
  32#define LP8501_EXEC_ENG3_M              0x03
  33#define LP8501_RUN_ENG1                 0x20
  34#define LP8501_RUN_ENG2                 0x08
  35#define LP8501_RUN_ENG3                 0x02
  36
  37#define LP8501_REG_OP_MODE              0x01
  38#define LP8501_MODE_ENG1_M              0x30
  39#define LP8501_MODE_ENG2_M              0x0C
  40#define LP8501_MODE_ENG3_M              0x03
  41#define LP8501_LOAD_ENG1                0x10
  42#define LP8501_LOAD_ENG2                0x04
  43#define LP8501_LOAD_ENG3                0x01
  44
  45#define LP8501_REG_PWR_CONFIG           0x05
  46#define LP8501_PWR_CONFIG_M             0x03
  47
  48#define LP8501_REG_LED_PWM_BASE         0x16
  49
  50#define LP8501_REG_LED_CURRENT_BASE     0x26
  51
  52#define LP8501_REG_CONFIG               0x36
  53#define LP8501_PWM_PSAVE                BIT(7)
  54#define LP8501_AUTO_INC                 BIT(6)
  55#define LP8501_PWR_SAVE                 BIT(5)
  56#define LP8501_CP_AUTO                  0x18
  57#define LP8501_INT_CLK                  BIT(0)
  58#define LP8501_DEFAULT_CFG      \
  59        (LP8501_PWM_PSAVE | LP8501_AUTO_INC | LP8501_PWR_SAVE | LP8501_CP_AUTO)
  60
  61#define LP8501_REG_RESET                0x3D
  62#define LP8501_RESET                    0xFF
  63
  64#define LP8501_REG_PROG_PAGE_SEL        0x4F
  65#define LP8501_PAGE_ENG1                0
  66#define LP8501_PAGE_ENG2                1
  67#define LP8501_PAGE_ENG3                2
  68
  69#define LP8501_REG_PROG_MEM             0x50
  70
  71#define LP8501_ENG1_IS_LOADING(mode)    \
  72        ((mode & LP8501_MODE_ENG1_M) == LP8501_LOAD_ENG1)
  73#define LP8501_ENG2_IS_LOADING(mode)    \
  74        ((mode & LP8501_MODE_ENG2_M) == LP8501_LOAD_ENG2)
  75#define LP8501_ENG3_IS_LOADING(mode)    \
  76        ((mode & LP8501_MODE_ENG3_M) == LP8501_LOAD_ENG3)
  77
  78static inline void lp8501_wait_opmode_done(void)
  79{
  80        usleep_range(1000, 2000);
  81}
  82
  83static void lp8501_set_led_current(struct lp55xx_led *led, u8 led_current)
  84{
  85        led->led_current = led_current;
  86        lp55xx_write(led->chip, LP8501_REG_LED_CURRENT_BASE + led->chan_nr,
  87                led_current);
  88}
  89
  90static int lp8501_post_init_device(struct lp55xx_chip *chip)
  91{
  92        int ret;
  93        u8 val = LP8501_DEFAULT_CFG;
  94
  95        ret = lp55xx_write(chip, LP8501_REG_ENABLE, LP8501_ENABLE);
  96        if (ret)
  97                return ret;
  98
  99        /* Chip startup time is 500 us, 1 - 2 ms gives some margin */
 100        usleep_range(1000, 2000);
 101
 102        if (chip->pdata->clock_mode != LP55XX_CLOCK_EXT)
 103                val |= LP8501_INT_CLK;
 104
 105        ret = lp55xx_write(chip, LP8501_REG_CONFIG, val);
 106        if (ret)
 107                return ret;
 108
 109        /* Power selection for each output */
 110        return lp55xx_update_bits(chip, LP8501_REG_PWR_CONFIG,
 111                                LP8501_PWR_CONFIG_M, chip->pdata->pwr_sel);
 112}
 113
 114static void lp8501_load_engine(struct lp55xx_chip *chip)
 115{
 116        enum lp55xx_engine_index idx = chip->engine_idx;
 117        static const u8 mask[] = {
 118                [LP55XX_ENGINE_1] = LP8501_MODE_ENG1_M,
 119                [LP55XX_ENGINE_2] = LP8501_MODE_ENG2_M,
 120                [LP55XX_ENGINE_3] = LP8501_MODE_ENG3_M,
 121        };
 122
 123        static const u8 val[] = {
 124                [LP55XX_ENGINE_1] = LP8501_LOAD_ENG1,
 125                [LP55XX_ENGINE_2] = LP8501_LOAD_ENG2,
 126                [LP55XX_ENGINE_3] = LP8501_LOAD_ENG3,
 127        };
 128
 129        static const u8 page_sel[] = {
 130                [LP55XX_ENGINE_1] = LP8501_PAGE_ENG1,
 131                [LP55XX_ENGINE_2] = LP8501_PAGE_ENG2,
 132                [LP55XX_ENGINE_3] = LP8501_PAGE_ENG3,
 133        };
 134
 135        lp55xx_update_bits(chip, LP8501_REG_OP_MODE, mask[idx], val[idx]);
 136
 137        lp8501_wait_opmode_done();
 138
 139        lp55xx_write(chip, LP8501_REG_PROG_PAGE_SEL, page_sel[idx]);
 140}
 141
 142static void lp8501_stop_engine(struct lp55xx_chip *chip)
 143{
 144        lp55xx_write(chip, LP8501_REG_OP_MODE, 0);
 145        lp8501_wait_opmode_done();
 146}
 147
 148static void lp8501_turn_off_channels(struct lp55xx_chip *chip)
 149{
 150        int i;
 151
 152        for (i = 0; i < LP8501_MAX_LEDS; i++)
 153                lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + i, 0);
 154}
 155
 156static void lp8501_run_engine(struct lp55xx_chip *chip, bool start)
 157{
 158        int ret;
 159        u8 mode;
 160        u8 exec;
 161
 162        /* stop engine */
 163        if (!start) {
 164                lp8501_stop_engine(chip);
 165                lp8501_turn_off_channels(chip);
 166                return;
 167        }
 168
 169        /*
 170         * To run the engine,
 171         * operation mode and enable register should updated at the same time
 172         */
 173
 174        ret = lp55xx_read(chip, LP8501_REG_OP_MODE, &mode);
 175        if (ret)
 176                return;
 177
 178        ret = lp55xx_read(chip, LP8501_REG_ENABLE, &exec);
 179        if (ret)
 180                return;
 181
 182        /* change operation mode to RUN only when each engine is loading */
 183        if (LP8501_ENG1_IS_LOADING(mode)) {
 184                mode = (mode & ~LP8501_MODE_ENG1_M) | LP8501_RUN_ENG1;
 185                exec = (exec & ~LP8501_EXEC_ENG1_M) | LP8501_RUN_ENG1;
 186        }
 187
 188        if (LP8501_ENG2_IS_LOADING(mode)) {
 189                mode = (mode & ~LP8501_MODE_ENG2_M) | LP8501_RUN_ENG2;
 190                exec = (exec & ~LP8501_EXEC_ENG2_M) | LP8501_RUN_ENG2;
 191        }
 192
 193        if (LP8501_ENG3_IS_LOADING(mode)) {
 194                mode = (mode & ~LP8501_MODE_ENG3_M) | LP8501_RUN_ENG3;
 195                exec = (exec & ~LP8501_EXEC_ENG3_M) | LP8501_RUN_ENG3;
 196        }
 197
 198        lp55xx_write(chip, LP8501_REG_OP_MODE, mode);
 199        lp8501_wait_opmode_done();
 200
 201        lp55xx_update_bits(chip, LP8501_REG_ENABLE, LP8501_EXEC_M, exec);
 202}
 203
 204static int lp8501_update_program_memory(struct lp55xx_chip *chip,
 205                                        const u8 *data, size_t size)
 206{
 207        u8 pattern[LP8501_PROGRAM_LENGTH] = {0};
 208        unsigned cmd;
 209        char c[3];
 210        int update_size;
 211        int nrchars;
 212        int offset = 0;
 213        int ret;
 214        int i;
 215
 216        /* clear program memory before updating */
 217        for (i = 0; i < LP8501_PROGRAM_LENGTH; i++)
 218                lp55xx_write(chip, LP8501_REG_PROG_MEM + i, 0);
 219
 220        i = 0;
 221        while ((offset < size - 1) && (i < LP8501_PROGRAM_LENGTH)) {
 222                /* separate sscanfs because length is working only for %s */
 223                ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
 224                if (ret != 1)
 225                        goto err;
 226
 227                ret = sscanf(c, "%2x", &cmd);
 228                if (ret != 1)
 229                        goto err;
 230
 231                pattern[i] = (u8)cmd;
 232                offset += nrchars;
 233                i++;
 234        }
 235
 236        /* Each instruction is 16bit long. Check that length is even */
 237        if (i % 2)
 238                goto err;
 239
 240        update_size = i;
 241        for (i = 0; i < update_size; i++)
 242                lp55xx_write(chip, LP8501_REG_PROG_MEM + i, pattern[i]);
 243
 244        return 0;
 245
 246err:
 247        dev_err(&chip->cl->dev, "wrong pattern format\n");
 248        return -EINVAL;
 249}
 250
 251static void lp8501_firmware_loaded(struct lp55xx_chip *chip)
 252{
 253        const struct firmware *fw = chip->fw;
 254
 255        if (fw->size > LP8501_PROGRAM_LENGTH) {
 256                dev_err(&chip->cl->dev, "firmware data size overflow: %zu\n",
 257                        fw->size);
 258                return;
 259        }
 260
 261        /*
 262         * Program memory sequence
 263         *  1) set engine mode to "LOAD"
 264         *  2) write firmware data into program memory
 265         */
 266
 267        lp8501_load_engine(chip);
 268        lp8501_update_program_memory(chip, fw->data, fw->size);
 269}
 270
 271static int lp8501_led_brightness(struct lp55xx_led *led)
 272{
 273        struct lp55xx_chip *chip = led->chip;
 274        int ret;
 275
 276        mutex_lock(&chip->lock);
 277        ret = lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + led->chan_nr,
 278                     led->brightness);
 279        mutex_unlock(&chip->lock);
 280
 281        return ret;
 282}
 283
 284/* Chip specific configurations */
 285static struct lp55xx_device_config lp8501_cfg = {
 286        .reset = {
 287                .addr = LP8501_REG_RESET,
 288                .val  = LP8501_RESET,
 289        },
 290        .enable = {
 291                .addr = LP8501_REG_ENABLE,
 292                .val  = LP8501_ENABLE,
 293        },
 294        .max_channel  = LP8501_MAX_LEDS,
 295        .post_init_device   = lp8501_post_init_device,
 296        .brightness_fn      = lp8501_led_brightness,
 297        .set_led_current    = lp8501_set_led_current,
 298        .firmware_cb        = lp8501_firmware_loaded,
 299        .run_engine         = lp8501_run_engine,
 300};
 301
 302static int lp8501_probe(struct i2c_client *client,
 303                        const struct i2c_device_id *id)
 304{
 305        int ret;
 306        struct lp55xx_chip *chip;
 307        struct lp55xx_led *led;
 308        struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
 309        struct device_node *np = dev_of_node(&client->dev);
 310
 311        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
 312        if (!chip)
 313                return -ENOMEM;
 314
 315        chip->cfg = &lp8501_cfg;
 316
 317        if (!pdata) {
 318                if (np) {
 319                        pdata = lp55xx_of_populate_pdata(&client->dev, np,
 320                                                         chip);
 321                        if (IS_ERR(pdata))
 322                                return PTR_ERR(pdata);
 323                } else {
 324                        dev_err(&client->dev, "no platform data\n");
 325                        return -EINVAL;
 326                }
 327        }
 328
 329        led = devm_kcalloc(&client->dev,
 330                        pdata->num_channels, sizeof(*led), GFP_KERNEL);
 331        if (!led)
 332                return -ENOMEM;
 333
 334        chip->cl = client;
 335        chip->pdata = pdata;
 336
 337        mutex_init(&chip->lock);
 338
 339        i2c_set_clientdata(client, led);
 340
 341        ret = lp55xx_init_device(chip);
 342        if (ret)
 343                goto err_init;
 344
 345        dev_info(&client->dev, "%s Programmable led chip found\n", id->name);
 346
 347        ret = lp55xx_register_leds(led, chip);
 348        if (ret)
 349                goto err_out;
 350
 351        ret = lp55xx_register_sysfs(chip);
 352        if (ret) {
 353                dev_err(&client->dev, "registering sysfs failed\n");
 354                goto err_out;
 355        }
 356
 357        return 0;
 358
 359err_out:
 360        lp55xx_deinit_device(chip);
 361err_init:
 362        return ret;
 363}
 364
 365static int lp8501_remove(struct i2c_client *client)
 366{
 367        struct lp55xx_led *led = i2c_get_clientdata(client);
 368        struct lp55xx_chip *chip = led->chip;
 369
 370        lp8501_stop_engine(chip);
 371        lp55xx_unregister_sysfs(chip);
 372        lp55xx_deinit_device(chip);
 373
 374        return 0;
 375}
 376
 377static const struct i2c_device_id lp8501_id[] = {
 378        { "lp8501",  0 },
 379        { }
 380};
 381MODULE_DEVICE_TABLE(i2c, lp8501_id);
 382
 383#ifdef CONFIG_OF
 384static const struct of_device_id of_lp8501_leds_match[] = {
 385        { .compatible = "ti,lp8501", },
 386        {},
 387};
 388
 389MODULE_DEVICE_TABLE(of, of_lp8501_leds_match);
 390#endif
 391
 392static struct i2c_driver lp8501_driver = {
 393        .driver = {
 394                .name   = "lp8501",
 395                .of_match_table = of_match_ptr(of_lp8501_leds_match),
 396        },
 397        .probe          = lp8501_probe,
 398        .remove         = lp8501_remove,
 399        .id_table       = lp8501_id,
 400};
 401
 402module_i2c_driver(lp8501_driver);
 403
 404MODULE_DESCRIPTION("Texas Instruments LP8501 LED driver");
 405MODULE_AUTHOR("Milo Kim");
 406MODULE_LICENSE("GPL");
 407