diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/clk-uclass.c | 59 | ||||
-rw-r--r-- | drivers/clk/clk_sandbox_test.c | 29 | ||||
-rw-r--r-- | drivers/reset/Kconfig | 8 | ||||
-rw-r--r-- | drivers/reset/Makefile | 1 | ||||
-rw-r--r-- | drivers/reset/reset-meson.c | 90 | ||||
-rw-r--r-- | drivers/reset/reset-uclass.c | 60 | ||||
-rw-r--r-- | drivers/reset/sandbox-reset-test.c | 29 | ||||
-rw-r--r-- | drivers/reset/sandbox-reset.c | 2 | ||||
-rw-r--r-- | drivers/serial/Makefile | 20 | ||||
-rw-r--r-- | drivers/serial/serial_meson.c | 1 | ||||
-rw-r--r-- | drivers/sysreset/sysreset_syscon.c | 8 |
11 files changed, 298 insertions, 9 deletions
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index ad763795d9..6e99b3b15d 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -104,6 +104,39 @@ int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) return clk_get_by_indexed_prop(dev, "clocks", index, clk); } +int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk) +{ + int i, ret, err, count; + + bulk->count = 0; + + count = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); + if (!count) + return 0; + + bulk->clks = devm_kcalloc(dev, count, sizeof(struct clk), GFP_KERNEL); + if (!bulk->clks) + return -ENOMEM; + + for (i = 0; i < count; i++) { + ret = clk_get_by_index(dev, i, &bulk->clks[i]); + if (ret < 0) + goto bulk_get_err; + + ++bulk->count; + } + + return 0; + +bulk_get_err: + err = clk_release_all(bulk->clks, bulk->count); + if (err) + debug("%s: could release all clocks for %p\n", + __func__, dev); + + return ret; +} + static int clk_set_default_parents(struct udevice *dev) { struct clk clk, parent_clk; @@ -336,6 +369,19 @@ int clk_enable(struct clk *clk) return ops->enable(clk); } +int clk_enable_bulk(struct clk_bulk *bulk) +{ + int i, ret; + + for (i = 0; i < bulk->count; i++) { + ret = clk_enable(&bulk->clks[i]); + if (ret < 0 && ret != -ENOSYS) + return ret; + } + + return 0; +} + int clk_disable(struct clk *clk) { const struct clk_ops *ops = clk_dev_ops(clk->dev); @@ -348,6 +394,19 @@ int clk_disable(struct clk *clk) return ops->disable(clk); } +int clk_disable_bulk(struct clk_bulk *bulk) +{ + int i, ret; + + for (i = 0; i < bulk->count; i++) { + ret = clk_disable(&bulk->clks[i]); + if (ret < 0 && ret != -ENOSYS) + return ret; + } + + return 0; +} + UCLASS_DRIVER(clk) = { .id = UCLASS_CLK, .name = "clk", diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c index 999100de9d..d0898815b3 100644 --- a/drivers/clk/clk_sandbox_test.c +++ b/drivers/clk/clk_sandbox_test.c @@ -11,6 +11,7 @@ struct sandbox_clk_test { struct clk clks[SANDBOX_CLK_TEST_ID_COUNT]; + struct clk_bulk bulk; }; static const char * const sandbox_clk_test_names[] = { @@ -34,6 +35,13 @@ int sandbox_clk_test_get(struct udevice *dev) return 0; } +int sandbox_clk_test_get_bulk(struct udevice *dev) +{ + struct sandbox_clk_test *sbct = dev_get_priv(dev); + + return clk_get_bulk(dev, &sbct->bulk); +} + ulong sandbox_clk_test_get_rate(struct udevice *dev, int id) { struct sandbox_clk_test *sbct = dev_get_priv(dev); @@ -64,6 +72,13 @@ int sandbox_clk_test_enable(struct udevice *dev, int id) return clk_enable(&sbct->clks[id]); } +int sandbox_clk_test_enable_bulk(struct udevice *dev) +{ + struct sandbox_clk_test *sbct = dev_get_priv(dev); + + return clk_enable_bulk(&sbct->bulk); +} + int sandbox_clk_test_disable(struct udevice *dev, int id) { struct sandbox_clk_test *sbct = dev_get_priv(dev); @@ -74,6 +89,13 @@ int sandbox_clk_test_disable(struct udevice *dev, int id) return clk_disable(&sbct->clks[id]); } +int sandbox_clk_test_disable_bulk(struct udevice *dev) +{ + struct sandbox_clk_test *sbct = dev_get_priv(dev); + + return clk_disable_bulk(&sbct->bulk); +} + int sandbox_clk_test_free(struct udevice *dev) { struct sandbox_clk_test *sbct = dev_get_priv(dev); @@ -88,6 +110,13 @@ int sandbox_clk_test_free(struct udevice *dev) return 0; } +int sandbox_clk_test_release_bulk(struct udevice *dev) +{ + struct sandbox_clk_test *sbct = dev_get_priv(dev); + + return clk_release_bulk(&sbct->bulk); +} + static const struct udevice_id sandbox_clk_test_ids[] = { { .compatible = "sandbox,clk-test" }, { } diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 71a786bab5..ccfdac7823 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -83,4 +83,12 @@ config RESET_ROCKCHIP though is that some reset signals, like I2C or MISC reset multiple devices. +config RESET_MESON + bool "Reset controller driver for Amlogic Meson SoCs" + depends on DM_RESET && ARCH_MESON + imply REGMAP + default y + help + Support for reset controller on Amlogic Meson SoC. + endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 7d7e080c78..d1d5146825 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o 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 diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c new file mode 100644 index 0000000000..5324f86f5f --- /dev/null +++ b/drivers/reset/reset-meson.c @@ -0,0 +1,90 @@ +/* + * Amlogic Meson Reset Controller driver + * + * Copyright (c) 2018 BayLibre, SAS. + * Author: Neil Armstrong <narmstrong@baylibre.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <dm.h> +#include <reset-uclass.h> +#include <regmap.h> + +#define REG_COUNT 8 +#define BITS_PER_REG 32 +#define LEVEL_OFFSET 0x7c + +struct meson_reset_priv { + struct regmap *regmap; +}; + +static int meson_reset_request(struct reset_ctl *reset_ctl) +{ + if (reset_ctl->id > (REG_COUNT * BITS_PER_REG)) + return -EINVAL; + + return 0; +} + +static int meson_reset_free(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int meson_reset_level(struct reset_ctl *reset_ctl, bool assert) +{ + struct meson_reset_priv *priv = dev_get_priv(reset_ctl->dev); + uint bank = reset_ctl->id / BITS_PER_REG; + uint offset = reset_ctl->id % BITS_PER_REG; + uint reg_offset = LEVEL_OFFSET + (bank << 2); + uint val; + + regmap_read(priv->regmap, reg_offset, &val); + if (assert) + val &= ~BIT(offset); + else + val |= BIT(offset); + regmap_write(priv->regmap, reg_offset, val); + + return 0; +} + +static int meson_reset_assert(struct reset_ctl *reset_ctl) +{ + return meson_reset_level(reset_ctl, true); +} + +static int meson_reset_deassert(struct reset_ctl *reset_ctl) +{ + return meson_reset_level(reset_ctl, false); +} + +struct reset_ops meson_reset_ops = { + .request = meson_reset_request, + .free = meson_reset_free, + .rst_assert = meson_reset_assert, + .rst_deassert = meson_reset_deassert, +}; + +static const struct udevice_id meson_reset_ids[] = { + { .compatible = "amlogic,meson-gxbb-reset" }, + { } +}; + +static int meson_reset_probe(struct udevice *dev) +{ + struct meson_reset_priv *priv = dev_get_priv(dev); + + return regmap_init_mem(dev, &priv->regmap); +} + +U_BOOT_DRIVER(meson_reset) = { + .name = "meson_reset", + .id = UCLASS_RESET, + .of_match = meson_reset_ids, + .probe = meson_reset_probe, + .ops = &meson_reset_ops, + .priv_auto_alloc_size = sizeof(struct meson_reset_priv), +}; diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c index 307a29705f..9a5c9c91b9 100644 --- a/drivers/reset/reset-uclass.c +++ b/drivers/reset/reset-uclass.c @@ -81,6 +81,40 @@ int reset_get_by_index(struct udevice *dev, int index, return 0; } +int reset_get_bulk(struct udevice *dev, struct reset_ctl_bulk *bulk) +{ + int i, ret, err, count; + + bulk->count = 0; + + count = dev_count_phandle_with_args(dev, "resets", "#reset-cells"); + if (!count) + return 0; + + bulk->resets = devm_kcalloc(dev, count, sizeof(struct reset_ctl), + GFP_KERNEL); + if (!bulk->resets) + return -ENOMEM; + + for (i = 0; i < count; i++) { + ret = reset_get_by_index(dev, i, &bulk->resets[i]); + if (ret < 0) + goto bulk_get_err; + + ++bulk->count; + } + + return 0; + +bulk_get_err: + err = reset_release_all(bulk->resets, bulk->count); + if (err) + debug("%s: could release all resets for %p\n", + __func__, dev); + + return ret; +} + int reset_get_by_name(struct udevice *dev, const char *name, struct reset_ctl *reset_ctl) { @@ -126,6 +160,19 @@ int reset_assert(struct reset_ctl *reset_ctl) return ops->rst_assert(reset_ctl); } +int reset_assert_bulk(struct reset_ctl_bulk *bulk) +{ + int i, ret; + + for (i = 0; i < bulk->count; i++) { + ret = reset_assert(&bulk->resets[i]); + if (ret < 0) + return ret; + } + + return 0; +} + int reset_deassert(struct reset_ctl *reset_ctl) { struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); @@ -135,6 +182,19 @@ int reset_deassert(struct reset_ctl *reset_ctl) return ops->rst_deassert(reset_ctl); } +int reset_deassert_bulk(struct reset_ctl_bulk *bulk) +{ + int i, ret; + + for (i = 0; i < bulk->count; i++) { + ret = reset_deassert(&bulk->resets[i]); + if (ret < 0) + return ret; + } + + return 0; +} + int reset_release_all(struct reset_ctl *reset_ctl, int count) { int i, ret; diff --git a/drivers/reset/sandbox-reset-test.c b/drivers/reset/sandbox-reset-test.c index e37d6c91ef..f0ceaa0483 100644 --- a/drivers/reset/sandbox-reset-test.c +++ b/drivers/reset/sandbox-reset-test.c @@ -12,6 +12,7 @@ struct sandbox_reset_test { struct reset_ctl ctl; + struct reset_ctl_bulk bulk; }; int sandbox_reset_test_get(struct udevice *dev) @@ -21,6 +22,13 @@ int sandbox_reset_test_get(struct udevice *dev) return reset_get_by_name(dev, "test", &sbrt->ctl); } +int sandbox_reset_test_get_bulk(struct udevice *dev) +{ + struct sandbox_reset_test *sbrt = dev_get_priv(dev); + + return reset_get_bulk(dev, &sbrt->bulk); +} + int sandbox_reset_test_assert(struct udevice *dev) { struct sandbox_reset_test *sbrt = dev_get_priv(dev); @@ -28,6 +36,13 @@ int sandbox_reset_test_assert(struct udevice *dev) return reset_assert(&sbrt->ctl); } +int sandbox_reset_test_assert_bulk(struct udevice *dev) +{ + struct sandbox_reset_test *sbrt = dev_get_priv(dev); + + return reset_assert_bulk(&sbrt->bulk); +} + int sandbox_reset_test_deassert(struct udevice *dev) { struct sandbox_reset_test *sbrt = dev_get_priv(dev); @@ -35,6 +50,13 @@ int sandbox_reset_test_deassert(struct udevice *dev) return reset_deassert(&sbrt->ctl); } +int sandbox_reset_test_deassert_bulk(struct udevice *dev) +{ + struct sandbox_reset_test *sbrt = dev_get_priv(dev); + + return reset_deassert_bulk(&sbrt->bulk); +} + int sandbox_reset_test_free(struct udevice *dev) { struct sandbox_reset_test *sbrt = dev_get_priv(dev); @@ -42,6 +64,13 @@ int sandbox_reset_test_free(struct udevice *dev) return reset_free(&sbrt->ctl); } +int sandbox_reset_test_release_bulk(struct udevice *dev) +{ + struct sandbox_reset_test *sbrt = dev_get_priv(dev); + + return reset_release_bulk(&sbrt->bulk); +} + static const struct udevice_id sandbox_reset_test_ids[] = { { .compatible = "sandbox,reset-ctl-test" }, { } diff --git a/drivers/reset/sandbox-reset.c b/drivers/reset/sandbox-reset.c index 4258af521b..c310749dc8 100644 --- a/drivers/reset/sandbox-reset.c +++ b/drivers/reset/sandbox-reset.c @@ -10,7 +10,7 @@ #include <asm/io.h> #include <asm/reset.h> -#define SANDBOX_RESET_SIGNALS 3 +#define SANDBOX_RESET_SIGNALS 101 struct sandbox_reset_signal { bool asserted; diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index cac9a8b312..6937ef9628 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -5,11 +5,27 @@ # SPDX-License-Identifier: GPL-2.0+ # +ifdef CONFIG_SPL_BUILD + +ifeq ($(CONFIG_$(SPL_TPL_)BUILD)$(CONFIG_$(SPL_TPL_)DM_SERIAL),yy) +obj-y += serial-uclass.o +else +obj-y += serial.o +endif + +else + ifdef CONFIG_DM_SERIAL -obj-$(CONFIG_$(SPL_TPL_)DM_SERIAL) += serial-uclass.o -obj-$(CONFIG_PL01X_SERIAL) += serial_pl01x.o +obj-y += serial-uclass.o else obj-y += serial.o +endif + +endif + +ifdef CONFIG_DM_SERIAL +obj-$(CONFIG_PL01X_SERIAL) += serial_pl01x.o +else obj-$(CONFIG_PL010_SERIAL) += serial_pl01x.o obj-$(CONFIG_PL011_SERIAL) += serial_pl01x.o obj-$(CONFIG_SYS_NS16550_SERIAL) += serial_ns16550.o diff --git a/drivers/serial/serial_meson.c b/drivers/serial/serial_meson.c index 363affb8c5..6412ca6496 100644 --- a/drivers/serial/serial_meson.c +++ b/drivers/serial/serial_meson.c @@ -125,6 +125,7 @@ static const struct dm_serial_ops meson_serial_ops = { static const struct udevice_id meson_serial_ids[] = { { .compatible = "amlogic,meson-uart" }, + { .compatible = "amlogic,meson-gx-uart" }, { } }; diff --git a/drivers/sysreset/sysreset_syscon.c b/drivers/sysreset/sysreset_syscon.c index 3abce7f678..22c602a4d2 100644 --- a/drivers/sysreset/sysreset_syscon.c +++ b/drivers/sysreset/sysreset_syscon.c @@ -15,8 +15,6 @@ #include <sysreset.h> #include <syscon.h> -DECLARE_GLOBAL_DATA_PTR; - struct syscon_reboot_priv { struct regmap *regmap; unsigned int offset; @@ -55,10 +53,8 @@ int syscon_reboot_probe(struct udevice *dev) return -ENODEV; } - priv->offset = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), - "offset", 0); - priv->mask = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), - "mask", 0); + priv->offset = dev_read_u32_default(dev, "offset", 0); + priv->mask = dev_read_u32_default(dev, "mask", 0); return 0; } |