5
5
*/
6
6
7
7
#include <linux/array_size.h>
8
+ #include <linux/auxiliary_bus.h>
8
9
#include <linux/clk-provider.h>
9
10
#include <linux/delay.h>
11
+ #include <linux/idr.h>
10
12
#include <linux/mfd/syscon.h>
11
13
#include <linux/minmax.h>
12
14
#include <linux/module.h>
13
15
#include <linux/platform_device.h>
16
+ #include <linux/slab.h>
17
+ #include <soc/spacemit/k1-syscon.h>
14
18
15
19
#include "ccu_common.h"
16
20
#include "ccu_pll.h"
19
23
20
24
#include <dt-bindings/clock/spacemit,k1-syscon.h>
21
25
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
-
132
26
struct spacemit_ccu_data {
27
+ const char * reset_name ;
133
28
struct clk_hw * * hws ;
134
29
size_t num ;
135
30
};
136
31
32
+ static DEFINE_IDA (auxiliary_ids );
33
+
137
34
/* APBS clocks start, APBS region contains and only contains all PLL clocks */
138
35
139
36
/*
@@ -170,7 +67,8 @@ CCU_FACTOR_GATE_DEFINE(pll1_d4, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(3), 4,
170
67
CCU_FACTOR_GATE_DEFINE (pll1_d5 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (4 ), 5 , 1 );
171
68
CCU_FACTOR_GATE_DEFINE (pll1_d6 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (5 ), 6 , 1 );
172
69
CCU_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 );
174
72
CCU_FACTOR_GATE_DEFINE (pll1_d11_223p4 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (15 ), 11 , 1 );
175
73
CCU_FACTOR_GATE_DEFINE (pll1_d13_189 , CCU_PARENT_HW (pll1 ), APBS_PLL1_SWCR2 , BIT (16 ), 13 , 1 );
176
74
CCU_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[] = {
819
717
};
820
718
821
719
static 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 ),
824
723
};
825
724
826
725
static struct clk_hw * k1_ccu_mpmu_hws [] = {
@@ -860,8 +759,9 @@ static struct clk_hw *k1_ccu_mpmu_hws[] = {
860
759
};
861
760
862
761
static 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 ),
865
765
};
866
766
867
767
static struct clk_hw * k1_ccu_apbc_hws [] = {
@@ -968,8 +868,9 @@ static struct clk_hw *k1_ccu_apbc_hws[] = {
968
868
};
969
869
970
870
static 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 ),
973
874
};
974
875
975
876
static struct clk_hw * k1_ccu_apmu_hws [] = {
@@ -1038,8 +939,21 @@ static struct clk_hw *k1_ccu_apmu_hws[] = {
1038
939
};
1039
940
1040
941
static 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" ,
1043
957
};
1044
958
1045
959
static int spacemit_ccu_register (struct device * dev ,
@@ -1050,6 +964,10 @@ static int spacemit_ccu_register(struct device *dev,
1050
964
struct clk_hw_onecell_data * clk_data ;
1051
965
int i , ret ;
1052
966
967
+ /* Nothing to do if the CCU does not implement any clocks */
968
+ if (!data -> hws )
969
+ return 0 ;
970
+
1053
971
clk_data = devm_kzalloc (dev , struct_size (clk_data , hws , data -> num ),
1054
972
GFP_KERNEL );
1055
973
if (!clk_data )
@@ -1090,9 +1008,74 @@ static int spacemit_ccu_register(struct device *dev,
1090
1008
return ret ;
1091
1009
}
1092
1010
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
+
1093
1075
static int k1_ccu_probe (struct platform_device * pdev )
1094
1076
{
1095
1077
struct regmap * base_regmap , * lock_regmap = NULL ;
1078
+ const struct spacemit_ccu_data * data ;
1096
1079
struct device * dev = & pdev -> dev ;
1097
1080
int ret ;
1098
1081
@@ -1121,11 +1104,16 @@ static int k1_ccu_probe(struct platform_device *pdev)
1121
1104
"failed to get lock regmap\n" );
1122
1105
}
1123
1106
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 );
1126
1110
if (ret )
1127
1111
return dev_err_probe (dev , ret , "failed to register clocks\n" );
1128
1112
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
+
1129
1117
return 0 ;
1130
1118
}
1131
1119
@@ -1146,6 +1134,18 @@ static const struct of_device_id of_k1_ccu_match[] = {
1146
1134
.compatible = "spacemit,k1-syscon-apmu" ,
1147
1135
.data = & k1_ccu_apmu_data ,
1148
1136
},
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
+ },
1149
1149
{ }
1150
1150
};
1151
1151
MODULE_DEVICE_TABLE (of , of_k1_ccu_match );
0 commit comments