Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Driver for ISSI IS31FL32xx family of I2C LED controllers
0004  *
0005  * Copyright 2015 Allworx Corp.
0006  *
0007  * Datasheets:
0008  *   http://www.issi.com/US/product-analog-fxled-driver.shtml
0009  *   http://www.si-en.com/product.asp?parentid=890
0010  */
0011 
0012 #include <linux/device.h>
0013 #include <linux/i2c.h>
0014 #include <linux/kernel.h>
0015 #include <linux/leds.h>
0016 #include <linux/module.h>
0017 #include <linux/of.h>
0018 #include <linux/of_device.h>
0019 
0020 /* Used to indicate a device has no such register */
0021 #define IS31FL32XX_REG_NONE 0xFF
0022 
0023 /* Software Shutdown bit in Shutdown Register */
0024 #define IS31FL32XX_SHUTDOWN_SSD_ENABLE  0
0025 #define IS31FL32XX_SHUTDOWN_SSD_DISABLE BIT(0)
0026 
0027 /* IS31FL3216 has a number of unique registers */
0028 #define IS31FL3216_CONFIG_REG 0x00
0029 #define IS31FL3216_LIGHTING_EFFECT_REG 0x03
0030 #define IS31FL3216_CHANNEL_CONFIG_REG 0x04
0031 
0032 /* Software Shutdown bit in 3216 Config Register */
0033 #define IS31FL3216_CONFIG_SSD_ENABLE  BIT(7)
0034 #define IS31FL3216_CONFIG_SSD_DISABLE 0
0035 
0036 struct is31fl32xx_priv;
0037 struct is31fl32xx_led_data {
0038     struct led_classdev cdev;
0039     u8 channel; /* 1-based, max priv->cdef->channels */
0040     struct is31fl32xx_priv *priv;
0041 };
0042 
0043 struct is31fl32xx_priv {
0044     const struct is31fl32xx_chipdef *cdef;
0045     struct i2c_client *client;
0046     unsigned int num_leds;
0047     struct is31fl32xx_led_data leds[];
0048 };
0049 
0050 /**
0051  * struct is31fl32xx_chipdef - chip-specific attributes
0052  * @channels            : Number of LED channels
0053  * @shutdown_reg        : address of Shutdown register (optional)
0054  * @pwm_update_reg      : address of PWM Update register
0055  * @global_control_reg  : address of Global Control register (optional)
0056  * @reset_reg           : address of Reset register (optional)
0057  * @pwm_register_base   : address of first PWM register
0058  * @pwm_registers_reversed: : true if PWM registers count down instead of up
0059  * @led_control_register_base : address of first LED control register (optional)
0060  * @enable_bits_per_led_control_register: number of LEDs enable bits in each
0061  * @reset_func          : pointer to reset function
0062  * @sw_shutdown_func    : pointer to software shutdown function
0063  *
0064  * For all optional register addresses, the sentinel value %IS31FL32XX_REG_NONE
0065  * indicates that this chip has no such register.
0066  *
0067  * If non-NULL, @reset_func will be called during probing to set all
0068  * necessary registers to a known initialization state. This is needed
0069  * for chips that do not have a @reset_reg.
0070  *
0071  * @enable_bits_per_led_control_register must be >=1 if
0072  * @led_control_register_base != %IS31FL32XX_REG_NONE.
0073  */
0074 struct is31fl32xx_chipdef {
0075     u8  channels;
0076     u8  shutdown_reg;
0077     u8  pwm_update_reg;
0078     u8  global_control_reg;
0079     u8  reset_reg;
0080     u8  pwm_register_base;
0081     bool    pwm_registers_reversed;
0082     u8  led_control_register_base;
0083     u8  enable_bits_per_led_control_register;
0084     int (*reset_func)(struct is31fl32xx_priv *priv);
0085     int (*sw_shutdown_func)(struct is31fl32xx_priv *priv, bool enable);
0086 };
0087 
0088 static const struct is31fl32xx_chipdef is31fl3236_cdef = {
0089     .channels               = 36,
0090     .shutdown_reg               = 0x00,
0091     .pwm_update_reg             = 0x25,
0092     .global_control_reg         = 0x4a,
0093     .reset_reg              = 0x4f,
0094     .pwm_register_base          = 0x01,
0095     .led_control_register_base      = 0x26,
0096     .enable_bits_per_led_control_register   = 1,
0097 };
0098 
0099 static const struct is31fl32xx_chipdef is31fl3235_cdef = {
0100     .channels               = 28,
0101     .shutdown_reg               = 0x00,
0102     .pwm_update_reg             = 0x25,
0103     .global_control_reg         = 0x4a,
0104     .reset_reg              = 0x4f,
0105     .pwm_register_base          = 0x05,
0106     .led_control_register_base      = 0x2a,
0107     .enable_bits_per_led_control_register   = 1,
0108 };
0109 
0110 static const struct is31fl32xx_chipdef is31fl3218_cdef = {
0111     .channels               = 18,
0112     .shutdown_reg               = 0x00,
0113     .pwm_update_reg             = 0x16,
0114     .global_control_reg         = IS31FL32XX_REG_NONE,
0115     .reset_reg              = 0x17,
0116     .pwm_register_base          = 0x01,
0117     .led_control_register_base      = 0x13,
0118     .enable_bits_per_led_control_register   = 6,
0119 };
0120 
0121 static int is31fl3216_reset(struct is31fl32xx_priv *priv);
0122 static int is31fl3216_software_shutdown(struct is31fl32xx_priv *priv,
0123                     bool enable);
0124 static const struct is31fl32xx_chipdef is31fl3216_cdef = {
0125     .channels               = 16,
0126     .shutdown_reg               = IS31FL32XX_REG_NONE,
0127     .pwm_update_reg             = 0xB0,
0128     .global_control_reg         = IS31FL32XX_REG_NONE,
0129     .reset_reg              = IS31FL32XX_REG_NONE,
0130     .pwm_register_base          = 0x10,
0131     .pwm_registers_reversed         = true,
0132     .led_control_register_base      = 0x01,
0133     .enable_bits_per_led_control_register   = 8,
0134     .reset_func             = is31fl3216_reset,
0135     .sw_shutdown_func           = is31fl3216_software_shutdown,
0136 };
0137 
0138 static int is31fl32xx_write(struct is31fl32xx_priv *priv, u8 reg, u8 val)
0139 {
0140     int ret;
0141 
0142     dev_dbg(&priv->client->dev, "writing register 0x%02X=0x%02X", reg, val);
0143 
0144     ret =  i2c_smbus_write_byte_data(priv->client, reg, val);
0145     if (ret) {
0146         dev_err(&priv->client->dev,
0147             "register write to 0x%02X failed (error %d)",
0148             reg, ret);
0149     }
0150     return ret;
0151 }
0152 
0153 /*
0154  * Custom reset function for IS31FL3216 because it does not have a RESET
0155  * register the way that the other IS31FL32xx chips do. We don't bother
0156  * writing the GPIO and animation registers, because the registers we
0157  * do write ensure those will have no effect.
0158  */
0159 static int is31fl3216_reset(struct is31fl32xx_priv *priv)
0160 {
0161     unsigned int i;
0162     int ret;
0163 
0164     ret = is31fl32xx_write(priv, IS31FL3216_CONFIG_REG,
0165                    IS31FL3216_CONFIG_SSD_ENABLE);
0166     if (ret)
0167         return ret;
0168     for (i = 0; i < priv->cdef->channels; i++) {
0169         ret = is31fl32xx_write(priv, priv->cdef->pwm_register_base+i,
0170                        0x00);
0171         if (ret)
0172             return ret;
0173     }
0174     ret = is31fl32xx_write(priv, priv->cdef->pwm_update_reg, 0);
0175     if (ret)
0176         return ret;
0177     ret = is31fl32xx_write(priv, IS31FL3216_LIGHTING_EFFECT_REG, 0x00);
0178     if (ret)
0179         return ret;
0180     ret = is31fl32xx_write(priv, IS31FL3216_CHANNEL_CONFIG_REG, 0x00);
0181     if (ret)
0182         return ret;
0183 
0184     return 0;
0185 }
0186 
0187 /*
0188  * Custom Software-Shutdown function for IS31FL3216 because it does not have
0189  * a SHUTDOWN register the way that the other IS31FL32xx chips do.
0190  * We don't bother doing a read/modify/write on the CONFIG register because
0191  * we only ever use a value of '0' for the other fields in that register.
0192  */
0193 static int is31fl3216_software_shutdown(struct is31fl32xx_priv *priv,
0194                     bool enable)
0195 {
0196     u8 value = enable ? IS31FL3216_CONFIG_SSD_ENABLE :
0197                 IS31FL3216_CONFIG_SSD_DISABLE;
0198 
0199     return is31fl32xx_write(priv, IS31FL3216_CONFIG_REG, value);
0200 }
0201 
0202 /*
0203  * NOTE: A mutex is not needed in this function because:
0204  * - All referenced data is read-only after probe()
0205  * - The I2C core has a mutex on to protect the bus
0206  * - There are no read/modify/write operations
0207  * - Intervening operations between the write of the PWM register
0208  *   and the Update register are harmless.
0209  *
0210  * Example:
0211  *  PWM_REG_1 write 16
0212  *  UPDATE_REG write 0
0213  *  PWM_REG_2 write 128
0214  *  UPDATE_REG write 0
0215  *   vs:
0216  *  PWM_REG_1 write 16
0217  *  PWM_REG_2 write 128
0218  *  UPDATE_REG write 0
0219  *  UPDATE_REG write 0
0220  * are equivalent. Poking the Update register merely applies all PWM
0221  * register writes up to that point.
0222  */
0223 static int is31fl32xx_brightness_set(struct led_classdev *led_cdev,
0224                      enum led_brightness brightness)
0225 {
0226     const struct is31fl32xx_led_data *led_data =
0227         container_of(led_cdev, struct is31fl32xx_led_data, cdev);
0228     const struct is31fl32xx_chipdef *cdef = led_data->priv->cdef;
0229     u8 pwm_register_offset;
0230     int ret;
0231 
0232     dev_dbg(led_cdev->dev, "%s: %d\n", __func__, brightness);
0233 
0234     /* NOTE: led_data->channel is 1-based */
0235     if (cdef->pwm_registers_reversed)
0236         pwm_register_offset = cdef->channels - led_data->channel;
0237     else
0238         pwm_register_offset = led_data->channel - 1;
0239 
0240     ret = is31fl32xx_write(led_data->priv,
0241                    cdef->pwm_register_base + pwm_register_offset,
0242                    brightness);
0243     if (ret)
0244         return ret;
0245 
0246     return is31fl32xx_write(led_data->priv, cdef->pwm_update_reg, 0);
0247 }
0248 
0249 static int is31fl32xx_reset_regs(struct is31fl32xx_priv *priv)
0250 {
0251     const struct is31fl32xx_chipdef *cdef = priv->cdef;
0252     int ret;
0253 
0254     if (cdef->reset_reg != IS31FL32XX_REG_NONE) {
0255         ret = is31fl32xx_write(priv, cdef->reset_reg, 0);
0256         if (ret)
0257             return ret;
0258     }
0259 
0260     if (cdef->reset_func)
0261         return cdef->reset_func(priv);
0262 
0263     return 0;
0264 }
0265 
0266 static int is31fl32xx_software_shutdown(struct is31fl32xx_priv *priv,
0267                     bool enable)
0268 {
0269     const struct is31fl32xx_chipdef *cdef = priv->cdef;
0270     int ret;
0271 
0272     if (cdef->shutdown_reg != IS31FL32XX_REG_NONE) {
0273         u8 value = enable ? IS31FL32XX_SHUTDOWN_SSD_ENABLE :
0274                     IS31FL32XX_SHUTDOWN_SSD_DISABLE;
0275         ret = is31fl32xx_write(priv, cdef->shutdown_reg, value);
0276         if (ret)
0277             return ret;
0278     }
0279 
0280     if (cdef->sw_shutdown_func)
0281         return cdef->sw_shutdown_func(priv, enable);
0282 
0283     return 0;
0284 }
0285 
0286 static int is31fl32xx_init_regs(struct is31fl32xx_priv *priv)
0287 {
0288     const struct is31fl32xx_chipdef *cdef = priv->cdef;
0289     int ret;
0290 
0291     ret = is31fl32xx_reset_regs(priv);
0292     if (ret)
0293         return ret;
0294 
0295     /*
0296      * Set enable bit for all channels.
0297      * We will control state with PWM registers alone.
0298      */
0299     if (cdef->led_control_register_base != IS31FL32XX_REG_NONE) {
0300         u8 value =
0301             GENMASK(cdef->enable_bits_per_led_control_register-1, 0);
0302         u8 num_regs = cdef->channels /
0303                 cdef->enable_bits_per_led_control_register;
0304         int i;
0305 
0306         for (i = 0; i < num_regs; i++) {
0307             ret = is31fl32xx_write(priv,
0308                            cdef->led_control_register_base+i,
0309                            value);
0310             if (ret)
0311                 return ret;
0312         }
0313     }
0314 
0315     ret = is31fl32xx_software_shutdown(priv, false);
0316     if (ret)
0317         return ret;
0318 
0319     if (cdef->global_control_reg != IS31FL32XX_REG_NONE) {
0320         ret = is31fl32xx_write(priv, cdef->global_control_reg, 0x00);
0321         if (ret)
0322             return ret;
0323     }
0324 
0325     return 0;
0326 }
0327 
0328 static int is31fl32xx_parse_child_dt(const struct device *dev,
0329                      const struct device_node *child,
0330                      struct is31fl32xx_led_data *led_data)
0331 {
0332     struct led_classdev *cdev = &led_data->cdev;
0333     int ret = 0;
0334     u32 reg;
0335 
0336     ret = of_property_read_u32(child, "reg", &reg);
0337     if (ret || reg < 1 || reg > led_data->priv->cdef->channels) {
0338         dev_err(dev,
0339             "Child node %pOF does not have a valid reg property\n",
0340             child);
0341         return -EINVAL;
0342     }
0343     led_data->channel = reg;
0344 
0345     cdev->brightness_set_blocking = is31fl32xx_brightness_set;
0346 
0347     return 0;
0348 }
0349 
0350 static struct is31fl32xx_led_data *is31fl32xx_find_led_data(
0351                     struct is31fl32xx_priv *priv,
0352                     u8 channel)
0353 {
0354     size_t i;
0355 
0356     for (i = 0; i < priv->num_leds; i++) {
0357         if (priv->leds[i].channel == channel)
0358             return &priv->leds[i];
0359     }
0360 
0361     return NULL;
0362 }
0363 
0364 static int is31fl32xx_parse_dt(struct device *dev,
0365                    struct is31fl32xx_priv *priv)
0366 {
0367     struct device_node *child;
0368     int ret = 0;
0369 
0370     for_each_available_child_of_node(dev_of_node(dev), child) {
0371         struct led_init_data init_data = {};
0372         struct is31fl32xx_led_data *led_data =
0373             &priv->leds[priv->num_leds];
0374         const struct is31fl32xx_led_data *other_led_data;
0375 
0376         led_data->priv = priv;
0377 
0378         ret = is31fl32xx_parse_child_dt(dev, child, led_data);
0379         if (ret)
0380             goto err;
0381 
0382         /* Detect if channel is already in use by another child */
0383         other_led_data = is31fl32xx_find_led_data(priv,
0384                               led_data->channel);
0385         if (other_led_data) {
0386             dev_err(dev,
0387                 "Node %pOF 'reg' conflicts with another LED\n",
0388                 child);
0389             ret = -EINVAL;
0390             goto err;
0391         }
0392 
0393         init_data.fwnode = of_fwnode_handle(child);
0394 
0395         ret = devm_led_classdev_register_ext(dev, &led_data->cdev,
0396                              &init_data);
0397         if (ret) {
0398             dev_err(dev, "Failed to register LED for %pOF: %d\n",
0399                 child, ret);
0400             goto err;
0401         }
0402 
0403         priv->num_leds++;
0404     }
0405 
0406     return 0;
0407 
0408 err:
0409     of_node_put(child);
0410     return ret;
0411 }
0412 
0413 static const struct of_device_id of_is31fl32xx_match[] = {
0414     { .compatible = "issi,is31fl3236", .data = &is31fl3236_cdef, },
0415     { .compatible = "issi,is31fl3235", .data = &is31fl3235_cdef, },
0416     { .compatible = "issi,is31fl3218", .data = &is31fl3218_cdef, },
0417     { .compatible = "si-en,sn3218",    .data = &is31fl3218_cdef, },
0418     { .compatible = "issi,is31fl3216", .data = &is31fl3216_cdef, },
0419     { .compatible = "si-en,sn3216",    .data = &is31fl3216_cdef, },
0420     {},
0421 };
0422 
0423 MODULE_DEVICE_TABLE(of, of_is31fl32xx_match);
0424 
0425 static int is31fl32xx_probe(struct i2c_client *client,
0426                 const struct i2c_device_id *id)
0427 {
0428     const struct is31fl32xx_chipdef *cdef;
0429     struct device *dev = &client->dev;
0430     struct is31fl32xx_priv *priv;
0431     int count;
0432     int ret = 0;
0433 
0434     cdef = device_get_match_data(dev);
0435 
0436     count = of_get_available_child_count(dev_of_node(dev));
0437     if (!count)
0438         return -EINVAL;
0439 
0440     priv = devm_kzalloc(dev, struct_size(priv, leds, count),
0441                 GFP_KERNEL);
0442     if (!priv)
0443         return -ENOMEM;
0444 
0445     priv->client = client;
0446     priv->cdef = cdef;
0447     i2c_set_clientdata(client, priv);
0448 
0449     ret = is31fl32xx_init_regs(priv);
0450     if (ret)
0451         return ret;
0452 
0453     ret = is31fl32xx_parse_dt(dev, priv);
0454     if (ret)
0455         return ret;
0456 
0457     return 0;
0458 }
0459 
0460 static int is31fl32xx_remove(struct i2c_client *client)
0461 {
0462     struct is31fl32xx_priv *priv = i2c_get_clientdata(client);
0463     int ret;
0464 
0465     ret = is31fl32xx_reset_regs(priv);
0466     if (ret)
0467         dev_err(&client->dev, "Failed to reset registers on removal (%pe)\n",
0468             ERR_PTR(ret));
0469 
0470     return 0;
0471 }
0472 
0473 /*
0474  * i2c-core (and modalias) requires that id_table be properly filled,
0475  * even though it is not used for DeviceTree based instantiation.
0476  */
0477 static const struct i2c_device_id is31fl32xx_id[] = {
0478     { "is31fl3236" },
0479     { "is31fl3235" },
0480     { "is31fl3218" },
0481     { "sn3218" },
0482     { "is31fl3216" },
0483     { "sn3216" },
0484     {},
0485 };
0486 
0487 MODULE_DEVICE_TABLE(i2c, is31fl32xx_id);
0488 
0489 static struct i2c_driver is31fl32xx_driver = {
0490     .driver = {
0491         .name   = "is31fl32xx",
0492         .of_match_table = of_is31fl32xx_match,
0493     },
0494     .probe      = is31fl32xx_probe,
0495     .remove     = is31fl32xx_remove,
0496     .id_table   = is31fl32xx_id,
0497 };
0498 
0499 module_i2c_driver(is31fl32xx_driver);
0500 
0501 MODULE_AUTHOR("David Rivshin <drivshin@allworx.com>");
0502 MODULE_DESCRIPTION("ISSI IS31FL32xx LED driver");
0503 MODULE_LICENSE("GPL v2");