// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * ECAP PWM driver
 *
 * Copyright (C) 2012 Texas Instruments, Inc. - https://www.ti.com/
 */

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/pwm.h>
#include <linux/of.h>

/* ECAP registers and bits definitions */
#define CAP1			0x08
#define CAP2			0x0C
#define CAP3			0x10
#define CAP4			0x14
#define ECCTL2			0x2A
#define ECCTL2_APWM_POL_LOW	BIT(10)
#define ECCTL2_APWM_MODE	BIT(9)
#define ECCTL2_SYNC_SEL_DISA	(BIT(7) | BIT(6))
#define ECCTL2_TSCTR_FREERUN	BIT(4)

struct ecap_context {
	u32 cap3;
	u32 cap4;
	u16 ecctl2;
};

struct ecap_pwm_chip {
	unsigned int clk_rate;
	void __iomem *mmio_base;
	struct ecap_context ctx;
};

static inline struct ecap_pwm_chip *to_ecap_pwm_chip(struct pwm_chip *chip)
{
	return pwmchip_get_drvdata(chip);
}

/*
 * period_ns = 10^9 * period_cycles / PWM_CLK_RATE
 * duty_ns   = 10^9 * duty_cycles / PWM_CLK_RATE
 */
static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
			   int duty_ns, int period_ns, int enabled)
{
	struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
	u32 period_cycles, duty_cycles;
	unsigned long long c;
	u16 value;

	c = pc->clk_rate;
	c = c * period_ns;
	do_div(c, NSEC_PER_SEC);
	period_cycles = (u32)c;

	if (period_cycles < 1) {
		period_cycles = 1;
		duty_cycles = 1;
	} else {
		c = pc->clk_rate;
		c = c * duty_ns;
		do_div(c, NSEC_PER_SEC);
		duty_cycles = (u32)c;
	}

	pm_runtime_get_sync(pwmchip_parent(chip));

	value = readw(pc->mmio_base + ECCTL2);

	/* Configure APWM mode & disable sync option */
	value |= ECCTL2_APWM_MODE | ECCTL2_SYNC_SEL_DISA;

	writew(value, pc->mmio_base + ECCTL2);

	if (!enabled) {
		/* Update active registers if not running */
		writel(duty_cycles, pc->mmio_base + CAP2);
		writel(period_cycles, pc->mmio_base + CAP1);
	} else {
		/*
		 * Update shadow registers to configure period and
		 * compare values. This helps current PWM period to
		 * complete on reconfiguring
		 */
		writel(duty_cycles, pc->mmio_base + CAP4);
		writel(period_cycles, pc->mmio_base + CAP3);
	}

	if (!enabled) {
		value = readw(pc->mmio_base + ECCTL2);
		/* Disable APWM mode to put APWM output Low */
		value &= ~ECCTL2_APWM_MODE;
		writew(value, pc->mmio_base + ECCTL2);
	}

	pm_runtime_put_sync(pwmchip_parent(chip));

	return 0;
}

static int ecap_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
				 enum pwm_polarity polarity)
{
	struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
	u16 value;

	pm_runtime_get_sync(pwmchip_parent(chip));

	value = readw(pc->mmio_base + ECCTL2);

	if (polarity == PWM_POLARITY_INVERSED)
		/* Duty cycle defines LOW period of PWM */
		value |= ECCTL2_APWM_POL_LOW;
	else
		/* Duty cycle defines HIGH period of PWM */
		value &= ~ECCTL2_APWM_POL_LOW;

	writew(value, pc->mmio_base + ECCTL2);

	pm_runtime_put_sync(pwmchip_parent(chip));

	return 0;
}

static int ecap_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
{
	struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
	u16 value;

	/* Leave clock enabled on enabling PWM */
	pm_runtime_get_sync(pwmchip_parent(chip));

	/*
	 * Enable 'Free run Time stamp counter mode' to start counter
	 * and  'APWM mode' to enable APWM output
	 */
	value = readw(pc->mmio_base + ECCTL2);
	value |= ECCTL2_TSCTR_FREERUN | ECCTL2_APWM_MODE;
	writew(value, pc->mmio_base + ECCTL2);

	return 0;
}

static void ecap_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
{
	struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);
	u16 value;

	/*
	 * Disable 'Free run Time stamp counter mode' to stop counter
	 * and 'APWM mode' to put APWM output to low
	 */
	value = readw(pc->mmio_base + ECCTL2);
	value &= ~(ECCTL2_TSCTR_FREERUN | ECCTL2_APWM_MODE);
	writew(value, pc->mmio_base + ECCTL2);

	/* Disable clock on PWM disable */
	pm_runtime_put_sync(pwmchip_parent(chip));
}

