18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Driver for Atmel Pulse Width Modulation Controller
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2013 Atmel Corporation
68c2ecf20Sopenharmony_ci *		 Bo Shen <voice.shen@atmel.com>
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Links to reference manuals for the supported PWM chips can be found in
98c2ecf20Sopenharmony_ci * Documentation/arm/microchip.rst.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Limitations:
128c2ecf20Sopenharmony_ci * - Periods start with the inactive level.
138c2ecf20Sopenharmony_ci * - Hardware has to be stopped in general to update settings.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * Software bugs/possible improvements:
168c2ecf20Sopenharmony_ci * - When atmel_pwm_apply() is called with state->enabled=false a change in
178c2ecf20Sopenharmony_ci *   state->polarity isn't honored.
188c2ecf20Sopenharmony_ci * - Instead of sleeping to wait for a completed period, the interrupt
198c2ecf20Sopenharmony_ci *   functionality could be used.
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <linux/clk.h>
238c2ecf20Sopenharmony_ci#include <linux/delay.h>
248c2ecf20Sopenharmony_ci#include <linux/err.h>
258c2ecf20Sopenharmony_ci#include <linux/io.h>
268c2ecf20Sopenharmony_ci#include <linux/module.h>
278c2ecf20Sopenharmony_ci#include <linux/mutex.h>
288c2ecf20Sopenharmony_ci#include <linux/of.h>
298c2ecf20Sopenharmony_ci#include <linux/of_device.h>
308c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
318c2ecf20Sopenharmony_ci#include <linux/pwm.h>
328c2ecf20Sopenharmony_ci#include <linux/slab.h>
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/* The following is global registers for PWM controller */
358c2ecf20Sopenharmony_ci#define PWM_ENA			0x04
368c2ecf20Sopenharmony_ci#define PWM_DIS			0x08
378c2ecf20Sopenharmony_ci#define PWM_SR			0x0C
388c2ecf20Sopenharmony_ci#define PWM_ISR			0x1C
398c2ecf20Sopenharmony_ci/* Bit field in SR */
408c2ecf20Sopenharmony_ci#define PWM_SR_ALL_CH_ON	0x0F
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* The following register is PWM channel related registers */
438c2ecf20Sopenharmony_ci#define PWM_CH_REG_OFFSET	0x200
448c2ecf20Sopenharmony_ci#define PWM_CH_REG_SIZE		0x20
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#define PWM_CMR			0x0
478c2ecf20Sopenharmony_ci/* Bit field in CMR */
488c2ecf20Sopenharmony_ci#define PWM_CMR_CPOL		(1 << 9)
498c2ecf20Sopenharmony_ci#define PWM_CMR_UPD_CDTY	(1 << 10)
508c2ecf20Sopenharmony_ci#define PWM_CMR_CPRE_MSK	0xF
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* The following registers for PWM v1 */
538c2ecf20Sopenharmony_ci#define PWMV1_CDTY		0x04
548c2ecf20Sopenharmony_ci#define PWMV1_CPRD		0x08
558c2ecf20Sopenharmony_ci#define PWMV1_CUPD		0x10
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/* The following registers for PWM v2 */
588c2ecf20Sopenharmony_ci#define PWMV2_CDTY		0x04
598c2ecf20Sopenharmony_ci#define PWMV2_CDTYUPD		0x08
608c2ecf20Sopenharmony_ci#define PWMV2_CPRD		0x0C
618c2ecf20Sopenharmony_ci#define PWMV2_CPRDUPD		0x10
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci#define PWM_MAX_PRES		10
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistruct atmel_pwm_registers {
668c2ecf20Sopenharmony_ci	u8 period;
678c2ecf20Sopenharmony_ci	u8 period_upd;
688c2ecf20Sopenharmony_ci	u8 duty;
698c2ecf20Sopenharmony_ci	u8 duty_upd;
708c2ecf20Sopenharmony_ci};
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistruct atmel_pwm_config {
738c2ecf20Sopenharmony_ci	u32 period_bits;
748c2ecf20Sopenharmony_ci};
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistruct atmel_pwm_data {
778c2ecf20Sopenharmony_ci	struct atmel_pwm_registers regs;
788c2ecf20Sopenharmony_ci	struct atmel_pwm_config cfg;
798c2ecf20Sopenharmony_ci};
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistruct atmel_pwm_chip {
828c2ecf20Sopenharmony_ci	struct pwm_chip chip;
838c2ecf20Sopenharmony_ci	struct clk *clk;
848c2ecf20Sopenharmony_ci	void __iomem *base;
858c2ecf20Sopenharmony_ci	const struct atmel_pwm_data *data;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	unsigned int updated_pwms;
888c2ecf20Sopenharmony_ci	/* ISR is cleared when read, ensure only one thread does that */
898c2ecf20Sopenharmony_ci	struct mutex isr_lock;
908c2ecf20Sopenharmony_ci};
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistatic inline struct atmel_pwm_chip *to_atmel_pwm_chip(struct pwm_chip *chip)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	return container_of(chip, struct atmel_pwm_chip, chip);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic inline u32 atmel_pwm_readl(struct atmel_pwm_chip *chip,
988c2ecf20Sopenharmony_ci				  unsigned long offset)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	return readl_relaxed(chip->base + offset);
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic inline void atmel_pwm_writel(struct atmel_pwm_chip *chip,
1048c2ecf20Sopenharmony_ci				    unsigned long offset, unsigned long val)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	writel_relaxed(val, chip->base + offset);
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cistatic inline u32 atmel_pwm_ch_readl(struct atmel_pwm_chip *chip,
1108c2ecf20Sopenharmony_ci				     unsigned int ch, unsigned long offset)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	unsigned long base = PWM_CH_REG_OFFSET + ch * PWM_CH_REG_SIZE;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	return atmel_pwm_readl(chip, base + offset);
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistatic inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip,
1188c2ecf20Sopenharmony_ci				       unsigned int ch, unsigned long offset,
1198c2ecf20Sopenharmony_ci				       unsigned long val)
1208c2ecf20Sopenharmony_ci{
1218c2ecf20Sopenharmony_ci	unsigned long base = PWM_CH_REG_OFFSET + ch * PWM_CH_REG_SIZE;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	atmel_pwm_writel(chip, base + offset, val);
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip,
1278c2ecf20Sopenharmony_ci					     const struct pwm_state *state,
1288c2ecf20Sopenharmony_ci					     unsigned long *cprd, u32 *pres)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
1318c2ecf20Sopenharmony_ci	unsigned long long cycles = state->period;
1328c2ecf20Sopenharmony_ci	int shift;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	/* Calculate the period cycles and prescale value */
1358c2ecf20Sopenharmony_ci	cycles *= clk_get_rate(atmel_pwm->clk);
1368c2ecf20Sopenharmony_ci	do_div(cycles, NSEC_PER_SEC);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	/*
1398c2ecf20Sopenharmony_ci	 * The register for the period length is cfg.period_bits bits wide.
1408c2ecf20Sopenharmony_ci	 * So for each bit the number of clock cycles is wider divide the input
1418c2ecf20Sopenharmony_ci	 * clock frequency by two using pres and shift cprd accordingly.
1428c2ecf20Sopenharmony_ci	 */
1438c2ecf20Sopenharmony_ci	shift = fls(cycles) - atmel_pwm->data->cfg.period_bits;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	if (shift > PWM_MAX_PRES) {
1468c2ecf20Sopenharmony_ci		dev_err(chip->dev, "pres exceeds the maximum value\n");
1478c2ecf20Sopenharmony_ci		return -EINVAL;
1488c2ecf20Sopenharmony_ci	} else if (shift > 0) {
1498c2ecf20Sopenharmony_ci		*pres = shift;
1508c2ecf20Sopenharmony_ci		cycles >>= *pres;
1518c2ecf20Sopenharmony_ci	} else {
1528c2ecf20Sopenharmony_ci		*pres = 0;
1538c2ecf20Sopenharmony_ci	}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	*cprd = cycles;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	return 0;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic void atmel_pwm_calculate_cdty(const struct pwm_state *state,
1618c2ecf20Sopenharmony_ci				     unsigned long cprd, unsigned long *cdty)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	unsigned long long cycles = state->duty_cycle;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	cycles *= cprd;
1668c2ecf20Sopenharmony_ci	do_div(cycles, state->period);
1678c2ecf20Sopenharmony_ci	*cdty = cprd - cycles;
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic void atmel_pwm_update_cdty(struct pwm_chip *chip, struct pwm_device *pwm,
1718c2ecf20Sopenharmony_ci				  unsigned long cdty)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
1748c2ecf20Sopenharmony_ci	u32 val;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	if (atmel_pwm->data->regs.duty_upd ==
1778c2ecf20Sopenharmony_ci	    atmel_pwm->data->regs.period_upd) {
1788c2ecf20Sopenharmony_ci		val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
1798c2ecf20Sopenharmony_ci		val &= ~PWM_CMR_UPD_CDTY;
1808c2ecf20Sopenharmony_ci		atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
1818c2ecf20Sopenharmony_ci	}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm,
1848c2ecf20Sopenharmony_ci			    atmel_pwm->data->regs.duty_upd, cdty);
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic void atmel_pwm_set_cprd_cdty(struct pwm_chip *chip,
1888c2ecf20Sopenharmony_ci				    struct pwm_device *pwm,
1898c2ecf20Sopenharmony_ci				    unsigned long cprd, unsigned long cdty)
1908c2ecf20Sopenharmony_ci{
1918c2ecf20Sopenharmony_ci	struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm,
1948c2ecf20Sopenharmony_ci			    atmel_pwm->data->regs.duty, cdty);
1958c2ecf20Sopenharmony_ci	atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm,
1968c2ecf20Sopenharmony_ci			    atmel_pwm->data->regs.period, cprd);
1978c2ecf20Sopenharmony_ci}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistatic void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm,
2008c2ecf20Sopenharmony_ci			      bool disable_clk)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
2038c2ecf20Sopenharmony_ci	unsigned long timeout = jiffies + 2 * HZ;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	/*
2068c2ecf20Sopenharmony_ci	 * Wait for at least a complete period to have passed before disabling a
2078c2ecf20Sopenharmony_ci	 * channel to be sure that CDTY has been updated
2088c2ecf20Sopenharmony_ci	 */
2098c2ecf20Sopenharmony_ci	mutex_lock(&atmel_pwm->isr_lock);
2108c2ecf20Sopenharmony_ci	atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	while (!(atmel_pwm->updated_pwms & (1 << pwm->hwpwm)) &&
2138c2ecf20Sopenharmony_ci	       time_before(jiffies, timeout)) {
2148c2ecf20Sopenharmony_ci		usleep_range(10, 100);
2158c2ecf20Sopenharmony_ci		atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
2168c2ecf20Sopenharmony_ci	}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	mutex_unlock(&atmel_pwm->isr_lock);
2198c2ecf20Sopenharmony_ci	atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	/*
2228c2ecf20Sopenharmony_ci	 * Wait for the PWM channel disable operation to be effective before
2238c2ecf20Sopenharmony_ci	 * stopping the clock.
2248c2ecf20Sopenharmony_ci	 */
2258c2ecf20Sopenharmony_ci	timeout = jiffies + 2 * HZ;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	while ((atmel_pwm_readl(atmel_pwm, PWM_SR) & (1 << pwm->hwpwm)) &&
2288c2ecf20Sopenharmony_ci	       time_before(jiffies, timeout))
2298c2ecf20Sopenharmony_ci		usleep_range(10, 100);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if (disable_clk)
2328c2ecf20Sopenharmony_ci		clk_disable(atmel_pwm->clk);
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
2368c2ecf20Sopenharmony_ci			   const struct pwm_state *state)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
2398c2ecf20Sopenharmony_ci	struct pwm_state cstate;
2408c2ecf20Sopenharmony_ci	unsigned long cprd, cdty;
2418c2ecf20Sopenharmony_ci	u32 pres, val;
2428c2ecf20Sopenharmony_ci	int ret;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	pwm_get_state(pwm, &cstate);
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	if (state->enabled) {
2478c2ecf20Sopenharmony_ci		if (cstate.enabled &&
2488c2ecf20Sopenharmony_ci		    cstate.polarity == state->polarity &&
2498c2ecf20Sopenharmony_ci		    cstate.period == state->period) {
2508c2ecf20Sopenharmony_ci			cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm,
2518c2ecf20Sopenharmony_ci						  atmel_pwm->data->regs.period);
2528c2ecf20Sopenharmony_ci			atmel_pwm_calculate_cdty(state, cprd, &cdty);
2538c2ecf20Sopenharmony_ci			atmel_pwm_update_cdty(chip, pwm, cdty);
2548c2ecf20Sopenharmony_ci			return 0;
2558c2ecf20Sopenharmony_ci		}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci		ret = atmel_pwm_calculate_cprd_and_pres(chip, state, &cprd,
2588c2ecf20Sopenharmony_ci							&pres);
2598c2ecf20Sopenharmony_ci		if (ret) {
2608c2ecf20Sopenharmony_ci			dev_err(chip->dev,
2618c2ecf20Sopenharmony_ci				"failed to calculate cprd and prescaler\n");
2628c2ecf20Sopenharmony_ci			return ret;
2638c2ecf20Sopenharmony_ci		}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci		atmel_pwm_calculate_cdty(state, cprd, &cdty);
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci		if (cstate.enabled) {
2688c2ecf20Sopenharmony_ci			atmel_pwm_disable(chip, pwm, false);
2698c2ecf20Sopenharmony_ci		} else {
2708c2ecf20Sopenharmony_ci			ret = clk_enable(atmel_pwm->clk);
2718c2ecf20Sopenharmony_ci			if (ret) {
2728c2ecf20Sopenharmony_ci				dev_err(chip->dev, "failed to enable clock\n");
2738c2ecf20Sopenharmony_ci				return ret;
2748c2ecf20Sopenharmony_ci			}
2758c2ecf20Sopenharmony_ci		}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci		/* It is necessary to preserve CPOL, inside CMR */
2788c2ecf20Sopenharmony_ci		val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
2798c2ecf20Sopenharmony_ci		val = (val & ~PWM_CMR_CPRE_MSK) | (pres & PWM_CMR_CPRE_MSK);
2808c2ecf20Sopenharmony_ci		if (state->polarity == PWM_POLARITY_NORMAL)
2818c2ecf20Sopenharmony_ci			val &= ~PWM_CMR_CPOL;
2828c2ecf20Sopenharmony_ci		else
2838c2ecf20Sopenharmony_ci			val |= PWM_CMR_CPOL;
2848c2ecf20Sopenharmony_ci		atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
2858c2ecf20Sopenharmony_ci		atmel_pwm_set_cprd_cdty(chip, pwm, cprd, cdty);
2868c2ecf20Sopenharmony_ci		mutex_lock(&atmel_pwm->isr_lock);
2878c2ecf20Sopenharmony_ci		atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
2888c2ecf20Sopenharmony_ci		atmel_pwm->updated_pwms &= ~(1 << pwm->hwpwm);
2898c2ecf20Sopenharmony_ci		mutex_unlock(&atmel_pwm->isr_lock);
2908c2ecf20Sopenharmony_ci		atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << pwm->hwpwm);
2918c2ecf20Sopenharmony_ci	} else if (cstate.enabled) {
2928c2ecf20Sopenharmony_ci		atmel_pwm_disable(chip, pwm, true);
2938c2ecf20Sopenharmony_ci	}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	return 0;
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
2998c2ecf20Sopenharmony_ci				struct pwm_state *state)
3008c2ecf20Sopenharmony_ci{
3018c2ecf20Sopenharmony_ci	struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
3028c2ecf20Sopenharmony_ci	u32 sr, cmr;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	sr = atmel_pwm_readl(atmel_pwm, PWM_SR);
3058c2ecf20Sopenharmony_ci	cmr = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	if (sr & (1 << pwm->hwpwm)) {
3088c2ecf20Sopenharmony_ci		unsigned long rate = clk_get_rate(atmel_pwm->clk);
3098c2ecf20Sopenharmony_ci		u32 cdty, cprd, pres;
3108c2ecf20Sopenharmony_ci		u64 tmp;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci		pres = cmr & PWM_CMR_CPRE_MSK;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci		cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm,
3158c2ecf20Sopenharmony_ci					  atmel_pwm->data->regs.period);
3168c2ecf20Sopenharmony_ci		tmp = (u64)cprd * NSEC_PER_SEC;
3178c2ecf20Sopenharmony_ci		tmp <<= pres;
3188c2ecf20Sopenharmony_ci		state->period = DIV64_U64_ROUND_UP(tmp, rate);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci		cdty = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm,
3218c2ecf20Sopenharmony_ci					  atmel_pwm->data->regs.duty);
3228c2ecf20Sopenharmony_ci		tmp = (u64)(cprd - cdty) * NSEC_PER_SEC;
3238c2ecf20Sopenharmony_ci		tmp <<= pres;
3248c2ecf20Sopenharmony_ci		state->duty_cycle = DIV64_U64_ROUND_UP(tmp, rate);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci		state->enabled = true;
3278c2ecf20Sopenharmony_ci	} else {
3288c2ecf20Sopenharmony_ci		state->enabled = false;
3298c2ecf20Sopenharmony_ci	}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	if (cmr & PWM_CMR_CPOL)
3328c2ecf20Sopenharmony_ci		state->polarity = PWM_POLARITY_INVERSED;
3338c2ecf20Sopenharmony_ci	else
3348c2ecf20Sopenharmony_ci		state->polarity = PWM_POLARITY_NORMAL;
3358c2ecf20Sopenharmony_ci}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic const struct pwm_ops atmel_pwm_ops = {
3388c2ecf20Sopenharmony_ci	.apply = atmel_pwm_apply,
3398c2ecf20Sopenharmony_ci	.get_state = atmel_pwm_get_state,
3408c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
3418c2ecf20Sopenharmony_ci};
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_cistatic const struct atmel_pwm_data atmel_sam9rl_pwm_data = {
3448c2ecf20Sopenharmony_ci	.regs = {
3458c2ecf20Sopenharmony_ci		.period		= PWMV1_CPRD,
3468c2ecf20Sopenharmony_ci		.period_upd	= PWMV1_CUPD,
3478c2ecf20Sopenharmony_ci		.duty		= PWMV1_CDTY,
3488c2ecf20Sopenharmony_ci		.duty_upd	= PWMV1_CUPD,
3498c2ecf20Sopenharmony_ci	},
3508c2ecf20Sopenharmony_ci	.cfg = {
3518c2ecf20Sopenharmony_ci		/* 16 bits to keep period and duty. */
3528c2ecf20Sopenharmony_ci		.period_bits	= 16,
3538c2ecf20Sopenharmony_ci	},
3548c2ecf20Sopenharmony_ci};
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cistatic const struct atmel_pwm_data atmel_sama5_pwm_data = {
3578c2ecf20Sopenharmony_ci	.regs = {
3588c2ecf20Sopenharmony_ci		.period		= PWMV2_CPRD,
3598c2ecf20Sopenharmony_ci		.period_upd	= PWMV2_CPRDUPD,
3608c2ecf20Sopenharmony_ci		.duty		= PWMV2_CDTY,
3618c2ecf20Sopenharmony_ci		.duty_upd	= PWMV2_CDTYUPD,
3628c2ecf20Sopenharmony_ci	},
3638c2ecf20Sopenharmony_ci	.cfg = {
3648c2ecf20Sopenharmony_ci		/* 16 bits to keep period and duty. */
3658c2ecf20Sopenharmony_ci		.period_bits	= 16,
3668c2ecf20Sopenharmony_ci	},
3678c2ecf20Sopenharmony_ci};
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cistatic const struct atmel_pwm_data mchp_sam9x60_pwm_data = {
3708c2ecf20Sopenharmony_ci	.regs = {
3718c2ecf20Sopenharmony_ci		.period		= PWMV1_CPRD,
3728c2ecf20Sopenharmony_ci		.period_upd	= PWMV1_CUPD,
3738c2ecf20Sopenharmony_ci		.duty		= PWMV1_CDTY,
3748c2ecf20Sopenharmony_ci		.duty_upd	= PWMV1_CUPD,
3758c2ecf20Sopenharmony_ci	},
3768c2ecf20Sopenharmony_ci	.cfg = {
3778c2ecf20Sopenharmony_ci		/* 32 bits to keep period and duty. */
3788c2ecf20Sopenharmony_ci		.period_bits	= 32,
3798c2ecf20Sopenharmony_ci	},
3808c2ecf20Sopenharmony_ci};
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_cistatic const struct of_device_id atmel_pwm_dt_ids[] = {
3838c2ecf20Sopenharmony_ci	{
3848c2ecf20Sopenharmony_ci		.compatible = "atmel,at91sam9rl-pwm",
3858c2ecf20Sopenharmony_ci		.data = &atmel_sam9rl_pwm_data,
3868c2ecf20Sopenharmony_ci	}, {
3878c2ecf20Sopenharmony_ci		.compatible = "atmel,sama5d3-pwm",
3888c2ecf20Sopenharmony_ci		.data = &atmel_sama5_pwm_data,
3898c2ecf20Sopenharmony_ci	}, {
3908c2ecf20Sopenharmony_ci		.compatible = "atmel,sama5d2-pwm",
3918c2ecf20Sopenharmony_ci		.data = &atmel_sama5_pwm_data,
3928c2ecf20Sopenharmony_ci	}, {
3938c2ecf20Sopenharmony_ci		.compatible = "microchip,sam9x60-pwm",
3948c2ecf20Sopenharmony_ci		.data = &mchp_sam9x60_pwm_data,
3958c2ecf20Sopenharmony_ci	}, {
3968c2ecf20Sopenharmony_ci		/* sentinel */
3978c2ecf20Sopenharmony_ci	},
3988c2ecf20Sopenharmony_ci};
3998c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_cistatic int atmel_pwm_probe(struct platform_device *pdev)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	struct atmel_pwm_chip *atmel_pwm;
4048c2ecf20Sopenharmony_ci	struct resource *res;
4058c2ecf20Sopenharmony_ci	int ret;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	atmel_pwm = devm_kzalloc(&pdev->dev, sizeof(*atmel_pwm), GFP_KERNEL);
4088c2ecf20Sopenharmony_ci	if (!atmel_pwm)
4098c2ecf20Sopenharmony_ci		return -ENOMEM;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	mutex_init(&atmel_pwm->isr_lock);
4128c2ecf20Sopenharmony_ci	atmel_pwm->data = of_device_get_match_data(&pdev->dev);
4138c2ecf20Sopenharmony_ci	atmel_pwm->updated_pwms = 0;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
4168c2ecf20Sopenharmony_ci	atmel_pwm->base = devm_ioremap_resource(&pdev->dev, res);
4178c2ecf20Sopenharmony_ci	if (IS_ERR(atmel_pwm->base))
4188c2ecf20Sopenharmony_ci		return PTR_ERR(atmel_pwm->base);
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	atmel_pwm->clk = devm_clk_get(&pdev->dev, NULL);
4218c2ecf20Sopenharmony_ci	if (IS_ERR(atmel_pwm->clk))
4228c2ecf20Sopenharmony_ci		return PTR_ERR(atmel_pwm->clk);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	ret = clk_prepare(atmel_pwm->clk);
4258c2ecf20Sopenharmony_ci	if (ret) {
4268c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to prepare PWM clock\n");
4278c2ecf20Sopenharmony_ci		return ret;
4288c2ecf20Sopenharmony_ci	}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	atmel_pwm->chip.dev = &pdev->dev;
4318c2ecf20Sopenharmony_ci	atmel_pwm->chip.ops = &atmel_pwm_ops;
4328c2ecf20Sopenharmony_ci	atmel_pwm->chip.of_xlate = of_pwm_xlate_with_flags;
4338c2ecf20Sopenharmony_ci	atmel_pwm->chip.of_pwm_n_cells = 3;
4348c2ecf20Sopenharmony_ci	atmel_pwm->chip.base = -1;
4358c2ecf20Sopenharmony_ci	atmel_pwm->chip.npwm = 4;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	ret = pwmchip_add(&atmel_pwm->chip);
4388c2ecf20Sopenharmony_ci	if (ret < 0) {
4398c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to add PWM chip %d\n", ret);
4408c2ecf20Sopenharmony_ci		goto unprepare_clk;
4418c2ecf20Sopenharmony_ci	}
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, atmel_pwm);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	return ret;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ciunprepare_clk:
4488c2ecf20Sopenharmony_ci	clk_unprepare(atmel_pwm->clk);
4498c2ecf20Sopenharmony_ci	return ret;
4508c2ecf20Sopenharmony_ci}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_cistatic int atmel_pwm_remove(struct platform_device *pdev)
4538c2ecf20Sopenharmony_ci{
4548c2ecf20Sopenharmony_ci	struct atmel_pwm_chip *atmel_pwm = platform_get_drvdata(pdev);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	clk_unprepare(atmel_pwm->clk);
4578c2ecf20Sopenharmony_ci	mutex_destroy(&atmel_pwm->isr_lock);
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	return pwmchip_remove(&atmel_pwm->chip);
4608c2ecf20Sopenharmony_ci}
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_cistatic struct platform_driver atmel_pwm_driver = {
4638c2ecf20Sopenharmony_ci	.driver = {
4648c2ecf20Sopenharmony_ci		.name = "atmel-pwm",
4658c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(atmel_pwm_dt_ids),
4668c2ecf20Sopenharmony_ci	},
4678c2ecf20Sopenharmony_ci	.probe = atmel_pwm_probe,
4688c2ecf20Sopenharmony_ci	.remove = atmel_pwm_remove,
4698c2ecf20Sopenharmony_ci};
4708c2ecf20Sopenharmony_cimodule_platform_driver(atmel_pwm_driver);
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:atmel-pwm");
4738c2ecf20Sopenharmony_ciMODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
4748c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Atmel PWM driver");
4758c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
476