1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * drivers/pwm/pwm-tegra.c 4 * 5 * Tegra pulse-width-modulation controller driver 6 * 7 * Copyright (c) 2010, NVIDIA Corporation. 8 * Based on arch/arm/plat-mxc/pwm.c by Sascha Hauer <s.hauer@pengutronix.de> 9 */ 10 11 #include <linux/clk.h> 12 #include <linux/err.h> 13 #include <linux/io.h> 14 #include <linux/module.h> 15 #include <linux/of.h> 16 #include <linux/of_device.h> 17 #include <linux/pwm.h> 18 #include <linux/platform_device.h> 19 #include <linux/pinctrl/consumer.h> 20 #include <linux/slab.h> 21 #include <linux/reset.h> 22 23 #define PWM_ENABLE (1 << 31) 24 #define PWM_DUTY_WIDTH 8 25 #define PWM_DUTY_SHIFT 16 26 #define PWM_SCALE_WIDTH 13 27 #define PWM_SCALE_SHIFT 0 28 29 struct tegra_pwm_soc { 30 unsigned int num_channels; 31 32 /* Maximum IP frequency for given SoCs */ 33 unsigned long max_frequency; 34 }; 35 36 struct tegra_pwm_chip { 37 struct pwm_chip chip; 38 struct device *dev; 39 40 struct clk *clk; 41 struct reset_control*rst; 42 43 unsigned long clk_rate; 44 45 void __iomem *regs; 46 47 const struct tegra_pwm_soc *soc; 48 }; 49 50 static inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip) 51 { 52 return container_of(chip, struct tegra_pwm_chip, chip); 53 } 54 55 static inline u32 pwm_readl(struct tegra_pwm_chip *chip, unsigned int num) 56 { 57 return readl(chip->regs + (num << 4)); 58 } 59 60 static inline void pwm_writel(struct tegra_pwm_chip *chip, unsigned int num, 61 unsigned long val) 62 { 63 writel(val, chip->regs + (num << 4)); 64 } 65 66 static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 67 int duty_ns, int period_ns) 68 { 69 struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); 70 unsigned long long c = duty_ns, hz; 71 unsigned long rate; 72 u32 val = 0; 73 int err; 74 75 /* 76 * Convert from duty_ns / period_ns to a fixed number of duty ticks 77 * per (1 << PWM_DUTY_WIDTH) cycles and make sure to round to the 78 * nearest integer during division. 79 */ 80 c *= (1 << PWM_DUTY_WIDTH); 81 c = DIV_ROUND_CLOSEST_ULL(c, period_ns); 82 83 val = (u32)c << PWM_DUTY_SHIFT; 84 85 /* 86 * Compute the prescaler value for which (1 << PWM_DUTY_WIDTH) 87 * cycles at the PWM clock rate will take period_ns nanoseconds. 88 */ 89 rate = pc->clk_rate >> PWM_DUTY_WIDTH; 90 91 /* Consider precision in PWM_SCALE_WIDTH rate calculation */ 92 hz = DIV_ROUND_CLOSEST_ULL(100ULL * NSEC_PER_SEC, period_ns); 93 rate = DIV_ROUND_CLOSEST_ULL(100ULL * rate, hz); 94 95 /* 96 * Since the actual PWM divider is the register's frequency divider 97 * field minus 1, we need to decrement to get the correct value to 98 * write to the register. 99 */ 100 if (rate > 0) 101 rate--; 102 103 /* 104 * Make sure that the rate will fit in the register's frequency 105 * divider field. 106 */ 107 if (rate >> PWM_SCALE_WIDTH) 108 return -EINVAL; 109 110 val |= rate << PWM_SCALE_SHIFT; 111 112 /* 113 * If the PWM channel is disabled, make sure to turn on the clock 114 * before writing the register. Otherwise, keep it enabled. 115 */ 116 if (!pwm_is_enabled(pwm)) { 117 err = clk_prepare_enable(pc->clk); 118 if (err < 0) 119 return err; 120 } else 121 val |= PWM_ENABLE; 122 123 pwm_writel(pc, pwm->hwpwm, val); 124 125 /* 126 * If the PWM is not enabled, turn the clock off again to save power. 127 */ 128 if (!pwm_is_enabled(pwm)) 129 clk_disable_unprepare(pc->clk); 130 131 return 0; 132 } 133 134 static int tegra_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 135 { 136 struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); 137 int rc = 0; 138 u32 val; 139 140 rc = clk_prepare_enable(pc->clk); 141 if (rc < 0) 142 return rc; 143 144 val = pwm_readl(pc, pwm->hwpwm); 145 val |= PWM_ENABLE; 146 pwm_writel(pc, pwm->hwpwm, val); 147 148 return 0; 149 } 150 151 static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 152 { 153 struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); 154 u32 val; 155 156 val = pwm_readl(pc, pwm->hwpwm); 157 val &= ~PWM_ENABLE; 158 pwm_writel(pc, pwm->hwpwm, val); 159 160 clk_disable_unprepare(pc->clk); 161 } 162 163 static const struct pwm_ops tegra_pwm_ops = { 164 .config = tegra_pwm_config, 165 .enable = tegra_pwm_enable, 166 .disable = tegra_pwm_disable, 167 .owner = THIS_MODULE, 168 }; 169 170 static int tegra_pwm_probe(struct platform_device *pdev) 171 { 172 struct tegra_pwm_chip *pwm; 173 struct resource *r; 174 int ret; 175 176 pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); 177 if (!pwm) 178 return -ENOMEM; 179 180 pwm->soc = of_device_get_match_data(&pdev->dev); 181 pwm->dev = &pdev->dev; 182 183 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 184 pwm->regs = devm_ioremap_resource(&pdev->dev, r); 185 if (IS_ERR(pwm->regs)) 186 return PTR_ERR(pwm->regs); 187 188 platform_set_drvdata(pdev, pwm); 189 190 pwm->clk = devm_clk_get(&pdev->dev, NULL); 191 if (IS_ERR(pwm->clk)) 192 return PTR_ERR(pwm->clk); 193 194 /* Set maximum frequency of the IP */ 195 ret = clk_set_rate(pwm->clk, pwm->soc->max_frequency); 196 if (ret < 0) { 197 dev_err(&pdev->dev, "Failed to set max frequency: %d\n", ret); 198 return ret; 199 } 200 201 /* 202 * The requested and configured frequency may differ due to 203 * clock register resolutions. Get the configured frequency 204 * so that PWM period can be calculated more accurately. 205 */ 206 pwm->clk_rate = clk_get_rate(pwm->clk); 207 208 pwm->rst = devm_reset_control_get_exclusive(&pdev->dev, "pwm"); 209 if (IS_ERR(pwm->rst)) { 210 ret = PTR_ERR(pwm->rst); 211 dev_err(&pdev->dev, "Reset control is not found: %d\n", ret); 212 return ret; 213 } 214 215 reset_control_deassert(pwm->rst); 216 217 pwm->chip.dev = &pdev->dev; 218 pwm->chip.ops = &tegra_pwm_ops; 219 pwm->chip.base = -1; 220 pwm->chip.npwm = pwm->soc->num_channels; 221 222 ret = pwmchip_add(&pwm->chip); 223 if (ret < 0) { 224 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); 225 reset_control_assert(pwm->rst); 226 return ret; 227 } 228 229 return 0; 230 } 231 232 static int tegra_pwm_remove(struct platform_device *pdev) 233 { 234 struct tegra_pwm_chip *pc = platform_get_drvdata(pdev); 235 unsigned int i; 236 int err; 237 238 if (WARN_ON(!pc)) 239 return -ENODEV; 240 241 err = clk_prepare_enable(pc->clk); 242 if (err < 0) 243 return err; 244 245 for (i = 0; i < pc->chip.npwm; i++) { 246 struct pwm_device *pwm = &pc->chip.pwms[i]; 247 248 if (!pwm_is_enabled(pwm)) 249 if (clk_prepare_enable(pc->clk) < 0) 250 continue; 251 252 pwm_writel(pc, i, 0); 253 254 clk_disable_unprepare(pc->clk); 255 } 256 257 reset_control_assert(pc->rst); 258 clk_disable_unprepare(pc->clk); 259 260 return pwmchip_remove(&pc->chip); 261 } 262 263 #ifdef CONFIG_PM_SLEEP 264 static int tegra_pwm_suspend(struct device *dev) 265 { 266 return pinctrl_pm_select_sleep_state(dev); 267 } 268 269 static int tegra_pwm_resume(struct device *dev) 270 { 271 return pinctrl_pm_select_default_state(dev); 272 } 273 #endif 274 275 static const struct tegra_pwm_soc tegra20_pwm_soc = { 276 .num_channels = 4, 277 .max_frequency = 48000000UL, 278 }; 279 280 static const struct tegra_pwm_soc tegra186_pwm_soc = { 281 .num_channels = 1, 282 .max_frequency = 102000000UL, 283 }; 284 285 static const struct tegra_pwm_soc tegra194_pwm_soc = { 286 .num_channels = 1, 287 .max_frequency = 408000000UL, 288 }; 289 290 static const struct of_device_id tegra_pwm_of_match[] = { 291 { .compatible = "nvidia,tegra20-pwm", .data = &tegra20_pwm_soc }, 292 { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc }, 293 { .compatible = "nvidia,tegra194-pwm", .data = &tegra194_pwm_soc }, 294 { } 295 }; 296 MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); 297 298 static const struct dev_pm_ops tegra_pwm_pm_ops = { 299 SET_SYSTEM_SLEEP_PM_OPS(tegra_pwm_suspend, tegra_pwm_resume) 300 }; 301 302 static struct platform_driver tegra_pwm_driver = { 303 .driver = { 304 .name = "tegra-pwm", 305 .of_match_table = tegra_pwm_of_match, 306 .pm = &tegra_pwm_pm_ops, 307 }, 308 .probe = tegra_pwm_probe, 309 .remove = tegra_pwm_remove, 310 }; 311 312 module_platform_driver(tegra_pwm_driver); 313 314 MODULE_LICENSE("GPL"); 315 MODULE_AUTHOR("NVIDIA Corporation"); 316 MODULE_ALIAS("platform:tegra-pwm"); 317