1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2018 Spreadtrum Communications Inc. 3 4 #include <linux/leds.h> 5 #include <linux/module.h> 6 #include <linux/of.h> 7 #include <linux/platform_device.h> 8 #include <linux/regmap.h> 9 10 /* PMIC global control register definition */ 11 #define SC27XX_MODULE_EN0 0xc08 12 #define SC27XX_CLK_EN0 0xc18 13 #define SC27XX_RGB_CTRL 0xebc 14 15 #define SC27XX_BLTC_EN BIT(9) 16 #define SC27XX_RTC_EN BIT(7) 17 #define SC27XX_RGB_PD BIT(0) 18 19 /* Breathing light controller register definition */ 20 #define SC27XX_LEDS_CTRL 0x00 21 #define SC27XX_LEDS_PRESCALE 0x04 22 #define SC27XX_LEDS_DUTY 0x08 23 #define SC27XX_LEDS_CURVE0 0x0c 24 #define SC27XX_LEDS_CURVE1 0x10 25 26 #define SC27XX_CTRL_SHIFT 4 27 #define SC27XX_LED_RUN BIT(0) 28 #define SC27XX_LED_TYPE BIT(1) 29 30 #define SC27XX_DUTY_SHIFT 8 31 #define SC27XX_DUTY_MASK GENMASK(15, 0) 32 #define SC27XX_MOD_MASK GENMASK(7, 0) 33 34 #define SC27XX_CURVE_SHIFT 8 35 #define SC27XX_CURVE_L_MASK GENMASK(7, 0) 36 #define SC27XX_CURVE_H_MASK GENMASK(15, 8) 37 38 #define SC27XX_LEDS_OFFSET 0x10 39 #define SC27XX_LEDS_MAX 3 40 #define SC27XX_LEDS_PATTERN_CNT 4 41 /* Stage duration step, in milliseconds */ 42 #define SC27XX_LEDS_STEP 125 43 /* Minimum and maximum duration, in milliseconds */ 44 #define SC27XX_DELTA_T_MIN SC27XX_LEDS_STEP 45 #define SC27XX_DELTA_T_MAX (SC27XX_LEDS_STEP * 255) 46 47 struct sc27xx_led { 48 struct fwnode_handle *fwnode; 49 struct led_classdev ldev; 50 struct sc27xx_led_priv *priv; 51 u8 line; 52 bool active; 53 }; 54 55 struct sc27xx_led_priv { 56 struct sc27xx_led leds[SC27XX_LEDS_MAX]; 57 struct regmap *regmap; 58 struct mutex lock; 59 u32 base; 60 }; 61 62 #define to_sc27xx_led(ldev) \ 63 container_of(ldev, struct sc27xx_led, ldev) 64 65 static int sc27xx_led_init(struct regmap *regmap) 66 { 67 int err; 68 69 err = regmap_update_bits(regmap, SC27XX_MODULE_EN0, SC27XX_BLTC_EN, 70 SC27XX_BLTC_EN); 71 if (err) 72 return err; 73 74 err = regmap_update_bits(regmap, SC27XX_CLK_EN0, SC27XX_RTC_EN, 75 SC27XX_RTC_EN); 76 if (err) 77 return err; 78 79 return regmap_update_bits(regmap, SC27XX_RGB_CTRL, SC27XX_RGB_PD, 0); 80 } 81 82 static u32 sc27xx_led_get_offset(struct sc27xx_led *leds) 83 { 84 return leds->priv->base + SC27XX_LEDS_OFFSET * leds->line; 85 } 86 87 static int sc27xx_led_enable(struct sc27xx_led *leds, enum led_brightness value) 88 { 89 u32 base = sc27xx_led_get_offset(leds); 90 u32 ctrl_base = leds->priv->base + SC27XX_LEDS_CTRL; 91 u8 ctrl_shift = SC27XX_CTRL_SHIFT * leds->line; 92 struct regmap *regmap = leds->priv->regmap; 93 int err; 94 95 err = regmap_update_bits(regmap, base + SC27XX_LEDS_DUTY, 96 SC27XX_DUTY_MASK, 97 (value << SC27XX_DUTY_SHIFT) | 98 SC27XX_MOD_MASK); 99 if (err) 100 return err; 101 102 return regmap_update_bits(regmap, ctrl_base, 103 (SC27XX_LED_RUN | SC27XX_LED_TYPE) << ctrl_shift, 104 (SC27XX_LED_RUN | SC27XX_LED_TYPE) << ctrl_shift); 105 } 106 107 static int sc27xx_led_disable(struct sc27xx_led *leds) 108 { 109 struct regmap *regmap = leds->priv->regmap; 110 u32 ctrl_base = leds->priv->base + SC27XX_LEDS_CTRL; 111 u8 ctrl_shift = SC27XX_CTRL_SHIFT * leds->line; 112 113 return regmap_update_bits(regmap, ctrl_base, 114 (SC27XX_LED_RUN | SC27XX_LED_TYPE) << ctrl_shift, 0); 115 } 116 117 static int sc27xx_led_set(struct led_classdev *ldev, enum led_brightness value) 118 { 119 struct sc27xx_led *leds = to_sc27xx_led(ldev); 120 int err; 121 122 mutex_lock(&leds->priv->lock); 123 124 if (value == LED_OFF) 125 err = sc27xx_led_disable(leds); 126 else 127 err = sc27xx_led_enable(leds, value); 128 129 mutex_unlock(&leds->priv->lock); 130 131 return err; 132 } 133 134 static void sc27xx_led_clamp_align_delta_t(u32 *delta_t) 135 { 136 u32 v, offset, t = *delta_t; 137 138 v = t + SC27XX_LEDS_STEP / 2; 139 v = clamp_t(u32, v, SC27XX_DELTA_T_MIN, SC27XX_DELTA_T_MAX); 140 offset = v - SC27XX_DELTA_T_MIN; 141 offset = SC27XX_LEDS_STEP * (offset / SC27XX_LEDS_STEP); 142 143 *delta_t = SC27XX_DELTA_T_MIN + offset; 144 } 145 146 static int sc27xx_led_pattern_clear(struct led_classdev *ldev) 147 { 148 struct sc27xx_led *leds = to_sc27xx_led(ldev); 149 struct regmap *regmap = leds->priv->regmap; 150 u32 base = sc27xx_led_get_offset(leds); 151 u32 ctrl_base = leds->priv->base + SC27XX_LEDS_CTRL; 152 u8 ctrl_shift = SC27XX_CTRL_SHIFT * leds->line; 153 int err; 154 155 mutex_lock(&leds->priv->lock); 156 157 /* Reset the rise, high, fall and low time to zero. */ 158 regmap_write(regmap, base + SC27XX_LEDS_CURVE0, 0); 159 regmap_write(regmap, base + SC27XX_LEDS_CURVE1, 0); 160 161 err = regmap_update_bits(regmap, ctrl_base, 162 (SC27XX_LED_RUN | SC27XX_LED_TYPE) << ctrl_shift, 0); 163 164 ldev->brightness = LED_OFF; 165 166 mutex_unlock(&leds->priv->lock); 167 168 return err; 169 } 170 171 static int sc27xx_led_pattern_set(struct led_classdev *ldev, 172 struct led_pattern *pattern, 173 u32 len, int repeat) 174 { 175 struct sc27xx_led *leds = to_sc27xx_led(ldev); 176 u32 base = sc27xx_led_get_offset(leds); 177 u32 ctrl_base = leds->priv->base + SC27XX_LEDS_CTRL; 178 u8 ctrl_shift = SC27XX_CTRL_SHIFT * leds->line; 179 struct regmap *regmap = leds->priv->regmap; 180 int err; 181 182 /* 183 * Must contain 4 tuples to configure the rise time, high time, fall 184 * time and low time to enable the breathing mode. 185 */ 186 if (len != SC27XX_LEDS_PATTERN_CNT) 187 return -EINVAL; 188 189 mutex_lock(&leds->priv->lock); 190 191 sc27xx_led_clamp_align_delta_t(&pattern[0].delta_t); 192 err = regmap_update_bits(regmap, base + SC27XX_LEDS_CURVE0, 193 SC27XX_CURVE_L_MASK, 194 pattern[0].delta_t / SC27XX_LEDS_STEP); 195 if (err) 196 goto out; 197 198 sc27xx_led_clamp_align_delta_t(&pattern[1].delta_t); 199 err = regmap_update_bits(regmap, base + SC27XX_LEDS_CURVE1, 200 SC27XX_CURVE_L_MASK, 201 pattern[1].delta_t / SC27XX_LEDS_STEP); 202 if (err) 203 goto out; 204 205 sc27xx_led_clamp_align_delta_t(&pattern[2].delta_t); 206 err = regmap_update_bits(regmap, base + SC27XX_LEDS_CURVE0, 207 SC27XX_CURVE_H_MASK, 208 (pattern[2].delta_t / SC27XX_LEDS_STEP) << 209 SC27XX_CURVE_SHIFT); 210 if (err) 211 goto out; 212 213 sc27xx_led_clamp_align_delta_t(&pattern[3].delta_t); 214 err = regmap_update_bits(regmap, base + SC27XX_LEDS_CURVE1, 215 SC27XX_CURVE_H_MASK, 216 (pattern[3].delta_t / SC27XX_LEDS_STEP) << 217 SC27XX_CURVE_SHIFT); 218 if (err) 219 goto out; 220 221 err = regmap_update_bits(regmap, base + SC27XX_LEDS_DUTY, 222 SC27XX_DUTY_MASK, 223 (pattern[1].brightness << SC27XX_DUTY_SHIFT) | 224 SC27XX_MOD_MASK); 225 if (err) 226 goto out; 227 228 /* Enable the LED breathing mode */ 229 err = regmap_update_bits(regmap, ctrl_base, 230 SC27XX_LED_RUN << ctrl_shift, 231 SC27XX_LED_RUN << ctrl_shift); 232 if (!err) 233 ldev->brightness = pattern[1].brightness; 234 235 out: 236 mutex_unlock(&leds->priv->lock); 237 238 return err; 239 } 240 241 static int sc27xx_led_register(struct device *dev, struct sc27xx_led_priv *priv) 242 { 243 int i, err; 244 245 err = sc27xx_led_init(priv->regmap); 246 if (err) 247 return err; 248 249 for (i = 0; i < SC27XX_LEDS_MAX; i++) { 250 struct sc27xx_led *led = &priv->leds[i]; 251 struct led_init_data init_data = {}; 252 253 if (!led->active) 254 continue; 255 256 led->line = i; 257 led->priv = priv; 258 led->ldev.brightness_set_blocking = sc27xx_led_set; 259 led->ldev.pattern_set = sc27xx_led_pattern_set; 260 led->ldev.pattern_clear = sc27xx_led_pattern_clear; 261 led->ldev.default_trigger = "pattern"; 262 263 init_data.fwnode = led->fwnode; 264 init_data.devicename = "sc27xx"; 265 init_data.default_label = ":"; 266 267 err = devm_led_classdev_register_ext(dev, &led->ldev, 268 &init_data); 269 if (err) 270 return err; 271 } 272 273 return 0; 274 } 275 276 static int sc27xx_led_probe(struct platform_device *pdev) 277 { 278 struct device *dev = &pdev->dev; 279 struct device_node *np = dev_of_node(dev); 280 struct sc27xx_led_priv *priv; 281 u32 base, count, reg; 282 int err; 283 284 count = of_get_available_child_count(np); 285 if (!count || count > SC27XX_LEDS_MAX) 286 return -EINVAL; 287 288 err = of_property_read_u32(np, "reg", &base); 289 if (err) { 290 dev_err(dev, "fail to get reg of property\n"); 291 return err; 292 } 293 294 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 295 if (!priv) 296 return -ENOMEM; 297 298 platform_set_drvdata(pdev, priv); 299 priv->base = base; 300 priv->regmap = dev_get_regmap(dev->parent, NULL); 301 if (!priv->regmap) { 302 err = -ENODEV; 303 dev_err(dev, "failed to get regmap: %d\n", err); 304 return err; 305 } 306 307 for_each_available_child_of_node_scoped(np, child) { 308 err = of_property_read_u32(child, "reg", ®); 309 if (err) 310 return err; 311 312 if (reg >= SC27XX_LEDS_MAX || priv->leds[reg].active) 313 return -EINVAL; 314 315 priv->leds[reg].fwnode = of_fwnode_handle(child); 316 priv->leds[reg].active = true; 317 } 318 319 mutex_init(&priv->lock); 320 321 err = sc27xx_led_register(dev, priv); 322 if (err) 323 mutex_destroy(&priv->lock); 324 325 return err; 326 } 327 328 static void sc27xx_led_remove(struct platform_device *pdev) 329 { 330 struct sc27xx_led_priv *priv = platform_get_drvdata(pdev); 331 332 mutex_destroy(&priv->lock); 333 } 334 335 static const struct of_device_id sc27xx_led_of_match[] = { 336 { .compatible = "sprd,sc2731-bltc", }, 337 { } 338 }; 339 MODULE_DEVICE_TABLE(of, sc27xx_led_of_match); 340 341 static struct platform_driver sc27xx_led_driver = { 342 .driver = { 343 .name = "sprd-bltc", 344 .of_match_table = sc27xx_led_of_match, 345 }, 346 .probe = sc27xx_led_probe, 347 .remove_new = sc27xx_led_remove, 348 }; 349 350 module_platform_driver(sc27xx_led_driver); 351 352 MODULE_DESCRIPTION("Spreadtrum SC27xx breathing light controller driver"); 353 MODULE_AUTHOR("Xiaotong Lu <xiaotong.lu@spreadtrum.com>"); 354 MODULE_AUTHOR("Baolin Wang <baolin.wang@linaro.org>"); 355 MODULE_LICENSE("GPL v2"); 356