// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) ST-Ericsson SA 2010
 *
 * Author: Arun R Murthy <arun.murthy@stericsson.com>
 * Datasheet: https://web.archive.org/web/20130614115108/http://www.stericsson.com/developers/CD00291561_UM1031_AB8500_user_manual-rev5_CTDS_public.pdf
 */
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/pwm.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/module.h>

/*
 * PWM Out generators
 * Bank: 0x10
 */
#define AB8500_PWM_OUT_CTRL1_REG	0x60
#define AB8500_PWM_OUT_CTRL2_REG	0x61
#define AB8500_PWM_OUT_CTRL7_REG	0x66

#define AB8500_PWM_CLKRATE 9600000

struct ab8500_pwm_chip {
	struct pwm_chip chip;
	unsigned int hwid;
};

static struct ab8500_pwm_chip *ab8500_pwm_from_chip(struct pwm_chip *chip)
{
	return container_of(chip, struct ab8500_pwm_chip, chip);
}

static int ab8500_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
			    const struct pwm_state *state)
{
	int ret;
	u8 reg;
	u8 higher_val, lower_val;
	unsigned int duty_steps, div;
	struct ab8500_pwm_chip *ab8500 = ab8500_pwm_from_chip(chip);

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

	if (state->enabled) {
		/*
		 * A time quantum is
		 *   q = (32 - FreqPWMOutx[3:0]) / AB8500_PWM_CLKRATE
		 * The period is always 1024 q, duty_cycle is between 1q and 1024q.
		 *
		 * FreqPWMOutx[3:0] | output frequency | output frequency | 1024q = period
		 *                  | (from manual)    |   (1 / 1024q)    | = 1 / freq
		 * -----------------+------------------+------------------+--------------
		 *      b0000       |      293 Hz      |  292.968750 Hz   | 3413333.33 ns
		 *      b0001       |      302 Hz      |  302.419355 Hz   | 3306666.66 ns
		 *      b0010       |      312 Hz      |  312.500000 Hz   | 3200000    ns
		 *      b0011       |      323 Hz      |  323.275862 Hz   | 3093333.33 ns
		 *      b0100       |      334 Hz      |  334.821429 Hz   | 2986666.66 ns
		 *      b0101       |      347 Hz      |  347.222222 Hz   | 2880000    ns
		 *      b0110       |      360 Hz      |  360.576923 Hz   | 2773333.33 ns
		 *      b0111       |      375 Hz      |  375.000000 Hz   | 2666666.66 ns
		 *      b1000       |      390 Hz      |  390.625000 Hz   | 2560000    ns
		 *      b1001       |      407 Hz      |  407.608696 Hz   | 2453333.33 ns
		 *      b1010       |      426 Hz      |  426.136364 Hz   | 2346666.66 ns
		 *      b1011       |      446 Hz      |  446.428571 Hz   | 2240000    ns
		 *      b1100       |      468 Hz      |  468.750000 Hz   | 2133333.33 ns
		 *      b1101       |      493 Hz      |  493.421053 Hz   | 2026666.66 ns
		 *      b1110       |      520 Hz      |  520.833333 Hz   | 1920000    ns
		 *      b1111       |      551 Hz      |  551.470588 Hz   | 1813333.33 ns
		 *
		 *
		 * AB8500_PWM_CLKRATE is a multiple of 1024, so the division by
		 * 1024 can be done in this factor without loss of precision.
		 */
		div = min_t(u64, mul_u64_u64_div_u64(state->period,
						     AB8500_PWM_CLKRATE >> 10,
						     NSEC_PER_SEC), 32); /* 32 - FreqPWMOutx[3:0] */
		if (div <= 16)
			/* requested period < 3413333.33 */
			return -EINVAL;

		duty_steps = max_t(u64, mul_u64_u64_div_u64(state->duty_cycle,
							    AB8500_PWM_CLKRATE,
							    (u64)NSEC_PER_SEC * div), 1024);
	}

	/*
	 * The hardware doesn't support duty_steps = 0 explicitly, but emits low
	 * when disabled.
	 */
	if (!state->enabled || duty_steps == 0) {
		ret = abx500_mask_and_set_register_interruptible(chip->dev,
					AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
					1 << ab8500->hwid, 0);

		if (ret < 0)
			dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n",
								pwm->label, ret);
		return ret;
	}

	/*
	 * The lower 8 bits of duty_steps is written to ...
	 * AB8500_PWM_OUT_CTRL1_REG[0:7]
	 */
	lower_val = (duty_steps - 1) & 0x00ff;
	/*
	 * The two remaining high bits to
	 * AB8500_PWM_OUT_CTRL2_REG[0:1]; together with FreqPWMOutx.
	 */
	higher_val = ((duty_steps - 1) & 0x0300) >> 8 | (32 - div) << 4;

	reg = AB8500_PWM_OUT_CTRL1_REG + (ab8500->hwid * 2);

	ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
			reg, lower_val);
	if (ret < 0)
		return ret;

	ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC,
			(reg + 1), higher_val);
	if (ret < 0)
		return ret;

	/* enable */
	ret = abx500_mask_and_set_register_interruptible(chip->dev,
				AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG,
				1 << ab8500->hwid, 1 << ab8500->hwid);
	if (ret < 0)
		dev_err(chip->dev, "%s: Failed to enable PWM, Error %d\n",
							pwm->label, ret);

	return ret;
}

