diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2016-06-22 02:27:17 -0400 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2016-06-29 05:16:47 -0400 |
commit | f37be01e6dc606f2fcc5e95c9933d948ce19bd35 (patch) | |
tree | 41ec39f826b8a43df00173883dc4817748599d60 | |
parent | 0a58da1e2f25f213fb72d7d6a18dff9562621215 (diff) |
mfd: qcom_rpm: Parametrize also ack selector size
The RPM has two sets of selectors (IPC bit fields): request and
acknowledge. Apparently, some models use 4*32 bit words for select
and some use 7*32 bit words for request, but all use 7*32 words
for acknowledge bits.
So apparently you can on the models with requests of 4*32 select
bits send 4*32 messages and get 7*32 different replies, so on ACK
interrupt, 7*32 bit words need to be read. This is how the vendor
code apparently works.
Cc: stable@vger.kernel.org
Reported-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r-- | drivers/mfd/qcom_rpm.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c index 710cae2a9b02..2e44323455dd 100644 --- a/drivers/mfd/qcom_rpm.c +++ b/drivers/mfd/qcom_rpm.c | |||
@@ -39,7 +39,8 @@ struct qcom_rpm_data { | |||
39 | unsigned int req_sel_off; | 39 | unsigned int req_sel_off; |
40 | unsigned int ack_ctx_off; | 40 | unsigned int ack_ctx_off; |
41 | unsigned int ack_sel_off; | 41 | unsigned int ack_sel_off; |
42 | unsigned int sel_size; | 42 | unsigned int req_sel_size; |
43 | unsigned int ack_sel_size; | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | struct qcom_rpm { | 46 | struct qcom_rpm { |
@@ -160,7 +161,8 @@ static const struct qcom_rpm_data apq8064_template = { | |||
160 | .req_sel_off = 11, | 161 | .req_sel_off = 11, |
161 | .ack_ctx_off = 15, | 162 | .ack_ctx_off = 15, |
162 | .ack_sel_off = 23, | 163 | .ack_sel_off = 23, |
163 | .sel_size = 4, | 164 | .req_sel_size = 4, |
165 | .ack_sel_size = 7, | ||
164 | }; | 166 | }; |
165 | 167 | ||
166 | static const struct qcom_rpm_resource msm8660_rpm_resource_table[] = { | 168 | static const struct qcom_rpm_resource msm8660_rpm_resource_table[] = { |
@@ -248,7 +250,8 @@ static const struct qcom_rpm_data msm8660_template = { | |||
248 | .req_sel_off = 11, | 250 | .req_sel_off = 11, |
249 | .ack_ctx_off = 19, | 251 | .ack_ctx_off = 19, |
250 | .ack_sel_off = 27, | 252 | .ack_sel_off = 27, |
251 | .sel_size = 7, | 253 | .req_sel_size = 7, |
254 | .ack_sel_size = 7, | ||
252 | }; | 255 | }; |
253 | 256 | ||
254 | static const struct qcom_rpm_resource msm8960_rpm_resource_table[] = { | 257 | static const struct qcom_rpm_resource msm8960_rpm_resource_table[] = { |
@@ -335,7 +338,8 @@ static const struct qcom_rpm_data msm8960_template = { | |||
335 | .req_sel_off = 11, | 338 | .req_sel_off = 11, |
336 | .ack_ctx_off = 15, | 339 | .ack_ctx_off = 15, |
337 | .ack_sel_off = 23, | 340 | .ack_sel_off = 23, |
338 | .sel_size = 4, | 341 | .req_sel_size = 4, |
342 | .ack_sel_size = 7, | ||
339 | }; | 343 | }; |
340 | 344 | ||
341 | static const struct qcom_rpm_resource ipq806x_rpm_resource_table[] = { | 345 | static const struct qcom_rpm_resource ipq806x_rpm_resource_table[] = { |
@@ -380,7 +384,8 @@ static const struct qcom_rpm_data ipq806x_template = { | |||
380 | .req_sel_off = 11, | 384 | .req_sel_off = 11, |
381 | .ack_ctx_off = 15, | 385 | .ack_ctx_off = 15, |
382 | .ack_sel_off = 23, | 386 | .ack_sel_off = 23, |
383 | .sel_size = 4, | 387 | .req_sel_size = 4, |
388 | .ack_sel_size = 7, | ||
384 | }; | 389 | }; |
385 | 390 | ||
386 | static const struct of_device_id qcom_rpm_of_match[] = { | 391 | static const struct of_device_id qcom_rpm_of_match[] = { |
@@ -417,7 +422,7 @@ int qcom_rpm_write(struct qcom_rpm *rpm, | |||
417 | writel_relaxed(buf[i], RPM_REQ_REG(rpm, res->target_id + i)); | 422 | writel_relaxed(buf[i], RPM_REQ_REG(rpm, res->target_id + i)); |
418 | 423 | ||
419 | bitmap_set((unsigned long *)sel_mask, res->select_id, 1); | 424 | bitmap_set((unsigned long *)sel_mask, res->select_id, 1); |
420 | for (i = 0; i < rpm->data->sel_size; i++) { | 425 | for (i = 0; i < rpm->data->req_sel_size; i++) { |
421 | writel_relaxed(sel_mask[i], | 426 | writel_relaxed(sel_mask[i], |
422 | RPM_CTRL_REG(rpm, rpm->data->req_sel_off + i)); | 427 | RPM_CTRL_REG(rpm, rpm->data->req_sel_off + i)); |
423 | } | 428 | } |
@@ -446,7 +451,7 @@ static irqreturn_t qcom_rpm_ack_interrupt(int irq, void *dev) | |||
446 | int i; | 451 | int i; |
447 | 452 | ||
448 | ack = readl_relaxed(RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off)); | 453 | ack = readl_relaxed(RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off)); |
449 | for (i = 0; i < rpm->data->sel_size; i++) | 454 | for (i = 0; i < rpm->data->ack_sel_size; i++) |
450 | writel_relaxed(0, | 455 | writel_relaxed(0, |
451 | RPM_CTRL_REG(rpm, rpm->data->ack_sel_off + i)); | 456 | RPM_CTRL_REG(rpm, rpm->data->ack_sel_off + i)); |
452 | writel(0, RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off)); | 457 | writel(0, RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off)); |