linux/drivers/soc/bcm/brcmstb/common.c
<<
>>
Prefs
   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
  24static u32 family_id;
  25static u32 product_id;
  26
  27static const struct of_device_id brcmstb_machine_match[] = {
  28        { .compatible = "brcm,brcmstb", },
  29        { }
  30};
  31
  32bool 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
  43u32 brcmstb_get_family_id(void)
  44{
  45        return family_id;
  46}
  47EXPORT_SYMBOL(brcmstb_get_family_id);
  48
  49u32 brcmstb_get_product_id(void)
  50{
  51        return product_id;
  52}
  53EXPORT_SYMBOL(brcmstb_get_product_id);
  54
  55static 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
  69static 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);
  91out:
  92        of_node_put(sun_top_ctrl);
  93        return ret;
  94}
  95early_initcall(brcmstb_soc_device_early_init);
  96
  97static 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        }
 135out:
 136        of_node_put(sun_top_ctrl);
 137        return ret;
 138}
 139arch_initcall(brcmstb_soc_device_init);
 140