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