diff options
-rw-r--r-- | Documentation/devicetree/bindings/pwm/pwm-rockchip.txt | 4 | ||||
-rw-r--r-- | drivers/pwm/pwm-rockchip.c | 57 |
2 files changed, 50 insertions, 11 deletions
diff --git a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt index d47d15a6a298..b8be3d09ee26 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-rockchip.txt | |||
@@ -7,8 +7,8 @@ Required properties: | |||
7 | "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC | 7 | "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC |
8 | - reg: physical base address and length of the controller's registers | 8 | - reg: physical base address and length of the controller's registers |
9 | - clocks: phandle and clock specifier of the PWM reference clock | 9 | - clocks: phandle and clock specifier of the PWM reference clock |
10 | - #pwm-cells: should be 2. See pwm.txt in this directory for a | 10 | - #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory |
11 | description of the cell format. | 11 | for a description of the cell format. |
12 | 12 | ||
13 | Example: | 13 | Example: |
14 | 14 | ||
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index bdd8644c01cf..9442df244101 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c | |||
@@ -24,7 +24,9 @@ | |||
24 | #define PWM_ENABLE (1 << 0) | 24 | #define PWM_ENABLE (1 << 0) |
25 | #define PWM_CONTINUOUS (1 << 1) | 25 | #define PWM_CONTINUOUS (1 << 1) |
26 | #define PWM_DUTY_POSITIVE (1 << 3) | 26 | #define PWM_DUTY_POSITIVE (1 << 3) |
27 | #define PWM_DUTY_NEGATIVE (0 << 3) | ||
27 | #define PWM_INACTIVE_NEGATIVE (0 << 4) | 28 | #define PWM_INACTIVE_NEGATIVE (0 << 4) |
29 | #define PWM_INACTIVE_POSITIVE (1 << 4) | ||
28 | #define PWM_OUTPUT_LEFT (0 << 5) | 30 | #define PWM_OUTPUT_LEFT (0 << 5) |
29 | #define PWM_LP_DISABLE (0 << 8) | 31 | #define PWM_LP_DISABLE (0 << 8) |
30 | 32 | ||
@@ -45,8 +47,10 @@ struct rockchip_pwm_regs { | |||
45 | struct rockchip_pwm_data { | 47 | struct rockchip_pwm_data { |
46 | struct rockchip_pwm_regs regs; | 48 | struct rockchip_pwm_regs regs; |
47 | unsigned int prescaler; | 49 | unsigned int prescaler; |
50 | const struct pwm_ops *ops; | ||
48 | 51 | ||
49 | void (*set_enable)(struct pwm_chip *chip, bool enable); | 52 | void (*set_enable)(struct pwm_chip *chip, |
53 | struct pwm_device *pwm, bool enable); | ||
50 | }; | 54 | }; |
51 | 55 | ||
52 | static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) | 56 | static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) |
@@ -54,7 +58,8 @@ static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) | |||
54 | return container_of(c, struct rockchip_pwm_chip, chip); | 58 | return container_of(c, struct rockchip_pwm_chip, chip); |
55 | } | 59 | } |
56 | 60 | ||
57 | static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable) | 61 | static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, |
62 | struct pwm_device *pwm, bool enable) | ||
58 | { | 63 | { |
59 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 64 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
60 | u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN; | 65 | u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN; |
@@ -70,14 +75,19 @@ static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable) | |||
70 | writel_relaxed(val, pc->base + pc->data->regs.ctrl); | 75 | writel_relaxed(val, pc->base + pc->data->regs.ctrl); |
71 | } | 76 | } |
72 | 77 | ||
73 | static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable) | 78 | static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, |
79 | struct pwm_device *pwm, bool enable) | ||
74 | { | 80 | { |
75 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 81 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
76 | u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | | 82 | u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | |
77 | PWM_CONTINUOUS | PWM_DUTY_POSITIVE | | 83 | PWM_CONTINUOUS; |
78 | PWM_INACTIVE_NEGATIVE; | ||
79 | u32 val; | 84 | u32 val; |
80 | 85 | ||
86 | if (pwm->polarity == PWM_POLARITY_INVERSED) | ||
87 | enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE; | ||
88 | else | ||
89 | enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE; | ||
90 | |||
81 | val = readl_relaxed(pc->base + pc->data->regs.ctrl); | 91 | val = readl_relaxed(pc->base + pc->data->regs.ctrl); |
82 | 92 | ||
83 | if (enable) | 93 | if (enable) |
@@ -124,6 +134,19 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | |||
124 | return 0; | 134 | return 0; |
125 | } | 135 | } |
126 | 136 | ||
137 | static int rockchip_pwm_set_polarity(struct pwm_chip *chip, | ||
138 | struct pwm_device *pwm, | ||
139 | enum pwm_polarity polarity) | ||
140 | { | ||
141 | /* | ||
142 | * No action needed here because pwm->polarity will be set by the core | ||
143 | * and the core will only change polarity when the PWM is not enabled. | ||
144 | * We'll handle things in set_enable(). | ||
145 | */ | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
127 | static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | 150 | static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) |
128 | { | 151 | { |
129 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 152 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
@@ -133,7 +156,7 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
133 | if (ret) | 156 | if (ret) |
134 | return ret; | 157 | return ret; |
135 | 158 | ||
136 | pc->data->set_enable(chip, true); | 159 | pc->data->set_enable(chip, pwm, true); |
137 | 160 | ||
138 | return 0; | 161 | return 0; |
139 | } | 162 | } |
@@ -142,18 +165,26 @@ static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
142 | { | 165 | { |
143 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); | 166 | struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); |
144 | 167 | ||
145 | pc->data->set_enable(chip, false); | 168 | pc->data->set_enable(chip, pwm, false); |
146 | 169 | ||
147 | clk_disable(pc->clk); | 170 | clk_disable(pc->clk); |
148 | } | 171 | } |
149 | 172 | ||
150 | static const struct pwm_ops rockchip_pwm_ops = { | 173 | static const struct pwm_ops rockchip_pwm_ops_v1 = { |
151 | .config = rockchip_pwm_config, | 174 | .config = rockchip_pwm_config, |
152 | .enable = rockchip_pwm_enable, | 175 | .enable = rockchip_pwm_enable, |
153 | .disable = rockchip_pwm_disable, | 176 | .disable = rockchip_pwm_disable, |
154 | .owner = THIS_MODULE, | 177 | .owner = THIS_MODULE, |
155 | }; | 178 | }; |
156 | 179 | ||
180 | static const struct pwm_ops rockchip_pwm_ops_v2 = { | ||
181 | .config = rockchip_pwm_config, | ||
182 | .set_polarity = rockchip_pwm_set_polarity, | ||
183 | .enable = rockchip_pwm_enable, | ||
184 | .disable = rockchip_pwm_disable, | ||
185 | .owner = THIS_MODULE, | ||
186 | }; | ||
187 | |||
157 | static const struct rockchip_pwm_data pwm_data_v1 = { | 188 | static const struct rockchip_pwm_data pwm_data_v1 = { |
158 | .regs = { | 189 | .regs = { |
159 | .duty = 0x04, | 190 | .duty = 0x04, |
@@ -162,6 +193,7 @@ static const struct rockchip_pwm_data pwm_data_v1 = { | |||
162 | .ctrl = 0x0c, | 193 | .ctrl = 0x0c, |
163 | }, | 194 | }, |
164 | .prescaler = 2, | 195 | .prescaler = 2, |
196 | .ops = &rockchip_pwm_ops_v1, | ||
165 | .set_enable = rockchip_pwm_set_enable_v1, | 197 | .set_enable = rockchip_pwm_set_enable_v1, |
166 | }; | 198 | }; |
167 | 199 | ||
@@ -173,6 +205,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = { | |||
173 | .ctrl = 0x0c, | 205 | .ctrl = 0x0c, |
174 | }, | 206 | }, |
175 | .prescaler = 1, | 207 | .prescaler = 1, |
208 | .ops = &rockchip_pwm_ops_v2, | ||
176 | .set_enable = rockchip_pwm_set_enable_v2, | 209 | .set_enable = rockchip_pwm_set_enable_v2, |
177 | }; | 210 | }; |
178 | 211 | ||
@@ -184,6 +217,7 @@ static const struct rockchip_pwm_data pwm_data_vop = { | |||
184 | .ctrl = 0x00, | 217 | .ctrl = 0x00, |
185 | }, | 218 | }, |
186 | .prescaler = 1, | 219 | .prescaler = 1, |
220 | .ops = &rockchip_pwm_ops_v2, | ||
187 | .set_enable = rockchip_pwm_set_enable_v2, | 221 | .set_enable = rockchip_pwm_set_enable_v2, |
188 | }; | 222 | }; |
189 | 223 | ||
@@ -227,10 +261,15 @@ static int rockchip_pwm_probe(struct platform_device *pdev) | |||
227 | 261 | ||
228 | pc->data = id->data; | 262 | pc->data = id->data; |
229 | pc->chip.dev = &pdev->dev; | 263 | pc->chip.dev = &pdev->dev; |
230 | pc->chip.ops = &rockchip_pwm_ops; | 264 | pc->chip.ops = pc->data->ops; |
231 | pc->chip.base = -1; | 265 | pc->chip.base = -1; |
232 | pc->chip.npwm = 1; | 266 | pc->chip.npwm = 1; |
233 | 267 | ||
268 | if (pc->data->ops->set_polarity) { | ||
269 | pc->chip.of_xlate = of_pwm_xlate_with_flags; | ||
270 | pc->chip.of_pwm_n_cells = 3; | ||
271 | } | ||
272 | |||
234 | ret = pwmchip_add(&pc->chip); | 273 | ret = pwmchip_add(&pc->chip); |
235 | if (ret < 0) { | 274 | if (ret < 0) { |
236 | clk_unprepare(pc->clk); | 275 | clk_unprepare(pc->clk); |