aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNishanth Menon2015-11-06 18:11:23 -0600
committerTero Kristo2015-11-09 03:39:29 -0600
commitb90fea33c1560b69b5cb50a1da992ede077a37b4 (patch)
treee0f7b2e0efc4158a3b099e331da7182be8e28214
parent1edda4194e17a1011aaa54199f31d07ae3df3e9a (diff)
downloadti-linux-kernel-b90fea33c1560b69b5cb50a1da992ede077a37b4.tar.gz
ti-linux-kernel-b90fea33c1560b69b5cb50a1da992ede077a37b4.tar.xz
ti-linux-kernel-b90fea33c1560b69b5cb50a1da992ede077a37b4.zip
firmware: ti_sci: Add support for Clock control
Texas Instrument's System Control Interface (TI-SCI) Message Protocol is used in Texas Instrument's System on Chip (SoC) such as those in keystone family K2G SoC to communicate between various compute processors with a central system controller entity. SCI message protocol provides support for management of various hardware entitites within the SoC. Add support driver to allow communication with system controller entity within the SoC using the mailbox client. In general, we expect to function at a device level of abstraction, however, for proper operation of hardware blocks, many clocks directly supplying the hardware block needs to be queried or configured. Introduce support for the set of SCI message protocol support that provide us with this capability. Signed-off-by: Nishanth Menon <nm@ti.com>
-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/**