1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Driver for TWL4030/6030 Generic Pulse Width Modulator 4 * 5 * Copyright (C) 2012 Texas Instruments 6 * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> 7 */ 8 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/platform_device.h> 12 #include <linux/pwm.h> 13 #include <linux/mfd/twl.h> 14 #include <linux/slab.h> 15 16 /* 17 * This driver handles the PWMs of TWL4030 and TWL6030. 18 * The TRM names for the PWMs on TWL4030 are: PWM0, PWM1 19 * TWL6030 also have two PWMs named in the TRM as PWM1, PWM2 20 */ 21 22 #define TWL_PWM_MAX 0x7f 23 24 /* Registers, bits and macro for TWL4030 */ 25 #define TWL4030_GPBR1_REG 0x0c 26 #define TWL4030_PMBR1_REG 0x0d 27 28 /* GPBR1 register bits */ 29 #define TWL4030_PWMXCLK_ENABLE (1 << 0) 30 #define TWL4030_PWMX_ENABLE (1 << 2) 31 #define TWL4030_PWMX_BITS (TWL4030_PWMX_ENABLE | TWL4030_PWMXCLK_ENABLE) 32 #define TWL4030_PWM_TOGGLE(pwm, x) ((x) << (pwm)) 33 34 /* PMBR1 register bits */ 35 #define TWL4030_GPIO6_PWM0_MUTE_MASK (0x03 << 2) 36 #define TWL4030_GPIO6_PWM0_MUTE_PWM0 (0x01 << 2) 37 #define TWL4030_GPIO7_VIBRASYNC_PWM1_MASK (0x03 << 4) 38 #define TWL4030_GPIO7_VIBRASYNC_PWM1_PWM1 (0x03 << 4) 39 40 /* Register, bits and macro for TWL6030 */ 41 #define TWL6030_TOGGLE3_REG 0x92 42 43 #define TWL6030_PWMXR (1 << 0) 44 #define TWL6030_PWMXS (1 << 1) 45 #define TWL6030_PWMXEN (1 << 2) 46 #define TWL6030_PWM_TOGGLE(pwm, x) ((x) << (pwm * 3)) 47 48 struct twl_pwm_chip { 49 struct mutex mutex; 50 u8 twl6030_toggle3; 51 u8 twl4030_pwm_mux; 52 }; 53 54 static inline struct twl_pwm_chip *to_twl(struct pwm_chip *chip) 55 { 56 return pwmchip_get_drvdata(chip); 57 } 58 59 static int twl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 60 u64 duty_ns, u64 period_ns) 61 { 62 int duty_cycle = DIV64_U64_ROUND_UP(duty_ns * TWL_PWM_MAX, period_ns) + 1; 63 u8 pwm_config[2] = { 1, 0 }; 64 int base, ret; 65 66 /* 67 * To configure the duty period: 68 * On-cycle is set to 1 (the minimum allowed value) 69 * The off time of 0 is not configurable, so the mapping is: 70 * 0 -> off cycle = 2, 71 * 1 -> off cycle = 2, 72 * 2 -> off cycle = 3, 73 * 126 - > off cycle 127, 74 * 127 - > off cycle 1 75 * When on cycle == off cycle the PWM will be always on 76 */ 77 if (duty_cycle == 1) 78 duty_cycle = 2; 79 else if (duty_cycle > TWL_PWM_MAX) 80 duty_cycle = 1; 81 82 base = pwm->hwpwm * 3; 83 84 pwm_config[1] = duty_cycle; 85 86 ret = twl_i2c_write(TWL_MODULE_PWM, pwm_config, base, 2); 87 if (ret < 0) 88 dev_err(pwmchip_parent(chip), "%s: Failed to configure PWM\n", pwm->label); 89 90 return ret; 91 } 92 93 static int twl4030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 94 { 95 struct twl_pwm_chip *twl = to_twl(chip); 96 int ret; 97 u8 val; 98 99 mutex_lock(&twl->mutex); 100 ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_GPBR1_REG); 101 if (ret < 0) { 102 dev_err(pwmchip_parent(chip), "%s: Failed to read GPBR1\n", pwm->label); 103 goto out; 104 } 105 106 val |= TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMXCLK_ENABLE); 107 108 ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG); 109 if (ret < 0) 110 dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM\n", pwm->label); 111 112 val |= TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMX_ENABLE); 113 114 ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG); 115 if (ret < 0) 116 dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM\n", pwm->label); 117 118 out: 119 mutex_unlock(&twl->mutex); 120 return ret; 121 } 122 123 static void twl4030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 124 { 125 struct twl_pwm_chip *twl = to_twl(chip); 126 int ret; 127 u8 val; 128 129 mutex_lock(&twl->mutex); 130 ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_GPBR1_REG); 131 if (ret < 0) { 132 dev_err(pwmchip_parent(chip), "%s: Failed to read GPBR1\n", pwm->label); 133 goto out; 134 } 135 136 val &= ~TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMX_ENABLE); 137 138 ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG); 139 if (ret < 0) 140 dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label); 141 142 val &= ~TWL4030_PWM_TOGGLE(pwm->hwpwm, TWL4030_PWMXCLK_ENABLE); 143 144 ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_GPBR1_REG); 145 if (ret < 0) 146 dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label); 147 148 out: 149 mutex_unlock(&twl->mutex); 150 } 151 152 static int twl4030_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) 153 { 154 struct twl_pwm_chip *twl = to_twl(chip); 155 int ret; 156 u8 val, mask, bits; 157 158 if (pwm->hwpwm == 1) { 159 mask = TWL4030_GPIO7_VIBRASYNC_PWM1_MASK; 160 bits = TWL4030_GPIO7_VIBRASYNC_PWM1_PWM1; 161 } else { 162 mask = TWL4030_GPIO6_PWM0_MUTE_MASK; 163 bits = TWL4030_GPIO6_PWM0_MUTE_PWM0; 164 } 165 166 mutex_lock(&twl->mutex); 167 ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_PMBR1_REG); 168 if (ret < 0) { 169 dev_err(pwmchip_parent(chip), "%s: Failed to read PMBR1\n", pwm->label); 170 goto out; 171 } 172 173 /* Save the current MUX configuration for the PWM */ 174 twl->twl4030_pwm_mux &= ~mask; 175 twl->twl4030_pwm_mux |= (val & mask); 176 177 /* Select PWM functionality */ 178 val &= ~mask; 179 val |= bits; 180 181 ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_PMBR1_REG); 182 if (ret < 0) 183 dev_err(pwmchip_parent(chip), "%s: Failed to request PWM\n", pwm->label); 184 185 out: 186 mutex_unlock(&twl->mutex); 187 return ret; 188 } 189 190 static void twl4030_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) 191 { 192 struct twl_pwm_chip *twl = to_twl(chip); 193 int ret; 194 u8 val, mask; 195 196 if (pwm->hwpwm == 1) 197 mask = TWL4030_GPIO7_VIBRASYNC_PWM1_MASK; 198 else 199 mask = TWL4030_GPIO6_PWM0_MUTE_MASK; 200 201 mutex_lock(&twl->mutex); 202 ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &val, TWL4030_PMBR1_REG); 203 if (ret < 0) { 204 dev_err(pwmchip_parent(chip), "%s: Failed to read PMBR1\n", pwm->label); 205 goto out; 206 } 207 208 /* Restore the MUX configuration for the PWM */ 209 val &= ~mask; 210 val |= (twl->twl4030_pwm_mux & mask); 211 212 ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, val, TWL4030_PMBR1_REG); 213 if (ret < 0) 214 dev_err(pwmchip_parent(chip), "%s: Failed to free PWM\n", pwm->label); 215 216 out: 217 mutex_unlock(&twl->mutex); 218 } 219 220 static int twl6030_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 221 { 222 struct twl_pwm_chip *twl = to_twl(chip); 223 int ret; 224 u8 val; 225 226 mutex_lock(&twl->mutex); 227 val = twl->twl6030_toggle3; 228 val |= TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXS | TWL6030_PWMXEN); 229 val &= ~TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXR); 230 231 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG); 232 if (ret < 0) { 233 dev_err(pwmchip_parent(chip), "%s: Failed to enable PWM\n", pwm->label); 234 goto out; 235 } 236 237 twl->twl6030_toggle3 = val; 238 out: 239 mutex_unlock(&twl->mutex); 240 return ret; 241 } 242 243 static void twl6030_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 244 { 245 struct twl_pwm_chip *twl = to_twl(chip); 246 int ret; 247 u8 val; 248 249 mutex_lock(&twl->mutex); 250 val = twl->twl6030_toggle3; 251 val |= TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXR); 252 val &= ~TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXS | TWL6030_PWMXEN); 253 254 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG); 255 if (ret < 0) { 256 dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label); 257 goto out; 258 } 259 260 val |= TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXEN); 261 262 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG); 263 if (ret < 0) { 264 dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label); 265 goto out; 266 } 267 268 val &= ~TWL6030_PWM_TOGGLE(pwm->hwpwm, TWL6030_PWMXEN); 269 270 ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_TOGGLE3_REG); 271 if (ret < 0) { 272 dev_err(pwmchip_parent(chip), "%s: Failed to disable PWM\n", pwm->label); 273 goto out; 274 } 275 276 twl->twl6030_toggle3 = val; 277 out: 278 mutex_unlock(&twl->mutex); 279 } 280 281 static int twl4030_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 282 const struct pwm_state *state) 283 { 284 int err; 285 286 if (state->polarity != PWM_POLARITY_NORMAL) 287 return -EINVAL; 288 289 if (!state->enabled) { 290 if (pwm->state.enabled) 291 twl4030_pwm_disable(chip, pwm); 292 293 return 0; 294 } 295 296 err = twl_pwm_config(chip, pwm, state->duty_cycle, state->period); 297 if (err) 298 return err; 299 300 if (!pwm->state.enabled) 301 err = twl4030_pwm_enable(chip, pwm); 302 303 return err; 304 } 305 306 static int twl6030_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 307 const struct pwm_state *state) 308 { 309 int err; 310 311 if (state->polarity != PWM_POLARITY_NORMAL) 312 return -EINVAL; 313 314 if (!state->enabled) { 315 if (pwm->state.enabled) 316 twl6030_pwm_disable(chip, pwm); 317 318 return 0; 319 } 320 321 err = twl_pwm_config(chip, pwm, state->duty_cycle, state->period); 322 if (err) 323 return err; 324 325 if (!pwm->state.enabled) 326 err = twl6030_pwm_enable(chip, pwm); 327 328 return err; 329 } 330 331 static const struct pwm_ops twl4030_pwm_ops = { 332 .apply = twl4030_pwm_apply, 333 .request = twl4030_pwm_request, 334 .free = twl4030_pwm_free, 335 }; 336 337 static const struct pwm_ops twl6030_pwm_ops = { 338 .apply = twl6030_pwm_apply, 339 }; 340 341 static int twl_pwm_probe(struct platform_device *pdev) 342 { 343 struct pwm_chip *chip; 344 struct twl_pwm_chip *twl; 345 346 chip = devm_pwmchip_alloc(&pdev->dev, 2, sizeof(*twl)); 347 if (IS_ERR(chip)) 348 return PTR_ERR(chip); 349 twl = to_twl(chip); 350 351 if (twl_class_is_4030()) 352 chip->ops = &twl4030_pwm_ops; 353 else 354 chip->ops = &twl6030_pwm_ops; 355 356 mutex_init(&twl->mutex); 357 358 return devm_pwmchip_add(&pdev->dev, chip); 359 } 360 361 #ifdef CONFIG_OF 362 static const struct of_device_id twl_pwm_of_match[] = { 363 { .compatible = "ti,twl4030-pwm" }, 364 { .compatible = "ti,twl6030-pwm" }, 365 { }, 366 }; 367 MODULE_DEVICE_TABLE(of, twl_pwm_of_match); 368 #endif 369 370 static struct platform_driver twl_pwm_driver = { 371 .driver = { 372 .name = "twl-pwm", 373 .of_match_table = of_match_ptr(twl_pwm_of_match), 374 }, 375 .probe = twl_pwm_probe, 376 }; 377 module_platform_driver(twl_pwm_driver); 378 379 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); 380 MODULE_DESCRIPTION("PWM driver for TWL4030 and TWL6030"); 381 MODULE_ALIAS("platform:twl-pwm"); 382 MODULE_LICENSE("GPL"); 383