159ea3c9fSNikita Travkin // SPDX-License-Identifier: GPL-2.0+
259ea3c9fSNikita Travkin // Driver for Awinic AW2013 3-channel LED driver
359ea3c9fSNikita Travkin
459ea3c9fSNikita Travkin #include <linux/i2c.h>
559ea3c9fSNikita Travkin #include <linux/leds.h>
659ea3c9fSNikita Travkin #include <linux/module.h>
759ea3c9fSNikita Travkin #include <linux/regulator/consumer.h>
859ea3c9fSNikita Travkin #include <linux/mutex.h>
959ea3c9fSNikita Travkin #include <linux/of.h>
1059ea3c9fSNikita Travkin #include <linux/regmap.h>
1159ea3c9fSNikita Travkin
1259ea3c9fSNikita Travkin #define AW2013_MAX_LEDS 3
1359ea3c9fSNikita Travkin
1459ea3c9fSNikita Travkin /* Reset and ID register */
1559ea3c9fSNikita Travkin #define AW2013_RSTR 0x00
1659ea3c9fSNikita Travkin #define AW2013_RSTR_RESET 0x55
1759ea3c9fSNikita Travkin #define AW2013_RSTR_CHIP_ID 0x33
1859ea3c9fSNikita Travkin
1959ea3c9fSNikita Travkin /* Global control register */
2059ea3c9fSNikita Travkin #define AW2013_GCR 0x01
2159ea3c9fSNikita Travkin #define AW2013_GCR_ENABLE BIT(0)
2259ea3c9fSNikita Travkin
2359ea3c9fSNikita Travkin /* LED channel enable register */
2459ea3c9fSNikita Travkin #define AW2013_LCTR 0x30
2559ea3c9fSNikita Travkin #define AW2013_LCTR_LE(x) BIT((x))
2659ea3c9fSNikita Travkin
2759ea3c9fSNikita Travkin /* LED channel control registers */
2859ea3c9fSNikita Travkin #define AW2013_LCFG(x) (0x31 + (x))
2959ea3c9fSNikita Travkin #define AW2013_LCFG_IMAX_MASK (BIT(0) | BIT(1)) // Should be 0-3
3059ea3c9fSNikita Travkin #define AW2013_LCFG_MD BIT(4)
3159ea3c9fSNikita Travkin #define AW2013_LCFG_FI BIT(5)
3259ea3c9fSNikita Travkin #define AW2013_LCFG_FO BIT(6)
3359ea3c9fSNikita Travkin
3459ea3c9fSNikita Travkin /* LED channel PWM registers */
3559ea3c9fSNikita Travkin #define AW2013_REG_PWM(x) (0x34 + (x))
3659ea3c9fSNikita Travkin
3759ea3c9fSNikita Travkin /* LED channel timing registers */
3859ea3c9fSNikita Travkin #define AW2013_LEDT0(x) (0x37 + (x) * 3)
3959ea3c9fSNikita Travkin #define AW2013_LEDT0_T1(x) ((x) << 4) // Should be 0-7
4059ea3c9fSNikita Travkin #define AW2013_LEDT0_T2(x) (x) // Should be 0-5
4159ea3c9fSNikita Travkin
4259ea3c9fSNikita Travkin #define AW2013_LEDT1(x) (0x38 + (x) * 3)
4359ea3c9fSNikita Travkin #define AW2013_LEDT1_T3(x) ((x) << 4) // Should be 0-7
4459ea3c9fSNikita Travkin #define AW2013_LEDT1_T4(x) (x) // Should be 0-7
4559ea3c9fSNikita Travkin
4659ea3c9fSNikita Travkin #define AW2013_LEDT2(x) (0x39 + (x) * 3)
4759ea3c9fSNikita Travkin #define AW2013_LEDT2_T0(x) ((x) << 4) // Should be 0-8
4859ea3c9fSNikita Travkin #define AW2013_LEDT2_REPEAT(x) (x) // Should be 0-15
4959ea3c9fSNikita Travkin
5059ea3c9fSNikita Travkin #define AW2013_REG_MAX 0x77
5159ea3c9fSNikita Travkin
5259ea3c9fSNikita Travkin #define AW2013_TIME_STEP 130 /* ms */
5359ea3c9fSNikita Travkin
5459ea3c9fSNikita Travkin struct aw2013;
5559ea3c9fSNikita Travkin
5659ea3c9fSNikita Travkin struct aw2013_led {
5759ea3c9fSNikita Travkin struct aw2013 *chip;
5859ea3c9fSNikita Travkin struct led_classdev cdev;
5959ea3c9fSNikita Travkin u32 num;
6059ea3c9fSNikita Travkin unsigned int imax;
6159ea3c9fSNikita Travkin };
6259ea3c9fSNikita Travkin
6359ea3c9fSNikita Travkin struct aw2013 {
6459ea3c9fSNikita Travkin struct mutex mutex; /* held when writing to registers */
65baca986eSLin, Meng-Bo struct regulator_bulk_data regulators[2];
6659ea3c9fSNikita Travkin struct i2c_client *client;
6759ea3c9fSNikita Travkin struct aw2013_led leds[AW2013_MAX_LEDS];
6859ea3c9fSNikita Travkin struct regmap *regmap;
6959ea3c9fSNikita Travkin int num_leds;
7059ea3c9fSNikita Travkin bool enabled;
7159ea3c9fSNikita Travkin };
7259ea3c9fSNikita Travkin
aw2013_chip_init(struct aw2013 * chip)7359ea3c9fSNikita Travkin static int aw2013_chip_init(struct aw2013 *chip)
7459ea3c9fSNikita Travkin {
7559ea3c9fSNikita Travkin int i, ret;
7659ea3c9fSNikita Travkin
7759ea3c9fSNikita Travkin ret = regmap_write(chip->regmap, AW2013_GCR, AW2013_GCR_ENABLE);
7859ea3c9fSNikita Travkin if (ret) {
7959ea3c9fSNikita Travkin dev_err(&chip->client->dev, "Failed to enable the chip: %d\n",
8059ea3c9fSNikita Travkin ret);
8159ea3c9fSNikita Travkin return ret;
8259ea3c9fSNikita Travkin }
8359ea3c9fSNikita Travkin
8459ea3c9fSNikita Travkin for (i = 0; i < chip->num_leds; i++) {
8559ea3c9fSNikita Travkin ret = regmap_update_bits(chip->regmap,
8659ea3c9fSNikita Travkin AW2013_LCFG(chip->leds[i].num),
8759ea3c9fSNikita Travkin AW2013_LCFG_IMAX_MASK,
8859ea3c9fSNikita Travkin chip->leds[i].imax);
8959ea3c9fSNikita Travkin if (ret) {
9059ea3c9fSNikita Travkin dev_err(&chip->client->dev,
9159ea3c9fSNikita Travkin "Failed to set maximum current for led %d: %d\n",
9259ea3c9fSNikita Travkin chip->leds[i].num, ret);
9359ea3c9fSNikita Travkin return ret;
9459ea3c9fSNikita Travkin }
9559ea3c9fSNikita Travkin }
9659ea3c9fSNikita Travkin
9759ea3c9fSNikita Travkin return ret;
9859ea3c9fSNikita Travkin }
9959ea3c9fSNikita Travkin
aw2013_chip_disable(struct aw2013 * chip)10059ea3c9fSNikita Travkin static void aw2013_chip_disable(struct aw2013 *chip)
10159ea3c9fSNikita Travkin {
10259ea3c9fSNikita Travkin int ret;
10359ea3c9fSNikita Travkin
10459ea3c9fSNikita Travkin if (!chip->enabled)
10559ea3c9fSNikita Travkin return;
10659ea3c9fSNikita Travkin
10759ea3c9fSNikita Travkin regmap_write(chip->regmap, AW2013_GCR, 0);
10859ea3c9fSNikita Travkin
109baca986eSLin, Meng-Bo ret = regulator_bulk_disable(ARRAY_SIZE(chip->regulators),
110baca986eSLin, Meng-Bo chip->regulators);
11159ea3c9fSNikita Travkin if (ret) {
11259ea3c9fSNikita Travkin dev_err(&chip->client->dev,
113baca986eSLin, Meng-Bo "Failed to disable regulators: %d\n", ret);
11459ea3c9fSNikita Travkin return;
11559ea3c9fSNikita Travkin }
11659ea3c9fSNikita Travkin
11759ea3c9fSNikita Travkin chip->enabled = false;
11859ea3c9fSNikita Travkin }
11959ea3c9fSNikita Travkin
aw2013_chip_enable(struct aw2013 * chip)12059ea3c9fSNikita Travkin static int aw2013_chip_enable(struct aw2013 *chip)
12159ea3c9fSNikita Travkin {
12259ea3c9fSNikita Travkin int ret;
12359ea3c9fSNikita Travkin
12459ea3c9fSNikita Travkin if (chip->enabled)
12559ea3c9fSNikita Travkin return 0;
12659ea3c9fSNikita Travkin
127baca986eSLin, Meng-Bo ret = regulator_bulk_enable(ARRAY_SIZE(chip->regulators),
128baca986eSLin, Meng-Bo chip->regulators);
12959ea3c9fSNikita Travkin if (ret) {
13059ea3c9fSNikita Travkin dev_err(&chip->client->dev,
131baca986eSLin, Meng-Bo "Failed to enable regulators: %d\n", ret);
13259ea3c9fSNikita Travkin return ret;
13359ea3c9fSNikita Travkin }
13459ea3c9fSNikita Travkin chip->enabled = true;
13559ea3c9fSNikita Travkin
13659ea3c9fSNikita Travkin ret = aw2013_chip_init(chip);
13759ea3c9fSNikita Travkin if (ret)
13859ea3c9fSNikita Travkin aw2013_chip_disable(chip);
13959ea3c9fSNikita Travkin
14059ea3c9fSNikita Travkin return ret;
14159ea3c9fSNikita Travkin }
14259ea3c9fSNikita Travkin
aw2013_chip_in_use(struct aw2013 * chip)14359ea3c9fSNikita Travkin static bool aw2013_chip_in_use(struct aw2013 *chip)
14459ea3c9fSNikita Travkin {
14559ea3c9fSNikita Travkin int i;
14659ea3c9fSNikita Travkin
14759ea3c9fSNikita Travkin for (i = 0; i < chip->num_leds; i++)
14859ea3c9fSNikita Travkin if (chip->leds[i].cdev.brightness)
14959ea3c9fSNikita Travkin return true;
15059ea3c9fSNikita Travkin
15159ea3c9fSNikita Travkin return false;
15259ea3c9fSNikita Travkin }
15359ea3c9fSNikita Travkin
aw2013_brightness_set(struct led_classdev * cdev,enum led_brightness brightness)15459ea3c9fSNikita Travkin static int aw2013_brightness_set(struct led_classdev *cdev,
15559ea3c9fSNikita Travkin enum led_brightness brightness)
15659ea3c9fSNikita Travkin {
15759ea3c9fSNikita Travkin struct aw2013_led *led = container_of(cdev, struct aw2013_led, cdev);
15859ea3c9fSNikita Travkin int ret, num;
15959ea3c9fSNikita Travkin
16059ea3c9fSNikita Travkin mutex_lock(&led->chip->mutex);
16159ea3c9fSNikita Travkin
16259ea3c9fSNikita Travkin if (aw2013_chip_in_use(led->chip)) {
16359ea3c9fSNikita Travkin ret = aw2013_chip_enable(led->chip);
16459ea3c9fSNikita Travkin if (ret)
16559ea3c9fSNikita Travkin goto error;
16659ea3c9fSNikita Travkin }
16759ea3c9fSNikita Travkin
16859ea3c9fSNikita Travkin num = led->num;
16959ea3c9fSNikita Travkin
17059ea3c9fSNikita Travkin ret = regmap_write(led->chip->regmap, AW2013_REG_PWM(num), brightness);
17159ea3c9fSNikita Travkin if (ret)
17259ea3c9fSNikita Travkin goto error;
17359ea3c9fSNikita Travkin
17459ea3c9fSNikita Travkin if (brightness) {
17559ea3c9fSNikita Travkin ret = regmap_update_bits(led->chip->regmap, AW2013_LCTR,
17659ea3c9fSNikita Travkin AW2013_LCTR_LE(num), 0xFF);
17759ea3c9fSNikita Travkin } else {
17859ea3c9fSNikita Travkin ret = regmap_update_bits(led->chip->regmap, AW2013_LCTR,
17959ea3c9fSNikita Travkin AW2013_LCTR_LE(num), 0);
18059ea3c9fSNikita Travkin if (ret)
18159ea3c9fSNikita Travkin goto error;
18259ea3c9fSNikita Travkin ret = regmap_update_bits(led->chip->regmap, AW2013_LCFG(num),
18359ea3c9fSNikita Travkin AW2013_LCFG_MD, 0);
18459ea3c9fSNikita Travkin }
18559ea3c9fSNikita Travkin if (ret)
18659ea3c9fSNikita Travkin goto error;
18759ea3c9fSNikita Travkin
18859ea3c9fSNikita Travkin if (!aw2013_chip_in_use(led->chip))
18959ea3c9fSNikita Travkin aw2013_chip_disable(led->chip);
19059ea3c9fSNikita Travkin
19159ea3c9fSNikita Travkin error:
19259ea3c9fSNikita Travkin mutex_unlock(&led->chip->mutex);
19359ea3c9fSNikita Travkin
19459ea3c9fSNikita Travkin return ret;
19559ea3c9fSNikita Travkin }
19659ea3c9fSNikita Travkin
aw2013_blink_set(struct led_classdev * cdev,unsigned long * delay_on,unsigned long * delay_off)19759ea3c9fSNikita Travkin static int aw2013_blink_set(struct led_classdev *cdev,
19859ea3c9fSNikita Travkin unsigned long *delay_on, unsigned long *delay_off)
19959ea3c9fSNikita Travkin {
20059ea3c9fSNikita Travkin struct aw2013_led *led = container_of(cdev, struct aw2013_led, cdev);
20159ea3c9fSNikita Travkin int ret, num = led->num;
20259ea3c9fSNikita Travkin unsigned long off = 0, on = 0;
20359ea3c9fSNikita Travkin
20459ea3c9fSNikita Travkin /* If no blink specified, default to 1 Hz. */
20559ea3c9fSNikita Travkin if (!*delay_off && !*delay_on) {
20659ea3c9fSNikita Travkin *delay_off = 500;
20759ea3c9fSNikita Travkin *delay_on = 500;
20859ea3c9fSNikita Travkin }
20959ea3c9fSNikita Travkin
21059ea3c9fSNikita Travkin if (!led->cdev.brightness) {
21159ea3c9fSNikita Travkin led->cdev.brightness = LED_FULL;
21259ea3c9fSNikita Travkin ret = aw2013_brightness_set(&led->cdev, led->cdev.brightness);
21359ea3c9fSNikita Travkin if (ret)
21459ea3c9fSNikita Travkin return ret;
21559ea3c9fSNikita Travkin }
21659ea3c9fSNikita Travkin
21759ea3c9fSNikita Travkin /* Never on - just set to off */
21859ea3c9fSNikita Travkin if (!*delay_on) {
21959ea3c9fSNikita Travkin led->cdev.brightness = LED_OFF;
22059ea3c9fSNikita Travkin return aw2013_brightness_set(&led->cdev, LED_OFF);
22159ea3c9fSNikita Travkin }
22259ea3c9fSNikita Travkin
22359ea3c9fSNikita Travkin mutex_lock(&led->chip->mutex);
22459ea3c9fSNikita Travkin
22559ea3c9fSNikita Travkin /* Never off - brightness is already set, disable blinking */
22659ea3c9fSNikita Travkin if (!*delay_off) {
22759ea3c9fSNikita Travkin ret = regmap_update_bits(led->chip->regmap, AW2013_LCFG(num),
22859ea3c9fSNikita Travkin AW2013_LCFG_MD, 0);
22959ea3c9fSNikita Travkin goto out;
23059ea3c9fSNikita Travkin }
23159ea3c9fSNikita Travkin
23259ea3c9fSNikita Travkin /* Convert into values the HW will understand. */
23359ea3c9fSNikita Travkin off = min(5, ilog2((*delay_off - 1) / AW2013_TIME_STEP) + 1);
23459ea3c9fSNikita Travkin on = min(7, ilog2((*delay_on - 1) / AW2013_TIME_STEP) + 1);
23559ea3c9fSNikita Travkin
23659ea3c9fSNikita Travkin *delay_off = BIT(off) * AW2013_TIME_STEP;
23759ea3c9fSNikita Travkin *delay_on = BIT(on) * AW2013_TIME_STEP;
23859ea3c9fSNikita Travkin
23959ea3c9fSNikita Travkin /* Set timings */
24059ea3c9fSNikita Travkin ret = regmap_write(led->chip->regmap,
24159ea3c9fSNikita Travkin AW2013_LEDT0(num), AW2013_LEDT0_T2(on));
24259ea3c9fSNikita Travkin if (ret)
24359ea3c9fSNikita Travkin goto out;
24459ea3c9fSNikita Travkin ret = regmap_write(led->chip->regmap,
24559ea3c9fSNikita Travkin AW2013_LEDT1(num), AW2013_LEDT1_T4(off));
24659ea3c9fSNikita Travkin if (ret)
24759ea3c9fSNikita Travkin goto out;
24859ea3c9fSNikita Travkin
24959ea3c9fSNikita Travkin /* Finally, enable the LED */
25059ea3c9fSNikita Travkin ret = regmap_update_bits(led->chip->regmap, AW2013_LCFG(num),
25159ea3c9fSNikita Travkin AW2013_LCFG_MD, 0xFF);
25259ea3c9fSNikita Travkin if (ret)
25359ea3c9fSNikita Travkin goto out;
25459ea3c9fSNikita Travkin
25559ea3c9fSNikita Travkin ret = regmap_update_bits(led->chip->regmap, AW2013_LCTR,
25659ea3c9fSNikita Travkin AW2013_LCTR_LE(num), 0xFF);
25759ea3c9fSNikita Travkin
25859ea3c9fSNikita Travkin out:
25959ea3c9fSNikita Travkin mutex_unlock(&led->chip->mutex);
26059ea3c9fSNikita Travkin
26159ea3c9fSNikita Travkin return ret;
26259ea3c9fSNikita Travkin }
26359ea3c9fSNikita Travkin
aw2013_probe_dt(struct aw2013 * chip)26459ea3c9fSNikita Travkin static int aw2013_probe_dt(struct aw2013 *chip)
26559ea3c9fSNikita Travkin {
2668853c95eSMarek Behún struct device_node *np = dev_of_node(&chip->client->dev), *child;
26759ea3c9fSNikita Travkin int count, ret = 0, i = 0;
26859ea3c9fSNikita Travkin struct aw2013_led *led;
26959ea3c9fSNikita Travkin
27099a013c8SMarek Behún count = of_get_available_child_count(np);
27159ea3c9fSNikita Travkin if (!count || count > AW2013_MAX_LEDS)
27259ea3c9fSNikita Travkin return -EINVAL;
27359ea3c9fSNikita Travkin
27459ea3c9fSNikita Travkin regmap_write(chip->regmap, AW2013_RSTR, AW2013_RSTR_RESET);
27559ea3c9fSNikita Travkin
27659ea3c9fSNikita Travkin for_each_available_child_of_node(np, child) {
27759ea3c9fSNikita Travkin struct led_init_data init_data = {};
27859ea3c9fSNikita Travkin u32 source;
27959ea3c9fSNikita Travkin u32 imax;
28059ea3c9fSNikita Travkin
28159ea3c9fSNikita Travkin ret = of_property_read_u32(child, "reg", &source);
28259ea3c9fSNikita Travkin if (ret != 0 || source >= AW2013_MAX_LEDS) {
28359ea3c9fSNikita Travkin dev_err(&chip->client->dev,
28459ea3c9fSNikita Travkin "Couldn't read LED address: %d\n", ret);
28559ea3c9fSNikita Travkin count--;
28659ea3c9fSNikita Travkin continue;
28759ea3c9fSNikita Travkin }
28859ea3c9fSNikita Travkin
28959ea3c9fSNikita Travkin led = &chip->leds[i];
29059ea3c9fSNikita Travkin led->num = source;
29159ea3c9fSNikita Travkin led->chip = chip;
29259ea3c9fSNikita Travkin init_data.fwnode = of_fwnode_handle(child);
29359ea3c9fSNikita Travkin
29459ea3c9fSNikita Travkin if (!of_property_read_u32(child, "led-max-microamp", &imax)) {
29559ea3c9fSNikita Travkin led->imax = min_t(u32, imax / 5000, 3);
29659ea3c9fSNikita Travkin } else {
29759ea3c9fSNikita Travkin led->imax = 1; // 5mA
29859ea3c9fSNikita Travkin dev_info(&chip->client->dev,
29959ea3c9fSNikita Travkin "DT property led-max-microamp is missing\n");
30059ea3c9fSNikita Travkin }
30159ea3c9fSNikita Travkin
30259ea3c9fSNikita Travkin led->cdev.brightness_set_blocking = aw2013_brightness_set;
30359ea3c9fSNikita Travkin led->cdev.blink_set = aw2013_blink_set;
30459ea3c9fSNikita Travkin
30559ea3c9fSNikita Travkin ret = devm_led_classdev_register_ext(&chip->client->dev,
30659ea3c9fSNikita Travkin &led->cdev, &init_data);
3072c677562SMarek Behún if (ret < 0) {
3082c677562SMarek Behún of_node_put(child);
30959ea3c9fSNikita Travkin return ret;
3102c677562SMarek Behún }
31159ea3c9fSNikita Travkin
31259ea3c9fSNikita Travkin i++;
31359ea3c9fSNikita Travkin }
31459ea3c9fSNikita Travkin
31559ea3c9fSNikita Travkin if (!count)
31659ea3c9fSNikita Travkin return -EINVAL;
31759ea3c9fSNikita Travkin
31859ea3c9fSNikita Travkin chip->num_leds = i;
31959ea3c9fSNikita Travkin
32059ea3c9fSNikita Travkin return 0;
32159ea3c9fSNikita Travkin }
32259ea3c9fSNikita Travkin
32359ea3c9fSNikita Travkin static const struct regmap_config aw2013_regmap_config = {
32459ea3c9fSNikita Travkin .reg_bits = 8,
32559ea3c9fSNikita Travkin .val_bits = 8,
32659ea3c9fSNikita Travkin .max_register = AW2013_REG_MAX,
32759ea3c9fSNikita Travkin };
32859ea3c9fSNikita Travkin
aw2013_probe(struct i2c_client * client)32959ea3c9fSNikita Travkin static int aw2013_probe(struct i2c_client *client)
33059ea3c9fSNikita Travkin {
33159ea3c9fSNikita Travkin struct aw2013 *chip;
33259ea3c9fSNikita Travkin int ret;
33359ea3c9fSNikita Travkin unsigned int chipid;
33459ea3c9fSNikita Travkin
33559ea3c9fSNikita Travkin chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
33659ea3c9fSNikita Travkin if (!chip)
33759ea3c9fSNikita Travkin return -ENOMEM;
33859ea3c9fSNikita Travkin
33959ea3c9fSNikita Travkin mutex_init(&chip->mutex);
34059ea3c9fSNikita Travkin mutex_lock(&chip->mutex);
34159ea3c9fSNikita Travkin
34259ea3c9fSNikita Travkin chip->client = client;
34359ea3c9fSNikita Travkin i2c_set_clientdata(client, chip);
34459ea3c9fSNikita Travkin
34559ea3c9fSNikita Travkin chip->regmap = devm_regmap_init_i2c(client, &aw2013_regmap_config);
34659ea3c9fSNikita Travkin if (IS_ERR(chip->regmap)) {
34759ea3c9fSNikita Travkin ret = PTR_ERR(chip->regmap);
34859ea3c9fSNikita Travkin dev_err(&client->dev, "Failed to allocate register map: %d\n",
34959ea3c9fSNikita Travkin ret);
35059ea3c9fSNikita Travkin goto error;
35159ea3c9fSNikita Travkin }
35259ea3c9fSNikita Travkin
353baca986eSLin, Meng-Bo chip->regulators[0].supply = "vcc";
354baca986eSLin, Meng-Bo chip->regulators[1].supply = "vio";
355baca986eSLin, Meng-Bo ret = devm_regulator_bulk_get(&client->dev,
356baca986eSLin, Meng-Bo ARRAY_SIZE(chip->regulators),
357baca986eSLin, Meng-Bo chip->regulators);
358baca986eSLin, Meng-Bo if (ret < 0) {
35959ea3c9fSNikita Travkin if (ret != -EPROBE_DEFER)
36059ea3c9fSNikita Travkin dev_err(&client->dev,
361baca986eSLin, Meng-Bo "Failed to request regulators: %d\n", ret);
36259ea3c9fSNikita Travkin goto error;
36359ea3c9fSNikita Travkin }
36459ea3c9fSNikita Travkin
365baca986eSLin, Meng-Bo ret = regulator_bulk_enable(ARRAY_SIZE(chip->regulators),
366baca986eSLin, Meng-Bo chip->regulators);
36759ea3c9fSNikita Travkin if (ret) {
36859ea3c9fSNikita Travkin dev_err(&client->dev,
369baca986eSLin, Meng-Bo "Failed to enable regulators: %d\n", ret);
37059ea3c9fSNikita Travkin goto error;
37159ea3c9fSNikita Travkin }
37259ea3c9fSNikita Travkin
37359ea3c9fSNikita Travkin ret = regmap_read(chip->regmap, AW2013_RSTR, &chipid);
37459ea3c9fSNikita Travkin if (ret) {
37559ea3c9fSNikita Travkin dev_err(&client->dev, "Failed to read chip ID: %d\n",
37659ea3c9fSNikita Travkin ret);
37759ea3c9fSNikita Travkin goto error_reg;
37859ea3c9fSNikita Travkin }
37959ea3c9fSNikita Travkin
38059ea3c9fSNikita Travkin if (chipid != AW2013_RSTR_CHIP_ID) {
38159ea3c9fSNikita Travkin dev_err(&client->dev, "Chip reported wrong ID: %x\n",
38259ea3c9fSNikita Travkin chipid);
38359ea3c9fSNikita Travkin ret = -ENODEV;
38459ea3c9fSNikita Travkin goto error_reg;
38559ea3c9fSNikita Travkin }
38659ea3c9fSNikita Travkin
38759ea3c9fSNikita Travkin ret = aw2013_probe_dt(chip);
38859ea3c9fSNikita Travkin if (ret < 0)
38959ea3c9fSNikita Travkin goto error_reg;
39059ea3c9fSNikita Travkin
391baca986eSLin, Meng-Bo ret = regulator_bulk_disable(ARRAY_SIZE(chip->regulators),
392baca986eSLin, Meng-Bo chip->regulators);
39359ea3c9fSNikita Travkin if (ret) {
39459ea3c9fSNikita Travkin dev_err(&client->dev,
395baca986eSLin, Meng-Bo "Failed to disable regulators: %d\n", ret);
39659ea3c9fSNikita Travkin goto error;
39759ea3c9fSNikita Travkin }
39859ea3c9fSNikita Travkin
39959ea3c9fSNikita Travkin mutex_unlock(&chip->mutex);
40059ea3c9fSNikita Travkin
40159ea3c9fSNikita Travkin return 0;
40259ea3c9fSNikita Travkin
40359ea3c9fSNikita Travkin error_reg:
404baca986eSLin, Meng-Bo regulator_bulk_disable(ARRAY_SIZE(chip->regulators),
405baca986eSLin, Meng-Bo chip->regulators);
40659ea3c9fSNikita Travkin
40759ea3c9fSNikita Travkin error:
408*e3f63060SGeorge Stark mutex_unlock(&chip->mutex);
40959ea3c9fSNikita Travkin mutex_destroy(&chip->mutex);
41059ea3c9fSNikita Travkin return ret;
41159ea3c9fSNikita Travkin }
41259ea3c9fSNikita Travkin
aw2013_remove(struct i2c_client * client)413ed5c2f5fSUwe Kleine-König static void aw2013_remove(struct i2c_client *client)
41459ea3c9fSNikita Travkin {
41559ea3c9fSNikita Travkin struct aw2013 *chip = i2c_get_clientdata(client);
41659ea3c9fSNikita Travkin
41759ea3c9fSNikita Travkin aw2013_chip_disable(chip);
41859ea3c9fSNikita Travkin
41959ea3c9fSNikita Travkin mutex_destroy(&chip->mutex);
42059ea3c9fSNikita Travkin }
42159ea3c9fSNikita Travkin
42259ea3c9fSNikita Travkin static const struct of_device_id aw2013_match_table[] = {
42359ea3c9fSNikita Travkin { .compatible = "awinic,aw2013", },
42459ea3c9fSNikita Travkin { /* sentinel */ },
42559ea3c9fSNikita Travkin };
42659ea3c9fSNikita Travkin
42759ea3c9fSNikita Travkin MODULE_DEVICE_TABLE(of, aw2013_match_table);
42859ea3c9fSNikita Travkin
42959ea3c9fSNikita Travkin static struct i2c_driver aw2013_driver = {
43059ea3c9fSNikita Travkin .driver = {
43159ea3c9fSNikita Travkin .name = "leds-aw2013",
4323d590af8SZhu Wang .of_match_table = aw2013_match_table,
43359ea3c9fSNikita Travkin },
434d9ff8a8eSUwe Kleine-König .probe = aw2013_probe,
43559ea3c9fSNikita Travkin .remove = aw2013_remove,
43659ea3c9fSNikita Travkin };
43759ea3c9fSNikita Travkin
43859ea3c9fSNikita Travkin module_i2c_driver(aw2013_driver);
43959ea3c9fSNikita Travkin
44059ea3c9fSNikita Travkin MODULE_AUTHOR("Nikita Travkin <nikitos.tr@gmail.com>");
44159ea3c9fSNikita Travkin MODULE_DESCRIPTION("AW2013 LED driver");
44259ea3c9fSNikita Travkin MODULE_LICENSE("GPL v2");
443