// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2019 Spreadtrum Communications Inc.
 */

#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/math64.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>

#define SPRD_PWM_PRESCALE	0x0
#define SPRD_PWM_MOD		0x4
#define SPRD_PWM_DUTY		0x8
#define SPRD_PWM_ENABLE		0x18

#define SPRD_PWM_MOD_MAX	GENMASK(7, 0)
#define SPRD_PWM_DUTY_MSK	GENMASK(15, 0)
#define SPRD_PWM_PRESCALE_MSK	GENMASK(7, 0)
#define SPRD_PWM_ENABLE_BIT	BIT(0)

#define SPRD_PWM_CHN_NUM	4
#define SPRD_PWM_REGS_SHIFT	5
#define SPRD_PWM_CHN_CLKS_NUM	2
#define SPRD_PWM_CHN_OUTPUT_CLK	1

struct sprd_pwm_chn {
	struct clk_bulk_data clks[SPRD_PWM_CHN_CLKS_NUM];
	u32 clk_rate;
};

struct sprd_pwm_chip {
	void __iomem *base;
	struct sprd_pwm_chn chn[SPRD_PWM_CHN_NUM];
};

static inline struct sprd_pwm_chip* sprd_pwm_from_chip(struct pwm_chip *chip)
{
	return pwmchip_get_drvdata(chip);
}

/*
 * The list of clocks required by PWM channels, and each channel has 2 clocks:
 * enable clock and pwm clock.
 */
static const char * const sprd_pwm_clks[] = {
	"enable0", "pwm0",
	"enable1", "pwm1",
	"enable2", "pwm2",
	"enable3", "pwm3",
};

static u32 sprd_pwm_read(struct sprd_pwm_chip *spc, u32 hwid, u32 reg)
{
	u32 offset = reg + (hwid << SPRD_PWM_REGS_SHIFT);

	return readl_relaxed(spc->base + offset);
}

static void sprd_pwm_write(struct sprd_pwm_chip *spc, u32 hwid,
			   u32 reg, u32 val)
{
	u32 offset = reg + (hwid << SPRD_PWM_REGS_SHIFT);

	writel_relaxed(val, spc->base + offset);
}

static int sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
			      struct pwm_state *state)
{
	struct sprd_pwm_chip *spc = sprd_pwm_from_chip(chip);
	struct sprd_pwm_chn *chn = &spc->chn[pwm->hwpwm];
	u32 val, duty, prescale;
	u64 tmp;
	int ret;

	/*
	 * The clocks to PWM channel has to be enabled first before
	 * reading to the registers.
	 */
	ret = clk_bulk_prepare_enable(SPRD_PWM_CHN_CLKS_NUM, chn->clks);
	if (ret) {
		dev_err(pwmchip_parent(chip), "failed to enable pwm%u clocks\n",
			pwm->hwpwm);
		return ret;
	}

	val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_ENABLE);
	if (val & SPRD_PWM_ENABLE_BIT)
		state->enabled = true;
	else
		state->enabled = false;

	/*
	 * The hardware provides a counter that is feed by the source clock.
	 * The period length is (PRESCALE + 1) * MOD counter steps.
	 * The duty cycle length is (PRESCALE + 1) * DUTY counter steps.
	 * Thus the period_ns and duty_ns calculation formula should be:
	 * period_ns = NSEC_PER_SEC * (prescale + 1) * mod / clk_rate
	 * duty_ns = NSEC_PER_SEC * (prescale + 1) * duty / clk_rate
	 */
	val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_PRESCALE);
	prescale = val & SPRD_PWM_PRESCALE_MSK;
	tmp = (prescale + 1) * NSEC_PER_SEC * SPRD_PWM_MOD_MAX;
	state->period = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate);

	val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_DUTY);
	duty = val & SPRD_PWM_DUTY_MSK;
	tmp = (prescale + 1) * NSEC_PER_SEC * duty;
	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate);
	state->polarity = PWM_POLARITY_NORMAL;

	/* Disable PWM clocks if the PWM channel is not in enable state. */
	if (!state->enabled)
		clk_bulk_disable_unprepare(SPRD_PWM_CHN_CLKS_NUM, chn->clks);

	return 0;
}

