Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * LP5521/LP5523/LP55231/LP5562 Common Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright 2012 Texas Instruments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Derived from leds-lp5521.c, leds-lp5523.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/leds.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/platform_data/leds-lp55xx.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include "leds-lp55xx-common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) /* External clock rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define LP55XX_CLK_32K			32768
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static struct lp55xx_led *cdev_to_lp55xx_led(struct led_classdev *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	return container_of(cdev, struct lp55xx_led, cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static struct lp55xx_led *dev_to_lp55xx_led(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	return cdev_to_lp55xx_led(dev_get_drvdata(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) static struct lp55xx_led *mcled_cdev_to_led(struct led_classdev_mc *mc_cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	return container_of(mc_cdev, struct lp55xx_led, mc_cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) static void lp55xx_reset_device(struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct lp55xx_device_config *cfg = chip->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	u8 addr = cfg->reset.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	u8 val  = cfg->reset.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	/* no error checking here because no ACK from the device after reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	lp55xx_write(chip, addr, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) static int lp55xx_detect_device(struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	struct lp55xx_device_config *cfg = chip->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	u8 addr = cfg->enable.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	u8 val  = cfg->enable.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	ret = lp55xx_write(chip, addr, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	usleep_range(1000, 2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	ret = lp55xx_read(chip, addr, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	if (val != cfg->enable.val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) static int lp55xx_post_init_device(struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	struct lp55xx_device_config *cfg = chip->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	if (!cfg->post_init_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	return cfg->post_init_device(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) static ssize_t led_current_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			    struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 			    char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	struct lp55xx_led *led = dev_to_lp55xx_led(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	return scnprintf(buf, PAGE_SIZE, "%d\n", led->led_current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) static ssize_t led_current_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 			     struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			     const char *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	struct lp55xx_led *led = dev_to_lp55xx_led(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	struct lp55xx_chip *chip = led->chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	unsigned long curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	if (kstrtoul(buf, 0, &curr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	if (curr > led->max_current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	if (!chip->cfg->set_led_current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	mutex_lock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	chip->cfg->set_led_current(led, (u8)curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	mutex_unlock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static ssize_t max_current_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			    struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			    char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	struct lp55xx_led *led = dev_to_lp55xx_led(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	return scnprintf(buf, PAGE_SIZE, "%d\n", led->max_current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static DEVICE_ATTR_RW(led_current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static DEVICE_ATTR_RO(max_current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static struct attribute *lp55xx_led_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	&dev_attr_led_current.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	&dev_attr_max_current.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ATTRIBUTE_GROUPS(lp55xx_led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int lp55xx_set_mc_brightness(struct led_classdev *cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 				    enum led_brightness brightness)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	struct led_classdev_mc *mc_dev = lcdev_to_mccdev(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	struct lp55xx_led *led = mcled_cdev_to_led(mc_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	struct lp55xx_device_config *cfg = led->chip->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	led_mc_calc_color_components(&led->mc_cdev, brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	return cfg->multicolor_brightness_fn(led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int lp55xx_set_brightness(struct led_classdev *cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			     enum led_brightness brightness)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	struct lp55xx_led *led = cdev_to_lp55xx_led(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	struct lp55xx_device_config *cfg = led->chip->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	led->brightness = (u8)brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	return cfg->brightness_fn(led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static int lp55xx_init_led(struct lp55xx_led *led,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			struct lp55xx_chip *chip, int chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	struct lp55xx_platform_data *pdata = chip->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	struct lp55xx_device_config *cfg = chip->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	struct device *dev = &chip->cl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	int max_channel = cfg->max_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	struct mc_subled *mc_led_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	struct led_classdev *led_cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	char name[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	int i, j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	if (chan >= max_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		dev_err(dev, "invalid channel: %d / %d\n", chan, max_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	if (pdata->led_config[chan].led_current == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	if (pdata->led_config[chan].name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		led->cdev.name = pdata->led_config[chan].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		snprintf(name, sizeof(name), "%s:channel%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 			pdata->label ? : chip->cl->name, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		led->cdev.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	if (pdata->led_config[chan].num_colors > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		mc_led_info = devm_kcalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 					   pdata->led_config[chan].num_colors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 					   sizeof(*mc_led_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		if (!mc_led_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		led_cdev = &led->mc_cdev.led_cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		led_cdev->name = led->cdev.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		led_cdev->brightness_set_blocking = lp55xx_set_mc_brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		led->mc_cdev.num_colors = pdata->led_config[chan].num_colors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		for (i = 0; i < led->mc_cdev.num_colors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			mc_led_info[i].color_index =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 				pdata->led_config[chan].color_id[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			mc_led_info[i].channel =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 					pdata->led_config[chan].output_num[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			j++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		led->mc_cdev.subled_info = mc_led_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		led->cdev.brightness_set_blocking = lp55xx_set_brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	led->cdev.groups = lp55xx_led_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	led->cdev.default_trigger = pdata->led_config[chan].default_trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	led->led_current = pdata->led_config[chan].led_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	led->max_current = pdata->led_config[chan].max_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	led->chan_nr = pdata->led_config[chan].chan_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	if (led->chan_nr >= max_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		dev_err(dev, "Use channel numbers between 0 and %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 			max_channel - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	if (pdata->led_config[chan].num_colors > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		ret = devm_led_classdev_multicolor_register(dev, &led->mc_cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		ret = devm_led_classdev_register(dev, &led->cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		dev_err(dev, "led register err: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static void lp55xx_firmware_loaded(const struct firmware *fw, void *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	struct lp55xx_chip *chip = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	struct device *dev = &chip->cl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	enum lp55xx_engine_index idx = chip->engine_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	if (!fw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		dev_err(dev, "firmware request failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	/* handling firmware data is chip dependent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	mutex_lock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	chip->engines[idx - 1].mode = LP55XX_ENGINE_LOAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	chip->fw = fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	if (chip->cfg->firmware_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		chip->cfg->firmware_cb(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	mutex_unlock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	/* firmware should be released for other channel use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	release_firmware(chip->fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	chip->fw = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static int lp55xx_request_firmware(struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	const char *name = chip->cl->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	struct device *dev = &chip->cl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	return request_firmware_nowait(THIS_MODULE, false, name, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 				GFP_KERNEL, chip, lp55xx_firmware_loaded);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static ssize_t select_engine_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 			    struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			    char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	struct lp55xx_chip *chip = led->chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	return sprintf(buf, "%d\n", chip->engine_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static ssize_t select_engine_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			     struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 			     const char *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	struct lp55xx_chip *chip = led->chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	if (kstrtoul(buf, 0, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	/* select the engine to be run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	case LP55XX_ENGINE_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	case LP55XX_ENGINE_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	case LP55XX_ENGINE_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		mutex_lock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		chip->engine_idx = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		ret = lp55xx_request_firmware(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		mutex_unlock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		dev_err(dev, "%lu: invalid engine index. (1, 2, 3)\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		dev_err(dev, "request firmware err: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static inline void lp55xx_run_engine(struct lp55xx_chip *chip, bool start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	if (chip->cfg->run_engine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		chip->cfg->run_engine(chip, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static ssize_t run_engine_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 			     struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 			     const char *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	struct lp55xx_chip *chip = led->chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	if (kstrtoul(buf, 0, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	/* run or stop the selected engine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	if (val <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		lp55xx_run_engine(chip, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	mutex_lock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	lp55xx_run_engine(chip, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	mutex_unlock(&chip->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static DEVICE_ATTR_RW(select_engine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static DEVICE_ATTR_WO(run_engine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static struct attribute *lp55xx_engine_attributes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	&dev_attr_select_engine.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	&dev_attr_run_engine.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static const struct attribute_group lp55xx_engine_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	.attrs = lp55xx_engine_attributes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int lp55xx_write(struct lp55xx_chip *chip, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	return i2c_smbus_write_byte_data(chip->cl, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) EXPORT_SYMBOL_GPL(lp55xx_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int lp55xx_read(struct lp55xx_chip *chip, u8 reg, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	s32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	ret = i2c_smbus_read_byte_data(chip->cl, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	*val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) EXPORT_SYMBOL_GPL(lp55xx_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int lp55xx_update_bits(struct lp55xx_chip *chip, u8 reg, u8 mask, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	u8 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	ret = lp55xx_read(chip, reg, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	tmp &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	tmp |= val & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	return lp55xx_write(chip, reg, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) EXPORT_SYMBOL_GPL(lp55xx_update_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) bool lp55xx_is_extclk_used(struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	clk = devm_clk_get(&chip->cl->dev, "32k_clk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	if (IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		goto use_internal_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	err = clk_prepare_enable(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		goto use_internal_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	if (clk_get_rate(clk) != LP55XX_CLK_32K) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		clk_disable_unprepare(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		goto use_internal_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	dev_info(&chip->cl->dev, "%dHz external clock used\n",	LP55XX_CLK_32K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	chip->clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) use_internal_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	dev_info(&chip->cl->dev, "internal clock used\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) EXPORT_SYMBOL_GPL(lp55xx_is_extclk_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int lp55xx_init_device(struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	struct lp55xx_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	struct lp55xx_device_config *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	struct device *dev = &chip->cl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	WARN_ON(!chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	pdata = chip->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	cfg = chip->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	if (!pdata || !cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	if (pdata->enable_gpiod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		gpiod_set_consumer_name(pdata->enable_gpiod, "LP55xx enable");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		gpiod_set_value(pdata->enable_gpiod, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 		usleep_range(1000, 2000); /* Keep enable down at least 1ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 		gpiod_set_value(pdata->enable_gpiod, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 		usleep_range(1000, 2000); /* 500us abs min. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	lp55xx_reset_device(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	 * Exact value is not available. 10 - 20ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	 * appears to be enough for reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	usleep_range(10000, 20000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	ret = lp55xx_detect_device(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		dev_err(dev, "device detection err: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	/* chip specific initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	ret = lp55xx_post_init_device(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		dev_err(dev, "post init device err: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		goto err_post_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) err_post_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	lp55xx_deinit_device(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) EXPORT_SYMBOL_GPL(lp55xx_init_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) void lp55xx_deinit_device(struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	struct lp55xx_platform_data *pdata = chip->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	if (chip->clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		clk_disable_unprepare(chip->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	if (pdata->enable_gpiod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		gpiod_set_value(pdata->enable_gpiod, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) EXPORT_SYMBOL_GPL(lp55xx_deinit_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) int lp55xx_register_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	struct lp55xx_platform_data *pdata = chip->pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	struct lp55xx_device_config *cfg = chip->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	int num_channels = pdata->num_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	struct lp55xx_led *each;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	u8 led_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	if (!cfg->brightness_fn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		dev_err(&chip->cl->dev, "empty brightness configuration\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	for (i = 0; i < num_channels; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 		/* do not initialize channels that are not connected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		if (pdata->led_config[i].led_current == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		led_current = pdata->led_config[i].led_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		each = led + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		ret = lp55xx_init_led(each, chip, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 			goto err_init_led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		chip->num_leds++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		each->chip = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		/* setting led current at each channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		if (cfg->set_led_current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 			cfg->set_led_current(each, led_current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) err_init_led:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) EXPORT_SYMBOL_GPL(lp55xx_register_leds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) int lp55xx_register_sysfs(struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	struct device *dev = &chip->cl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	struct lp55xx_device_config *cfg = chip->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	if (!cfg->run_engine || !cfg->firmware_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		goto dev_specific_attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	ret = sysfs_create_group(&dev->kobj, &lp55xx_engine_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) dev_specific_attrs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	return cfg->dev_attr_group ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		sysfs_create_group(&dev->kobj, cfg->dev_attr_group) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) EXPORT_SYMBOL_GPL(lp55xx_register_sysfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	struct device *dev = &chip->cl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	struct lp55xx_device_config *cfg = chip->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	if (cfg->dev_attr_group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		sysfs_remove_group(&dev->kobj, cfg->dev_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	sysfs_remove_group(&dev->kobj, &lp55xx_engine_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static int lp55xx_parse_common_child(struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 				     struct lp55xx_led_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 				     int led_number, int *chan_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	of_property_read_string(np, "chan-name",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 				&cfg[led_number].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	of_property_read_u8(np, "led-cur",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 			    &cfg[led_number].led_current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	of_property_read_u8(np, "max-cur",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 			    &cfg[led_number].max_current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	ret = of_property_read_u32(np, "reg", chan_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	if (*chan_nr < 0 || *chan_nr > cfg->max_channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static int lp55xx_parse_multi_led_child(struct device_node *child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 					 struct lp55xx_led_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 					 int child_number, int color_number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	int chan_nr, color_id, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	ret = lp55xx_parse_common_child(child, cfg, child_number, &chan_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	ret = of_property_read_u32(child, "color", &color_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	cfg[child_number].color_id[color_number] = color_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	cfg[child_number].output_num[color_number] = chan_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static int lp55xx_parse_multi_led(struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 				  struct lp55xx_led_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 				  int child_number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	struct device_node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	int num_colors = 0, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	for_each_available_child_of_node(np, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		ret = lp55xx_parse_multi_led_child(child, cfg, child_number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 						   num_colors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 			of_node_put(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		num_colors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	cfg[child_number].num_colors = num_colors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static int lp55xx_parse_logical_led(struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 				   struct lp55xx_led_config *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 				   int child_number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	int led_color, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	int chan_nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	cfg[child_number].default_trigger =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 		of_get_property(np, "linux,default-trigger", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	ret = of_property_read_u32(np, "color", &led_color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	if (led_color == LED_COLOR_ID_RGB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 		return lp55xx_parse_multi_led(np, cfg, child_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	ret =  lp55xx_parse_common_child(np, cfg, child_number, &chan_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	cfg[child_number].chan_nr = chan_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 						      struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 						      struct lp55xx_chip *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	struct device_node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	struct lp55xx_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	struct lp55xx_led_config *cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	int num_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	num_channels = of_get_available_child_count(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	if (num_channels == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 		dev_err(dev, "no LED channels\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	cfg = devm_kcalloc(dev, num_channels, sizeof(*cfg), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	if (!cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	pdata->led_config = &cfg[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	pdata->num_channels = num_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	cfg->max_channel = chip->cfg->max_channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	for_each_available_child_of_node(np, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 		ret = lp55xx_parse_logical_led(child, cfg, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 			of_node_put(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 			return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 		i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	of_property_read_string(np, "label", &pdata->label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	of_property_read_u8(np, "clock-mode", &pdata->clock_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	pdata->enable_gpiod = devm_gpiod_get_optional(dev, "enable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 						      GPIOD_ASIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	if (IS_ERR(pdata->enable_gpiod))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 		return ERR_CAST(pdata->enable_gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	/* LP8501 specific */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	of_property_read_u8(np, "pwr-sel", (u8 *)&pdata->pwr_sel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 	return pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) EXPORT_SYMBOL_GPL(lp55xx_of_populate_pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) MODULE_DESCRIPTION("LP55xx Common Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) MODULE_LICENSE("GPL");