^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");