summaryrefslogtreecommitdiff
path: root/drivers/bus
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bus')
-rw-r--r--drivers/bus/Kconfig10
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/imx-weim.c7
-rw-r--r--drivers/bus/sun50i-de2.c48
-rw-r--r--drivers/bus/ti-sysc.c64
5 files changed, 129 insertions, 1 deletions
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index d1c0b60e9326..1851112ccc29 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -103,6 +103,16 @@ config SIMPLE_PM_BUS
Controller (BSC, sometimes called "LBSC within Bus Bridge", or
"External Bus Interface") as found on several Renesas ARM SoCs.
+config SUN50I_DE2_BUS
+ bool "Allwinner A64 DE2 Bus Driver"
+ default ARM64
+ depends on ARCH_SUNXI
+ select SUNXI_SRAM
+ help
+ Say y here to enable support for Allwinner A64 DE2 bus driver. It's
+ mostly transparent, but a SRAM region needs to be claimed in the SRAM
+ controller to make the all blocks in the DE2 part accessible.
+
config SUNXI_RSB
tristate "Allwinner sunXi Reduced Serial Bus Driver"
default MACH_SUN8I || MACH_SUN9I || ARM64
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index b8f036cca7ff..ca300b1914ce 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o
+obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index 3d56ebcda720..6a94aa6a22c2 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -45,6 +45,8 @@ static const struct imx_weim_devtype imx51_weim_devtype = {
.cs_stride = 0x18,
};
+#define MAX_CS_REGS_COUNT 6
+
static const struct of_device_id weim_id_table[] = {
/* i.MX1/21 */
{ .compatible = "fsl,imx1-weim", .data = &imx1_weim_devtype, },
@@ -112,9 +114,12 @@ err:
static int __init weim_timing_setup(struct device_node *np, void __iomem *base,
const struct imx_weim_devtype *devtype)
{
- u32 cs_idx, value[devtype->cs_regs_count];
+ u32 cs_idx, value[MAX_CS_REGS_COUNT];
int i, ret;
+ if (WARN_ON(devtype->cs_regs_count > MAX_CS_REGS_COUNT))
+ return -EINVAL;
+
/* get the CS index from this child node's "reg" property. */
ret = of_property_read_u32(np, "reg", &cs_idx);
if (ret)
diff --git a/drivers/bus/sun50i-de2.c b/drivers/bus/sun50i-de2.c
new file mode 100644
index 000000000000..672518741f86
--- /dev/null
+++ b/drivers/bus/sun50i-de2.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner A64 Display Engine 2.0 Bus Driver
+ *
+ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/soc/sunxi/sunxi_sram.h>
+
+static int sun50i_de2_bus_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int ret;
+
+ ret = sunxi_sram_claim(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
+ return ret;
+ }
+
+ of_platform_populate(np, NULL, NULL, &pdev->dev);
+
+ return 0;
+}
+
+static int sun50i_de2_bus_remove(struct platform_device *pdev)
+{
+ sunxi_sram_release(&pdev->dev);
+ return 0;
+}
+
+static const struct of_device_id sun50i_de2_bus_of_match[] = {
+ { .compatible = "allwinner,sun50i-a64-de2", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver sun50i_de2_bus_driver = {
+ .probe = sun50i_de2_bus_probe,
+ .remove = sun50i_de2_bus_remove,
+ .driver = {
+ .name = "sun50i-de2-bus",
+ .of_match_table = sun50i_de2_bus_of_match,
+ },
+};
+
+builtin_platform_driver(sun50i_de2_bus_driver);
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 4576a1268e0e..e4fe954e63a9 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -23,11 +23,14 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
+#include <linux/iopoll.h>
#include <linux/platform_data/ti-sysc.h>
#include <dt-bindings/bus/ti-sysc.h>
+#define MAX_MODULE_SOFTRESET_WAIT 10000
+
static const char * const reg_names[] = { "rev", "sysc", "syss", };
enum sysc_clocks {
@@ -88,6 +91,11 @@ struct sysc {
struct delayed_work idle_work;
};
+void sysc_write(struct sysc *ddata, int offset, u32 value)
+{
+ writel_relaxed(value, ddata->module_va + offset);
+}
+
static u32 sysc_read(struct sysc *ddata, int offset)
{
if (ddata->cfg.quirks & SYSC_QUIRK_16BIT) {
@@ -940,6 +948,36 @@ static void sysc_init_revision_quirks(struct sysc *ddata)
}
}
+static int sysc_reset(struct sysc *ddata)
+{
+ int offset = ddata->offsets[SYSC_SYSCONFIG];
+ int val;
+
+ if (ddata->legacy_mode || offset < 0 ||
+ ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
+ return 0;
+
+ /*
+ * Currently only support reset status in sysstatus.
+ * Warn and return error in all other cases
+ */
+ if (!ddata->cfg.syss_mask) {
+ dev_err(ddata->dev, "No ti,syss-mask. Reset failed\n");
+ return -EINVAL;
+ }
+
+ val = sysc_read(ddata, offset);
+ val |= (0x1 << ddata->cap->regbits->srst_shift);
+ sysc_write(ddata, offset, val);
+
+ /* Poll on reset status */
+ offset = ddata->offsets[SYSC_SYSSTATUS];
+
+ return readl_poll_timeout(ddata->module_va + offset, val,
+ (val & ddata->cfg.syss_mask) == 0x0,
+ 100, MAX_MODULE_SOFTRESET_WAIT);
+}
+
/* At this point the module is configured enough to read the revision */
static int sysc_init_module(struct sysc *ddata)
{
@@ -957,6 +995,14 @@ static int sysc_init_module(struct sysc *ddata)
return 0;
}
+ error = sysc_reset(ddata);
+ if (error) {
+ dev_err(ddata->dev, "Reset failed with %d\n", error);
+ pm_runtime_put_sync(ddata->dev);
+
+ return error;
+ }
+
ddata->revision = sysc_read_revision(ddata);
pm_runtime_put_sync(ddata->dev);
@@ -1549,6 +1595,23 @@ static const struct sysc_capabilities sysc_omap4_usb_host_fs = {
.regbits = &sysc_regbits_omap4_usb_host_fs,
};
+static const struct sysc_regbits sysc_regbits_dra7_mcan = {
+ .dmadisable_shift = -ENODEV,
+ .midle_shift = -ENODEV,
+ .sidle_shift = -ENODEV,
+ .clkact_shift = -ENODEV,
+ .enwkup_shift = 4,
+ .srst_shift = 0,
+ .emufree_shift = -ENODEV,
+ .autoidle_shift = -ENODEV,
+};
+
+static const struct sysc_capabilities sysc_dra7_mcan = {
+ .type = TI_SYSC_DRA7_MCAN,
+ .sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET,
+ .regbits = &sysc_regbits_dra7_mcan,
+};
+
static int sysc_init_pdata(struct sysc *ddata)
{
struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
@@ -1740,6 +1803,7 @@ static const struct of_device_id sysc_match[] = {
{ .compatible = "ti,sysc-mcasp", .data = &sysc_omap4_mcasp, },
{ .compatible = "ti,sysc-usb-host-fs",
.data = &sysc_omap4_usb_host_fs, },
+ { .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, },
{ },
};
MODULE_DEVICE_TABLE(of, sysc_match);