33 * Copyright (c) 2013-2023, NVIDIA CORPORATION. All rights reserved.
44 */
55
6+ #include <linux/acpi.h>
67#include <linux/clk.h>
78#include <linux/device.h>
89#include <linux/kobject.h>
910#include <linux/init.h>
1011#include <linux/io.h>
12+ #include <linux/mod_devicetable.h>
1113#include <linux/nvmem-consumer.h>
1214#include <linux/nvmem-provider.h>
1315#include <linux/of.h>
@@ -113,6 +115,28 @@ static void tegra_fuse_restore(void *base)
113115 fuse -> clk = NULL ;
114116}
115117
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+
116140static int tegra_fuse_probe (struct platform_device * pdev )
117141{
118142 void __iomem * base = fuse -> base ;
@@ -130,15 +154,46 @@ static int tegra_fuse_probe(struct platform_device *pdev)
130154 return PTR_ERR (fuse -> base );
131155 fuse -> phys = res -> start ;
132156
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 ;
138160
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" );
140191 }
141192
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+
142197 platform_set_drvdata (pdev , fuse );
143198 fuse -> dev = & pdev -> dev ;
144199
@@ -179,12 +234,8 @@ static int tegra_fuse_probe(struct platform_device *pdev)
179234 }
180235
181236 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" );
188239
189240 /*
190241 * 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 = {
262313 SET_SYSTEM_SLEEP_PM_OPS (tegra_fuse_suspend , tegra_fuse_resume )
263314};
264315
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+
265322static struct platform_driver tegra_fuse_driver = {
266323 .driver = {
267324 .name = "tegra-fuse" ,
268325 .of_match_table = tegra_fuse_match ,
326+ .acpi_match_table = tegra_fuse_acpi_match ,
269327 .pm = & tegra_fuse_pm ,
270328 .suppress_bind_attrs = true,
271329 },
@@ -287,7 +345,16 @@ u32 __init tegra_fuse_read_early(unsigned int offset)
287345
288346int tegra_fuse_readl (unsigned long offset , u32 * value )
289347{
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 )
291358 return - EPROBE_DEFER ;
292359
293360 if (IS_ERR (fuse -> clk ))
@@ -343,7 +410,8 @@ const struct attribute_group tegra_soc_attr_group = {
343410};
344411
345412#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 )
347415static ssize_t platform_show (struct device * dev , struct device_attribute * attr ,
348416 char * buf )
349417{
@@ -370,7 +438,7 @@ const struct attribute_group tegra194_soc_attr_group = {
370438};
371439#endif
372440
373- struct device * __init tegra_soc_device_register (void )
441+ struct device * tegra_soc_device_register (void )
374442{
375443 struct soc_device_attribute * attr ;
376444 struct soc_device * dev ;
@@ -407,6 +475,7 @@ static int __init tegra_init_fuse(void)
407475 const struct of_device_id * match ;
408476 struct device_node * np ;
409477 struct resource regs ;
478+ int err ;
410479
411480 tegra_init_apbmisc ();
412481
@@ -497,22 +566,13 @@ static int __init tegra_init_fuse(void)
497566
498567 fuse -> soc -> init (fuse );
499568
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 );
506570
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" );
514574
515- return 0 ;
575+ return err ;
516576}
517577early_initcall (tegra_init_fuse );
518578
0 commit comments