static int ecap_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
			  const struct pwm_state *state)
{
	int err;
	int enabled = pwm->state.enabled;

	if (state->polarity != pwm->state.polarity) {

		if (enabled) {
			ecap_pwm_disable(chip, pwm);
			enabled = false;
		}

		err = ecap_pwm_set_polarity(chip, pwm, state->polarity);
		if (err)
			return err;
	}

	if (!state->enabled) {
		if (enabled)
			ecap_pwm_disable(chip, pwm);
		return 0;
	}

	if (state->period > NSEC_PER_SEC)
		return -ERANGE;

	err = ecap_pwm_config(chip, pwm, state->duty_cycle,
			      state->period, enabled);
	if (err)
		return err;

	if (!enabled)
		return ecap_pwm_enable(chip, pwm);

	return 0;
}

static const struct pwm_ops ecap_pwm_ops = {
	.apply = ecap_pwm_apply,
};

static const struct of_device_id ecap_of_match[] = {
	{ .compatible	= "ti,am3352-ecap" },
	{ .compatible	= "ti,am33xx-ecap" },
	{},
};
MODULE_DEVICE_TABLE(of, ecap_of_match);

static int ecap_pwm_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct ecap_pwm_chip *pc;
	struct pwm_chip *chip;
	struct clk *clk;
	int ret;

	chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*pc));
	if (IS_ERR(chip))
		return PTR_ERR(chip);
	pc = to_ecap_pwm_chip(chip);

	clk = devm_clk_get(&pdev->dev, "fck");
	if (IS_ERR(clk)) {
		if (of_device_is_compatible(np, "ti,am33xx-ecap")) {
			dev_warn(&pdev->dev, "Binding is obsolete.\n");
			clk = devm_clk_get(pdev->dev.parent, "fck");
		}
	}

	if (IS_ERR(clk)) {
		dev_err(&pdev->dev, "failed to get clock\n");
		return PTR_ERR(clk);
	}

	pc->clk_rate = clk_get_rate(clk);
	if (!pc->clk_rate) {
		dev_err(&pdev->dev, "failed to get clock rate\n");
		return -EINVAL;
	}

	chip->ops = &ecap_pwm_ops;

	pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(pc->mmio_base))
		return PTR_ERR(pc->mmio_base);

	ret = devm_pwmchip_add(&pdev->dev, chip);
	if (ret < 0) {
		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
		return ret;
	}

	platform_set_drvdata(pdev, chip);
	pm_runtime_enable(&pdev->dev);

	return 0;
}

static void ecap_pwm_remove(struct platform_device *pdev)
{
	pm_runtime_disable(&pdev->dev);
}

static void ecap_pwm_save_context(struct pwm_chip *chip)
{
	struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);

	pm_runtime_get_sync(pwmchip_parent(chip));
	pc->ctx.ecctl2 = readw(pc->mmio_base + ECCTL2);
	pc->ctx.cap4 = readl(pc->mmio_base + CAP4);
	pc->ctx.cap3 = readl(pc->mmio_base + CAP3);
	pm_runtime_put_sync(pwmchip_parent(chip));
}

static void ecap_pwm_restore_context(struct pwm_chip *chip)
{
	struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip);

	writel(pc->ctx.cap3, pc->mmio_base + CAP3);
	writel(pc->ctx.cap4, pc->mmio_base + CAP4);
	writew(pc->ctx.ecctl2, pc->mmio_base + ECCTL2);
}

static int ecap_pwm_suspend(struct device *dev)
{
	struct pwm_chip *chip = dev_get_drvdata(dev);
	struct pwm_device *pwm = chip->pwms;

	ecap_pwm_save_context(chip);

	/* Disable explicitly if PWM is running */
	if (pwm_is_enabled(pwm))
		pm_runtime_put_sync(dev);

	return 0;
}

static int ecap_pwm_resume(struct device *dev)
{
	struct pwm_chip *chip = dev_get_drvdata(dev);
	struct pwm_device *pwm = chip->pwms;

	/* Enable explicitly if PWM was running */
	if (pwm_is_enabled(pwm))
		pm_runtime_get_sync(dev);

	ecap_pwm_restore_context(chip);
	return 0;
}

static DEFINE_SIMPLE_DEV_PM_OPS(ecap_pwm_pm_ops, ecap_pwm_suspend, ecap_pwm_resume);

static struct platform_driver ecap_pwm_driver = {
	.driver = {
		.name = "ecap",
		.of_match_table = ecap_of_match,
		.pm = pm_ptr(&ecap_pwm_pm_ops),
	},
	.probe = ecap_pwm_probe,
	.remove_new = ecap_pwm_remove,
};
module_platform_driver(ecap_pwm_driver);

MODULE_DESCRIPTION("ECAP PWM driver");
MODULE_AUTHOR("Texas Instruments");
MODULE_LICENSE("GPL");
