diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-16 16:05:01 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-16 16:05:01 -0800 |
commit | cf9b0772f2e410645fece13b749bd56505b998b8 (patch) | |
tree | 8b171a2c49d1e9e41d4e43fb91602e664cde8551 /drivers/reset/reset-meson.c | |
parent | 527d1470744d338c912f94bc1f4dba08ffdff349 (diff) | |
parent | 339cd0ea082287ea8e2b7e7159a5a33665a2cbe3 (diff) |
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Arnd Bergmann:
"This branch contains platform-related driver updates for ARM and
ARM64, these are the areas that bring the changes:
New drivers:
- driver support for Renesas R-Car V3M (R8A77970)
- power management support for Amlogic GX
- a new driver for the Tegra BPMP thermal sensor
- a new bus driver for Technologic Systems NBUS
Changes for subsystems that prefer to merge through arm-soc:
- the usual updates for reset controller drivers from Philipp Zabel,
with five added drivers for SoCs in the arc, meson, socfpa,
uniphier and mediatek families
- updates to the ARM SCPI and PSCI frameworks, from Sudeep Holla,
Heiner Kallweit and Lorenzo Pieralisi
Changes specific to some ARM-based SoC
- the Freescale/NXP DPAA QBMan drivers from PowerPC can now work on
ARM as well
- several changes for power management on Broadcom SoCs
- various improvements on Qualcomm, Broadcom, Amlogic, Atmel,
Mediatek
- minor Cleanups for Samsung, TI OMAP SoCs"
[ NOTE! This doesn't work without the previous ARM SoC device-tree pull,
because the R8A77970 driver is missing a header file that came from
that pull.
The fact that this got merged afterwards only fixes it at this point,
and bisection of that driver will fail if/when you walk into the
history of that driver. - Linus ]
* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (96 commits)
soc: amlogic: meson-gx-pwrc-vpu: fix power-off when powered by bootloader
bus: add driver for the Technologic Systems NBUS
memory: omap-gpmc: Remove deprecated gpmc_update_nand_reg()
soc: qcom: remove unused label
soc: amlogic: gx pm domain: add PM and OF dependencies
drivers/firmware: psci_checker: Add missing destroy_timer_on_stack()
dt-bindings: power: add amlogic meson power domain bindings
soc: amlogic: add Meson GX VPU Domains driver
soc: qcom: Remote filesystem memory driver
dt-binding: soc: qcom: Add binding for rmtfs memory
of: reserved_mem: Accessor for acquiring reserved_mem
of/platform: Generalize /reserved-memory handling
soc: mediatek: pwrap: fix fatal compiler error
soc: mediatek: pwrap: fix compiler errors
arm64: mediatek: cleanup message for platform selection
soc: Allow test-building of MediaTek drivers
soc: mediatek: place Kconfig for all SoC drivers under menu
soc: mediatek: pwrap: add support for MT7622 SoC
soc: mediatek: pwrap: add common way for setup CS timing extenstion
soc: mediatek: pwrap: add MediaTek MT6380 as one slave of pwrap
..
Diffstat (limited to 'drivers/reset/reset-meson.c')
-rw-r--r-- | drivers/reset/reset-meson.c | 65 |
1 files changed, 58 insertions, 7 deletions
diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c index a8b915eb8b58..c419a3753d00 100644 --- a/drivers/reset/reset-meson.c +++ b/drivers/reset/reset-meson.c @@ -62,13 +62,16 @@ #include <linux/reset-controller.h> #include <linux/slab.h> #include <linux/types.h> +#include <linux/of_device.h> #define REG_COUNT 8 #define BITS_PER_REG 32 +#define LEVEL_OFFSET 0x7c struct meson_reset { void __iomem *reg_base; struct reset_controller_dev rcdev; + spinlock_t lock; }; static int meson_reset_reset(struct reset_controller_dev *rcdev, @@ -80,26 +83,68 @@ static int meson_reset_reset(struct reset_controller_dev *rcdev, unsigned int offset = id % BITS_PER_REG; void __iomem *reg_addr = data->reg_base + (bank << 2); - if (bank >= REG_COUNT) - return -EINVAL; - writel(BIT(offset), reg_addr); return 0; } -static const struct reset_control_ops meson_reset_ops = { +static int meson_reset_level(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + struct meson_reset *data = + container_of(rcdev, struct meson_reset, rcdev); + unsigned int bank = id / BITS_PER_REG; + unsigned int offset = id % BITS_PER_REG; + void __iomem *reg_addr = data->reg_base + LEVEL_OFFSET + (bank << 2); + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&data->lock, flags); + + reg = readl(reg_addr); + if (assert) + writel(reg & ~BIT(offset), reg_addr); + else + writel(reg | BIT(offset), reg_addr); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static int meson_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return meson_reset_level(rcdev, id, true); +} + +static int meson_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return meson_reset_level(rcdev, id, false); +} + +static const struct reset_control_ops meson_reset_meson8_ops = { .reset = meson_reset_reset, }; +static const struct reset_control_ops meson_reset_gx_ops = { + .reset = meson_reset_reset, + .assert = meson_reset_assert, + .deassert = meson_reset_deassert, +}; + static const struct of_device_id meson_reset_dt_ids[] = { - { .compatible = "amlogic,meson8b-reset", }, - { .compatible = "amlogic,meson-gxbb-reset", }, + { .compatible = "amlogic,meson8b-reset", + .data = &meson_reset_meson8_ops, }, + { .compatible = "amlogic,meson-gxbb-reset", + .data = &meson_reset_gx_ops, }, { /* sentinel */ }, }; static int meson_reset_probe(struct platform_device *pdev) { + const struct reset_control_ops *ops; struct meson_reset *data; struct resource *res; @@ -107,6 +152,10 @@ static int meson_reset_probe(struct platform_device *pdev) if (!data) return -ENOMEM; + ops = of_device_get_match_data(&pdev->dev); + if (!ops) + return -EINVAL; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); data->reg_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(data->reg_base)) @@ -114,9 +163,11 @@ static int meson_reset_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); + spin_lock_init(&data->lock); + data->rcdev.owner = THIS_MODULE; data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG; - data->rcdev.ops = &meson_reset_ops; + data->rcdev.ops = ops; data->rcdev.of_node = pdev->dev.of_node; return devm_reset_controller_register(&pdev->dev, &data->rcdev); |