1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Driver for TWL4030/6030 Pulse Width Modulator used as LED driver 4 * 5 * Copyright (C) 2012 Texas Instruments 6 * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> 7 * 8 * This driver is a complete rewrite of the former pwm-twl6030.c authorded by: 9 * Hemanth V <hemanthv@ti.com> 10 * 11 * Reference manual for the twl6030 is available at: 12 * https://www.ti.com/lit/ds/symlink/twl6030.pdf 13 * 14 * Limitations: 15 * - The twl6030 hardware only supports two period lengths (128 clock ticks and 16 * 64 clock ticks), the driver only uses 128 ticks 17 * - The hardware doesn't support ON = 0, so the active part of a period doesn't 18 * start at its beginning. 19 * - The hardware could support inverted polarity (with a similar limitation as 20 * for normal: the last clock tick is always inactive). 21 * - The hardware emits a constant low output when disabled. 22 * - A request for .duty_cycle = 0 results in an output wave with one active 23 * clock tick per period. This should better use the disabled state. 24 * - The driver only implements setting the relative duty cycle. 25 * - The driver doesn't implement .get_state(). 26 */ 27 28 #include <linux/module.h> 29 #include <linux/of.h> 30 #include <linux/platform_device.h> 31 #include <linux/pwm.h> 32 #include <linux/mfd/twl.h> 33 #include <linux/slab.h> 34 35 /* 36 * This driver handles the PWM driven LED terminals of TWL4030 and TWL6030. 37 * To generate the signal on TWL4030: 38 * - LEDA uses PWMA 39 * - LEDB uses PWMB 40 * TWL6030 has one LED pin with dedicated LEDPWM 41 */ 42 43 #define TWL4030_LED_MAX 0x7f 44 #define TWL6030_LED_MAX 0xff 45 46 /* Registers, bits and macro for TWL4030 */ 47 #define TWL4030_LEDEN_REG 0x00 48 #define TWL4030_PWMA_REG 0x01 49 50 #define TWL4030_LEDXON (1 << 0) 51 #define TWL4030_LEDXPWM (1 << 4) 52 #define TWL4030_LED_PINS (TWL4030_LEDXON | TWL4030_LEDXPWM) 53 #define TWL4030_LED_TOGGLE(led, x) ((x) << (led)) 54 55 /* Register, bits and macro for TWL6030 */ 56 #define TWL6030_LED_PWM_CTRL1 0xf4 57 #define TWL6030_LED_PWM_CTRL2 0xf5 58 59 #define TWL6040_LED_MODE_HW 0x00 60 #define TWL6040_LED_MODE_ON 0x01 61 #define TWL6040_LED_MODE_OFF 0x02 62 #define TWL6040_LED_MODE_MASK 0x03 63 64 static inline struct twl_pwmled_chip *to_twl(struct pwm_chip *chip) 65 { 66 return pwmchip_get_drvdata(chip); 67 } 68 69 static int twl4030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm, 70 int duty_ns, int period_ns) 71 { 72 int duty_cycle = DIV_ROUND_UP(duty_ns * TWL4030_LED_MAX, period_ns) + 1; 73 u8 pwm_config[2] = { 1, 0 }; 74 int base, ret; 75 76 /* 77 * To configure the duty period: 78 * On-cycle is set to 1 (the minimum allowed value) 79 * The off time of 0 is not configurable, so the mapping is: 80 * 0 -> off cycle = 2, 81 * 1 -> off cycle = 2, 82 * 2 -> off cycle = 3, 83 * 126 - > off cycle 127, 84 * 127 - > off cycle 1 85 * When on cycle == off cycle the PWM will be always on 86 */ 87 if (duty_cycle == 1) 88 duty_cycle = 2; 89 else if (duty_cycle > TWL4030_LED_MAX) 90 duty_cycle = 1; 91 92 base = pwm->hwpwm * 2 + TWL4030_PWMA_REG; 93 94 pwm_config[1] = duty_cycle; 95 96 ret = twl_i2c_write(TWL4030_MODULE_LED, pwm_config, base, 2); 97 if (ret < 0) 98 dev_err(pwmchip_parent(chip), "%s: Failed to configure PWM\n", pwm->label); 99 100 return ret; 101 } 102 103 static int twl4030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm) 104 { 105 int ret; 106 u8 val; 107 108 ret = twl_i2c_read_u8(TWL4030_MODULE_LED, &val, TWL4030_LEDEN_REG); 109 if (ret < 0) { 110 dev_err(pwmchip_parent(chip), "%s: Failed to read LEDEN\n", pwm->label); 111 return ret; 112 } 113 114 val |= TWL4030_LED_TOGGLE(pwm->hwpwm, TWL4030_LED_PINS); 115 116 ret = twl_i2c_write_u8(TWL4030_MODULE_LED, val, TWL4030_LEDEN_REG); 117 if (ret < 0) 118 dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM\n", pwm->label); 119 120 return ret; 121 } 122 123 static void twl4030_pwmled_disable(struct pwm_chip *chip, 124 struct pwm_device *pwm) 125 { 126 int ret; 127 u8 val; 128 129 ret = twl_i2c_read_u8(TWL4030_MODULE_LED, &val, TWL4030_LEDEN_REG); 130 if (ret < 0) { 131 dev_err(pwmchip_parent(chip), "%s: Failed to read LEDEN\n", pwm->label); 132 return; 133 } 134 135 val &= ~TWL4030_LED_TOGGLE(pwm->hwpwm, TWL4030_LED_PINS); 136 137 ret = twl_i2c_write_u8(TWL4030_MODULE_LED, val, TWL4030_LEDEN_REG); 138 if (ret < 0) 139 dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label); 140 } 141 142 static int twl4030_pwmled_apply(struct pwm_chip *chip, struct pwm_device *pwm, 143 const struct pwm_state *state) 144 { 145 int ret; 146 147 if (state->polarity != PWM_POLARITY_NORMAL) 148 return -EINVAL; 149 150 if (!state->enabled) { 151 if (pwm->state.enabled) 152 twl4030_pwmled_disable(chip, pwm); 153 154 return 0; 155 } 156 157 /* 158 * We cannot skip calling ->config even if state->period == 159 * pwm->state.period && state->duty_cycle == pwm->state.duty_cycle 160 * because we might have exited early in the last call to 161 * pwm_apply_might_sleep because of !state->enabled and so the two values in 162 * pwm->state might not be configured in hardware. 163 */ 164 ret = twl4030_pwmled_config(chip, pwm, 165 state->duty_cycle, state->period); 166 if (ret) 167 return ret; 168 169 if (!pwm->state.enabled) 170 ret = twl4030_pwmled_enable(chip, pwm); 171 172 return ret; 173 } 174 175 176 static const struct pwm_ops twl4030_pwmled_ops = { 177 .apply = twl4030_pwmled_apply, 178 }; 179 180 static int twl6030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm, 181 int duty_ns, int period_ns) 182 { 183 int duty_cycle = (duty_ns * TWL6030_LED_MAX) / period_ns; 184 u8 on_time; 185 int ret; 186 187 on_time = duty_cycle & 0xff; 188 189 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, on_time, 190 TWL6030_LED_PWM_CTRL1); 191 if (ret < 0) 192 dev_err(pwmchip_parent(chip), "%s: Failed to configure PWM\n", pwm->label); 193 194 return ret; 195 } 196 197 static int twl6030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm) 198 { 199 int ret; 200 u8 val; 201 202 ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); 203 if (ret < 0) { 204 dev_err(pwmchip_parent(chip), "%s: Failed to read PWM_CTRL2\n", 205 pwm->label); 206 return ret; 207 } 208 209 val &= ~TWL6040_LED_MODE_MASK; 210 val |= TWL6040_LED_MODE_ON; 211 212 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); 213 if (ret < 0) 214 dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM\n", pwm->label); 215 216 return ret; 217 } 218 219 static void twl6030_pwmled_disable(struct pwm_chip *chip, 220 struct pwm_device *pwm) 221 { 222 int ret; 223 u8 val; 224 225 ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); 226 if (ret < 0) { 227 dev_err(pwmchip_parent(chip), "%s: Failed to read PWM_CTRL2\n", 228 pwm->label); 229 return; 230 } 231 232 val &= ~TWL6040_LED_MODE_MASK; 233 val |= TWL6040_LED_MODE_OFF; 234 235 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); 236 if (ret < 0) 237 dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label); 238 } 239 240 static int twl6030_pwmled_apply(struct pwm_chip *chip, struct pwm_device *pwm, 241 const struct pwm_state *state) 242 { 243 int err; 244 245 if (state->polarity != pwm->state.polarity) 246 return -EINVAL; 247 248 if (!state->enabled) { 249 if (pwm->state.enabled) 250 twl6030_pwmled_disable(chip, pwm); 251 252 return 0; 253 } 254 255 err = twl6030_pwmled_config(chip, pwm, 256 state->duty_cycle, state->period); 257 if (err) 258 return err; 259 260 if (!pwm->state.enabled) 261 err = twl6030_pwmled_enable(chip, pwm); 262 263 return err; 264 } 265 266 static int twl6030_pwmled_request(struct pwm_chip *chip, struct pwm_device *pwm) 267 { 268 int ret; 269 u8 val; 270 271 ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); 272 if (ret < 0) { 273 dev_err(pwmchip_parent(chip), "%s: Failed to read PWM_CTRL2\n", 274 pwm->label); 275 return ret; 276 } 277 278 val &= ~TWL6040_LED_MODE_MASK; 279 val |= TWL6040_LED_MODE_OFF; 280 281 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); 282 if (ret < 0) 283 dev_err(pwmchip_parent(chip), "%s: Failed to request PWM\n", pwm->label); 284 285 return ret; 286 } 287 288 static void twl6030_pwmled_free(struct pwm_chip *chip, struct pwm_device *pwm) 289 { 290 int ret; 291 u8 val; 292 293 ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); 294 if (ret < 0) { 295 dev_err(pwmchip_parent(chip), "%s: Failed to read PWM_CTRL2\n", 296 pwm->label); 297 return; 298 } 299 300 val &= ~TWL6040_LED_MODE_MASK; 301 val |= TWL6040_LED_MODE_HW; 302 303 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); 304 if (ret < 0) 305 dev_err(pwmchip_parent(chip), "%s: Failed to free PWM\n", pwm->label); 306 } 307 308 static const struct pwm_ops twl6030_pwmled_ops = { 309 .apply = twl6030_pwmled_apply, 310 .request = twl6030_pwmled_request, 311 .free = twl6030_pwmled_free, 312 }; 313 314 static int twl_pwmled_probe(struct platform_device *pdev) 315 { 316 struct pwm_chip *chip; 317 unsigned int npwm; 318 const struct pwm_ops *ops; 319 320 if (twl_class_is_4030()) { 321 ops = &twl4030_pwmled_ops; 322 npwm = 2; 323 } else { 324 ops = &twl6030_pwmled_ops; 325 npwm = 1; 326 } 327 328 chip = devm_pwmchip_alloc(&pdev->dev, npwm, 0); 329 if (IS_ERR(chip)) 330 return PTR_ERR(chip); 331 332 chip->ops = ops; 333 334 return devm_pwmchip_add(&pdev->dev, chip); 335 } 336 337 #ifdef CONFIG_OF 338 static const struct of_device_id twl_pwmled_of_match[] = { 339 { .compatible = "ti,twl4030-pwmled" }, 340 { .compatible = "ti,twl6030-pwmled" }, 341 { }, 342 }; 343 MODULE_DEVICE_TABLE(of, twl_pwmled_of_match); 344 #endif 345 346 static struct platform_driver twl_pwmled_driver = { 347 .driver = { 348 .name = "twl-pwmled", 349 .of_match_table = of_match_ptr(twl_pwmled_of_match), 350 }, 351 .probe = twl_pwmled_probe, 352 }; 353 module_platform_driver(twl_pwmled_driver); 354 355 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); 356 MODULE_DESCRIPTION("PWM driver for TWL4030 and TWL6030 LED outputs"); 357 MODULE_ALIAS("platform:twl-pwmled"); 358 MODULE_LICENSE("GPL"); 359