10
10
#include <linux/kernel.h>
11
11
#include <linux/io.h>
12
12
#include <linux/platform_device.h>
13
+ #include <linux/pm_opp.h>
13
14
#include <linux/pm_runtime.h>
14
15
#include <linux/pm_domain.h>
15
16
#include <linux/pm_qos.h>
@@ -1315,7 +1316,6 @@ EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweron);
1315
1316
#endif /* CONFIG_PM_SLEEP */
1316
1317
1317
1318
static struct generic_pm_domain_data * genpd_alloc_dev_data (struct device * dev ,
1318
- struct generic_pm_domain * genpd ,
1319
1319
struct gpd_timing_data * td )
1320
1320
{
1321
1321
struct generic_pm_domain_data * gpd_data ;
@@ -1384,7 +1384,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
1384
1384
if (IS_ERR_OR_NULL (genpd ) || IS_ERR_OR_NULL (dev ))
1385
1385
return - EINVAL ;
1386
1386
1387
- gpd_data = genpd_alloc_dev_data (dev , genpd , td );
1387
+ gpd_data = genpd_alloc_dev_data (dev , td );
1388
1388
if (IS_ERR (gpd_data ))
1389
1389
return PTR_ERR (gpd_data );
1390
1390
@@ -1413,23 +1413,21 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
1413
1413
}
1414
1414
1415
1415
/**
1416
- * __pm_genpd_add_device - Add a device to an I/O PM domain.
1416
+ * pm_genpd_add_device - Add a device to an I/O PM domain.
1417
1417
* @genpd: PM domain to add the device to.
1418
1418
* @dev: Device to be added.
1419
- * @td: Set of PM QoS timing parameters to attach to the device.
1420
1419
*/
1421
- int __pm_genpd_add_device (struct generic_pm_domain * genpd , struct device * dev ,
1422
- struct gpd_timing_data * td )
1420
+ int pm_genpd_add_device (struct generic_pm_domain * genpd , struct device * dev )
1423
1421
{
1424
1422
int ret ;
1425
1423
1426
1424
mutex_lock (& gpd_list_lock );
1427
- ret = genpd_add_device (genpd , dev , td );
1425
+ ret = genpd_add_device (genpd , dev , NULL );
1428
1426
mutex_unlock (& gpd_list_lock );
1429
1427
1430
1428
return ret ;
1431
1429
}
1432
- EXPORT_SYMBOL_GPL (__pm_genpd_add_device );
1430
+ EXPORT_SYMBOL_GPL (pm_genpd_add_device );
1433
1431
1434
1432
static int genpd_remove_device (struct generic_pm_domain * genpd ,
1435
1433
struct device * dev )
@@ -1476,13 +1474,13 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
1476
1474
1477
1475
/**
1478
1476
* pm_genpd_remove_device - Remove a device from an I/O PM domain.
1479
- * @genpd: PM domain to remove the device from.
1480
1477
* @dev: Device to be removed.
1481
1478
*/
1482
- int pm_genpd_remove_device (struct generic_pm_domain * genpd ,
1483
- struct device * dev )
1479
+ int pm_genpd_remove_device (struct device * dev )
1484
1480
{
1485
- if (!genpd || genpd != genpd_lookup_dev (dev ))
1481
+ struct generic_pm_domain * genpd = genpd_lookup_dev (dev );
1482
+
1483
+ if (!genpd )
1486
1484
return - EINVAL ;
1487
1485
1488
1486
return genpd_remove_device (genpd , dev );
@@ -1691,6 +1689,9 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
1691
1689
return ret ;
1692
1690
}
1693
1691
1692
+ device_initialize (& genpd -> dev );
1693
+ dev_set_name (& genpd -> dev , "%s" , genpd -> name );
1694
+
1694
1695
mutex_lock (& gpd_list_lock );
1695
1696
list_add (& genpd -> gpd_list_node , & gpd_list );
1696
1697
mutex_unlock (& gpd_list_lock );
@@ -1887,14 +1888,33 @@ int of_genpd_add_provider_simple(struct device_node *np,
1887
1888
1888
1889
mutex_lock (& gpd_list_lock );
1889
1890
1890
- if (genpd_present (genpd )) {
1891
- ret = genpd_add_provider (np , genpd_xlate_simple , genpd );
1892
- if (!ret ) {
1893
- genpd -> provider = & np -> fwnode ;
1894
- genpd -> has_provider = true;
1891
+ if (!genpd_present (genpd ))
1892
+ goto unlock ;
1893
+
1894
+ genpd -> dev .of_node = np ;
1895
+
1896
+ /* Parse genpd OPP table */
1897
+ if (genpd -> set_performance_state ) {
1898
+ ret = dev_pm_opp_of_add_table (& genpd -> dev );
1899
+ if (ret ) {
1900
+ dev_err (& genpd -> dev , "Failed to add OPP table: %d\n" ,
1901
+ ret );
1902
+ goto unlock ;
1895
1903
}
1896
1904
}
1897
1905
1906
+ ret = genpd_add_provider (np , genpd_xlate_simple , genpd );
1907
+ if (ret ) {
1908
+ if (genpd -> set_performance_state )
1909
+ dev_pm_opp_of_remove_table (& genpd -> dev );
1910
+
1911
+ goto unlock ;
1912
+ }
1913
+
1914
+ genpd -> provider = & np -> fwnode ;
1915
+ genpd -> has_provider = true;
1916
+
1917
+ unlock :
1898
1918
mutex_unlock (& gpd_list_lock );
1899
1919
1900
1920
return ret ;
@@ -1909,6 +1929,7 @@ EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple);
1909
1929
int of_genpd_add_provider_onecell (struct device_node * np ,
1910
1930
struct genpd_onecell_data * data )
1911
1931
{
1932
+ struct generic_pm_domain * genpd ;
1912
1933
unsigned int i ;
1913
1934
int ret = - EINVAL ;
1914
1935
@@ -1921,13 +1942,27 @@ int of_genpd_add_provider_onecell(struct device_node *np,
1921
1942
data -> xlate = genpd_xlate_onecell ;
1922
1943
1923
1944
for (i = 0 ; i < data -> num_domains ; i ++ ) {
1924
- if (!data -> domains [i ])
1945
+ genpd = data -> domains [i ];
1946
+
1947
+ if (!genpd )
1925
1948
continue ;
1926
- if (!genpd_present (data -> domains [ i ] ))
1949
+ if (!genpd_present (genpd ))
1927
1950
goto error ;
1928
1951
1929
- data -> domains [i ]-> provider = & np -> fwnode ;
1930
- data -> domains [i ]-> has_provider = true;
1952
+ genpd -> dev .of_node = np ;
1953
+
1954
+ /* Parse genpd OPP table */
1955
+ if (genpd -> set_performance_state ) {
1956
+ ret = dev_pm_opp_of_add_table_indexed (& genpd -> dev , i );
1957
+ if (ret ) {
1958
+ dev_err (& genpd -> dev , "Failed to add OPP table for index %d: %d\n" ,
1959
+ i , ret );
1960
+ goto error ;
1961
+ }
1962
+ }
1963
+
1964
+ genpd -> provider = & np -> fwnode ;
1965
+ genpd -> has_provider = true;
1931
1966
}
1932
1967
1933
1968
ret = genpd_add_provider (np , data -> xlate , data );
@@ -1940,10 +1975,16 @@ int of_genpd_add_provider_onecell(struct device_node *np,
1940
1975
1941
1976
error :
1942
1977
while (i -- ) {
1943
- if (!data -> domains [i ])
1978
+ genpd = data -> domains [i ];
1979
+
1980
+ if (!genpd )
1944
1981
continue ;
1945
- data -> domains [i ]-> provider = NULL ;
1946
- data -> domains [i ]-> has_provider = false;
1982
+
1983
+ genpd -> provider = NULL ;
1984
+ genpd -> has_provider = false;
1985
+
1986
+ if (genpd -> set_performance_state )
1987
+ dev_pm_opp_of_remove_table (& genpd -> dev );
1947
1988
}
1948
1989
1949
1990
mutex_unlock (& gpd_list_lock );
@@ -1970,10 +2011,17 @@ void of_genpd_del_provider(struct device_node *np)
1970
2011
* provider, set the 'has_provider' to false
1971
2012
* so that the PM domain can be safely removed.
1972
2013
*/
1973
- list_for_each_entry (gpd , & gpd_list , gpd_list_node )
1974
- if (gpd -> provider == & np -> fwnode )
2014
+ list_for_each_entry (gpd , & gpd_list , gpd_list_node ) {
2015
+ if (gpd -> provider == & np -> fwnode ) {
1975
2016
gpd -> has_provider = false;
1976
2017
2018
+ if (!gpd -> set_performance_state )
2019
+ continue ;
2020
+
2021
+ dev_pm_opp_of_remove_table (& gpd -> dev );
2022
+ }
2023
+ }
2024
+
1977
2025
list_del (& cp -> link );
1978
2026
of_node_put (cp -> node );
1979
2027
kfree (cp );
@@ -2346,6 +2394,55 @@ int of_genpd_parse_idle_states(struct device_node *dn,
2346
2394
}
2347
2395
EXPORT_SYMBOL_GPL (of_genpd_parse_idle_states );
2348
2396
2397
+ /**
2398
+ * of_genpd_opp_to_performance_state- Gets performance state of device's
2399
+ * power domain corresponding to a DT node's "required-opps" property.
2400
+ *
2401
+ * @dev: Device for which the performance-state needs to be found.
2402
+ * @opp_node: DT node where the "required-opps" property is present. This can be
2403
+ * the device node itself (if it doesn't have an OPP table) or a node
2404
+ * within the OPP table of a device (if device has an OPP table).
2405
+ * @state: Pointer to return performance state.
2406
+ *
2407
+ * Returns performance state corresponding to the "required-opps" property of
2408
+ * a DT node. This calls platform specific genpd->opp_to_performance_state()
2409
+ * callback to translate power domain OPP to performance state.
2410
+ *
2411
+ * Returns performance state on success and 0 on failure.
2412
+ */
2413
+ unsigned int of_genpd_opp_to_performance_state (struct device * dev ,
2414
+ struct device_node * opp_node )
2415
+ {
2416
+ struct generic_pm_domain * genpd ;
2417
+ struct dev_pm_opp * opp ;
2418
+ int state = 0 ;
2419
+
2420
+ genpd = dev_to_genpd (dev );
2421
+ if (IS_ERR (genpd ))
2422
+ return 0 ;
2423
+
2424
+ if (unlikely (!genpd -> set_performance_state ))
2425
+ return 0 ;
2426
+
2427
+ genpd_lock (genpd );
2428
+
2429
+ opp = of_dev_pm_opp_find_required_opp (& genpd -> dev , opp_node );
2430
+ if (IS_ERR (opp )) {
2431
+ dev_err (dev , "Failed to find required OPP: %ld\n" ,
2432
+ PTR_ERR (opp ));
2433
+ goto unlock ;
2434
+ }
2435
+
2436
+ state = genpd -> opp_to_performance_state (genpd , opp );
2437
+ dev_pm_opp_put (opp );
2438
+
2439
+ unlock :
2440
+ genpd_unlock (genpd );
2441
+
2442
+ return state ;
2443
+ }
2444
+ EXPORT_SYMBOL_GPL (of_genpd_opp_to_performance_state );
2445
+
2349
2446
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
2350
2447
2351
2448
@@ -2613,6 +2710,19 @@ static int genpd_devices_show(struct seq_file *s, void *data)
2613
2710
return ret ;
2614
2711
}
2615
2712
2713
+ static int genpd_perf_state_show (struct seq_file * s , void * data )
2714
+ {
2715
+ struct generic_pm_domain * genpd = s -> private ;
2716
+
2717
+ if (genpd_lock_interruptible (genpd ))
2718
+ return - ERESTARTSYS ;
2719
+
2720
+ seq_printf (s , "%u\n" , genpd -> performance_state );
2721
+
2722
+ genpd_unlock (genpd );
2723
+ return 0 ;
2724
+ }
2725
+
2616
2726
#define define_genpd_open_function (name ) \
2617
2727
static int genpd_##name##_open(struct inode *inode, struct file *file) \
2618
2728
{ \
@@ -2626,6 +2736,7 @@ define_genpd_open_function(idle_states);
2626
2736
define_genpd_open_function (active_time );
2627
2737
define_genpd_open_function (total_idle_time );
2628
2738
define_genpd_open_function (devices );
2739
+ define_genpd_open_function (perf_state );
2629
2740
2630
2741
#define define_genpd_debugfs_fops (name ) \
2631
2742
static const struct file_operations genpd_##name##_fops = { \
@@ -2642,6 +2753,7 @@ define_genpd_debugfs_fops(idle_states);
2642
2753
define_genpd_debugfs_fops (active_time );
2643
2754
define_genpd_debugfs_fops (total_idle_time );
2644
2755
define_genpd_debugfs_fops (devices );
2756
+ define_genpd_debugfs_fops (perf_state );
2645
2757
2646
2758
static int __init genpd_debug_init (void )
2647
2759
{
@@ -2675,6 +2787,9 @@ static int __init genpd_debug_init(void)
2675
2787
d , genpd , & genpd_total_idle_time_fops );
2676
2788
debugfs_create_file ("devices" , 0444 ,
2677
2789
d , genpd , & genpd_devices_fops );
2790
+ if (genpd -> set_performance_state )
2791
+ debugfs_create_file ("perf_state" , 0444 ,
2792
+ d , genpd , & genpd_perf_state_fops );
2678
2793
}
2679
2794
2680
2795
return 0 ;
0 commit comments