2 * drivers/pwm/pwm-vt8500.c
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
5 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
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.
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.
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>
23 #include <linux/pwm.h>
24 #include <linux/delay.h>
25 #include <linux/clk.h>
27 #include <asm/div64.h>
30 #include <linux/of_device.h>
31 #include <linux/of_address.h>
34 * SoC architecture allocates register space for 4 PWMs but only
35 * 2 are currently implemented.
37 #define VT8500_NR_PWMS 2
45 #define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip)
47 #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
48 static inline void pwm_busy_wait(void __iomem
*reg
, u8 bitmask
)
50 int loops
= msecs_to_loops(10);
51 while ((readb(reg
) & bitmask
) && --loops
)
55 pr_warn("Waiting for status bits 0x%x to clear timed out\n",
59 static int vt8500_pwm_config(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
60 int duty_ns
, int period_ns
)
62 struct vt8500_chip
*vt8500
= to_vt8500_chip(chip
);
64 unsigned long period_cycles
, prescale
, pv
, dc
;
67 err
= clk_enable(vt8500
->clk
);
69 dev_err(chip
->dev
, "failed to enable clock\n");
73 c
= clk_get_rate(vt8500
->clk
);
75 do_div(c
, 1000000000);
78 if (period_cycles
< 1)
80 prescale
= (period_cycles
- 1) / 4096;
81 pv
= period_cycles
/ (prescale
+ 1) - 1;
85 if (prescale
> 1023) {
86 clk_disable(vt8500
->clk
);
90 c
= (unsigned long long)pv
* duty_ns
;
94 pwm_busy_wait(vt8500
->base
+ 0x40 + pwm
->hwpwm
, (1 << 1));
95 writel(prescale
, vt8500
->base
+ 0x4 + (pwm
->hwpwm
<< 4));
97 pwm_busy_wait(vt8500
->base
+ 0x40 + pwm
->hwpwm
, (1 << 2));
98 writel(pv
, vt8500
->base
+ 0x8 + (pwm
->hwpwm
<< 4));
100 pwm_busy_wait(vt8500
->base
+ 0x40 + pwm
->hwpwm
, (1 << 3));
101 writel(dc
, vt8500
->base
+ 0xc + (pwm
->hwpwm
<< 4));
103 clk_disable(vt8500
->clk
);
107 static int vt8500_pwm_enable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
110 struct vt8500_chip
*vt8500
= to_vt8500_chip(chip
);
112 err
= clk_enable(vt8500
->clk
);
114 dev_err(chip
->dev
, "failed to enable clock\n");
118 pwm_busy_wait(vt8500
->base
+ 0x40 + pwm
->hwpwm
, (1 << 0));
119 writel(5, vt8500
->base
+ (pwm
->hwpwm
<< 4));
123 static void vt8500_pwm_disable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
125 struct vt8500_chip
*vt8500
= to_vt8500_chip(chip
);
127 pwm_busy_wait(vt8500
->base
+ 0x40 + pwm
->hwpwm
, (1 << 0));
128 writel(0, vt8500
->base
+ (pwm
->hwpwm
<< 4));
130 clk_disable(vt8500
->clk
);
133 static struct pwm_ops vt8500_pwm_ops
= {
134 .enable
= vt8500_pwm_enable
,
135 .disable
= vt8500_pwm_disable
,
136 .config
= vt8500_pwm_config
,
137 .owner
= THIS_MODULE
,
140 static const struct of_device_id vt8500_pwm_dt_ids
[] = {
141 { .compatible
= "via,vt8500-pwm", },
144 MODULE_DEVICE_TABLE(of
, vt8500_pwm_dt_ids
);
146 static int vt8500_pwm_probe(struct platform_device
*pdev
)
148 struct vt8500_chip
*chip
;
150 struct device_node
*np
= pdev
->dev
.of_node
;
154 dev_err(&pdev
->dev
, "invalid devicetree node\n");
158 chip
= devm_kzalloc(&pdev
->dev
, sizeof(*chip
), GFP_KERNEL
);
160 dev_err(&pdev
->dev
, "failed to allocate memory\n");
164 chip
->chip
.dev
= &pdev
->dev
;
165 chip
->chip
.ops
= &vt8500_pwm_ops
;
166 chip
->chip
.base
= -1;
167 chip
->chip
.npwm
= VT8500_NR_PWMS
;
169 chip
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
170 if (IS_ERR(chip
->clk
)) {
171 dev_err(&pdev
->dev
, "clock source not specified\n");
172 return PTR_ERR(chip
->clk
);
175 r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
177 dev_err(&pdev
->dev
, "no memory resource defined\n");
181 chip
->base
= devm_request_and_ioremap(&pdev
->dev
, r
);
183 return -EADDRNOTAVAIL
;
185 ret
= clk_prepare(chip
->clk
);
187 dev_err(&pdev
->dev
, "failed to prepare clock\n");
191 ret
= pwmchip_add(&chip
->chip
);
193 dev_err(&pdev
->dev
, "failed to add PWM chip\n");
197 platform_set_drvdata(pdev
, chip
);
201 static int vt8500_pwm_remove(struct platform_device
*pdev
)
203 struct vt8500_chip
*chip
;
205 chip
= platform_get_drvdata(pdev
);
209 clk_unprepare(chip
->clk
);
211 return pwmchip_remove(&chip
->chip
);
214 static struct platform_driver vt8500_pwm_driver
= {
215 .probe
= vt8500_pwm_probe
,
216 .remove
= vt8500_pwm_remove
,
218 .name
= "vt8500-pwm",
219 .owner
= THIS_MODULE
,
220 .of_match_table
= vt8500_pwm_dt_ids
,
223 module_platform_driver(vt8500_pwm_driver
);
225 MODULE_DESCRIPTION("VT8500 PWM Driver");
226 MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
227 MODULE_LICENSE("GPL v2");