18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * TI/National Semiconductor LP3943 PWM driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2013 Texas Instruments 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Milo Kim <milo.kim@ti.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/err.h> 118c2ecf20Sopenharmony_ci#include <linux/i2c.h> 128c2ecf20Sopenharmony_ci#include <linux/mfd/lp3943.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 158c2ecf20Sopenharmony_ci#include <linux/pwm.h> 168c2ecf20Sopenharmony_ci#include <linux/slab.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define LP3943_MAX_DUTY 255 198c2ecf20Sopenharmony_ci#define LP3943_MIN_PERIOD 6250 208c2ecf20Sopenharmony_ci#define LP3943_MAX_PERIOD 1600000 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistruct lp3943_pwm { 238c2ecf20Sopenharmony_ci struct pwm_chip chip; 248c2ecf20Sopenharmony_ci struct lp3943 *lp3943; 258c2ecf20Sopenharmony_ci struct lp3943_platform_data *pdata; 268c2ecf20Sopenharmony_ci}; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic inline struct lp3943_pwm *to_lp3943_pwm(struct pwm_chip *_chip) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci return container_of(_chip, struct lp3943_pwm, chip); 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic struct lp3943_pwm_map * 348c2ecf20Sopenharmony_cilp3943_pwm_request_map(struct lp3943_pwm *lp3943_pwm, int hwpwm) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci struct lp3943_platform_data *pdata = lp3943_pwm->pdata; 378c2ecf20Sopenharmony_ci struct lp3943 *lp3943 = lp3943_pwm->lp3943; 388c2ecf20Sopenharmony_ci struct lp3943_pwm_map *pwm_map; 398c2ecf20Sopenharmony_ci int i, offset; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci pwm_map = kzalloc(sizeof(*pwm_map), GFP_KERNEL); 428c2ecf20Sopenharmony_ci if (!pwm_map) 438c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci pwm_map->output = pdata->pwms[hwpwm]->output; 468c2ecf20Sopenharmony_ci pwm_map->num_outputs = pdata->pwms[hwpwm]->num_outputs; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci for (i = 0; i < pwm_map->num_outputs; i++) { 498c2ecf20Sopenharmony_ci offset = pwm_map->output[i]; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* Return an error if the pin is already assigned */ 528c2ecf20Sopenharmony_ci if (test_and_set_bit(offset, &lp3943->pin_used)) { 538c2ecf20Sopenharmony_ci kfree(pwm_map); 548c2ecf20Sopenharmony_ci return ERR_PTR(-EBUSY); 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return pwm_map; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic int lp3943_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip); 648c2ecf20Sopenharmony_ci struct lp3943_pwm_map *pwm_map; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci pwm_map = lp3943_pwm_request_map(lp3943_pwm, pwm->hwpwm); 678c2ecf20Sopenharmony_ci if (IS_ERR(pwm_map)) 688c2ecf20Sopenharmony_ci return PTR_ERR(pwm_map); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci return pwm_set_chip_data(pwm, pwm_map); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic void lp3943_pwm_free_map(struct lp3943_pwm *lp3943_pwm, 748c2ecf20Sopenharmony_ci struct lp3943_pwm_map *pwm_map) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci struct lp3943 *lp3943 = lp3943_pwm->lp3943; 778c2ecf20Sopenharmony_ci int i, offset; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci for (i = 0; i < pwm_map->num_outputs; i++) { 808c2ecf20Sopenharmony_ci offset = pwm_map->output[i]; 818c2ecf20Sopenharmony_ci clear_bit(offset, &lp3943->pin_used); 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci kfree(pwm_map); 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic void lp3943_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip); 908c2ecf20Sopenharmony_ci struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci lp3943_pwm_free_map(lp3943_pwm, pwm_map); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int lp3943_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 968c2ecf20Sopenharmony_ci int duty_ns, int period_ns) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip); 998c2ecf20Sopenharmony_ci struct lp3943 *lp3943 = lp3943_pwm->lp3943; 1008c2ecf20Sopenharmony_ci u8 val, reg_duty, reg_prescale; 1018c2ecf20Sopenharmony_ci int err; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci /* 1048c2ecf20Sopenharmony_ci * How to configure the LP3943 PWMs 1058c2ecf20Sopenharmony_ci * 1068c2ecf20Sopenharmony_ci * 1) Period = 6250 ~ 1600000 1078c2ecf20Sopenharmony_ci * 2) Prescale = period / 6250 -1 1088c2ecf20Sopenharmony_ci * 3) Duty = input duty 1098c2ecf20Sopenharmony_ci * 1108c2ecf20Sopenharmony_ci * Prescale and duty are register values 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci if (pwm->hwpwm == 0) { 1148c2ecf20Sopenharmony_ci reg_prescale = LP3943_REG_PRESCALE0; 1158c2ecf20Sopenharmony_ci reg_duty = LP3943_REG_PWM0; 1168c2ecf20Sopenharmony_ci } else { 1178c2ecf20Sopenharmony_ci reg_prescale = LP3943_REG_PRESCALE1; 1188c2ecf20Sopenharmony_ci reg_duty = LP3943_REG_PWM1; 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci period_ns = clamp(period_ns, LP3943_MIN_PERIOD, LP3943_MAX_PERIOD); 1228c2ecf20Sopenharmony_ci val = (u8)(period_ns / LP3943_MIN_PERIOD - 1); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci err = lp3943_write_byte(lp3943, reg_prescale, val); 1258c2ecf20Sopenharmony_ci if (err) 1268c2ecf20Sopenharmony_ci return err; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci duty_ns = min(duty_ns, period_ns); 1298c2ecf20Sopenharmony_ci val = (u8)(duty_ns * LP3943_MAX_DUTY / period_ns); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci return lp3943_write_byte(lp3943, reg_duty, val); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic int lp3943_pwm_set_mode(struct lp3943_pwm *lp3943_pwm, 1358c2ecf20Sopenharmony_ci struct lp3943_pwm_map *pwm_map, 1368c2ecf20Sopenharmony_ci u8 val) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci struct lp3943 *lp3943 = lp3943_pwm->lp3943; 1398c2ecf20Sopenharmony_ci const struct lp3943_reg_cfg *mux = lp3943->mux_cfg; 1408c2ecf20Sopenharmony_ci int i, index, err; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci for (i = 0; i < pwm_map->num_outputs; i++) { 1438c2ecf20Sopenharmony_ci index = pwm_map->output[i]; 1448c2ecf20Sopenharmony_ci err = lp3943_update_bits(lp3943, mux[index].reg, 1458c2ecf20Sopenharmony_ci mux[index].mask, 1468c2ecf20Sopenharmony_ci val << mux[index].shift); 1478c2ecf20Sopenharmony_ci if (err) 1488c2ecf20Sopenharmony_ci return err; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci return 0; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic int lp3943_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip); 1578c2ecf20Sopenharmony_ci struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm); 1588c2ecf20Sopenharmony_ci u8 val; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (pwm->hwpwm == 0) 1618c2ecf20Sopenharmony_ci val = LP3943_DIM_PWM0; 1628c2ecf20Sopenharmony_ci else 1638c2ecf20Sopenharmony_ci val = LP3943_DIM_PWM1; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* 1668c2ecf20Sopenharmony_ci * Each PWM generator is set to control any of outputs of LP3943. 1678c2ecf20Sopenharmony_ci * To enable/disable the PWM, these output pins should be configured. 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci return lp3943_pwm_set_mode(lp3943_pwm, pwm_map, val); 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic void lp3943_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip); 1768c2ecf20Sopenharmony_ci struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /* 1798c2ecf20Sopenharmony_ci * LP3943 outputs are open-drain, so the pin should be configured 1808c2ecf20Sopenharmony_ci * when the PWM is disabled. 1818c2ecf20Sopenharmony_ci */ 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci lp3943_pwm_set_mode(lp3943_pwm, pwm_map, LP3943_GPIO_OUT_HIGH); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic const struct pwm_ops lp3943_pwm_ops = { 1878c2ecf20Sopenharmony_ci .request = lp3943_pwm_request, 1888c2ecf20Sopenharmony_ci .free = lp3943_pwm_free, 1898c2ecf20Sopenharmony_ci .config = lp3943_pwm_config, 1908c2ecf20Sopenharmony_ci .enable = lp3943_pwm_enable, 1918c2ecf20Sopenharmony_ci .disable = lp3943_pwm_disable, 1928c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 1938c2ecf20Sopenharmony_ci}; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cistatic int lp3943_pwm_parse_dt(struct device *dev, 1968c2ecf20Sopenharmony_ci struct lp3943_pwm *lp3943_pwm) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci static const char * const name[] = { "ti,pwm0", "ti,pwm1", }; 1998c2ecf20Sopenharmony_ci struct device_node *node = dev->of_node; 2008c2ecf20Sopenharmony_ci struct lp3943_platform_data *pdata; 2018c2ecf20Sopenharmony_ci struct lp3943_pwm_map *pwm_map; 2028c2ecf20Sopenharmony_ci enum lp3943_pwm_output *output; 2038c2ecf20Sopenharmony_ci int i, err, proplen, count = 0; 2048c2ecf20Sopenharmony_ci u32 num_outputs; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (!node) 2078c2ecf20Sopenharmony_ci return -EINVAL; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 2108c2ecf20Sopenharmony_ci if (!pdata) 2118c2ecf20Sopenharmony_ci return -ENOMEM; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci /* 2148c2ecf20Sopenharmony_ci * Read the output map configuration from the device tree. 2158c2ecf20Sopenharmony_ci * Each of the two PWM generators can drive zero or more outputs. 2168c2ecf20Sopenharmony_ci */ 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci for (i = 0; i < LP3943_NUM_PWMS; i++) { 2198c2ecf20Sopenharmony_ci if (!of_get_property(node, name[i], &proplen)) 2208c2ecf20Sopenharmony_ci continue; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci num_outputs = proplen / sizeof(u32); 2238c2ecf20Sopenharmony_ci if (num_outputs == 0) 2248c2ecf20Sopenharmony_ci continue; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci output = devm_kcalloc(dev, num_outputs, sizeof(*output), 2278c2ecf20Sopenharmony_ci GFP_KERNEL); 2288c2ecf20Sopenharmony_ci if (!output) 2298c2ecf20Sopenharmony_ci return -ENOMEM; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci err = of_property_read_u32_array(node, name[i], output, 2328c2ecf20Sopenharmony_ci num_outputs); 2338c2ecf20Sopenharmony_ci if (err) 2348c2ecf20Sopenharmony_ci return err; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci pwm_map = devm_kzalloc(dev, sizeof(*pwm_map), GFP_KERNEL); 2378c2ecf20Sopenharmony_ci if (!pwm_map) 2388c2ecf20Sopenharmony_ci return -ENOMEM; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci pwm_map->output = output; 2418c2ecf20Sopenharmony_ci pwm_map->num_outputs = num_outputs; 2428c2ecf20Sopenharmony_ci pdata->pwms[i] = pwm_map; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci count++; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (count == 0) 2488c2ecf20Sopenharmony_ci return -ENODATA; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci lp3943_pwm->pdata = pdata; 2518c2ecf20Sopenharmony_ci return 0; 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic int lp3943_pwm_probe(struct platform_device *pdev) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent); 2578c2ecf20Sopenharmony_ci struct lp3943_pwm *lp3943_pwm; 2588c2ecf20Sopenharmony_ci int ret; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci lp3943_pwm = devm_kzalloc(&pdev->dev, sizeof(*lp3943_pwm), GFP_KERNEL); 2618c2ecf20Sopenharmony_ci if (!lp3943_pwm) 2628c2ecf20Sopenharmony_ci return -ENOMEM; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci lp3943_pwm->pdata = lp3943->pdata; 2658c2ecf20Sopenharmony_ci if (!lp3943_pwm->pdata) { 2668c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_OF)) 2678c2ecf20Sopenharmony_ci ret = lp3943_pwm_parse_dt(&pdev->dev, lp3943_pwm); 2688c2ecf20Sopenharmony_ci else 2698c2ecf20Sopenharmony_ci ret = -ENODEV; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci if (ret) 2728c2ecf20Sopenharmony_ci return ret; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci lp3943_pwm->lp3943 = lp3943; 2768c2ecf20Sopenharmony_ci lp3943_pwm->chip.dev = &pdev->dev; 2778c2ecf20Sopenharmony_ci lp3943_pwm->chip.ops = &lp3943_pwm_ops; 2788c2ecf20Sopenharmony_ci lp3943_pwm->chip.npwm = LP3943_NUM_PWMS; 2798c2ecf20Sopenharmony_ci lp3943_pwm->chip.base = -1; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, lp3943_pwm); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci return pwmchip_add(&lp3943_pwm->chip); 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic int lp3943_pwm_remove(struct platform_device *pdev) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci struct lp3943_pwm *lp3943_pwm = platform_get_drvdata(pdev); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci return pwmchip_remove(&lp3943_pwm->chip); 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 2948c2ecf20Sopenharmony_cistatic const struct of_device_id lp3943_pwm_of_match[] = { 2958c2ecf20Sopenharmony_ci { .compatible = "ti,lp3943-pwm", }, 2968c2ecf20Sopenharmony_ci { } 2978c2ecf20Sopenharmony_ci}; 2988c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, lp3943_pwm_of_match); 2998c2ecf20Sopenharmony_ci#endif 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic struct platform_driver lp3943_pwm_driver = { 3028c2ecf20Sopenharmony_ci .probe = lp3943_pwm_probe, 3038c2ecf20Sopenharmony_ci .remove = lp3943_pwm_remove, 3048c2ecf20Sopenharmony_ci .driver = { 3058c2ecf20Sopenharmony_ci .name = "lp3943-pwm", 3068c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(lp3943_pwm_of_match), 3078c2ecf20Sopenharmony_ci }, 3088c2ecf20Sopenharmony_ci}; 3098c2ecf20Sopenharmony_cimodule_platform_driver(lp3943_pwm_driver); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("LP3943 PWM driver"); 3128c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:lp3943-pwm"); 3138c2ecf20Sopenharmony_ciMODULE_AUTHOR("Milo Kim"); 3148c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 315