aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firmware/ti_sci.c685
-rw-r--r--drivers/firmware/ti_sci.h289
-rw-r--r--include/linux/ti_sci_protocol.h78
3 files changed, 1052 insertions, 0 deletions
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 1e9a2a68c471..51194b3cbbaf 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -837,6 +837,675 @@ static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id,
837} 837}
838 838
839/** 839/**
840 * ti_sci_set_clock_state() - Set clock state helper
841 * @handle: pointer to TI SCI handle
842 * @dev_id: Device identifier this request is for
843 * @clk_id: Clock identifier for the device for this request.
844 * Each device has it's own set of clock inputs. This indexes
845 * which clock input to modify.
846 * @flags: Header flags as needed
847 * @state: State to request for the clock.
848 *
849 * Return: 0 if all went well, else returns appropriate error value.
850 */
851static int ti_sci_set_clock_state(const struct ti_sci_handle *handle,
852 u32 dev_id, u8 clk_id,
853 u32 flags, u8 state)
854{
855 struct ti_sci_info *info;
856 struct ti_sci_msg_req_set_clock_state *req;
857 struct ti_sci_msg_hdr *resp;
858 struct ti_sci_xfer *xfer;
859 struct device *dev;
860 int ret = 0;
861
862 if (IS_ERR(handle))
863 return PTR_ERR(handle);
864 if (!handle)
865 return -EINVAL;
866
867 info = handle_to_ti_sci_info(handle);
868 dev = info->dev;
869
870 xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE,
871 flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
872 sizeof(*req), sizeof(*resp));
873 if (IS_ERR(xfer)) {
874 ret = PTR_ERR(xfer);
875 dev_err(dev, "Message alloc failed(%d)\n", ret);
876 return ret;
877 }
878 req = (struct ti_sci_msg_req_set_clock_state *)xfer->xfer_buf;
879 req->dev_id = dev_id;
880 req->clk_id = clk_id;
881 req->request_state = state;
882
883 ret = ti_sci_do_xfer(info, xfer);
884 if (ret) {
885 dev_err(dev, "Mbox send fail %d\n", ret);
886 goto fail;
887 }
888
889 resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
890
891 ret = tis_sci_is_response_ack(resp) ? 0 : -ENODEV;
892
893fail:
894 ti_sci_put_one_xfer(&info->minfo, xfer);
895
896 return ret;
897}
898
899/**
900 * ti_sci_cmd_get_clock_state() - Get clock state helper
901 * @handle: pointer to TI SCI handle
902 * @dev_id: Device identifier this request is for
903 * @clk_id: Clock identifier for the device for this request.
904 * Each device has it's own set of clock inputs. This indexes
905 * which clock input to modify.
906 * @programmed_state: State requested for clock to move to
907 * @current_state: State that the clock is currently in
908 *
909 * Return: 0 if all went well, else returns appropriate error value.
910 */
911static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle,
912 u32 dev_id, u8 clk_id,
913 u8 *programmed_state, u8 *current_state)
914{
915 struct ti_sci_info *info;
916 struct ti_sci_msg_req_get_clock_state *req;
917 struct ti_sci_msg_resp_get_clock_state *resp;
918 struct ti_sci_xfer *xfer;
919 struct device *dev;
920 int ret = 0;
921
922 if (IS_ERR(handle))
923 return PTR_ERR(handle);
924 if (!handle)
925 return -EINVAL;
926
927 if (!programmed_state && !current_state)
928 return -EINVAL;
929
930 info = handle_to_ti_sci_info(handle);
931 dev = info->dev;
932
933 xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE,
934 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
935 sizeof(*req), sizeof(*resp));
936 if (IS_ERR(xfer)) {
937 ret = PTR_ERR(xfer);
938 dev_err(dev, "Message alloc failed(%d)\n", ret);
939 return ret;
940 }
941 req = (struct ti_sci_msg_req_get_clock_state *)xfer->xfer_buf;
942 req->dev_id = dev_id;
943 req->clk_id = clk_id;
944
945 ret = ti_sci_do_xfer(info, xfer);
946 if (ret) {
947 dev_err(dev, "Mbox send fail %d\n", ret);
948 goto fail;
949 }
950
951 resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->xfer_buf;
952
953 if (!tis_sci_is_response_ack(resp)) {
954 ret = -ENODEV;
955 goto fail;
956 }
957
958 if (programmed_state)
959 *programmed_state = resp->programmed_state;
960 if (current_state)
961 *current_state = resp->current_state;
962
963fail:
964 ti_sci_put_one_xfer(&info->minfo, xfer);
965
966 return ret;
967}
968
969/**
970 * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI
971 * @handle: pointer to TI SCI handle
972 * @dev_id: Device identifier this request is for
973 * @clk_id: Clock identifier for the device for this request.
974 * Each device has it's own set of clock inputs. This indexes
975 * which clock input to modify.
976 * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false'
977 * @can_change_freq: 'true' if frequency change is desired, else 'false'
978 * @enable_input_term: 'true' if input termination is desired, else 'false'
979 *
980 * Return: 0 if all went well, else returns appropriate error value.
981 */
982static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
983 u8 clk_id, bool needs_ssc, bool can_change_freq,
984 bool enable_input_term)
985{
986 u32 flags = 0;
987
988 flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
989 flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
990 flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
991
992 return ti_sci_set_clock_state(handle, dev_id, clk_id, flags,
993 MSG_CLOCK_SW_STATE_REQ);
994}
995
996/**
997 * ti_sci_cmd_idle_clock() - Idle a clock which is in our control
998 * @handle: pointer to TI SCI handle
999 * @dev_id: Device identifier this request is for
1000 * @clk_id: Clock identifier for the device for this request.
1001 * Each device has it's own set of clock inputs. This indexes
1002 * which clock input to modify.
1003 *
1004 * NOTE: This clock must have been requested by get_clock previously.
1005 *
1006 * Return: 0 if all went well, else returns appropriate error value.
1007 */
1008static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
1009 u32 dev_id, u8 clk_id)
1010{
1011 return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
1012 MSG_CLOCK_SW_STATE_UNREQ);
1013}
1014
1015/**
1016 * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI
1017 * @handle: pointer to TI SCI handle
1018 * @dev_id: Device identifier this request is for
1019 * @clk_id: Clock identifier for the device for this request.
1020 * Each device has it's own set of clock inputs. This indexes
1021 * which clock input to modify.
1022 *
1023 * NOTE: This clock must have been requested by get_clock previously.
1024 *
1025 * Return: 0 if all went well, else returns appropriate error value.
1026 */
1027static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
1028 u32 dev_id, u8 clk_id)
1029{
1030 return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
1031 MSG_CLOCK_SW_STATE_AUTO);
1032}
1033
1034/**
1035 * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed
1036 * @handle: pointer to TI SCI handle
1037 * @dev_id: Device identifier this request is for
1038 * @clk_id: Clock identifier for the device for this request.
1039 * Each device has it's own set of clock inputs. This indexes
1040 * which clock input to modify.
1041 * @req_state: state indicating if the clock is auto managed
1042 *
1043 * Return: 0 if all went well, else returns appropriate error value.
1044 */
1045static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle,
1046 u32 dev_id, u8 clk_id, bool *req_state)
1047{
1048 u8 state = 0;
1049 int ret;
1050
1051 if (!req_state)
1052 return -EINVAL;
1053
1054 ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL);
1055 if (ret)
1056 return ret;
1057
1058 *req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
1059 return 0;
1060}
1061
1062/**
1063 * ti_sci_cmd_clk_is_on() - Is the clock ON
1064 * @handle: pointer to TI SCI handle
1065 * @dev_id: Device identifier this request is for
1066 * @clk_id: Clock identifier for the device for this request.
1067 * Each device has it's own set of clock inputs. This indexes
1068 * which clock input to modify.
1069 * @req_state: state indicating if the clock is managed by us and enabled
1070 * @curr_state: state indicating if the clock is ready for operation
1071 *
1072 * Return: 0 if all went well, else returns appropriate error value.
1073 */
1074static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id,
1075 u8 clk_id, bool *req_state, bool *curr_state)
1076{
1077 u8 c_state = 0, r_state = 0;
1078 int ret;
1079
1080 if (!req_state && !curr_state)
1081 return -EINVAL;
1082
1083 ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
1084 &r_state, &c_state);
1085 if (ret)
1086 return ret;
1087
1088 if (req_state)
1089 *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
1090 if (curr_state)
1091 *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
1092 return 0;
1093}
1094
1095/**
1096 * ti_sci_cmd_clk_is_off() - Is the clock OFF
1097 * @handle: pointer to TI SCI handle
1098 * @dev_id: Device identifier this request is for
1099 * @clk_id: Clock identifier for the device for this request.
1100 * Each device has it's own set of clock inputs. This indexes
1101 * which clock input to modify.
1102 * @req_state: state indicating if the clock is managed by us and disabled
1103 * @curr_state: state indicating if the clock is NOT ready for operation
1104 *
1105 * Return: 0 if all went well, else returns appropriate error value.
1106 */
1107static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id,
1108 u8 clk_id, bool *req_state, bool *curr_state)
1109{
1110 u8 c_state = 0, r_state = 0;
1111 int ret;
1112
1113 if (!req_state && !curr_state)
1114 return -EINVAL;
1115
1116 ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
1117 &r_state, &c_state);
1118 if (ret)
1119 return ret;
1120
1121 if (req_state)
1122 *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
1123 if (curr_state)
1124 *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
1125 return 0;
1126}
1127
1128/**
1129 * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock
1130 * @handle: pointer to TI SCI handle
1131 * @dev_id: Device identifier this request is for
1132 * @clk_id: Clock identifier for the device for this request.
1133 * Each device has it's own set of clock inputs. This indexes
1134 * which clock input to modify.
1135 * @parent_id: Parent clock identifier to set
1136 *
1137 * Return: 0 if all went well, else returns appropriate error value.
1138 */
1139static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle,
1140 u32 dev_id, u8 clk_id, u8 parent_id)
1141{
1142 struct ti_sci_info *info;
1143 struct ti_sci_msg_req_set_clock_parent *req;
1144 struct ti_sci_msg_hdr *resp;
1145 struct ti_sci_xfer *xfer;
1146 struct device *dev;
1147 int ret = 0;
1148
1149 if (IS_ERR(handle))
1150 return PTR_ERR(handle);
1151 if (!handle)
1152 return -EINVAL;
1153
1154 info = handle_to_ti_sci_info(handle);
1155 dev = info->dev;
1156
1157 xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT,
1158 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1159 sizeof(*req), sizeof(*resp));
1160 if (IS_ERR(xfer)) {
1161 ret = PTR_ERR(xfer);
1162 dev_err(dev, "Message alloc failed(%d)\n", ret);
1163 return ret;
1164 }
1165 req = (struct ti_sci_msg_req_set_clock_parent *)xfer->xfer_buf;
1166 req->dev_id = dev_id;
1167 req->clk_id = clk_id;
1168 req->parent_id = parent_id;
1169
1170 ret = ti_sci_do_xfer(info, xfer);
1171 if (ret) {
1172 dev_err(dev, "Mbox send fail %d\n", ret);
1173 goto fail;
1174 }
1175
1176 resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
1177
1178 ret = tis_sci_is_response_ack(resp) ? 0 : -ENODEV;
1179
1180fail:
1181 ti_sci_put_one_xfer(&info->minfo, xfer);
1182
1183 return ret;
1184}
1185
1186/**
1187 * ti_sci_cmd_clk_get_parent() - Get current parent clock source
1188 * @handle: pointer to TI SCI handle
1189 * @dev_id: Device identifier this request is for
1190 * @clk_id: Clock identifier for the device for this request.
1191 * Each device has it's own set of clock inputs. This indexes
1192 * which clock input to modify.
1193 * @parent_id: Current clock parent
1194 *
1195 * Return: 0 if all went well, else returns appropriate error value.
1196 */
1197static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle,
1198 u32 dev_id, u8 clk_id, u8 *parent_id)
1199{
1200 struct ti_sci_info *info;
1201 struct ti_sci_msg_req_get_clock_parent *req;
1202 struct ti_sci_msg_resp_get_clock_parent *resp;
1203 struct ti_sci_xfer *xfer;
1204 struct device *dev;
1205 int ret = 0;
1206
1207 if (IS_ERR(handle))
1208 return PTR_ERR(handle);
1209 if (!handle || !parent_id)
1210 return -EINVAL;
1211
1212 info = handle_to_ti_sci_info(handle);
1213 dev = info->dev;
1214
1215 xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT,
1216 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1217 sizeof(*req), sizeof(*resp));
1218 if (IS_ERR(xfer)) {
1219 ret = PTR_ERR(xfer);
1220 dev_err(dev, "Message alloc failed(%d)\n", ret);
1221 return ret;
1222 }
1223 req = (struct ti_sci_msg_req_get_clock_parent *)xfer->xfer_buf;
1224 req->dev_id = dev_id;
1225 req->clk_id = clk_id;
1226
1227 ret = ti_sci_do_xfer(info, xfer);
1228 if (ret) {
1229 dev_err(dev, "Mbox send fail %d\n", ret);
1230 goto fail;
1231 }
1232
1233 resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->xfer_buf;
1234
1235 if (!tis_sci_is_response_ack(resp))
1236 ret = -ENODEV;
1237 else
1238 *parent_id = resp->parent_id;
1239
1240fail:
1241 ti_sci_put_one_xfer(&info->minfo, xfer);
1242
1243 return ret;
1244}
1245
1246/**
1247 * ti_sci_cmd_clk_get_num_parents() - Get the number of parents of the current clock source
1248 * @handle: pointer to TI SCI handle
1249 * @dev_id: Device identifier this request is for
1250 * @clk_id: Clock identifier for the device for this request.
1251 * Each device has it's own set of clock inputs. This indexes
1252 * which clock input to modify.
1253 * @num_parents: Returns he number of parents to the current clock.
1254 *
1255 * Return: 0 if all went well, else returns appropriate error value.
1256 */
1257static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle,
1258 u32 dev_id, u8 clk_id,
1259 u8 *num_parents)
1260{
1261 struct ti_sci_info *info;
1262 struct ti_sci_msg_req_get_clock_num_parents *req;
1263 struct ti_sci_msg_resp_get_clock_num_parents *resp;
1264 struct ti_sci_xfer *xfer;
1265 struct device *dev;
1266 int ret = 0;
1267
1268 if (IS_ERR(handle))
1269 return PTR_ERR(handle);
1270 if (!handle || !num_parents)
1271 return -EINVAL;
1272
1273 info = handle_to_ti_sci_info(handle);
1274 dev = info->dev;
1275
1276 xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
1277 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1278 sizeof(*req), sizeof(*resp));
1279 if (IS_ERR(xfer)) {
1280 ret = PTR_ERR(xfer);
1281 dev_err(dev, "Message alloc failed(%d)\n", ret);
1282 return ret;
1283 }
1284 req = (struct ti_sci_msg_req_get_clock_num_parents *)xfer->xfer_buf;
1285 req->dev_id = dev_id;
1286 req->clk_id = clk_id;
1287
1288 ret = ti_sci_do_xfer(info, xfer);
1289 if (ret) {
1290 dev_err(dev, "Mbox send fail %d\n", ret);
1291 goto fail;
1292 }
1293
1294 resp = (struct ti_sci_msg_resp_get_clock_num_parents *)xfer->xfer_buf;
1295
1296 if (!tis_sci_is_response_ack(resp))
1297 ret = -ENODEV;
1298 else
1299 *num_parents = resp->num_parents;
1300
1301fail:
1302 ti_sci_put_one_xfer(&info->minfo, xfer);
1303
1304 return ret;
1305}
1306
1307/**
1308 * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency
1309 * @handle: pointer to TI SCI handle
1310 * @dev_id: Device identifier this request is for
1311 * @clk_id: Clock identifier for the device for this request.
1312 * Each device has it's own set of clock inputs. This indexes
1313 * which clock input to modify.
1314 * @min_freq: The minimum allowable frequency in Hz. This is the minimum
1315 * allowable programmed frequency and does not account for clock
1316 * tolerances and jitter.
1317 * @target_freq: The target clock frequency in Hz. A frequency will be
1318 * processed as close to this target frequency as possible.
1319 * @max_freq: The maximum allowable frequency in Hz. This is the maximum
1320 * allowable programmed frequency and does not account for clock
1321 * tolerances and jitter.
1322 * @match_freq: Frequency match in Hz response.
1323 *
1324 * Return: 0 if all went well, else returns appropriate error value.
1325 */
1326static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle,
1327 u32 dev_id, u8 clk_id, u64 min_freq,
1328 u64 target_freq, u64 max_freq,
1329 u64 *match_freq)
1330{
1331 struct ti_sci_info *info;
1332 struct ti_sci_msg_req_query_clock_freq *req;
1333 struct ti_sci_msg_resp_query_clock_freq *resp;
1334 struct ti_sci_xfer *xfer;
1335 struct device *dev;
1336 int ret = 0;
1337
1338 if (IS_ERR(handle))
1339 return PTR_ERR(handle);
1340 if (!handle || !match_freq)
1341 return -EINVAL;
1342
1343 info = handle_to_ti_sci_info(handle);
1344 dev = info->dev;
1345
1346 xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ,
1347 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1348 sizeof(*req), sizeof(*resp));
1349 if (IS_ERR(xfer)) {
1350 ret = PTR_ERR(xfer);
1351 dev_err(dev, "Message alloc failed(%d)\n", ret);
1352 return ret;
1353 }
1354 req = (struct ti_sci_msg_req_query_clock_freq *)xfer->xfer_buf;
1355 req->dev_id = dev_id;
1356 req->clk_id = clk_id;
1357 req->min_freq_hz = min_freq;
1358 req->target_freq_hz = target_freq;
1359 req->max_freq_hz = max_freq;
1360
1361 ret = ti_sci_do_xfer(info, xfer);
1362 if (ret) {
1363 dev_err(dev, "Mbox send fail %d\n", ret);
1364 goto fail;
1365 }
1366
1367 resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->xfer_buf;
1368
1369 if (!tis_sci_is_response_ack(resp))
1370 ret = -ENODEV;
1371 else
1372 *match_freq = resp->freq_hz;
1373
1374fail:
1375 ti_sci_put_one_xfer(&info->minfo, xfer);
1376
1377 return ret;
1378}
1379
1380/**
1381 * ti_sci_cmd_clk_set_freq() - Set a frequency for clock
1382 * @handle: pointer to TI SCI handle
1383 * @dev_id: Device identifier this request is for
1384 * @clk_id: Clock identifier for the device for this request.
1385 * Each device has it's own set of clock inputs. This indexes
1386 * which clock input to modify.
1387 * @min_freq: The minimum allowable frequency in Hz. This is the minimum
1388 * allowable programmed frequency and does not account for clock
1389 * tolerances and jitter.
1390 * @target_freq: The target clock frequency in Hz. A frequency will be
1391 * processed as close to this target frequency as possible.
1392 * @max_freq: The maximum allowable frequency in Hz. This is the maximum
1393 * allowable programmed frequency and does not account for clock
1394 * tolerances and jitter.
1395 *
1396 * Return: 0 if all went well, else returns appropriate error value.
1397 */
1398static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle,
1399 u32 dev_id, u8 clk_id, u64 min_freq,
1400 u64 target_freq, u64 max_freq)
1401{
1402 struct ti_sci_info *info;
1403 struct ti_sci_msg_req_set_clock_freq *req;
1404 struct ti_sci_msg_hdr *resp;
1405 struct ti_sci_xfer *xfer;
1406 struct device *dev;
1407 int ret = 0;
1408
1409 if (IS_ERR(handle))
1410 return PTR_ERR(handle);
1411 if (!handle)
1412 return -EINVAL;
1413
1414 info = handle_to_ti_sci_info(handle);
1415 dev = info->dev;
1416
1417 xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ,
1418 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1419 sizeof(*req), sizeof(*resp));
1420 if (IS_ERR(xfer)) {
1421 ret = PTR_ERR(xfer);
1422 dev_err(dev, "Message alloc failed(%d)\n", ret);
1423 return ret;
1424 }
1425 req = (struct ti_sci_msg_req_set_clock_freq *)xfer->xfer_buf;
1426 req->dev_id = dev_id;
1427 req->clk_id = clk_id;
1428 req->min_freq_hz = min_freq;
1429 req->target_freq_hz = target_freq;
1430 req->max_freq_hz = max_freq;
1431
1432 ret = ti_sci_do_xfer(info, xfer);
1433 if (ret) {
1434 dev_err(dev, "Mbox send fail %d\n", ret);
1435 goto fail;
1436 }
1437
1438 resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
1439
1440 ret = tis_sci_is_response_ack(resp) ? 0 : -ENODEV;
1441
1442fail:
1443 ti_sci_put_one_xfer(&info->minfo, xfer);
1444
1445 return ret;
1446}
1447
1448/**
1449 * ti_sci_cmd_clk_get_freq() - Get current frequency
1450 * @handle: pointer to TI SCI handle
1451 * @dev_id: Device identifier this request is for
1452 * @clk_id: Clock identifier for the device for this request.
1453 * Each device has it's own set of clock inputs. This indexes
1454 * which clock input to modify.
1455 * @freq: Currently frequency in Hz
1456 *
1457 * Return: 0 if all went well, else returns appropriate error value.
1458 */
1459static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
1460 u32 dev_id, u8 clk_id, u64 *freq)
1461{
1462 struct ti_sci_info *info;
1463 struct ti_sci_msg_req_get_clock_freq *req;
1464 struct ti_sci_msg_resp_get_clock_freq *resp;
1465 struct ti_sci_xfer *xfer;
1466 struct device *dev;
1467 int ret = 0;
1468
1469 if (IS_ERR(handle))
1470 return PTR_ERR(handle);
1471 if (!handle || !freq)
1472 return -EINVAL;
1473
1474 info = handle_to_ti_sci_info(handle);
1475 dev = info->dev;
1476
1477 xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ,
1478 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1479 sizeof(*req), sizeof(*resp));
1480 if (IS_ERR(xfer)) {
1481 ret = PTR_ERR(xfer);
1482 dev_err(dev, "Message alloc failed(%d)\n", ret);
1483 return ret;
1484 }
1485 req = (struct ti_sci_msg_req_get_clock_freq *)xfer->xfer_buf;
1486 req->dev_id = dev_id;
1487 req->clk_id = clk_id;
1488
1489 ret = ti_sci_do_xfer(info, xfer);
1490 if (ret) {
1491 dev_err(dev, "Mbox send fail %d\n", ret);
1492 goto fail;
1493 }
1494
1495 resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->xfer_buf;
1496
1497 if (!tis_sci_is_response_ack(resp))
1498 ret = -ENODEV;
1499 else
1500 *freq = resp->freq_hz;
1501
1502fail:
1503 ti_sci_put_one_xfer(&info->minfo, xfer);
1504
1505 return ret;
1506}
1507
1508/**
840 * ti_sci_setup_ops() - Setup the operations structures 1509 * ti_sci_setup_ops() - Setup the operations structures
841 * @info: pointer to TISCI pointer 1510 * @info: pointer to TISCI pointer
842 */ 1511 */
@@ -844,6 +1513,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
844{ 1513{
845 struct ti_sci_ops *ops = &info->handle.ops; 1514 struct ti_sci_ops *ops = &info->handle.ops;
846 struct ti_sci_dev_ops *dops = &ops->dev_ops; 1515 struct ti_sci_dev_ops *dops = &ops->dev_ops;
1516 struct ti_sci_clk_ops *cops = &ops->clk_ops;
847 1517
848 dops->get_device = ti_sci_cmd_get_device; 1518 dops->get_device = ti_sci_cmd_get_device;
849 dops->idle_device = ti_sci_cmd_idle_device; 1519 dops->idle_device = ti_sci_cmd_idle_device;
@@ -855,6 +1525,21 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
855 dops->is_stop = ti_sci_cmd_dev_is_stop; 1525 dops->is_stop = ti_sci_cmd_dev_is_stop;
856 dops->is_on = ti_sci_cmd_dev_is_on; 1526 dops->is_on = ti_sci_cmd_dev_is_on;
857 dops->is_transitioning = ti_sci_cmd_dev_is_trans; 1527 dops->is_transitioning = ti_sci_cmd_dev_is_trans;
1528
1529 cops->get_clock = ti_sci_cmd_get_clock;
1530 cops->idle_clock = ti_sci_cmd_idle_clock;
1531 cops->put_clock = ti_sci_cmd_put_clock;
1532 cops->is_auto = ti_sci_cmd_clk_is_auto;
1533 cops->is_on = ti_sci_cmd_clk_is_on;
1534 cops->is_off = ti_sci_cmd_clk_is_off;
1535
1536 cops->set_parent = ti_sci_cmd_clk_set_parent;
1537 cops->get_parent = ti_sci_cmd_clk_get_parent;
1538 cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
1539
1540 cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
1541 cops->set_freq = ti_sci_cmd_clk_set_freq;
1542 cops->get_freq = ti_sci_cmd_clk_get_freq;
858} 1543}
859 1544
860/** 1545/**
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index b5b0f9745933..d02615152f2c 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -51,6 +51,16 @@
51#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 51#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200
52#define TI_SCI_MSG_GET_DEVICE_STATE 0x0201 52#define TI_SCI_MSG_GET_DEVICE_STATE 0x0201
53 53
54/* Clock requests */
55#define TI_SCI_MSG_SET_CLOCK_STATE 0x0100
56#define TI_SCI_MSG_GET_CLOCK_STATE 0x0101
57#define TI_SCI_MSG_SET_CLOCK_PARENT 0x0102
58#define TI_SCI_MSG_GET_CLOCK_PARENT 0x0103
59#define TI_SCI_MSG_GET_NUM_CLOCK_PARENTS 0x0104
60#define TI_SCI_MSG_SET_CLOCK_FREQ 0x010c
61#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d
62#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e
63
54/** 64/**
55 * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses 65 * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
56 * @type: Type of messages: One of TI_SCI_MSG* values 66 * @type: Type of messages: One of TI_SCI_MSG* values
@@ -172,4 +182,283 @@ struct ti_sci_msg_resp_get_device_state {
172 u8 current_state; 182 u8 current_state;
173} __packed; 183} __packed;
174 184
185/**
186 * struct ti_sci_msg_req_set_clock_state - Request to setup a Clock state
187 * @hdr: Generic Header, Certain flags can be set specific to the clocks:
188 * MSG_FLAG_CLOCK_ALLOW_SSC: Allow this clock to be modified
189 * via spread spectrum clocking.
190 * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE: Allow this clock's
191 * frequency to be changed while it is running so long as it
192 * is within the min/max limits.
193 * MSG_FLAG_CLOCK_INPUT_TERM: Enable input termination, this
194 * is only applicable to clock inputs on the SoC pseudo-device.
195 * @dev_id: Device identifier this request is for
196 * @clk_id: Clock identifier for the device for this request.
197 * Each device has it's own set of clock inputs. This indexes
198 * which clock input to modify.
199 * @request_state: Request the state for the clock to be set to.
200 * MSG_CLOCK_SW_STATE_UNREQ: The IP does not require this clock,
201 * it can be disabled, regardless of the state of the device
202 * MSG_CLOCK_SW_STATE_AUTO: Allow the System Controller to
203 * automatically manage the state of this clock. If the device
204 * is enabled, then the clock is enabled. If the device is set
205 * to off or retention, then the clock is internally set as not
206 * being required by the device.(default)
207 * MSG_CLOCK_SW_STATE_REQ: Configure the clock to be enabled,
208 * regardless of the state of the device.
209 *
210 * Normally, all required clocks are managed by TISCI entity, this is used
211 * only for specific control *IF* required. Auto managed state is
212 * MSG_CLOCK_SW_STATE_AUTO, in other states, TISCI entity assume remote
213 * will explicitly control.
214 *
215 * Request type is TI_SCI_MSG_SET_CLOCK_STATE, response is a generic
216 * ACK or NACK message.
217 */
218struct ti_sci_msg_req_set_clock_state {
219 /* Additional hdr->flags options */
220#define MSG_FLAG_CLOCK_ALLOW_SSC TISCI_MSG_FLAG(8)
221#define MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE TISCI_MSG_FLAG(9)
222#define MSG_FLAG_CLOCK_INPUT_TERM TISCI_MSG_FLAG(10)
223 struct ti_sci_msg_hdr hdr;
224 u32 dev_id;
225 u8 clk_id;
226#define MSG_CLOCK_SW_STATE_UNREQ 0
227#define MSG_CLOCK_SW_STATE_AUTO 1
228#define MSG_CLOCK_SW_STATE_REQ 2
229 u8 request_state;
230} __packed;
231
232/**
233 * struct ti_sci_msg_req_get_clock_state - Request for clock state
234 * @hdr: Generic Header
235 * @dev_id: Device identifier this request is for
236 * @clk_id: Clock identifier for the device for this request.
237 * Each device has it's own set of clock inputs. This indexes
238 * which clock input to get state of.
239 *
240 * Request type is TI_SCI_MSG_GET_CLOCK_STATE, response is state
241 * of the clock
242 */
243struct ti_sci_msg_req_get_clock_state {
244 struct ti_sci_msg_hdr hdr;
245 u32 dev_id;
246 u8 clk_id;
247} __packed;
248
249/**
250 * struct ti_sci_msg_resp_get_clock_state - Response to get clock state
251 * @hdr: Generic Header
252 * @programmed_state: Any programmed state of the clock. This is one of
253 * MSG_CLOCK_SW_STATE* values.
254 * @current_state: Current state of the clock. This is one of:
255 * MSG_CLOCK_HW_STATE_NOT_READY: Clock is not ready
256 * MSG_CLOCK_HW_STATE_READY: Clock is ready
257 *
258 * Response to TI_SCI_MSG_GET_CLOCK_STATE.
259 */
260struct ti_sci_msg_resp_get_clock_state {
261 struct ti_sci_msg_hdr hdr;
262 u8 programmed_state;
263#define MSG_CLOCK_HW_STATE_NOT_READY 0
264#define MSG_CLOCK_HW_STATE_READY 1
265 u8 current_state;
266} __packed;
267
268/**
269 * struct ti_sci_msg_req_set_clock_parent - Set the clock parent
270 * @hdr: Generic Header
271 * @dev_id: Device identifier this request is for
272 * @clk_id: Clock identifier for the device for this request.
273 * Each device has it's own set of clock inputs. This indexes
274 * which clock input to modify.
275 * @parent_id: The new clock parent is selectable by an index via this
276 * parameter.
277 *
278 * Request type is TI_SCI_MSG_SET_CLOCK_PARENT, response is generic
279 * ACK / NACK message.
280 */
281struct ti_sci_msg_req_set_clock_parent {
282 struct ti_sci_msg_hdr hdr;
283 u32 dev_id;
284 u8 clk_id;
285 u8 parent_id;
286} __packed;
287
288/**
289 * struct ti_sci_msg_req_get_clock_parent - Get the clock parent
290 * @hdr: Generic Header
291 * @dev_id: Device identifier this request is for
292 * @clk_id: Clock identifier for the device for this request.
293 * Each device has it's own set of clock inputs. This indexes
294 * which clock input to get the parent for.
295 *
296 * Request type is TI_SCI_MSG_GET_CLOCK_PARENT, response is parent information
297 */
298struct ti_sci_msg_req_get_clock_parent {
299 struct ti_sci_msg_hdr hdr;
300 u32 dev_id;
301 u8 clk_id;
302} __packed;
303
304/**
305 * struct ti_sci_msg_resp_get_clock_parent - Response with clock parent
306 * @hdr: Generic Header
307 * @parent_id: The current clock parent
308 *
309 * Response to TI_SCI_MSG_GET_CLOCK_PARENT.
310 */
311struct ti_sci_msg_resp_get_clock_parent {
312 struct ti_sci_msg_hdr hdr;
313 u8 parent_id;
314} __packed;
315
316/**
317 * struct ti_sci_msg_req_get_clock_num_parents - Request to get clock parents
318 * @hdr: Generic header
319 * @dev_id: Device identifier this request is for
320 * @clk_id: Clock identifier for the device for this request.
321 *
322 * This request provides information about how many clock parent options
323 * are available for a given clock to a device. This is typically used
324 * for input clocks.
325 *
326 * Request type is TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, response is appropriate
327 * message, or NACK in case of inability to satisfy request.
328 */
329struct ti_sci_msg_req_get_clock_num_parents {
330 struct ti_sci_msg_hdr hdr;
331 u32 dev_id;
332 u8 clk_id;
333} __packed;
334
335/**
336 * struct ti_sci_msg_resp_get_clock_num_parents - Response for get clk parents
337 * @hdr: Generic header
338 * @num_parents: Number of clock parents
339 *
340 * Response to TI_SCI_MSG_GET_NUM_CLOCK_PARENTS
341 */
342struct ti_sci_msg_resp_get_clock_num_parents {
343 struct ti_sci_msg_hdr hdr;
344 u8 num_parents;
345} __packed;
346
347/**
348 * struct ti_sci_msg_req_query_clock_freq - Request to query a frequency
349 * @hdr: Generic Header
350 * @dev_id: Device identifier this request is for
351 * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum
352 * allowable programmed frequency and does not account for clock
353 * tolerances and jitter.
354 * @target_freq_hz: The target clock frequency. A frequency will be found
355 * as close to this target frequency as possible.
356 * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum
357 * allowable programmed frequency and does not account for clock
358 * tolerances and jitter.
359 * @clk_id: Clock identifier for the device for this request.
360 *
361 * NOTE: Normally clock frequency management is automatically done by TISCI
362 * entity. In case of specific requests, TISCI evaluates capability to achieve
363 * requested frequency within provided range and responds with
364 * result message.
365 *
366 * Request type is TI_SCI_MSG_QUERY_CLOCK_FREQ, response is appropriate message,
367 * or NACK in case of inability to satisfy request.
368 */
369struct ti_sci_msg_req_query_clock_freq {
370 struct ti_sci_msg_hdr hdr;
371 u32 dev_id;
372 u64 min_freq_hz;
373 u64 target_freq_hz;
374 u64 max_freq_hz;
375 u8 clk_id;
376} __packed;
377
378/**
379 * struct ti_sci_msg_resp_query_clock_freq - Response to a clock frequency query
380 * @hdr: Generic Header
381 * @freq_hz: Frequency that is the best match in Hz.
382 *
383 * Response to request type TI_SCI_MSG_QUERY_CLOCK_FREQ. NOTE: if the request
384 * cannot be satisfied, the message will be of type NACK.
385 */
386struct ti_sci_msg_resp_query_clock_freq {
387 struct ti_sci_msg_hdr hdr;
388 u64 freq_hz;
389} __packed;
390
391/**
392 * struct ti_sci_msg_req_set_clock_freq - Request to setup a clock frequency
393 * @hdr: Generic Header
394 * @dev_id: Device identifier this request is for
395 * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum
396 * allowable programmed frequency and does not account for clock
397 * tolerances and jitter.
398 * @target_freq_hz: The target clock frequency. The clock will be programmed
399 * at a rate as close to this target frequency as possible.
400 * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum
401 * allowable programmed frequency and does not account for clock
402 * tolerances and jitter.
403 * @clk_id: Clock identifier for the device for this request.
404 *
405 * NOTE: Normally clock frequency management is automatically done by TISCI
406 * entity. In case of specific requests, TISCI evaluates capability to achieve
407 * requested range and responds with success/failure message.
408 *
409 * This sets the desired frequency for a clock within an allowable
410 * range. This message will fail on an enabled clock unless
411 * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally,
412 * if other clocks have their frequency modified due to this message,
413 * they also must have the MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled.
414 *
415 * Calling set frequency on a clock input to the SoC pseudo-device will
416 * inform the PMMC of that clock's frequency. Setting a frequency of
417 * zero will indicate the clock is disabled.
418 *
419 * Calling set frequency on clock outputs from the SoC pseudo-device will
420 * function similarly to setting the clock frequency on a device.
421 *
422 * Request type is TI_SCI_MSG_SET_CLOCK_FREQ, response is a generic ACK/NACK
423 * message.
424 */
425struct ti_sci_msg_req_set_clock_freq {
426 struct ti_sci_msg_hdr hdr;
427 u32 dev_id;
428 u64 min_freq_hz;
429 u64 target_freq_hz;
430 u64 max_freq_hz;
431 u8 clk_id;
432} __packed;
433
434/**
435 * struct ti_sci_msg_req_get_clock_freq - Request to get the clock frequency
436 * @hdr: Generic Header
437 * @dev_id: Device identifier this request is for
438 * @clk_id: Clock identifier for the device for this request.
439 *
440 * NOTE: Normally clock frequency management is automatically done by TISCI
441 * entity. In some cases, clock frequencies are configured by host.
442 *
443 * Request type is TI_SCI_MSG_GET_CLOCK_FREQ, responded with clock frequency
444 * that the clock is currently at.
445 */
446struct ti_sci_msg_req_get_clock_freq {
447 struct ti_sci_msg_hdr hdr;
448 u32 dev_id;
449 u8 clk_id;
450} __packed;
451
452/**
453 * struct ti_sci_msg_resp_get_clock_freq - Response of clock frequency request
454 * @hdr: Generic Header
455 * @freq_hz: Frequency that the clock is currently on, in Hz.
456 *
457 * Response to request type TI_SCI_MSG_GET_CLOCK_FREQ.
458 */
459struct ti_sci_msg_resp_get_clock_freq {
460 struct ti_sci_msg_hdr hdr;
461 u64 freq_hz;
462} __packed;
463
175#endif /* __TI_SCI_H */ 464#endif /* __TI_SCI_H */
diff --git a/include/linux/ti_sci_protocol.h b/include/linux/ti_sci_protocol.h
index 4aa4c93dc78e..a7e25c651f3e 100644
--- a/include/linux/ti_sci_protocol.h
+++ b/include/linux/ti_sci_protocol.h
@@ -104,11 +104,89 @@ struct ti_sci_dev_ops {
104}; 104};
105 105
106/** 106/**
107 * struct ti_sci_clk_ops - Clock control operations
108 * @get_clock: Request for activation of clock and manage by processor
109 * - needs_ssc: 'true' if Spread Spectrum clock is desired.
110 * - can_change_freq: 'true' if frequency change is desired.
111 * - enable_input_term: 'true' if input termination is desired.
112 * @idle_clock: Request for Idling a clock managed by processor
113 * @put_clock: Release the clock to be auto managed by TISCI
114 * @is_auto: Is the clock being auto managed
115 * - req_state: state indicating if the clock is auto managed
116 * @is_on: Is the clock ON
117 * - req_state: if the clock is requested to be forced ON
118 * - current_state: if the clock is currently ON
119 * @is_off: Is the clock OFF
120 * - req_state: if the clock is requested to be forced OFF
121 * - current_state: if the clock is currently Gated
122 * @set_parent: Set the clock source of a specific device clock
123 * - parent_id: Parent clock identifier to set.
124 * @get_parent: Get the current clock source of a specific device clock
125 * - parent_id: Parent clock identifier which is the parent.
126 * @get_num_parents: Get the number of parents of the current clock source
127 * - num_parents: returns the number of parent clocks.
128 * @get_best_match_freq: Find a best matching frequency for a frequency
129 * range.
130 * - match_freq: Best matching frequency in Hz.
131 * @set_freq: Set the Clock frequency
132 * @get_freq: Get the Clock frequency
133 * - current_freq: Frequency in Hz that the clock is at.
134 *
135 * NOTE: for all these functions, the following parameters are generic in
136 * nature:
137 * -handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
138 * -did: Device identifier this request is for
139 * -cid: Clock identifier for the device for this request.
140 * Each device has it's own set of clock inputs. This indexes
141 * which clock input to modify.
142 * -min_freq: The minimum allowable frequency in Hz. This is the minimum
143 * allowable programmed frequency and does not account for clock
144 * tolerances and jitter.
145 * -target_freq: The target clock frequency in Hz. A frequency will be
146 * processed as close to this target frequency as possible.
147 * -max_freq: The maximum allowable frequency in Hz. This is the maximum
148 * allowable programmed frequency and does not account for clock
149 * tolerances and jitter.
150 *
151 * Request for the clock - NOTE: the client MUST maintain integrity of
152 * usage count by balancing get_clock with put_clock. No refcounting is
153 * managed by driver for that purpose.
154 */
155struct ti_sci_clk_ops {
156 int (*get_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid,
157 bool needs_ssc, bool can_change_freq,
158 bool enable_input_term);
159 int (*idle_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid);
160 int (*put_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid);
161 int (*is_auto)(const struct ti_sci_handle *handle, u32 did, u8 cid,
162 bool *req_state);
163 int (*is_on)(const struct ti_sci_handle *handle, u32 did, u8 cid,
164 bool *req_state, bool *current_state);
165 int (*is_off)(const struct ti_sci_handle *handle, u32 did, u8 cid,
166 bool *req_state, bool *current_state);
167 int (*set_parent)(const struct ti_sci_handle *handle, u32 did, u8 cid,
168 u8 parent_id);
169 int (*get_parent)(const struct ti_sci_handle *handle, u32 did, u8 cid,
170 u8 *parent_id);
171 int (*get_num_parents)(const struct ti_sci_handle *handle, u32 did,
172 u8 cid, u8 *num_parents);
173 int (*get_best_match_freq)(const struct ti_sci_handle *handle, u32 did,
174 u8 cid, u64 min_freq, u64 target_freq,
175 u64 max_freq, u64 *match_freq);
176 int (*set_freq)(const struct ti_sci_handle *handle, u32 did, u8 cid,
177 u64 min_freq, u64 target_freq, u64 max_freq);
178 int (*get_freq)(const struct ti_sci_handle *handle, u32 did, u8 cid,
179 u64 *current_freq);
180};
181
182/**
107 * struct ti_sci_ops - Function support for TI SCI 183 * struct ti_sci_ops - Function support for TI SCI
108 * @dev_ops: Device specific operations 184 * @dev_ops: Device specific operations
185 * @clk_ops: Clock specific operations
109 */ 186 */
110struct ti_sci_ops { 187struct ti_sci_ops {
111 struct ti_sci_dev_ops dev_ops; 188 struct ti_sci_dev_ops dev_ops;
189 struct ti_sci_clk_ops clk_ops;
112}; 190};
113 191
114/** 192/**