3
3
* Copyright (c) 2013-2023, NVIDIA CORPORATION. All rights reserved.
4
4
*/
5
5
6
+ #include <linux/acpi.h>
6
7
#include <linux/clk.h>
7
8
#include <linux/device.h>
8
9
#include <linux/kobject.h>
9
10
#include <linux/init.h>
10
11
#include <linux/io.h>
12
+ #include <linux/mod_devicetable.h>
11
13
#include <linux/nvmem-consumer.h>
12
14
#include <linux/nvmem-provider.h>
13
15
#include <linux/of.h>
@@ -113,6 +115,28 @@ static void tegra_fuse_restore(void *base)
113
115
fuse -> clk = NULL ;
114
116
}
115
117
118
+ static void tegra_fuse_print_sku_info (struct tegra_sku_info * tegra_sku_info )
119
+ {
120
+ pr_info ("Tegra Revision: %s SKU: %d CPU Process: %d SoC Process: %d\n" ,
121
+ tegra_revision_name [tegra_sku_info -> revision ],
122
+ tegra_sku_info -> sku_id , tegra_sku_info -> cpu_process_id ,
123
+ tegra_sku_info -> soc_process_id );
124
+ pr_debug ("Tegra CPU Speedo ID %d, SoC Speedo ID %d\n" ,
125
+ tegra_sku_info -> cpu_speedo_id , tegra_sku_info -> soc_speedo_id );
126
+ }
127
+
128
+ static int tegra_fuse_add_lookups (struct tegra_fuse * fuse )
129
+ {
130
+ fuse -> lookups = kmemdup_array (fuse -> soc -> lookups , sizeof (* fuse -> lookups ),
131
+ fuse -> soc -> num_lookups , GFP_KERNEL );
132
+ if (!fuse -> lookups )
133
+ return - ENOMEM ;
134
+
135
+ nvmem_add_cell_lookups (fuse -> lookups , fuse -> soc -> num_lookups );
136
+
137
+ return 0 ;
138
+ }
139
+
116
140
static int tegra_fuse_probe (struct platform_device * pdev )
117
141
{
118
142
void __iomem * base = fuse -> base ;
@@ -130,15 +154,46 @@ static int tegra_fuse_probe(struct platform_device *pdev)
130
154
return PTR_ERR (fuse -> base );
131
155
fuse -> phys = res -> start ;
132
156
133
- fuse -> clk = devm_clk_get (& pdev -> dev , "fuse" );
134
- if (IS_ERR (fuse -> clk )) {
135
- if (PTR_ERR (fuse -> clk ) != - EPROBE_DEFER )
136
- dev_err (& pdev -> dev , "failed to get FUSE clock: %ld" ,
137
- PTR_ERR (fuse -> clk ));
157
+ /* Initialize the soc data and lookups if using ACPI boot. */
158
+ if (is_acpi_node (dev_fwnode (& pdev -> dev )) && !fuse -> soc ) {
159
+ u8 chip ;
138
160
139
- return PTR_ERR (fuse -> clk );
161
+ tegra_acpi_init_apbmisc ();
162
+
163
+ chip = tegra_get_chip_id ();
164
+ switch (chip ) {
165
+ #if defined(CONFIG_ARCH_TEGRA_194_SOC )
166
+ case TEGRA194 :
167
+ fuse -> soc = & tegra194_fuse_soc ;
168
+ break ;
169
+ #endif
170
+ #if defined(CONFIG_ARCH_TEGRA_234_SOC )
171
+ case TEGRA234 :
172
+ fuse -> soc = & tegra234_fuse_soc ;
173
+ break ;
174
+ #endif
175
+ #if defined(CONFIG_ARCH_TEGRA_241_SOC )
176
+ case TEGRA241 :
177
+ fuse -> soc = & tegra241_fuse_soc ;
178
+ break ;
179
+ #endif
180
+ default :
181
+ return dev_err_probe (& pdev -> dev , - EINVAL , "Unsupported SoC: %02x\n" , chip );
182
+ }
183
+
184
+ fuse -> soc -> init (fuse );
185
+ tegra_fuse_print_sku_info (& tegra_sku_info );
186
+ tegra_soc_device_register ();
187
+
188
+ err = tegra_fuse_add_lookups (fuse );
189
+ if (err )
190
+ return dev_err_probe (& pdev -> dev , err , "failed to add FUSE lookups\n" );
140
191
}
141
192
193
+ fuse -> clk = devm_clk_get_optional (& pdev -> dev , "fuse" );
194
+ if (IS_ERR (fuse -> clk ))
195
+ return dev_err_probe (& pdev -> dev , PTR_ERR (fuse -> clk ), "failed to get FUSE clock\n" );
196
+
142
197
platform_set_drvdata (pdev , fuse );
143
198
fuse -> dev = & pdev -> dev ;
144
199
@@ -179,12 +234,8 @@ static int tegra_fuse_probe(struct platform_device *pdev)
179
234
}
180
235
181
236
fuse -> rst = devm_reset_control_get_optional (& pdev -> dev , "fuse" );
182
- if (IS_ERR (fuse -> rst )) {
183
- err = PTR_ERR (fuse -> rst );
184
- dev_err (& pdev -> dev , "failed to get FUSE reset: %pe\n" ,
185
- fuse -> rst );
186
- return err ;
187
- }
237
+ if (IS_ERR (fuse -> rst ))
238
+ return dev_err_probe (& pdev -> dev , PTR_ERR (fuse -> rst ), "failed to get FUSE reset\n" );
188
239
189
240
/*
190
241
* FUSE clock is enabled at a boot time, hence this resume/suspend
@@ -262,10 +313,17 @@ static const struct dev_pm_ops tegra_fuse_pm = {
262
313
SET_SYSTEM_SLEEP_PM_OPS (tegra_fuse_suspend , tegra_fuse_resume )
263
314
};
264
315
316
+ static const struct acpi_device_id tegra_fuse_acpi_match [] = {
317
+ { "NVDA200F" },
318
+ { /* sentinel */ }
319
+ };
320
+ MODULE_DEVICE_TABLE (acpi , tegra_fuse_acpi_match );
321
+
265
322
static struct platform_driver tegra_fuse_driver = {
266
323
.driver = {
267
324
.name = "tegra-fuse" ,
268
325
.of_match_table = tegra_fuse_match ,
326
+ .acpi_match_table = tegra_fuse_acpi_match ,
269
327
.pm = & tegra_fuse_pm ,
270
328
.suppress_bind_attrs = true,
271
329
},
@@ -287,7 +345,16 @@ u32 __init tegra_fuse_read_early(unsigned int offset)
287
345
288
346
int tegra_fuse_readl (unsigned long offset , u32 * value )
289
347
{
290
- if (!fuse -> read || !fuse -> clk )
348
+ if (!fuse -> dev )
349
+ return - EPROBE_DEFER ;
350
+
351
+ /*
352
+ * Wait for fuse->clk to be initialized if device-tree boot is used.
353
+ */
354
+ if (is_of_node (dev_fwnode (fuse -> dev )) && !fuse -> clk )
355
+ return - EPROBE_DEFER ;
356
+
357
+ if (!fuse -> read )
291
358
return - EPROBE_DEFER ;
292
359
293
360
if (IS_ERR (fuse -> clk ))
@@ -343,7 +410,8 @@ const struct attribute_group tegra_soc_attr_group = {
343
410
};
344
411
345
412
#if IS_ENABLED (CONFIG_ARCH_TEGRA_194_SOC ) || \
346
- IS_ENABLED (CONFIG_ARCH_TEGRA_234_SOC )
413
+ IS_ENABLED (CONFIG_ARCH_TEGRA_234_SOC ) || \
414
+ IS_ENABLED (CONFIG_ARCH_TEGRA_241_SOC )
347
415
static ssize_t platform_show (struct device * dev , struct device_attribute * attr ,
348
416
char * buf )
349
417
{
@@ -370,7 +438,7 @@ const struct attribute_group tegra194_soc_attr_group = {
370
438
};
371
439
#endif
372
440
373
- struct device * __init tegra_soc_device_register (void )
441
+ struct device * tegra_soc_device_register (void )
374
442
{
375
443
struct soc_device_attribute * attr ;
376
444
struct soc_device * dev ;
@@ -407,6 +475,7 @@ static int __init tegra_init_fuse(void)
407
475
const struct of_device_id * match ;
408
476
struct device_node * np ;
409
477
struct resource regs ;
478
+ int err ;
410
479
411
480
tegra_init_apbmisc ();
412
481
@@ -497,22 +566,13 @@ static int __init tegra_init_fuse(void)
497
566
498
567
fuse -> soc -> init (fuse );
499
568
500
- pr_info ("Tegra Revision: %s SKU: %d CPU Process: %d SoC Process: %d\n" ,
501
- tegra_revision_name [tegra_sku_info .revision ],
502
- tegra_sku_info .sku_id , tegra_sku_info .cpu_process_id ,
503
- tegra_sku_info .soc_process_id );
504
- pr_debug ("Tegra CPU Speedo ID %d, SoC Speedo ID %d\n" ,
505
- tegra_sku_info .cpu_speedo_id , tegra_sku_info .soc_speedo_id );
569
+ tegra_fuse_print_sku_info (& tegra_sku_info );
506
570
507
- if (fuse -> soc -> lookups ) {
508
- size_t size = sizeof (* fuse -> lookups ) * fuse -> soc -> num_lookups ;
509
-
510
- fuse -> lookups = kmemdup (fuse -> soc -> lookups , size , GFP_KERNEL );
511
- if (fuse -> lookups )
512
- nvmem_add_cell_lookups (fuse -> lookups , fuse -> soc -> num_lookups );
513
- }
571
+ err = tegra_fuse_add_lookups (fuse );
572
+ if (err )
573
+ pr_err ("failed to add FUSE lookups\n" );
514
574
515
- return 0 ;
575
+ return err ;
516
576
}
517
577
early_initcall (tegra_init_fuse );
518
578
0 commit comments