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 #include <soc/brcmstb/common.h> 15 16 static u32 family_id; 17 static u32 product_id; 18 19 static const struct of_device_id brcmstb_machine_match[] = { 20 { .compatible = "brcm,brcmstb", }, 21 { } 22 }; 23 24 bool soc_is_brcmstb(void) 25 { 26 const struct of_device_id *match; 27 struct device_node *root; 28 29 root = of_find_node_by_path("/"); 30 if (!root) 31 return false; 32 33 match = of_match_node(brcmstb_machine_match, root); 34 of_node_put(root); 35 36 return match != NULL; 37 } 38 39 u32 brcmstb_get_family_id(void) 40 { 41 return family_id; 42 } 43 EXPORT_SYMBOL(brcmstb_get_family_id); 44 45 u32 brcmstb_get_product_id(void) 46 { 47 return product_id; 48 } 49 EXPORT_SYMBOL(brcmstb_get_product_id); 50 51 static const struct of_device_id sun_top_ctrl_match[] = { 52 { .compatible = "brcm,bcm7125-sun-top-ctrl", }, 53 { .compatible = "brcm,bcm7346-sun-top-ctrl", }, 54 { .compatible = "brcm,bcm7358-sun-top-ctrl", }, 55 { .compatible = "brcm,bcm7360-sun-top-ctrl", }, 56 { .compatible = "brcm,bcm7362-sun-top-ctrl", }, 57 { .compatible = "brcm,bcm7420-sun-top-ctrl", }, 58 { .compatible = "brcm,bcm7425-sun-top-ctrl", }, 59 { .compatible = "brcm,bcm7429-sun-top-ctrl", }, 60 { .compatible = "brcm,bcm7435-sun-top-ctrl", }, 61 { .compatible = "brcm,brcmstb-sun-top-ctrl", }, 62 { } 63 }; 64 65 static int __init brcmstb_soc_device_early_init(void) 66 { 67 struct device_node *sun_top_ctrl; 68 void __iomem *sun_top_ctrl_base; 69 int ret = 0; 70 71 /* We could be on a multi-platform kernel, don't make this fatal but 72 * bail out early 73 */ 74 sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); 75 if (!sun_top_ctrl) 76 return ret; 77 78 sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0); 79 if (!sun_top_ctrl_base) { 80 ret = -ENODEV; 81 goto out; 82 } 83 84 family_id = readl(sun_top_ctrl_base); 85 product_id = readl(sun_top_ctrl_base + 0x4); 86 iounmap(sun_top_ctrl_base); 87 out: 88 of_node_put(sun_top_ctrl); 89 return ret; 90 } 91 early_initcall(brcmstb_soc_device_early_init); 92 93 static int __init brcmstb_soc_device_init(void) 94 { 95 struct soc_device_attribute *soc_dev_attr; 96 struct device_node *sun_top_ctrl; 97 struct soc_device *soc_dev; 98 int ret = 0; 99 100 /* We could be on a multi-platform kernel, don't make this fatal but 101 * bail out early 102 */ 103 sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); 104 if (!sun_top_ctrl) 105 return ret; 106 107 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 108 if (!soc_dev_attr) { 109 ret = -ENOMEM; 110 goto out; 111 } 112 113 soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x", 114 family_id >> 28 ? 115 family_id >> 16 : family_id >> 8); 116 soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x", 117 product_id >> 28 ? 118 product_id >> 16 : product_id >> 8); 119 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d", 120 ((product_id & 0xf0) >> 4) + 'A', 121 product_id & 0xf); 122 123 soc_dev = soc_device_register(soc_dev_attr); 124 if (IS_ERR(soc_dev)) { 125 kfree(soc_dev_attr->family); 126 kfree(soc_dev_attr->soc_id); 127 kfree(soc_dev_attr->revision); 128 kfree(soc_dev_attr); 129 ret = -ENOMEM; 130 } 131 out: 132 of_node_put(sun_top_ctrl); 133 return ret; 134 } 135 arch_initcall(brcmstb_soc_device_init); 136