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