1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019 Samsung Electronics Co., Ltd. 4 * http://www.samsung.com/ 5 * 6 * EXYNOS - CHIP ID support 7 * Author: Pankaj Dubey <pankaj.dubey@samsung.com> 8 * Author: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> 9 */ 10 11 #include <linux/io.h> 12 #include <linux/mfd/syscon.h> 13 #include <linux/of.h> 14 #include <linux/regmap.h> 15 #include <linux/slab.h> 16 #include <linux/soc/samsung/exynos-chipid.h> 17 #include <linux/sys_soc.h> 18 19 static const struct exynos_soc_id { 20 const char *name; 21 unsigned int id; 22 } soc_ids[] = { 23 { "EXYNOS3250", 0xE3472000 }, 24 { "EXYNOS4210", 0x43200000 }, /* EVT0 revision */ 25 { "EXYNOS4210", 0x43210000 }, 26 { "EXYNOS4212", 0x43220000 }, 27 { "EXYNOS4412", 0xE4412000 }, 28 { "EXYNOS5250", 0x43520000 }, 29 { "EXYNOS5260", 0xE5260000 }, 30 { "EXYNOS5410", 0xE5410000 }, 31 { "EXYNOS5420", 0xE5420000 }, 32 { "EXYNOS5440", 0xE5440000 }, 33 { "EXYNOS5800", 0xE5422000 }, 34 { "EXYNOS7420", 0xE7420000 }, 35 { "EXYNOS5433", 0xE5433000 }, 36 }; 37 38 static const char * __init product_id_to_soc_id(unsigned int product_id) 39 { 40 int i; 41 42 for (i = 0; i < ARRAY_SIZE(soc_ids); i++) 43 if ((product_id & EXYNOS_MASK) == soc_ids[i].id) 44 return soc_ids[i].name; 45 return NULL; 46 } 47 48 int __init exynos_chipid_early_init(void) 49 { 50 struct soc_device_attribute *soc_dev_attr; 51 struct soc_device *soc_dev; 52 struct device_node *root; 53 struct regmap *regmap; 54 u32 product_id; 55 u32 revision; 56 int ret; 57 58 regmap = syscon_regmap_lookup_by_compatible("samsung,exynos4210-chipid"); 59 if (IS_ERR(regmap)) 60 return PTR_ERR(regmap); 61 62 ret = regmap_read(regmap, EXYNOS_CHIPID_REG_PRO_ID, &product_id); 63 if (ret < 0) 64 return ret; 65 66 revision = product_id & EXYNOS_REV_MASK; 67 68 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 69 if (!soc_dev_attr) 70 return -ENOMEM; 71 72 soc_dev_attr->family = "Samsung Exynos"; 73 74 root = of_find_node_by_path("/"); 75 of_property_read_string(root, "model", &soc_dev_attr->machine); 76 of_node_put(root); 77 78 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%x", revision); 79 soc_dev_attr->soc_id = product_id_to_soc_id(product_id); 80 if (!soc_dev_attr->soc_id) { 81 pr_err("Unknown SoC\n"); 82 ret = -ENODEV; 83 goto err; 84 } 85 86 /* please note that the actual registration will be deferred */ 87 soc_dev = soc_device_register(soc_dev_attr); 88 if (IS_ERR(soc_dev)) { 89 ret = PTR_ERR(soc_dev); 90 goto err; 91 } 92 93 /* it is too early to use dev_info() here (soc_dev is NULL) */ 94 pr_info("soc soc0: Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n", 95 soc_dev_attr->soc_id, product_id, revision); 96 97 return 0; 98 99 err: 100 kfree(soc_dev_attr->revision); 101 kfree(soc_dev_attr); 102 return ret; 103 } 104 105 early_initcall(exynos_chipid_early_init); 106