aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/soc
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2015-09-02 18:46:50 -0400
committerAndy Gross <agross@codeaurora.org>2015-10-14 15:51:21 -0400
commit30b7ea5eda0afb13164b2d7049a56645cfc1d47b (patch)
tree079da3999634f35fb1359748e7f6a500a7e2f5e3 /drivers/soc
parent50e1b29b4438bdb0be61ff41e6925cab6f8a9284 (diff)
soc: qcom: smd_rpm: Handle big endian CPUs
The smd rpm structures are always in little endian, but this driver is not capable of being used on big endian CPUs. Annotate the little endian data members and update the code to do the proper byte swapping. Cc: Bjorn Andersson <bjorn.andersson@sonymobile.com> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@sonymobile.com> Signed-off-by: Andy Gross <agross@codeaurora.org>
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/qcom/smd-rpm.c50
1 files changed, 26 insertions, 24 deletions
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index 7709579d63d0..d4cbaa3d4629 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -45,8 +45,8 @@ struct qcom_smd_rpm {
45 * @length: length of the payload 45 * @length: length of the payload
46 */ 46 */
47struct qcom_rpm_header { 47struct qcom_rpm_header {
48 u32 service_type; 48 __le32 service_type;
49 u32 length; 49 __le32 length;
50}; 50};
51 51
52/** 52/**
@@ -58,11 +58,11 @@ struct qcom_rpm_header {
58 * @data_len: length of the payload following this header 58 * @data_len: length of the payload following this header
59 */ 59 */
60struct qcom_rpm_request { 60struct qcom_rpm_request {
61 u32 msg_id; 61 __le32 msg_id;
62 u32 flags; 62 __le32 flags;
63 u32 type; 63 __le32 type;
64 u32 id; 64 __le32 id;
65 u32 data_len; 65 __le32 data_len;
66}; 66};
67 67
68/** 68/**
@@ -75,10 +75,10 @@ struct qcom_rpm_request {
75 * Multiple of these messages can be stacked in an rpm message. 75 * Multiple of these messages can be stacked in an rpm message.
76 */ 76 */
77struct qcom_rpm_message { 77struct qcom_rpm_message {
78 u32 msg_type; 78 __le32 msg_type;
79 u32 length; 79 __le32 length;
80 union { 80 union {
81 u32 msg_id; 81 __le32 msg_id;
82 u8 message[0]; 82 u8 message[0];
83 }; 83 };
84}; 84};
@@ -122,14 +122,14 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
122 122
123 mutex_lock(&rpm->lock); 123 mutex_lock(&rpm->lock);
124 124
125 pkt->hdr.service_type = RPM_SERVICE_TYPE_REQUEST; 125 pkt->hdr.service_type = cpu_to_le32(RPM_SERVICE_TYPE_REQUEST);
126 pkt->hdr.length = sizeof(struct qcom_rpm_request) + count; 126 pkt->hdr.length = cpu_to_le32(sizeof(struct qcom_rpm_request) + count);
127 127
128 pkt->req.msg_id = msg_id++; 128 pkt->req.msg_id = cpu_to_le32(msg_id++);
129 pkt->req.flags = BIT(state); 129 pkt->req.flags = cpu_to_le32(BIT(state));
130 pkt->req.type = type; 130 pkt->req.type = cpu_to_le32(type);
131 pkt->req.id = id; 131 pkt->req.id = cpu_to_le32(id);
132 pkt->req.data_len = count; 132 pkt->req.data_len = cpu_to_le32(count);
133 memcpy(pkt->payload, buf, count); 133 memcpy(pkt->payload, buf, count);
134 134
135 ret = qcom_smd_send(rpm->rpm_channel, pkt, sizeof(*pkt)); 135 ret = qcom_smd_send(rpm->rpm_channel, pkt, sizeof(*pkt));
@@ -154,27 +154,29 @@ static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev,
154 size_t count) 154 size_t count)
155{ 155{
156 const struct qcom_rpm_header *hdr = data; 156 const struct qcom_rpm_header *hdr = data;
157 size_t hdr_length = le32_to_cpu(hdr->length);
157 const struct qcom_rpm_message *msg; 158 const struct qcom_rpm_message *msg;
158 struct qcom_smd_rpm *rpm = dev_get_drvdata(&qsdev->dev); 159 struct qcom_smd_rpm *rpm = dev_get_drvdata(&qsdev->dev);
159 const u8 *buf = data + sizeof(struct qcom_rpm_header); 160 const u8 *buf = data + sizeof(struct qcom_rpm_header);
160 const u8 *end = buf + hdr->length; 161 const u8 *end = buf + hdr_length;
161 char msgbuf[32]; 162 char msgbuf[32];
162 int status = 0; 163 int status = 0;
163 u32 len; 164 u32 len, msg_length;
164 165
165 if (hdr->service_type != RPM_SERVICE_TYPE_REQUEST || 166 if (le32_to_cpu(hdr->service_type) != RPM_SERVICE_TYPE_REQUEST ||
166 hdr->length < sizeof(struct qcom_rpm_message)) { 167 hdr_length < sizeof(struct qcom_rpm_message)) {
167 dev_err(&qsdev->dev, "invalid request\n"); 168 dev_err(&qsdev->dev, "invalid request\n");
168 return 0; 169 return 0;
169 } 170 }
170 171
171 while (buf < end) { 172 while (buf < end) {
172 msg = (struct qcom_rpm_message *)buf; 173 msg = (struct qcom_rpm_message *)buf;
173 switch (msg->msg_type) { 174 msg_length = le32_to_cpu(msg->length);
175 switch (le32_to_cpu(msg->msg_type)) {
174 case RPM_MSG_TYPE_MSG_ID: 176 case RPM_MSG_TYPE_MSG_ID:
175 break; 177 break;
176 case RPM_MSG_TYPE_ERR: 178 case RPM_MSG_TYPE_ERR:
177 len = min_t(u32, ALIGN(msg->length, 4), sizeof(msgbuf)); 179 len = min_t(u32, ALIGN(msg_length, 4), sizeof(msgbuf));
178 memcpy_fromio(msgbuf, msg->message, len); 180 memcpy_fromio(msgbuf, msg->message, len);
179 msgbuf[len - 1] = 0; 181 msgbuf[len - 1] = 0;
180 182
@@ -185,7 +187,7 @@ static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev,
185 break; 187 break;
186 } 188 }
187 189
188 buf = PTR_ALIGN(buf + 2 * sizeof(u32) + msg->length, 4); 190 buf = PTR_ALIGN(buf + 2 * sizeof(u32) + msg_length, 4);
189 } 191 }
190 192
191 rpm->ack_status = status; 193 rpm->ack_status = status;