/*
 * Copyright (C) 2017 Sanechips Technology Co., Ltd.
 * Copyright 2017 Linaro Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

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

#define ZX_PWM_MODE		0x0
#define ZX_PWM_CLKDIV_SHIFT	2
#define ZX_PWM_CLKDIV_MASK	GENMASK(11, 2)
#define ZX_PWM_CLKDIV(x)	(((x) << ZX_PWM_CLKDIV_SHIFT) & \
					 ZX_PWM_CLKDIV_MASK)
#define ZX_PWM_POLAR		BIT(1)
#define ZX_PWM_EN		BIT(0)
#define ZX_PWM_PERIOD		0x4
#define ZX_PWM_DUTY		0x8

#define ZX_PWM_CLKDIV_MAX	1023
#define ZX_PWM_PERIOD_MAX	65535

struct zx_pwm_chip {
	struct pwm_chip chip;
	struct clk *pclk;
	struct clk *wclk;
	void __iomem *base;
};

static inline struct zx_pwm_chip *to_zx_pwm_chip(struct pwm_chip *chip)
{
	return container_of(chip, struct zx_pwm_chip, chip);
}

static inline u32 zx_pwm_readl(struct zx_pwm_chip *zpc, unsigned int hwpwm,
			       unsigned int offset)
{
	return readl(zpc->base + (hwpwm + 1) * 0x10 + offset);
}

static inline void zx_pwm_writel(struct zx_pwm_chip *zpc, unsigned int hwpwm,
				 unsigned int offset, u32 value)
{
	writel(value, zpc->base + (hwpwm + 1) * 0x10 + offset);
}

static void zx_pwm_set_mask(struct zx_pwm_chip *zpc, unsigned int hwpwm,
			    unsigned int offset, u32 mask, u32 value)
{
	u32 data;

	data = zx_pwm_readl(zpc, hwpwm, offset);
	data &= ~mask;
	data |= value & mask;
	zx_pwm_writel(zpc, hwpwm, offset, data);
}

static void zx_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
			     struct pwm_state *state)
{
	struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip);
	unsigned long rate;
	unsigned int div;
	u32 value;
	u64 tmp;

	value = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_MODE);

	if (value & ZX_PWM_POLAR)
		state->polarity = PWM_POLARITY_NORMAL;
	else
		state->polarity = PWM_POLARITY_INVERSED;

	if (value & ZX_PWM_EN)
		state->enabled = true;
	else
		state->enabled = false;

	div = (value & ZX_PWM_CLKDIV_MASK) >> ZX_PWM_CLKDIV_SHIFT;
	rate = clk_get_rate(zpc->wclk);

	tmp = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_PERIOD);
	tmp *= div * NSEC_PER_SEC;
	state->period = DIV_ROUND_CLOSEST_ULL(tmp, rate);

	tmp = zx_pwm_readl(zpc, pwm->hwpwm, ZX_PWM_DUTY);
	tmp *= div * NSEC_PER_SEC;
	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, rate);
}

static int zx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
			 unsigned int duty_ns, unsigned int period_ns)
{
	struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip);
	unsigned int period_cycles, duty_cycles;
	unsigned long long c;
	unsigned int div = 1;
	unsigned long rate;

	/* Find out the best divider */
	rate = clk_get_rate(zpc->wclk);

	while (1) {
		c = rate / div;
		c = c * period_ns;
		do_div(c, NSEC_PER_SEC);

		if (c < ZX_PWM_PERIOD_MAX)
			break;

		div++;

		if (div > ZX_PWM_CLKDIV_MAX)
			return -ERANGE;
	}

	/* Calculate duty cycles */
	period_cycles = c;
	c *= duty_ns;
	do_div(c, period_ns);
	duty_cycles = c;

	/*
	 * If the PWM is being enabled, we have to temporarily disable it
	 * before configuring the registers.
	 */
	if (pwm_is_enabled(pwm))
		zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_EN, 0);

	/* Set up registers */
	zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_CLKDIV_MASK,
			ZX_PWM_CLKDIV(div));
	zx_pwm_writel(zpc, pwm->hwpwm, ZX_PWM_PERIOD, period_cycles);
	zx_pwm_writel(zpc, pwm->hwpwm, ZX_PWM_DUTY, duty_cycles);

	/* Re-enable the PWM if needed */
	if (pwm_is_enabled(pwm))
		zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE,
				ZX_PWM_EN, ZX_PWM_EN);

	return 0;
}