static int ab8500_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
				struct pwm_state *state)
{
	u8 ctrl7, lower_val, higher_val;
	int ret;
	struct ab8500_pwm_chip *ab8500 = ab8500_pwm_from_chip(chip);
	unsigned int div, duty_steps;

	ret = abx500_get_register_interruptible(chip->dev, AB8500_MISC,
						AB8500_PWM_OUT_CTRL7_REG,
						&ctrl7);
	if (ret)
		return ret;

	state->polarity = PWM_POLARITY_NORMAL;

	if (!(ctrl7 & 1 << ab8500->hwid)) {
		state->enabled = false;
		return 0;
	}

	ret = abx500_get_register_interruptible(chip->dev, AB8500_MISC,
						AB8500_PWM_OUT_CTRL1_REG + (ab8500->hwid * 2),
						&lower_val);
	if (ret)
		return ret;

	ret = abx500_get_register_interruptible(chip->dev, AB8500_MISC,
						AB8500_PWM_OUT_CTRL2_REG + (ab8500->hwid * 2),
						&higher_val);
	if (ret)
		return ret;

	div = 32 - ((higher_val & 0xf0) >> 4);
	duty_steps = ((higher_val & 3) << 8 | lower_val) + 1;

	state->period = DIV64_U64_ROUND_UP((u64)div << 10, AB8500_PWM_CLKRATE);
	state->duty_cycle = DIV64_U64_ROUND_UP((u64)div * duty_steps, AB8500_PWM_CLKRATE);

	return 0;
}

static const struct pwm_ops ab8500_pwm_ops = {
	.apply = ab8500_pwm_apply,
	.get_state = ab8500_pwm_get_state,
	.owner = THIS_MODULE,
};

static int ab8500_pwm_probe(struct platform_device *pdev)
{
	struct ab8500_pwm_chip *ab8500;
	int err;

	if (pdev->id < 1 || pdev->id > 31)
		return dev_err_probe(&pdev->dev, -EINVAL, "Invalid device id %d\n", pdev->id);

	/*
	 * Nothing to be done in probe, this is required to get the
	 * device which is required for ab8500 read and write
	 */
	ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL);
	if (ab8500 == NULL)
		return -ENOMEM;

	ab8500->chip.dev = &pdev->dev;
	ab8500->chip.ops = &ab8500_pwm_ops;
	ab8500->chip.npwm = 1;
	ab8500->hwid = pdev->id - 1;

	err = devm_pwmchip_add(&pdev->dev, &ab8500->chip);
	if (err < 0)
		return dev_err_probe(&pdev->dev, err, "Failed to add pwm chip\n");

	dev_dbg(&pdev->dev, "pwm probe successful\n");

	return 0;
}

static struct platform_driver ab8500_pwm_driver = {
	.driver = {
		.name = "ab8500-pwm",
	},
	.probe = ab8500_pwm_probe,
};
module_platform_driver(ab8500_pwm_driver);

MODULE_AUTHOR("Arun MURTHY <arun.murthy@stericsson.com>");
MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver");
MODULE_ALIAS("platform:ab8500-pwm");
MODULE_LICENSE("GPL v2");
