30
30
31
31
struct imx8_soc_data {
32
32
char * name ;
33
- int (* soc_revision )(u32 * socrev , u64 * socuid );
33
+ const char * ocotp_compatible ;
34
+ int (* soc_revision )(struct platform_device * pdev , u32 * socrev , u64 * socuid );
35
+ };
36
+
37
+ struct imx8_soc_drvdata {
38
+ void __iomem * ocotp_base ;
39
+ struct clk * clk ;
34
40
};
35
41
36
42
#ifdef CONFIG_HAVE_ARM_SMCCC
@@ -49,30 +55,12 @@ static u32 imx8mq_soc_revision_from_atf(void)
49
55
static inline u32 imx8mq_soc_revision_from_atf (void ) { return 0 ; };
50
56
#endif
51
57
52
- static int imx8mq_soc_revision (u32 * socrev , u64 * socuid )
58
+ static int imx8mq_soc_revision (struct platform_device * pdev , u32 * socrev , u64 * socuid )
53
59
{
54
- struct device_node * np __free (device_node ) =
55
- of_find_compatible_node (NULL , NULL , "fsl,imx8mq-ocotp" );
56
- void __iomem * ocotp_base ;
60
+ struct imx8_soc_drvdata * drvdata = platform_get_drvdata (pdev );
61
+ void __iomem * ocotp_base = drvdata -> ocotp_base ;
57
62
u32 magic ;
58
63
u32 rev ;
59
- struct clk * clk ;
60
- int ret ;
61
-
62
- if (!np )
63
- return - EINVAL ;
64
-
65
- ocotp_base = of_iomap (np , 0 );
66
- if (!ocotp_base )
67
- return - EINVAL ;
68
-
69
- clk = of_clk_get_by_name (np , NULL );
70
- if (IS_ERR (clk )) {
71
- ret = PTR_ERR (clk );
72
- goto err_clk ;
73
- }
74
-
75
- clk_prepare_enable (clk );
76
64
77
65
/*
78
66
* SOC revision on older imx8mq is not available in fuses so query
@@ -91,55 +79,24 @@ static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
91
79
92
80
* socrev = rev ;
93
81
94
- clk_disable_unprepare (clk );
95
- clk_put (clk );
96
- iounmap (ocotp_base );
97
-
98
82
return 0 ;
99
-
100
- err_clk :
101
- iounmap (ocotp_base );
102
- return ret ;
103
83
}
104
84
105
- static int imx8mm_soc_uid (u64 * socuid )
85
+ static int imx8mm_soc_uid (struct platform_device * pdev , u64 * socuid )
106
86
{
107
- struct device_node * np __free (device_node ) =
108
- of_find_compatible_node (NULL , NULL , "fsl,imx8mm-ocotp" );
109
- void __iomem * ocotp_base ;
110
- struct clk * clk ;
111
- int ret = 0 ;
87
+ struct imx8_soc_drvdata * drvdata = platform_get_drvdata (pdev );
88
+ void __iomem * ocotp_base = drvdata -> ocotp_base ;
112
89
u32 offset = of_machine_is_compatible ("fsl,imx8mp" ) ?
113
90
IMX8MP_OCOTP_UID_OFFSET : 0 ;
114
91
115
- if (!np )
116
- return - EINVAL ;
117
-
118
- ocotp_base = of_iomap (np , 0 );
119
- if (!ocotp_base )
120
- return - EINVAL ;
121
-
122
- clk = of_clk_get_by_name (np , NULL );
123
- if (IS_ERR (clk )) {
124
- ret = PTR_ERR (clk );
125
- goto err_clk ;
126
- }
127
-
128
- clk_prepare_enable (clk );
129
-
130
92
* socuid = readl_relaxed (ocotp_base + OCOTP_UID_HIGH + offset );
131
93
* socuid <<= 32 ;
132
94
* socuid |= readl_relaxed (ocotp_base + OCOTP_UID_LOW + offset );
133
95
134
- clk_disable_unprepare (clk );
135
- clk_put (clk );
136
-
137
- err_clk :
138
- iounmap (ocotp_base );
139
- return ret ;
96
+ return 0 ;
140
97
}
141
98
142
- static int imx8mm_soc_revision (u32 * socrev , u64 * socuid )
99
+ static int imx8mm_soc_revision (struct platform_device * pdev , u32 * socrev , u64 * socuid )
143
100
{
144
101
struct device_node * np __free (device_node ) =
145
102
of_find_compatible_node (NULL , NULL , "fsl,imx8mm-anatop" );
@@ -156,26 +113,66 @@ static int imx8mm_soc_revision(u32 *socrev, u64 *socuid)
156
113
157
114
iounmap (anatop_base );
158
115
159
- return imx8mm_soc_uid (socuid );
116
+ return imx8mm_soc_uid (pdev , socuid );
117
+ }
118
+
119
+ static int imx8m_soc_prepare (struct platform_device * pdev , const char * ocotp_compatible )
120
+ {
121
+ struct device_node * np __free (device_node ) =
122
+ of_find_compatible_node (NULL , NULL , ocotp_compatible );
123
+ struct imx8_soc_drvdata * drvdata = platform_get_drvdata (pdev );
124
+ int ret = 0 ;
125
+
126
+ if (!np )
127
+ return - EINVAL ;
128
+
129
+ drvdata -> ocotp_base = of_iomap (np , 0 );
130
+ if (!drvdata -> ocotp_base )
131
+ return - EINVAL ;
132
+
133
+ drvdata -> clk = of_clk_get_by_name (np , NULL );
134
+ if (IS_ERR (drvdata -> clk )) {
135
+ ret = PTR_ERR (drvdata -> clk );
136
+ goto err_clk ;
137
+ }
138
+
139
+ return clk_prepare_enable (drvdata -> clk );
140
+
141
+ err_clk :
142
+ iounmap (drvdata -> ocotp_base );
143
+ return ret ;
144
+ }
145
+
146
+ static void imx8m_soc_unprepare (struct platform_device * pdev )
147
+ {
148
+ struct imx8_soc_drvdata * drvdata = platform_get_drvdata (pdev );
149
+
150
+ clk_disable_unprepare (drvdata -> clk );
151
+ clk_put (drvdata -> clk );
152
+ iounmap (drvdata -> ocotp_base );
160
153
}
161
154
162
155
static const struct imx8_soc_data imx8mq_soc_data = {
163
156
.name = "i.MX8MQ" ,
157
+ .ocotp_compatible = "fsl,imx8mq-ocotp" ,
164
158
.soc_revision = imx8mq_soc_revision ,
165
159
};
166
160
167
161
static const struct imx8_soc_data imx8mm_soc_data = {
168
162
.name = "i.MX8MM" ,
163
+ .ocotp_compatible = "fsl,imx8mm-ocotp" ,
169
164
.soc_revision = imx8mm_soc_revision ,
170
165
};
171
166
172
167
static const struct imx8_soc_data imx8mn_soc_data = {
173
168
.name = "i.MX8MN" ,
169
+ .ocotp_compatible = "fsl,imx8mm-ocotp" ,
174
170
.soc_revision = imx8mm_soc_revision ,
175
171
};
176
172
177
173
static const struct imx8_soc_data imx8mp_soc_data = {
178
174
.name = "i.MX8MP" ,
175
+ .ocotp_compatible = "fsl,imx8mm-ocotp" ,
179
176
.soc_revision = imx8mm_soc_revision ,
180
177
};
181
178
@@ -207,6 +204,7 @@ static int imx8m_soc_probe(struct platform_device *pdev)
207
204
struct soc_device_attribute * soc_dev_attr ;
208
205
struct platform_device * cpufreq_dev ;
209
206
const struct imx8_soc_data * data ;
207
+ struct imx8_soc_drvdata * drvdata ;
210
208
struct device * dev = & pdev -> dev ;
211
209
const struct of_device_id * id ;
212
210
struct soc_device * soc_dev ;
@@ -218,6 +216,12 @@ static int imx8m_soc_probe(struct platform_device *pdev)
218
216
if (!soc_dev_attr )
219
217
return - ENOMEM ;
220
218
219
+ drvdata = devm_kzalloc (dev , sizeof (* drvdata ), GFP_KERNEL );
220
+ if (!drvdata )
221
+ return - ENOMEM ;
222
+
223
+ platform_set_drvdata (pdev , drvdata );
224
+
221
225
soc_dev_attr -> family = "Freescale i.MX" ;
222
226
223
227
ret = of_property_read_string (of_root , "model" , & soc_dev_attr -> machine );
@@ -231,11 +235,18 @@ static int imx8m_soc_probe(struct platform_device *pdev)
231
235
data = id -> data ;
232
236
if (data ) {
233
237
soc_dev_attr -> soc_id = data -> name ;
238
+ ret = imx8m_soc_prepare (pdev , data -> ocotp_compatible );
239
+ if (ret )
240
+ return ret ;
241
+
234
242
if (data -> soc_revision ) {
235
- ret = data -> soc_revision (& soc_rev , & soc_uid );
236
- if (ret )
243
+ ret = data -> soc_revision (pdev , & soc_rev , & soc_uid );
244
+ if (ret ) {
245
+ imx8m_soc_unprepare (pdev );
237
246
return ret ;
247
+ }
238
248
}
249
+ imx8m_soc_unprepare (pdev );
239
250
}
240
251
241
252
soc_dev_attr -> revision = imx8_revision (dev , soc_rev );
0 commit comments