[go: nahoru, domu]

19421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON/*
29421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON * Copyright (C) Overkiz SAS 2012
39421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON *
49421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON * Author: Boris BREZILLON <b.brezillon@overkiz.com>
59421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON * License terms: GNU General Public License (GPL) version 2
69421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON */
79421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
89421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/module.h>
99421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/init.h>
109421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/clocksource.h>
119421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/clockchips.h>
129421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/interrupt.h>
139421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/irq.h>
149421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
159421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/clk.h>
169421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/err.h>
179421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/ioport.h>
189421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/io.h>
199421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/platform_device.h>
209421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/atmel_tc.h>
219421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/pwm.h>
229421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/of_device.h>
239421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#include <linux/slab.h>
249421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
259421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#define NPWM	6
269421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
279421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#define ATMEL_TC_ACMR_MASK	(ATMEL_TC_ACPA | ATMEL_TC_ACPC |	\
289421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				 ATMEL_TC_AEEVT | ATMEL_TC_ASWTRG)
299421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
309421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON#define ATMEL_TC_BCMR_MASK	(ATMEL_TC_BCPB | ATMEL_TC_BCPC |	\
319421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				 ATMEL_TC_BEEVT | ATMEL_TC_BSWTRG)
329421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
339421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstruct atmel_tcb_pwm_device {
349421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	enum pwm_polarity polarity;	/* PWM polarity */
359421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned div;			/* PWM clock divider */
369421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned duty;			/* PWM duty expressed in clk cycles */
379421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned period;		/* PWM period expressed in clk cycles */
389421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON};
399421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
409421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstruct atmel_tcb_pwm_chip {
419421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct pwm_chip chip;
429421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	spinlock_t lock;
439421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tc *tc;
449421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_device *pwms[NPWM];
459421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON};
469421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
479421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic inline struct atmel_tcb_pwm_chip *to_tcb_chip(struct pwm_chip *chip)
489421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON{
499421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	return container_of(chip, struct atmel_tcb_pwm_chip, chip);
509421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON}
519421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
529421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic int atmel_tcb_pwm_set_polarity(struct pwm_chip *chip,
539421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				      struct pwm_device *pwm,
549421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				      enum pwm_polarity polarity)
559421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON{
569421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm);
579421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
589421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->polarity = polarity;
599421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
609421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	return 0;
619421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON}
629421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
639421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic int atmel_tcb_pwm_request(struct pwm_chip *chip,
649421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				 struct pwm_device *pwm)
659421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON{
669421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
679421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_device *tcbpwm;
689421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tc *tc = tcbpwmc->tc;
699421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	void __iomem *regs = tc->regs;
709421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned group = pwm->hwpwm / 2;
719421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned index = pwm->hwpwm % 2;
729421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned cmr;
739421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	int ret;
749421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
759421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm = devm_kzalloc(chip->dev, sizeof(*tcbpwm), GFP_KERNEL);
769421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (!tcbpwm)
779421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		return -ENOMEM;
789421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
798796f9c5656dedd186eda88c07db6a58d1985938Boris BREZILLON	ret = clk_prepare_enable(tc->clk[group]);
809421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (ret) {
819421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		devm_kfree(chip->dev, tcbpwm);
829421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		return ret;
839421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
849421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
859421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	pwm_set_chip_data(pwm, tcbpwm);
869421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->polarity = PWM_POLARITY_NORMAL;
879421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->duty = 0;
889421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->period = 0;
899421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->div = 0;
909421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
919421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	spin_lock(&tcbpwmc->lock);
929421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	cmr = __raw_readl(regs + ATMEL_TC_REG(group, CMR));
939421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/*
949421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * Get init config from Timer Counter registers if
959421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * Timer Counter is already configured as a PWM generator.
969421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 */
979421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (cmr & ATMEL_TC_WAVE) {
989421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		if (index == 0)
999421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			tcbpwm->duty =
1009421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				__raw_readl(regs + ATMEL_TC_REG(group, RA));
1019421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		else
1029421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			tcbpwm->duty =
1039421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				__raw_readl(regs + ATMEL_TC_REG(group, RB));
1049421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1059421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		tcbpwm->div = cmr & ATMEL_TC_TCCLKS;
1069421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		tcbpwm->period = __raw_readl(regs + ATMEL_TC_REG(group, RC));
1079421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		cmr &= (ATMEL_TC_TCCLKS | ATMEL_TC_ACMR_MASK |
1089421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			ATMEL_TC_BCMR_MASK);
1099421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	} else
1109421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		cmr = 0;
1119421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1129421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	cmr |= ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO | ATMEL_TC_EEVT_XC0;
1139421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	__raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR));
1149421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	spin_unlock(&tcbpwmc->lock);
1159421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1169421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwmc->pwms[pwm->hwpwm] = tcbpwm;
1179421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1189421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	return 0;
1199421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON}
1209421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1219421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic void atmel_tcb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
1229421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON{
1239421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
1249421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm);
1259421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tc *tc = tcbpwmc->tc;
1269421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1278796f9c5656dedd186eda88c07db6a58d1985938Boris BREZILLON	clk_disable_unprepare(tc->clk[pwm->hwpwm / 2]);
1289421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwmc->pwms[pwm->hwpwm] = NULL;
1299421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	devm_kfree(chip->dev, tcbpwm);
1309421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON}
1319421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1329421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
1339421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON{
1349421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
1359421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm);
1369421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tc *tc = tcbpwmc->tc;
1379421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	void __iomem *regs = tc->regs;
1389421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned group = pwm->hwpwm / 2;
1399421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned index = pwm->hwpwm % 2;
1409421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned cmr;
1419421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	enum pwm_polarity polarity = tcbpwm->polarity;
1429421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1439421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/*
1449421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * If duty is 0 the timer will be stopped and we have to
1459421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * configure the output correctly on software trigger:
1469421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 *  - set output to high if PWM_POLARITY_INVERSED
1479421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 *  - set output to low if PWM_POLARITY_NORMAL
1489421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 *
1499421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * This is why we're reverting polarity in this case.
1509421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 */
1519421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (tcbpwm->duty == 0)
1529421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		polarity = !polarity;
1539421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1549421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	spin_lock(&tcbpwmc->lock);
1559421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	cmr = __raw_readl(regs + ATMEL_TC_REG(group, CMR));
1569421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1579421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/* flush old setting and set the new one */
1589421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (index == 0) {
1599421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		cmr &= ~ATMEL_TC_ACMR_MASK;
1609421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		if (polarity == PWM_POLARITY_INVERSED)
1619421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			cmr |= ATMEL_TC_ASWTRG_CLEAR;
1629421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		else
1639421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			cmr |= ATMEL_TC_ASWTRG_SET;
1649421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	} else {
1659421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		cmr &= ~ATMEL_TC_BCMR_MASK;
1669421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		if (polarity == PWM_POLARITY_INVERSED)
1679421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			cmr |= ATMEL_TC_BSWTRG_CLEAR;
1689421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		else
1699421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			cmr |= ATMEL_TC_BSWTRG_SET;
1709421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
1719421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1729421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	__raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR));
1739421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1749421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/*
1759421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * Use software trigger to apply the new setting.
1769421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * If both PWM devices in this group are disabled we stop the clock.
1779421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 */
1789421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (!(cmr & (ATMEL_TC_ACPC | ATMEL_TC_BCPC)))
1799421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		__raw_writel(ATMEL_TC_SWTRG | ATMEL_TC_CLKDIS,
1809421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			     regs + ATMEL_TC_REG(group, CCR));
1819421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	else
1829421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		__raw_writel(ATMEL_TC_SWTRG, regs +
1839421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			     ATMEL_TC_REG(group, CCR));
1849421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1859421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	spin_unlock(&tcbpwmc->lock);
1869421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON}
1879421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1889421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
1899421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON{
1909421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
1919421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm);
1929421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tc *tc = tcbpwmc->tc;
1939421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	void __iomem *regs = tc->regs;
1949421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned group = pwm->hwpwm / 2;
1959421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned index = pwm->hwpwm % 2;
1969421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	u32 cmr;
1979421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	enum pwm_polarity polarity = tcbpwm->polarity;
1989421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
1999421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/*
2009421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * If duty is 0 the timer will be stopped and we have to
2019421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * configure the output correctly on software trigger:
2029421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 *  - set output to high if PWM_POLARITY_INVERSED
2039421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 *  - set output to low if PWM_POLARITY_NORMAL
2049421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 *
2059421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * This is why we're reverting polarity in this case.
2069421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 */
2079421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (tcbpwm->duty == 0)
2089421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		polarity = !polarity;
2099421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
2109421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	spin_lock(&tcbpwmc->lock);
2119421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	cmr = __raw_readl(regs + ATMEL_TC_REG(group, CMR));
2129421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
2139421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/* flush old setting and set the new one */
2149421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	cmr &= ~ATMEL_TC_TCCLKS;
2159421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
2169421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (index == 0) {
2179421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		cmr &= ~ATMEL_TC_ACMR_MASK;
2189421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
2199421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		/* Set CMR flags according to given polarity */
2209421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		if (polarity == PWM_POLARITY_INVERSED)
2219421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			cmr |= ATMEL_TC_ASWTRG_CLEAR;
2229421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		else
2239421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			cmr |= ATMEL_TC_ASWTRG_SET;
2249421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	} else {
2259421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		cmr &= ~ATMEL_TC_BCMR_MASK;
2269421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		if (polarity == PWM_POLARITY_INVERSED)
2279421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			cmr |= ATMEL_TC_BSWTRG_CLEAR;
2289421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		else
2299421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			cmr |= ATMEL_TC_BSWTRG_SET;
2309421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
2319421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
2329421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/*
2339421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * If duty is 0 or equal to period there's no need to register
2349421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * a specific action on RA/RB and RC compare.
2359421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * The output will be configured on software trigger and keep
2369421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * this config till next config call.
2379421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 */
2389421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (tcbpwm->duty != tcbpwm->period && tcbpwm->duty > 0) {
2399421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		if (index == 0) {
2409421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			if (polarity == PWM_POLARITY_INVERSED)
2419421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				cmr |= ATMEL_TC_ACPA_SET | ATMEL_TC_ACPC_CLEAR;
2429421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			else
2439421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				cmr |= ATMEL_TC_ACPA_CLEAR | ATMEL_TC_ACPC_SET;
2449421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		} else {
2459421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			if (polarity == PWM_POLARITY_INVERSED)
2469421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				cmr |= ATMEL_TC_BCPB_SET | ATMEL_TC_BCPC_CLEAR;
2479421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			else
2489421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				cmr |= ATMEL_TC_BCPB_CLEAR | ATMEL_TC_BCPC_SET;
2499421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		}
2509421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
2519421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
252f3a82170aef72bf57f03e5c154fc94fad54968b1Boris BREZILLON	cmr |= (tcbpwm->div & ATMEL_TC_TCCLKS);
253f3a82170aef72bf57f03e5c154fc94fad54968b1Boris BREZILLON
2549421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	__raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR));
2559421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
2569421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (index == 0)
2579421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		__raw_writel(tcbpwm->duty, regs + ATMEL_TC_REG(group, RA));
2589421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	else
2599421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		__raw_writel(tcbpwm->duty, regs + ATMEL_TC_REG(group, RB));
2609421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
2619421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	__raw_writel(tcbpwm->period, regs + ATMEL_TC_REG(group, RC));
2629421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
2639421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/* Use software trigger to apply the new setting */
2649421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	__raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
2659421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		     regs + ATMEL_TC_REG(group, CCR));
2669421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	spin_unlock(&tcbpwmc->lock);
2679421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	return 0;
2689421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON}
2699421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
2709421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
2719421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON				int duty_ns, int period_ns)
2729421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON{
2739421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip);
2749421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm);
2759421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned group = pwm->hwpwm / 2;
2769421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned index = pwm->hwpwm % 2;
2779421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_device *atcbpwm = NULL;
2789421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tc *tc = tcbpwmc->tc;
2799421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	int i;
2809421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	int slowclk = 0;
2819421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned period;
2829421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned duty;
2839421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned rate = clk_get_rate(tc->clk[group]);
2849421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned long long min;
2859421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	unsigned long long max;
2869421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
2879421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/*
2889421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * Find best clk divisor:
2899421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * the smallest divisor which can fulfill the period_ns requirements.
2909421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 */
2919421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	for (i = 0; i < 5; ++i) {
2929421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		if (atmel_tc_divisors[i] == 0) {
2939421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			slowclk = i;
2949421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			continue;
2959421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		}
2969421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		min = div_u64((u64)NSEC_PER_SEC * atmel_tc_divisors[i], rate);
2979421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		max = min << tc->tcb_config->counter_width;
2989421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		if (max >= period_ns)
2999421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			break;
3009421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
3019421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3029421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/*
3039421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * If none of the divisor are small enough to represent period_ns
3049421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * take slow clock (32KHz).
3059421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 */
3069421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (i == 5) {
3079421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		i = slowclk;
3089421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		rate = 32768;
3099421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		min = div_u64(NSEC_PER_SEC, rate);
310ceb12f939809b3445d0b2118d4b07638bb07afa6Boris BREZILLON		max = min << tc->tcb_config->counter_width;
3119421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3129421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		/* If period is too big return ERANGE error */
3139421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		if (max < period_ns)
3149421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			return -ERANGE;
3159421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
3169421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3179421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	duty = div_u64(duty_ns, min);
3189421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	period = div_u64(period_ns, min);
3199421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3209421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (index == 0)
3219421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		atcbpwm = tcbpwmc->pwms[pwm->hwpwm + 1];
3229421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	else
3239421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		atcbpwm = tcbpwmc->pwms[pwm->hwpwm - 1];
3249421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3259421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/*
3269421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * PWM devices provided by TCB driver are grouped by 2:
3279421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * - group 0: PWM 0 & 1
3289421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * - group 1: PWM 2 & 3
3299421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * - group 2: PWM 4 & 5
3309421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 *
3319421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * PWM devices in a given group must be configured with the
3329421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * same period_ns.
3339421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 *
3349421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * We're checking the period value of the second PWM device
3359421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 * in this group before applying the new config.
3369421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	 */
3379421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if ((atcbpwm && atcbpwm->duty > 0 &&
3389421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			atcbpwm->duty != atcbpwm->period) &&
3399421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		(atcbpwm->div != i || atcbpwm->period != period)) {
3409421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		dev_err(chip->dev,
3419421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			"failed to configure period_ns: PWM group already configured with a different value\n");
3429421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		return -EINVAL;
3439421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
3449421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3459421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->period = period;
3469421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->div = i;
3479421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->duty = duty;
3489421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3499421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	/* If the PWM is enabled, call enable to apply the new conf */
3509421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (test_bit(PWMF_ENABLED, &pwm->flags))
3519421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		atmel_tcb_pwm_enable(chip, pwm);
3529421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3539421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	return 0;
3549421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON}
3559421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3569421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic const struct pwm_ops atmel_tcb_pwm_ops = {
3579421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	.request = atmel_tcb_pwm_request,
3589421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	.free = atmel_tcb_pwm_free,
3599421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	.config = atmel_tcb_pwm_config,
3609421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	.set_polarity = atmel_tcb_pwm_set_polarity,
3619421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	.enable = atmel_tcb_pwm_enable,
3629421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	.disable = atmel_tcb_pwm_disable,
36383c80dc5358270a665666ea5b9ddd24351d86354Axel Lin	.owner = THIS_MODULE,
3649421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON};
3659421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3669421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic int atmel_tcb_pwm_probe(struct platform_device *pdev)
3679421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON{
3689421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_chip *tcbpwm;
3699421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct device_node *np = pdev->dev.of_node;
3709421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tc *tc;
3719421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	int err;
3729421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	int tcblock;
3739421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3749421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	err = of_property_read_u32(np, "tc-block", &tcblock);
3759421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (err < 0) {
3769421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		dev_err(&pdev->dev,
3779421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			"failed to get Timer Counter Block number from device tree (error: %d)\n",
3789421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON			err);
3799421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		return err;
3809421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
3819421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3824930d247af29f849cd1bddd65be2400684dc886eGaël PORTAY	tc = atmel_tc_alloc(tcblock);
3839421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (tc == NULL) {
3849421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		dev_err(&pdev->dev, "failed to allocate Timer Counter Block\n");
3859421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		return -ENOMEM;
3869421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
3879421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3889421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm = devm_kzalloc(&pdev->dev, sizeof(*tcbpwm), GFP_KERNEL);
3899421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (tcbpwm == NULL) {
3909421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		atmel_tc_free(tc);
3919421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		dev_err(&pdev->dev, "failed to allocate memory\n");
3929421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		return -ENOMEM;
3939421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
3949421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
3959421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->chip.dev = &pdev->dev;
3969421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->chip.ops = &atmel_tcb_pwm_ops;
3979421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->chip.of_xlate = of_pwm_xlate_with_flags;
3989421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->chip.of_pwm_n_cells = 3;
3999421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->chip.base = -1;
4009421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->chip.npwm = NPWM;
4019421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	tcbpwm->tc = tc;
4029421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4039421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	spin_lock_init(&tcbpwm->lock);
4049421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4059421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	err = pwmchip_add(&tcbpwm->chip);
4069421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (err < 0) {
4079421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		atmel_tc_free(tc);
4089421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		return err;
4099421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	}
4109421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4119421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	platform_set_drvdata(pdev, tcbpwm);
4129421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4139421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	return 0;
4149421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON}
4159421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4169421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic int atmel_tcb_pwm_remove(struct platform_device *pdev)
4179421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON{
4189421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
4199421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	int err;
4209421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4219421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	err = pwmchip_remove(&tcbpwm->chip);
4229421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	if (err < 0)
4239421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		return err;
4249421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4259421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	atmel_tc_free(tcbpwm->tc);
4269421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4279421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	return 0;
4289421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON}
4299421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4309421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic const struct of_device_id atmel_tcb_pwm_dt_ids[] = {
4319421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	{ .compatible = "atmel,tcb-pwm", },
4329421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	{ /* sentinel */ }
4339421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON};
4349421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONMODULE_DEVICE_TABLE(of, atmel_tcb_pwm_dt_ids);
4359421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4369421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONstatic struct platform_driver atmel_tcb_pwm_driver = {
4379421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	.driver = {
4389421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		.name = "atmel-tcb-pwm",
4393dd0a909479c1d372341d749b4ff94cd638b57daThierry Reding		.owner = THIS_MODULE,
4409421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON		.of_match_table = atmel_tcb_pwm_dt_ids,
4419421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	},
4429421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	.probe = atmel_tcb_pwm_probe,
4439421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON	.remove = atmel_tcb_pwm_remove,
4449421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON};
4459421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONmodule_platform_driver(atmel_tcb_pwm_driver);
4469421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLON
4479421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONMODULE_AUTHOR("Boris BREZILLON <b.brezillon@overkiz.com>");
4489421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONMODULE_DESCRIPTION("Atmel Timer Counter Pulse Width Modulation Driver");
4499421bade0765d8ffb86b8a99213b611278a3542aBoris BREZILLONMODULE_LICENSE("GPL v2");
450