1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright © 2014 NVIDIA Corporation 4 * Copyright © 2015 Broadcom Corporation 5 */ 6 7 #include <linux/io.h> 8 #include <linux/of.h> 9 #include <linux/of_address.h> 10 #include <linux/slab.h> 11 #include <linux/soc/brcmstb/brcmstb.h> 12 #include <linux/sys_soc.h> 13 14 static u32 family_id; 15 static u32 product_id; 16 17 static const struct of_device_id brcmstb_machine_match[] = { 18 { .compatible = "brcm,brcmstb", }, 19 { } 20 }; 21 22 u32 brcmstb_get_family_id(void) 23 { 24 return family_id; 25 } 26 EXPORT_SYMBOL(brcmstb_get_family_id); 27 28 u32 brcmstb_get_product_id(void) 29 { 30 return product_id; 31 } 32 EXPORT_SYMBOL(brcmstb_get_product_id); 33 34 static const struct of_device_id sun_top_ctrl_match[] = { 35 { .compatible = "brcm,bcm7125-sun-top-ctrl", }, 36 { .compatible = "brcm,bcm7346-sun-top-ctrl", }, 37 { .compatible = "brcm,bcm7358-sun-top-ctrl", }, 38 { .compatible = "brcm,bcm7360-sun-top-ctrl", }, 39 { .compatible = "brcm,bcm7362-sun-top-ctrl", }, 40 { .compatible = "brcm,bcm7420-sun-top-ctrl", }, 41 { .compatible = "brcm,bcm7425-sun-top-ctrl", }, 42 { .compatible = "brcm,bcm7429-sun-top-ctrl", }, 43 { .compatible = "brcm,bcm7435-sun-top-ctrl", }, 44 { .compatible = "brcm,brcmstb-sun-top-ctrl", }, 45 { } 46 }; 47 48 static int __init brcmstb_soc_device_early_init(void) 49 { 50 struct device_node *sun_top_ctrl; 51 void __iomem *sun_top_ctrl_base; 52 int ret = 0; 53 54 /* We could be on a multi-platform kernel, don't make this fatal but 55 * bail out early 56 */ 57 sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); 58 if (!sun_top_ctrl) 59 return ret; 60 61 sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0); 62 if (!sun_top_ctrl_base) { 63 ret = -ENODEV; 64 goto out; 65 } 66 67 family_id = readl(sun_top_ctrl_base); 68 product_id = readl(sun_top_ctrl_base + 0x4); 69 iounmap(sun_top_ctrl_base); 70 out: 71 of_node_put(sun_top_ctrl); 72 return ret; 73 } 74 early_initcall(brcmstb_soc_device_early_init); 75 76 static int __init brcmstb_soc_device_init(void) 77 { 78 struct soc_device_attribute *soc_dev_attr; 79 struct device_node *sun_top_ctrl; 80 struct soc_device *soc_dev; 81 int ret = 0; 82 83 /* We could be on a multi-platform kernel, don't make this fatal but 84 * bail out early 85 */ 86 sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); 87 if (!sun_top_ctrl) 88 return ret; 89 90 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 91 if (!soc_dev_attr) { 92 ret = -ENOMEM; 93 goto out; 94 } 95 96 soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x", 97 family_id >> 28 ? 98 family_id >> 16 : family_id >> 8); 99 soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x", 100 product_id >> 28 ? 101 product_id >> 16 : product_id >> 8); 102 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d", 103 ((product_id & 0xf0) >> 4) + 'A', 104 product_id & 0xf); 105 106 soc_dev = soc_device_register(soc_dev_attr); 107 if (IS_ERR(soc_dev)) { 108 kfree(soc_dev_attr->family); 109 kfree(soc_dev_attr->soc_id); 110 kfree(soc_dev_attr->revision); 111 kfree(soc_dev_attr); 112 ret = -ENOMEM; 113 } 114 out: 115 of_node_put(sun_top_ctrl); 116 return ret; 117 } 118 arch_initcall(brcmstb_soc_device_init); 119