// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2012 Freescale Semiconductor, Inc.
 */

#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/slab.h>
#include <linux/stmp_device.h>

#define SET	0x4
#define CLR	0x8
#define TOG	0xc

#define PWM_CTRL		0x0
#define PWM_ACTIVE0		0x10
#define PWM_PERIOD0		0x20
#define  PERIOD_PERIOD(p)	((p) & 0xffff)
#define  PERIOD_PERIOD_MAX	0x10000
#define  PERIOD_ACTIVE_HIGH	(3 << 16)
#define  PERIOD_ACTIVE_LOW	(2 << 16)
#define  PERIOD_INACTIVE_HIGH	(3 << 18)
#define  PERIOD_INACTIVE_LOW	(2 << 18)
#define  PERIOD_POLARITY_NORMAL	(PERIOD_ACTIVE_HIGH | PERIOD_INACTIVE_LOW)
#define  PERIOD_POLARITY_INVERSE	(PERIOD_ACTIVE_LOW | PERIOD_INACTIVE_HIGH)
#define  PERIOD_CDIV(div)	(((div) & 0x7) << 20)
#define  PERIOD_CDIV_MAX	8

static const u8 cdiv_shift[PERIOD_CDIV_MAX] = {
	0, 1, 2, 3, 4, 6, 8, 10
};

struct mxs_pwm_chip {
	struct pwm_chip chip;
	struct clk *clk;
	void __iomem *base;
};

#define to_mxs_pwm_chip(_chip) container_of(_chip, struct mxs_pwm_chip, chip)

static int mxs_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
			 const struct pwm_state *state)
{
	struct mxs_pwm_chip *mxs = to_mxs_pwm_chip(chip);
	int ret, div = 0;
	unsigned int period_cycles, duty_cycles;
	unsigned long rate;
	unsigned long long c;
	unsigned int pol_bits;

	/*
	 * If the PWM channel is disabled, make sure to turn on the
	 * clock before calling clk_get_rate() and writing to the
	 * registers. Otherwise, just keep it enabled.
	 */
	if (!pwm_is_enabled(pwm)) {
		ret = clk_prepare_enable(mxs->clk);
		if (ret)
			return ret;
	}

	if (!state->enabled && pwm_is_enabled(pwm))
		writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + CLR);

	rate = clk_get_rate(mxs->clk);
	while (1) {
		c = rate >> cdiv_shift[div];
		c = c * state->period;
		do_div(c, 1000000000);
		if (c < PERIOD_PERIOD_MAX)
			break;
		div++;
		if (div >= PERIOD_CDIV_MAX)
			return -EINVAL;
	}

	period_cycles = c;
	c *= state->duty_cycle;
	do_div(c, state->period);
	duty_cycles = c;

	/*
	 * The data sheet the says registers must be written to in
	 * this order (ACTIVEn, then PERIODn). Also, the new settings
	 * only take effect at the beginning of a new period, avoiding
	 * glitches.
	 */

	pol_bits = state->polarity == PWM_POLARITY_NORMAL ?
		PERIOD_POLARITY_NORMAL : PERIOD_POLARITY_INVERSE;
	writel(duty_cycles << 16,
	       mxs->base + PWM_ACTIVE0 + pwm->hwpwm * 0x20);
	writel(PERIOD_PERIOD(period_cycles) | pol_bits | PERIOD_CDIV(div),
	       mxs->base + PWM_PERIOD0 + pwm->hwpwm * 0x20);

	if (state->enabled) {
		if (!pwm_is_enabled(pwm)) {
			/*
			 * The clock was enabled above. Just enable
			 * the channel in the control register.
			 */
			writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + SET);
		}
	} else {
		clk_disable_unprepare(mxs->clk);
	}
	return 0;
}

static const struct pwm_ops mxs_pwm_ops = {
	.apply = mxs_pwm_apply,
	.owner = THIS_MODULE,
};

static int mxs_pwm_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct mxs_pwm_chip *mxs;
	int ret;

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

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

	mxs->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(mxs->clk))
		return PTR_ERR(mxs->clk);

	mxs->chip.dev = &pdev->dev;
	mxs->chip.ops = &mxs_pwm_ops;
	mxs->chip.of_xlate = of_pwm_xlate_with_flags;
	mxs->chip.of_pwm_n_cells = 3;
	mxs->chip.base = -1;

	ret = of_property_read_u32(np, "fsl,pwm-number", &mxs->chip.npwm);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to get pwm number: %d\n", ret);
		return ret;
	}

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

	platform_set_drvdata(pdev, mxs);

	ret = stmp_reset_block(mxs->base);
	if (ret)
		goto pwm_remove;

	return 0;

pwm_remove:
	pwmchip_remove(&mxs->chip);
	return ret;
}

static int mxs_pwm_remove(struct platform_device *pdev)
{
	struct mxs_pwm_chip *mxs = platform_get_drvdata(pdev);

	return pwmchip_remove(&mxs->chip);
}

static const struct of_device_id mxs_pwm_dt_ids[] = {
	{ .compatible = "fsl,imx23-pwm", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mxs_pwm_dt_ids);

static struct platform_driver mxs_pwm_driver = {
	.driver = {
		.name = "mxs-pwm",
		.of_match_table = mxs_pwm_dt_ids,
	},
	.probe = mxs_pwm_probe,
	.remove = mxs_pwm_remove,
};
module_platform_driver(mxs_pwm_driver);

MODULE_ALIAS("platform:mxs-pwm");
MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
MODULE_DESCRIPTION("Freescale MXS PWM Driver");
MODULE_LICENSE("GPL v2");
