0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include <linux/module.h>
0026 #include <linux/delay.h>
0027 #include <linux/string.h>
0028 #include <linux/ctype.h>
0029 #include <linux/leds.h>
0030 #include <linux/err.h>
0031 #include <linux/i2c.h>
0032 #include <linux/property.h>
0033 #include <linux/slab.h>
0034 #include <linux/of.h>
0035
0036
0037 #define PCA963X_LED_OFF 0x0
0038 #define PCA963X_LED_ON 0x1
0039 #define PCA963X_LED_PWM 0x2
0040 #define PCA963X_LED_GRP_PWM 0x3
0041
0042 #define PCA963X_MODE2_OUTDRV 0x04
0043 #define PCA963X_MODE2_INVRT 0x10
0044 #define PCA963X_MODE2_DMBLNK 0x20
0045
0046 #define PCA963X_MODE1 0x00
0047 #define PCA963X_MODE2 0x01
0048 #define PCA963X_PWM_BASE 0x02
0049
0050 enum pca963x_type {
0051 pca9633,
0052 pca9634,
0053 pca9635,
0054 };
0055
0056 struct pca963x_chipdef {
0057 u8 grppwm;
0058 u8 grpfreq;
0059 u8 ledout_base;
0060 int n_leds;
0061 unsigned int scaling;
0062 };
0063
0064 static struct pca963x_chipdef pca963x_chipdefs[] = {
0065 [pca9633] = {
0066 .grppwm = 0x6,
0067 .grpfreq = 0x7,
0068 .ledout_base = 0x8,
0069 .n_leds = 4,
0070 },
0071 [pca9634] = {
0072 .grppwm = 0xa,
0073 .grpfreq = 0xb,
0074 .ledout_base = 0xc,
0075 .n_leds = 8,
0076 },
0077 [pca9635] = {
0078 .grppwm = 0x12,
0079 .grpfreq = 0x13,
0080 .ledout_base = 0x14,
0081 .n_leds = 16,
0082 },
0083 };
0084
0085
0086 #define PCA963X_BLINK_PERIOD_MIN 42
0087 #define PCA963X_BLINK_PERIOD_MAX 10667
0088
0089 static const struct i2c_device_id pca963x_id[] = {
0090 { "pca9632", pca9633 },
0091 { "pca9633", pca9633 },
0092 { "pca9634", pca9634 },
0093 { "pca9635", pca9635 },
0094 { }
0095 };
0096 MODULE_DEVICE_TABLE(i2c, pca963x_id);
0097
0098 struct pca963x;
0099
0100 struct pca963x_led {
0101 struct pca963x *chip;
0102 struct led_classdev led_cdev;
0103 int led_num;
0104 u8 gdc;
0105 u8 gfrq;
0106 };
0107
0108 struct pca963x {
0109 struct pca963x_chipdef *chipdef;
0110 struct mutex mutex;
0111 struct i2c_client *client;
0112 unsigned long leds_on;
0113 struct pca963x_led leds[];
0114 };
0115
0116 static int pca963x_brightness(struct pca963x_led *led,
0117 enum led_brightness brightness)
0118 {
0119 struct i2c_client *client = led->chip->client;
0120 struct pca963x_chipdef *chipdef = led->chip->chipdef;
0121 u8 ledout_addr, ledout, mask, val;
0122 int shift;
0123 int ret;
0124
0125 ledout_addr = chipdef->ledout_base + (led->led_num / 4);
0126 shift = 2 * (led->led_num % 4);
0127 mask = 0x3 << shift;
0128 ledout = i2c_smbus_read_byte_data(client, ledout_addr);
0129
0130 switch (brightness) {
0131 case LED_FULL:
0132 val = (ledout & ~mask) | (PCA963X_LED_ON << shift);
0133 ret = i2c_smbus_write_byte_data(client, ledout_addr, val);
0134 break;
0135 case LED_OFF:
0136 val = ledout & ~mask;
0137 ret = i2c_smbus_write_byte_data(client, ledout_addr, val);
0138 break;
0139 default:
0140 ret = i2c_smbus_write_byte_data(client,
0141 PCA963X_PWM_BASE +
0142 led->led_num,
0143 brightness);
0144 if (ret < 0)
0145 return ret;
0146
0147 val = (ledout & ~mask) | (PCA963X_LED_PWM << shift);
0148 ret = i2c_smbus_write_byte_data(client, ledout_addr, val);
0149 break;
0150 }
0151
0152 return ret;
0153 }
0154
0155 static void pca963x_blink(struct pca963x_led *led)
0156 {
0157 struct i2c_client *client = led->chip->client;
0158 struct pca963x_chipdef *chipdef = led->chip->chipdef;
0159 u8 ledout_addr, ledout, mask, val, mode2;
0160 int shift;
0161
0162 ledout_addr = chipdef->ledout_base + (led->led_num / 4);
0163 shift = 2 * (led->led_num % 4);
0164 mask = 0x3 << shift;
0165 mode2 = i2c_smbus_read_byte_data(client, PCA963X_MODE2);
0166
0167 i2c_smbus_write_byte_data(client, chipdef->grppwm, led->gdc);
0168
0169 i2c_smbus_write_byte_data(client, chipdef->grpfreq, led->gfrq);
0170
0171 if (!(mode2 & PCA963X_MODE2_DMBLNK))
0172 i2c_smbus_write_byte_data(client, PCA963X_MODE2,
0173 mode2 | PCA963X_MODE2_DMBLNK);
0174
0175 mutex_lock(&led->chip->mutex);
0176
0177 ledout = i2c_smbus_read_byte_data(client, ledout_addr);
0178 if ((ledout & mask) != (PCA963X_LED_GRP_PWM << shift)) {
0179 val = (ledout & ~mask) | (PCA963X_LED_GRP_PWM << shift);
0180 i2c_smbus_write_byte_data(client, ledout_addr, val);
0181 }
0182
0183 mutex_unlock(&led->chip->mutex);
0184 }
0185
0186 static int pca963x_power_state(struct pca963x_led *led)
0187 {
0188 struct i2c_client *client = led->chip->client;
0189 unsigned long *leds_on = &led->chip->leds_on;
0190 unsigned long cached_leds = *leds_on;
0191
0192 if (led->led_cdev.brightness)
0193 set_bit(led->led_num, leds_on);
0194 else
0195 clear_bit(led->led_num, leds_on);
0196
0197 if (!(*leds_on) != !cached_leds)
0198 return i2c_smbus_write_byte_data(client, PCA963X_MODE1,
0199 *leds_on ? 0 : BIT(4));
0200
0201 return 0;
0202 }
0203
0204 static int pca963x_led_set(struct led_classdev *led_cdev,
0205 enum led_brightness value)
0206 {
0207 struct pca963x_led *led;
0208 int ret;
0209
0210 led = container_of(led_cdev, struct pca963x_led, led_cdev);
0211
0212 mutex_lock(&led->chip->mutex);
0213
0214 ret = pca963x_brightness(led, value);
0215 if (ret < 0)
0216 goto unlock;
0217 ret = pca963x_power_state(led);
0218
0219 unlock:
0220 mutex_unlock(&led->chip->mutex);
0221 return ret;
0222 }
0223
0224 static unsigned int pca963x_period_scale(struct pca963x_led *led,
0225 unsigned int val)
0226 {
0227 unsigned int scaling = led->chip->chipdef->scaling;
0228
0229 return scaling ? DIV_ROUND_CLOSEST(val * scaling, 1000) : val;
0230 }
0231
0232 static int pca963x_blink_set(struct led_classdev *led_cdev,
0233 unsigned long *delay_on, unsigned long *delay_off)
0234 {
0235 unsigned long time_on, time_off, period;
0236 struct pca963x_led *led;
0237 u8 gdc, gfrq;
0238
0239 led = container_of(led_cdev, struct pca963x_led, led_cdev);
0240
0241 time_on = *delay_on;
0242 time_off = *delay_off;
0243
0244
0245 if (!time_on && !time_off) {
0246 time_on = 500;
0247 time_off = 500;
0248 }
0249
0250 period = pca963x_period_scale(led, time_on + time_off);
0251
0252
0253 if ((period < PCA963X_BLINK_PERIOD_MIN) ||
0254 (period > PCA963X_BLINK_PERIOD_MAX)) {
0255 time_on = 500;
0256 time_off = 500;
0257 period = pca963x_period_scale(led, 1000);
0258 }
0259
0260
0261
0262
0263
0264
0265 gdc = (pca963x_period_scale(led, time_on) * 256) / period;
0266
0267
0268
0269
0270
0271
0272 gfrq = (period * 24 / 1000) - 1;
0273
0274 led->gdc = gdc;
0275 led->gfrq = gfrq;
0276
0277 pca963x_blink(led);
0278
0279 *delay_on = time_on;
0280 *delay_off = time_off;
0281
0282 return 0;
0283 }
0284
0285 static int pca963x_register_leds(struct i2c_client *client,
0286 struct pca963x *chip)
0287 {
0288 struct pca963x_chipdef *chipdef = chip->chipdef;
0289 struct pca963x_led *led = chip->leds;
0290 struct device *dev = &client->dev;
0291 struct fwnode_handle *child;
0292 bool hw_blink;
0293 s32 mode2;
0294 u32 reg;
0295 int ret;
0296
0297 if (device_property_read_u32(dev, "nxp,period-scale",
0298 &chipdef->scaling))
0299 chipdef->scaling = 1000;
0300
0301 hw_blink = device_property_read_bool(dev, "nxp,hw-blink");
0302
0303 mode2 = i2c_smbus_read_byte_data(client, PCA963X_MODE2);
0304 if (mode2 < 0)
0305 return mode2;
0306
0307
0308 if (device_property_read_bool(dev, "nxp,totem-pole"))
0309 mode2 |= PCA963X_MODE2_OUTDRV;
0310 else
0311 mode2 &= ~PCA963X_MODE2_OUTDRV;
0312
0313
0314 if (device_property_read_bool(dev, "nxp,inverted-out"))
0315 mode2 |= PCA963X_MODE2_INVRT;
0316 else
0317 mode2 &= ~PCA963X_MODE2_INVRT;
0318
0319 ret = i2c_smbus_write_byte_data(client, PCA963X_MODE2, mode2);
0320 if (ret < 0)
0321 return ret;
0322
0323 device_for_each_child_node(dev, child) {
0324 struct led_init_data init_data = {};
0325 char default_label[32];
0326
0327 ret = fwnode_property_read_u32(child, "reg", ®);
0328 if (ret || reg >= chipdef->n_leds) {
0329 dev_err(dev, "Invalid 'reg' property for node %pfw\n",
0330 child);
0331 ret = -EINVAL;
0332 goto err;
0333 }
0334
0335 led->led_num = reg;
0336 led->chip = chip;
0337 led->led_cdev.brightness_set_blocking = pca963x_led_set;
0338 if (hw_blink)
0339 led->led_cdev.blink_set = pca963x_blink_set;
0340
0341 init_data.fwnode = child;
0342
0343 init_data.devicename = "pca963x";
0344 snprintf(default_label, sizeof(default_label), "%d:%.2x:%u",
0345 client->adapter->nr, client->addr, reg);
0346 init_data.default_label = default_label;
0347
0348 ret = devm_led_classdev_register_ext(dev, &led->led_cdev,
0349 &init_data);
0350 if (ret) {
0351 dev_err(dev, "Failed to register LED for node %pfw\n",
0352 child);
0353 goto err;
0354 }
0355
0356 ++led;
0357 }
0358
0359 return 0;
0360 err:
0361 fwnode_handle_put(child);
0362 return ret;
0363 }
0364
0365 static const struct of_device_id of_pca963x_match[] = {
0366 { .compatible = "nxp,pca9632", },
0367 { .compatible = "nxp,pca9633", },
0368 { .compatible = "nxp,pca9634", },
0369 { .compatible = "nxp,pca9635", },
0370 {},
0371 };
0372 MODULE_DEVICE_TABLE(of, of_pca963x_match);
0373
0374 static int pca963x_probe(struct i2c_client *client,
0375 const struct i2c_device_id *id)
0376 {
0377 struct device *dev = &client->dev;
0378 struct pca963x_chipdef *chipdef;
0379 struct pca963x *chip;
0380 int i, count;
0381
0382 chipdef = &pca963x_chipdefs[id->driver_data];
0383
0384 count = device_get_child_node_count(dev);
0385 if (!count || count > chipdef->n_leds) {
0386 dev_err(dev, "Node %pfw must define between 1 and %d LEDs\n",
0387 dev_fwnode(dev), chipdef->n_leds);
0388 return -EINVAL;
0389 }
0390
0391 chip = devm_kzalloc(dev, struct_size(chip, leds, count), GFP_KERNEL);
0392 if (!chip)
0393 return -ENOMEM;
0394
0395 i2c_set_clientdata(client, chip);
0396
0397 mutex_init(&chip->mutex);
0398 chip->chipdef = chipdef;
0399 chip->client = client;
0400
0401
0402 for (i = 0; i < chipdef->n_leds / 4; i++)
0403 i2c_smbus_write_byte_data(client, chipdef->ledout_base + i, 0x00);
0404
0405
0406 i2c_smbus_write_byte_data(client, PCA963X_MODE1, BIT(4));
0407
0408 return pca963x_register_leds(client, chip);
0409 }
0410
0411 static struct i2c_driver pca963x_driver = {
0412 .driver = {
0413 .name = "leds-pca963x",
0414 .of_match_table = of_pca963x_match,
0415 },
0416 .probe = pca963x_probe,
0417 .id_table = pca963x_id,
0418 };
0419
0420 module_i2c_driver(pca963x_driver);
0421
0422 MODULE_AUTHOR("Peter Meerwald <p.meerwald@bct-electronic.com>");
0423 MODULE_DESCRIPTION("PCA963X LED driver");
0424 MODULE_LICENSE("GPL v2");