// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2016 Linaro Ltd.
 *
 * Author: Linus Walleij <linus.walleij@linaro.org>
 */

#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/mfd/stmpe.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/slab.h>

#define STMPE24XX_PWMCS		0x30
#define PWMCS_EN_PWM0		BIT(0)
#define PWMCS_EN_PWM1		BIT(1)
#define PWMCS_EN_PWM2		BIT(2)
#define STMPE24XX_PWMIC0	0x38
#define STMPE24XX_PWMIC1	0x39
#define STMPE24XX_PWMIC2	0x3a

#define STMPE_PWM_24XX_PINBASE	21

struct stmpe_pwm {
	struct stmpe *stmpe;
	struct pwm_chip chip;
	u8 last_duty;
};

static inline struct stmpe_pwm *to_stmpe_pwm(struct pwm_chip *chip)
{
	return container_of(chip, struct stmpe_pwm, chip);
}

static int stmpe_24xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
{
	struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip);
	u8 value;
	int ret;

	ret = stmpe_reg_read(stmpe_pwm->stmpe, STMPE24XX_PWMCS);
	if (ret < 0) {
		dev_err(chip->dev, "error reading PWM#%u control\n",
			pwm->hwpwm);
		return ret;
	}

	value = ret | BIT(pwm->hwpwm);

	ret = stmpe_reg_write(stmpe_pwm->stmpe, STMPE24XX_PWMCS, value);
	if (ret) {
		dev_err(chip->dev, "error writing PWM#%u control\n",
			pwm->hwpwm);
		return ret;
	}

	return 0;
}

static void stmpe_24xx_pwm_disable(struct pwm_chip *chip,
				   struct pwm_device *pwm)
{
	struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip);
	u8 value;
	int ret;

	ret = stmpe_reg_read(stmpe_pwm->stmpe, STMPE24XX_PWMCS);
	if (ret < 0) {
		dev_err(chip->dev, "error reading PWM#%u control\n",
			pwm->hwpwm);
		return;
	}

	value = ret & ~BIT(pwm->hwpwm);

	ret = stmpe_reg_write(stmpe_pwm->stmpe, STMPE24XX_PWMCS, value);
	if (ret) {
		dev_err(chip->dev, "error writing PWM#%u control\n",
			pwm->hwpwm);
		return;
	}
}

/* STMPE 24xx PWM instructions */
#define SMAX		0x007f
#define SMIN		0x00ff
#define GTS		0x0000
#define LOAD		BIT(14) /* Only available on 2403 */
#define RAMPUP		0x0000
#define RAMPDOWN	BIT(7)
#define PRESCALE_512	BIT(14)
#define STEPTIME_1	BIT(8)
#define BRANCH		(BIT(15) | BIT(13))

