8
8
#include <linux/bits.h>
9
9
#include <linux/of.h>
10
10
#include <linux/io.h>
11
+ #include <linux/io-64-nonatomic-hi-lo.h>
11
12
#include <linux/platform_device.h>
12
13
#include <linux/pm_opp.h>
13
14
#include <linux/sort.h>
@@ -293,7 +294,41 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain,
293
294
return ret ;
294
295
}
295
296
296
- static int scmi_perf_limits_set (const struct scmi_handle * handle , u32 domain ,
297
+ #define SCMI_PERF_FC_RING_DB (w ) \
298
+ do { \
299
+ u##w val = 0; \
300
+ \
301
+ if (db->mask) \
302
+ val = ioread##w(db->addr) & db->mask; \
303
+ iowrite##w((u##w)db->set | val, db->addr); \
304
+ } while (0)
305
+
306
+ static void scmi_perf_fc_ring_db (struct scmi_fc_db_info * db )
307
+ {
308
+ if (!db || !db -> addr )
309
+ return ;
310
+
311
+ if (db -> width == 1 )
312
+ SCMI_PERF_FC_RING_DB (8 );
313
+ else if (db -> width == 2 )
314
+ SCMI_PERF_FC_RING_DB (16 );
315
+ else if (db -> width == 4 )
316
+ SCMI_PERF_FC_RING_DB (32 );
317
+ else /* db->width == 8 */
318
+ #ifdef CONFIG_64BIT
319
+ SCMI_PERF_FC_RING_DB (64 );
320
+ #else
321
+ {
322
+ u64 val = 0 ;
323
+
324
+ if (db -> mask )
325
+ val = ioread64_hi_lo (db -> addr ) & db -> mask ;
326
+ iowrite64_hi_lo (db -> set , db -> addr );
327
+ }
328
+ #endif
329
+ }
330
+
331
+ static int scmi_perf_mb_limits_set (const struct scmi_handle * handle , u32 domain ,
297
332
u32 max_perf , u32 min_perf )
298
333
{
299
334
int ret ;
@@ -316,7 +351,23 @@ static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain,
316
351
return ret ;
317
352
}
318
353
319
- static int scmi_perf_limits_get (const struct scmi_handle * handle , u32 domain ,
354
+ static int scmi_perf_limits_set (const struct scmi_handle * handle , u32 domain ,
355
+ u32 max_perf , u32 min_perf )
356
+ {
357
+ struct scmi_perf_info * pi = handle -> perf_priv ;
358
+ struct perf_dom_info * dom = pi -> dom_info + domain ;
359
+
360
+ if (dom -> fc_info && dom -> fc_info -> limit_set_addr ) {
361
+ iowrite32 (max_perf , dom -> fc_info -> limit_set_addr );
362
+ iowrite32 (min_perf , dom -> fc_info -> limit_set_addr + 4 );
363
+ scmi_perf_fc_ring_db (dom -> fc_info -> limit_set_db );
364
+ return 0 ;
365
+ }
366
+
367
+ return scmi_perf_mb_limits_set (handle , domain , max_perf , min_perf );
368
+ }
369
+
370
+ static int scmi_perf_mb_limits_get (const struct scmi_handle * handle , u32 domain ,
320
371
u32 * max_perf , u32 * min_perf )
321
372
{
322
373
int ret ;
@@ -342,7 +393,22 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
342
393
return ret ;
343
394
}
344
395
345
- static int scmi_perf_level_set (const struct scmi_handle * handle , u32 domain ,
396
+ static int scmi_perf_limits_get (const struct scmi_handle * handle , u32 domain ,
397
+ u32 * max_perf , u32 * min_perf )
398
+ {
399
+ struct scmi_perf_info * pi = handle -> perf_priv ;
400
+ struct perf_dom_info * dom = pi -> dom_info + domain ;
401
+
402
+ if (dom -> fc_info && dom -> fc_info -> limit_get_addr ) {
403
+ * max_perf = ioread32 (dom -> fc_info -> limit_get_addr );
404
+ * min_perf = ioread32 (dom -> fc_info -> limit_get_addr + 4 );
405
+ return 0 ;
406
+ }
407
+
408
+ return scmi_perf_mb_limits_get (handle , domain , max_perf , min_perf );
409
+ }
410
+
411
+ static int scmi_perf_mb_level_set (const struct scmi_handle * handle , u32 domain ,
346
412
u32 level , bool poll )
347
413
{
348
414
int ret ;
@@ -365,7 +431,22 @@ static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain,
365
431
return ret ;
366
432
}
367
433
368
- static int scmi_perf_level_get (const struct scmi_handle * handle , u32 domain ,
434
+ static int scmi_perf_level_set (const struct scmi_handle * handle , u32 domain ,
435
+ u32 level , bool poll )
436
+ {
437
+ struct scmi_perf_info * pi = handle -> perf_priv ;
438
+ struct perf_dom_info * dom = pi -> dom_info + domain ;
439
+
440
+ if (dom -> fc_info && dom -> fc_info -> level_set_addr ) {
441
+ iowrite32 (level , dom -> fc_info -> level_set_addr );
442
+ scmi_perf_fc_ring_db (dom -> fc_info -> level_set_db );
443
+ return 0 ;
444
+ }
445
+
446
+ return scmi_perf_mb_level_set (handle , domain , level , poll );
447
+ }
448
+
449
+ static int scmi_perf_mb_level_get (const struct scmi_handle * handle , u32 domain ,
369
450
u32 * level , bool poll )
370
451
{
371
452
int ret ;
@@ -387,6 +468,20 @@ static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain,
387
468
return ret ;
388
469
}
389
470
471
+ static int scmi_perf_level_get (const struct scmi_handle * handle , u32 domain ,
472
+ u32 * level , bool poll )
473
+ {
474
+ struct scmi_perf_info * pi = handle -> perf_priv ;
475
+ struct perf_dom_info * dom = pi -> dom_info + domain ;
476
+
477
+ if (dom -> fc_info && dom -> fc_info -> level_get_addr ) {
478
+ * level = ioread32 (dom -> fc_info -> level_get_addr );
479
+ return 0 ;
480
+ }
481
+
482
+ return scmi_perf_mb_level_get (handle , domain , level , poll );
483
+ }
484
+
390
485
static bool scmi_perf_fc_size_is_valid (u32 msg , u32 size )
391
486
{
392
487
if ((msg == PERF_LEVEL_GET || msg == PERF_LEVEL_SET ) && size == 4 )
0 commit comments