diff options
| -rw-r--r-- | drivers/firmware/Kconfig | 5 | ||||
| -rw-r--r-- | drivers/soc/bcm/brcmstb/common.c | 88 |
2 files changed, 50 insertions, 43 deletions
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index bbd2155d8483..bcfda01c2ab8 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -114,7 +114,10 @@ config ISCSI_IBFT config RASPBERRYPI_FIRMWARE tristate "Raspberry Pi Firmware Driver" - depends on BCM2835_MBOX + depends on ARCH_BCM2835 || COMPILE_TEST + depends on ARM || ARM64 + depends on MAILBOX + default ARCH_BCM2835 help This option enables support for communicating with the firmware on the Raspberry Pi. diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c index 2da79bd42930..7be0374f5943 100644 --- a/drivers/soc/bcm/brcmstb/common.c +++ b/drivers/soc/bcm/brcmstb/common.c @@ -11,18 +11,22 @@ #include <linux/soc/brcmstb/brcmstb.h> #include <linux/sys_soc.h> -static u32 family_id; -static u32 product_id; +struct brcmstb_soc_info { + u32 family_id; + u32 product_id; +}; + +static struct brcmstb_soc_info *soc_info; u32 brcmstb_get_family_id(void) { - return family_id; + return soc_info ? soc_info->family_id : 0; } EXPORT_SYMBOL(brcmstb_get_family_id); u32 brcmstb_get_product_id(void) { - return product_id; + return soc_info ? soc_info->product_id : 0; } EXPORT_SYMBOL(brcmstb_get_product_id); @@ -40,10 +44,12 @@ static const struct of_device_id sun_top_ctrl_match[] = { { } }; -static int __init brcmstb_soc_device_early_init(void) +static int __init brcmstb_soc_device_init(void) { + struct soc_device_attribute *soc_dev_attr; struct device_node *sun_top_ctrl; void __iomem *sun_top_ctrl_base; + struct soc_device *soc_dev; int ret = 0; /* We could be on a multi-platform kernel, don't make this fatal but @@ -51,63 +57,61 @@ static int __init brcmstb_soc_device_early_init(void) */ sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); if (!sun_top_ctrl) - return ret; + return 0; sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0); if (!sun_top_ctrl_base) { ret = -ENODEV; - goto out; + goto out_put_node; } - family_id = readl(sun_top_ctrl_base); - product_id = readl(sun_top_ctrl_base + 0x4); - iounmap(sun_top_ctrl_base); -out: - of_node_put(sun_top_ctrl); - return ret; -} -early_initcall(brcmstb_soc_device_early_init); - -static int __init brcmstb_soc_device_init(void) -{ - struct soc_device_attribute *soc_dev_attr; - struct device_node *sun_top_ctrl; - struct soc_device *soc_dev; - int ret = 0; + soc_info = kzalloc(sizeof(*soc_info), GFP_KERNEL); + if (!soc_info) { + ret = -ENOMEM; + goto out_unmap; + } - /* We could be on a multi-platform kernel, don't make this fatal but - * bail out early - */ - sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match); - if (!sun_top_ctrl) - return ret; + soc_info->family_id = readl(sun_top_ctrl_base); + soc_info->product_id = readl(sun_top_ctrl_base + 0x4); soc_dev_attr = kzalloc_obj(*soc_dev_attr); if (!soc_dev_attr) { ret = -ENOMEM; - goto out; + goto out_free_info; } soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x", - family_id >> 28 ? - family_id >> 16 : family_id >> 8); + soc_info->family_id >> 28 ? + soc_info->family_id >> 16 : soc_info->family_id >> 8); soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x", - product_id >> 28 ? - product_id >> 16 : product_id >> 8); + soc_info->product_id >> 28 ? + soc_info->product_id >> 16 : soc_info->product_id >> 8); soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d", - ((product_id & 0xf0) >> 4) + 'A', - product_id & 0xf); + ((soc_info->product_id & 0xf0) >> 4) + 'A', + soc_info->product_id & 0xf); soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { - kfree(soc_dev_attr->family); - kfree(soc_dev_attr->soc_id); - kfree(soc_dev_attr->revision); - kfree(soc_dev_attr); - ret = -ENOMEM; + ret = PTR_ERR(soc_dev); + goto out_free_attr; } -out: + + iounmap(sun_top_ctrl_base); + of_node_put(sun_top_ctrl); + return 0; + +out_free_attr: + kfree(soc_dev_attr->revision); + kfree(soc_dev_attr->soc_id); + kfree(soc_dev_attr->family); + kfree(soc_dev_attr); +out_free_info: + kfree(soc_info); + soc_info = NULL; +out_unmap: + iounmap(sun_top_ctrl_base); +out_put_node: of_node_put(sun_top_ctrl); return ret; } -arch_initcall(brcmstb_soc_device_init); +early_initcall(brcmstb_soc_device_init); |
