aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mvebu/mvebu-soc-id.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mvebu/mvebu-soc-id.c')
-rw-r--r--arch/arm/mach-mvebu/mvebu-soc-id.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.c b/arch/arm/mach-mvebu/mvebu-soc-id.c
index f3b325f6cbd4..d0f35b4d4a23 100644
--- a/arch/arm/mach-mvebu/mvebu-soc-id.c
+++ b/arch/arm/mach-mvebu/mvebu-soc-id.c
@@ -23,6 +23,8 @@
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
#include "mvebu-soc-id.h"
#define PCIE_DEV_ID_OFF 0x0
@@ -38,6 +40,7 @@ static bool is_id_valid;
static const struct of_device_id mvebu_pcie_of_match_table[] = {
{ .compatible = "marvell,armada-xp-pcie", },
{ .compatible = "marvell,armada-370-pcie", },
+ { .compatible = "marvell,kirkwood-pcie" },
{},
};
@@ -107,7 +110,18 @@ static int __init mvebu_soc_id_init(void)
iounmap(pci_base);
res_ioremap:
- clk_disable_unprepare(clk);
+ /*
+ * If the PCIe unit is actually enabled and we have PCI
+ * support in the kernel, we intentionally do not release the
+ * reference to the clock. We want to keep it running since
+ * the bootloader does some PCIe link configuration that the
+ * kernel is for now unable to do, and gating the clock would
+ * make us loose this precious configuration.
+ */
+ if (!of_device_is_available(child) || !IS_ENABLED(CONFIG_PCI_MVEBU)) {
+ clk_disable_unprepare(clk);
+ clk_put(clk);
+ }
clk_err:
of_node_put(child);
@@ -115,5 +129,33 @@ clk_err:
return ret;
}
-core_initcall(mvebu_soc_id_init);
+early_initcall(mvebu_soc_id_init);
+
+static int __init mvebu_soc_device(void)
+{
+ struct soc_device_attribute *soc_dev_attr;
+ struct soc_device *soc_dev;
+
+ /* Also protects against running on non-mvebu systems */
+ if (!is_id_valid)
+ return 0;
+
+ soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ if (!soc_dev_attr)
+ return -ENOMEM;
+
+ soc_dev_attr->family = kasprintf(GFP_KERNEL, "Marvell");
+ soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X", soc_rev);
+ soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%X", soc_dev_id);
+ soc_dev = soc_device_register(soc_dev_attr);
+ if (IS_ERR(soc_dev)) {
+ kfree(soc_dev_attr->family);
+ kfree(soc_dev_attr->revision);
+ kfree(soc_dev_attr->soc_id);
+ kfree(soc_dev_attr);
+ }
+
+ return 0;
+}
+postcore_initcall(mvebu_soc_device);