1 /* 2 * Copyright © 2014 NVIDIA Corporation 3 * Copyright © 2015 Broadcom Corporation 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #include <linux/io.h> 16 #include <linux/of.h> 17 #include <linux/of_address.h> 18 #include <linux/slab.h> 19 #include <linux/soc/brcmstb/brcmstb.h> 20 #include <linux/sys_soc.h> 21 22 #include <soc/brcmstb/common.h> 23 24 static u32 family_id; 25 static u32 product_id; 26 27 static const struct of_device_id brcmstb_machine_match[] = { 28 { .compatible = "brcm,brcmstb", }, 29 { } 30 }; 31 32 bool soc_is_brcmstb(void) 33 { 34 const struct of_device_id *match; 35 struct device_node *root; 36 37 root = of_find_node_by_path("/"); 38 if (!root) 39 return false; 40 41 match = of_match_node(brcmstb_machine_match, root); 42 of_node_put(root); 43 44 return match != NULL; 45 } 46 47 u32 brcmstb_get_family_id(void) 48 { 49 return family_id; 50 } 51 EXPORT_SYMBOL(brcmstb_get_family_id); 52 53 u32 brcmstb_get_product_id(void) 54 { 55 return product_id; 56 } 57 EXPORT_SYMBOL(brcmstb_get_product_id); 58 59 static const struct of_device_id sun_top_ctrl_match[] = { 60 { .compatible = "brcm,bcm7125-sun-top-ctrl", }, 61 { .compatible = "brcm,bcm7346-sun-top-ctrl", }, 62 { .compatible = "brcm,bcm7358-sun-top-ctrl", }, 63 { .compatible = "brcm,bcm7360-sun-top-ctrl", }, 64 { .compatible = "brcm,bcm7362-sun-top-ctrl", }, 65 { .compatible = "brcm,bcm7420-sun-top-ctrl", }, 66 { .compatible = "brcm,bcm7425-sun-top-ctrl", }, 67 { .compatible = "brcm,bcm7429-sun-top-ctrl", }, 68 { .compatible = "brcm,bcm7435-sun-top-ctrl", }, 69 { .compatible = "brcm,brcmstb-sun-top-ctrl", }, 70 { } 71 }; 72 73 static int __init brcmstb_soc_device_early_init(void) 74 { 75 struct device_node *sun_top_ctrl; 76 void __iomem *sun_top_ctrl_base; 77 int ret = 0; 78 79 /* We could be on a multi-platform kernel, don't make this fatal but 80 * bail out early 81 */ 82 sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); 83 if (!sun_top_ctrl) 84 return ret; 85 86 sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0); 87 if (!sun_top_ctrl_base) { 88 ret = -ENODEV; 89 goto out; 90 } 91 92 family_id = readl(sun_top_ctrl_base); 93 product_id = readl(sun_top_ctrl_base + 0x4); 94 iounmap(sun_top_ctrl_base); 95 out: 96 of_node_put(sun_top_ctrl); 97 return ret; 98 } 99 early_initcall(brcmstb_soc_device_early_init); 100 101 static int __init brcmstb_soc_device_init(void) 102 { 103 struct soc_device_attribute *soc_dev_attr; 104 struct device_node *sun_top_ctrl; 105 struct soc_device *soc_dev; 106 int ret = 0; 107 108 /* We could be on a multi-platform kernel, don't make this fatal but 109 * bail out early 110 */ 111 sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); 112 if (!sun_top_ctrl) 113 return ret; 114 115 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 116 if (!soc_dev_attr) { 117 ret = -ENOMEM; 118 goto out; 119 } 120 121 soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x", 122 family_id >> 28 ? 123 family_id >> 16 : family_id >> 8); 124 soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x", 125 product_id >> 28 ? 126 product_id >> 16 : product_id >> 8); 127 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d", 128 ((product_id & 0xf0) >> 4) + 'A', 129 product_id & 0xf); 130 131 soc_dev = soc_device_register(soc_dev_attr); 132 if (IS_ERR(soc_dev)) { 133 kfree(soc_dev_attr->family); 134 kfree(soc_dev_attr->soc_id); 135 kfree(soc_dev_attr->revision); 136 kfree(soc_dev_attr); 137 ret = -ENOMEM; 138 } 139 out: 140 of_node_put(sun_top_ctrl); 141 return ret; 142 } 143 arch_initcall(brcmstb_soc_device_init); 144