1/* 2 * drivers/pwm/pwm-vt8500.c 3 * 4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz> 5 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> 6 * 7 * This software is licensed under the terms of the GNU General Public 8 * License version 2, as published by the Free Software Foundation, and 9 * may be copied, distributed, and modified under those terms. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17#include <linux/module.h> 18#include <linux/kernel.h> 19#include <linux/platform_device.h> 20#include <linux/slab.h> 21#include <linux/err.h> 22#include <linux/io.h> 23#include <linux/pwm.h> 24#include <linux/delay.h> 25#include <linux/clk.h> 26 27#include <asm/div64.h> 28 29#include <linux/of.h> 30#include <linux/of_device.h> 31#include <linux/of_address.h> 32 33/* 34 * SoC architecture allocates register space for 4 PWMs but only 35 * 2 are currently implemented. 36 */ 37#define VT8500_NR_PWMS 2 38 39#define REG_CTRL(pwm) (((pwm) << 4) + 0x00) 40#define REG_SCALAR(pwm) (((pwm) << 4) + 0x04) 41#define REG_PERIOD(pwm) (((pwm) << 4) + 0x08) 42#define REG_DUTY(pwm) (((pwm) << 4) + 0x0C) 43#define REG_STATUS 0x40 44 45#define CTRL_ENABLE BIT(0) 46#define CTRL_INVERT BIT(1) 47#define CTRL_AUTOLOAD BIT(2) 48#define CTRL_STOP_IMM BIT(3) 49#define CTRL_LOAD_PRESCALE BIT(4) 50#define CTRL_LOAD_PERIOD BIT(5) 51 52#define STATUS_CTRL_UPDATE BIT(0) 53#define STATUS_SCALAR_UPDATE BIT(1) 54#define STATUS_PERIOD_UPDATE BIT(2) 55#define STATUS_DUTY_UPDATE BIT(3) 56#define STATUS_ALL_UPDATE 0x0F 57 58struct vt8500_chip { 59 struct pwm_chip chip; 60 void __iomem *base; 61 struct clk *clk; 62}; 63 64#define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip) 65 66#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) 67static inline void pwm_busy_wait(struct vt8500_chip *vt8500, int nr, u8 bitmask) 68{ 69 int loops = msecs_to_loops(10); 70 u32 mask = bitmask << (nr << 8); 71 72 while ((readl(vt8500->base + REG_STATUS) & mask) && --loops) 73 cpu_relax(); 74 75 if (unlikely(!loops)) 76 dev_warn(vt8500->chip.dev, "Waiting for status bits 0x%x to clear timed out\n", 77 mask); 78} 79 80static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 81 int duty_ns, int period_ns) 82{ 83 struct vt8500_chip *vt8500 = to_vt8500_chip(chip); 84 unsigned long long c; 85 unsigned long period_cycles, prescale, pv, dc; 86 int err; 87 u32 val; 88 89 err = clk_enable(vt8500->clk); 90 if (err < 0) { 91 dev_err(chip->dev, "failed to enable clock\n"); 92 return err; 93 } 94 95 c = clk_get_rate(vt8500->clk); 96 c = c * period_ns; 97 do_div(c, 1000000000); 98 period_cycles = c; 99 100 if (period_cycles < 1) 101 period_cycles = 1; 102 prescale = (period_cycles - 1) / 4096; 103 pv = period_cycles / (prescale + 1) - 1; 104 if (pv > 4095) 105 pv = 4095; 106 107 if (prescale > 1023) { 108 clk_disable(vt8500->clk); 109 return -EINVAL; 110 } 111 112 c = (unsigned long long)pv * duty_ns; 113 do_div(c, period_ns); 114 dc = c; 115 116 writel(prescale, vt8500->base + REG_SCALAR(pwm->hwpwm)); 117 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_SCALAR_UPDATE); 118 119 writel(pv, vt8500->base + REG_PERIOD(pwm->hwpwm)); 120 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_PERIOD_UPDATE); 121 122 writel(dc, vt8500->base + REG_DUTY(pwm->hwpwm)); 123 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_DUTY_UPDATE); 124 125 val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); 126 val |= CTRL_AUTOLOAD; 127 writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); 128 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); 129 130 clk_disable(vt8500->clk); 131 return 0; 132} 133 134static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 135{ 136 struct vt8500_chip *vt8500 = to_vt8500_chip(chip); 137 int err; 138 u32 val; 139 140 err = clk_enable(vt8500->clk); 141 if (err < 0) { 142 dev_err(chip->dev, "failed to enable clock\n"); 143 return err; 144 } 145 146 val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); 147 val |= CTRL_ENABLE; 148 writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); 149 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); 150 151 return 0; 152} 153 154static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 155{ 156 struct vt8500_chip *vt8500 = to_vt8500_chip(chip); 157 u32 val; 158 159 val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); 160 val &= ~CTRL_ENABLE; 161 writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); 162 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); 163 164 clk_disable(vt8500->clk); 165} 166 167static int vt8500_pwm_set_polarity(struct pwm_chip *chip, 168 struct pwm_device *pwm, 169 enum pwm_polarity polarity) 170{ 171 struct vt8500_chip *vt8500 = to_vt8500_chip(chip); 172 u32 val; 173 174 val = readl(vt8500->base + REG_CTRL(pwm->hwpwm)); 175 176 if (polarity == PWM_POLARITY_INVERSED) 177 val |= CTRL_INVERT; 178 else 179 val &= ~CTRL_INVERT; 180 181 writel(val, vt8500->base + REG_CTRL(pwm->hwpwm)); 182 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE); 183 184 return 0; 185} 186 187static struct pwm_ops vt8500_pwm_ops = { 188 .enable = vt8500_pwm_enable, 189 .disable = vt8500_pwm_disable, 190 .config = vt8500_pwm_config, 191 .set_polarity = vt8500_pwm_set_polarity, 192 .owner = THIS_MODULE, 193}; 194 195static const struct of_device_id vt8500_pwm_dt_ids[] = { 196 { .compatible = "via,vt8500-pwm", }, 197 { /* Sentinel */ } 198}; 199MODULE_DEVICE_TABLE(of, vt8500_pwm_dt_ids); 200 201static int vt8500_pwm_probe(struct platform_device *pdev) 202{ 203 struct vt8500_chip *chip; 204 struct resource *r; 205 struct device_node *np = pdev->dev.of_node; 206 int ret; 207 208 if (!np) { 209 dev_err(&pdev->dev, "invalid devicetree node\n"); 210 return -EINVAL; 211 } 212 213 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); 214 if (chip == NULL) 215 return -ENOMEM; 216 217 chip->chip.dev = &pdev->dev; 218 chip->chip.ops = &vt8500_pwm_ops; 219 chip->chip.of_xlate = of_pwm_xlate_with_flags; 220 chip->chip.of_pwm_n_cells = 3; 221 chip->chip.base = -1; 222 chip->chip.npwm = VT8500_NR_PWMS; 223 224 chip->clk = devm_clk_get(&pdev->dev, NULL); 225 if (IS_ERR(chip->clk)) { 226 dev_err(&pdev->dev, "clock source not specified\n"); 227 return PTR_ERR(chip->clk); 228 } 229 230 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 231 chip->base = devm_ioremap_resource(&pdev->dev, r); 232 if (IS_ERR(chip->base)) 233 return PTR_ERR(chip->base); 234 235 ret = clk_prepare(chip->clk); 236 if (ret < 0) { 237 dev_err(&pdev->dev, "failed to prepare clock\n"); 238 return ret; 239 } 240 241 ret = pwmchip_add(&chip->chip); 242 if (ret < 0) { 243 dev_err(&pdev->dev, "failed to add PWM chip\n"); 244 return ret; 245 } 246 247 platform_set_drvdata(pdev, chip); 248 return ret; 249} 250 251static int vt8500_pwm_remove(struct platform_device *pdev) 252{ 253 struct vt8500_chip *chip; 254 255 chip = platform_get_drvdata(pdev); 256 if (chip == NULL) 257 return -ENODEV; 258 259 clk_unprepare(chip->clk); 260 261 return pwmchip_remove(&chip->chip); 262} 263 264static struct platform_driver vt8500_pwm_driver = { 265 .probe = vt8500_pwm_probe, 266 .remove = vt8500_pwm_remove, 267 .driver = { 268 .name = "vt8500-pwm", 269 .owner = THIS_MODULE, 270 .of_match_table = vt8500_pwm_dt_ids, 271 }, 272}; 273module_platform_driver(vt8500_pwm_driver); 274 275MODULE_DESCRIPTION("VT8500 PWM Driver"); 276MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>"); 277MODULE_LICENSE("GPL v2"); 278