static int sprd_pwm_config(struct sprd_pwm_chip *spc, struct pwm_device *pwm,
			   int duty_ns, int period_ns)
{
	struct sprd_pwm_chn *chn = &spc->chn[pwm->hwpwm];
	u32 prescale, duty;
	u64 tmp;

	/*
	 * The hardware provides a counter that is feed by the source clock.
	 * The period length is (PRESCALE + 1) * MOD counter steps.
	 * The duty cycle length is (PRESCALE + 1) * DUTY counter steps.
	 *
	 * To keep the maths simple we're always using MOD = SPRD_PWM_MOD_MAX.
	 * The value for PRESCALE is selected such that the resulting period
	 * gets the maximal length not bigger than the requested one with the
	 * given settings (MOD = SPRD_PWM_MOD_MAX and input clock).
	 */
	duty = duty_ns * SPRD_PWM_MOD_MAX / period_ns;

	tmp = (u64)chn->clk_rate * period_ns;
	do_div(tmp, NSEC_PER_SEC);
	prescale = DIV_ROUND_CLOSEST_ULL(tmp, SPRD_PWM_MOD_MAX) - 1;
	if (prescale > SPRD_PWM_PRESCALE_MSK)
		prescale = SPRD_PWM_PRESCALE_MSK;

	/*
	 * Note: Writing DUTY triggers the hardware to actually apply the
	 * values written to MOD and DUTY to the output, so must keep writing
	 * DUTY last.
	 *
	 * The hardware can ensures that current running period is completed
	 * before changing a new configuration to avoid mixed settings.
	 */
	sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_PRESCALE, prescale);
	sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_MOD, SPRD_PWM_MOD_MAX);
	sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_DUTY, duty);

	return 0;
}

static int sprd_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
			  const struct pwm_state *state)
{
	struct sprd_pwm_chip *spc = sprd_pwm_from_chip(chip);
	struct sprd_pwm_chn *chn = &spc->chn[pwm->hwpwm];
	struct pwm_state *cstate = &pwm->state;
	int ret;

	if (state->polarity != PWM_POLARITY_NORMAL)
		return -EINVAL;

	if (state->enabled) {
		if (!cstate->enabled) {
			/*
			 * The clocks to PWM channel has to be enabled first
			 * before writing to the registers.
			 */
			ret = clk_bulk_prepare_enable(SPRD_PWM_CHN_CLKS_NUM,
						      chn->clks);
			if (ret) {
				dev_err(pwmchip_parent(chip),
					"failed to enable pwm%u clocks\n",
					pwm->hwpwm);
				return ret;
			}
		}

		ret = sprd_pwm_config(spc, pwm, state->duty_cycle,
				      state->period);
		if (ret)
			return ret;

		sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_ENABLE, 1);
	} else if (cstate->enabled) {
		/*
		 * Note: After setting SPRD_PWM_ENABLE to zero, the controller
		 * will not wait for current period to be completed, instead it
		 * will stop the PWM channel immediately.
		 */
		sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_ENABLE, 0);

		clk_bulk_disable_unprepare(SPRD_PWM_CHN_CLKS_NUM, chn->clks);
	}

	return 0;
}

static const struct pwm_ops sprd_pwm_ops = {
	.apply = sprd_pwm_apply,
	.get_state = sprd_pwm_get_state,
};

static int sprd_pwm_clk_init(struct device *dev,
			     struct sprd_pwm_chn chn[SPRD_PWM_CHN_NUM])
{
	struct clk *clk_pwm;
	int ret, i;

	for (i = 0; i < SPRD_PWM_CHN_NUM; i++) {
		int j;

		for (j = 0; j < SPRD_PWM_CHN_CLKS_NUM; ++j)
			chn[i].clks[j].id =
				sprd_pwm_clks[i * SPRD_PWM_CHN_CLKS_NUM + j];

		ret = devm_clk_bulk_get(dev, SPRD_PWM_CHN_CLKS_NUM,
					chn[i].clks);
		if (ret) {
			if (ret == -ENOENT)
				break;

			return dev_err_probe(dev, ret,
					     "failed to get channel clocks\n");
		}

		clk_pwm = chn[i].clks[SPRD_PWM_CHN_OUTPUT_CLK].clk;
		chn[i].clk_rate = clk_get_rate(clk_pwm);
	}

	if (!i)
		return dev_err_probe(dev, -ENODEV, "no available PWM channels\n");

	return i;
}

static int sprd_pwm_probe(struct platform_device *pdev)
{
	struct pwm_chip *chip;
	struct sprd_pwm_chip *spc;
	struct sprd_pwm_chn chn[SPRD_PWM_CHN_NUM];
	int ret, npwm;

	npwm = sprd_pwm_clk_init(&pdev->dev, chn);
	if (npwm < 0)
		return npwm;

	chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*spc));
	if (IS_ERR(chip))
		return PTR_ERR(chip);
	spc = sprd_pwm_from_chip(chip);

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

	memcpy(spc->chn, chn, sizeof(chn));

	chip->ops = &sprd_pwm_ops;

	ret = devm_pwmchip_add(&pdev->dev, chip);
	if (ret)
		dev_err(&pdev->dev, "failed to add PWM chip\n");

	return ret;
}

static const struct of_device_id sprd_pwm_of_match[] = {
	{ .compatible = "sprd,ums512-pwm", },
	{ },
};
MODULE_DEVICE_TABLE(of, sprd_pwm_of_match);

static struct platform_driver sprd_pwm_driver = {
	.driver = {
		.name = "sprd-pwm",
		.of_match_table = sprd_pwm_of_match,
	},
	.probe = sprd_pwm_probe,
};

module_platform_driver(sprd_pwm_driver);

MODULE_DESCRIPTION("Spreadtrum PWM Driver");
MODULE_LICENSE("GPL v2");
