linux/drivers/leds/leds-pca963x.c
<<
>>
Prefs
   1/*
   2 * Copyright 2011 bct electronic GmbH
   3 * Copyright 2013 Qtechnology/AS
   4 *
   5 * Author: Peter Meerwald <p.meerwald@bct-electronic.com>
   6 * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
   7 *
   8 * Based on leds-pca955x.c
   9 *
  10 * This file is subject to the terms and conditions of version 2 of
  11 * the GNU General Public License.  See the file COPYING in the main
  12 * directory of this archive for more details.
  13 *
  14 * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62)
  15 * LED driver for the PCA9634 I2C LED driver (7-bit slave address set by hw.)
  16 *
  17 * Note that hardware blinking violates the leds infrastructure driver
  18 * interface since the hardware only supports blinking all LEDs with the
  19 * same delay_on/delay_off rates.  That is, only the LEDs that are set to
  20 * blink will actually blink but all LEDs that are set to blink will blink
  21 * in identical fashion.  The delay_on/delay_off values of the last LED
  22 * that is set to blink will be used for all of the blinking LEDs.
  23 * Hardware blinking is disabled by default but can be enabled by setting
  24 * the 'blink_type' member in the platform_data struct to 'PCA963X_HW_BLINK'
  25 * or by adding the 'nxp,hw-blink' property to the DTS.
  26 */
  27
  28#include <linux/module.h>
  29#include <linux/delay.h>
  30#include <linux/string.h>
  31#include <linux/ctype.h>
  32#include <linux/leds.h>
  33#include <linux/err.h>
  34#include <linux/i2c.h>
  35#include <linux/workqueue.h>
  36#include <linux/slab.h>
  37#include <linux/of.h>
  38#include <linux/platform_data/leds-pca963x.h>
  39
  40/* LED select registers determine the source that drives LED outputs */
  41#define PCA963X_LED_OFF         0x0     /* LED driver off */
  42#define PCA963X_LED_ON          0x1     /* LED driver on */
  43#define PCA963X_LED_PWM         0x2     /* Controlled through PWM */
  44#define PCA963X_LED_GRP_PWM     0x3     /* Controlled through PWM/GRPPWM */
  45
  46#define PCA963X_MODE2_DMBLNK    0x20    /* Enable blinking */
  47
  48#define PCA963X_MODE1           0x00
  49#define PCA963X_MODE2           0x01
  50#define PCA963X_PWM_BASE        0x02
  51
  52enum pca963x_type {
  53        pca9633,
  54        pca9634,
  55};
  56
  57struct pca963x_chipdef {
  58        u8                      grppwm;
  59        u8                      grpfreq;
  60        u8                      ledout_base;
  61        int                     n_leds;
  62};
  63
  64static struct pca963x_chipdef pca963x_chipdefs[] = {
  65        [pca9633] = {
  66                .grppwm         = 0x6,
  67                .grpfreq        = 0x7,
  68                .ledout_base    = 0x8,
  69                .n_leds         = 4,
  70        },
  71        [pca9634] = {
  72                .grppwm         = 0xa,
  73                .grpfreq        = 0xb,
  74                .ledout_base    = 0xc,
  75                .n_leds         = 8,
  76        },
  77};
  78
  79/* Total blink period in milliseconds */
  80#define PCA963X_BLINK_PERIOD_MIN        42
  81#define PCA963X_BLINK_PERIOD_MAX        10667
  82
  83static const struct i2c_device_id pca963x_id[] = {
  84        { "pca9632", pca9633 },
  85        { "pca9633", pca9633 },
  86        { "pca9634", pca9634 },
  87        { }
  88};
  89MODULE_DEVICE_TABLE(i2c, pca963x_id);
  90
  91enum pca963x_cmd {
  92        BRIGHTNESS_SET,
  93        BLINK_SET,
  94};
  95
  96struct pca963x_led;
  97
  98struct pca963x {
  99        struct pca963x_chipdef *chipdef;
 100        struct mutex mutex;
 101        struct i2c_client *client;
 102        struct pca963x_led *leds;
 103};
 104
 105struct pca963x_led {
 106        struct pca963x *chip;
 107        struct work_struct work;
 108        enum led_brightness brightness;
 109        struct led_classdev led_cdev;
 110        int led_num; /* 0 .. 7 potentially */
 111        enum pca963x_cmd cmd;
 112        char name[32];
 113        u8 gdc;
 114        u8 gfrq;
 115};
 116
 117static void pca963x_brightness_work(struct pca963x_led *pca963x)
 118{
 119        u8 ledout_addr = pca963x->chip->chipdef->ledout_base
 120                + (pca963x->led_num / 4);
 121        u8 ledout;
 122        int shift = 2 * (pca963x->led_num % 4);
 123        u8 mask = 0x3 << shift;
 124
 125        mutex_lock(&pca963x->chip->mutex);
 126        ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr);
 127        switch (pca963x->brightness) {
 128        case LED_FULL:
 129                i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr,
 130                        (ledout & ~mask) | (PCA963X_LED_ON << shift));
 131                break;
 132        case LED_OFF:
 133                i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr,
 134                        ledout & ~mask);
 135                break;
 136        default:
 137                i2c_smbus_write_byte_data(pca963x->chip->client,
 138                        PCA963X_PWM_BASE + pca963x->led_num,
 139                        pca963x->brightness);
 140                i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr,
 141                        (ledout & ~mask) | (PCA963X_LED_PWM << shift));
 142                break;
 143        }
 144        mutex_unlock(&pca963x->chip->mutex);
 145}
 146
 147static void pca963x_blink_work(struct pca963x_led *pca963x)
 148{
 149        u8 ledout_addr = pca963x->chip->chipdef->ledout_base +
 150                (pca963x->led_num / 4);
 151        u8 ledout;
 152        u8 mode2 = i2c_smbus_read_byte_data(pca963x->chip->client,
 153                                                        PCA963X_MODE2);
 154        int shift = 2 * (pca963x->led_num % 4);
 155        u8 mask = 0x3 << shift;
 156
 157        i2c_smbus_write_byte_data(pca963x->chip->client,
 158                        pca963x->chip->chipdef->grppwm, pca963x->gdc);
 159
 160        i2c_smbus_write_byte_data(pca963x->chip->client,
 161                        pca963x->chip->chipdef->grpfreq, pca963x->gfrq);
 162
 163        if (!(mode2 & PCA963X_MODE2_DMBLNK))
 164                i2c_smbus_write_byte_data(pca963x->chip->client, PCA963X_MODE2,
 165                        mode2 | PCA963X_MODE2_DMBLNK);
 166
 167        mutex_lock(&pca963x->chip->mutex);
 168        ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr);
 169        if ((ledout & mask) != (PCA963X_LED_GRP_PWM << shift))
 170                i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr,
 171                        (ledout & ~mask) | (PCA963X_LED_GRP_PWM << shift));
 172        mutex_unlock(&pca963x->chip->mutex);
 173}
 174
 175static void pca963x_work(struct work_struct *work)
 176{
 177        struct pca963x_led *pca963x = container_of(work,
 178                struct pca963x_led, work);
 179
 180        switch (pca963x->cmd) {
 181        case BRIGHTNESS_SET:
 182                pca963x_brightness_work(pca963x);
 183                break;
 184        case BLINK_SET:
 185                pca963x_blink_work(pca963x);
 186                break;
 187        }
 188}
 189
 190static void pca963x_led_set(struct led_classdev *led_cdev,
 191        enum led_brightness value)
 192{
 193        struct pca963x_led *pca963x;
 194
 195        pca963x = container_of(led_cdev, struct pca963x_led, led_cdev);
 196
 197        pca963x->cmd = BRIGHTNESS_SET;
 198        pca963x->brightness = value;
 199
 200        /*
 201         * Must use workqueue for the actual I/O since I2C operations
 202         * can sleep.
 203         */
 204        schedule_work(&pca963x->work);
 205}
 206
 207static int pca963x_blink_set(struct led_classdev *led_cdev,
 208                unsigned long *delay_on, unsigned long *delay_off)
 209{
 210        struct pca963x_led *pca963x;
 211        unsigned long time_on, time_off, period;
 212        u8 gdc, gfrq;
 213
 214        pca963x = container_of(led_cdev, struct pca963x_led, led_cdev);
 215
 216        time_on = *delay_on;
 217        time_off = *delay_off;
 218
 219        /* If both zero, pick reasonable defaults of 500ms each */
 220        if (!time_on && !time_off) {
 221                time_on = 500;
 222                time_off = 500;
 223        }
 224
 225        period = time_on + time_off;
 226
 227        /* If period not supported by hardware, default to someting sane. */
 228        if ((period < PCA963X_BLINK_PERIOD_MIN) ||
 229            (period > PCA963X_BLINK_PERIOD_MAX)) {
 230                time_on = 500;
 231                time_off = 500;
 232                period = time_on + time_off;
 233        }
 234
 235        /*
 236         * From manual: duty cycle = (GDC / 256) ->
 237         *      (time_on / period) = (GDC / 256) ->
 238         *              GDC = ((time_on * 256) / period)
 239         */
 240        gdc = (time_on * 256) / period;
 241
 242        /*
 243         * From manual: period = ((GFRQ + 1) / 24) in seconds.
 244         * So, period (in ms) = (((GFRQ + 1) / 24) * 1000) ->
 245         *              GFRQ = ((period * 24 / 1000) - 1)
 246         */
 247        gfrq = (period * 24 / 1000) - 1;
 248
 249        pca963x->cmd = BLINK_SET;
 250        pca963x->gdc = gdc;
 251        pca963x->gfrq = gfrq;
 252
 253        /*
 254         * Must use workqueue for the actual I/O since I2C operations
 255         * can sleep.
 256         */
 257        schedule_work(&pca963x->work);
 258
 259        *delay_on = time_on;
 260        *delay_off = time_off;
 261
 262        return 0;
 263}
 264
 265#if IS_ENABLED(CONFIG_OF)
 266static struct pca963x_platform_data *
 267pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip)
 268{
 269        struct device_node *np = client->dev.of_node, *child;
 270        struct pca963x_platform_data *pdata;
 271        struct led_info *pca963x_leds;
 272        int count;
 273
 274        count = of_get_child_count(np);
 275        if (!count || count > chip->n_leds)
 276                return ERR_PTR(-ENODEV);
 277
 278        pca963x_leds = devm_kzalloc(&client->dev,
 279                        sizeof(struct led_info) * chip->n_leds, GFP_KERNEL);
 280        if (!pca963x_leds)
 281                return ERR_PTR(-ENOMEM);
 282
 283        for_each_child_of_node(np, child) {
 284                struct led_info led;
 285                u32 reg;
 286                int res;
 287
 288                res = of_property_read_u32(child, "reg", &reg);
 289                if ((res != 0) || (reg >= chip->n_leds))
 290                        continue;
 291                led.name =
 292                        of_get_property(child, "label", NULL) ? : child->name;
 293                led.default_trigger =
 294                        of_get_property(child, "linux,default-trigger", NULL);
 295                pca963x_leds[reg] = led;
 296        }
 297        pdata = devm_kzalloc(&client->dev,
 298                             sizeof(struct pca963x_platform_data), GFP_KERNEL);
 299        if (!pdata)
 300                return ERR_PTR(-ENOMEM);
 301
 302        pdata->leds.leds = pca963x_leds;
 303        pdata->leds.num_leds = chip->n_leds;
 304
 305        /* default to open-drain unless totem pole (push-pull) is specified */
 306        if (of_property_read_bool(np, "nxp,totem-pole"))
 307                pdata->outdrv = PCA963X_TOTEM_POLE;
 308        else
 309                pdata->outdrv = PCA963X_OPEN_DRAIN;
 310
 311        /* default to software blinking unless hardware blinking is specified */
 312        if (of_property_read_bool(np, "nxp,hw-blink"))
 313                pdata->blink_type = PCA963X_HW_BLINK;
 314        else
 315                pdata->blink_type = PCA963X_SW_BLINK;
 316
 317        return pdata;
 318}
 319
 320static const struct of_device_id of_pca963x_match[] = {
 321        { .compatible = "nxp,pca9632", },
 322        { .compatible = "nxp,pca9633", },
 323        { .compatible = "nxp,pca9634", },
 324        {},
 325};
 326#else
 327static struct pca963x_platform_data *
 328pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip)
 329{
 330        return ERR_PTR(-ENODEV);
 331}
 332#endif
 333
 334static int pca963x_probe(struct i2c_client *client,
 335                                        const struct i2c_device_id *id)
 336{
 337        struct pca963x *pca963x_chip;
 338        struct pca963x_led *pca963x;
 339        struct pca963x_platform_data *pdata;
 340        struct pca963x_chipdef *chip;
 341        int i, err;
 342
 343        chip = &pca963x_chipdefs[id->driver_data];
 344        pdata = dev_get_platdata(&client->dev);
 345
 346        if (!pdata) {
 347                pdata = pca963x_dt_init(client, chip);
 348                if (IS_ERR(pdata)) {
 349                        dev_warn(&client->dev, "could not parse configuration\n");
 350                        pdata = NULL;
 351                }
 352        }
 353
 354        if (pdata && (pdata->leds.num_leds < 1 ||
 355                                 pdata->leds.num_leds > chip->n_leds)) {
 356                dev_err(&client->dev, "board info must claim 1-%d LEDs",
 357                                                                chip->n_leds);
 358                return -EINVAL;
 359        }
 360
 361        pca963x_chip = devm_kzalloc(&client->dev, sizeof(*pca963x_chip),
 362                                                                GFP_KERNEL);
 363        if (!pca963x_chip)
 364                return -ENOMEM;
 365        pca963x = devm_kzalloc(&client->dev, chip->n_leds * sizeof(*pca963x),
 366                                                                GFP_KERNEL);
 367        if (!pca963x)
 368                return -ENOMEM;
 369
 370        i2c_set_clientdata(client, pca963x_chip);
 371
 372        mutex_init(&pca963x_chip->mutex);
 373        pca963x_chip->chipdef = chip;
 374        pca963x_chip->client = client;
 375        pca963x_chip->leds = pca963x;
 376
 377        /* Turn off LEDs by default*/
 378        i2c_smbus_write_byte_data(client, chip->ledout_base, 0x00);
 379        if (chip->n_leds > 4)
 380                i2c_smbus_write_byte_data(client, chip->ledout_base + 1, 0x00);
 381
 382        for (i = 0; i < chip->n_leds; i++) {
 383                pca963x[i].led_num = i;
 384                pca963x[i].chip = pca963x_chip;
 385
 386                /* Platform data can specify LED names and default triggers */
 387                if (pdata && i < pdata->leds.num_leds) {
 388                        if (pdata->leds.leds[i].name)
 389                                snprintf(pca963x[i].name,
 390                                         sizeof(pca963x[i].name), "pca963x:%s",
 391                                         pdata->leds.leds[i].name);
 392                        if (pdata->leds.leds[i].default_trigger)
 393                                pca963x[i].led_cdev.default_trigger =
 394                                        pdata->leds.leds[i].default_trigger;
 395                }
 396                if (!pdata || i >= pdata->leds.num_leds ||
 397                                                !pdata->leds.leds[i].name)
 398                        snprintf(pca963x[i].name, sizeof(pca963x[i].name),
 399                                 "pca963x:%d:%.2x:%d", client->adapter->nr,
 400                                 client->addr, i);
 401
 402                pca963x[i].led_cdev.name = pca963x[i].name;
 403                pca963x[i].led_cdev.brightness_set = pca963x_led_set;
 404
 405                if (pdata && pdata->blink_type == PCA963X_HW_BLINK)
 406                        pca963x[i].led_cdev.blink_set = pca963x_blink_set;
 407
 408                INIT_WORK(&pca963x[i].work, pca963x_work);
 409
 410                err = led_classdev_register(&client->dev, &pca963x[i].led_cdev);
 411                if (err < 0)
 412                        goto exit;
 413        }
 414
 415        /* Disable LED all-call address and set normal mode */
 416        i2c_smbus_write_byte_data(client, PCA963X_MODE1, 0x00);
 417
 418        /* Configure output: open-drain or totem pole (push-pull) */
 419        if (pdata && pdata->outdrv == PCA963X_OPEN_DRAIN)
 420                i2c_smbus_write_byte_data(client, PCA963X_MODE2, 0x01);
 421
 422        return 0;
 423
 424exit:
 425        while (i--) {
 426                led_classdev_unregister(&pca963x[i].led_cdev);
 427                cancel_work_sync(&pca963x[i].work);
 428        }
 429
 430        return err;
 431}
 432
 433static int pca963x_remove(struct i2c_client *client)
 434{
 435        struct pca963x *pca963x = i2c_get_clientdata(client);
 436        int i;
 437
 438        for (i = 0; i < pca963x->chipdef->n_leds; i++) {
 439                led_classdev_unregister(&pca963x->leds[i].led_cdev);
 440                cancel_work_sync(&pca963x->leds[i].work);
 441        }
 442
 443        return 0;
 444}
 445
 446static struct i2c_driver pca963x_driver = {
 447        .driver = {
 448                .name   = "leds-pca963x",
 449                .owner  = THIS_MODULE,
 450                .of_match_table = of_match_ptr(of_pca963x_match),
 451        },
 452        .probe  = pca963x_probe,
 453        .remove = pca963x_remove,
 454        .id_table = pca963x_id,
 455};
 456
 457module_i2c_driver(pca963x_driver);
 458
 459MODULE_AUTHOR("Peter Meerwald <p.meerwald@bct-electronic.com>");
 460MODULE_DESCRIPTION("PCA963X LED driver");
 461MODULE_LICENSE("GPL v2");
 462
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.