18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * drivers/pwm/pwm-tegra.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Tegra pulse-width-modulation controller driver 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2010-2020, NVIDIA Corporation. 88c2ecf20Sopenharmony_ci * Based on arch/arm/plat-mxc/pwm.c by Sascha Hauer <s.hauer@pengutronix.de> 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Overview of Tegra Pulse Width Modulator Register: 118c2ecf20Sopenharmony_ci * 1. 13-bit: Frequency division (SCALE) 128c2ecf20Sopenharmony_ci * 2. 8-bit : Pulse division (DUTY) 138c2ecf20Sopenharmony_ci * 3. 1-bit : Enable bit 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * The PWM clock frequency is divided by 256 before subdividing it based 168c2ecf20Sopenharmony_ci * on the programmable frequency division value to generate the required 178c2ecf20Sopenharmony_ci * frequency for PWM output. The maximum output frequency that can be 188c2ecf20Sopenharmony_ci * achieved is (max rate of source clock) / 256. 198c2ecf20Sopenharmony_ci * e.g. if source clock rate is 408 MHz, maximum output frequency can be: 208c2ecf20Sopenharmony_ci * 408 MHz/256 = 1.6 MHz. 218c2ecf20Sopenharmony_ci * This 1.6 MHz frequency can further be divided using SCALE value in PWM. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * PWM pulse width: 8 bits are usable [23:16] for varying pulse width. 248c2ecf20Sopenharmony_ci * To achieve 100% duty cycle, program Bit [24] of this register to 258c2ecf20Sopenharmony_ci * 1’b1. In which case the other bits [23:16] are set to don't care. 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * Limitations: 288c2ecf20Sopenharmony_ci * - When PWM is disabled, the output is driven to inactive. 298c2ecf20Sopenharmony_ci * - It does not allow the current PWM period to complete and 308c2ecf20Sopenharmony_ci * stops abruptly. 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * - If the register is reconfigured while PWM is running, 338c2ecf20Sopenharmony_ci * it does not complete the currently running period. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * - If the user input duty is beyond acceptible limits, 368c2ecf20Sopenharmony_ci * -EINVAL is returned. 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#include <linux/clk.h> 408c2ecf20Sopenharmony_ci#include <linux/err.h> 418c2ecf20Sopenharmony_ci#include <linux/io.h> 428c2ecf20Sopenharmony_ci#include <linux/module.h> 438c2ecf20Sopenharmony_ci#include <linux/of.h> 448c2ecf20Sopenharmony_ci#include <linux/of_device.h> 458c2ecf20Sopenharmony_ci#include <linux/pwm.h> 468c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 478c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h> 488c2ecf20Sopenharmony_ci#include <linux/slab.h> 498c2ecf20Sopenharmony_ci#include <linux/reset.h> 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define PWM_ENABLE (1 << 31) 528c2ecf20Sopenharmony_ci#define PWM_DUTY_WIDTH 8 538c2ecf20Sopenharmony_ci#define PWM_DUTY_SHIFT 16 548c2ecf20Sopenharmony_ci#define PWM_SCALE_WIDTH 13 558c2ecf20Sopenharmony_ci#define PWM_SCALE_SHIFT 0 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistruct tegra_pwm_soc { 588c2ecf20Sopenharmony_ci unsigned int num_channels; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* Maximum IP frequency for given SoCs */ 618c2ecf20Sopenharmony_ci unsigned long max_frequency; 628c2ecf20Sopenharmony_ci}; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistruct tegra_pwm_chip { 658c2ecf20Sopenharmony_ci struct pwm_chip chip; 668c2ecf20Sopenharmony_ci struct device *dev; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci struct clk *clk; 698c2ecf20Sopenharmony_ci struct reset_control*rst; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci unsigned long clk_rate; 728c2ecf20Sopenharmony_ci unsigned long min_period_ns; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci void __iomem *regs; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci const struct tegra_pwm_soc *soc; 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci return container_of(chip, struct tegra_pwm_chip, chip); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic inline u32 pwm_readl(struct tegra_pwm_chip *chip, unsigned int num) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci return readl(chip->regs + (num << 4)); 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic inline void pwm_writel(struct tegra_pwm_chip *chip, unsigned int num, 908c2ecf20Sopenharmony_ci unsigned long val) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci writel(val, chip->regs + (num << 4)); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 968c2ecf20Sopenharmony_ci int duty_ns, int period_ns) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); 998c2ecf20Sopenharmony_ci unsigned long long c = duty_ns, hz; 1008c2ecf20Sopenharmony_ci unsigned long rate, required_clk_rate; 1018c2ecf20Sopenharmony_ci u32 val = 0; 1028c2ecf20Sopenharmony_ci int err; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* 1058c2ecf20Sopenharmony_ci * Convert from duty_ns / period_ns to a fixed number of duty ticks 1068c2ecf20Sopenharmony_ci * per (1 << PWM_DUTY_WIDTH) cycles and make sure to round to the 1078c2ecf20Sopenharmony_ci * nearest integer during division. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci c *= (1 << PWM_DUTY_WIDTH); 1108c2ecf20Sopenharmony_ci c = DIV_ROUND_CLOSEST_ULL(c, period_ns); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci val = (u32)c << PWM_DUTY_SHIFT; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* 1158c2ecf20Sopenharmony_ci * min period = max clock limit >> PWM_DUTY_WIDTH 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_ci if (period_ns < pc->min_period_ns) 1188c2ecf20Sopenharmony_ci return -EINVAL; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* 1218c2ecf20Sopenharmony_ci * Compute the prescaler value for which (1 << PWM_DUTY_WIDTH) 1228c2ecf20Sopenharmony_ci * cycles at the PWM clock rate will take period_ns nanoseconds. 1238c2ecf20Sopenharmony_ci * 1248c2ecf20Sopenharmony_ci * num_channels: If single instance of PWM controller has multiple 1258c2ecf20Sopenharmony_ci * channels (e.g. Tegra210 or older) then it is not possible to 1268c2ecf20Sopenharmony_ci * configure separate clock rates to each of the channels, in such 1278c2ecf20Sopenharmony_ci * case the value stored during probe will be referred. 1288c2ecf20Sopenharmony_ci * 1298c2ecf20Sopenharmony_ci * If every PWM controller instance has one channel respectively, i.e. 1308c2ecf20Sopenharmony_ci * nums_channels == 1 then only the clock rate can be modified 1318c2ecf20Sopenharmony_ci * dynamically (e.g. Tegra186 or Tegra194). 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_ci if (pc->soc->num_channels == 1) { 1348c2ecf20Sopenharmony_ci /* 1358c2ecf20Sopenharmony_ci * Rate is multiplied with 2^PWM_DUTY_WIDTH so that it matches 1368c2ecf20Sopenharmony_ci * with the maximum possible rate that the controller can 1378c2ecf20Sopenharmony_ci * provide. Any further lower value can be derived by setting 1388c2ecf20Sopenharmony_ci * PFM bits[0:12]. 1398c2ecf20Sopenharmony_ci * 1408c2ecf20Sopenharmony_ci * required_clk_rate is a reference rate for source clock and 1418c2ecf20Sopenharmony_ci * it is derived based on user requested period. By setting the 1428c2ecf20Sopenharmony_ci * source clock rate as required_clk_rate, PWM controller will 1438c2ecf20Sopenharmony_ci * be able to configure the requested period. 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_ci required_clk_rate = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC << PWM_DUTY_WIDTH, 1468c2ecf20Sopenharmony_ci period_ns); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci err = clk_set_rate(pc->clk, required_clk_rate); 1498c2ecf20Sopenharmony_ci if (err < 0) 1508c2ecf20Sopenharmony_ci return -EINVAL; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci /* Store the new rate for further references */ 1538c2ecf20Sopenharmony_ci pc->clk_rate = clk_get_rate(pc->clk); 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci rate = pc->clk_rate >> PWM_DUTY_WIDTH; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* Consider precision in PWM_SCALE_WIDTH rate calculation */ 1598c2ecf20Sopenharmony_ci hz = DIV_ROUND_CLOSEST_ULL(100ULL * NSEC_PER_SEC, period_ns); 1608c2ecf20Sopenharmony_ci rate = DIV_ROUND_CLOSEST_ULL(100ULL * rate, hz); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci /* 1638c2ecf20Sopenharmony_ci * Since the actual PWM divider is the register's frequency divider 1648c2ecf20Sopenharmony_ci * field plus 1, we need to decrement to get the correct value to 1658c2ecf20Sopenharmony_ci * write to the register. 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci if (rate > 0) 1688c2ecf20Sopenharmony_ci rate--; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci /* 1718c2ecf20Sopenharmony_ci * Make sure that the rate will fit in the register's frequency 1728c2ecf20Sopenharmony_ci * divider field. 1738c2ecf20Sopenharmony_ci */ 1748c2ecf20Sopenharmony_ci if (rate >> PWM_SCALE_WIDTH) 1758c2ecf20Sopenharmony_ci return -EINVAL; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci val |= rate << PWM_SCALE_SHIFT; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* 1808c2ecf20Sopenharmony_ci * If the PWM channel is disabled, make sure to turn on the clock 1818c2ecf20Sopenharmony_ci * before writing the register. Otherwise, keep it enabled. 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_ci if (!pwm_is_enabled(pwm)) { 1848c2ecf20Sopenharmony_ci err = clk_prepare_enable(pc->clk); 1858c2ecf20Sopenharmony_ci if (err < 0) 1868c2ecf20Sopenharmony_ci return err; 1878c2ecf20Sopenharmony_ci } else 1888c2ecf20Sopenharmony_ci val |= PWM_ENABLE; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci pwm_writel(pc, pwm->hwpwm, val); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* 1938c2ecf20Sopenharmony_ci * If the PWM is not enabled, turn the clock off again to save power. 1948c2ecf20Sopenharmony_ci */ 1958c2ecf20Sopenharmony_ci if (!pwm_is_enabled(pwm)) 1968c2ecf20Sopenharmony_ci clk_disable_unprepare(pc->clk); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci return 0; 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic int tegra_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); 2048c2ecf20Sopenharmony_ci int rc = 0; 2058c2ecf20Sopenharmony_ci u32 val; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci rc = clk_prepare_enable(pc->clk); 2088c2ecf20Sopenharmony_ci if (rc < 0) 2098c2ecf20Sopenharmony_ci return rc; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci val = pwm_readl(pc, pwm->hwpwm); 2128c2ecf20Sopenharmony_ci val |= PWM_ENABLE; 2138c2ecf20Sopenharmony_ci pwm_writel(pc, pwm->hwpwm, val); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci return 0; 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); 2218c2ecf20Sopenharmony_ci u32 val; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci val = pwm_readl(pc, pwm->hwpwm); 2248c2ecf20Sopenharmony_ci val &= ~PWM_ENABLE; 2258c2ecf20Sopenharmony_ci pwm_writel(pc, pwm->hwpwm, val); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci clk_disable_unprepare(pc->clk); 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic const struct pwm_ops tegra_pwm_ops = { 2318c2ecf20Sopenharmony_ci .config = tegra_pwm_config, 2328c2ecf20Sopenharmony_ci .enable = tegra_pwm_enable, 2338c2ecf20Sopenharmony_ci .disable = tegra_pwm_disable, 2348c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2358c2ecf20Sopenharmony_ci}; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic int tegra_pwm_probe(struct platform_device *pdev) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci struct tegra_pwm_chip *pwm; 2408c2ecf20Sopenharmony_ci struct resource *r; 2418c2ecf20Sopenharmony_ci int ret; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); 2448c2ecf20Sopenharmony_ci if (!pwm) 2458c2ecf20Sopenharmony_ci return -ENOMEM; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci pwm->soc = of_device_get_match_data(&pdev->dev); 2488c2ecf20Sopenharmony_ci pwm->dev = &pdev->dev; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2518c2ecf20Sopenharmony_ci pwm->regs = devm_ioremap_resource(&pdev->dev, r); 2528c2ecf20Sopenharmony_ci if (IS_ERR(pwm->regs)) 2538c2ecf20Sopenharmony_ci return PTR_ERR(pwm->regs); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, pwm); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci pwm->clk = devm_clk_get(&pdev->dev, NULL); 2588c2ecf20Sopenharmony_ci if (IS_ERR(pwm->clk)) 2598c2ecf20Sopenharmony_ci return PTR_ERR(pwm->clk); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* Set maximum frequency of the IP */ 2628c2ecf20Sopenharmony_ci ret = clk_set_rate(pwm->clk, pwm->soc->max_frequency); 2638c2ecf20Sopenharmony_ci if (ret < 0) { 2648c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to set max frequency: %d\n", ret); 2658c2ecf20Sopenharmony_ci return ret; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* 2698c2ecf20Sopenharmony_ci * The requested and configured frequency may differ due to 2708c2ecf20Sopenharmony_ci * clock register resolutions. Get the configured frequency 2718c2ecf20Sopenharmony_ci * so that PWM period can be calculated more accurately. 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_ci pwm->clk_rate = clk_get_rate(pwm->clk); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /* Set minimum limit of PWM period for the IP */ 2768c2ecf20Sopenharmony_ci pwm->min_period_ns = 2778c2ecf20Sopenharmony_ci (NSEC_PER_SEC / (pwm->soc->max_frequency >> PWM_DUTY_WIDTH)) + 1; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci pwm->rst = devm_reset_control_get_exclusive(&pdev->dev, "pwm"); 2808c2ecf20Sopenharmony_ci if (IS_ERR(pwm->rst)) { 2818c2ecf20Sopenharmony_ci ret = PTR_ERR(pwm->rst); 2828c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Reset control is not found: %d\n", ret); 2838c2ecf20Sopenharmony_ci return ret; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci reset_control_deassert(pwm->rst); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci pwm->chip.dev = &pdev->dev; 2898c2ecf20Sopenharmony_ci pwm->chip.ops = &tegra_pwm_ops; 2908c2ecf20Sopenharmony_ci pwm->chip.base = -1; 2918c2ecf20Sopenharmony_ci pwm->chip.npwm = pwm->soc->num_channels; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci ret = pwmchip_add(&pwm->chip); 2948c2ecf20Sopenharmony_ci if (ret < 0) { 2958c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); 2968c2ecf20Sopenharmony_ci reset_control_assert(pwm->rst); 2978c2ecf20Sopenharmony_ci return ret; 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci return 0; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic int tegra_pwm_remove(struct platform_device *pdev) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci struct tegra_pwm_chip *pc = platform_get_drvdata(pdev); 3068c2ecf20Sopenharmony_ci int err; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (WARN_ON(!pc)) 3098c2ecf20Sopenharmony_ci return -ENODEV; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci err = clk_prepare_enable(pc->clk); 3128c2ecf20Sopenharmony_ci if (err < 0) 3138c2ecf20Sopenharmony_ci return err; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci reset_control_assert(pc->rst); 3168c2ecf20Sopenharmony_ci clk_disable_unprepare(pc->clk); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci return pwmchip_remove(&pc->chip); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 3228c2ecf20Sopenharmony_cistatic int tegra_pwm_suspend(struct device *dev) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci return pinctrl_pm_select_sleep_state(dev); 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic int tegra_pwm_resume(struct device *dev) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci return pinctrl_pm_select_default_state(dev); 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci#endif 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic const struct tegra_pwm_soc tegra20_pwm_soc = { 3348c2ecf20Sopenharmony_ci .num_channels = 4, 3358c2ecf20Sopenharmony_ci .max_frequency = 48000000UL, 3368c2ecf20Sopenharmony_ci}; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_cistatic const struct tegra_pwm_soc tegra186_pwm_soc = { 3398c2ecf20Sopenharmony_ci .num_channels = 1, 3408c2ecf20Sopenharmony_ci .max_frequency = 102000000UL, 3418c2ecf20Sopenharmony_ci}; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_cistatic const struct tegra_pwm_soc tegra194_pwm_soc = { 3448c2ecf20Sopenharmony_ci .num_channels = 1, 3458c2ecf20Sopenharmony_ci .max_frequency = 408000000UL, 3468c2ecf20Sopenharmony_ci}; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic const struct of_device_id tegra_pwm_of_match[] = { 3498c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra20-pwm", .data = &tegra20_pwm_soc }, 3508c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc }, 3518c2ecf20Sopenharmony_ci { .compatible = "nvidia,tegra194-pwm", .data = &tegra194_pwm_soc }, 3528c2ecf20Sopenharmony_ci { } 3538c2ecf20Sopenharmony_ci}; 3548c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, tegra_pwm_of_match); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic const struct dev_pm_ops tegra_pwm_pm_ops = { 3578c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(tegra_pwm_suspend, tegra_pwm_resume) 3588c2ecf20Sopenharmony_ci}; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic struct platform_driver tegra_pwm_driver = { 3618c2ecf20Sopenharmony_ci .driver = { 3628c2ecf20Sopenharmony_ci .name = "tegra-pwm", 3638c2ecf20Sopenharmony_ci .of_match_table = tegra_pwm_of_match, 3648c2ecf20Sopenharmony_ci .pm = &tegra_pwm_pm_ops, 3658c2ecf20Sopenharmony_ci }, 3668c2ecf20Sopenharmony_ci .probe = tegra_pwm_probe, 3678c2ecf20Sopenharmony_ci .remove = tegra_pwm_remove, 3688c2ecf20Sopenharmony_ci}; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cimodule_platform_driver(tegra_pwm_driver); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 3738c2ecf20Sopenharmony_ciMODULE_AUTHOR("Sandipan Patra <spatra@nvidia.com>"); 3748c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Tegra PWM controller driver"); 3758c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:tegra-pwm"); 376