summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-16 14:05:12 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-16 14:05:12 -0800
commit8c609698569578913ad40bb160b97c3f6cfa15ec (patch)
treea8a0a3b90ec9056a05f62a1c84970b5f34a3c139 /drivers
parent18c83d2c0390fd0e8336ad090a047c56037d19f5 (diff)
parentfa32475ad56d339178c9be12678906f2b39e3b47 (diff)
downloadop-kernel-dev-8c609698569578913ad40bb160b97c3f6cfa15ec.zip
op-kernel-dev-8c609698569578913ad40bb160b97c3f6cfa15ec.tar.gz
Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform updates from Arnd Bergmann: "Most of the commits are for defconfig changes, to enable newly added drivers or features that people have started using. For the changed lines lines, we have mostly cleanups, the affected platforms are OMAP, Versatile, EP93xx, Samsung, Broadcom, i.MX, and Actions. The largest single change is the introduction of the TI "sysc" bus driver, with the intention of cleaning up more legacy code. Two new SoC platforms get added this time: - Allwinner R40 is a modernized version of the A20 chip, now with a Quad-Core ARM Cortex-A7. According to the manufacturer, it is intended for "Smart Hardware" - Broadcom Hurricane 2 (Aka Strataconnect BCM5334X) is a family of chips meant for managed gigabit ethernet switches, based around a Cortex-A9 CPU. Finally, we gain SMP support for two platforms: Renesas R-Car E2 and Amlogic Meson8/8b, which were previously added but only supported uniprocessor operation" * tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (118 commits) ARM: multi_v7_defconfig: Select RPMSG_VIRTIO as module ARM: multi_v7_defconfig: enable CONFIG_GPIO_UNIPHIER arm64: defconfig: enable CONFIG_GPIO_UNIPHIER ARM: meson: enable MESON_IRQ_GPIO in Kconfig for meson8b ARM: meson: Add SMP bringup code for Meson8 and Meson8b ARM: smp_scu: allow the platform code to read the SCU CPU status ARM: smp_scu: add a helper for powering on a specific CPU dt-bindings: Amlogic: Add Meson8 and Meson8b SMP related documentation ARM: OMAP3: Delete an unnecessary variable initialisation in omap3xxx_hwmod_init() ARM: OMAP3: Use common error handling code in omap3xxx_hwmod_init() ARM: defconfig: select the right SX150X driver arm64: defconfig: Enable QCOM_IOMMU arm64: Add ThunderX drivers to defconfig arm64: defconfig: Enable Tegra PCI controller cpufreq: imx6q: Move speed grading check to cpufreq driver arm64: defconfig: re-enable Qualcomm DB410c USB ARM: configs: stm32: Add MDMA support in STM32 defconfig ARM: imx: Enable cpuidle for i.MX6DL starting at 1.1 bus: ti-sysc: Fix unbalanced pm_runtime_enable by adding remove bus: ti-sysc: mark PM functions as __maybe_unused ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bus/Kconfig7
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/ti-sysc.c583
-rw-r--r--drivers/clk/bcm/clk-bcm2835-aux.c1
-rw-r--r--drivers/clk/bcm/clk-bcm2835.c30
-rw-r--r--drivers/irqchip/irq-bcm2836.c79
6 files changed, 593 insertions, 108 deletions
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 3e66f4c..fa94a85 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -158,6 +158,13 @@ config TEGRA_GMI
Driver for the Tegra Generic Memory Interface bus which can be used
to attach devices such as NOR, UART, FPGA and more.
+config TI_SYSC
+ bool "TI sysc interconnect target module driver"
+ depends on ARCH_OMAP2PLUS
+ help
+ Generic driver for Texas Instruments interconnect target module
+ found on many TI SoCs.
+
config UNIPHIER_SYSTEM_BUS
tristate "UniPhier System Bus driver"
depends on ARCH_UNIPHIER && OF
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 3ae96cf..94a0790 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
obj-$(CONFIG_TEGRA_GMI) += tegra-gmi.o
+obj-$(CONFIG_TI_SYSC) += ti-sysc.o
obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
new file mode 100644
index 0000000..c3c76a1
--- /dev/null
+++ b/drivers/bus/ti-sysc.c
@@ -0,0 +1,583 @@
+/*
+ * ti-sysc.c - Texas Instruments sysc interconnect target driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+enum sysc_registers {
+ SYSC_REVISION,
+ SYSC_SYSCONFIG,
+ SYSC_SYSSTATUS,
+ SYSC_MAX_REGS,
+};
+
+static const char * const reg_names[] = { "rev", "sysc", "syss", };
+
+enum sysc_clocks {
+ SYSC_FCK,
+ SYSC_ICK,
+ SYSC_MAX_CLOCKS,
+};
+
+static const char * const clock_names[] = { "fck", "ick", };
+
+/**
+ * struct sysc - TI sysc interconnect target module registers and capabilities
+ * @dev: struct device pointer
+ * @module_pa: physical address of the interconnect target module
+ * @module_size: size of the interconnect target module
+ * @module_va: virtual address of the interconnect target module
+ * @offsets: register offsets from module base
+ * @clocks: clocks used by the interconnect target module
+ * @legacy_mode: configured for legacy mode if set
+ */
+struct sysc {
+ struct device *dev;
+ u64 module_pa;
+ u32 module_size;
+ void __iomem *module_va;
+ int offsets[SYSC_MAX_REGS];
+ struct clk *clocks[SYSC_MAX_CLOCKS];
+ const char *legacy_mode;
+};
+
+static u32 sysc_read_revision(struct sysc *ddata)
+{
+ return readl_relaxed(ddata->module_va +
+ ddata->offsets[SYSC_REVISION]);
+}
+
+static int sysc_get_one_clock(struct sysc *ddata,
+ enum sysc_clocks index)
+{
+ const char *name;
+ int error;
+
+ switch (index) {
+ case SYSC_FCK:
+ break;
+ case SYSC_ICK:
+ break;
+ default:
+ return -EINVAL;
+ }
+ name = clock_names[index];
+
+ ddata->clocks[index] = devm_clk_get(ddata->dev, name);
+ if (IS_ERR(ddata->clocks[index])) {
+ if (PTR_ERR(ddata->clocks[index]) == -ENOENT)
+ return 0;
+
+ dev_err(ddata->dev, "clock get error for %s: %li\n",
+ name, PTR_ERR(ddata->clocks[index]));
+
+ return PTR_ERR(ddata->clocks[index]);
+ }
+
+ error = clk_prepare(ddata->clocks[index]);
+ if (error) {
+ dev_err(ddata->dev, "clock prepare error for %s: %i\n",
+ name, error);
+
+ return error;
+ }
+
+ return 0;
+}
+
+static int sysc_get_clocks(struct sysc *ddata)
+{
+ int i, error;
+
+ if (ddata->legacy_mode)
+ return 0;
+
+ for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
+ error = sysc_get_one_clock(ddata, i);
+ if (error && error != -ENOENT)
+ return error;
+ }
+
+ return 0;
+}
+
+/**
+ * sysc_parse_and_check_child_range - parses module IO region from ranges
+ * @ddata: device driver data
+ *
+ * In general we only need rev, syss, and sysc registers and not the whole
+ * module range. But we do want the offsets for these registers from the
+ * module base. This allows us to check them against the legacy hwmod
+ * platform data. Let's also check the ranges are configured properly.
+ */
+static int sysc_parse_and_check_child_range(struct sysc *ddata)
+{
+ struct device_node *np = ddata->dev->of_node;
+ const __be32 *ranges;
+ u32 nr_addr, nr_size;
+ int len, error;
+
+ ranges = of_get_property(np, "ranges", &len);
+ if (!ranges) {
+ dev_err(ddata->dev, "missing ranges for %pOF\n", np);
+
+ return -ENOENT;
+ }
+
+ len /= sizeof(*ranges);
+
+ if (len < 3) {
+ dev_err(ddata->dev, "incomplete ranges for %pOF\n", np);
+
+ return -EINVAL;
+ }
+
+ error = of_property_read_u32(np, "#address-cells", &nr_addr);
+ if (error)
+ return -ENOENT;
+
+ error = of_property_read_u32(np, "#size-cells", &nr_size);
+ if (error)
+ return -ENOENT;
+
+ if (nr_addr != 1 || nr_size != 1) {
+ dev_err(ddata->dev, "invalid ranges for %pOF\n", np);
+
+ return -EINVAL;
+ }
+
+ ranges++;
+ ddata->module_pa = of_translate_address(np, ranges++);
+ ddata->module_size = be32_to_cpup(ranges);
+
+ dev_dbg(ddata->dev, "interconnect target 0x%llx size 0x%x for %pOF\n",
+ ddata->module_pa, ddata->module_size, np);
+
+ return 0;
+}
+
+/**
+ * sysc_check_one_child - check child configuration
+ * @ddata: device driver data
+ * @np: child device node
+ *
+ * Let's avoid messy situations where we have new interconnect target
+ * node but children have "ti,hwmods". These belong to the interconnect
+ * target node and are managed by this driver.
+ */
+static int sysc_check_one_child(struct sysc *ddata,
+ struct device_node *np)
+{
+ const char *name;
+
+ name = of_get_property(np, "ti,hwmods", NULL);
+ if (name)
+ dev_warn(ddata->dev, "really a child ti,hwmods property?");
+
+ return 0;
+}
+
+static int sysc_check_children(struct sysc *ddata)
+{
+ struct device_node *child;
+ int error;
+
+ for_each_child_of_node(ddata->dev->of_node, child) {
+ error = sysc_check_one_child(ddata, child);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+/**
+ * sysc_parse_one - parses the interconnect target module registers
+ * @ddata: device driver data
+ * @reg: register to parse
+ */
+static int sysc_parse_one(struct sysc *ddata, enum sysc_registers reg)
+{
+ struct resource *res;
+ const char *name;
+
+ switch (reg) {
+ case SYSC_REVISION:
+ case SYSC_SYSCONFIG:
+ case SYSC_SYSSTATUS:
+ name = reg_names[reg];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ res = platform_get_resource_byname(to_platform_device(ddata->dev),
+ IORESOURCE_MEM, name);
+ if (!res) {
+ dev_dbg(ddata->dev, "has no %s register\n", name);
+ ddata->offsets[reg] = -ENODEV;
+
+ return 0;
+ }
+
+ ddata->offsets[reg] = res->start - ddata->module_pa;
+
+ return 0;
+}
+
+static int sysc_parse_registers(struct sysc *ddata)
+{
+ int i, error;
+
+ for (i = 0; i < SYSC_MAX_REGS; i++) {
+ error = sysc_parse_one(ddata, i);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+/**
+ * sysc_check_registers - check for misconfigured register overlaps
+ * @ddata: device driver data
+ */
+static int sysc_check_registers(struct sysc *ddata)
+{
+ int i, j, nr_regs = 0, nr_matches = 0;
+
+ for (i = 0; i < SYSC_MAX_REGS; i++) {
+ if (ddata->offsets[i] < 0)
+ continue;
+
+ if (ddata->offsets[i] > (ddata->module_size - 4)) {
+ dev_err(ddata->dev, "register outside module range");
+
+ return -EINVAL;
+ }
+
+ for (j = 0; j < SYSC_MAX_REGS; j++) {
+ if (ddata->offsets[j] < 0)
+ continue;
+
+ if (ddata->offsets[i] == ddata->offsets[j])
+ nr_matches++;
+ }
+ nr_regs++;
+ }
+
+ if (nr_regs < 1) {
+ dev_err(ddata->dev, "missing registers\n");
+
+ return -EINVAL;
+ }
+
+ if (nr_matches > nr_regs) {
+ dev_err(ddata->dev, "overlapping registers: (%i/%i)",
+ nr_regs, nr_matches);
+
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * syc_ioremap - ioremap register space for the interconnect target module
+ * @ddata: deviec driver data
+ *
+ * Note that the interconnect target module registers can be anywhere
+ * within the first child device address space. For example, SGX has
+ * them at offset 0x1fc00 in the 32MB module address space. We just
+ * what we need around the interconnect target module registers.
+ */
+static int sysc_ioremap(struct sysc *ddata)
+{
+ u32 size = 0;
+
+ if (ddata->offsets[SYSC_SYSSTATUS] >= 0)
+ size = ddata->offsets[SYSC_SYSSTATUS];
+ else if (ddata->offsets[SYSC_SYSCONFIG] >= 0)
+ size = ddata->offsets[SYSC_SYSCONFIG];
+ else if (ddata->offsets[SYSC_REVISION] >= 0)
+ size = ddata->offsets[SYSC_REVISION];
+ else
+ return -EINVAL;
+
+ size &= 0xfff00;
+ size += SZ_256;
+
+ ddata->module_va = devm_ioremap(ddata->dev,
+ ddata->module_pa,
+ size);
+ if (!ddata->module_va)
+ return -EIO;
+
+ return 0;
+}
+
+/**
+ * sysc_map_and_check_registers - ioremap and check device registers
+ * @ddata: device driver data
+ */
+static int sysc_map_and_check_registers(struct sysc *ddata)
+{
+ int error;
+
+ error = sysc_parse_and_check_child_range(ddata);
+ if (error)
+ return error;
+
+ error = sysc_check_children(ddata);
+ if (error)
+ return error;
+
+ error = sysc_parse_registers(ddata);
+ if (error)
+ return error;
+
+ error = sysc_ioremap(ddata);
+ if (error)
+ return error;
+
+ error = sysc_check_registers(ddata);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+/**
+ * sysc_show_rev - read and show interconnect target module revision
+ * @bufp: buffer to print the information to
+ * @ddata: device driver data
+ */
+static int sysc_show_rev(char *bufp, struct sysc *ddata)
+{
+ int error, len;
+
+ if (ddata->offsets[SYSC_REVISION] < 0)
+ return sprintf(bufp, ":NA");
+
+ error = pm_runtime_get_sync(ddata->dev);
+ if (error < 0) {
+ pm_runtime_put_noidle(ddata->dev);
+
+ return 0;
+ }
+
+ len = sprintf(bufp, ":%08x", sysc_read_revision(ddata));
+
+ pm_runtime_mark_last_busy(ddata->dev);
+ pm_runtime_put_autosuspend(ddata->dev);
+
+ return len;
+}
+
+static int sysc_show_reg(struct sysc *ddata,
+ char *bufp, enum sysc_registers reg)
+{
+ if (ddata->offsets[reg] < 0)
+ return sprintf(bufp, ":NA");
+
+ return sprintf(bufp, ":%x", ddata->offsets[reg]);
+}
+
+/**
+ * sysc_show_registers - show information about interconnect target module
+ * @ddata: device driver data
+ */
+static void sysc_show_registers(struct sysc *ddata)
+{
+ char buf[128];
+ char *bufp = buf;
+ int i;
+
+ for (i = 0; i < SYSC_MAX_REGS; i++)
+ bufp += sysc_show_reg(ddata, bufp, i);
+
+ bufp += sysc_show_rev(bufp, ddata);
+
+ dev_dbg(ddata->dev, "%llx:%x%s\n",
+ ddata->module_pa, ddata->module_size,
+ buf);
+}
+
+static int __maybe_unused sysc_runtime_suspend(struct device *dev)
+{
+ struct sysc *ddata;
+ int i;
+
+ ddata = dev_get_drvdata(dev);
+
+ if (ddata->legacy_mode)
+ return 0;
+
+ for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
+ if (IS_ERR_OR_NULL(ddata->clocks[i]))
+ continue;
+ clk_disable(ddata->clocks[i]);
+ }
+
+ return 0;
+}
+
+static int __maybe_unused sysc_runtime_resume(struct device *dev)
+{
+ struct sysc *ddata;
+ int i, error;
+
+ ddata = dev_get_drvdata(dev);
+
+ if (ddata->legacy_mode)
+ return 0;
+
+ for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
+ if (IS_ERR_OR_NULL(ddata->clocks[i]))
+ continue;
+ error = clk_enable(ddata->clocks[i]);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops sysc_pm_ops = {
+ SET_RUNTIME_PM_OPS(sysc_runtime_suspend,
+ sysc_runtime_resume,
+ NULL)
+};
+
+static void sysc_unprepare(struct sysc *ddata)
+{
+ int i;
+
+ for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
+ if (!IS_ERR_OR_NULL(ddata->clocks[i]))
+ clk_unprepare(ddata->clocks[i]);
+ }
+}
+
+static int sysc_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct sysc *ddata;
+ int error;
+
+ ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ ddata->dev = &pdev->dev;
+ ddata->legacy_mode = of_get_property(np, "ti,hwmods", NULL);
+
+ error = sysc_get_clocks(ddata);
+ if (error)
+ return error;
+
+ error = sysc_map_and_check_registers(ddata);
+ if (error)
+ goto unprepare;
+
+ platform_set_drvdata(pdev, ddata);
+
+ pm_runtime_enable(ddata->dev);
+ error = pm_runtime_get_sync(ddata->dev);
+ if (error < 0) {
+ pm_runtime_put_noidle(ddata->dev);
+ pm_runtime_disable(ddata->dev);
+ goto unprepare;
+ }
+
+ pm_runtime_use_autosuspend(ddata->dev);
+
+ sysc_show_registers(ddata);
+
+ error = of_platform_populate(ddata->dev->of_node,
+ NULL, NULL, ddata->dev);
+ if (error)
+ goto err;
+
+ pm_runtime_mark_last_busy(ddata->dev);
+ pm_runtime_put_autosuspend(ddata->dev);
+
+ return 0;
+
+err:
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+unprepare:
+ sysc_unprepare(ddata);
+
+ return error;
+}
+
+static int sysc_remove(struct platform_device *pdev)
+{
+ struct sysc *ddata = platform_get_drvdata(pdev);
+ int error;
+
+ error = pm_runtime_get_sync(ddata->dev);
+ if (error < 0) {
+ pm_runtime_put_noidle(ddata->dev);
+ pm_runtime_disable(ddata->dev);
+ goto unprepare;
+ }
+
+ of_platform_depopulate(&pdev->dev);
+
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+unprepare:
+ sysc_unprepare(ddata);
+
+ return 0;
+}
+
+static const struct of_device_id sysc_match[] = {
+ { .compatible = "ti,sysc-omap2" },
+ { .compatible = "ti,sysc-omap4" },
+ { .compatible = "ti,sysc-omap4-simple" },
+ { .compatible = "ti,sysc-omap3430-sr" },
+ { .compatible = "ti,sysc-omap3630-sr" },
+ { .compatible = "ti,sysc-omap4-sr" },
+ { .compatible = "ti,sysc-omap3-sham" },
+ { .compatible = "ti,sysc-omap-aes" },
+ { .compatible = "ti,sysc-mcasp" },
+ { .compatible = "ti,sysc-usb-host-fs" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, sysc_match);
+
+static struct platform_driver sysc_driver = {
+ .probe = sysc_probe,
+ .remove = sysc_remove,
+ .driver = {
+ .name = "ti-sysc",
+ .of_match_table = sysc_match,
+ .pm = &sysc_pm_ops,
+ },
+};
+module_platform_driver(sysc_driver);
+
+MODULE_DESCRIPTION("TI sysc interconnect target driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/bcm/clk-bcm2835-aux.c b/drivers/clk/bcm/clk-bcm2835-aux.c
index bd750cf..77e276d 100644
--- a/drivers/clk/bcm/clk-bcm2835-aux.c
+++ b/drivers/clk/bcm/clk-bcm2835-aux.c
@@ -14,7 +14,6 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
-#include <linux/clk/bcm2835.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/bcm2835-aux.h>
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 58ce6af..44301a3 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -37,7 +37,6 @@
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/clk.h>
-#include <linux/clk/bcm2835.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/module.h>
@@ -416,35 +415,6 @@ static int bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base,
return regdump ? 0 : -ENOMEM;
}
-/*
- * These are fixed clocks. They're probably not all root clocks and it may
- * be possible to turn them on and off but until this is mapped out better
- * it's the only way they can be used.
- */
-void __init bcm2835_init_clocks(void)
-{
- struct clk_hw *hw;
- int ret;
-
- hw = clk_hw_register_fixed_rate(NULL, "apb_pclk", NULL, 0, 126000000);
- if (IS_ERR(hw))
- pr_err("apb_pclk not registered\n");
-
- hw = clk_hw_register_fixed_rate(NULL, "uart0_pclk", NULL, 0, 3000000);
- if (IS_ERR(hw))
- pr_err("uart0_pclk not registered\n");
- ret = clk_hw_register_clkdev(hw, NULL, "20201000.uart");
- if (ret)
- pr_err("uart0_pclk alias not registered\n");
-
- hw = clk_hw_register_fixed_rate(NULL, "uart1_pclk", NULL, 0, 125000000);
- if (IS_ERR(hw))
- pr_err("uart1_pclk not registered\n");
- ret = clk_hw_register_clkdev(hw, NULL, "20215000.uart");
- if (ret)
- pr_err("uart1_pclk alias not registered\n");
-}
-
struct bcm2835_pll_data {
const char *name;
u32 cm_ctrl_reg;
diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c
index dc8c1e3..667b9e1 100644
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -19,62 +19,9 @@
#include <linux/of_irq.h>
#include <linux/irqchip.h>
#include <linux/irqdomain.h>
-#include <asm/exception.h>
-
-#define LOCAL_CONTROL 0x000
-#define LOCAL_PRESCALER 0x008
+#include <linux/irqchip/irq-bcm2836.h>
-/*
- * The low 2 bits identify the CPU that the GPU IRQ goes to, and the
- * next 2 bits identify the CPU that the GPU FIQ goes to.
- */
-#define LOCAL_GPU_ROUTING 0x00c
-/* When setting bits 0-3, enables PMU interrupts on that CPU. */
-#define LOCAL_PM_ROUTING_SET 0x010
-/* When setting bits 0-3, disables PMU interrupts on that CPU. */
-#define LOCAL_PM_ROUTING_CLR 0x014
-/*
- * The low 4 bits of this are the CPU's timer IRQ enables, and the
- * next 4 bits are the CPU's timer FIQ enables (which override the IRQ
- * bits).
- */
-#define LOCAL_TIMER_INT_CONTROL0 0x040
-/*
- * The low 4 bits of this are the CPU's per-mailbox IRQ enables, and
- * the next 4 bits are the CPU's per-mailbox FIQ enables (which
- * override the IRQ bits).
- */
-#define LOCAL_MAILBOX_INT_CONTROL0 0x050
-/*
- * The CPU's interrupt status register. Bits are defined by the the
- * LOCAL_IRQ_* bits below.
- */
-#define LOCAL_IRQ_PENDING0 0x060
-/* Same status bits as above, but for FIQ. */
-#define LOCAL_FIQ_PENDING0 0x070
-/*
- * Mailbox write-to-set bits. There are 16 mailboxes, 4 per CPU, and
- * these bits are organized by mailbox number and then CPU number. We
- * use mailbox 0 for IPIs. The mailbox's interrupt is raised while
- * any bit is set.
- */
-#define LOCAL_MAILBOX0_SET0 0x080
-#define LOCAL_MAILBOX3_SET0 0x08c
-/* Mailbox write-to-clear bits. */
-#define LOCAL_MAILBOX0_CLR0 0x0c0
-#define LOCAL_MAILBOX3_CLR0 0x0cc
-
-#define LOCAL_IRQ_CNTPSIRQ 0
-#define LOCAL_IRQ_CNTPNSIRQ 1
-#define LOCAL_IRQ_CNTHPIRQ 2
-#define LOCAL_IRQ_CNTVIRQ 3
-#define LOCAL_IRQ_MAILBOX0 4
-#define LOCAL_IRQ_MAILBOX1 5
-#define LOCAL_IRQ_MAILBOX2 6
-#define LOCAL_IRQ_MAILBOX3 7
-#define LOCAL_IRQ_GPU_FAST 8
-#define LOCAL_IRQ_PMU_FAST 9
-#define LAST_IRQ LOCAL_IRQ_PMU_FAST
+#include <asm/exception.h>
struct bcm2836_arm_irqchip_intc {
struct irq_domain *domain;
@@ -215,24 +162,6 @@ static int bcm2836_cpu_dying(unsigned int cpu)
cpu);
return 0;
}
-
-#ifdef CONFIG_ARM
-static int __init bcm2836_smp_boot_secondary(unsigned int cpu,
- struct task_struct *idle)
-{
- unsigned long secondary_startup_phys =
- (unsigned long)virt_to_phys((void *)secondary_startup);
-
- writel(secondary_startup_phys,
- intc.base + LOCAL_MAILBOX3_SET0 + 16 * cpu);
-
- return 0;
-}
-
-static const struct smp_operations bcm2836_smp_ops __initconst = {
- .smp_boot_secondary = bcm2836_smp_boot_secondary,
-};
-#endif
#endif
static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = {
@@ -249,10 +178,6 @@ bcm2836_arm_irqchip_smp_init(void)
bcm2836_cpu_dying);
set_smp_cross_call(bcm2836_arm_irqchip_send_ipi);
-
-#ifdef CONFIG_ARM
- smp_set_ops(&bcm2836_smp_ops);
-#endif
#endif
}
OpenPOWER on IntegriCloud