aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-vt8500.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 12:34:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 12:34:29 -0500
commit3eb05225ee8efb81fe50558f5f9d94e7477ade8f (patch)
tree40692236718c808455f1fcdfbc1c6de6a274eb36 /drivers/pwm/pwm-vt8500.c
parented5dc2372dba46e0ecd08791b1a0399d313e5cff (diff)
parent30f786170352b8264bc7b61c2482713e54accec8 (diff)
Merge tag 'for-3.9-rc1' of git://gitorious.org/linux-pwm/linux-pwm
Pull PWM changes from Thierry Reding: "A new driver has been added to support the PWM mode of the timer counter blocks found on Atmel AT91 SoCs. The VT8500 driver now supports changing the PWM signal polarity and the TI drivers (EHRPWM and ECAP) gained suspend and resume functionality. User drivers can now query the core for whether access to a PWM device will sleep (if the PWM chip is on a slow bus such as I2C or SPI). The pwm-backlight driver now handles the backlight BL_CORE_FBBLANK state in addition to the FB layer's blanking states. To round things off, a few fixes and cleanups are also included" * tag 'for-3.9-rc1' of git://gitorious.org/linux-pwm/linux-pwm: pwm: twl: Use to_twl() instead of container_of() pwm: tegra: assume CONFIG_OF pwm_backlight: Validate dft_brightness in main probe function pwm: Export pwm_{set,get}_chip_data() pwm: Make Kconfig entries more consistent pwm: Add can_sleep property to drivers pwm: Add pwm_can_sleep() as exported API to users pwm-backlight: handle BL_CORE_FBBLANK state pwm: pwm-tiecap: Low power sleep support pwm: pwm-tiehrpwm: Low power sleep support pwm: pwm-tiehrpwm: Update the clock handling of pwm-tiehrpwm driver pwm: vt8500: Add polarity support pwm: vt8500: Register write busy test performed incorrectly pwm: atmel: add Timer Counter Block PWM driver
Diffstat (limited to 'drivers/pwm/pwm-vt8500.c')
-rw-r--r--drivers/pwm/pwm-vt8500.c87
1 files changed, 72 insertions, 15 deletions
diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c
index f9de9b28e46e..69effd19afc7 100644
--- a/drivers/pwm/pwm-vt8500.c
+++ b/drivers/pwm/pwm-vt8500.c
@@ -36,6 +36,25 @@
36 */ 36 */
37#define VT8500_NR_PWMS 2 37#define VT8500_NR_PWMS 2
38 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
39struct vt8500_chip { 58struct vt8500_chip {
40 struct pwm_chip chip; 59 struct pwm_chip chip;
41 void __iomem *base; 60 void __iomem *base;
@@ -45,15 +64,17 @@ struct vt8500_chip {
45#define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip) 64#define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip)
46 65
47#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) 66#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
48static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask) 67static inline void pwm_busy_wait(struct vt8500_chip *vt8500, int nr, u8 bitmask)
49{ 68{
50 int loops = msecs_to_loops(10); 69 int loops = msecs_to_loops(10);
51 while ((readb(reg) & bitmask) && --loops) 70 u32 mask = bitmask << (nr << 8);
71
72 while ((readl(vt8500->base + REG_STATUS) & mask) && --loops)
52 cpu_relax(); 73 cpu_relax();
53 74
54 if (unlikely(!loops)) 75 if (unlikely(!loops))
55 pr_warn("Waiting for status bits 0x%x to clear timed out\n", 76 dev_warn(vt8500->chip.dev, "Waiting for status bits 0x%x to clear timed out\n",
56 bitmask); 77 mask);
57} 78}
58 79
59static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 80static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -63,6 +84,7 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
63 unsigned long long c; 84 unsigned long long c;
64 unsigned long period_cycles, prescale, pv, dc; 85 unsigned long period_cycles, prescale, pv, dc;
65 int err; 86 int err;
87 u32 val;
66 88
67 err = clk_enable(vt8500->clk); 89 err = clk_enable(vt8500->clk);
68 if (err < 0) { 90 if (err < 0) {
@@ -91,14 +113,19 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
91 do_div(c, period_ns); 113 do_div(c, period_ns);
92 dc = c; 114 dc = c;
93 115
94 pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 1)); 116 writel(prescale, vt8500->base + REG_SCALAR(pwm->hwpwm));
95 writel(prescale, vt8500->base + 0x4 + (pwm->hwpwm << 4)); 117 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_SCALAR_UPDATE);
96 118
97 pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 2)); 119 writel(pv, vt8500->base + REG_PERIOD(pwm->hwpwm));
98 writel(pv, vt8500->base + 0x8 + (pwm->hwpwm << 4)); 120 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_PERIOD_UPDATE);
99 121
100 pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 3)); 122 writel(dc, vt8500->base + REG_DUTY(pwm->hwpwm));
101 writel(dc, vt8500->base + 0xc + (pwm->hwpwm << 4)); 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);
102 129
103 clk_disable(vt8500->clk); 130 clk_disable(vt8500->clk);
104 return 0; 131 return 0;
@@ -106,8 +133,9 @@ static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
106 133
107static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 134static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
108{ 135{
109 int err;
110 struct vt8500_chip *vt8500 = to_vt8500_chip(chip); 136 struct vt8500_chip *vt8500 = to_vt8500_chip(chip);
137 int err;
138 u32 val;
111 139
112 err = clk_enable(vt8500->clk); 140 err = clk_enable(vt8500->clk);
113 if (err < 0) { 141 if (err < 0) {
@@ -115,25 +143,52 @@ static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
115 return err; 143 return err;
116 } 144 }
117 145
118 pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0)); 146 val = readl(vt8500->base + REG_CTRL(pwm->hwpwm));
119 writel(5, vt8500->base + (pwm->hwpwm << 4)); 147 val |= CTRL_ENABLE;
148 writel(val, vt8500->base + REG_CTRL(pwm->hwpwm));
149 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE);
150
120 return 0; 151 return 0;
121} 152}
122 153
123static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 154static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
124{ 155{
125 struct vt8500_chip *vt8500 = to_vt8500_chip(chip); 156 struct vt8500_chip *vt8500 = to_vt8500_chip(chip);
157 u32 val;
126 158
127 pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0)); 159 val = readl(vt8500->base + REG_CTRL(pwm->hwpwm));
128 writel(0, vt8500->base + (pwm->hwpwm << 4)); 160 val &= ~CTRL_ENABLE;
161 writel(val, vt8500->base + REG_CTRL(pwm->hwpwm));
162 pwm_busy_wait(vt8500, pwm->hwpwm, STATUS_CTRL_UPDATE);
129 163
130 clk_disable(vt8500->clk); 164 clk_disable(vt8500->clk);
131} 165}
132 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
133static struct pwm_ops vt8500_pwm_ops = { 187static struct pwm_ops vt8500_pwm_ops = {
134 .enable = vt8500_pwm_enable, 188 .enable = vt8500_pwm_enable,
135 .disable = vt8500_pwm_disable, 189 .disable = vt8500_pwm_disable,
136 .config = vt8500_pwm_config, 190 .config = vt8500_pwm_config,
191 .set_polarity = vt8500_pwm_set_polarity,
137 .owner = THIS_MODULE, 192 .owner = THIS_MODULE,
138}; 193};
139 194
@@ -163,6 +218,8 @@ static int vt8500_pwm_probe(struct platform_device *pdev)
163 218
164 chip->chip.dev = &pdev->dev; 219 chip->chip.dev = &pdev->dev;
165 chip->chip.ops = &vt8500_pwm_ops; 220 chip->chip.ops = &vt8500_pwm_ops;
221 chip->chip.of_xlate = of_pwm_xlate_with_flags;
222 chip->chip.of_pwm_n_cells = 3;
166 chip->chip.base = -1; 223 chip->chip.base = -1;
167 chip->chip.npwm = VT8500_NR_PWMS; 224 chip->chip.npwm = VT8500_NR_PWMS;
168 225