summaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-rockchip.c
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@free-electrons.com>2016-06-14 05:13:12 -0400
committerThierry Reding <thierry.reding@gmail.com>2016-07-11 06:49:27 -0400
commit1ebb74cf3537135f157beddf1a4366070155edda (patch)
tree847bd545aabb5459217c9bddf9be2cbf25e49e20 /drivers/pwm/pwm-rockchip.c
parent12f9ce4a519845070d338253ab9528b5d7e2df34 (diff)
pwm: rockchip: Add support for hardware readout
Implement the ->get_state() function to expose initial state. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Reviewed-by: Brian Norris <briannorris@chromium.org> Tested-by: Brian Norris <briannorris@chromium.org> Tested-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm/pwm-rockchip.c')
-rw-r--r--drivers/pwm/pwm-rockchip.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index 68d72ce8fba5..c72b4192c7bf 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -51,6 +51,8 @@ struct rockchip_pwm_data {
51 51
52 void (*set_enable)(struct pwm_chip *chip, 52 void (*set_enable)(struct pwm_chip *chip,
53 struct pwm_device *pwm, bool enable); 53 struct pwm_device *pwm, bool enable);
54 void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
55 struct pwm_state *state);
54}; 56};
55 57
56static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) 58static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
@@ -75,6 +77,19 @@ static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip,
75 writel_relaxed(val, pc->base + pc->data->regs.ctrl); 77 writel_relaxed(val, pc->base + pc->data->regs.ctrl);
76} 78}
77 79
80static void rockchip_pwm_get_state_v1(struct pwm_chip *chip,
81 struct pwm_device *pwm,
82 struct pwm_state *state)
83{
84 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
85 u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
86 u32 val;
87
88 val = readl_relaxed(pc->base + pc->data->regs.ctrl);
89 if ((val & enable_conf) == enable_conf)
90 state->enabled = true;
91}
92
78static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, 93static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip,
79 struct pwm_device *pwm, bool enable) 94 struct pwm_device *pwm, bool enable)
80{ 95{
@@ -98,6 +113,53 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip,
98 writel_relaxed(val, pc->base + pc->data->regs.ctrl); 113 writel_relaxed(val, pc->base + pc->data->regs.ctrl);
99} 114}
100 115
116static void rockchip_pwm_get_state_v2(struct pwm_chip *chip,
117 struct pwm_device *pwm,
118 struct pwm_state *state)
119{
120 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
121 u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
122 PWM_CONTINUOUS;
123 u32 val;
124
125 val = readl_relaxed(pc->base + pc->data->regs.ctrl);
126 if ((val & enable_conf) != enable_conf)
127 return;
128
129 state->enabled = true;
130
131 if (!(val & PWM_DUTY_POSITIVE))
132 state->polarity = PWM_POLARITY_INVERSED;
133}
134
135static void rockchip_pwm_get_state(struct pwm_chip *chip,
136 struct pwm_device *pwm,
137 struct pwm_state *state)
138{
139 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
140 unsigned long clk_rate;
141 u64 tmp;
142 int ret;
143
144 ret = clk_enable(pc->clk);
145 if (ret)
146 return;
147
148 clk_rate = clk_get_rate(pc->clk);
149
150 tmp = readl_relaxed(pc->base + pc->data->regs.period);
151 tmp *= pc->data->prescaler * NSEC_PER_SEC;
152 state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
153
154 tmp = readl_relaxed(pc->base + pc->data->regs.duty);
155 tmp *= pc->data->prescaler * NSEC_PER_SEC;
156 state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
157
158 pc->data->get_state(chip, pwm, state);
159
160 clk_disable(pc->clk);
161}
162
101static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 163static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
102 int duty_ns, int period_ns) 164 int duty_ns, int period_ns)
103{ 165{
@@ -170,6 +232,7 @@ static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
170} 232}
171 233
172static const struct pwm_ops rockchip_pwm_ops_v1 = { 234static const struct pwm_ops rockchip_pwm_ops_v1 = {
235 .get_state = rockchip_pwm_get_state,
173 .config = rockchip_pwm_config, 236 .config = rockchip_pwm_config,
174 .enable = rockchip_pwm_enable, 237 .enable = rockchip_pwm_enable,
175 .disable = rockchip_pwm_disable, 238 .disable = rockchip_pwm_disable,
@@ -177,6 +240,7 @@ static const struct pwm_ops rockchip_pwm_ops_v1 = {
177}; 240};
178 241
179static const struct pwm_ops rockchip_pwm_ops_v2 = { 242static const struct pwm_ops rockchip_pwm_ops_v2 = {
243 .get_state = rockchip_pwm_get_state,
180 .config = rockchip_pwm_config, 244 .config = rockchip_pwm_config,
181 .set_polarity = rockchip_pwm_set_polarity, 245 .set_polarity = rockchip_pwm_set_polarity,
182 .enable = rockchip_pwm_enable, 246 .enable = rockchip_pwm_enable,
@@ -194,6 +258,7 @@ static const struct rockchip_pwm_data pwm_data_v1 = {
194 .prescaler = 2, 258 .prescaler = 2,
195 .ops = &rockchip_pwm_ops_v1, 259 .ops = &rockchip_pwm_ops_v1,
196 .set_enable = rockchip_pwm_set_enable_v1, 260 .set_enable = rockchip_pwm_set_enable_v1,
261 .get_state = rockchip_pwm_get_state_v1,
197}; 262};
198 263
199static const struct rockchip_pwm_data pwm_data_v2 = { 264static const struct rockchip_pwm_data pwm_data_v2 = {
@@ -206,6 +271,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
206 .prescaler = 1, 271 .prescaler = 1,
207 .ops = &rockchip_pwm_ops_v2, 272 .ops = &rockchip_pwm_ops_v2,
208 .set_enable = rockchip_pwm_set_enable_v2, 273 .set_enable = rockchip_pwm_set_enable_v2,
274 .get_state = rockchip_pwm_get_state_v2,
209}; 275};
210 276
211static const struct rockchip_pwm_data pwm_data_vop = { 277static const struct rockchip_pwm_data pwm_data_vop = {
@@ -218,6 +284,7 @@ static const struct rockchip_pwm_data pwm_data_vop = {
218 .prescaler = 1, 284 .prescaler = 1,
219 .ops = &rockchip_pwm_ops_v2, 285 .ops = &rockchip_pwm_ops_v2,
220 .set_enable = rockchip_pwm_set_enable_v2, 286 .set_enable = rockchip_pwm_set_enable_v2,
287 .get_state = rockchip_pwm_get_state_v2,
221}; 288};
222 289
223static const struct of_device_id rockchip_pwm_dt_ids[] = { 290static const struct of_device_id rockchip_pwm_dt_ids[] = {