18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2016 Linaro Ltd.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Author: Linus Walleij <linus.walleij@linaro.org>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/bitops.h>
98c2ecf20Sopenharmony_ci#include <linux/delay.h>
108c2ecf20Sopenharmony_ci#include <linux/err.h>
118c2ecf20Sopenharmony_ci#include <linux/mfd/stmpe.h>
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/slab.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define STMPE24XX_PWMCS		0x30
198c2ecf20Sopenharmony_ci#define PWMCS_EN_PWM0		BIT(0)
208c2ecf20Sopenharmony_ci#define PWMCS_EN_PWM1		BIT(1)
218c2ecf20Sopenharmony_ci#define PWMCS_EN_PWM2		BIT(2)
228c2ecf20Sopenharmony_ci#define STMPE24XX_PWMIC0	0x38
238c2ecf20Sopenharmony_ci#define STMPE24XX_PWMIC1	0x39
248c2ecf20Sopenharmony_ci#define STMPE24XX_PWMIC2	0x3a
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define STMPE_PWM_24XX_PINBASE	21
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistruct stmpe_pwm {
298c2ecf20Sopenharmony_ci	struct stmpe *stmpe;
308c2ecf20Sopenharmony_ci	struct pwm_chip chip;
318c2ecf20Sopenharmony_ci	u8 last_duty;
328c2ecf20Sopenharmony_ci};
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic inline struct stmpe_pwm *to_stmpe_pwm(struct pwm_chip *chip)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	return container_of(chip, struct stmpe_pwm, chip);
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic int stmpe_24xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip);
428c2ecf20Sopenharmony_ci	u8 value;
438c2ecf20Sopenharmony_ci	int ret;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	ret = stmpe_reg_read(stmpe_pwm->stmpe, STMPE24XX_PWMCS);
468c2ecf20Sopenharmony_ci	if (ret < 0) {
478c2ecf20Sopenharmony_ci		dev_err(chip->dev, "error reading PWM#%u control\n",
488c2ecf20Sopenharmony_ci			pwm->hwpwm);
498c2ecf20Sopenharmony_ci		return ret;
508c2ecf20Sopenharmony_ci	}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	value = ret | BIT(pwm->hwpwm);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	ret = stmpe_reg_write(stmpe_pwm->stmpe, STMPE24XX_PWMCS, value);
558c2ecf20Sopenharmony_ci	if (ret) {
568c2ecf20Sopenharmony_ci		dev_err(chip->dev, "error writing PWM#%u control\n",
578c2ecf20Sopenharmony_ci			pwm->hwpwm);
588c2ecf20Sopenharmony_ci		return ret;
598c2ecf20Sopenharmony_ci	}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	return 0;
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistatic void stmpe_24xx_pwm_disable(struct pwm_chip *chip,
658c2ecf20Sopenharmony_ci				   struct pwm_device *pwm)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip);
688c2ecf20Sopenharmony_ci	u8 value;
698c2ecf20Sopenharmony_ci	int ret;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	ret = stmpe_reg_read(stmpe_pwm->stmpe, STMPE24XX_PWMCS);
728c2ecf20Sopenharmony_ci	if (ret < 0) {
738c2ecf20Sopenharmony_ci		dev_err(chip->dev, "error reading PWM#%u control\n",
748c2ecf20Sopenharmony_ci			pwm->hwpwm);
758c2ecf20Sopenharmony_ci		return;
768c2ecf20Sopenharmony_ci	}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	value = ret & ~BIT(pwm->hwpwm);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	ret = stmpe_reg_write(stmpe_pwm->stmpe, STMPE24XX_PWMCS, value);
818c2ecf20Sopenharmony_ci	if (ret) {
828c2ecf20Sopenharmony_ci		dev_err(chip->dev, "error writing PWM#%u control\n",
838c2ecf20Sopenharmony_ci			pwm->hwpwm);
848c2ecf20Sopenharmony_ci		return;
858c2ecf20Sopenharmony_ci	}
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/* STMPE 24xx PWM instructions */
898c2ecf20Sopenharmony_ci#define SMAX		0x007f
908c2ecf20Sopenharmony_ci#define SMIN		0x00ff
918c2ecf20Sopenharmony_ci#define GTS		0x0000
928c2ecf20Sopenharmony_ci#define LOAD		BIT(14) /* Only available on 2403 */
938c2ecf20Sopenharmony_ci#define RAMPUP		0x0000
948c2ecf20Sopenharmony_ci#define RAMPDOWN	BIT(7)
958c2ecf20Sopenharmony_ci#define PRESCALE_512	BIT(14)
968c2ecf20Sopenharmony_ci#define STEPTIME_1	BIT(8)
978c2ecf20Sopenharmony_ci#define BRANCH		(BIT(15) | BIT(13))
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic int stmpe_24xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
1008c2ecf20Sopenharmony_ci				 int duty_ns, int period_ns)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip);
1038c2ecf20Sopenharmony_ci	unsigned int i, pin;
1048c2ecf20Sopenharmony_ci	u16 program[3] = {
1058c2ecf20Sopenharmony_ci		SMAX,
1068c2ecf20Sopenharmony_ci		GTS,
1078c2ecf20Sopenharmony_ci		GTS,
1088c2ecf20Sopenharmony_ci	};
1098c2ecf20Sopenharmony_ci	u8 offset;
1108c2ecf20Sopenharmony_ci	int ret;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	/* Make sure we are disabled */
1138c2ecf20Sopenharmony_ci	if (pwm_is_enabled(pwm)) {
1148c2ecf20Sopenharmony_ci		stmpe_24xx_pwm_disable(chip, pwm);
1158c2ecf20Sopenharmony_ci	} else {
1168c2ecf20Sopenharmony_ci		/* Connect the PWM to the pin */
1178c2ecf20Sopenharmony_ci		pin = pwm->hwpwm;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci		/* On STMPE2401 and 2403 pins 21,22,23 are used */
1208c2ecf20Sopenharmony_ci		if (stmpe_pwm->stmpe->partnum == STMPE2401 ||
1218c2ecf20Sopenharmony_ci		    stmpe_pwm->stmpe->partnum == STMPE2403)
1228c2ecf20Sopenharmony_ci			pin += STMPE_PWM_24XX_PINBASE;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci		ret = stmpe_set_altfunc(stmpe_pwm->stmpe, BIT(pin),
1258c2ecf20Sopenharmony_ci					STMPE_BLOCK_PWM);
1268c2ecf20Sopenharmony_ci		if (ret) {
1278c2ecf20Sopenharmony_ci			dev_err(chip->dev, "unable to connect PWM#%u to pin\n",
1288c2ecf20Sopenharmony_ci				pwm->hwpwm);
1298c2ecf20Sopenharmony_ci			return ret;
1308c2ecf20Sopenharmony_ci		}
1318c2ecf20Sopenharmony_ci	}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	/* STMPE24XX */
1348c2ecf20Sopenharmony_ci	switch (pwm->hwpwm) {
1358c2ecf20Sopenharmony_ci	case 0:
1368c2ecf20Sopenharmony_ci		offset = STMPE24XX_PWMIC0;
1378c2ecf20Sopenharmony_ci		break;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	case 1:
1408c2ecf20Sopenharmony_ci		offset = STMPE24XX_PWMIC1;
1418c2ecf20Sopenharmony_ci		break;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	case 2:
1448c2ecf20Sopenharmony_ci		offset = STMPE24XX_PWMIC2;
1458c2ecf20Sopenharmony_ci		break;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	default:
1488c2ecf20Sopenharmony_ci		/* Should not happen as npwm is 3 */
1498c2ecf20Sopenharmony_ci		return -ENODEV;
1508c2ecf20Sopenharmony_ci	}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	dev_dbg(chip->dev, "PWM#%u: config duty %d ns, period %d ns\n",
1538c2ecf20Sopenharmony_ci		pwm->hwpwm, duty_ns, period_ns);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	if (duty_ns == 0) {
1568c2ecf20Sopenharmony_ci		if (stmpe_pwm->stmpe->partnum == STMPE2401)
1578c2ecf20Sopenharmony_ci			program[0] = SMAX; /* off all the time */
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci		if (stmpe_pwm->stmpe->partnum == STMPE2403)
1608c2ecf20Sopenharmony_ci			program[0] = LOAD | 0xff; /* LOAD 0xff */
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci		stmpe_pwm->last_duty = 0x00;
1638c2ecf20Sopenharmony_ci	} else if (duty_ns == period_ns) {
1648c2ecf20Sopenharmony_ci		if (stmpe_pwm->stmpe->partnum == STMPE2401)
1658c2ecf20Sopenharmony_ci			program[0] = SMIN; /* on all the time */
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci		if (stmpe_pwm->stmpe->partnum == STMPE2403)
1688c2ecf20Sopenharmony_ci			program[0] = LOAD | 0x00; /* LOAD 0x00 */
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci		stmpe_pwm->last_duty = 0xff;
1718c2ecf20Sopenharmony_ci	} else {
1728c2ecf20Sopenharmony_ci		u8 value, last = stmpe_pwm->last_duty;
1738c2ecf20Sopenharmony_ci		unsigned long duty;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		/*
1768c2ecf20Sopenharmony_ci		 * Counter goes from 0x00 to 0xff repeatedly at 32768 Hz,
1778c2ecf20Sopenharmony_ci		 * (means a period of 30517 ns) then this is compared to the
1788c2ecf20Sopenharmony_ci		 * counter from the ramp, if this is >= PWM counter the output
1798c2ecf20Sopenharmony_ci		 * is high. With LOAD we can define how much of the cycle it
1808c2ecf20Sopenharmony_ci		 * is on.
1818c2ecf20Sopenharmony_ci		 *
1828c2ecf20Sopenharmony_ci		 * Prescale = 0 -> 2 kHz -> T = 1/f = 488281.25 ns
1838c2ecf20Sopenharmony_ci		 */
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci		/* Scale to 0..0xff */
1868c2ecf20Sopenharmony_ci		duty = duty_ns * 256;
1878c2ecf20Sopenharmony_ci		duty = DIV_ROUND_CLOSEST(duty, period_ns);
1888c2ecf20Sopenharmony_ci		value = duty;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci		if (value == last) {
1918c2ecf20Sopenharmony_ci			/* Run the old program */
1928c2ecf20Sopenharmony_ci			if (pwm_is_enabled(pwm))
1938c2ecf20Sopenharmony_ci				stmpe_24xx_pwm_enable(chip, pwm);
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci			return 0;
1968c2ecf20Sopenharmony_ci		} else if (stmpe_pwm->stmpe->partnum == STMPE2403) {
1978c2ecf20Sopenharmony_ci			/* STMPE2403 can simply set the right PWM value */
1988c2ecf20Sopenharmony_ci			program[0] = LOAD | value;
1998c2ecf20Sopenharmony_ci			program[1] = 0x0000;
2008c2ecf20Sopenharmony_ci		} else if (stmpe_pwm->stmpe->partnum == STMPE2401) {
2018c2ecf20Sopenharmony_ci			/* STMPE2401 need a complex program */
2028c2ecf20Sopenharmony_ci			u16 incdec = 0x0000;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci			if (last < value)
2058c2ecf20Sopenharmony_ci				/* Count up */
2068c2ecf20Sopenharmony_ci				incdec = RAMPUP | (value - last);
2078c2ecf20Sopenharmony_ci			else
2088c2ecf20Sopenharmony_ci				/* Count down */
2098c2ecf20Sopenharmony_ci				incdec = RAMPDOWN | (last - value);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci			/* Step to desired value, smoothly */
2128c2ecf20Sopenharmony_ci			program[0] = PRESCALE_512 | STEPTIME_1 | incdec;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci			/* Loop eternally to 0x00 */
2158c2ecf20Sopenharmony_ci			program[1] = BRANCH;
2168c2ecf20Sopenharmony_ci		}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci		dev_dbg(chip->dev,
2198c2ecf20Sopenharmony_ci			"PWM#%u: value = %02x, last_duty = %02x, program=%04x,%04x,%04x\n",
2208c2ecf20Sopenharmony_ci			pwm->hwpwm, value, last, program[0], program[1],
2218c2ecf20Sopenharmony_ci			program[2]);
2228c2ecf20Sopenharmony_ci		stmpe_pwm->last_duty = value;
2238c2ecf20Sopenharmony_ci	}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	/*
2268c2ecf20Sopenharmony_ci	 * We can write programs of up to 64 16-bit words into this channel.
2278c2ecf20Sopenharmony_ci	 */
2288c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(program); i++) {
2298c2ecf20Sopenharmony_ci		u8 value;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci		value = (program[i] >> 8) & 0xff;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci		ret = stmpe_reg_write(stmpe_pwm->stmpe, offset, value);
2348c2ecf20Sopenharmony_ci		if (ret) {
2358c2ecf20Sopenharmony_ci			dev_err(chip->dev, "error writing register %02x: %d\n",
2368c2ecf20Sopenharmony_ci				offset, ret);
2378c2ecf20Sopenharmony_ci			return ret;
2388c2ecf20Sopenharmony_ci		}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci		value = program[i] & 0xff;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci		ret = stmpe_reg_write(stmpe_pwm->stmpe, offset, value);
2438c2ecf20Sopenharmony_ci		if (ret) {
2448c2ecf20Sopenharmony_ci			dev_err(chip->dev, "error writing register %02x: %d\n",
2458c2ecf20Sopenharmony_ci				offset, ret);
2468c2ecf20Sopenharmony_ci			return ret;
2478c2ecf20Sopenharmony_ci		}
2488c2ecf20Sopenharmony_ci	}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	/* If we were enabled, re-enable this PWM */
2518c2ecf20Sopenharmony_ci	if (pwm_is_enabled(pwm))
2528c2ecf20Sopenharmony_ci		stmpe_24xx_pwm_enable(chip, pwm);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	/* Sleep for 200ms so we're sure it will take effect */
2558c2ecf20Sopenharmony_ci	msleep(200);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	dev_dbg(chip->dev, "programmed PWM#%u, %u bytes\n", pwm->hwpwm, i);
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	return 0;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_cistatic const struct pwm_ops stmpe_24xx_pwm_ops = {
2638c2ecf20Sopenharmony_ci	.config = stmpe_24xx_pwm_config,
2648c2ecf20Sopenharmony_ci	.enable = stmpe_24xx_pwm_enable,
2658c2ecf20Sopenharmony_ci	.disable = stmpe_24xx_pwm_disable,
2668c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
2678c2ecf20Sopenharmony_ci};
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistatic int __init stmpe_pwm_probe(struct platform_device *pdev)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
2728c2ecf20Sopenharmony_ci	struct stmpe_pwm *pwm;
2738c2ecf20Sopenharmony_ci	int ret;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
2768c2ecf20Sopenharmony_ci	if (!pwm)
2778c2ecf20Sopenharmony_ci		return -ENOMEM;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	pwm->stmpe = stmpe;
2808c2ecf20Sopenharmony_ci	pwm->chip.dev = &pdev->dev;
2818c2ecf20Sopenharmony_ci	pwm->chip.base = -1;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	if (stmpe->partnum == STMPE2401 || stmpe->partnum == STMPE2403) {
2848c2ecf20Sopenharmony_ci		pwm->chip.ops = &stmpe_24xx_pwm_ops;
2858c2ecf20Sopenharmony_ci		pwm->chip.npwm = 3;
2868c2ecf20Sopenharmony_ci	} else {
2878c2ecf20Sopenharmony_ci		if (stmpe->partnum == STMPE1601)
2888c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "STMPE1601 not yet supported\n");
2898c2ecf20Sopenharmony_ci		else
2908c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Unknown STMPE PWM\n");
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci		return -ENODEV;
2938c2ecf20Sopenharmony_ci	}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	ret = stmpe_enable(stmpe, STMPE_BLOCK_PWM);
2968c2ecf20Sopenharmony_ci	if (ret)
2978c2ecf20Sopenharmony_ci		return ret;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	ret = pwmchip_add(&pwm->chip);
3008c2ecf20Sopenharmony_ci	if (ret) {
3018c2ecf20Sopenharmony_ci		stmpe_disable(stmpe, STMPE_BLOCK_PWM);
3028c2ecf20Sopenharmony_ci		return ret;
3038c2ecf20Sopenharmony_ci	}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, pwm);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	return 0;
3088c2ecf20Sopenharmony_ci}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_cistatic struct platform_driver stmpe_pwm_driver = {
3118c2ecf20Sopenharmony_ci	.driver = {
3128c2ecf20Sopenharmony_ci		.name = "stmpe-pwm",
3138c2ecf20Sopenharmony_ci	},
3148c2ecf20Sopenharmony_ci};
3158c2ecf20Sopenharmony_cibuiltin_platform_driver_probe(stmpe_pwm_driver, stmpe_pwm_probe);
316