@@ -139,7 +139,6 @@ struct rzg2l_pll5_mux_dsi_div_param {
139
139
* @num_resets: Number of Module Resets in info->resets[]
140
140
* @last_dt_core_clk: ID of the last Core Clock exported to DT
141
141
* @info: Pointer to platform data
142
- * @genpd: PM domain
143
142
* @mux_dsi_div_params: pll5 mux and dsi div parameters
144
143
*/
145
144
struct rzg2l_cpg_priv {
@@ -156,8 +155,6 @@ struct rzg2l_cpg_priv {
156
155
157
156
const struct rzg2l_cpg_info * info ;
158
157
159
- struct generic_pm_domain genpd ;
160
-
161
158
struct rzg2l_pll5_mux_dsi_div_param mux_dsi_div_params ;
162
159
};
163
160
@@ -1559,9 +1556,34 @@ static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_priv *priv,
1559
1556
return true;
1560
1557
}
1561
1558
1559
+ /**
1560
+ * struct rzg2l_cpg_pm_domains - RZ/G2L PM domains data structure
1561
+ * @onecell_data: cell data
1562
+ * @domains: generic PM domains
1563
+ */
1564
+ struct rzg2l_cpg_pm_domains {
1565
+ struct genpd_onecell_data onecell_data ;
1566
+ struct generic_pm_domain * domains [];
1567
+ };
1568
+
1569
+ /**
1570
+ * struct rzg2l_cpg_pd - RZ/G2L power domain data structure
1571
+ * @genpd: generic PM domain
1572
+ * @priv: pointer to CPG private data structure
1573
+ * @conf: CPG PM domain configuration info
1574
+ * @id: RZ/G2L power domain ID
1575
+ */
1576
+ struct rzg2l_cpg_pd {
1577
+ struct generic_pm_domain genpd ;
1578
+ struct rzg2l_cpg_priv * priv ;
1579
+ struct rzg2l_cpg_pm_domain_conf conf ;
1580
+ u16 id ;
1581
+ };
1582
+
1562
1583
static int rzg2l_cpg_attach_dev (struct generic_pm_domain * domain , struct device * dev )
1563
1584
{
1564
- struct rzg2l_cpg_priv * priv = container_of (domain , struct rzg2l_cpg_priv , genpd );
1585
+ struct rzg2l_cpg_pd * pd = container_of (domain , struct rzg2l_cpg_pd , genpd );
1586
+ struct rzg2l_cpg_priv * priv = pd -> priv ;
1565
1587
struct device_node * np = dev -> of_node ;
1566
1588
struct of_phandle_args clkspec ;
1567
1589
bool once = true;
@@ -1617,31 +1639,180 @@ static void rzg2l_cpg_detach_dev(struct generic_pm_domain *unused, struct device
1617
1639
}
1618
1640
1619
1641
static void rzg2l_cpg_genpd_remove (void * data )
1642
+ {
1643
+ struct genpd_onecell_data * celldata = data ;
1644
+
1645
+ for (unsigned int i = 0 ; i < celldata -> num_domains ; i ++ )
1646
+ pm_genpd_remove (celldata -> domains [i ]);
1647
+ }
1648
+
1649
+ static void rzg2l_cpg_genpd_remove_simple (void * data )
1620
1650
{
1621
1651
pm_genpd_remove (data );
1622
1652
}
1623
1653
1654
+ static int rzg2l_cpg_power_on (struct generic_pm_domain * domain )
1655
+ {
1656
+ struct rzg2l_cpg_pd * pd = container_of (domain , struct rzg2l_cpg_pd , genpd );
1657
+ struct rzg2l_cpg_reg_conf mstop = pd -> conf .mstop ;
1658
+ struct rzg2l_cpg_priv * priv = pd -> priv ;
1659
+
1660
+ /* Set MSTOP. */
1661
+ if (mstop .mask )
1662
+ writel (mstop .mask << 16 , priv -> base + mstop .off );
1663
+
1664
+ return 0 ;
1665
+ }
1666
+
1667
+ static int rzg2l_cpg_power_off (struct generic_pm_domain * domain )
1668
+ {
1669
+ struct rzg2l_cpg_pd * pd = container_of (domain , struct rzg2l_cpg_pd , genpd );
1670
+ struct rzg2l_cpg_reg_conf mstop = pd -> conf .mstop ;
1671
+ struct rzg2l_cpg_priv * priv = pd -> priv ;
1672
+
1673
+ /* Set MSTOP. */
1674
+ if (mstop .mask )
1675
+ writel (mstop .mask | (mstop .mask << 16 ), priv -> base + mstop .off );
1676
+
1677
+ return 0 ;
1678
+ }
1679
+
1680
+ static int __init rzg2l_cpg_pd_setup (struct rzg2l_cpg_pd * pd , bool always_on )
1681
+ {
1682
+ struct dev_power_governor * governor ;
1683
+
1684
+ pd -> genpd .flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP ;
1685
+ pd -> genpd .attach_dev = rzg2l_cpg_attach_dev ;
1686
+ pd -> genpd .detach_dev = rzg2l_cpg_detach_dev ;
1687
+ if (always_on ) {
1688
+ pd -> genpd .flags |= GENPD_FLAG_ALWAYS_ON ;
1689
+ governor = & pm_domain_always_on_gov ;
1690
+ } else {
1691
+ pd -> genpd .power_on = rzg2l_cpg_power_on ;
1692
+ pd -> genpd .power_off = rzg2l_cpg_power_off ;
1693
+ governor = & simple_qos_governor ;
1694
+ }
1695
+
1696
+ return pm_genpd_init (& pd -> genpd , governor , !always_on );
1697
+ }
1698
+
1624
1699
static int __init rzg2l_cpg_add_clk_domain (struct rzg2l_cpg_priv * priv )
1625
1700
{
1626
1701
struct device * dev = priv -> dev ;
1627
1702
struct device_node * np = dev -> of_node ;
1628
- struct generic_pm_domain * genpd = & priv -> genpd ;
1703
+ struct rzg2l_cpg_pd * pd ;
1704
+ int ret ;
1705
+
1706
+ pd = devm_kzalloc (dev , sizeof (* pd ), GFP_KERNEL );
1707
+ if (!pd )
1708
+ return - ENOMEM ;
1709
+
1710
+ pd -> genpd .name = np -> name ;
1711
+ pd -> priv = priv ;
1712
+ ret = rzg2l_cpg_pd_setup (pd , true);
1713
+ if (ret )
1714
+ return ret ;
1715
+
1716
+ ret = devm_add_action_or_reset (dev , rzg2l_cpg_genpd_remove_simple , & pd -> genpd );
1717
+ if (ret )
1718
+ return ret ;
1719
+
1720
+ return of_genpd_add_provider_simple (np , & pd -> genpd );
1721
+ }
1722
+
1723
+ static struct generic_pm_domain *
1724
+ rzg2l_cpg_pm_domain_xlate (const struct of_phandle_args * spec , void * data )
1725
+ {
1726
+ struct generic_pm_domain * domain = ERR_PTR (- ENOENT );
1727
+ struct genpd_onecell_data * genpd = data ;
1728
+
1729
+ if (spec -> args_count != 1 )
1730
+ return ERR_PTR (- EINVAL );
1731
+
1732
+ for (unsigned int i = 0 ; i < genpd -> num_domains ; i ++ ) {
1733
+ struct rzg2l_cpg_pd * pd = container_of (genpd -> domains [i ], struct rzg2l_cpg_pd ,
1734
+ genpd );
1735
+
1736
+ if (pd -> id == spec -> args [0 ]) {
1737
+ domain = & pd -> genpd ;
1738
+ break ;
1739
+ }
1740
+ }
1741
+
1742
+ return domain ;
1743
+ }
1744
+
1745
+ static int __init rzg2l_cpg_add_pm_domains (struct rzg2l_cpg_priv * priv )
1746
+ {
1747
+ const struct rzg2l_cpg_info * info = priv -> info ;
1748
+ struct device * dev = priv -> dev ;
1749
+ struct device_node * np = dev -> of_node ;
1750
+ struct rzg2l_cpg_pm_domains * domains ;
1751
+ struct generic_pm_domain * parent ;
1752
+ u32 ncells ;
1629
1753
int ret ;
1630
1754
1631
- genpd -> name = np -> name ;
1632
- genpd -> flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON |
1633
- GENPD_FLAG_ACTIVE_WAKEUP ;
1634
- genpd -> attach_dev = rzg2l_cpg_attach_dev ;
1635
- genpd -> detach_dev = rzg2l_cpg_detach_dev ;
1636
- ret = pm_genpd_init (genpd , & pm_domain_always_on_gov , false);
1755
+ ret = of_property_read_u32 (np , "#power-domain-cells" , & ncells );
1756
+ if (ret )
1757
+ return ret ;
1758
+
1759
+ /* For backward compatibility. */
1760
+ if (!ncells )
1761
+ return rzg2l_cpg_add_clk_domain (priv );
1762
+
1763
+ domains = devm_kzalloc (dev , struct_size (domains , domains , info -> num_pm_domains ),
1764
+ GFP_KERNEL );
1765
+ if (!domains )
1766
+ return - ENOMEM ;
1767
+
1768
+ domains -> onecell_data .domains = domains -> domains ;
1769
+ domains -> onecell_data .num_domains = info -> num_pm_domains ;
1770
+ domains -> onecell_data .xlate = rzg2l_cpg_pm_domain_xlate ;
1771
+
1772
+ ret = devm_add_action_or_reset (dev , rzg2l_cpg_genpd_remove , & domains -> onecell_data );
1637
1773
if (ret )
1638
1774
return ret ;
1639
1775
1640
- ret = devm_add_action_or_reset (dev , rzg2l_cpg_genpd_remove , genpd );
1776
+ for (unsigned int i = 0 ; i < info -> num_pm_domains ; i ++ ) {
1777
+ bool always_on = !!(info -> pm_domains [i ].flags & RZG2L_PD_F_ALWAYS_ON );
1778
+ struct rzg2l_cpg_pd * pd ;
1779
+
1780
+ pd = devm_kzalloc (dev , sizeof (* pd ), GFP_KERNEL );
1781
+ if (!pd )
1782
+ return - ENOMEM ;
1783
+
1784
+ pd -> genpd .name = info -> pm_domains [i ].name ;
1785
+ pd -> conf = info -> pm_domains [i ].conf ;
1786
+ pd -> id = info -> pm_domains [i ].id ;
1787
+ pd -> priv = priv ;
1788
+
1789
+ ret = rzg2l_cpg_pd_setup (pd , always_on );
1790
+ if (ret )
1791
+ return ret ;
1792
+
1793
+ if (always_on ) {
1794
+ ret = rzg2l_cpg_power_on (& pd -> genpd );
1795
+ if (ret )
1796
+ return ret ;
1797
+ }
1798
+
1799
+ domains -> domains [i ] = & pd -> genpd ;
1800
+ /* Parent should be on the very first entry of info->pm_domains[]. */
1801
+ if (!i ) {
1802
+ parent = & pd -> genpd ;
1803
+ continue ;
1804
+ }
1805
+
1806
+ ret = pm_genpd_add_subdomain (parent , & pd -> genpd );
1807
+ if (ret )
1808
+ return ret ;
1809
+ }
1810
+
1811
+ ret = of_genpd_add_provider_onecell (np , & domains -> onecell_data );
1641
1812
if (ret )
1642
1813
return ret ;
1643
1814
1644
- return of_genpd_add_provider_simple ( np , genpd ) ;
1815
+ return 0 ;
1645
1816
}
1646
1817
1647
1818
static int __init rzg2l_cpg_probe (struct platform_device * pdev )
@@ -1697,7 +1868,7 @@ static int __init rzg2l_cpg_probe(struct platform_device *pdev)
1697
1868
if (error )
1698
1869
return error ;
1699
1870
1700
- error = rzg2l_cpg_add_clk_domain (priv );
1871
+ error = rzg2l_cpg_add_pm_domains (priv );
1701
1872
if (error )
1702
1873
return error ;
1703
1874
0 commit comments