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