1 /* 2 * Imagination Technologies Pulse Width Modulator driver 3 * 4 * Copyright (c) 2014-2015, Imagination Technologies 5 * 6 * Based on drivers/pwm/pwm-tegra.c, Copyright (c) 2010, NVIDIA Corporation 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License. 11 */ 12 13 #include <linux/clk.h> 14 #include <linux/err.h> 15 #include <linux/io.h> 16 #include <linux/mfd/syscon.h> 17 #include <linux/module.h> 18 #include <linux/of.h> 19 #include <linux/platform_device.h> 20 #include <linux/pwm.h> 21 #include <linux/regmap.h> 22 #include <linux/slab.h> 23 24 /* PWM registers */ 25 #define PWM_CTRL_CFG 0x0000 26 #define PWM_CTRL_CFG_NO_SUB_DIV 0 27 #define PWM_CTRL_CFG_SUB_DIV0 1 28 #define PWM_CTRL_CFG_SUB_DIV1 2 29 #define PWM_CTRL_CFG_SUB_DIV0_DIV1 3 30 #define PWM_CTRL_CFG_DIV_SHIFT(ch) ((ch) * 2 + 4) 31 #define PWM_CTRL_CFG_DIV_MASK 0x3 32 33 #define PWM_CH_CFG(ch) (0x4 + (ch) * 4) 34 #define PWM_CH_CFG_TMBASE_SHIFT 0 35 #define PWM_CH_CFG_DUTY_SHIFT 16 36 37 #define PERIP_PWM_PDM_CONTROL 0x0140 38 #define PERIP_PWM_PDM_CONTROL_CH_MASK 0x1 39 #define PERIP_PWM_PDM_CONTROL_CH_SHIFT(ch) ((ch) * 4) 40 41 #define MAX_TMBASE_STEPS 65536 42 43 struct img_pwm_chip { 44 struct device *dev; 45 struct pwm_chip chip; 46 struct clk *pwm_clk; 47 struct clk *sys_clk; 48 void __iomem *base; 49 struct regmap *periph_regs; 50 }; 51 52 static inline struct img_pwm_chip *to_img_pwm_chip(struct pwm_chip *chip) 53 { 54 return container_of(chip, struct img_pwm_chip, chip); 55 } 56 57 static inline void img_pwm_writel(struct img_pwm_chip *chip, 58 u32 reg, u32 val) 59 { 60 writel(val, chip->base + reg); 61 } 62 63 static inline u32 img_pwm_readl(struct img_pwm_chip *chip, 64 u32 reg) 65 { 66 return readl(chip->base + reg); 67 } 68 69 static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 70 int duty_ns, int period_ns) 71 { 72 u32 val, div, duty, timebase; 73 unsigned long mul, output_clk_hz, input_clk_hz; 74 struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); 75 76 input_clk_hz = clk_get_rate(pwm_chip->pwm_clk); 77 output_clk_hz = DIV_ROUND_UP(NSEC_PER_SEC, period_ns); 78 79 mul = DIV_ROUND_UP(input_clk_hz, output_clk_hz); 80 if (mul <= MAX_TMBASE_STEPS) { 81 div = PWM_CTRL_CFG_NO_SUB_DIV; 82 timebase = DIV_ROUND_UP(mul, 1); 83 } else if (mul <= MAX_TMBASE_STEPS * 8) { 84 div = PWM_CTRL_CFG_SUB_DIV0; 85 timebase = DIV_ROUND_UP(mul, 8); 86 } else if (mul <= MAX_TMBASE_STEPS * 64) { 87 div = PWM_CTRL_CFG_SUB_DIV1; 88 timebase = DIV_ROUND_UP(mul, 64); 89 } else if (mul <= MAX_TMBASE_STEPS * 512) { 90 div = PWM_CTRL_CFG_SUB_DIV0_DIV1; 91 timebase = DIV_ROUND_UP(mul, 512); 92 } else if (mul > MAX_TMBASE_STEPS * 512) { 93 dev_err(chip->dev, 94 "failed to configure timebase steps/divider value\n"); 95 return -EINVAL; 96 } 97 98 duty = DIV_ROUND_UP(timebase * duty_ns, period_ns); 99 100 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); 101 val &= ~(PWM_CTRL_CFG_DIV_MASK << PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm)); 102 val |= (div & PWM_CTRL_CFG_DIV_MASK) << 103 PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm); 104 img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val); 105 106 val = (duty << PWM_CH_CFG_DUTY_SHIFT) | 107 (timebase << PWM_CH_CFG_TMBASE_SHIFT); 108 img_pwm_writel(pwm_chip, PWM_CH_CFG(pwm->hwpwm), val); 109 110 return 0; 111 } 112 113 static int img_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 114 { 115 u32 val; 116 struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); 117 118 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); 119 val |= BIT(pwm->hwpwm); 120 img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val); 121 122 regmap_update_bits(pwm_chip->periph_regs, PERIP_PWM_PDM_CONTROL, 123 PERIP_PWM_PDM_CONTROL_CH_MASK << 124 PERIP_PWM_PDM_CONTROL_CH_SHIFT(pwm->hwpwm), 0); 125 126 return 0; 127 } 128 129 static void img_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 130 { 131 u32 val; 132 struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); 133 134 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); 135 val &= ~BIT(pwm->hwpwm); 136 img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val); 137 } 138 139 static const struct pwm_ops img_pwm_ops = { 140 .config = img_pwm_config, 141 .enable = img_pwm_enable, 142 .disable = img_pwm_disable, 143 .owner = THIS_MODULE, 144 }; 145 146 static int img_pwm_probe(struct platform_device *pdev) 147 { 148 int ret; 149 struct resource *res; 150 struct img_pwm_chip *pwm; 151 152 pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); 153 if (!pwm) 154 return -ENOMEM; 155 156 pwm->dev = &pdev->dev; 157 158 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 159 pwm->base = devm_ioremap_resource(&pdev->dev, res); 160 if (IS_ERR(pwm->base)) 161 return PTR_ERR(pwm->base); 162 163 pwm->periph_regs = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, 164 "img,cr-periph"); 165 if (IS_ERR(pwm->periph_regs)) 166 return PTR_ERR(pwm->periph_regs); 167 168 pwm->sys_clk = devm_clk_get(&pdev->dev, "sys"); 169 if (IS_ERR(pwm->sys_clk)) { 170 dev_err(&pdev->dev, "failed to get system clock\n"); 171 return PTR_ERR(pwm->sys_clk); 172 } 173 174 pwm->pwm_clk = devm_clk_get(&pdev->dev, "pwm"); 175 if (IS_ERR(pwm->pwm_clk)) { 176 dev_err(&pdev->dev, "failed to get pwm clock\n"); 177 return PTR_ERR(pwm->pwm_clk); 178 } 179 180 ret = clk_prepare_enable(pwm->sys_clk); 181 if (ret < 0) { 182 dev_err(&pdev->dev, "could not prepare or enable sys clock\n"); 183 return ret; 184 } 185 186 ret = clk_prepare_enable(pwm->pwm_clk); 187 if (ret < 0) { 188 dev_err(&pdev->dev, "could not prepare or enable pwm clock\n"); 189 goto disable_sysclk; 190 } 191 192 pwm->chip.dev = &pdev->dev; 193 pwm->chip.ops = &img_pwm_ops; 194 pwm->chip.base = -1; 195 pwm->chip.npwm = 4; 196 197 ret = pwmchip_add(&pwm->chip); 198 if (ret < 0) { 199 dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret); 200 goto disable_pwmclk; 201 } 202 203 platform_set_drvdata(pdev, pwm); 204 return 0; 205 206 disable_pwmclk: 207 clk_disable_unprepare(pwm->pwm_clk); 208 disable_sysclk: 209 clk_disable_unprepare(pwm->sys_clk); 210 return ret; 211 } 212 213 static int img_pwm_remove(struct platform_device *pdev) 214 { 215 struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev); 216 u32 val; 217 unsigned int i; 218 219 for (i = 0; i < pwm_chip->chip.npwm; i++) { 220 val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG); 221 val &= ~BIT(i); 222 img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val); 223 } 224 225 clk_disable_unprepare(pwm_chip->pwm_clk); 226 clk_disable_unprepare(pwm_chip->sys_clk); 227 228 return pwmchip_remove(&pwm_chip->chip); 229 } 230 231 static const struct of_device_id img_pwm_of_match[] = { 232 { .compatible = "img,pistachio-pwm", }, 233 { } 234 }; 235 MODULE_DEVICE_TABLE(of, img_pwm_of_match); 236 237 static struct platform_driver img_pwm_driver = { 238 .driver = { 239 .name = "img-pwm", 240 .of_match_table = img_pwm_of_match, 241 }, 242 .probe = img_pwm_probe, 243 .remove = img_pwm_remove, 244 }; 245 module_platform_driver(img_pwm_driver); 246 247 MODULE_AUTHOR("Sai Masarapu <Sai.Masarapu@imgtec.com>"); 248 MODULE_DESCRIPTION("Imagination Technologies PWM DAC driver"); 249 MODULE_LICENSE("GPL v2"); 250