static int zx_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
			struct pwm_state *state)
{
	struct zx_pwm_chip *zpc = to_zx_pwm_chip(chip);
	struct pwm_state cstate;
	int ret;

	pwm_get_state(pwm, &cstate);

	if (state->polarity != cstate.polarity)
		zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE, ZX_PWM_POLAR,
				(state->polarity == PWM_POLARITY_INVERSED) ?
				 0 : ZX_PWM_POLAR);

	if (state->period != cstate.period ||
	    state->duty_cycle != cstate.duty_cycle) {
		ret = zx_pwm_config(chip, pwm, state->duty_cycle,
				    state->period);
		if (ret)
			return ret;
	}

	if (state->enabled != cstate.enabled) {
		if (state->enabled) {
			ret = clk_prepare_enable(zpc->wclk);
			if (ret)
				return ret;

			zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE,
					ZX_PWM_EN, ZX_PWM_EN);
		} else {
			zx_pwm_set_mask(zpc, pwm->hwpwm, ZX_PWM_MODE,
					ZX_PWM_EN, 0);
			clk_disable_unprepare(zpc->wclk);
		}
	}

	return 0;
}

static const struct pwm_ops zx_pwm_ops = {
	.apply = zx_pwm_apply,
	.get_state = zx_pwm_get_state,
	.owner = THIS_MODULE,
};

static int zx_pwm_probe(struct platform_device *pdev)
{
	struct zx_pwm_chip *zpc;
	struct resource *res;
	unsigned int i;
	int ret;

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

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	zpc->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(zpc->base))
		return PTR_ERR(zpc->base);

	zpc->pclk = devm_clk_get(&pdev->dev, "pclk");
	if (IS_ERR(zpc->pclk))
		return PTR_ERR(zpc->pclk);

	zpc->wclk = devm_clk_get(&pdev->dev, "wclk");
	if (IS_ERR(zpc->wclk))
		return PTR_ERR(zpc->wclk);

	ret = clk_prepare_enable(zpc->pclk);
	if (ret)
		return ret;

	zpc->chip.dev = &pdev->dev;
	zpc->chip.ops = &zx_pwm_ops;
	zpc->chip.base = -1;
	zpc->chip.npwm = 4;
	zpc->chip.of_xlate = of_pwm_xlate_with_flags;
	zpc->chip.of_pwm_n_cells = 3;

	/*
	 * PWM devices may be enabled by firmware, and let's disable all of
	 * them initially to save power.
	 */
	for (i = 0; i < zpc->chip.npwm; i++)
		zx_pwm_set_mask(zpc, i, ZX_PWM_MODE, ZX_PWM_EN, 0);

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

	platform_set_drvdata(pdev, zpc);

	return 0;
}

static int zx_pwm_remove(struct platform_device *pdev)
{
	struct zx_pwm_chip *zpc = platform_get_drvdata(pdev);
	int ret;

	ret = pwmchip_remove(&zpc->chip);
	clk_disable_unprepare(zpc->pclk);

	return ret;
}

static const struct of_device_id zx_pwm_dt_ids[] = {
	{ .compatible = "zte,zx296718-pwm", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, zx_pwm_dt_ids);

static struct platform_driver zx_pwm_driver = {
	.driver = {
		.name = "zx-pwm",
		.of_match_table = zx_pwm_dt_ids,
	},
	.probe = zx_pwm_probe,
	.remove = zx_pwm_remove,
};
module_platform_driver(zx_pwm_driver);

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