24
24
#define OCOTP_UID_HIGH 0x420
25
25
26
26
#define IMX8MP_OCOTP_UID_OFFSET 0x10
27
+ #define IMX8MP_OCOTP_UID_HIGH 0xE00
27
28
28
29
/* Same as ANADIG_DIGPROG_IMX7D */
29
30
#define ANADIG_DIGPROG_IMX8MM 0x800
30
31
31
32
struct imx8_soc_data {
32
33
char * name ;
33
- int (* soc_revision )(u32 * socrev , u64 * socuid );
34
+ const char * ocotp_compatible ;
35
+ int (* soc_revision )(struct platform_device * pdev , u32 * socrev );
36
+ int (* soc_uid )(struct platform_device * pdev , u64 * socuid );
37
+ };
38
+
39
+ struct imx8_soc_drvdata {
40
+ void __iomem * ocotp_base ;
41
+ struct clk * clk ;
34
42
};
35
43
36
44
#ifdef CONFIG_HAVE_ARM_SMCCC
@@ -49,30 +57,24 @@ static u32 imx8mq_soc_revision_from_atf(void)
49
57
static inline u32 imx8mq_soc_revision_from_atf (void ) { return 0 ; };
50
58
#endif
51
59
52
- static int imx8mq_soc_revision ( u32 * socrev , u64 * socuid )
60
+ static int imx8m_soc_uid ( struct platform_device * pdev , u64 * socuid )
53
61
{
54
- struct device_node * np __free (device_node ) =
55
- of_find_compatible_node (NULL , NULL , "fsl,imx8mq-ocotp" );
56
- void __iomem * ocotp_base ;
57
- u32 magic ;
58
- u32 rev ;
59
- struct clk * clk ;
60
- int ret ;
62
+ struct imx8_soc_drvdata * drvdata = platform_get_drvdata (pdev );
63
+ void __iomem * ocotp_base = drvdata -> ocotp_base ;
61
64
62
- if (!np )
63
- return - EINVAL ;
64
-
65
- ocotp_base = of_iomap (np , 0 );
66
- if (!ocotp_base )
67
- return - EINVAL ;
65
+ * socuid = readl_relaxed (ocotp_base + OCOTP_UID_HIGH );
66
+ * socuid <<= 32 ;
67
+ * socuid |= readl_relaxed (ocotp_base + OCOTP_UID_LOW );
68
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
- }
69
+ return 0 ;
70
+ }
74
71
75
- clk_prepare_enable (clk );
72
+ static int imx8mq_soc_revision (struct platform_device * pdev , u32 * socrev )
73
+ {
74
+ struct imx8_soc_drvdata * drvdata = platform_get_drvdata (pdev );
75
+ void __iomem * ocotp_base = drvdata -> ocotp_base ;
76
+ u32 magic ;
77
+ u32 rev ;
76
78
77
79
/*
78
80
* SOC revision on older imx8mq is not available in fuses so query
@@ -85,98 +87,109 @@ static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
85
87
rev = REV_B1 ;
86
88
}
87
89
88
- * socuid = readl_relaxed (ocotp_base + OCOTP_UID_HIGH );
89
- * socuid <<= 32 ;
90
- * socuid |= readl_relaxed (ocotp_base + OCOTP_UID_LOW );
91
-
92
90
* socrev = rev ;
93
91
94
- clk_disable_unprepare (clk );
95
- clk_put (clk );
96
- iounmap (ocotp_base );
97
-
98
92
return 0 ;
93
+ }
99
94
100
- err_clk :
101
- iounmap (ocotp_base );
102
- return ret ;
95
+ static int imx8mp_soc_uid (struct platform_device * pdev , u64 * socuid )
96
+ {
97
+ struct imx8_soc_drvdata * drvdata = platform_get_drvdata (pdev );
98
+ void __iomem * ocotp_base = drvdata -> ocotp_base ;
99
+
100
+ socuid [0 ] = readl_relaxed (ocotp_base + OCOTP_UID_HIGH + IMX8MP_OCOTP_UID_OFFSET );
101
+ socuid [0 ] <<= 32 ;
102
+ socuid [0 ] |= readl_relaxed (ocotp_base + OCOTP_UID_LOW + IMX8MP_OCOTP_UID_OFFSET );
103
+
104
+ socuid [1 ] = readl_relaxed (ocotp_base + IMX8MP_OCOTP_UID_HIGH + 0x10 );
105
+ socuid [1 ] <<= 32 ;
106
+ socuid [1 ] |= readl_relaxed (ocotp_base + IMX8MP_OCOTP_UID_HIGH );
107
+
108
+ return 0 ;
103
109
}
104
110
105
- static int imx8mm_soc_uid ( u64 * socuid )
111
+ static int imx8mm_soc_revision ( struct platform_device * pdev , u32 * socrev )
106
112
{
107
113
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 ;
112
- u32 offset = of_machine_is_compatible ("fsl,imx8mp" ) ?
113
- IMX8MP_OCOTP_UID_OFFSET : 0 ;
114
+ of_find_compatible_node (NULL , NULL , "fsl,imx8mm-anatop" );
115
+ void __iomem * anatop_base ;
114
116
115
117
if (!np )
116
118
return - EINVAL ;
117
119
118
- ocotp_base = of_iomap (np , 0 );
119
- if (!ocotp_base )
120
+ anatop_base = of_iomap (np , 0 );
121
+ if (!anatop_base )
120
122
return - EINVAL ;
121
123
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
- * socuid = readl_relaxed (ocotp_base + OCOTP_UID_HIGH + offset );
131
- * socuid <<= 32 ;
132
- * socuid |= readl_relaxed (ocotp_base + OCOTP_UID_LOW + offset );
124
+ * socrev = readl_relaxed (anatop_base + ANADIG_DIGPROG_IMX8MM );
133
125
134
- clk_disable_unprepare (clk );
135
- clk_put (clk );
126
+ iounmap (anatop_base );
136
127
137
- err_clk :
138
- iounmap (ocotp_base );
139
- return ret ;
128
+ return 0 ;
140
129
}
141
130
142
- static int imx8mm_soc_revision ( u32 * socrev , u64 * socuid )
131
+ static int imx8m_soc_prepare ( struct platform_device * pdev , const char * ocotp_compatible )
143
132
{
144
133
struct device_node * np __free (device_node ) =
145
- of_find_compatible_node (NULL , NULL , "fsl,imx8mm-anatop" );
146
- void __iomem * anatop_base ;
134
+ of_find_compatible_node (NULL , NULL , ocotp_compatible );
135
+ struct imx8_soc_drvdata * drvdata = platform_get_drvdata (pdev );
136
+ int ret = 0 ;
147
137
148
138
if (!np )
149
139
return - EINVAL ;
150
140
151
- anatop_base = of_iomap (np , 0 );
152
- if (!anatop_base )
141
+ drvdata -> ocotp_base = of_iomap (np , 0 );
142
+ if (!drvdata -> ocotp_base )
153
143
return - EINVAL ;
154
144
155
- * socrev = readl_relaxed (anatop_base + ANADIG_DIGPROG_IMX8MM );
145
+ drvdata -> clk = of_clk_get_by_name (np , NULL );
146
+ if (IS_ERR (drvdata -> clk )) {
147
+ ret = PTR_ERR (drvdata -> clk );
148
+ goto err_clk ;
149
+ }
156
150
157
- iounmap (anatop_base );
151
+ return clk_prepare_enable (drvdata -> clk );
152
+
153
+ err_clk :
154
+ iounmap (drvdata -> ocotp_base );
155
+ return ret ;
156
+ }
157
+
158
+ static void imx8m_soc_unprepare (struct platform_device * pdev )
159
+ {
160
+ struct imx8_soc_drvdata * drvdata = platform_get_drvdata (pdev );
158
161
159
- return imx8mm_soc_uid (socuid );
162
+ clk_disable_unprepare (drvdata -> clk );
163
+ clk_put (drvdata -> clk );
164
+ iounmap (drvdata -> ocotp_base );
160
165
}
161
166
162
167
static const struct imx8_soc_data imx8mq_soc_data = {
163
168
.name = "i.MX8MQ" ,
169
+ .ocotp_compatible = "fsl,imx8mq-ocotp" ,
164
170
.soc_revision = imx8mq_soc_revision ,
171
+ .soc_uid = imx8m_soc_uid ,
165
172
};
166
173
167
174
static const struct imx8_soc_data imx8mm_soc_data = {
168
175
.name = "i.MX8MM" ,
176
+ .ocotp_compatible = "fsl,imx8mm-ocotp" ,
169
177
.soc_revision = imx8mm_soc_revision ,
178
+ .soc_uid = imx8m_soc_uid ,
170
179
};
171
180
172
181
static const struct imx8_soc_data imx8mn_soc_data = {
173
182
.name = "i.MX8MN" ,
183
+ .ocotp_compatible = "fsl,imx8mm-ocotp" ,
174
184
.soc_revision = imx8mm_soc_revision ,
185
+ .soc_uid = imx8m_soc_uid ,
175
186
};
176
187
177
188
static const struct imx8_soc_data imx8mp_soc_data = {
178
189
.name = "i.MX8MP" ,
190
+ .ocotp_compatible = "fsl,imx8mm-ocotp" ,
179
191
.soc_revision = imx8mm_soc_revision ,
192
+ .soc_uid = imx8mp_soc_uid ,
180
193
};
181
194
182
195
static __maybe_unused const struct of_device_id imx8_soc_match [] = {
@@ -207,17 +220,24 @@ static int imx8m_soc_probe(struct platform_device *pdev)
207
220
struct soc_device_attribute * soc_dev_attr ;
208
221
struct platform_device * cpufreq_dev ;
209
222
const struct imx8_soc_data * data ;
223
+ struct imx8_soc_drvdata * drvdata ;
210
224
struct device * dev = & pdev -> dev ;
211
225
const struct of_device_id * id ;
212
226
struct soc_device * soc_dev ;
213
227
u32 soc_rev = 0 ;
214
- u64 soc_uid = 0 ;
228
+ u64 soc_uid [ 2 ] = { 0 , 0 } ;
215
229
int ret ;
216
230
217
231
soc_dev_attr = devm_kzalloc (dev , sizeof (* soc_dev_attr ), GFP_KERNEL );
218
232
if (!soc_dev_attr )
219
233
return - ENOMEM ;
220
234
235
+ drvdata = devm_kzalloc (dev , sizeof (* drvdata ), GFP_KERNEL );
236
+ if (!drvdata )
237
+ return - ENOMEM ;
238
+
239
+ platform_set_drvdata (pdev , drvdata );
240
+
221
241
soc_dev_attr -> family = "Freescale i.MX" ;
222
242
223
243
ret = of_property_read_string (of_root , "model" , & soc_dev_attr -> machine );
@@ -231,18 +251,37 @@ static int imx8m_soc_probe(struct platform_device *pdev)
231
251
data = id -> data ;
232
252
if (data ) {
233
253
soc_dev_attr -> soc_id = data -> name ;
254
+ ret = imx8m_soc_prepare (pdev , data -> ocotp_compatible );
255
+ if (ret )
256
+ return ret ;
257
+
234
258
if (data -> soc_revision ) {
235
- ret = data -> soc_revision (& soc_rev , & soc_uid );
236
- if (ret )
259
+ ret = data -> soc_revision (pdev , & soc_rev );
260
+ if (ret ) {
261
+ imx8m_soc_unprepare (pdev );
262
+ return ret ;
263
+ }
264
+ }
265
+ if (data -> soc_uid ) {
266
+ ret = data -> soc_uid (pdev , soc_uid );
267
+ if (ret ) {
268
+ imx8m_soc_unprepare (pdev );
237
269
return ret ;
270
+ }
238
271
}
272
+ imx8m_soc_unprepare (pdev );
239
273
}
240
274
241
275
soc_dev_attr -> revision = imx8_revision (dev , soc_rev );
242
276
if (!soc_dev_attr -> revision )
243
277
return - ENOMEM ;
244
278
245
- soc_dev_attr -> serial_number = devm_kasprintf (dev , GFP_KERNEL , "%016llX" , soc_uid );
279
+ if (soc_uid [1 ])
280
+ soc_dev_attr -> serial_number = devm_kasprintf (dev , GFP_KERNEL , "%016llX%016llX" ,
281
+ soc_uid [1 ], soc_uid [0 ]);
282
+ else
283
+ soc_dev_attr -> serial_number = devm_kasprintf (dev , GFP_KERNEL , "%016llX" ,
284
+ soc_uid [0 ]);
246
285
if (!soc_dev_attr -> serial_number )
247
286
return - ENOMEM ;
248
287
0 commit comments