55 */
66
77#include <linux/array_size.h>
8+ #include <linux/auxiliary_bus.h>
89#include <linux/clk-provider.h>
910#include <linux/delay.h>
11+ #include <linux/idr.h>
1012#include <linux/mfd/syscon.h>
1113#include <linux/minmax.h>
1214#include <linux/module.h>
1315#include <linux/platform_device.h>
16+ #include <linux/slab.h>
17+ #include <soc/spacemit/k1-syscon.h>
1418
1519#include "ccu_common.h"
1620#include "ccu_pll.h"
1923
2024#include <dt-bindings/clock/spacemit,k1-syscon.h>
2125
22- /* APBS register offset */
23- #define APBS_PLL1_SWCR1 0x100
24- #define APBS_PLL1_SWCR2 0x104
25- #define APBS_PLL1_SWCR3 0x108
26- #define APBS_PLL2_SWCR1 0x118
27- #define APBS_PLL2_SWCR2 0x11c
28- #define APBS_PLL2_SWCR3 0x120
29- #define APBS_PLL3_SWCR1 0x124
30- #define APBS_PLL3_SWCR2 0x128
31- #define APBS_PLL3_SWCR3 0x12c
32-
33- /* MPMU register offset */
34- #define MPMU_POSR 0x0010
35- #define POSR_PLL1_LOCK BIT(27)
36- #define POSR_PLL2_LOCK BIT(28)
37- #define POSR_PLL3_LOCK BIT(29)
38- #define MPMU_SUCCR 0x0014
39- #define MPMU_ISCCR 0x0044
40- #define MPMU_WDTPCR 0x0200
41- #define MPMU_RIPCCR 0x0210
42- #define MPMU_ACGR 0x1024
43- #define MPMU_APBCSCR 0x1050
44- #define MPMU_SUCCR_1 0x10b0
45-
46- /* APBC register offset */
47- #define APBC_UART1_CLK_RST 0x00
48- #define APBC_UART2_CLK_RST 0x04
49- #define APBC_GPIO_CLK_RST 0x08
50- #define APBC_PWM0_CLK_RST 0x0c
51- #define APBC_PWM1_CLK_RST 0x10
52- #define APBC_PWM2_CLK_RST 0x14
53- #define APBC_PWM3_CLK_RST 0x18
54- #define APBC_TWSI8_CLK_RST 0x20
55- #define APBC_UART3_CLK_RST 0x24
56- #define APBC_RTC_CLK_RST 0x28
57- #define APBC_TWSI0_CLK_RST 0x2c
58- #define APBC_TWSI1_CLK_RST 0x30
59- #define APBC_TIMERS1_CLK_RST 0x34
60- #define APBC_TWSI2_CLK_RST 0x38
61- #define APBC_AIB_CLK_RST 0x3c
62- #define APBC_TWSI4_CLK_RST 0x40
63- #define APBC_TIMERS2_CLK_RST 0x44
64- #define APBC_ONEWIRE_CLK_RST 0x48
65- #define APBC_TWSI5_CLK_RST 0x4c
66- #define APBC_DRO_CLK_RST 0x58
67- #define APBC_IR_CLK_RST 0x5c
68- #define APBC_TWSI6_CLK_RST 0x60
69- #define APBC_COUNTER_CLK_SEL 0x64
70- #define APBC_TWSI7_CLK_RST 0x68
71- #define APBC_TSEN_CLK_RST 0x6c
72- #define APBC_UART4_CLK_RST 0x70
73- #define APBC_UART5_CLK_RST 0x74
74- #define APBC_UART6_CLK_RST 0x78
75- #define APBC_SSP3_CLK_RST 0x7c
76- #define APBC_SSPA0_CLK_RST 0x80
77- #define APBC_SSPA1_CLK_RST 0x84
78- #define APBC_IPC_AP2AUD_CLK_RST 0x90
79- #define APBC_UART7_CLK_RST 0x94
80- #define APBC_UART8_CLK_RST 0x98
81- #define APBC_UART9_CLK_RST 0x9c
82- #define APBC_CAN0_CLK_RST 0xa0
83- #define APBC_PWM4_CLK_RST 0xa8
84- #define APBC_PWM5_CLK_RST 0xac
85- #define APBC_PWM6_CLK_RST 0xb0
86- #define APBC_PWM7_CLK_RST 0xb4
87- #define APBC_PWM8_CLK_RST 0xb8
88- #define APBC_PWM9_CLK_RST 0xbc
89- #define APBC_PWM10_CLK_RST 0xc0
90- #define APBC_PWM11_CLK_RST 0xc4
91- #define APBC_PWM12_CLK_RST 0xc8
92- #define APBC_PWM13_CLK_RST 0xcc
93- #define APBC_PWM14_CLK_RST 0xd0
94- #define APBC_PWM15_CLK_RST 0xd4
95- #define APBC_PWM16_CLK_RST 0xd8
96- #define APBC_PWM17_CLK_RST 0xdc
97- #define APBC_PWM18_CLK_RST 0xe0
98- #define APBC_PWM19_CLK_RST 0xe4
99-
100- /* APMU register offset */
101- #define APMU_JPG_CLK_RES_CTRL 0x020
102- #define APMU_CSI_CCIC2_CLK_RES_CTRL 0x024
103- #define APMU_ISP_CLK_RES_CTRL 0x038
104- #define APMU_LCD_CLK_RES_CTRL1 0x044
105- #define APMU_LCD_SPI_CLK_RES_CTRL 0x048
106- #define APMU_LCD_CLK_RES_CTRL2 0x04c
107- #define APMU_CCIC_CLK_RES_CTRL 0x050
108- #define APMU_SDH0_CLK_RES_CTRL 0x054
109- #define APMU_SDH1_CLK_RES_CTRL 0x058
110- #define APMU_USB_CLK_RES_CTRL 0x05c
111- #define APMU_QSPI_CLK_RES_CTRL 0x060
112- #define APMU_DMA_CLK_RES_CTRL 0x064
113- #define APMU_AES_CLK_RES_CTRL 0x068
114- #define APMU_VPU_CLK_RES_CTRL 0x0a4
115- #define APMU_GPU_CLK_RES_CTRL 0x0cc
116- #define APMU_SDH2_CLK_RES_CTRL 0x0e0
117- #define APMU_PMUA_MC_CTRL 0x0e8
118- #define APMU_PMU_CC2_AP 0x100
119- #define APMU_PMUA_EM_CLK_RES_CTRL 0x104
120- #define APMU_AUDIO_CLK_RES_CTRL 0x14c
121- #define APMU_HDMI_CLK_RES_CTRL 0x1b8
122- #define APMU_CCI550_CLK_CTRL 0x300
123- #define APMU_ACLK_CLK_CTRL 0x388
124- #define APMU_CPU_C0_CLK_CTRL 0x38C
125- #define APMU_CPU_C1_CLK_CTRL 0x390
126- #define APMU_PCIE_CLK_RES_CTRL_0 0x3cc
127- #define APMU_PCIE_CLK_RES_CTRL_1 0x3d4
128- #define APMU_PCIE_CLK_RES_CTRL_2 0x3dc
129- #define APMU_EMAC0_CLK_RES_CTRL 0x3e4
130- #define APMU_EMAC1_CLK_RES_CTRL 0x3ec
131-
13226struct spacemit_ccu_data {
27+ const char * reset_name ;
13328 struct clk_hw * * hws ;
13429 size_t num ;
13530};
13631
32+ static DEFINE_IDA (auxiliary_ids );
33+
13734/* APBS clocks start, APBS region contains and only contains all PLL clocks */
13835
13936/*
@@ -170,7 +67,8 @@ CCU_FACTOR_GATE_DEFINE(pll1_d4, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(3), 4,
17067CCU_FACTOR_GATE_DEFINE (pll1_d5 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (4 ), 5 , 1 );
17168CCU_FACTOR_GATE_DEFINE (pll1_d6 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (5 ), 6 , 1 );
17269CCU_FACTOR_GATE_DEFINE (pll1_d7 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (6 ), 7 , 1 );
173- CCU_FACTOR_GATE_DEFINE (pll1_d8 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (7 ), 8 , 1 );
70+ CCU_FACTOR_GATE_FLAGS_DEFINE (pll1_d8 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (7 ), 8 , 1 ,
71+ CLK_IS_CRITICAL );
17472CCU_FACTOR_GATE_DEFINE (pll1_d11_223p4 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (15 ), 11 , 1 );
17573CCU_FACTOR_GATE_DEFINE (pll1_d13_189 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (16 ), 13 , 1 );
17674CCU_FACTOR_GATE_DEFINE (pll1_d23_106p8 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (20 ), 23 , 1 );
@@ -819,8 +717,9 @@ static struct clk_hw *k1_ccu_pll_hws[] = {
819717};
820718
821719static const struct spacemit_ccu_data k1_ccu_pll_data = {
822- .hws = k1_ccu_pll_hws ,
823- .num = ARRAY_SIZE (k1_ccu_pll_hws ),
720+ /* The PLL CCU implements no resets */
721+ .hws = k1_ccu_pll_hws ,
722+ .num = ARRAY_SIZE (k1_ccu_pll_hws ),
824723};
825724
826725static struct clk_hw * k1_ccu_mpmu_hws [] = {
@@ -860,8 +759,9 @@ static struct clk_hw *k1_ccu_mpmu_hws[] = {
860759};
861760
862761static const struct spacemit_ccu_data k1_ccu_mpmu_data = {
863- .hws = k1_ccu_mpmu_hws ,
864- .num = ARRAY_SIZE (k1_ccu_mpmu_hws ),
762+ .reset_name = "mpmu-reset" ,
763+ .hws = k1_ccu_mpmu_hws ,
764+ .num = ARRAY_SIZE (k1_ccu_mpmu_hws ),
865765};
866766
867767static struct clk_hw * k1_ccu_apbc_hws [] = {
@@ -968,8 +868,9 @@ static struct clk_hw *k1_ccu_apbc_hws[] = {
968868};
969869
970870static const struct spacemit_ccu_data k1_ccu_apbc_data = {
971- .hws = k1_ccu_apbc_hws ,
972- .num = ARRAY_SIZE (k1_ccu_apbc_hws ),
871+ .reset_name = "apbc-reset" ,
872+ .hws = k1_ccu_apbc_hws ,
873+ .num = ARRAY_SIZE (k1_ccu_apbc_hws ),
973874};
974875
975876static struct clk_hw * k1_ccu_apmu_hws [] = {
@@ -1038,8 +939,21 @@ static struct clk_hw *k1_ccu_apmu_hws[] = {
1038939};
1039940
1040941static const struct spacemit_ccu_data k1_ccu_apmu_data = {
1041- .hws = k1_ccu_apmu_hws ,
1042- .num = ARRAY_SIZE (k1_ccu_apmu_hws ),
942+ .reset_name = "apmu-reset" ,
943+ .hws = k1_ccu_apmu_hws ,
944+ .num = ARRAY_SIZE (k1_ccu_apmu_hws ),
945+ };
946+
947+ static const struct spacemit_ccu_data k1_ccu_rcpu_data = {
948+ .reset_name = "rcpu-reset" ,
949+ };
950+
951+ static const struct spacemit_ccu_data k1_ccu_rcpu2_data = {
952+ .reset_name = "rcpu2-reset" ,
953+ };
954+
955+ static const struct spacemit_ccu_data k1_ccu_apbc2_data = {
956+ .reset_name = "apbc2-reset" ,
1043957};
1044958
1045959static int spacemit_ccu_register (struct device * dev ,
@@ -1050,6 +964,10 @@ static int spacemit_ccu_register(struct device *dev,
1050964 struct clk_hw_onecell_data * clk_data ;
1051965 int i , ret ;
1052966
967+ /* Nothing to do if the CCU does not implement any clocks */
968+ if (!data -> hws )
969+ return 0 ;
970+
1053971 clk_data = devm_kzalloc (dev , struct_size (clk_data , hws , data -> num ),
1054972 GFP_KERNEL );
1055973 if (!clk_data )
@@ -1090,9 +1008,74 @@ static int spacemit_ccu_register(struct device *dev,
10901008 return ret ;
10911009}
10921010
1011+ static void spacemit_cadev_release (struct device * dev )
1012+ {
1013+ struct auxiliary_device * adev = to_auxiliary_dev (dev );
1014+
1015+ ida_free (& auxiliary_ids , adev -> id );
1016+ kfree (to_spacemit_ccu_adev (adev ));
1017+ }
1018+
1019+ static void spacemit_adev_unregister (void * data )
1020+ {
1021+ struct auxiliary_device * adev = data ;
1022+
1023+ auxiliary_device_delete (adev );
1024+ auxiliary_device_uninit (adev );
1025+ }
1026+
1027+ static int spacemit_ccu_reset_register (struct device * dev ,
1028+ struct regmap * regmap ,
1029+ const char * reset_name )
1030+ {
1031+ struct spacemit_ccu_adev * cadev ;
1032+ struct auxiliary_device * adev ;
1033+ int ret ;
1034+
1035+ /* Nothing to do if the CCU does not implement a reset controller */
1036+ if (!reset_name )
1037+ return 0 ;
1038+
1039+ cadev = kzalloc (sizeof (* cadev ), GFP_KERNEL );
1040+ if (!cadev )
1041+ return - ENOMEM ;
1042+
1043+ cadev -> regmap = regmap ;
1044+
1045+ adev = & cadev -> adev ;
1046+ adev -> name = reset_name ;
1047+ adev -> dev .parent = dev ;
1048+ adev -> dev .release = spacemit_cadev_release ;
1049+ adev -> dev .of_node = dev -> of_node ;
1050+ ret = ida_alloc (& auxiliary_ids , GFP_KERNEL );
1051+ if (ret < 0 )
1052+ goto err_free_cadev ;
1053+ adev -> id = ret ;
1054+
1055+ ret = auxiliary_device_init (adev );
1056+ if (ret )
1057+ goto err_free_aux_id ;
1058+
1059+ ret = auxiliary_device_add (adev );
1060+ if (ret ) {
1061+ auxiliary_device_uninit (adev );
1062+ return ret ;
1063+ }
1064+
1065+ return devm_add_action_or_reset (dev , spacemit_adev_unregister , adev );
1066+
1067+ err_free_aux_id :
1068+ ida_free (& auxiliary_ids , adev -> id );
1069+ err_free_cadev :
1070+ kfree (cadev );
1071+
1072+ return ret ;
1073+ }
1074+
10931075static int k1_ccu_probe (struct platform_device * pdev )
10941076{
10951077 struct regmap * base_regmap , * lock_regmap = NULL ;
1078+ const struct spacemit_ccu_data * data ;
10961079 struct device * dev = & pdev -> dev ;
10971080 int ret ;
10981081
@@ -1121,11 +1104,16 @@ static int k1_ccu_probe(struct platform_device *pdev)
11211104 "failed to get lock regmap\n" );
11221105 }
11231106
1124- ret = spacemit_ccu_register (dev , base_regmap , lock_regmap ,
1125- of_device_get_match_data (dev ));
1107+ data = of_device_get_match_data (dev );
1108+
1109+ ret = spacemit_ccu_register (dev , base_regmap , lock_regmap , data );
11261110 if (ret )
11271111 return dev_err_probe (dev , ret , "failed to register clocks\n" );
11281112
1113+ ret = spacemit_ccu_reset_register (dev , base_regmap , data -> reset_name );
1114+ if (ret )
1115+ return dev_err_probe (dev , ret , "failed to register resets\n" );
1116+
11291117 return 0 ;
11301118}
11311119
@@ -1146,6 +1134,18 @@ static const struct of_device_id of_k1_ccu_match[] = {
11461134 .compatible = "spacemit,k1-syscon-apmu" ,
11471135 .data = & k1_ccu_apmu_data ,
11481136 },
1137+ {
1138+ .compatible = "spacemit,k1-syscon-rcpu" ,
1139+ .data = & k1_ccu_rcpu_data ,
1140+ },
1141+ {
1142+ .compatible = "spacemit,k1-syscon-rcpu2" ,
1143+ .data = & k1_ccu_rcpu2_data ,
1144+ },
1145+ {
1146+ .compatible = "spacemit,k1-syscon-apbc2" ,
1147+ .data = & k1_ccu_apbc2_data ,
1148+ },
11491149 { }
11501150};
11511151MODULE_DEVICE_TABLE (of , of_k1_ccu_match );
0 commit comments