summaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorRajan Vaja <rajanv@xilinx.com>2018-09-12 15:38:38 -0400
committerMichal Simek <michal.simek@xilinx.com>2018-09-26 02:47:34 -0400
commitf9627312e20721681ea326bd2b7935bf8034b288 (patch)
tree02cebd0925084b4dd47e2ffa3746b8d229df7546 /drivers/firmware
parent59ecdd778879f171072b663f91de6c3a595e2ed4 (diff)
firmware: xilinx: Add clock APIs
Add clock APIs to control clocks through firmware interface. Signed-off-by: Rajan Vaja <rajanv@xilinx.com> Signed-off-by: Jolly Shah <jollys@xilinx.com> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/xilinx/zynqmp.c186
1 files changed, 184 insertions, 2 deletions
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 2a333c04955b..697f4fa23a45 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -250,13 +250,195 @@ static int get_set_conduit_method(struct device_node *np)
250 */ 250 */
251static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out) 251static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
252{ 252{
253 return zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1, 253 int ret;
254 qdata.arg2, qdata.arg3, out); 254
255 ret = zynqmp_pm_invoke_fn(PM_QUERY_DATA, qdata.qid, qdata.arg1,
256 qdata.arg2, qdata.arg3, out);
257
258 /*
259 * For clock name query, all bytes in SMC response are clock name
260 * characters and return code is always success. For invalid clocks,
261 * clock name bytes would be zeros.
262 */
263 return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
264}
265
266/**
267 * zynqmp_pm_clock_enable() - Enable the clock for given id
268 * @clock_id: ID of the clock to be enabled
269 *
270 * This function is used by master to enable the clock
271 * including peripherals and PLL clocks.
272 *
273 * Return: Returns status, either success or error+reason
274 */
275static int zynqmp_pm_clock_enable(u32 clock_id)
276{
277 return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL);
278}
279
280/**
281 * zynqmp_pm_clock_disable() - Disable the clock for given id
282 * @clock_id: ID of the clock to be disable
283 *
284 * This function is used by master to disable the clock
285 * including peripherals and PLL clocks.
286 *
287 * Return: Returns status, either success or error+reason
288 */
289static int zynqmp_pm_clock_disable(u32 clock_id)
290{
291 return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL);
292}
293
294/**
295 * zynqmp_pm_clock_getstate() - Get the clock state for given id
296 * @clock_id: ID of the clock to be queried
297 * @state: 1/0 (Enabled/Disabled)
298 *
299 * This function is used by master to get the state of clock
300 * including peripherals and PLL clocks.
301 *
302 * Return: Returns status, either success or error+reason
303 */
304static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
305{
306 u32 ret_payload[PAYLOAD_ARG_CNT];
307 int ret;
308
309 ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETSTATE, clock_id, 0,
310 0, 0, ret_payload);
311 *state = ret_payload[1];
312
313 return ret;
314}
315
316/**
317 * zynqmp_pm_clock_setdivider() - Set the clock divider for given id
318 * @clock_id: ID of the clock
319 * @divider: divider value
320 *
321 * This function is used by master to set divider for any clock
322 * to achieve desired rate.
323 *
324 * Return: Returns status, either success or error+reason
325 */
326static int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
327{
328 return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider,
329 0, 0, NULL);
330}
331
332/**
333 * zynqmp_pm_clock_getdivider() - Get the clock divider for given id
334 * @clock_id: ID of the clock
335 * @divider: divider value
336 *
337 * This function is used by master to get divider values
338 * for any clock.
339 *
340 * Return: Returns status, either success or error+reason
341 */
342static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
343{
344 u32 ret_payload[PAYLOAD_ARG_CNT];
345 int ret;
346
347 ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETDIVIDER, clock_id, 0,
348 0, 0, ret_payload);
349 *divider = ret_payload[1];
350
351 return ret;
352}
353
354/**
355 * zynqmp_pm_clock_setrate() - Set the clock rate for given id
356 * @clock_id: ID of the clock
357 * @rate: rate value in hz
358 *
359 * This function is used by master to set rate for any clock.
360 *
361 * Return: Returns status, either success or error+reason
362 */
363static int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
364{
365 return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id,
366 lower_32_bits(rate),
367 upper_32_bits(rate),
368 0, NULL);
369}
370
371/**
372 * zynqmp_pm_clock_getrate() - Get the clock rate for given id
373 * @clock_id: ID of the clock
374 * @rate: rate value in hz
375 *
376 * This function is used by master to get rate
377 * for any clock.
378 *
379 * Return: Returns status, either success or error+reason
380 */
381static int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
382{
383 u32 ret_payload[PAYLOAD_ARG_CNT];
384 int ret;
385
386 ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETRATE, clock_id, 0,
387 0, 0, ret_payload);
388 *rate = ((u64)ret_payload[2] << 32) | ret_payload[1];
389
390 return ret;
391}
392
393/**
394 * zynqmp_pm_clock_setparent() - Set the clock parent for given id
395 * @clock_id: ID of the clock
396 * @parent_id: parent id
397 *
398 * This function is used by master to set parent for any clock.
399 *
400 * Return: Returns status, either success or error+reason
401 */
402static int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
403{
404 return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id,
405 parent_id, 0, 0, NULL);
406}
407
408/**
409 * zynqmp_pm_clock_getparent() - Get the clock parent for given id
410 * @clock_id: ID of the clock
411 * @parent_id: parent id
412 *
413 * This function is used by master to get parent index
414 * for any clock.
415 *
416 * Return: Returns status, either success or error+reason
417 */
418static int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
419{
420 u32 ret_payload[PAYLOAD_ARG_CNT];
421 int ret;
422
423 ret = zynqmp_pm_invoke_fn(PM_CLOCK_GETPARENT, clock_id, 0,
424 0, 0, ret_payload);
425 *parent_id = ret_payload[1];
426
427 return ret;
255} 428}
256 429
257static const struct zynqmp_eemi_ops eemi_ops = { 430static const struct zynqmp_eemi_ops eemi_ops = {
258 .get_api_version = zynqmp_pm_get_api_version, 431 .get_api_version = zynqmp_pm_get_api_version,
259 .query_data = zynqmp_pm_query_data, 432 .query_data = zynqmp_pm_query_data,
433 .clock_enable = zynqmp_pm_clock_enable,
434 .clock_disable = zynqmp_pm_clock_disable,
435 .clock_getstate = zynqmp_pm_clock_getstate,
436 .clock_setdivider = zynqmp_pm_clock_setdivider,
437 .clock_getdivider = zynqmp_pm_clock_getdivider,
438 .clock_setrate = zynqmp_pm_clock_setrate,
439 .clock_getrate = zynqmp_pm_clock_getrate,
440 .clock_setparent = zynqmp_pm_clock_setparent,
441 .clock_getparent = zynqmp_pm_clock_getparent,
260}; 442};
261 443
262/** 444/**