Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * TI LP8501 9 channel LED Driver
0004  *
0005  * Copyright (C) 2013 Texas Instruments
0006  *
0007  * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
0008  */
0009 
0010 #include <linux/delay.h>
0011 #include <linux/firmware.h>
0012 #include <linux/i2c.h>
0013 #include <linux/init.h>
0014 #include <linux/leds.h>
0015 #include <linux/module.h>
0016 #include <linux/mutex.h>
0017 #include <linux/of.h>
0018 #include <linux/platform_data/leds-lp55xx.h>
0019 #include <linux/slab.h>
0020 
0021 #include "leds-lp55xx-common.h"
0022 
0023 #define LP8501_PROGRAM_LENGTH       32
0024 #define LP8501_MAX_LEDS         9
0025 
0026 /* Registers */
0027 #define LP8501_REG_ENABLE       0x00
0028 #define LP8501_ENABLE           BIT(6)
0029 #define LP8501_EXEC_M           0x3F
0030 #define LP8501_EXEC_ENG1_M      0x30
0031 #define LP8501_EXEC_ENG2_M      0x0C
0032 #define LP8501_EXEC_ENG3_M      0x03
0033 #define LP8501_RUN_ENG1         0x20
0034 #define LP8501_RUN_ENG2         0x08
0035 #define LP8501_RUN_ENG3         0x02
0036 
0037 #define LP8501_REG_OP_MODE      0x01
0038 #define LP8501_MODE_ENG1_M      0x30
0039 #define LP8501_MODE_ENG2_M      0x0C
0040 #define LP8501_MODE_ENG3_M      0x03
0041 #define LP8501_LOAD_ENG1        0x10
0042 #define LP8501_LOAD_ENG2        0x04
0043 #define LP8501_LOAD_ENG3        0x01
0044 
0045 #define LP8501_REG_PWR_CONFIG       0x05
0046 #define LP8501_PWR_CONFIG_M     0x03
0047 
0048 #define LP8501_REG_LED_PWM_BASE     0x16
0049 
0050 #define LP8501_REG_LED_CURRENT_BASE 0x26
0051 
0052 #define LP8501_REG_CONFIG       0x36
0053 #define LP8501_PWM_PSAVE        BIT(7)
0054 #define LP8501_AUTO_INC         BIT(6)
0055 #define LP8501_PWR_SAVE         BIT(5)
0056 #define LP8501_CP_AUTO          0x18
0057 #define LP8501_INT_CLK          BIT(0)
0058 #define LP8501_DEFAULT_CFG  \
0059     (LP8501_PWM_PSAVE | LP8501_AUTO_INC | LP8501_PWR_SAVE | LP8501_CP_AUTO)
0060 
0061 #define LP8501_REG_RESET        0x3D
0062 #define LP8501_RESET            0xFF
0063 
0064 #define LP8501_REG_PROG_PAGE_SEL    0x4F
0065 #define LP8501_PAGE_ENG1        0
0066 #define LP8501_PAGE_ENG2        1
0067 #define LP8501_PAGE_ENG3        2
0068 
0069 #define LP8501_REG_PROG_MEM     0x50
0070 
0071 #define LP8501_ENG1_IS_LOADING(mode)    \
0072     ((mode & LP8501_MODE_ENG1_M) == LP8501_LOAD_ENG1)
0073 #define LP8501_ENG2_IS_LOADING(mode)    \
0074     ((mode & LP8501_MODE_ENG2_M) == LP8501_LOAD_ENG2)
0075 #define LP8501_ENG3_IS_LOADING(mode)    \
0076     ((mode & LP8501_MODE_ENG3_M) == LP8501_LOAD_ENG3)
0077 
0078 static inline void lp8501_wait_opmode_done(void)
0079 {
0080     usleep_range(1000, 2000);
0081 }
0082 
0083 static void lp8501_set_led_current(struct lp55xx_led *led, u8 led_current)
0084 {
0085     led->led_current = led_current;
0086     lp55xx_write(led->chip, LP8501_REG_LED_CURRENT_BASE + led->chan_nr,
0087         led_current);
0088 }
0089 
0090 static int lp8501_post_init_device(struct lp55xx_chip *chip)
0091 {
0092     int ret;
0093     u8 val = LP8501_DEFAULT_CFG;
0094 
0095     ret = lp55xx_write(chip, LP8501_REG_ENABLE, LP8501_ENABLE);
0096     if (ret)
0097         return ret;
0098 
0099     /* Chip startup time is 500 us, 1 - 2 ms gives some margin */
0100     usleep_range(1000, 2000);
0101 
0102     if (chip->pdata->clock_mode != LP55XX_CLOCK_EXT)
0103         val |= LP8501_INT_CLK;
0104 
0105     ret = lp55xx_write(chip, LP8501_REG_CONFIG, val);
0106     if (ret)
0107         return ret;
0108 
0109     /* Power selection for each output */
0110     return lp55xx_update_bits(chip, LP8501_REG_PWR_CONFIG,
0111                 LP8501_PWR_CONFIG_M, chip->pdata->pwr_sel);
0112 }
0113 
0114 static void lp8501_load_engine(struct lp55xx_chip *chip)
0115 {
0116     enum lp55xx_engine_index idx = chip->engine_idx;
0117     static const u8 mask[] = {
0118         [LP55XX_ENGINE_1] = LP8501_MODE_ENG1_M,
0119         [LP55XX_ENGINE_2] = LP8501_MODE_ENG2_M,
0120         [LP55XX_ENGINE_3] = LP8501_MODE_ENG3_M,
0121     };
0122 
0123     static const u8 val[] = {
0124         [LP55XX_ENGINE_1] = LP8501_LOAD_ENG1,
0125         [LP55XX_ENGINE_2] = LP8501_LOAD_ENG2,
0126         [LP55XX_ENGINE_3] = LP8501_LOAD_ENG3,
0127     };
0128 
0129     static const u8 page_sel[] = {
0130         [LP55XX_ENGINE_1] = LP8501_PAGE_ENG1,
0131         [LP55XX_ENGINE_2] = LP8501_PAGE_ENG2,
0132         [LP55XX_ENGINE_3] = LP8501_PAGE_ENG3,
0133     };
0134 
0135     lp55xx_update_bits(chip, LP8501_REG_OP_MODE, mask[idx], val[idx]);
0136 
0137     lp8501_wait_opmode_done();
0138 
0139     lp55xx_write(chip, LP8501_REG_PROG_PAGE_SEL, page_sel[idx]);
0140 }
0141 
0142 static void lp8501_stop_engine(struct lp55xx_chip *chip)
0143 {
0144     lp55xx_write(chip, LP8501_REG_OP_MODE, 0);
0145     lp8501_wait_opmode_done();
0146 }
0147 
0148 static void lp8501_turn_off_channels(struct lp55xx_chip *chip)
0149 {
0150     int i;
0151 
0152     for (i = 0; i < LP8501_MAX_LEDS; i++)
0153         lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + i, 0);
0154 }
0155 
0156 static void lp8501_run_engine(struct lp55xx_chip *chip, bool start)
0157 {
0158     int ret;
0159     u8 mode;
0160     u8 exec;
0161 
0162     /* stop engine */
0163     if (!start) {
0164         lp8501_stop_engine(chip);
0165         lp8501_turn_off_channels(chip);
0166         return;
0167     }
0168 
0169     /*
0170      * To run the engine,
0171      * operation mode and enable register should updated at the same time
0172      */
0173 
0174     ret = lp55xx_read(chip, LP8501_REG_OP_MODE, &mode);
0175     if (ret)
0176         return;
0177 
0178     ret = lp55xx_read(chip, LP8501_REG_ENABLE, &exec);
0179     if (ret)
0180         return;
0181 
0182     /* change operation mode to RUN only when each engine is loading */
0183     if (LP8501_ENG1_IS_LOADING(mode)) {
0184         mode = (mode & ~LP8501_MODE_ENG1_M) | LP8501_RUN_ENG1;
0185         exec = (exec & ~LP8501_EXEC_ENG1_M) | LP8501_RUN_ENG1;
0186     }
0187 
0188     if (LP8501_ENG2_IS_LOADING(mode)) {
0189         mode = (mode & ~LP8501_MODE_ENG2_M) | LP8501_RUN_ENG2;
0190         exec = (exec & ~LP8501_EXEC_ENG2_M) | LP8501_RUN_ENG2;
0191     }
0192 
0193     if (LP8501_ENG3_IS_LOADING(mode)) {
0194         mode = (mode & ~LP8501_MODE_ENG3_M) | LP8501_RUN_ENG3;
0195         exec = (exec & ~LP8501_EXEC_ENG3_M) | LP8501_RUN_ENG3;
0196     }
0197 
0198     lp55xx_write(chip, LP8501_REG_OP_MODE, mode);
0199     lp8501_wait_opmode_done();
0200 
0201     lp55xx_update_bits(chip, LP8501_REG_ENABLE, LP8501_EXEC_M, exec);
0202 }
0203 
0204 static int lp8501_update_program_memory(struct lp55xx_chip *chip,
0205                     const u8 *data, size_t size)
0206 {
0207     u8 pattern[LP8501_PROGRAM_LENGTH] = {0};
0208     unsigned cmd;
0209     char c[3];
0210     int update_size;
0211     int nrchars;
0212     int offset = 0;
0213     int ret;
0214     int i;
0215 
0216     /* clear program memory before updating */
0217     for (i = 0; i < LP8501_PROGRAM_LENGTH; i++)
0218         lp55xx_write(chip, LP8501_REG_PROG_MEM + i, 0);
0219 
0220     i = 0;
0221     while ((offset < size - 1) && (i < LP8501_PROGRAM_LENGTH)) {
0222         /* separate sscanfs because length is working only for %s */
0223         ret = sscanf(data + offset, "%2s%n ", c, &nrchars);
0224         if (ret != 1)
0225             goto err;
0226 
0227         ret = sscanf(c, "%2x", &cmd);
0228         if (ret != 1)
0229             goto err;
0230 
0231         pattern[i] = (u8)cmd;
0232         offset += nrchars;
0233         i++;
0234     }
0235 
0236     /* Each instruction is 16bit long. Check that length is even */
0237     if (i % 2)
0238         goto err;
0239 
0240     update_size = i;
0241     for (i = 0; i < update_size; i++)
0242         lp55xx_write(chip, LP8501_REG_PROG_MEM + i, pattern[i]);
0243 
0244     return 0;
0245 
0246 err:
0247     dev_err(&chip->cl->dev, "wrong pattern format\n");
0248     return -EINVAL;
0249 }
0250 
0251 static void lp8501_firmware_loaded(struct lp55xx_chip *chip)
0252 {
0253     const struct firmware *fw = chip->fw;
0254 
0255     if (fw->size > LP8501_PROGRAM_LENGTH) {
0256         dev_err(&chip->cl->dev, "firmware data size overflow: %zu\n",
0257             fw->size);
0258         return;
0259     }
0260 
0261     /*
0262      * Program memory sequence
0263      *  1) set engine mode to "LOAD"
0264      *  2) write firmware data into program memory
0265      */
0266 
0267     lp8501_load_engine(chip);
0268     lp8501_update_program_memory(chip, fw->data, fw->size);
0269 }
0270 
0271 static int lp8501_led_brightness(struct lp55xx_led *led)
0272 {
0273     struct lp55xx_chip *chip = led->chip;
0274     int ret;
0275 
0276     mutex_lock(&chip->lock);
0277     ret = lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + led->chan_nr,
0278              led->brightness);
0279     mutex_unlock(&chip->lock);
0280 
0281     return ret;
0282 }
0283 
0284 /* Chip specific configurations */
0285 static struct lp55xx_device_config lp8501_cfg = {
0286     .reset = {
0287         .addr = LP8501_REG_RESET,
0288         .val  = LP8501_RESET,
0289     },
0290     .enable = {
0291         .addr = LP8501_REG_ENABLE,
0292         .val  = LP8501_ENABLE,
0293     },
0294     .max_channel  = LP8501_MAX_LEDS,
0295     .post_init_device   = lp8501_post_init_device,
0296     .brightness_fn      = lp8501_led_brightness,
0297     .set_led_current    = lp8501_set_led_current,
0298     .firmware_cb        = lp8501_firmware_loaded,
0299     .run_engine         = lp8501_run_engine,
0300 };
0301 
0302 static int lp8501_probe(struct i2c_client *client,
0303             const struct i2c_device_id *id)
0304 {
0305     int ret;
0306     struct lp55xx_chip *chip;
0307     struct lp55xx_led *led;
0308     struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
0309     struct device_node *np = dev_of_node(&client->dev);
0310 
0311     chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
0312     if (!chip)
0313         return -ENOMEM;
0314 
0315     chip->cfg = &lp8501_cfg;
0316 
0317     if (!pdata) {
0318         if (np) {
0319             pdata = lp55xx_of_populate_pdata(&client->dev, np,
0320                              chip);
0321             if (IS_ERR(pdata))
0322                 return PTR_ERR(pdata);
0323         } else {
0324             dev_err(&client->dev, "no platform data\n");
0325             return -EINVAL;
0326         }
0327     }
0328 
0329     led = devm_kcalloc(&client->dev,
0330             pdata->num_channels, sizeof(*led), GFP_KERNEL);
0331     if (!led)
0332         return -ENOMEM;
0333 
0334     chip->cl = client;
0335     chip->pdata = pdata;
0336 
0337     mutex_init(&chip->lock);
0338 
0339     i2c_set_clientdata(client, led);
0340 
0341     ret = lp55xx_init_device(chip);
0342     if (ret)
0343         goto err_init;
0344 
0345     dev_info(&client->dev, "%s Programmable led chip found\n", id->name);
0346 
0347     ret = lp55xx_register_leds(led, chip);
0348     if (ret)
0349         goto err_out;
0350 
0351     ret = lp55xx_register_sysfs(chip);
0352     if (ret) {
0353         dev_err(&client->dev, "registering sysfs failed\n");
0354         goto err_out;
0355     }
0356 
0357     return 0;
0358 
0359 err_out:
0360     lp55xx_deinit_device(chip);
0361 err_init:
0362     return ret;
0363 }
0364 
0365 static int lp8501_remove(struct i2c_client *client)
0366 {
0367     struct lp55xx_led *led = i2c_get_clientdata(client);
0368     struct lp55xx_chip *chip = led->chip;
0369 
0370     lp8501_stop_engine(chip);
0371     lp55xx_unregister_sysfs(chip);
0372     lp55xx_deinit_device(chip);
0373 
0374     return 0;
0375 }
0376 
0377 static const struct i2c_device_id lp8501_id[] = {
0378     { "lp8501",  0 },
0379     { }
0380 };
0381 MODULE_DEVICE_TABLE(i2c, lp8501_id);
0382 
0383 #ifdef CONFIG_OF
0384 static const struct of_device_id of_lp8501_leds_match[] = {
0385     { .compatible = "ti,lp8501", },
0386     {},
0387 };
0388 
0389 MODULE_DEVICE_TABLE(of, of_lp8501_leds_match);
0390 #endif
0391 
0392 static struct i2c_driver lp8501_driver = {
0393     .driver = {
0394         .name   = "lp8501",
0395         .of_match_table = of_match_ptr(of_lp8501_leds_match),
0396     },
0397     .probe      = lp8501_probe,
0398     .remove     = lp8501_remove,
0399     .id_table   = lp8501_id,
0400 };
0401 
0402 module_i2c_driver(lp8501_driver);
0403 
0404 MODULE_DESCRIPTION("Texas Instruments LP8501 LED driver");
0405 MODULE_AUTHOR("Milo Kim");
0406 MODULE_LICENSE("GPL");