18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for TWL4030/6030 Pulse Width Modulator used as LED driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2012 Texas Instruments 68c2ecf20Sopenharmony_ci * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This driver is a complete rewrite of the former pwm-twl6030.c authorded by: 98c2ecf20Sopenharmony_ci * Hemanth V <hemanthv@ti.com> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/of.h> 148c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 158c2ecf20Sopenharmony_ci#include <linux/pwm.h> 168c2ecf20Sopenharmony_ci#include <linux/mfd/twl.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* 208c2ecf20Sopenharmony_ci * This driver handles the PWM driven LED terminals of TWL4030 and TWL6030. 218c2ecf20Sopenharmony_ci * To generate the signal on TWL4030: 228c2ecf20Sopenharmony_ci * - LEDA uses PWMA 238c2ecf20Sopenharmony_ci * - LEDB uses PWMB 248c2ecf20Sopenharmony_ci * TWL6030 has one LED pin with dedicated LEDPWM 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define TWL4030_LED_MAX 0x7f 288c2ecf20Sopenharmony_ci#define TWL6030_LED_MAX 0xff 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* Registers, bits and macro for TWL4030 */ 318c2ecf20Sopenharmony_ci#define TWL4030_LEDEN_REG 0x00 328c2ecf20Sopenharmony_ci#define TWL4030_PWMA_REG 0x01 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define TWL4030_LEDXON (1 << 0) 358c2ecf20Sopenharmony_ci#define TWL4030_LEDXPWM (1 << 4) 368c2ecf20Sopenharmony_ci#define TWL4030_LED_PINS (TWL4030_LEDXON | TWL4030_LEDXPWM) 378c2ecf20Sopenharmony_ci#define TWL4030_LED_TOGGLE(led, x) ((x) << (led)) 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* Register, bits and macro for TWL6030 */ 408c2ecf20Sopenharmony_ci#define TWL6030_LED_PWM_CTRL1 0xf4 418c2ecf20Sopenharmony_ci#define TWL6030_LED_PWM_CTRL2 0xf5 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define TWL6040_LED_MODE_HW 0x00 448c2ecf20Sopenharmony_ci#define TWL6040_LED_MODE_ON 0x01 458c2ecf20Sopenharmony_ci#define TWL6040_LED_MODE_OFF 0x02 468c2ecf20Sopenharmony_ci#define TWL6040_LED_MODE_MASK 0x03 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistruct twl_pwmled_chip { 498c2ecf20Sopenharmony_ci struct pwm_chip chip; 508c2ecf20Sopenharmony_ci struct mutex mutex; 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic inline struct twl_pwmled_chip *to_twl(struct pwm_chip *chip) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci return container_of(chip, struct twl_pwmled_chip, chip); 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic int twl4030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm, 598c2ecf20Sopenharmony_ci int duty_ns, int period_ns) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci int duty_cycle = DIV_ROUND_UP(duty_ns * TWL4030_LED_MAX, period_ns) + 1; 628c2ecf20Sopenharmony_ci u8 pwm_config[2] = { 1, 0 }; 638c2ecf20Sopenharmony_ci int base, ret; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci /* 668c2ecf20Sopenharmony_ci * To configure the duty period: 678c2ecf20Sopenharmony_ci * On-cycle is set to 1 (the minimum allowed value) 688c2ecf20Sopenharmony_ci * The off time of 0 is not configurable, so the mapping is: 698c2ecf20Sopenharmony_ci * 0 -> off cycle = 2, 708c2ecf20Sopenharmony_ci * 1 -> off cycle = 2, 718c2ecf20Sopenharmony_ci * 2 -> off cycle = 3, 728c2ecf20Sopenharmony_ci * 126 - > off cycle 127, 738c2ecf20Sopenharmony_ci * 127 - > off cycle 1 748c2ecf20Sopenharmony_ci * When on cycle == off cycle the PWM will be always on 758c2ecf20Sopenharmony_ci */ 768c2ecf20Sopenharmony_ci if (duty_cycle == 1) 778c2ecf20Sopenharmony_ci duty_cycle = 2; 788c2ecf20Sopenharmony_ci else if (duty_cycle > TWL4030_LED_MAX) 798c2ecf20Sopenharmony_ci duty_cycle = 1; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci base = pwm->hwpwm * 2 + TWL4030_PWMA_REG; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci pwm_config[1] = duty_cycle; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci ret = twl_i2c_write(TWL4030_MODULE_LED, pwm_config, base, 2); 868c2ecf20Sopenharmony_ci if (ret < 0) 878c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci return ret; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic int twl4030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci struct twl_pwmled_chip *twl = to_twl(chip); 958c2ecf20Sopenharmony_ci int ret; 968c2ecf20Sopenharmony_ci u8 val; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci mutex_lock(&twl->mutex); 998c2ecf20Sopenharmony_ci ret = twl_i2c_read_u8(TWL4030_MODULE_LED, &val, TWL4030_LEDEN_REG); 1008c2ecf20Sopenharmony_ci if (ret < 0) { 1018c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to read LEDEN\n", pwm->label); 1028c2ecf20Sopenharmony_ci goto out; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci val |= TWL4030_LED_TOGGLE(pwm->hwpwm, TWL4030_LED_PINS); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci ret = twl_i2c_write_u8(TWL4030_MODULE_LED, val, TWL4030_LEDEN_REG); 1088c2ecf20Sopenharmony_ci if (ret < 0) 1098c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ciout: 1128c2ecf20Sopenharmony_ci mutex_unlock(&twl->mutex); 1138c2ecf20Sopenharmony_ci return ret; 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic void twl4030_pwmled_disable(struct pwm_chip *chip, 1178c2ecf20Sopenharmony_ci struct pwm_device *pwm) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci struct twl_pwmled_chip *twl = to_twl(chip); 1208c2ecf20Sopenharmony_ci int ret; 1218c2ecf20Sopenharmony_ci u8 val; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci mutex_lock(&twl->mutex); 1248c2ecf20Sopenharmony_ci ret = twl_i2c_read_u8(TWL4030_MODULE_LED, &val, TWL4030_LEDEN_REG); 1258c2ecf20Sopenharmony_ci if (ret < 0) { 1268c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to read LEDEN\n", pwm->label); 1278c2ecf20Sopenharmony_ci goto out; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci val &= ~TWL4030_LED_TOGGLE(pwm->hwpwm, TWL4030_LED_PINS); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci ret = twl_i2c_write_u8(TWL4030_MODULE_LED, val, TWL4030_LEDEN_REG); 1338c2ecf20Sopenharmony_ci if (ret < 0) 1348c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ciout: 1378c2ecf20Sopenharmony_ci mutex_unlock(&twl->mutex); 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic int twl6030_pwmled_config(struct pwm_chip *chip, struct pwm_device *pwm, 1418c2ecf20Sopenharmony_ci int duty_ns, int period_ns) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci int duty_cycle = (duty_ns * TWL6030_LED_MAX) / period_ns; 1448c2ecf20Sopenharmony_ci u8 on_time; 1458c2ecf20Sopenharmony_ci int ret; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci on_time = duty_cycle & 0xff; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, on_time, 1508c2ecf20Sopenharmony_ci TWL6030_LED_PWM_CTRL1); 1518c2ecf20Sopenharmony_ci if (ret < 0) 1528c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to configure PWM\n", pwm->label); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci return ret; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic int twl6030_pwmled_enable(struct pwm_chip *chip, struct pwm_device *pwm) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci struct twl_pwmled_chip *twl = to_twl(chip); 1608c2ecf20Sopenharmony_ci int ret; 1618c2ecf20Sopenharmony_ci u8 val; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci mutex_lock(&twl->mutex); 1648c2ecf20Sopenharmony_ci ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); 1658c2ecf20Sopenharmony_ci if (ret < 0) { 1668c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n", 1678c2ecf20Sopenharmony_ci pwm->label); 1688c2ecf20Sopenharmony_ci goto out; 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci val &= ~TWL6040_LED_MODE_MASK; 1728c2ecf20Sopenharmony_ci val |= TWL6040_LED_MODE_ON; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); 1758c2ecf20Sopenharmony_ci if (ret < 0) 1768c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to enable PWM\n", pwm->label); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ciout: 1798c2ecf20Sopenharmony_ci mutex_unlock(&twl->mutex); 1808c2ecf20Sopenharmony_ci return ret; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic void twl6030_pwmled_disable(struct pwm_chip *chip, 1848c2ecf20Sopenharmony_ci struct pwm_device *pwm) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci struct twl_pwmled_chip *twl = to_twl(chip); 1878c2ecf20Sopenharmony_ci int ret; 1888c2ecf20Sopenharmony_ci u8 val; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci mutex_lock(&twl->mutex); 1918c2ecf20Sopenharmony_ci ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); 1928c2ecf20Sopenharmony_ci if (ret < 0) { 1938c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n", 1948c2ecf20Sopenharmony_ci pwm->label); 1958c2ecf20Sopenharmony_ci goto out; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci val &= ~TWL6040_LED_MODE_MASK; 1998c2ecf20Sopenharmony_ci val |= TWL6040_LED_MODE_OFF; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); 2028c2ecf20Sopenharmony_ci if (ret < 0) 2038c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to disable PWM\n", pwm->label); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ciout: 2068c2ecf20Sopenharmony_ci mutex_unlock(&twl->mutex); 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic int twl6030_pwmled_request(struct pwm_chip *chip, struct pwm_device *pwm) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci struct twl_pwmled_chip *twl = to_twl(chip); 2128c2ecf20Sopenharmony_ci int ret; 2138c2ecf20Sopenharmony_ci u8 val; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci mutex_lock(&twl->mutex); 2168c2ecf20Sopenharmony_ci ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); 2178c2ecf20Sopenharmony_ci if (ret < 0) { 2188c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n", 2198c2ecf20Sopenharmony_ci pwm->label); 2208c2ecf20Sopenharmony_ci goto out; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci val &= ~TWL6040_LED_MODE_MASK; 2248c2ecf20Sopenharmony_ci val |= TWL6040_LED_MODE_OFF; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); 2278c2ecf20Sopenharmony_ci if (ret < 0) 2288c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to request PWM\n", pwm->label); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ciout: 2318c2ecf20Sopenharmony_ci mutex_unlock(&twl->mutex); 2328c2ecf20Sopenharmony_ci return ret; 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic void twl6030_pwmled_free(struct pwm_chip *chip, struct pwm_device *pwm) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci struct twl_pwmled_chip *twl = to_twl(chip); 2388c2ecf20Sopenharmony_ci int ret; 2398c2ecf20Sopenharmony_ci u8 val; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci mutex_lock(&twl->mutex); 2428c2ecf20Sopenharmony_ci ret = twl_i2c_read_u8(TWL6030_MODULE_ID1, &val, TWL6030_LED_PWM_CTRL2); 2438c2ecf20Sopenharmony_ci if (ret < 0) { 2448c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to read PWM_CTRL2\n", 2458c2ecf20Sopenharmony_ci pwm->label); 2468c2ecf20Sopenharmony_ci goto out; 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci val &= ~TWL6040_LED_MODE_MASK; 2508c2ecf20Sopenharmony_ci val |= TWL6040_LED_MODE_HW; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci ret = twl_i2c_write_u8(TWL6030_MODULE_ID1, val, TWL6030_LED_PWM_CTRL2); 2538c2ecf20Sopenharmony_ci if (ret < 0) 2548c2ecf20Sopenharmony_ci dev_err(chip->dev, "%s: Failed to free PWM\n", pwm->label); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ciout: 2578c2ecf20Sopenharmony_ci mutex_unlock(&twl->mutex); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic const struct pwm_ops twl4030_pwmled_ops = { 2618c2ecf20Sopenharmony_ci .enable = twl4030_pwmled_enable, 2628c2ecf20Sopenharmony_ci .disable = twl4030_pwmled_disable, 2638c2ecf20Sopenharmony_ci .config = twl4030_pwmled_config, 2648c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2658c2ecf20Sopenharmony_ci}; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic const struct pwm_ops twl6030_pwmled_ops = { 2688c2ecf20Sopenharmony_ci .enable = twl6030_pwmled_enable, 2698c2ecf20Sopenharmony_ci .disable = twl6030_pwmled_disable, 2708c2ecf20Sopenharmony_ci .config = twl6030_pwmled_config, 2718c2ecf20Sopenharmony_ci .request = twl6030_pwmled_request, 2728c2ecf20Sopenharmony_ci .free = twl6030_pwmled_free, 2738c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2748c2ecf20Sopenharmony_ci}; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistatic int twl_pwmled_probe(struct platform_device *pdev) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci struct twl_pwmled_chip *twl; 2798c2ecf20Sopenharmony_ci int ret; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL); 2828c2ecf20Sopenharmony_ci if (!twl) 2838c2ecf20Sopenharmony_ci return -ENOMEM; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (twl_class_is_4030()) { 2868c2ecf20Sopenharmony_ci twl->chip.ops = &twl4030_pwmled_ops; 2878c2ecf20Sopenharmony_ci twl->chip.npwm = 2; 2888c2ecf20Sopenharmony_ci } else { 2898c2ecf20Sopenharmony_ci twl->chip.ops = &twl6030_pwmled_ops; 2908c2ecf20Sopenharmony_ci twl->chip.npwm = 1; 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci twl->chip.dev = &pdev->dev; 2948c2ecf20Sopenharmony_ci twl->chip.base = -1; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci mutex_init(&twl->mutex); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci ret = pwmchip_add(&twl->chip); 2998c2ecf20Sopenharmony_ci if (ret < 0) 3008c2ecf20Sopenharmony_ci return ret; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, twl); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci return 0; 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic int twl_pwmled_remove(struct platform_device *pdev) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci struct twl_pwmled_chip *twl = platform_get_drvdata(pdev); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci return pwmchip_remove(&twl->chip); 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 3158c2ecf20Sopenharmony_cistatic const struct of_device_id twl_pwmled_of_match[] = { 3168c2ecf20Sopenharmony_ci { .compatible = "ti,twl4030-pwmled" }, 3178c2ecf20Sopenharmony_ci { .compatible = "ti,twl6030-pwmled" }, 3188c2ecf20Sopenharmony_ci { }, 3198c2ecf20Sopenharmony_ci}; 3208c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, twl_pwmled_of_match); 3218c2ecf20Sopenharmony_ci#endif 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic struct platform_driver twl_pwmled_driver = { 3248c2ecf20Sopenharmony_ci .driver = { 3258c2ecf20Sopenharmony_ci .name = "twl-pwmled", 3268c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(twl_pwmled_of_match), 3278c2ecf20Sopenharmony_ci }, 3288c2ecf20Sopenharmony_ci .probe = twl_pwmled_probe, 3298c2ecf20Sopenharmony_ci .remove = twl_pwmled_remove, 3308c2ecf20Sopenharmony_ci}; 3318c2ecf20Sopenharmony_cimodule_platform_driver(twl_pwmled_driver); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ciMODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); 3348c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PWM driver for TWL4030 and TWL6030 LED outputs"); 3358c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:twl-pwmled"); 3368c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 337