// SPDX-License-Identifier: GPL-2.0-only
/*
 * Toshiba Visconti pulse-width-modulation controller driver
 *
 * Copyright (c) 2020 - 2021 TOSHIBA CORPORATION
 * Copyright (c) 2020 - 2021 Toshiba Electronic Devices & Storage Corporation
 *
 * Authors: Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
 *
 * Limitations:
 * - The fixed input clock is running at 1 MHz and is divided by either 1,
 *   2, 4 or 8.
 * - When the settings of the PWM are modified, the new values are shadowed
 *   in hardware until the PIPGM_PCSR register is written and the currently
 *   running period is completed. This way the hardware switches atomically
 *   from the old setting to the new.
 * - Disabling the hardware completes the currently running period and keeps
 *   the output at low level at all times.
 */

#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>

#define PIPGM_PCSR(ch) (0x400 + 4 * (ch))
#define PIPGM_PDUT(ch) (0x420 + 4 * (ch))
#define PIPGM_PWMC(ch) (0x440 + 4 * (ch))

#define PIPGM_PWMC_PWMACT		BIT(5)
#define PIPGM_PWMC_CLK_MASK		GENMASK(1, 0)
#define PIPGM_PWMC_POLARITY_MASK	GENMASK(5, 5)

struct visconti_pwm_chip {
	struct pwm_chip chip;
	void __iomem *base;
};

static inline struct visconti_pwm_chip *visconti_pwm_from_chip(struct pwm_chip *chip)
{
	return container_of(chip, struct visconti_pwm_chip, chip);
}

static int visconti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
			      const struct pwm_state *state)
{
	struct visconti_pwm_chip *priv = visconti_pwm_from_chip(chip);
	u32 period, duty_cycle, pwmc0;

	if (!state->enabled) {
		writel(0, priv->base + PIPGM_PCSR(pwm->hwpwm));
		return 0;
	}

	/*
	 * The biggest period the hardware can provide is
	 *	(0xffff << 3) * 1000 ns
	 * This value fits easily in an u32, so simplify the maths by
	 * capping the values to 32 bit integers.
	 */
	if (state->period > (0xffff << 3) * 1000)
		period = (0xffff << 3) * 1000;
	else
		period = state->period;

	if (state->duty_cycle > period)
		duty_cycle = period;
	else
		duty_cycle = state->duty_cycle;

	/*
	 * The input clock runs fixed at 1 MHz, so we have only
	 * microsecond resolution and so can divide by
	 * NSEC_PER_SEC / CLKFREQ = 1000 without losing precision.
	 */
	period /= 1000;
	duty_cycle /= 1000;

	if (!period)
		return -ERANGE;

	/*
	 * PWMC controls a divider that divides the input clk by a power of two
	 * between 1 and 8. As a smaller divider yields higher precision, pick
	 * the smallest possible one. As period is at most 0xffff << 3, pwmc0 is
	 * in the intended range [0..3].
	 */
	pwmc0 = fls(period >> 16);
	if (WARN_ON(pwmc0 > 3))
		return -EINVAL;

	period >>= pwmc0;
	duty_cycle >>= pwmc0;

	if (state->polarity == PWM_POLARITY_INVERSED)
		pwmc0 |= PIPGM_PWMC_PWMACT;
	writel(pwmc0, priv->base + PIPGM_PWMC(pwm->hwpwm));
	writel(duty_cycle, priv->base + PIPGM_PDUT(pwm->hwpwm));
	writel(period, priv->base + PIPGM_PCSR(pwm->hwpwm));

	return 0;
}

static int visconti_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
				  struct pwm_state *state)
{
	struct visconti_pwm_chip *priv = visconti_pwm_from_chip(chip);
	u32 period, duty, pwmc0, pwmc0_clk;

	period = readl(priv->base + PIPGM_PCSR(pwm->hwpwm));
	duty = readl(priv->base + PIPGM_PDUT(pwm->hwpwm));
	pwmc0 = readl(priv->base + PIPGM_PWMC(pwm->hwpwm));
	pwmc0_clk = pwmc0 & PIPGM_PWMC_CLK_MASK;

	state->period = (period << pwmc0_clk) * NSEC_PER_USEC;
	state->duty_cycle = (duty << pwmc0_clk) * NSEC_PER_USEC;
	if (pwmc0 & PIPGM_PWMC_POLARITY_MASK)
		state->polarity = PWM_POLARITY_INVERSED;
	else
		state->polarity = PWM_POLARITY_NORMAL;

	state->enabled = true;

	return 0;
}

static const struct pwm_ops visconti_pwm_ops = {
	.apply = visconti_pwm_apply,
	.get_state = visconti_pwm_get_state,
	.owner = THIS_MODULE,
};

static int visconti_pwm_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct visconti_pwm_chip *priv;
	int ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(priv->base))
		return PTR_ERR(priv->base);

	priv->chip.dev = dev;
	priv->chip.ops = &visconti_pwm_ops;
	priv->chip.npwm = 4;

	ret = devm_pwmchip_add(&pdev->dev, &priv->chip);
	if (ret < 0)
		return dev_err_probe(&pdev->dev, ret, "Cannot register visconti PWM\n");

	return 0;
}

static const struct of_device_id visconti_pwm_of_match[] = {
	{ .compatible = "toshiba,visconti-pwm", },
	{ }
};
MODULE_DEVICE_TABLE(of, visconti_pwm_of_match);

static struct platform_driver visconti_pwm_driver = {
	.driver = {
		.name = "pwm-visconti",
		.of_match_table = visconti_pwm_of_match,
	},
	.probe = visconti_pwm_probe,
};
module_platform_driver(visconti_pwm_driver);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>");
MODULE_ALIAS("platform:pwm-visconti");
