1*b338a2aeSMatthias Fend // SPDX-License-Identifier: GPL-2.0-or-later 2*b338a2aeSMatthias Fend /* 3*b338a2aeSMatthias Fend * Texas Instruments TPS61310/TPS61311 flash LED driver with I2C interface 4*b338a2aeSMatthias Fend * 5*b338a2aeSMatthias Fend * Copyright 2025 Matthias Fend <matthias.fend@emfend.at> 6*b338a2aeSMatthias Fend */ 7*b338a2aeSMatthias Fend 8*b338a2aeSMatthias Fend #include <linux/gpio/consumer.h> 9*b338a2aeSMatthias Fend #include <linux/i2c.h> 10*b338a2aeSMatthias Fend #include <linux/led-class-flash.h> 11*b338a2aeSMatthias Fend #include <linux/leds.h> 12*b338a2aeSMatthias Fend #include <linux/module.h> 13*b338a2aeSMatthias Fend #include <linux/regmap.h> 14*b338a2aeSMatthias Fend #include <media/v4l2-flash-led-class.h> 15*b338a2aeSMatthias Fend 16*b338a2aeSMatthias Fend #define TPS6131X_REG_0 0x00 17*b338a2aeSMatthias Fend #define TPS6131X_REG_0_RESET BIT(7) 18*b338a2aeSMatthias Fend #define TPS6131X_REG_0_DCLC13 GENMASK(5, 3) 19*b338a2aeSMatthias Fend #define TPS6131X_REG_0_DCLC13_SHIFT 3 20*b338a2aeSMatthias Fend #define TPS6131X_REG_0_DCLC2 GENMASK(2, 0) 21*b338a2aeSMatthias Fend #define TPS6131X_REG_0_DCLC2_SHIFT 0 22*b338a2aeSMatthias Fend 23*b338a2aeSMatthias Fend #define TPS6131X_REG_1 0x01 24*b338a2aeSMatthias Fend #define TPS6131X_REG_1_MODE GENMASK(7, 6) 25*b338a2aeSMatthias Fend #define TPS6131X_REG_1_MODE_SHIFT 6 26*b338a2aeSMatthias Fend #define TPS6131X_REG_1_FC2 GENMASK(5, 0) 27*b338a2aeSMatthias Fend #define TPS6131X_REG_1_FC2_SHIFT 0 28*b338a2aeSMatthias Fend 29*b338a2aeSMatthias Fend #define TPS6131X_REG_2 0x02 30*b338a2aeSMatthias Fend #define TPS6131X_REG_2_MODE GENMASK(7, 6) 31*b338a2aeSMatthias Fend #define TPS6131X_REG_2_MODE_SHIFT 6 32*b338a2aeSMatthias Fend #define TPS6131X_REG_2_ENVM BIT(5) 33*b338a2aeSMatthias Fend #define TPS6131X_REG_2_FC13 GENMASK(4, 0) 34*b338a2aeSMatthias Fend #define TPS6131X_REG_2_FC13_SHIFT 0 35*b338a2aeSMatthias Fend 36*b338a2aeSMatthias Fend #define TPS6131X_REG_3 0x03 37*b338a2aeSMatthias Fend #define TPS6131X_REG_3_STIM GENMASK(7, 5) 38*b338a2aeSMatthias Fend #define TPS6131X_REG_3_STIM_SHIFT 5 39*b338a2aeSMatthias Fend #define TPS6131X_REG_3_HPFL BIT(4) 40*b338a2aeSMatthias Fend #define TPS6131X_REG_3_SELSTIM_TO BIT(3) 41*b338a2aeSMatthias Fend #define TPS6131X_REG_3_STT BIT(2) 42*b338a2aeSMatthias Fend #define TPS6131X_REG_3_SFT BIT(1) 43*b338a2aeSMatthias Fend #define TPS6131X_REG_3_TXMASK BIT(0) 44*b338a2aeSMatthias Fend 45*b338a2aeSMatthias Fend #define TPS6131X_REG_4 0x04 46*b338a2aeSMatthias Fend #define TPS6131X_REG_4_PG BIT(7) 47*b338a2aeSMatthias Fend #define TPS6131X_REG_4_HOTDIE_HI BIT(6) 48*b338a2aeSMatthias Fend #define TPS6131X_REG_4_HOTDIE_LO BIT(5) 49*b338a2aeSMatthias Fend #define TPS6131X_REG_4_ILIM BIT(4) 50*b338a2aeSMatthias Fend #define TPS6131X_REG_4_INDC GENMASK(3, 0) 51*b338a2aeSMatthias Fend #define TPS6131X_REG_4_INDC_SHIFT 0 52*b338a2aeSMatthias Fend 53*b338a2aeSMatthias Fend #define TPS6131X_REG_5 0x05 54*b338a2aeSMatthias Fend #define TPS6131X_REG_5_SELFCAL BIT(7) 55*b338a2aeSMatthias Fend #define TPS6131X_REG_5_ENPSM BIT(6) 56*b338a2aeSMatthias Fend #define TPS6131X_REG_5_STSTRB1_DIR BIT(5) 57*b338a2aeSMatthias Fend #define TPS6131X_REG_5_GPIO BIT(4) 58*b338a2aeSMatthias Fend #define TPS6131X_REG_5_GPIOTYPE BIT(3) 59*b338a2aeSMatthias Fend #define TPS6131X_REG_5_ENLED3 BIT(2) 60*b338a2aeSMatthias Fend #define TPS6131X_REG_5_ENLED2 BIT(1) 61*b338a2aeSMatthias Fend #define TPS6131X_REG_5_ENLED1 BIT(0) 62*b338a2aeSMatthias Fend 63*b338a2aeSMatthias Fend #define TPS6131X_REG_6 0x06 64*b338a2aeSMatthias Fend #define TPS6131X_REG_6_ENTS BIT(7) 65*b338a2aeSMatthias Fend #define TPS6131X_REG_6_LEDHOT BIT(6) 66*b338a2aeSMatthias Fend #define TPS6131X_REG_6_LEDWARN BIT(5) 67*b338a2aeSMatthias Fend #define TPS6131X_REG_6_LEDHDR BIT(4) 68*b338a2aeSMatthias Fend #define TPS6131X_REG_6_OV GENMASK(3, 0) 69*b338a2aeSMatthias Fend #define TPS6131X_REG_6_OV_SHIFT 0 70*b338a2aeSMatthias Fend 71*b338a2aeSMatthias Fend #define TPS6131X_REG_7 0x07 72*b338a2aeSMatthias Fend #define TPS6131X_REG_7_ENBATMON BIT(7) 73*b338a2aeSMatthias Fend #define TPS6131X_REG_7_BATDROOP GENMASK(6, 4) 74*b338a2aeSMatthias Fend #define TPS6131X_REG_7_BATDROOP_SHIFT 4 75*b338a2aeSMatthias Fend #define TPS6131X_REG_7_REVID GENMASK(2, 0) 76*b338a2aeSMatthias Fend #define TPS6131X_REG_7_REVID_SHIFT 0 77*b338a2aeSMatthias Fend 78*b338a2aeSMatthias Fend #define TPS6131X_MAX_CHANNELS 3 79*b338a2aeSMatthias Fend 80*b338a2aeSMatthias Fend #define TPS6131X_FLASH_MAX_I_CHAN13_MA 400 81*b338a2aeSMatthias Fend #define TPS6131X_FLASH_MAX_I_CHAN2_MA 800 82*b338a2aeSMatthias Fend #define TPS6131X_FLASH_STEP_I_MA 25 83*b338a2aeSMatthias Fend 84*b338a2aeSMatthias Fend #define TPS6131X_TORCH_MAX_I_CHAN13_MA 175 85*b338a2aeSMatthias Fend #define TPS6131X_TORCH_MAX_I_CHAN2_MA 175 86*b338a2aeSMatthias Fend #define TPS6131X_TORCH_STEP_I_MA 25 87*b338a2aeSMatthias Fend 88*b338a2aeSMatthias Fend /* The torch watchdog timer must be refreshed within an interval of 13 seconds. */ 89*b338a2aeSMatthias Fend #define TPS6131X_TORCH_REFRESH_INTERVAL_JIFFIES msecs_to_jiffies(10000) 90*b338a2aeSMatthias Fend 91*b338a2aeSMatthias Fend #define UA_TO_MA(UA) ((UA) / 1000) 92*b338a2aeSMatthias Fend 93*b338a2aeSMatthias Fend enum tps6131x_mode { 94*b338a2aeSMatthias Fend TPS6131X_MODE_SHUTDOWN = 0x0, 95*b338a2aeSMatthias Fend TPS6131X_MODE_TORCH = 0x1, 96*b338a2aeSMatthias Fend TPS6131X_MODE_FLASH = 0x2, 97*b338a2aeSMatthias Fend }; 98*b338a2aeSMatthias Fend 99*b338a2aeSMatthias Fend struct tps6131x { 100*b338a2aeSMatthias Fend struct device *dev; 101*b338a2aeSMatthias Fend struct regmap *regmap; 102*b338a2aeSMatthias Fend struct gpio_desc *reset_gpio; 103*b338a2aeSMatthias Fend /* 104*b338a2aeSMatthias Fend * Registers 0, 1, 2, and 3 control parts of the controller that are not completely 105*b338a2aeSMatthias Fend * independent of each other. Since some operations require the registers to be written in 106*b338a2aeSMatthias Fend * a specific order to avoid unwanted side effects, they are synchronized with a lock. 107*b338a2aeSMatthias Fend */ 108*b338a2aeSMatthias Fend struct mutex lock; /* Hardware access lock for register 0, 1, 2 and 3 */ 109*b338a2aeSMatthias Fend struct delayed_work torch_refresh_work; 110*b338a2aeSMatthias Fend bool valley_current_limit; 111*b338a2aeSMatthias Fend bool chan1_en; 112*b338a2aeSMatthias Fend bool chan2_en; 113*b338a2aeSMatthias Fend bool chan3_en; 114*b338a2aeSMatthias Fend struct fwnode_handle *led_node; 115*b338a2aeSMatthias Fend u32 max_flash_current_ma; 116*b338a2aeSMatthias Fend u32 step_flash_current_ma; 117*b338a2aeSMatthias Fend u32 max_torch_current_ma; 118*b338a2aeSMatthias Fend u32 step_torch_current_ma; 119*b338a2aeSMatthias Fend u32 max_timeout_us; 120*b338a2aeSMatthias Fend struct led_classdev_flash fled_cdev; 121*b338a2aeSMatthias Fend struct v4l2_flash *v4l2_flash; 122*b338a2aeSMatthias Fend }; 123*b338a2aeSMatthias Fend 124*b338a2aeSMatthias Fend static struct tps6131x *fled_cdev_to_tps6131x(struct led_classdev_flash *fled_cdev) 125*b338a2aeSMatthias Fend { 126*b338a2aeSMatthias Fend return container_of(fled_cdev, struct tps6131x, fled_cdev); 127*b338a2aeSMatthias Fend } 128*b338a2aeSMatthias Fend 129*b338a2aeSMatthias Fend /* 130*b338a2aeSMatthias Fend * Register contents after a power on/reset. These values cannot be changed. 131*b338a2aeSMatthias Fend */ 132*b338a2aeSMatthias Fend 133*b338a2aeSMatthias Fend #define TPS6131X_DCLC2_50MA 2 134*b338a2aeSMatthias Fend #define TPS6131X_DCLC13_25MA 1 135*b338a2aeSMatthias Fend #define TPS6131X_FC2_400MA 16 136*b338a2aeSMatthias Fend #define TPS6131X_FC13_200MA 8 137*b338a2aeSMatthias Fend #define TPS6131X_STIM_0_579MS_1_37MS 6 138*b338a2aeSMatthias Fend #define TPS6131X_SELSTIM_RANGE0 0 139*b338a2aeSMatthias Fend #define TPS6131X_INDC_OFF 0 140*b338a2aeSMatthias Fend #define TPS6131X_OV_4950MV 9 141*b338a2aeSMatthias Fend #define TPS6131X_BATDROOP_150MV 4 142*b338a2aeSMatthias Fend 143*b338a2aeSMatthias Fend static const struct reg_default tps6131x_regmap_defaults[] = { 144*b338a2aeSMatthias Fend { TPS6131X_REG_0, (TPS6131X_DCLC13_25MA << TPS6131X_REG_0_DCLC13_SHIFT) | 145*b338a2aeSMatthias Fend (TPS6131X_DCLC2_50MA << TPS6131X_REG_0_DCLC2_SHIFT) }, 146*b338a2aeSMatthias Fend { TPS6131X_REG_1, (TPS6131X_MODE_SHUTDOWN << TPS6131X_REG_1_MODE_SHIFT) | 147*b338a2aeSMatthias Fend (TPS6131X_FC2_400MA << TPS6131X_REG_1_FC2_SHIFT) }, 148*b338a2aeSMatthias Fend { TPS6131X_REG_2, (TPS6131X_MODE_SHUTDOWN << TPS6131X_REG_2_MODE_SHIFT) | 149*b338a2aeSMatthias Fend (TPS6131X_FC13_200MA << TPS6131X_REG_2_FC13_SHIFT) }, 150*b338a2aeSMatthias Fend { TPS6131X_REG_3, (TPS6131X_STIM_0_579MS_1_37MS << TPS6131X_REG_3_STIM_SHIFT) | 151*b338a2aeSMatthias Fend (TPS6131X_SELSTIM_RANGE0 << TPS6131X_REG_3_SELSTIM_TO) | 152*b338a2aeSMatthias Fend TPS6131X_REG_3_TXMASK }, 153*b338a2aeSMatthias Fend { TPS6131X_REG_4, (TPS6131X_INDC_OFF << TPS6131X_REG_4_INDC_SHIFT) }, 154*b338a2aeSMatthias Fend { TPS6131X_REG_5, TPS6131X_REG_5_ENPSM | TPS6131X_REG_5_STSTRB1_DIR | 155*b338a2aeSMatthias Fend TPS6131X_REG_5_GPIOTYPE | TPS6131X_REG_5_ENLED2 }, 156*b338a2aeSMatthias Fend { TPS6131X_REG_6, (TPS6131X_OV_4950MV << TPS6131X_REG_6_OV_SHIFT) }, 157*b338a2aeSMatthias Fend { TPS6131X_REG_7, (TPS6131X_BATDROOP_150MV << TPS6131X_REG_7_BATDROOP_SHIFT) }, 158*b338a2aeSMatthias Fend }; 159*b338a2aeSMatthias Fend 160*b338a2aeSMatthias Fend /* 161*b338a2aeSMatthias Fend * These registers contain flags that are reset when read. 162*b338a2aeSMatthias Fend */ 163*b338a2aeSMatthias Fend static bool tps6131x_regmap_precious(struct device *dev, unsigned int reg) 164*b338a2aeSMatthias Fend { 165*b338a2aeSMatthias Fend switch (reg) { 166*b338a2aeSMatthias Fend case TPS6131X_REG_3: 167*b338a2aeSMatthias Fend case TPS6131X_REG_4: 168*b338a2aeSMatthias Fend case TPS6131X_REG_6: 169*b338a2aeSMatthias Fend return true; 170*b338a2aeSMatthias Fend default: 171*b338a2aeSMatthias Fend return false; 172*b338a2aeSMatthias Fend } 173*b338a2aeSMatthias Fend } 174*b338a2aeSMatthias Fend 175*b338a2aeSMatthias Fend static const struct regmap_config tps6131x_regmap = { 176*b338a2aeSMatthias Fend .reg_bits = 8, 177*b338a2aeSMatthias Fend .val_bits = 8, 178*b338a2aeSMatthias Fend .max_register = TPS6131X_REG_7, 179*b338a2aeSMatthias Fend .reg_defaults = tps6131x_regmap_defaults, 180*b338a2aeSMatthias Fend .num_reg_defaults = ARRAY_SIZE(tps6131x_regmap_defaults), 181*b338a2aeSMatthias Fend .cache_type = REGCACHE_FLAT, 182*b338a2aeSMatthias Fend .precious_reg = &tps6131x_regmap_precious, 183*b338a2aeSMatthias Fend }; 184*b338a2aeSMatthias Fend 185*b338a2aeSMatthias Fend struct tps6131x_timer_config { 186*b338a2aeSMatthias Fend u8 val; 187*b338a2aeSMatthias Fend u8 range; 188*b338a2aeSMatthias Fend u32 time_us; 189*b338a2aeSMatthias Fend }; 190*b338a2aeSMatthias Fend 191*b338a2aeSMatthias Fend static const struct tps6131x_timer_config tps6131x_timer_configs[] = { 192*b338a2aeSMatthias Fend { .val = 0, .range = 1, .time_us = 5300 }, 193*b338a2aeSMatthias Fend { .val = 1, .range = 1, .time_us = 10700 }, 194*b338a2aeSMatthias Fend { .val = 2, .range = 1, .time_us = 16000 }, 195*b338a2aeSMatthias Fend { .val = 3, .range = 1, .time_us = 21300 }, 196*b338a2aeSMatthias Fend { .val = 4, .range = 1, .time_us = 26600 }, 197*b338a2aeSMatthias Fend { .val = 5, .range = 1, .time_us = 32000 }, 198*b338a2aeSMatthias Fend { .val = 6, .range = 1, .time_us = 37300 }, 199*b338a2aeSMatthias Fend { .val = 0, .range = 0, .time_us = 68200 }, 200*b338a2aeSMatthias Fend { .val = 7, .range = 1, .time_us = 71500 }, 201*b338a2aeSMatthias Fend { .val = 1, .range = 0, .time_us = 102200 }, 202*b338a2aeSMatthias Fend { .val = 2, .range = 0, .time_us = 136300 }, 203*b338a2aeSMatthias Fend { .val = 3, .range = 0, .time_us = 170400 }, 204*b338a2aeSMatthias Fend { .val = 4, .range = 0, .time_us = 204500 }, 205*b338a2aeSMatthias Fend { .val = 5, .range = 0, .time_us = 340800 }, 206*b338a2aeSMatthias Fend { .val = 6, .range = 0, .time_us = 579300 }, 207*b338a2aeSMatthias Fend { .val = 7, .range = 0, .time_us = 852000 }, 208*b338a2aeSMatthias Fend }; 209*b338a2aeSMatthias Fend 210*b338a2aeSMatthias Fend static const struct tps6131x_timer_config *tps6131x_find_closest_timer_config(u32 timeout_us) 211*b338a2aeSMatthias Fend { 212*b338a2aeSMatthias Fend const struct tps6131x_timer_config *timer_config = &tps6131x_timer_configs[0]; 213*b338a2aeSMatthias Fend u32 diff, min_diff = U32_MAX; 214*b338a2aeSMatthias Fend int i; 215*b338a2aeSMatthias Fend 216*b338a2aeSMatthias Fend for (i = 0; i < ARRAY_SIZE(tps6131x_timer_configs); i++) { 217*b338a2aeSMatthias Fend diff = abs(tps6131x_timer_configs[i].time_us - timeout_us); 218*b338a2aeSMatthias Fend if (diff < min_diff) { 219*b338a2aeSMatthias Fend timer_config = &tps6131x_timer_configs[i]; 220*b338a2aeSMatthias Fend min_diff = diff; 221*b338a2aeSMatthias Fend if (!min_diff) 222*b338a2aeSMatthias Fend break; 223*b338a2aeSMatthias Fend } 224*b338a2aeSMatthias Fend } 225*b338a2aeSMatthias Fend 226*b338a2aeSMatthias Fend return timer_config; 227*b338a2aeSMatthias Fend } 228*b338a2aeSMatthias Fend 229*b338a2aeSMatthias Fend static int tps6131x_reset_chip(struct tps6131x *tps6131x) 230*b338a2aeSMatthias Fend { 231*b338a2aeSMatthias Fend int ret; 232*b338a2aeSMatthias Fend 233*b338a2aeSMatthias Fend if (tps6131x->reset_gpio) { 234*b338a2aeSMatthias Fend gpiod_set_value_cansleep(tps6131x->reset_gpio, 1); 235*b338a2aeSMatthias Fend fsleep(10); 236*b338a2aeSMatthias Fend gpiod_set_value_cansleep(tps6131x->reset_gpio, 0); 237*b338a2aeSMatthias Fend fsleep(100); 238*b338a2aeSMatthias Fend } else { 239*b338a2aeSMatthias Fend ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_0, TPS6131X_REG_0_RESET, 240*b338a2aeSMatthias Fend TPS6131X_REG_0_RESET); 241*b338a2aeSMatthias Fend if (ret) 242*b338a2aeSMatthias Fend return ret; 243*b338a2aeSMatthias Fend 244*b338a2aeSMatthias Fend fsleep(100); 245*b338a2aeSMatthias Fend 246*b338a2aeSMatthias Fend ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_0, TPS6131X_REG_0_RESET, 0); 247*b338a2aeSMatthias Fend if (ret) 248*b338a2aeSMatthias Fend return ret; 249*b338a2aeSMatthias Fend } 250*b338a2aeSMatthias Fend 251*b338a2aeSMatthias Fend return 0; 252*b338a2aeSMatthias Fend } 253*b338a2aeSMatthias Fend 254*b338a2aeSMatthias Fend static int tps6131x_init_chip(struct tps6131x *tps6131x) 255*b338a2aeSMatthias Fend { 256*b338a2aeSMatthias Fend u32 val; 257*b338a2aeSMatthias Fend int ret; 258*b338a2aeSMatthias Fend 259*b338a2aeSMatthias Fend val = tps6131x->valley_current_limit ? TPS6131X_REG_4_ILIM : 0; 260*b338a2aeSMatthias Fend 261*b338a2aeSMatthias Fend ret = regmap_write(tps6131x->regmap, TPS6131X_REG_4, val); 262*b338a2aeSMatthias Fend if (ret) 263*b338a2aeSMatthias Fend return ret; 264*b338a2aeSMatthias Fend 265*b338a2aeSMatthias Fend val = TPS6131X_REG_5_ENPSM | TPS6131X_REG_5_STSTRB1_DIR | TPS6131X_REG_5_GPIOTYPE; 266*b338a2aeSMatthias Fend 267*b338a2aeSMatthias Fend if (tps6131x->chan1_en) 268*b338a2aeSMatthias Fend val |= TPS6131X_REG_5_ENLED1; 269*b338a2aeSMatthias Fend 270*b338a2aeSMatthias Fend if (tps6131x->chan2_en) 271*b338a2aeSMatthias Fend val |= TPS6131X_REG_5_ENLED2; 272*b338a2aeSMatthias Fend 273*b338a2aeSMatthias Fend if (tps6131x->chan3_en) 274*b338a2aeSMatthias Fend val |= TPS6131X_REG_5_ENLED3; 275*b338a2aeSMatthias Fend 276*b338a2aeSMatthias Fend ret = regmap_write(tps6131x->regmap, TPS6131X_REG_5, val); 277*b338a2aeSMatthias Fend if (ret) 278*b338a2aeSMatthias Fend return ret; 279*b338a2aeSMatthias Fend 280*b338a2aeSMatthias Fend val = TPS6131X_REG_6_ENTS; 281*b338a2aeSMatthias Fend 282*b338a2aeSMatthias Fend ret = regmap_write(tps6131x->regmap, TPS6131X_REG_6, val); 283*b338a2aeSMatthias Fend if (ret) 284*b338a2aeSMatthias Fend return ret; 285*b338a2aeSMatthias Fend 286*b338a2aeSMatthias Fend return 0; 287*b338a2aeSMatthias Fend } 288*b338a2aeSMatthias Fend 289*b338a2aeSMatthias Fend static int tps6131x_set_mode(struct tps6131x *tps6131x, enum tps6131x_mode mode, bool force) 290*b338a2aeSMatthias Fend { 291*b338a2aeSMatthias Fend u8 val = mode << TPS6131X_REG_1_MODE_SHIFT; 292*b338a2aeSMatthias Fend 293*b338a2aeSMatthias Fend return regmap_update_bits_base(tps6131x->regmap, TPS6131X_REG_1, TPS6131X_REG_1_MODE, val, 294*b338a2aeSMatthias Fend NULL, false, force); 295*b338a2aeSMatthias Fend } 296*b338a2aeSMatthias Fend 297*b338a2aeSMatthias Fend static void tps6131x_torch_refresh_handler(struct work_struct *work) 298*b338a2aeSMatthias Fend { 299*b338a2aeSMatthias Fend struct tps6131x *tps6131x = container_of(work, struct tps6131x, torch_refresh_work.work); 300*b338a2aeSMatthias Fend int ret; 301*b338a2aeSMatthias Fend 302*b338a2aeSMatthias Fend guard(mutex)(&tps6131x->lock); 303*b338a2aeSMatthias Fend 304*b338a2aeSMatthias Fend ret = tps6131x_set_mode(tps6131x, TPS6131X_MODE_TORCH, true); 305*b338a2aeSMatthias Fend if (ret < 0) { 306*b338a2aeSMatthias Fend dev_err(tps6131x->dev, "Failed to refresh torch watchdog timer\n"); 307*b338a2aeSMatthias Fend return; 308*b338a2aeSMatthias Fend } 309*b338a2aeSMatthias Fend 310*b338a2aeSMatthias Fend schedule_delayed_work(&tps6131x->torch_refresh_work, 311*b338a2aeSMatthias Fend TPS6131X_TORCH_REFRESH_INTERVAL_JIFFIES); 312*b338a2aeSMatthias Fend } 313*b338a2aeSMatthias Fend 314*b338a2aeSMatthias Fend static int tps6131x_brightness_set(struct led_classdev *cdev, enum led_brightness brightness) 315*b338a2aeSMatthias Fend { 316*b338a2aeSMatthias Fend struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(cdev); 317*b338a2aeSMatthias Fend struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 318*b338a2aeSMatthias Fend u32 num_chans, steps_chan13, steps_chan2, steps_remaining; 319*b338a2aeSMatthias Fend u8 reg0; 320*b338a2aeSMatthias Fend int ret; 321*b338a2aeSMatthias Fend 322*b338a2aeSMatthias Fend cancel_delayed_work_sync(&tps6131x->torch_refresh_work); 323*b338a2aeSMatthias Fend 324*b338a2aeSMatthias Fend /* 325*b338a2aeSMatthias Fend * The brightness parameter uses the number of current steps as the unit (not the current 326*b338a2aeSMatthias Fend * value itself). Since the reported step size can vary depending on the configuration, 327*b338a2aeSMatthias Fend * this value must be converted into actual register steps. 328*b338a2aeSMatthias Fend */ 329*b338a2aeSMatthias Fend steps_remaining = (brightness * tps6131x->step_torch_current_ma) / TPS6131X_TORCH_STEP_I_MA; 330*b338a2aeSMatthias Fend 331*b338a2aeSMatthias Fend num_chans = tps6131x->chan1_en + tps6131x->chan2_en + tps6131x->chan3_en; 332*b338a2aeSMatthias Fend 333*b338a2aeSMatthias Fend /* 334*b338a2aeSMatthias Fend * The currents are distributed as evenly as possible across the activated channels. 335*b338a2aeSMatthias Fend * Since channels 1 and 3 share the same register setting, they always use the same current 336*b338a2aeSMatthias Fend * value. Channel 2 supports higher currents and thus takes over the remaining additional 337*b338a2aeSMatthias Fend * portion that cannot be covered by the other channels. 338*b338a2aeSMatthias Fend */ 339*b338a2aeSMatthias Fend steps_chan13 = min_t(u32, steps_remaining / num_chans, 340*b338a2aeSMatthias Fend TPS6131X_TORCH_MAX_I_CHAN13_MA / TPS6131X_TORCH_STEP_I_MA); 341*b338a2aeSMatthias Fend if (tps6131x->chan1_en) 342*b338a2aeSMatthias Fend steps_remaining -= steps_chan13; 343*b338a2aeSMatthias Fend if (tps6131x->chan3_en) 344*b338a2aeSMatthias Fend steps_remaining -= steps_chan13; 345*b338a2aeSMatthias Fend 346*b338a2aeSMatthias Fend steps_chan2 = min_t(u32, steps_remaining, 347*b338a2aeSMatthias Fend TPS6131X_TORCH_MAX_I_CHAN2_MA / TPS6131X_TORCH_STEP_I_MA); 348*b338a2aeSMatthias Fend 349*b338a2aeSMatthias Fend guard(mutex)(&tps6131x->lock); 350*b338a2aeSMatthias Fend 351*b338a2aeSMatthias Fend reg0 = (steps_chan13 << TPS6131X_REG_0_DCLC13_SHIFT) | 352*b338a2aeSMatthias Fend (steps_chan2 << TPS6131X_REG_0_DCLC2_SHIFT); 353*b338a2aeSMatthias Fend ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_0, 354*b338a2aeSMatthias Fend TPS6131X_REG_0_DCLC13 | TPS6131X_REG_0_DCLC2, reg0); 355*b338a2aeSMatthias Fend if (ret < 0) 356*b338a2aeSMatthias Fend return ret; 357*b338a2aeSMatthias Fend 358*b338a2aeSMatthias Fend ret = tps6131x_set_mode(tps6131x, brightness ? TPS6131X_MODE_TORCH : TPS6131X_MODE_SHUTDOWN, 359*b338a2aeSMatthias Fend true); 360*b338a2aeSMatthias Fend if (ret < 0) 361*b338a2aeSMatthias Fend return ret; 362*b338a2aeSMatthias Fend 363*b338a2aeSMatthias Fend /* 364*b338a2aeSMatthias Fend * In order to use both the flash and the video light functions purely via the I2C 365*b338a2aeSMatthias Fend * interface, STRB1 must be low. If STRB1 is low, then the video light watchdog timer 366*b338a2aeSMatthias Fend * is also active, which puts the device into the shutdown state after around 13 seconds. 367*b338a2aeSMatthias Fend * To prevent this, the mode must be refreshed within the watchdog timeout. 368*b338a2aeSMatthias Fend */ 369*b338a2aeSMatthias Fend if (brightness) 370*b338a2aeSMatthias Fend schedule_delayed_work(&tps6131x->torch_refresh_work, 371*b338a2aeSMatthias Fend TPS6131X_TORCH_REFRESH_INTERVAL_JIFFIES); 372*b338a2aeSMatthias Fend 373*b338a2aeSMatthias Fend return 0; 374*b338a2aeSMatthias Fend } 375*b338a2aeSMatthias Fend 376*b338a2aeSMatthias Fend static int tps6131x_strobe_set(struct led_classdev_flash *fled_cdev, bool state) 377*b338a2aeSMatthias Fend { 378*b338a2aeSMatthias Fend struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 379*b338a2aeSMatthias Fend int ret; 380*b338a2aeSMatthias Fend 381*b338a2aeSMatthias Fend guard(mutex)(&tps6131x->lock); 382*b338a2aeSMatthias Fend 383*b338a2aeSMatthias Fend ret = tps6131x_set_mode(tps6131x, state ? TPS6131X_MODE_FLASH : TPS6131X_MODE_SHUTDOWN, 384*b338a2aeSMatthias Fend true); 385*b338a2aeSMatthias Fend if (ret < 0) 386*b338a2aeSMatthias Fend return ret; 387*b338a2aeSMatthias Fend 388*b338a2aeSMatthias Fend if (state) { 389*b338a2aeSMatthias Fend ret = regmap_update_bits_base(tps6131x->regmap, TPS6131X_REG_3, TPS6131X_REG_3_SFT, 390*b338a2aeSMatthias Fend TPS6131X_REG_3_SFT, NULL, false, true); 391*b338a2aeSMatthias Fend if (ret) 392*b338a2aeSMatthias Fend return ret; 393*b338a2aeSMatthias Fend } 394*b338a2aeSMatthias Fend 395*b338a2aeSMatthias Fend ret = regmap_update_bits_base(tps6131x->regmap, TPS6131X_REG_3, TPS6131X_REG_3_SFT, 0, NULL, 396*b338a2aeSMatthias Fend false, true); 397*b338a2aeSMatthias Fend if (ret) 398*b338a2aeSMatthias Fend return ret; 399*b338a2aeSMatthias Fend 400*b338a2aeSMatthias Fend return 0; 401*b338a2aeSMatthias Fend } 402*b338a2aeSMatthias Fend 403*b338a2aeSMatthias Fend static int tps6131x_flash_brightness_set(struct led_classdev_flash *fled_cdev, u32 brightness) 404*b338a2aeSMatthias Fend { 405*b338a2aeSMatthias Fend struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 406*b338a2aeSMatthias Fend u32 num_chans; 407*b338a2aeSMatthias Fend u32 steps_chan13, steps_chan2; 408*b338a2aeSMatthias Fend u32 steps_remaining; 409*b338a2aeSMatthias Fend int ret; 410*b338a2aeSMatthias Fend 411*b338a2aeSMatthias Fend steps_remaining = brightness / TPS6131X_FLASH_STEP_I_MA; 412*b338a2aeSMatthias Fend num_chans = tps6131x->chan1_en + tps6131x->chan2_en + tps6131x->chan3_en; 413*b338a2aeSMatthias Fend steps_chan13 = min_t(u32, steps_remaining / num_chans, 414*b338a2aeSMatthias Fend TPS6131X_FLASH_MAX_I_CHAN13_MA / TPS6131X_FLASH_STEP_I_MA); 415*b338a2aeSMatthias Fend if (tps6131x->chan1_en) 416*b338a2aeSMatthias Fend steps_remaining -= steps_chan13; 417*b338a2aeSMatthias Fend if (tps6131x->chan3_en) 418*b338a2aeSMatthias Fend steps_remaining -= steps_chan13; 419*b338a2aeSMatthias Fend steps_chan2 = min_t(u32, steps_remaining, 420*b338a2aeSMatthias Fend TPS6131X_FLASH_MAX_I_CHAN2_MA / TPS6131X_FLASH_STEP_I_MA); 421*b338a2aeSMatthias Fend 422*b338a2aeSMatthias Fend guard(mutex)(&tps6131x->lock); 423*b338a2aeSMatthias Fend 424*b338a2aeSMatthias Fend ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_2, TPS6131X_REG_2_FC13, 425*b338a2aeSMatthias Fend steps_chan13 << TPS6131X_REG_2_FC13_SHIFT); 426*b338a2aeSMatthias Fend if (ret < 0) 427*b338a2aeSMatthias Fend return ret; 428*b338a2aeSMatthias Fend 429*b338a2aeSMatthias Fend ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_1, TPS6131X_REG_1_FC2, 430*b338a2aeSMatthias Fend steps_chan2 << TPS6131X_REG_1_FC2_SHIFT); 431*b338a2aeSMatthias Fend if (ret < 0) 432*b338a2aeSMatthias Fend return ret; 433*b338a2aeSMatthias Fend 434*b338a2aeSMatthias Fend fled_cdev->brightness.val = brightness; 435*b338a2aeSMatthias Fend 436*b338a2aeSMatthias Fend return 0; 437*b338a2aeSMatthias Fend } 438*b338a2aeSMatthias Fend 439*b338a2aeSMatthias Fend static int tps6131x_flash_timeout_set(struct led_classdev_flash *fled_cdev, u32 timeout_us) 440*b338a2aeSMatthias Fend { 441*b338a2aeSMatthias Fend const struct tps6131x_timer_config *timer_config; 442*b338a2aeSMatthias Fend struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 443*b338a2aeSMatthias Fend u8 reg3; 444*b338a2aeSMatthias Fend int ret; 445*b338a2aeSMatthias Fend 446*b338a2aeSMatthias Fend guard(mutex)(&tps6131x->lock); 447*b338a2aeSMatthias Fend 448*b338a2aeSMatthias Fend timer_config = tps6131x_find_closest_timer_config(timeout_us); 449*b338a2aeSMatthias Fend 450*b338a2aeSMatthias Fend reg3 = timer_config->val << TPS6131X_REG_3_STIM_SHIFT; 451*b338a2aeSMatthias Fend if (timer_config->range) 452*b338a2aeSMatthias Fend reg3 |= TPS6131X_REG_3_SELSTIM_TO; 453*b338a2aeSMatthias Fend 454*b338a2aeSMatthias Fend ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_3, 455*b338a2aeSMatthias Fend TPS6131X_REG_3_STIM | TPS6131X_REG_3_SELSTIM_TO, reg3); 456*b338a2aeSMatthias Fend if (ret < 0) 457*b338a2aeSMatthias Fend return ret; 458*b338a2aeSMatthias Fend 459*b338a2aeSMatthias Fend fled_cdev->timeout.val = timer_config->time_us; 460*b338a2aeSMatthias Fend 461*b338a2aeSMatthias Fend return 0; 462*b338a2aeSMatthias Fend } 463*b338a2aeSMatthias Fend 464*b338a2aeSMatthias Fend static int tps6131x_strobe_get(struct led_classdev_flash *fled_cdev, bool *state) 465*b338a2aeSMatthias Fend { 466*b338a2aeSMatthias Fend struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 467*b338a2aeSMatthias Fend unsigned int reg3; 468*b338a2aeSMatthias Fend int ret; 469*b338a2aeSMatthias Fend 470*b338a2aeSMatthias Fend ret = regmap_read_bypassed(tps6131x->regmap, TPS6131X_REG_3, ®3); 471*b338a2aeSMatthias Fend if (ret) 472*b338a2aeSMatthias Fend return ret; 473*b338a2aeSMatthias Fend 474*b338a2aeSMatthias Fend *state = !!(reg3 & TPS6131X_REG_3_SFT); 475*b338a2aeSMatthias Fend 476*b338a2aeSMatthias Fend return 0; 477*b338a2aeSMatthias Fend } 478*b338a2aeSMatthias Fend 479*b338a2aeSMatthias Fend static int tps6131x_flash_fault_get(struct led_classdev_flash *fled_cdev, u32 *fault) 480*b338a2aeSMatthias Fend { 481*b338a2aeSMatthias Fend struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 482*b338a2aeSMatthias Fend unsigned int reg3, reg4, reg6; 483*b338a2aeSMatthias Fend int ret; 484*b338a2aeSMatthias Fend 485*b338a2aeSMatthias Fend *fault = 0; 486*b338a2aeSMatthias Fend 487*b338a2aeSMatthias Fend ret = regmap_read_bypassed(tps6131x->regmap, TPS6131X_REG_3, ®3); 488*b338a2aeSMatthias Fend if (ret < 0) 489*b338a2aeSMatthias Fend return ret; 490*b338a2aeSMatthias Fend 491*b338a2aeSMatthias Fend ret = regmap_read_bypassed(tps6131x->regmap, TPS6131X_REG_4, ®4); 492*b338a2aeSMatthias Fend if (ret < 0) 493*b338a2aeSMatthias Fend return ret; 494*b338a2aeSMatthias Fend 495*b338a2aeSMatthias Fend ret = regmap_read_bypassed(tps6131x->regmap, TPS6131X_REG_6, ®6); 496*b338a2aeSMatthias Fend if (ret < 0) 497*b338a2aeSMatthias Fend return ret; 498*b338a2aeSMatthias Fend 499*b338a2aeSMatthias Fend if (reg3 & TPS6131X_REG_3_HPFL) 500*b338a2aeSMatthias Fend *fault |= LED_FAULT_SHORT_CIRCUIT; 501*b338a2aeSMatthias Fend 502*b338a2aeSMatthias Fend if (reg3 & TPS6131X_REG_3_SELSTIM_TO) 503*b338a2aeSMatthias Fend *fault |= LED_FAULT_TIMEOUT; 504*b338a2aeSMatthias Fend 505*b338a2aeSMatthias Fend if (reg4 & TPS6131X_REG_4_HOTDIE_HI) 506*b338a2aeSMatthias Fend *fault |= LED_FAULT_OVER_TEMPERATURE; 507*b338a2aeSMatthias Fend 508*b338a2aeSMatthias Fend if (reg6 & (TPS6131X_REG_6_LEDHOT | TPS6131X_REG_6_LEDWARN)) 509*b338a2aeSMatthias Fend *fault |= LED_FAULT_LED_OVER_TEMPERATURE; 510*b338a2aeSMatthias Fend 511*b338a2aeSMatthias Fend if (!(reg6 & TPS6131X_REG_6_LEDHDR)) 512*b338a2aeSMatthias Fend *fault |= LED_FAULT_UNDER_VOLTAGE; 513*b338a2aeSMatthias Fend 514*b338a2aeSMatthias Fend if (reg6 & TPS6131X_REG_6_LEDHOT) { 515*b338a2aeSMatthias Fend ret = regmap_update_bits_base(tps6131x->regmap, TPS6131X_REG_6, 516*b338a2aeSMatthias Fend TPS6131X_REG_6_LEDHOT, 0, NULL, false, true); 517*b338a2aeSMatthias Fend if (ret < 0) 518*b338a2aeSMatthias Fend return ret; 519*b338a2aeSMatthias Fend } 520*b338a2aeSMatthias Fend 521*b338a2aeSMatthias Fend return 0; 522*b338a2aeSMatthias Fend } 523*b338a2aeSMatthias Fend 524*b338a2aeSMatthias Fend static const struct led_flash_ops flash_ops = { 525*b338a2aeSMatthias Fend .flash_brightness_set = tps6131x_flash_brightness_set, 526*b338a2aeSMatthias Fend .strobe_set = tps6131x_strobe_set, 527*b338a2aeSMatthias Fend .strobe_get = tps6131x_strobe_get, 528*b338a2aeSMatthias Fend .timeout_set = tps6131x_flash_timeout_set, 529*b338a2aeSMatthias Fend .fault_get = tps6131x_flash_fault_get, 530*b338a2aeSMatthias Fend }; 531*b338a2aeSMatthias Fend 532*b338a2aeSMatthias Fend static int tps6131x_parse_node(struct tps6131x *tps6131x) 533*b338a2aeSMatthias Fend { 534*b338a2aeSMatthias Fend const struct tps6131x_timer_config *timer_config; 535*b338a2aeSMatthias Fend struct device *dev = tps6131x->dev; 536*b338a2aeSMatthias Fend u32 channels[TPS6131X_MAX_CHANNELS]; 537*b338a2aeSMatthias Fend u32 current_step_multiplier; 538*b338a2aeSMatthias Fend u32 current_ua; 539*b338a2aeSMatthias Fend u32 max_current_flash_ma, max_current_torch_ma; 540*b338a2aeSMatthias Fend u32 timeout_us; 541*b338a2aeSMatthias Fend int num_channels; 542*b338a2aeSMatthias Fend int i; 543*b338a2aeSMatthias Fend int ret; 544*b338a2aeSMatthias Fend 545*b338a2aeSMatthias Fend tps6131x->valley_current_limit = device_property_read_bool(dev, "ti,valley-current-limit"); 546*b338a2aeSMatthias Fend 547*b338a2aeSMatthias Fend tps6131x->led_node = fwnode_get_next_available_child_node(dev->fwnode, NULL); 548*b338a2aeSMatthias Fend if (!tps6131x->led_node) { 549*b338a2aeSMatthias Fend dev_err(dev, "Missing LED node\n"); 550*b338a2aeSMatthias Fend return -EINVAL; 551*b338a2aeSMatthias Fend } 552*b338a2aeSMatthias Fend 553*b338a2aeSMatthias Fend num_channels = fwnode_property_count_u32(tps6131x->led_node, "led-sources"); 554*b338a2aeSMatthias Fend if (num_channels <= 0) { 555*b338a2aeSMatthias Fend dev_err(dev, "Failed to read led-sources property\n"); 556*b338a2aeSMatthias Fend return -EINVAL; 557*b338a2aeSMatthias Fend } 558*b338a2aeSMatthias Fend 559*b338a2aeSMatthias Fend if (num_channels > TPS6131X_MAX_CHANNELS) { 560*b338a2aeSMatthias Fend dev_err(dev, "led-sources count %u exceeds maximum channel count %u\n", 561*b338a2aeSMatthias Fend num_channels, TPS6131X_MAX_CHANNELS); 562*b338a2aeSMatthias Fend return -EINVAL; 563*b338a2aeSMatthias Fend } 564*b338a2aeSMatthias Fend 565*b338a2aeSMatthias Fend ret = fwnode_property_read_u32_array(tps6131x->led_node, "led-sources", channels, 566*b338a2aeSMatthias Fend num_channels); 567*b338a2aeSMatthias Fend if (ret < 0) { 568*b338a2aeSMatthias Fend dev_err(dev, "Failed to read led-sources property\n"); 569*b338a2aeSMatthias Fend return ret; 570*b338a2aeSMatthias Fend } 571*b338a2aeSMatthias Fend 572*b338a2aeSMatthias Fend max_current_flash_ma = 0; 573*b338a2aeSMatthias Fend max_current_torch_ma = 0; 574*b338a2aeSMatthias Fend for (i = 0; i < num_channels; i++) { 575*b338a2aeSMatthias Fend switch (channels[i]) { 576*b338a2aeSMatthias Fend case 1: 577*b338a2aeSMatthias Fend tps6131x->chan1_en = true; 578*b338a2aeSMatthias Fend max_current_flash_ma += TPS6131X_FLASH_MAX_I_CHAN13_MA; 579*b338a2aeSMatthias Fend max_current_torch_ma += TPS6131X_TORCH_MAX_I_CHAN13_MA; 580*b338a2aeSMatthias Fend break; 581*b338a2aeSMatthias Fend case 2: 582*b338a2aeSMatthias Fend tps6131x->chan2_en = true; 583*b338a2aeSMatthias Fend max_current_flash_ma += TPS6131X_FLASH_MAX_I_CHAN2_MA; 584*b338a2aeSMatthias Fend max_current_torch_ma += TPS6131X_TORCH_MAX_I_CHAN2_MA; 585*b338a2aeSMatthias Fend break; 586*b338a2aeSMatthias Fend case 3: 587*b338a2aeSMatthias Fend tps6131x->chan3_en = true; 588*b338a2aeSMatthias Fend max_current_flash_ma += TPS6131X_FLASH_MAX_I_CHAN13_MA; 589*b338a2aeSMatthias Fend max_current_torch_ma += TPS6131X_TORCH_MAX_I_CHAN13_MA; 590*b338a2aeSMatthias Fend break; 591*b338a2aeSMatthias Fend default: 592*b338a2aeSMatthias Fend dev_err(dev, "led-source out of range [1-3]\n"); 593*b338a2aeSMatthias Fend return -EINVAL; 594*b338a2aeSMatthias Fend } 595*b338a2aeSMatthias Fend } 596*b338a2aeSMatthias Fend 597*b338a2aeSMatthias Fend /* 598*b338a2aeSMatthias Fend * If only channels 1 and 3 are used, the step size is doubled because the two channels 599*b338a2aeSMatthias Fend * share the same current control register. 600*b338a2aeSMatthias Fend */ 601*b338a2aeSMatthias Fend current_step_multiplier = 602*b338a2aeSMatthias Fend (tps6131x->chan1_en && tps6131x->chan3_en && !tps6131x->chan2_en) ? 2 : 1; 603*b338a2aeSMatthias Fend tps6131x->step_flash_current_ma = current_step_multiplier * TPS6131X_FLASH_STEP_I_MA; 604*b338a2aeSMatthias Fend tps6131x->step_torch_current_ma = current_step_multiplier * TPS6131X_TORCH_STEP_I_MA; 605*b338a2aeSMatthias Fend 606*b338a2aeSMatthias Fend ret = fwnode_property_read_u32(tps6131x->led_node, "led-max-microamp", ¤t_ua); 607*b338a2aeSMatthias Fend if (ret < 0) { 608*b338a2aeSMatthias Fend dev_err(dev, "Failed to read led-max-microamp property\n"); 609*b338a2aeSMatthias Fend return ret; 610*b338a2aeSMatthias Fend } 611*b338a2aeSMatthias Fend 612*b338a2aeSMatthias Fend tps6131x->max_torch_current_ma = UA_TO_MA(current_ua); 613*b338a2aeSMatthias Fend 614*b338a2aeSMatthias Fend if (!tps6131x->max_torch_current_ma || 615*b338a2aeSMatthias Fend tps6131x->max_torch_current_ma > max_current_torch_ma || 616*b338a2aeSMatthias Fend (tps6131x->max_torch_current_ma % tps6131x->step_torch_current_ma)) { 617*b338a2aeSMatthias Fend dev_err(dev, "led-max-microamp out of range or not a multiple of %u\n", 618*b338a2aeSMatthias Fend tps6131x->step_torch_current_ma); 619*b338a2aeSMatthias Fend return -EINVAL; 620*b338a2aeSMatthias Fend } 621*b338a2aeSMatthias Fend 622*b338a2aeSMatthias Fend ret = fwnode_property_read_u32(tps6131x->led_node, "flash-max-microamp", ¤t_ua); 623*b338a2aeSMatthias Fend if (ret < 0) { 624*b338a2aeSMatthias Fend dev_err(dev, "Failed to read flash-max-microamp property\n"); 625*b338a2aeSMatthias Fend return ret; 626*b338a2aeSMatthias Fend } 627*b338a2aeSMatthias Fend 628*b338a2aeSMatthias Fend tps6131x->max_flash_current_ma = UA_TO_MA(current_ua); 629*b338a2aeSMatthias Fend 630*b338a2aeSMatthias Fend if (!tps6131x->max_flash_current_ma || 631*b338a2aeSMatthias Fend tps6131x->max_flash_current_ma > max_current_flash_ma || 632*b338a2aeSMatthias Fend (tps6131x->max_flash_current_ma % tps6131x->step_flash_current_ma)) { 633*b338a2aeSMatthias Fend dev_err(dev, "flash-max-microamp out of range or not a multiple of %u\n", 634*b338a2aeSMatthias Fend tps6131x->step_flash_current_ma); 635*b338a2aeSMatthias Fend return -EINVAL; 636*b338a2aeSMatthias Fend } 637*b338a2aeSMatthias Fend 638*b338a2aeSMatthias Fend ret = fwnode_property_read_u32(tps6131x->led_node, "flash-max-timeout-us", &timeout_us); 639*b338a2aeSMatthias Fend if (ret < 0) { 640*b338a2aeSMatthias Fend dev_err(dev, "Failed to read flash-max-timeout-us property\n"); 641*b338a2aeSMatthias Fend return ret; 642*b338a2aeSMatthias Fend } 643*b338a2aeSMatthias Fend 644*b338a2aeSMatthias Fend timer_config = tps6131x_find_closest_timer_config(timeout_us); 645*b338a2aeSMatthias Fend tps6131x->max_timeout_us = timer_config->time_us; 646*b338a2aeSMatthias Fend 647*b338a2aeSMatthias Fend if (tps6131x->max_timeout_us != timeout_us) 648*b338a2aeSMatthias Fend dev_warn(dev, "flash-max-timeout-us %u not supported (using %u)\n", timeout_us, 649*b338a2aeSMatthias Fend tps6131x->max_timeout_us); 650*b338a2aeSMatthias Fend 651*b338a2aeSMatthias Fend return 0; 652*b338a2aeSMatthias Fend } 653*b338a2aeSMatthias Fend 654*b338a2aeSMatthias Fend static int tps6131x_led_class_setup(struct tps6131x *tps6131x) 655*b338a2aeSMatthias Fend { 656*b338a2aeSMatthias Fend const struct tps6131x_timer_config *timer_config; 657*b338a2aeSMatthias Fend struct led_classdev *led_cdev; 658*b338a2aeSMatthias Fend struct led_flash_setting *setting; 659*b338a2aeSMatthias Fend struct led_init_data init_data = {}; 660*b338a2aeSMatthias Fend int ret; 661*b338a2aeSMatthias Fend 662*b338a2aeSMatthias Fend tps6131x->fled_cdev.ops = &flash_ops; 663*b338a2aeSMatthias Fend 664*b338a2aeSMatthias Fend setting = &tps6131x->fled_cdev.timeout; 665*b338a2aeSMatthias Fend timer_config = tps6131x_find_closest_timer_config(0); 666*b338a2aeSMatthias Fend setting->min = timer_config->time_us; 667*b338a2aeSMatthias Fend setting->max = tps6131x->max_timeout_us; 668*b338a2aeSMatthias Fend setting->step = 1; /* Only some specific time periods are supported. No fixed step size. */ 669*b338a2aeSMatthias Fend setting->val = setting->min; 670*b338a2aeSMatthias Fend 671*b338a2aeSMatthias Fend setting = &tps6131x->fled_cdev.brightness; 672*b338a2aeSMatthias Fend setting->min = tps6131x->step_flash_current_ma; 673*b338a2aeSMatthias Fend setting->max = tps6131x->max_flash_current_ma; 674*b338a2aeSMatthias Fend setting->step = tps6131x->step_flash_current_ma; 675*b338a2aeSMatthias Fend setting->val = setting->min; 676*b338a2aeSMatthias Fend 677*b338a2aeSMatthias Fend led_cdev = &tps6131x->fled_cdev.led_cdev; 678*b338a2aeSMatthias Fend led_cdev->brightness_set_blocking = tps6131x_brightness_set; 679*b338a2aeSMatthias Fend led_cdev->max_brightness = tps6131x->max_torch_current_ma; 680*b338a2aeSMatthias Fend led_cdev->flags |= LED_DEV_CAP_FLASH; 681*b338a2aeSMatthias Fend 682*b338a2aeSMatthias Fend init_data.fwnode = tps6131x->led_node; 683*b338a2aeSMatthias Fend init_data.devicename = NULL; 684*b338a2aeSMatthias Fend init_data.default_label = NULL; 685*b338a2aeSMatthias Fend init_data.devname_mandatory = false; 686*b338a2aeSMatthias Fend 687*b338a2aeSMatthias Fend ret = devm_led_classdev_flash_register_ext(tps6131x->dev, &tps6131x->fled_cdev, 688*b338a2aeSMatthias Fend &init_data); 689*b338a2aeSMatthias Fend if (ret) 690*b338a2aeSMatthias Fend return ret; 691*b338a2aeSMatthias Fend 692*b338a2aeSMatthias Fend return 0; 693*b338a2aeSMatthias Fend } 694*b338a2aeSMatthias Fend 695*b338a2aeSMatthias Fend static int tps6131x_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, bool enable) 696*b338a2aeSMatthias Fend { 697*b338a2aeSMatthias Fend struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev; 698*b338a2aeSMatthias Fend struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 699*b338a2aeSMatthias Fend 700*b338a2aeSMatthias Fend guard(mutex)(&tps6131x->lock); 701*b338a2aeSMatthias Fend 702*b338a2aeSMatthias Fend return tps6131x_set_mode(tps6131x, enable ? TPS6131X_MODE_FLASH : TPS6131X_MODE_SHUTDOWN, 703*b338a2aeSMatthias Fend false); 704*b338a2aeSMatthias Fend } 705*b338a2aeSMatthias Fend 706*b338a2aeSMatthias Fend static const struct v4l2_flash_ops tps6131x_v4l2_flash_ops = { 707*b338a2aeSMatthias Fend .external_strobe_set = tps6131x_flash_external_strobe_set, 708*b338a2aeSMatthias Fend }; 709*b338a2aeSMatthias Fend 710*b338a2aeSMatthias Fend static int tps6131x_v4l2_setup(struct tps6131x *tps6131x) 711*b338a2aeSMatthias Fend { 712*b338a2aeSMatthias Fend struct v4l2_flash_config v4l2_cfg = { 0 }; 713*b338a2aeSMatthias Fend struct led_flash_setting *intensity = &v4l2_cfg.intensity; 714*b338a2aeSMatthias Fend 715*b338a2aeSMatthias Fend intensity->min = tps6131x->step_torch_current_ma; 716*b338a2aeSMatthias Fend intensity->max = tps6131x->max_torch_current_ma; 717*b338a2aeSMatthias Fend intensity->step = tps6131x->step_torch_current_ma; 718*b338a2aeSMatthias Fend intensity->val = intensity->min; 719*b338a2aeSMatthias Fend 720*b338a2aeSMatthias Fend strscpy(v4l2_cfg.dev_name, tps6131x->fled_cdev.led_cdev.dev->kobj.name, 721*b338a2aeSMatthias Fend sizeof(v4l2_cfg.dev_name)); 722*b338a2aeSMatthias Fend 723*b338a2aeSMatthias Fend v4l2_cfg.has_external_strobe = true; 724*b338a2aeSMatthias Fend v4l2_cfg.flash_faults = LED_FAULT_TIMEOUT | LED_FAULT_OVER_TEMPERATURE | 725*b338a2aeSMatthias Fend LED_FAULT_SHORT_CIRCUIT | LED_FAULT_UNDER_VOLTAGE | 726*b338a2aeSMatthias Fend LED_FAULT_LED_OVER_TEMPERATURE; 727*b338a2aeSMatthias Fend 728*b338a2aeSMatthias Fend tps6131x->v4l2_flash = v4l2_flash_init(tps6131x->dev, tps6131x->led_node, 729*b338a2aeSMatthias Fend &tps6131x->fled_cdev, &tps6131x_v4l2_flash_ops, 730*b338a2aeSMatthias Fend &v4l2_cfg); 731*b338a2aeSMatthias Fend if (IS_ERR(tps6131x->v4l2_flash)) { 732*b338a2aeSMatthias Fend dev_err(tps6131x->dev, "Failed to initialize v4l2 flash LED\n"); 733*b338a2aeSMatthias Fend return PTR_ERR(tps6131x->v4l2_flash); 734*b338a2aeSMatthias Fend } 735*b338a2aeSMatthias Fend 736*b338a2aeSMatthias Fend return 0; 737*b338a2aeSMatthias Fend } 738*b338a2aeSMatthias Fend 739*b338a2aeSMatthias Fend static int tps6131x_probe(struct i2c_client *client) 740*b338a2aeSMatthias Fend { 741*b338a2aeSMatthias Fend struct tps6131x *tps6131x; 742*b338a2aeSMatthias Fend int ret; 743*b338a2aeSMatthias Fend 744*b338a2aeSMatthias Fend tps6131x = devm_kzalloc(&client->dev, sizeof(*tps6131x), GFP_KERNEL); 745*b338a2aeSMatthias Fend if (!tps6131x) 746*b338a2aeSMatthias Fend return -ENOMEM; 747*b338a2aeSMatthias Fend 748*b338a2aeSMatthias Fend tps6131x->dev = &client->dev; 749*b338a2aeSMatthias Fend i2c_set_clientdata(client, tps6131x); 750*b338a2aeSMatthias Fend mutex_init(&tps6131x->lock); 751*b338a2aeSMatthias Fend INIT_DELAYED_WORK(&tps6131x->torch_refresh_work, tps6131x_torch_refresh_handler); 752*b338a2aeSMatthias Fend 753*b338a2aeSMatthias Fend ret = tps6131x_parse_node(tps6131x); 754*b338a2aeSMatthias Fend if (ret) 755*b338a2aeSMatthias Fend return ret; 756*b338a2aeSMatthias Fend 757*b338a2aeSMatthias Fend tps6131x->regmap = devm_regmap_init_i2c(client, &tps6131x_regmap); 758*b338a2aeSMatthias Fend if (IS_ERR(tps6131x->regmap)) { 759*b338a2aeSMatthias Fend ret = PTR_ERR(tps6131x->regmap); 760*b338a2aeSMatthias Fend return dev_err_probe(&client->dev, ret, "Failed to allocate register map\n"); 761*b338a2aeSMatthias Fend } 762*b338a2aeSMatthias Fend 763*b338a2aeSMatthias Fend tps6131x->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); 764*b338a2aeSMatthias Fend if (IS_ERR(tps6131x->reset_gpio)) { 765*b338a2aeSMatthias Fend ret = PTR_ERR(tps6131x->reset_gpio); 766*b338a2aeSMatthias Fend return dev_err_probe(&client->dev, ret, "Failed to get reset GPIO\n"); 767*b338a2aeSMatthias Fend } 768*b338a2aeSMatthias Fend 769*b338a2aeSMatthias Fend ret = tps6131x_reset_chip(tps6131x); 770*b338a2aeSMatthias Fend if (ret) 771*b338a2aeSMatthias Fend return dev_err_probe(&client->dev, ret, "Failed to reset LED controller\n"); 772*b338a2aeSMatthias Fend 773*b338a2aeSMatthias Fend ret = tps6131x_init_chip(tps6131x); 774*b338a2aeSMatthias Fend if (ret) 775*b338a2aeSMatthias Fend return dev_err_probe(&client->dev, ret, "Failed to initialize LED controller\n"); 776*b338a2aeSMatthias Fend 777*b338a2aeSMatthias Fend ret = tps6131x_led_class_setup(tps6131x); 778*b338a2aeSMatthias Fend if (ret) 779*b338a2aeSMatthias Fend return dev_err_probe(&client->dev, ret, "Failed to setup LED class\n"); 780*b338a2aeSMatthias Fend 781*b338a2aeSMatthias Fend ret = tps6131x_v4l2_setup(tps6131x); 782*b338a2aeSMatthias Fend if (ret) 783*b338a2aeSMatthias Fend return dev_err_probe(&client->dev, ret, "Failed to setup v4l2 flash\n"); 784*b338a2aeSMatthias Fend 785*b338a2aeSMatthias Fend return 0; 786*b338a2aeSMatthias Fend } 787*b338a2aeSMatthias Fend 788*b338a2aeSMatthias Fend static void tps6131x_remove(struct i2c_client *client) 789*b338a2aeSMatthias Fend { 790*b338a2aeSMatthias Fend struct tps6131x *tps6131x = i2c_get_clientdata(client); 791*b338a2aeSMatthias Fend 792*b338a2aeSMatthias Fend v4l2_flash_release(tps6131x->v4l2_flash); 793*b338a2aeSMatthias Fend 794*b338a2aeSMatthias Fend cancel_delayed_work_sync(&tps6131x->torch_refresh_work); 795*b338a2aeSMatthias Fend } 796*b338a2aeSMatthias Fend 797*b338a2aeSMatthias Fend static const struct of_device_id of_tps6131x_leds_match[] = { 798*b338a2aeSMatthias Fend { .compatible = "ti,tps61310" }, 799*b338a2aeSMatthias Fend {} 800*b338a2aeSMatthias Fend }; 801*b338a2aeSMatthias Fend MODULE_DEVICE_TABLE(of, of_tps6131x_leds_match); 802*b338a2aeSMatthias Fend 803*b338a2aeSMatthias Fend static struct i2c_driver tps6131x_i2c_driver = { 804*b338a2aeSMatthias Fend .driver = { 805*b338a2aeSMatthias Fend .name = "tps6131x", 806*b338a2aeSMatthias Fend .of_match_table = of_tps6131x_leds_match, 807*b338a2aeSMatthias Fend }, 808*b338a2aeSMatthias Fend .probe = tps6131x_probe, 809*b338a2aeSMatthias Fend .remove = tps6131x_remove, 810*b338a2aeSMatthias Fend }; 811*b338a2aeSMatthias Fend module_i2c_driver(tps6131x_i2c_driver); 812*b338a2aeSMatthias Fend 813*b338a2aeSMatthias Fend MODULE_DESCRIPTION("Texas Instruments TPS6131X flash LED driver"); 814*b338a2aeSMatthias Fend MODULE_AUTHOR("Matthias Fend <matthias.fend@emfend.at>"); 815*b338a2aeSMatthias Fend MODULE_LICENSE("GPL"); 816