summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/clk-uclass.c4
-rw-r--r--drivers/i2c/designware_i2c.c10
-rw-r--r--drivers/reset/Kconfig7
-rw-r--r--drivers/reset/Makefile1
-rw-r--r--drivers/reset/reset-socfpga.c105
-rw-r--r--drivers/reset/reset-uclass.c4
6 files changed, 127 insertions, 4 deletions
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 6e99b3b15df..53f418bfddd 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -111,8 +111,8 @@ int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk)
bulk->count = 0;
count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
- if (!count)
- return 0;
+ if (count < 1)
+ return count;
bulk->clks = devm_kcalloc(dev, count, sizeof(struct clk), GFP_KERNEL);
if (!bulk->clks)
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 8cfed2194c5..419d021a314 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -9,6 +9,7 @@
#include <dm.h>
#include <i2c.h>
#include <pci.h>
+#include <reset.h>
#include <asm/io.h>
#include "designware_i2c.h"
@@ -34,6 +35,7 @@ static struct dw_scl_sda_cfg byt_config = {
struct dw_i2c {
struct i2c_regs *regs;
struct dw_scl_sda_cfg *scl_sda_cfg;
+ struct reset_ctl reset_ctl;
};
#ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
@@ -534,6 +536,7 @@ static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
static int designware_i2c_probe(struct udevice *bus)
{
struct dw_i2c *priv = dev_get_priv(bus);
+ int ret;
if (device_is_on_pci_bus(bus)) {
#ifdef CONFIG_DM_PCI
@@ -549,6 +552,13 @@ static int designware_i2c_probe(struct udevice *bus)
priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus);
}
+ ret = reset_get_by_name(bus, "i2c", &priv->reset_ctl);
+ if (ret)
+ pr_info("reset_get_by_name() failed: %d\n", ret);
+
+ if (&priv->reset_ctl)
+ reset_deassert(&priv->reset_ctl);
+
__dw_i2c_init(priv->regs, 0, 0);
return 0;
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index ccfdac7823e..33c39b7fb67 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -91,4 +91,11 @@ config RESET_MESON
help
Support for reset controller on Amlogic Meson SoC.
+config RESET_SOCFPGA
+ bool "Reset controller driver for SoCFPGA"
+ depends on DM_RESET && ARCH_SOCFPGA
+ default y
+ help
+ Support for reset controller on SoCFPGA platform.
+
endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index d1d5146825d..ad08be4c8c1 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
+obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
new file mode 100644
index 00000000000..466455d0739
--- /dev/null
+++ b/drivers/reset/reset-socfpga.c
@@ -0,0 +1,105 @@
+/*
+ * Socfpga Reset Controller Driver
+ *
+ * Copyright 2014 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * based on
+ * Allwinner SoCs Reset Controller driver
+ *
+ * Copyright 2013 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/of_access.h>
+#include <reset-uclass.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+#define BANK_INCREMENT 4
+#define NR_BANKS 8
+
+struct socfpga_reset_data {
+ void __iomem *membase;
+};
+
+static int socfpga_reset_assert(struct reset_ctl *reset_ctl)
+{
+ struct socfpga_reset_data *data = dev_get_priv(reset_ctl->dev);
+ int id = reset_ctl->id;
+ int reg_width = sizeof(u32);
+ int bank = id / (reg_width * BITS_PER_BYTE);
+ int offset = id % (reg_width * BITS_PER_BYTE);
+
+ setbits_le32(data->membase + (bank * BANK_INCREMENT), BIT(offset));
+ return 0;
+}
+
+static int socfpga_reset_deassert(struct reset_ctl *reset_ctl)
+{
+ struct socfpga_reset_data *data = dev_get_priv(reset_ctl->dev);
+ int id = reset_ctl->id;
+ int reg_width = sizeof(u32);
+ int bank = id / (reg_width * BITS_PER_BYTE);
+ int offset = id % (reg_width * BITS_PER_BYTE);
+
+ clrbits_le32(data->membase + (bank * BANK_INCREMENT), BIT(offset));
+ return 0;
+}
+
+static int socfpga_reset_request(struct reset_ctl *reset_ctl)
+{
+ debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__,
+ reset_ctl, reset_ctl->dev, reset_ctl->id);
+
+ return 0;
+}
+
+static int socfpga_reset_free(struct reset_ctl *reset_ctl)
+{
+ debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
+ reset_ctl->dev, reset_ctl->id);
+
+ return 0;
+}
+
+static const struct reset_ops socfpga_reset_ops = {
+ .request = socfpga_reset_request,
+ .free = socfpga_reset_free,
+ .rst_assert = socfpga_reset_assert,
+ .rst_deassert = socfpga_reset_deassert,
+};
+
+static int socfpga_reset_probe(struct udevice *dev)
+{
+ struct socfpga_reset_data *data = dev_get_priv(dev);
+ const void *blob = gd->fdt_blob;
+ int node = dev_of_offset(dev);
+ u32 modrst_offset;
+
+ data->membase = devfdt_get_addr_ptr(dev);
+
+ modrst_offset = fdtdec_get_int(blob, node, "altr,modrst-offset", 0x10);
+ data->membase += modrst_offset;
+
+ return 0;
+}
+
+static const struct udevice_id socfpga_reset_match[] = {
+ { .compatible = "altr,rst-mgr" },
+ { /* sentinel */ },
+};
+
+U_BOOT_DRIVER(socfpga_reset) = {
+ .name = "socfpga-reset",
+ .id = UCLASS_RESET,
+ .of_match = socfpga_reset_match,
+ .probe = socfpga_reset_probe,
+ .priv_auto_alloc_size = sizeof(struct socfpga_reset_data),
+ .ops = &socfpga_reset_ops,
+};
diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c
index 9a5c9c91b9d..fa4f6538edd 100644
--- a/drivers/reset/reset-uclass.c
+++ b/drivers/reset/reset-uclass.c
@@ -88,8 +88,8 @@ int reset_get_bulk(struct udevice *dev, struct reset_ctl_bulk *bulk)
bulk->count = 0;
count = dev_count_phandle_with_args(dev, "resets", "#reset-cells");
- if (!count)
- return 0;
+ if (count < 1)
+ return count;
bulk->resets = devm_kcalloc(dev, count, sizeof(struct reset_ctl),
GFP_KERNEL);