0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #define pr_fmt(fmt) "mvebu-soc-id: " fmt
0016
0017 #include <linux/clk.h>
0018 #include <linux/init.h>
0019 #include <linux/io.h>
0020 #include <linux/kernel.h>
0021 #include <linux/of.h>
0022 #include <linux/of_address.h>
0023 #include <linux/slab.h>
0024 #include <linux/sys_soc.h>
0025 #include "common.h"
0026 #include "mvebu-soc-id.h"
0027
0028 #define PCIE_DEV_ID_OFF 0x0
0029 #define PCIE_DEV_REV_OFF 0x8
0030
0031 #define SOC_ID_MASK 0xFFFF0000
0032 #define SOC_REV_MASK 0xFF
0033
0034 static u32 soc_dev_id;
0035 static u32 soc_rev;
0036 static bool is_id_valid;
0037
0038 static const struct of_device_id mvebu_pcie_of_match_table[] = {
0039 { .compatible = "marvell,armada-xp-pcie", },
0040 { .compatible = "marvell,armada-370-pcie", },
0041 { .compatible = "marvell,kirkwood-pcie" },
0042 {},
0043 };
0044
0045 int mvebu_get_soc_id(u32 *dev, u32 *rev)
0046 {
0047 if (is_id_valid) {
0048 *dev = soc_dev_id;
0049 *rev = soc_rev;
0050 return 0;
0051 } else
0052 return -ENODEV;
0053 }
0054
0055 static int __init get_soc_id_by_pci(void)
0056 {
0057 struct device_node *np;
0058 int ret = 0;
0059 void __iomem *pci_base;
0060 struct clk *clk;
0061 struct device_node *child;
0062
0063 np = of_find_matching_node(NULL, mvebu_pcie_of_match_table);
0064 if (!np)
0065 return ret;
0066
0067
0068
0069
0070
0071 child = of_get_next_child(np, NULL);
0072 if (child == NULL) {
0073 pr_err("cannot get pci node\n");
0074 ret = -ENOMEM;
0075 goto clk_err;
0076 }
0077
0078 clk = of_clk_get_by_name(child, NULL);
0079 if (IS_ERR(clk)) {
0080 pr_err("cannot get clock\n");
0081 ret = -ENOMEM;
0082 goto clk_err;
0083 }
0084
0085 ret = clk_prepare_enable(clk);
0086 if (ret) {
0087 pr_err("cannot enable clock\n");
0088 goto clk_err;
0089 }
0090
0091 pci_base = of_iomap(child, 0);
0092 if (pci_base == NULL) {
0093 pr_err("cannot map registers\n");
0094 ret = -ENOMEM;
0095 goto res_ioremap;
0096 }
0097
0098
0099 soc_dev_id = readl(pci_base + PCIE_DEV_ID_OFF) >> 16;
0100
0101
0102 soc_rev = readl(pci_base + PCIE_DEV_REV_OFF) & SOC_REV_MASK;
0103
0104 is_id_valid = true;
0105
0106 pr_info("MVEBU SoC ID=0x%X, Rev=0x%X\n", soc_dev_id, soc_rev);
0107
0108 iounmap(pci_base);
0109
0110 res_ioremap:
0111
0112
0113
0114
0115
0116
0117
0118
0119 if (!of_device_is_available(child) || !IS_ENABLED(CONFIG_PCI_MVEBU)) {
0120 clk_disable_unprepare(clk);
0121 clk_put(clk);
0122 }
0123
0124 clk_err:
0125 of_node_put(child);
0126 of_node_put(np);
0127
0128 return ret;
0129 }
0130
0131 static int __init mvebu_soc_id_init(void)
0132 {
0133
0134
0135
0136
0137
0138 if (!mvebu_system_controller_get_soc_id(&soc_dev_id, &soc_rev)) {
0139 is_id_valid = true;
0140 pr_info("MVEBU SoC ID=0x%X, Rev=0x%X\n", soc_dev_id, soc_rev);
0141 return 0;
0142 }
0143
0144 return get_soc_id_by_pci();
0145 }
0146 early_initcall(mvebu_soc_id_init);
0147
0148 static int __init mvebu_soc_device(void)
0149 {
0150 struct soc_device_attribute *soc_dev_attr;
0151 struct soc_device *soc_dev;
0152
0153
0154 if (!is_id_valid)
0155 return 0;
0156
0157 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
0158 if (!soc_dev_attr)
0159 return -ENOMEM;
0160
0161 soc_dev_attr->family = kasprintf(GFP_KERNEL, "Marvell");
0162 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X", soc_rev);
0163 soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%X", soc_dev_id);
0164
0165 soc_dev = soc_device_register(soc_dev_attr);
0166 if (IS_ERR(soc_dev)) {
0167 kfree(soc_dev_attr->family);
0168 kfree(soc_dev_attr->revision);
0169 kfree(soc_dev_attr->soc_id);
0170 kfree(soc_dev_attr);
0171 }
0172
0173 return 0;
0174 }
0175 postcore_initcall(mvebu_soc_device);