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 static const struct of_device_id sun_top_ctrl_match[] = { 44 { .compatible = "brcm,brcmstb-sun-top-ctrl", }, 45 { } 46 }; 47 48 static int __init brcmstb_soc_device_init(void) 49 { 50 struct soc_device_attribute *soc_dev_attr; 51 struct soc_device *soc_dev; 52 struct device_node *sun_top_ctrl; 53 void __iomem *sun_top_ctrl_base; 54 int ret = 0; 55 56 sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); 57 if (!sun_top_ctrl) 58 return -ENODEV; 59 60 sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0); 61 if (!sun_top_ctrl_base) 62 return -ENODEV; 63 64 family_id = readl(sun_top_ctrl_base); 65 product_id = readl(sun_top_ctrl_base + 0x4); 66 67 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 68 if (!soc_dev_attr) { 69 ret = -ENOMEM; 70 goto out; 71 } 72 73 soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x", 74 family_id >> 28 ? 75 family_id >> 16 : family_id >> 8); 76 soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x", 77 product_id >> 28 ? 78 product_id >> 16 : product_id >> 8); 79 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d", 80 ((product_id & 0xf0) >> 4) + 'A', 81 product_id & 0xf); 82 83 soc_dev = soc_device_register(soc_dev_attr); 84 if (IS_ERR(soc_dev)) { 85 kfree(soc_dev_attr->family); 86 kfree(soc_dev_attr->soc_id); 87 kfree(soc_dev_attr->revision); 88 kfree(soc_dev_attr); 89 ret = -ENODEV; 90 goto out; 91 } 92 93 return 0; 94 95 out: 96 iounmap(sun_top_ctrl_base); 97 return ret; 98 } 99 arch_initcall(brcmstb_soc_device_init); 100