• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 Rockchip Electronics Co. Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11  * more details.
12  */
13 
14 #include <linux/crc32.h>
15 #include <linux/io.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/nvmem-consumer.h>
19 #include <linux/platform_device.h>
20 #include <linux/slab.h>
21 #include <asm/system_info.h>
22 #include <linux/rockchip/cpu.h>
23 
24 unsigned long rockchip_soc_id;
25 EXPORT_SYMBOL(rockchip_soc_id);
26 
rockchip_cpuinfo_probe(struct platform_device * pdev)27 static int rockchip_cpuinfo_probe(struct platform_device *pdev)
28 {
29 	struct device *dev = &pdev->dev;
30 	struct nvmem_cell *cell;
31 	unsigned char *efuse_buf, buf[16];
32 	size_t len = 0;
33 	int i;
34 
35 	cell = nvmem_cell_get(dev, "cpu-code");
36 	if (!IS_ERR(cell)) {
37 		efuse_buf = nvmem_cell_read(cell, &len);
38 		nvmem_cell_put(cell);
39 		if (IS_ERR(efuse_buf))
40 			return PTR_ERR(efuse_buf);
41 
42 		if (len == 2)
43 			rockchip_set_cpu((efuse_buf[0] << 8 | efuse_buf[1]));
44 		kfree(efuse_buf);
45 	}
46 
47 	cell = nvmem_cell_get(dev, "cpu-version");
48 	if (!IS_ERR(cell)) {
49 		efuse_buf = nvmem_cell_read(cell, &len);
50 		nvmem_cell_put(cell);
51 		if (IS_ERR(efuse_buf))
52 			return PTR_ERR(efuse_buf);
53 
54 		if ((len == 1) && (efuse_buf[0] > rockchip_get_cpu_version()))
55 			rockchip_set_cpu_version(efuse_buf[0]);
56 		kfree(efuse_buf);
57 	}
58 
59 	cell = nvmem_cell_get(dev, "id");
60 	if (IS_ERR(cell)) {
61 		dev_err(dev, "failed to get id cell: %ld\n", PTR_ERR(cell));
62 		if (PTR_ERR(cell) == -EPROBE_DEFER)
63 			return PTR_ERR(cell);
64 		return PTR_ERR(cell);
65 	}
66 	efuse_buf = nvmem_cell_read(cell, &len);
67 	nvmem_cell_put(cell);
68 	if (IS_ERR(efuse_buf))
69 		return PTR_ERR(efuse_buf);
70 
71 	if (len != 16) {
72 		kfree(efuse_buf);
73 		dev_err(dev, "invalid id len: %zu\n", len);
74 		return -EINVAL;
75 	}
76 
77 	for (i = 0; i < 8; i++) {
78 		buf[i] = efuse_buf[1 + (i << 1)];
79 		buf[i + 8] = efuse_buf[i << 1];
80 	}
81 
82 	kfree(efuse_buf);
83 
84 	dev_info(dev, "SoC\t\t: %lx\n", rockchip_soc_id);
85 
86 #ifdef CONFIG_NO_GKI
87 	system_serial_low = crc32(0, buf, 8);
88 	system_serial_high = crc32(system_serial_low, buf + 8, 8);
89 
90 	dev_info(dev, "Serial\t\t: %08x%08x\n",
91 		 system_serial_high, system_serial_low);
92 #endif
93 
94 	return 0;
95 }
96 
97 static const struct of_device_id rockchip_cpuinfo_of_match[] = {
98 	{ .compatible = "rockchip,cpuinfo", },
99 	{ },
100 };
101 MODULE_DEVICE_TABLE(of, rockchip_cpuinfo_of_match);
102 
103 static struct platform_driver rockchip_cpuinfo_driver = {
104 	.probe = rockchip_cpuinfo_probe,
105 	.driver = {
106 		.name = "rockchip-cpuinfo",
107 		.of_match_table = rockchip_cpuinfo_of_match,
108 	},
109 };
110 
rockchip_cpuinfo_init(void)111 static int __init rockchip_cpuinfo_init(void)
112 {
113 	return platform_driver_register(&rockchip_cpuinfo_driver);
114 }
115 subsys_initcall_sync(rockchip_cpuinfo_init);
116 
rockchip_cpuinfo_exit(void)117 static void __exit rockchip_cpuinfo_exit(void)
118 {
119 	platform_driver_unregister(&rockchip_cpuinfo_driver);
120 }
121 module_exit(rockchip_cpuinfo_exit);
122 
123 MODULE_LICENSE("GPL");
124