aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-vt8500.c
diff options
context:
space:
mode:
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