提交 b3262720 编写于 作者: L Linus Torvalds

Merge tag 'armsoc-late' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM SoC late updates from Olof Johansson:
 "A couple of late-merged changes that would be useful to get in this
  merge window:

   - Driver support for reset of audio complex on Meson platforms. The
     audio driver went in this merge window, and these changes have been
     in -next for a while (just not in our tree).

   - Power management fixes for IOMMU on Rockchip platforms, getting
     closer to kexec working on them, including Chromebooks.

   - Another pass updating "arm,psci" -> "psci" for some properties that
     have snuck in since last time it was done"

* tag 'armsoc-late' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc:
  iommu/rockchip: Move irq request past pm_runtime_enable
  iommu/rockchip: Handle errors returned from PM framework
  arm64: rockchip: Force CONFIG_PM on Rockchip systems
  ARM: rockchip: Force CONFIG_PM on Rockchip systems
  arm64: dts: Fix various entry-method properties to reflect documentation
  reset: imx7: Fix always writing bits as 0
  reset: meson: add meson audio arb driver
  reset: meson: add dt-bindings for meson-axg audio arb
...@@ -94,7 +94,7 @@ cpus { ...@@ -94,7 +94,7 @@ cpus {
}; };
idle-states { idle-states {
entry-method = "arm,psci"; entry-method = "psci";
CPU_SLEEP_0: cpu-sleep-0 { CPU_SLEEP_0: cpu-sleep-0 {
compatible = "arm,idle-state"; compatible = "arm,idle-state";
......
...@@ -237,8 +237,8 @@ processor idle states, defined as device tree nodes, are listed. ...@@ -237,8 +237,8 @@ processor idle states, defined as device tree nodes, are listed.
Value type: <stringlist> Value type: <stringlist>
Usage and definition depend on ARM architecture version. Usage and definition depend on ARM architecture version.
# On ARM v8 64-bit this property is required and must # On ARM v8 64-bit this property is required and must
be one of: be:
- "psci" (see bindings in [2]) - "psci"
# On ARM 32-bit systems this property is optional # On ARM 32-bit systems this property is optional
The nodes describing the idle states (state) can only be defined within the The nodes describing the idle states (state) can only be defined within the
......
* Amlogic audio memory arbiter controller
The Amlogic Audio ARB is a simple device which enables or
disables the access of Audio FIFOs to DDR on AXG based SoC.
Required properties:
- compatible: 'amlogic,meson-axg-audio-arb'
- reg: physical base address of the controller and length of memory
mapped region.
- clocks: phandle to the fifo peripheral clock provided by the audio
clock controller.
- #reset-cells: must be 1.
Example on the A113 SoC:
arb: reset-controller@280 {
compatible = "amlogic,meson-axg-audio-arb";
reg = <0x0 0x280 0x0 0x4>;
#reset-cells = <1>;
clocks = <&clkc_audio AUD_CLKID_DDR_ARB>;
};
...@@ -17,6 +17,7 @@ config ARCH_ROCKCHIP ...@@ -17,6 +17,7 @@ config ARCH_ROCKCHIP
select ARM_GLOBAL_TIMER select ARM_GLOBAL_TIMER
select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
select ZONE_DMA if ARM_LPAE select ZONE_DMA if ARM_LPAE
select PM
help help
Support for Rockchip's Cortex-A9 Single-to-Quad-Core-SoCs Support for Rockchip's Cortex-A9 Single-to-Quad-Core-SoCs
containing the RK2928, RK30xx and RK31xx series. containing the RK2928, RK30xx and RK31xx series.
...@@ -158,6 +158,7 @@ config ARCH_ROCKCHIP ...@@ -158,6 +158,7 @@ config ARCH_ROCKCHIP
select GPIOLIB select GPIOLIB
select PINCTRL select PINCTRL
select PINCTRL_ROCKCHIP select PINCTRL_ROCKCHIP
select PM
select ROCKCHIP_TIMER select ROCKCHIP_TIMER
help help
This enables support for the ARMv8 based Rockchip chipsets, This enables support for the ARMv8 based Rockchip chipsets,
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
}; };
idle-states { idle-states {
entry-method = "arm,psci"; entry-method = "psci";
CPU_SLEEP_0: cpu-sleep-0 { CPU_SLEEP_0: cpu-sleep-0 {
compatible = "arm,idle-state"; compatible = "arm,idle-state";
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
}; };
idle-states { idle-states {
entry-method = "arm,psci"; entry-method = "psci";
CPU_SLEEP_0: cpu-sleep-0 { CPU_SLEEP_0: cpu-sleep-0 {
compatible = "arm,idle-state"; compatible = "arm,idle-state";
......
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
}; };
idle-states { idle-states {
entry-method = "arm,psci"; entry-method = "psci";
CPU_SLEEP_0: cpu-sleep-0 { CPU_SLEEP_0: cpu-sleep-0 {
compatible = "arm,idle-state"; compatible = "arm,idle-state";
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
* PSCI node is not added default, U-boot will add missing * PSCI node is not added default, U-boot will add missing
* parts if it determines to use PSCI. * parts if it determines to use PSCI.
*/ */
entry-method = "arm,psci"; entry-method = "psci";
CPU_PH20: cpu-ph20 { CPU_PH20: cpu-ph20 {
compatible = "arm,idle-state"; compatible = "arm,idle-state";
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
* PSCI node is not added default, U-boot will add missing * PSCI node is not added default, U-boot will add missing
* parts if it determines to use PSCI. * parts if it determines to use PSCI.
*/ */
entry-method = "arm,psci"; entry-method = "psci";
CPU_PH20: cpu-ph20 { CPU_PH20: cpu-ph20 {
compatible = "arm,idle-state"; compatible = "arm,idle-state";
......
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
* PSCI node is not added default, U-boot will add missing * PSCI node is not added default, U-boot will add missing
* parts if it determines to use PSCI. * parts if it determines to use PSCI.
*/ */
entry-method = "arm,psci"; entry-method = "psci";
CPU_PH20: cpu-ph20 { CPU_PH20: cpu-ph20 {
compatible = "arm,idle-state"; compatible = "arm,idle-state";
......
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
}; };
idle-states { idle-states {
entry-method = "arm,psci"; entry-method = "psci";
CPU_SLEEP_0: cpu-sleep-0 { CPU_SLEEP_0: cpu-sleep-0 {
compatible = "arm,idle-state"; compatible = "arm,idle-state";
......
...@@ -114,7 +114,7 @@ ...@@ -114,7 +114,7 @@
}; };
idle-states{ idle-states{
entry-method = "arm,psci"; entry-method = "psci";
CORE_PD: core_pd { CORE_PD: core_pd {
compatible = "arm,idle-state"; compatible = "arm,idle-state";
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
}; };
idle-states { idle-states {
entry-method = "arm,psci"; entry-method = "psci";
CPU_SLEEP_0: cpu-sleep-0 { CPU_SLEEP_0: cpu-sleep-0 {
compatible = "arm,idle-state"; compatible = "arm,idle-state";
......
...@@ -521,10 +521,11 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id) ...@@ -521,10 +521,11 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
u32 int_status; u32 int_status;
dma_addr_t iova; dma_addr_t iova;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
int i; int i, err;
if (WARN_ON(!pm_runtime_get_if_in_use(iommu->dev))) err = pm_runtime_get_if_in_use(iommu->dev);
return 0; if (WARN_ON_ONCE(err <= 0))
return ret;
if (WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks))) if (WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks)))
goto out; goto out;
...@@ -620,11 +621,15 @@ static void rk_iommu_zap_iova(struct rk_iommu_domain *rk_domain, ...@@ -620,11 +621,15 @@ static void rk_iommu_zap_iova(struct rk_iommu_domain *rk_domain,
spin_lock_irqsave(&rk_domain->iommus_lock, flags); spin_lock_irqsave(&rk_domain->iommus_lock, flags);
list_for_each(pos, &rk_domain->iommus) { list_for_each(pos, &rk_domain->iommus) {
struct rk_iommu *iommu; struct rk_iommu *iommu;
int ret;
iommu = list_entry(pos, struct rk_iommu, node); iommu = list_entry(pos, struct rk_iommu, node);
/* Only zap TLBs of IOMMUs that are powered on. */ /* Only zap TLBs of IOMMUs that are powered on. */
if (pm_runtime_get_if_in_use(iommu->dev)) { ret = pm_runtime_get_if_in_use(iommu->dev);
if (WARN_ON_ONCE(ret < 0))
continue;
if (ret) {
WARN_ON(clk_bulk_enable(iommu->num_clocks, WARN_ON(clk_bulk_enable(iommu->num_clocks,
iommu->clocks)); iommu->clocks));
rk_iommu_zap_lines(iommu, iova, size); rk_iommu_zap_lines(iommu, iova, size);
...@@ -891,6 +896,7 @@ static void rk_iommu_detach_device(struct iommu_domain *domain, ...@@ -891,6 +896,7 @@ static void rk_iommu_detach_device(struct iommu_domain *domain,
struct rk_iommu *iommu; struct rk_iommu *iommu;
struct rk_iommu_domain *rk_domain = to_rk_domain(domain); struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
unsigned long flags; unsigned long flags;
int ret;
/* Allow 'virtual devices' (eg drm) to detach from domain */ /* Allow 'virtual devices' (eg drm) to detach from domain */
iommu = rk_iommu_from_dev(dev); iommu = rk_iommu_from_dev(dev);
...@@ -909,7 +915,9 @@ static void rk_iommu_detach_device(struct iommu_domain *domain, ...@@ -909,7 +915,9 @@ static void rk_iommu_detach_device(struct iommu_domain *domain,
list_del_init(&iommu->node); list_del_init(&iommu->node);
spin_unlock_irqrestore(&rk_domain->iommus_lock, flags); spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
if (pm_runtime_get_if_in_use(iommu->dev)) { ret = pm_runtime_get_if_in_use(iommu->dev);
WARN_ON_ONCE(ret < 0);
if (ret > 0) {
rk_iommu_disable(iommu); rk_iommu_disable(iommu);
pm_runtime_put(iommu->dev); pm_runtime_put(iommu->dev);
} }
...@@ -946,7 +954,8 @@ static int rk_iommu_attach_device(struct iommu_domain *domain, ...@@ -946,7 +954,8 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
list_add_tail(&iommu->node, &rk_domain->iommus); list_add_tail(&iommu->node, &rk_domain->iommus);
spin_unlock_irqrestore(&rk_domain->iommus_lock, flags); spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
if (!pm_runtime_get_if_in_use(iommu->dev)) ret = pm_runtime_get_if_in_use(iommu->dev);
if (!ret || WARN_ON_ONCE(ret < 0))
return 0; return 0;
ret = rk_iommu_enable(iommu); ret = rk_iommu_enable(iommu);
...@@ -1151,17 +1160,6 @@ static int rk_iommu_probe(struct platform_device *pdev) ...@@ -1151,17 +1160,6 @@ static int rk_iommu_probe(struct platform_device *pdev)
if (iommu->num_mmu == 0) if (iommu->num_mmu == 0)
return PTR_ERR(iommu->bases[0]); return PTR_ERR(iommu->bases[0]);
i = 0;
while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) {
if (irq < 0)
return irq;
err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
IRQF_SHARED, dev_name(dev), iommu);
if (err)
return err;
}
iommu->reset_disabled = device_property_read_bool(dev, iommu->reset_disabled = device_property_read_bool(dev,
"rockchip,disable-mmu-reset"); "rockchip,disable-mmu-reset");
...@@ -1218,6 +1216,19 @@ static int rk_iommu_probe(struct platform_device *pdev) ...@@ -1218,6 +1216,19 @@ static int rk_iommu_probe(struct platform_device *pdev)
pm_runtime_enable(dev); pm_runtime_enable(dev);
i = 0;
while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) {
if (irq < 0)
return irq;
err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
IRQF_SHARED, dev_name(dev), iommu);
if (err) {
pm_runtime_disable(dev);
goto err_remove_sysfs;
}
}
return 0; return 0;
err_remove_sysfs: err_remove_sysfs:
iommu_device_sysfs_remove(&iommu->iommu); iommu_device_sysfs_remove(&iommu->iommu);
......
...@@ -73,6 +73,13 @@ config RESET_MESON ...@@ -73,6 +73,13 @@ config RESET_MESON
help help
This enables the reset driver for Amlogic Meson SoCs. This enables the reset driver for Amlogic Meson SoCs.
config RESET_MESON_AUDIO_ARB
tristate "Meson Audio Memory Arbiter Reset Driver"
depends on ARCH_MESON || COMPILE_TEST
help
This enables the reset driver for Audio Memory Arbiter of
Amlogic's A113 based SoCs
config RESET_OXNAS config RESET_OXNAS
bool bool
......
...@@ -12,6 +12,7 @@ obj-$(CONFIG_RESET_IMX7) += reset-imx7.o ...@@ -12,6 +12,7 @@ obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o obj-$(CONFIG_RESET_MESON) += reset-meson.o
obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
......
...@@ -81,7 +81,7 @@ static int imx7_reset_set(struct reset_controller_dev *rcdev, ...@@ -81,7 +81,7 @@ static int imx7_reset_set(struct reset_controller_dev *rcdev,
{ {
struct imx7_src *imx7src = to_imx7_src(rcdev); struct imx7_src *imx7src = to_imx7_src(rcdev);
const struct imx7_src_signal *signal = &imx7_src_signals[id]; const struct imx7_src_signal *signal = &imx7_src_signals[id];
unsigned int value = 0; unsigned int value = assert ? signal->bit : 0;
switch (id) { switch (id) {
case IMX7_RESET_PCIEPHY: case IMX7_RESET_PCIEPHY:
......
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
// Copyright (c) 2018 BayLibre, SAS.
// Author: Jerome Brunet <jbrunet@baylibre.com>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/reset-controller.h>
#include <linux/spinlock.h>
#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
struct meson_audio_arb_data {
struct reset_controller_dev rstc;
void __iomem *regs;
struct clk *clk;
const unsigned int *reset_bits;
spinlock_t lock;
};
#define ARB_GENERAL_BIT 31
static const unsigned int axg_audio_arb_reset_bits[] = {
[AXG_ARB_TODDR_A] = 0,
[AXG_ARB_TODDR_B] = 1,
[AXG_ARB_TODDR_C] = 2,
[AXG_ARB_FRDDR_A] = 4,
[AXG_ARB_FRDDR_B] = 5,
[AXG_ARB_FRDDR_C] = 6,
};
static int meson_audio_arb_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
u32 val;
struct meson_audio_arb_data *arb =
container_of(rcdev, struct meson_audio_arb_data, rstc);
spin_lock(&arb->lock);
val = readl(arb->regs);
if (assert)
val &= ~BIT(arb->reset_bits[id]);
else
val |= BIT(arb->reset_bits[id]);
writel(val, arb->regs);
spin_unlock(&arb->lock);
return 0;
}
static int meson_audio_arb_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
u32 val;
struct meson_audio_arb_data *arb =
container_of(rcdev, struct meson_audio_arb_data, rstc);
val = readl(arb->regs);
return !(val & BIT(arb->reset_bits[id]));
}
static int meson_audio_arb_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return meson_audio_arb_update(rcdev, id, true);
}
static int meson_audio_arb_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return meson_audio_arb_update(rcdev, id, false);
}
static const struct reset_control_ops meson_audio_arb_rstc_ops = {
.assert = meson_audio_arb_assert,
.deassert = meson_audio_arb_deassert,
.status = meson_audio_arb_status,
};
static const struct of_device_id meson_audio_arb_of_match[] = {
{ .compatible = "amlogic,meson-axg-audio-arb", },
{}
};
MODULE_DEVICE_TABLE(of, meson_audio_arb_of_match);
static int meson_audio_arb_remove(struct platform_device *pdev)
{
struct meson_audio_arb_data *arb = platform_get_drvdata(pdev);
/* Disable all access */
spin_lock(&arb->lock);
writel(0, arb->regs);
spin_unlock(&arb->lock);
clk_disable_unprepare(arb->clk);
return 0;
}
static int meson_audio_arb_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct meson_audio_arb_data *arb;
struct resource *res;
int ret;
arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL);
if (!arb)
return -ENOMEM;
platform_set_drvdata(pdev, arb);
arb->clk = devm_clk_get(dev, NULL);
if (IS_ERR(arb->clk)) {
if (PTR_ERR(arb->clk) != -EPROBE_DEFER)
dev_err(dev, "failed to get clock\n");
return PTR_ERR(arb->clk);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
arb->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(arb->regs))
return PTR_ERR(arb->regs);
spin_lock_init(&arb->lock);
arb->reset_bits = axg_audio_arb_reset_bits;
arb->rstc.nr_resets = ARRAY_SIZE(axg_audio_arb_reset_bits);
arb->rstc.ops = &meson_audio_arb_rstc_ops;
arb->rstc.of_node = dev->of_node;
/*
* Enable general :
* In the initial state, all memory interfaces are disabled
* and the general bit is on
*/
ret = clk_prepare_enable(arb->clk);
if (ret) {
dev_err(dev, "failed to enable arb clock\n");
return ret;
}
writel(BIT(ARB_GENERAL_BIT), arb->regs);
/* Register reset controller */
ret = devm_reset_controller_register(dev, &arb->rstc);
if (ret) {
dev_err(dev, "failed to register arb reset controller\n");
meson_audio_arb_remove(pdev);
}
return ret;
}
static struct platform_driver meson_audio_arb_pdrv = {
.probe = meson_audio_arb_probe,
.remove = meson_audio_arb_remove,
.driver = {
.name = "meson-audio-arb-reset",
.of_match_table = meson_audio_arb_of_match,
},
};
module_platform_driver(meson_audio_arb_pdrv);
MODULE_DESCRIPTION("Amlogic A113 Audio Memory Arbiter");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL v2");
/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
*
* Copyright (c) 2018 Baylibre SAS.
* Author: Jerome Brunet <jbrunet@baylibre.com>
*/
#ifndef _DT_BINDINGS_AMLOGIC_MESON_AXG_AUDIO_ARB_H
#define _DT_BINDINGS_AMLOGIC_MESON_AXG_AUDIO_ARB_H
#define AXG_ARB_TODDR_A 0
#define AXG_ARB_TODDR_B 1
#define AXG_ARB_TODDR_C 2
#define AXG_ARB_FRDDR_A 3
#define AXG_ARB_FRDDR_B 4
#define AXG_ARB_FRDDR_C 5
#endif /* _DT_BINDINGS_AMLOGIC_MESON_AXG_AUDIO_ARB_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册