static int stmpe_24xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
				 int duty_ns, int period_ns)
{
	struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip);
	unsigned int i, pin;
	u16 program[3] = {
		SMAX,
		GTS,
		GTS,
	};
	u8 offset;
	int ret;

	/* Make sure we are disabled */
	if (pwm_is_enabled(pwm)) {
		stmpe_24xx_pwm_disable(chip, pwm);
	} else {
		/* Connect the PWM to the pin */
		pin = pwm->hwpwm;

		/* On STMPE2401 and 2403 pins 21,22,23 are used */
		if (stmpe_pwm->stmpe->partnum == STMPE2401 ||
		    stmpe_pwm->stmpe->partnum == STMPE2403)
			pin += STMPE_PWM_24XX_PINBASE;

		ret = stmpe_set_altfunc(stmpe_pwm->stmpe, BIT(pin),
					STMPE_BLOCK_PWM);
		if (ret) {
			dev_err(chip->dev, "unable to connect PWM#%u to pin\n",
				pwm->hwpwm);
			return ret;
		}
	}

	/* STMPE24XX */
	switch (pwm->hwpwm) {
	case 0:
		offset = STMPE24XX_PWMIC0;
		break;

	case 1:
		offset = STMPE24XX_PWMIC1;
		break;

	case 2:
		offset = STMPE24XX_PWMIC2;
		break;

	default:
		/* Should not happen as npwm is 3 */
		return -ENODEV;
	}

	dev_dbg(chip->dev, "PWM#%u: config duty %d ns, period %d ns\n",
		pwm->hwpwm, duty_ns, period_ns);

	if (duty_ns == 0) {
		if (stmpe_pwm->stmpe->partnum == STMPE2401)
			program[0] = SMAX; /* off all the time */

		if (stmpe_pwm->stmpe->partnum == STMPE2403)
			program[0] = LOAD | 0xff; /* LOAD 0xff */

		stmpe_pwm->last_duty = 0x00;
	} else if (duty_ns == period_ns) {
		if (stmpe_pwm->stmpe->partnum == STMPE2401)
			program[0] = SMIN; /* on all the time */

		if (stmpe_pwm->stmpe->partnum == STMPE2403)
			program[0] = LOAD | 0x00; /* LOAD 0x00 */

		stmpe_pwm->last_duty = 0xff;
	} else {
		u8 value, last = stmpe_pwm->last_duty;
		unsigned long duty;

		/*
		 * Counter goes from 0x00 to 0xff repeatedly at 32768 Hz,
		 * (means a period of 30517 ns) then this is compared to the
		 * counter from the ramp, if this is >= PWM counter the output
		 * is high. With LOAD we can define how much of the cycle it
		 * is on.
		 *
		 * Prescale = 0 -> 2 kHz -> T = 1/f = 488281.25 ns
		 */

		/* Scale to 0..0xff */
		duty = duty_ns * 256;
		duty = DIV_ROUND_CLOSEST(duty, period_ns);
		value = duty;

		if (value == last) {
			/* Run the old program */
			if (pwm_is_enabled(pwm))
				stmpe_24xx_pwm_enable(chip, pwm);

			return 0;
		} else if (stmpe_pwm->stmpe->partnum == STMPE2403) {
			/* STMPE2403 can simply set the right PWM value */
			program[0] = LOAD | value;
			program[1] = 0x0000;
		} else if (stmpe_pwm->stmpe->partnum == STMPE2401) {
			/* STMPE2401 need a complex program */
			u16 incdec = 0x0000;

			if (last < value)
				/* Count up */
				incdec = RAMPUP | (value - last);
			else
				/* Count down */
				incdec = RAMPDOWN | (last - value);

			/* Step to desired value, smoothly */
			program[0] = PRESCALE_512 | STEPTIME_1 | incdec;

			/* Loop eternally to 0x00 */
			program[1] = BRANCH;
		}

		dev_dbg(chip->dev,
			"PWM#%u: value = %02x, last_duty = %02x, program=%04x,%04x,%04x\n",
			pwm->hwpwm, value, last, program[0], program[1],
			program[2]);
		stmpe_pwm->last_duty = value;
	}

	/*
	 * We can write programs of up to 64 16-bit words into this channel.
	 */
	for (i = 0; i < ARRAY_SIZE(program); i++) {
		u8 value;

		value = (program[i] >> 8) & 0xff;

		ret = stmpe_reg_write(stmpe_pwm->stmpe, offset, value);
		if (ret) {
			dev_err(chip->dev, "error writing register %02x: %d\n",
				offset, ret);
			return ret;
		}

		value = program[i] & 0xff;

		ret = stmpe_reg_write(stmpe_pwm->stmpe, offset, value);
		if (ret) {
			dev_err(chip->dev, "error writing register %02x: %d\n",
				offset, ret);
			return ret;
		}
	}

	/* If we were enabled, re-enable this PWM */
	if (pwm_is_enabled(pwm))
		stmpe_24xx_pwm_enable(chip, pwm);

	/* Sleep for 200ms so we're sure it will take effect */
	msleep(200);

	dev_dbg(chip->dev, "programmed PWM#%u, %u bytes\n", pwm->hwpwm, i);

	return 0;
}

static const struct pwm_ops stmpe_24xx_pwm_ops = {
	.config = stmpe_24xx_pwm_config,
	.enable = stmpe_24xx_pwm_enable,
	.disable = stmpe_24xx_pwm_disable,
	.owner = THIS_MODULE,
};

static int __init stmpe_pwm_probe(struct platform_device *pdev)
{
	struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
	struct stmpe_pwm *pwm;
	int ret;

	pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
	if (!pwm)
		return -ENOMEM;

	pwm->stmpe = stmpe;
	pwm->chip.dev = &pdev->dev;

	if (stmpe->partnum == STMPE2401 || stmpe->partnum == STMPE2403) {
		pwm->chip.ops = &stmpe_24xx_pwm_ops;
		pwm->chip.npwm = 3;
	} else {
		if (stmpe->partnum == STMPE1601)
			dev_err(&pdev->dev, "STMPE1601 not yet supported\n");
		else
			dev_err(&pdev->dev, "Unknown STMPE PWM\n");

		return -ENODEV;
	}

	ret = stmpe_enable(stmpe, STMPE_BLOCK_PWM);
	if (ret)
		return ret;

	ret = pwmchip_add(&pwm->chip);
	if (ret) {
		stmpe_disable(stmpe, STMPE_BLOCK_PWM);
		return ret;
	}

	platform_set_drvdata(pdev, pwm);

	return 0;
}

static struct platform_driver stmpe_pwm_driver = {
	.driver = {
		.name = "stmpe-pwm",
	},
};
builtin_platform_driver_probe(stmpe_pwm_driver, stmpe_pwm_probe);
