* Applied "ASoC: rockchip: i2s: Support mono capture" to the asoc tree
From: Mark Brown @ 2018-01-08 12:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180105221242.22083-1-mka@chromium.org>
The patch
ASoC: rockchip: i2s: Support mono capture
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From db51707b9c9aeedd310ebce60f15d5bb006567e0 Mon Sep 17 00:00:00 2001
From: Matthias Kaehlcke <mka@chromium.org>
Date: Fri, 5 Jan 2018 14:12:42 -0800
Subject: [PATCH] ASoC: rockchip: i2s: Support mono capture
The Rockchip I2S controller only allows to configure even numbers of
capture channels. It is still possible to capture monophonic audio by
using dual-channel mode and ignoring the 'data' from the second
channel.
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/rockchip/rockchip_i2s.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 908211e1d6fc..cc22ab3d10dd 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -328,6 +328,7 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
val |= I2S_CHN_4;
break;
case 2:
+ case 1:
val |= I2S_CHN_2;
break;
default:
@@ -460,7 +461,7 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = {
},
.capture = {
.stream_name = "Capture",
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = (SNDRV_PCM_FMTBIT_S8 |
@@ -654,7 +655,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
}
if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
- if (val >= 2 && val <= 8)
+ if (val >= 1 && val <= 8)
soc_dai->capture.channels_max = val;
}
--
2.15.1
^ permalink raw reply related
* Applied "ASoC: mediatek: mt2701: fix return value check in mt2701_afe_pcm_dev_probe()" to the asoc tree
From: Mark Brown @ 2018-01-08 12:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515377701-37553-1-git-send-email-weiyongjun1@huawei.com>
The patch
ASoC: mediatek: mt2701: fix return value check in mt2701_afe_pcm_dev_probe()
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 3e8052d90d24320a1edb556c20523f3b17195985 Mon Sep 17 00:00:00 2001
From: Wei Yongjun <weiyongjun1@huawei.com>
Date: Mon, 8 Jan 2018 02:15:01 +0000
Subject: [PATCH] ASoC: mediatek: mt2701: fix return value check in
mt2701_afe_pcm_dev_probe()
In case of error, the function syscon_node_to_regmap() returns ERR_PTR()
and never returns NULL. The NULL test in the return value check should
be replaced with IS_ERR().
Fixes: dfa3cbb83e09 ("ASoC: mediatek: modify MT2701 AFE driver to adapt mfd device")
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index f0cd08fa5c5d..5bc4e00a4a29 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -1440,9 +1440,9 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
}
afe->regmap = syscon_node_to_regmap(dev->parent->of_node);
- if (!afe->regmap) {
+ if (IS_ERR(afe->regmap)) {
dev_err(dev, "could not get regmap from parent\n");
- return -ENODEV;
+ return PTR_ERR(afe->regmap);
}
mutex_init(&afe->irq_alloc_lock);
--
2.15.1
^ permalink raw reply related
* [PATCH v6 0/2] Documentation and driver of logicoreIP
From: Michal Simek @ 2018-01-08 12:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513881186-26020-1-git-send-email-dshah@xilinx.com>
On 21.12.2017 19:33, Dhaval Shah wrote:
> 1st patch provide Device Tree binding document for logicoreIP
> 2nd patch provide the xlnx_vcu logicoreIP driver, Kconfig changes
> and Makefile changes for the driver.
>
> Dhaval Shah (2):
> dt-bindings: misc: Add DT bindings to xlnx_vcu driver
> misc: xlnx_vcu: Add Xilinx ZYNQMP VCU logicoreIP init driver
>
> .../devicetree/bindings/soc/xilinx/xlnx,vcu.txt | 31 +
> drivers/soc/xilinx/Kconfig | 15 +
> drivers/soc/xilinx/Makefile | 1 +
> drivers/soc/xilinx/xlnx_vcu.c | 630 +++++++++++++++++++++
> 4 files changed, 677 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/soc/xilinx/xlnx,vcu.txt
> create mode 100644 drivers/soc/xilinx/xlnx_vcu.c
>
It looks like there is no any other concern regarding these patches
that's why I have applied them.
Thanks,
Michal
^ permalink raw reply
* [PATCH v2 1/2] acpi, spcr: Make SPCR avialable to other architectures
From: Prarit Bhargava @ 2018-01-08 12:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213124533.GA32362@red-moon>
[Sorry everyone for the late response, I went away on vacation and pushed this
off until I returned.]
On 12/13/2017 07:45 AM, Lorenzo Pieralisi wrote:
> [+Mark, Graeme]
>
> In $SUBJECT, s/avialable/available
>
> On Mon, Dec 11, 2017 at 10:50:58AM -0500, Prarit Bhargava wrote:
>> Other architectures can use SPCR to setup an early console or console
>> but the current code is ARM64 specific.
>
> I see nothing ARM64 specific in current code (apart from some
> ACPICA macros with an ARM tag in them) please explain to me
> what's preventing you to reuse current code on x86.
Ah, I didn't notice that. I thought the ACPICA macros were ARM specific. I'll
rework this patchset with that in mind.
>
>> Change the name of parse_spcr() to acpi_parse_spcr(). Add a weak
>> function acpi_arch_setup_console() that can be used for arch-specific
>> setup. Move flags into ACPI code. Update the Documention on the use of
>> the SPCR.
>>
>> [v2]: Don't return an error in the baud_rate check of acpi_parse_spcr().
>> Keep ACPI_SPCR_TABLE selected for ARM64. Fix 8-bit port access width
>> mmio value. Move baud rate check earlier.
>
> This does not belong in the commit log.
Yes, but some maintainers like to see what changed between v1 & v2.
>
>> Signed-off-by: Prarit Bhargava <prarit@redhat.com>
>> Cc: linux-doc at vger.kernel.org
>> Cc: linux-kernel at vger.kernel.org
>> Cc: linux-arm-kernel at lists.infradead.org
>> Cc: linux-pm at vger.kernel.org
>> Cc: linux-acpi at vger.kernel.org
>> Cc: linux-serial at vger.kernel.org
>> Cc: Bhupesh Sharma <bhsharma@redhat.com>
>> Cc: Lv Zheng <lv.zheng@intel.com>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Ingo Molnar <mingo@redhat.com>
>> Cc: "H. Peter Anvin" <hpa@zytor.com>
>> Cc: x86 at kernel.org
>> Cc: Jonathan Corbet <corbet@lwn.net>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
>> Cc: Timur Tabi <timur@codeaurora.org>
>> ---
>> Documentation/admin-guide/kernel-parameters.txt | 6 +-
>> arch/arm64/kernel/acpi.c | 128 ++++++++++++++++-
>> drivers/acpi/Kconfig | 7 +-
>> drivers/acpi/spcr.c | 175 ++++++------------------
>> drivers/tty/serial/earlycon.c | 15 +-
>> include/linux/acpi.h | 11 +-
>> include/linux/serial_core.h | 2 -
>> 7 files changed, 184 insertions(+), 160 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
>> index 6571fbfdb2a1..0d173289c67e 100644
>> --- a/Documentation/admin-guide/kernel-parameters.txt
>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>> @@ -914,9 +914,9 @@
>>
>> earlycon= [KNL] Output early console device and options.
>>
>> - When used with no options, the early console is
>> - determined by the stdout-path property in device
>> - tree's chosen node.
>> + [ARM64] The early console is determined by the
>> + stdout-path property in device tree's chosen node,
>> + or determined by the ACPI SPCR table.
>>
>> cdns,<addr>[,options]
>> Start an early, polled-mode console on a Cadence
>> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
>> index b3162715ed78..b3e33bbdf3b7 100644
>> --- a/arch/arm64/kernel/acpi.c
>> +++ b/arch/arm64/kernel/acpi.c
>> @@ -25,7 +25,6 @@
>> #include <linux/memblock.h>
>> #include <linux/of_fdt.h>
>> #include <linux/smp.h>
>> -#include <linux/serial_core.h>
>>
>> #include <asm/cputype.h>
>> #include <asm/cpu_ops.h>
>> @@ -177,6 +176,128 @@ static int __init acpi_fadt_sanity_check(void)
>> return ret;
>> }
>>
>> +/*
>> + * Erratum 44 for QDF2432v1 and QDF2400v1 SoCs describes the BUSY bit as
>> + * occasionally getting stuck as 1. To avoid the potential for a hang, check
>> + * TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART
>> + * implementations, so only do so if an affected platform is detected in
>> + * acpi_parse_spcr().
>> + */
>> +bool qdf2400_e44_present;
>> +EXPORT_SYMBOL(qdf2400_e44_present);
>
> My eyes, this is horrible but it is not introduced by this patch. It
> would have been much better if:
>
> drivers/tty/serial/amba-pl011.c
>
> parsed the SPCR table (again) to detect it instead of relying on this
> horrible exported flag.
It looks like Timur & you had a discussion and the current consensus is to keep
the code the same.
>
>> +
>> +/*
>> + * Some Qualcomm Datacenter Technologies SoCs have a defective UART BUSY bit.
>> + * Detect them by examining the OEM fields in the SPCR header, similar to PCI
>> + * quirk detection in pci_mcfg.c.
>> + */
>> +static bool qdf2400_erratum_44_present(struct acpi_table_header *h)
>> +{
>> + if (memcmp(h->oem_id, "QCOM ", ACPI_OEM_ID_SIZE))
>> + return false;
>> +
>> + if (!memcmp(h->oem_table_id, "QDF2432 ", ACPI_OEM_TABLE_ID_SIZE))
>> + return true;
>> +
>> + if (!memcmp(h->oem_table_id, "QDF2400 ", ACPI_OEM_TABLE_ID_SIZE) &&
>> + h->oem_revision == 1)
>> + return true;
>> +
>> + return false;
>> +}
>> +
>> +/*
>> + * APM X-Gene v1 and v2 UART hardware is an 16550 like device but has its
>> + * register aligned to 32-bit. In addition, the BIOS also encoded the
>> + * access width to be 8 bits. This function detects this errata condition.
>> + */
>> +static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb)
>> +{
>> + bool xgene_8250 = false;
>> +
>> + if (tb->interface_type != ACPI_DBG2_16550_COMPATIBLE)
>> + return false;
>> +
>> + if (memcmp(tb->header.oem_id, "APMC0D", ACPI_OEM_ID_SIZE) &&
>> + memcmp(tb->header.oem_id, "HPE ", ACPI_OEM_ID_SIZE))
>> + return false;
>> +
>> + if (!memcmp(tb->header.oem_table_id, "XGENESPC",
>> + ACPI_OEM_TABLE_ID_SIZE) && tb->header.oem_revision == 0)
>> + xgene_8250 = true;
>> +
>> + if (!memcmp(tb->header.oem_table_id, "ProLiant",
>> + ACPI_OEM_TABLE_ID_SIZE) && tb->header.oem_revision == 1)
>> + xgene_8250 = true;
>> +
>> + return xgene_8250;
>> +}
>> +
>> +int acpi_arch_setup_console(struct acpi_table_spcr *table,
>> + char *opts, char *uart, char *iotype,
>> + int baud_rate, bool earlycon)
>> +{
>> + if (table->header.revision < 2) {
>> + pr_err("wrong table version\n");
>> + return -ENOENT;
>> + }
>> +
>> + switch (table->interface_type) {
>> + case ACPI_DBG2_ARM_SBSA_32BIT:
>> + snprintf(iotype, ACPI_SPCR_BUF_SIZE, "mmio32");
>> + /* fall through */
>> + case ACPI_DBG2_ARM_PL011:
>> + case ACPI_DBG2_ARM_SBSA_GENERIC:
>> + case ACPI_DBG2_BCM2835:
>> + snprintf(uart, ACPI_SPCR_BUF_SIZE, "pl011");
>> + break;
>> + default:
>> + if (strlen(uart) == 0)
>> + return -ENOENT;
>> + }
>> +
>> + /*
>> + * If the E44 erratum is required, then we need to tell the pl011
>> + * driver to implement the work-around.
>> + *
>> + * The global variable is used by the probe function when it
>> + * creates the UARTs, whether or not they're used as a console.
>> + *
>> + * If the user specifies "traditional" earlycon, the qdf2400_e44
>> + * console name matches the EARLYCON_DECLARE() statement, and
>> + * SPCR is not used. Parameter "earlycon" is false.
>> + *
>> + * If the user specifies "SPCR" earlycon, then we need to update
>> + * the console name so that it also says "qdf2400_e44". Parameter
>> + * "earlycon" is true.
>> + *
>> + * For consistency, if we change the console name, then we do it
>> + * for everyone, not just earlycon.
>> + */
>> + if (qdf2400_erratum_44_present(&table->header)) {
>> + qdf2400_e44_present = true;
>> + if (earlycon)
>> + snprintf(uart, ACPI_SPCR_BUF_SIZE, "qdf2400_e44");
>> + }
>> +
>> + if (xgene_8250_erratum_present(table)) {
>> + snprintf(iotype, ACPI_SPCR_BUF_SIZE, "mmio32");
>> +
>> + /* for xgene v1 and v2 we don't know the clock rate of the
>> + * UART so don't attempt to change to the baud rate state
>> + * in the table because driver cannot calculate the dividers
>> + */
>> + snprintf(opts, ACPI_SPCR_OPTS_SIZE, "%s,%s,0x%llx", uart,
>> + iotype, table->serial_port.address);
>> + } else {
>> + snprintf(opts, ACPI_SPCR_OPTS_SIZE, "%s,%s,0x%llx,%d", uart,
>> + iotype, table->serial_port.address, baud_rate);
>> + }
>> +
>> + return 0;
>> +}
>> +EXPORT_SYMBOL(acpi_arch_setup_console);
>
> EXPORT_SYMBOL() ? Why ?
>
> BTW, why do we need an arch hook ? I do not see anything that prevents
> you from using this code on x86 systems - is there anything arch
> specific in the SPCR specification itself ?
See above comment. But also keep in mind I have seen a lot of x86 systems that
do not define the ACPI table version correctly. The table version is 0 or 1,
and the current spec says it must be 2. It looks like ARM requires 2.
>
>> +
>> /*
>> * acpi_boot_table_init() called from setup_arch(), always.
>> * 1. find RSDP and get its address, and then find XSDT
>> @@ -230,10 +351,11 @@ void __init acpi_boot_table_init(void)
>>
>> done:
>> if (acpi_disabled) {
>> - if (earlycon_init_is_deferred)
>> + if (console_acpi_spcr_enable)
>> early_init_dt_scan_chosen_stdout();
>> } else {
>> - parse_spcr(earlycon_init_is_deferred);
>> + /* Always enable the ACPI SPCR console */
>> + acpi_parse_spcr(console_acpi_spcr_enable);
>> if (IS_ENABLED(CONFIG_ACPI_BGRT))
>> acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
>> }
>> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
>> index 46505396869e..9ae98eeada76 100644
>> --- a/drivers/acpi/Kconfig
>> +++ b/drivers/acpi/Kconfig
>> @@ -79,7 +79,12 @@ config ACPI_DEBUGGER_USER
>> endif
>>
>> config ACPI_SPCR_TABLE
>> - bool
>> + bool "ACPI Serial Port Console Redirection Support"
>> + default y if ARM64
>
> You need to remove the selection in arch/arm64 then. Also, moving away
> from a non-visible config may have consequences on ARM64, Graeme and
> Mark are more familiar with the SPCR dependencies so please chime in.
Ok, I'll double check this.
>
>> + help
>> + Enable support for Serial Port Console Redirection (SPCR) Table.
>> + This table provides information about the configuration of the
>> + earlycon console.
>>
>> config ACPI_LPIT
>> bool
>> diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c
>> index 324b35bfe781..f4bb8110e404 100644
>> --- a/drivers/acpi/spcr.c
>> +++ b/drivers/acpi/spcr.c
>> @@ -16,65 +16,18 @@
>> #include <linux/kernel.h>
>> #include <linux/serial_core.h>
>>
>> -/*
>> - * Erratum 44 for QDF2432v1 and QDF2400v1 SoCs describes the BUSY bit as
>> - * occasionally getting stuck as 1. To avoid the potential for a hang, check
>> - * TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART
>> - * implementations, so only do so if an affected platform is detected in
>> - * parse_spcr().
>> - */
>> -bool qdf2400_e44_present;
>> -EXPORT_SYMBOL(qdf2400_e44_present);
>> -
>> -/*
>> - * Some Qualcomm Datacenter Technologies SoCs have a defective UART BUSY bit.
>> - * Detect them by examining the OEM fields in the SPCR header, similiar to PCI
>> - * quirk detection in pci_mcfg.c.
>> - */
>> -static bool qdf2400_erratum_44_present(struct acpi_table_header *h)
>> -{
>> - if (memcmp(h->oem_id, "QCOM ", ACPI_OEM_ID_SIZE))
>> - return false;
>> -
>> - if (!memcmp(h->oem_table_id, "QDF2432 ", ACPI_OEM_TABLE_ID_SIZE))
>> - return true;
>> -
>> - if (!memcmp(h->oem_table_id, "QDF2400 ", ACPI_OEM_TABLE_ID_SIZE) &&
>> - h->oem_revision == 1)
>> - return true;
>> -
>> - return false;
>> -}
>> -
>> -/*
>> - * APM X-Gene v1 and v2 UART hardware is an 16550 like device but has its
>> - * register aligned to 32-bit. In addition, the BIOS also encoded the
>> - * access width to be 8 bits. This function detects this errata condition.
>> - */
>> -static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb)
>> +int __weak acpi_arch_setup_console(struct acpi_table_spcr *table,
>> + char *opts, char *uart, char *iotype,
>> + int baud_rate, bool earlycon)
>> {
>> - bool xgene_8250 = false;
>> -
>> - if (tb->interface_type != ACPI_DBG2_16550_COMPATIBLE)
>> - return false;
>> -
>> - if (memcmp(tb->header.oem_id, "APMC0D", ACPI_OEM_ID_SIZE) &&
>> - memcmp(tb->header.oem_id, "HPE ", ACPI_OEM_ID_SIZE))
>> - return false;
>> -
>> - if (!memcmp(tb->header.oem_table_id, "XGENESPC",
>> - ACPI_OEM_TABLE_ID_SIZE) && tb->header.oem_revision == 0)
>> - xgene_8250 = true;
>> -
>> - if (!memcmp(tb->header.oem_table_id, "ProLiant",
>> - ACPI_OEM_TABLE_ID_SIZE) && tb->header.oem_revision == 1)
>> - xgene_8250 = true;
>> -
>> - return xgene_8250;
>> + snprintf(opts, ACPI_SPCR_OPTS_SIZE, "%s,%s,0x%llx,%d", uart, iotype,
>> + table->serial_port.address, baud_rate);
>> + return 0;
>> }
>>
>> +bool console_acpi_spcr_enable __initdata;
>> /**
>> - * parse_spcr() - parse ACPI SPCR table and add preferred console
>> + * acpi_parse_spcr() - parse ACPI SPCR table and add preferred console
>> *
>> * @earlycon: set up earlycon for the console specified by the table
>> *
>> @@ -86,13 +39,13 @@ static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb)
>> * from arch initialization code as soon as the DT/ACPI decision is made.
>> *
>> */
>> -int __init parse_spcr(bool earlycon)
>> +int __init acpi_parse_spcr(bool earlycon)
>> {
>> - static char opts[64];
>> + static char opts[ACPI_SPCR_OPTS_SIZE];
>> + static char uart[ACPI_SPCR_BUF_SIZE];
>> + static char iotype[ACPI_SPCR_BUF_SIZE];
>> struct acpi_table_spcr *table;
>> acpi_status status;
>> - char *uart;
>> - char *iotype;
>> int baud_rate;
>> int err;
>>
>> @@ -105,48 +58,6 @@ int __init parse_spcr(bool earlycon)
>> if (ACPI_FAILURE(status))
>> return -ENOENT;
>>
>> - if (table->header.revision < 2) {
>> - err = -ENOENT;
>> - pr_err("wrong table version\n");
>> - goto done;
>> - }
>> -
>> - if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
>> - switch (ACPI_ACCESS_BIT_WIDTH((
>> - table->serial_port.access_width))) {
>> - default:
>> - pr_err("Unexpected SPCR Access Width. Defaulting to byte size\n");
>> - case 8:
>> - iotype = "mmio";
>> - break;
>> - case 16:
>> - iotype = "mmio16";
>> - break;
>> - case 32:
>> - iotype = "mmio32";
>> - break;
>> - }
>> - } else
>> - iotype = "io";
>> -
>> - switch (table->interface_type) {
>> - case ACPI_DBG2_ARM_SBSA_32BIT:
>> - iotype = "mmio32";
>> - /* fall through */
>> - case ACPI_DBG2_ARM_PL011:
>> - case ACPI_DBG2_ARM_SBSA_GENERIC:
>> - case ACPI_DBG2_BCM2835:
>> - uart = "pl011";
>> - break;
>> - case ACPI_DBG2_16550_COMPATIBLE:
>> - case ACPI_DBG2_16550_SUBSET:
>> - uart = "uart";
>> - break;
>> - default:
>> - err = -ENOENT;
>> - goto done;
>> - }
>> -
>> switch (table->baud_rate) {
>> case 3:
>> baud_rate = 9600;
>> @@ -165,43 +76,36 @@ int __init parse_spcr(bool earlycon)
>> goto done;
>> }
>>
>> - /*
>> - * If the E44 erratum is required, then we need to tell the pl011
>> - * driver to implement the work-around.
>> - *
>> - * The global variable is used by the probe function when it
>> - * creates the UARTs, whether or not they're used as a console.
>> - *
>> - * If the user specifies "traditional" earlycon, the qdf2400_e44
>> - * console name matches the EARLYCON_DECLARE() statement, and
>> - * SPCR is not used. Parameter "earlycon" is false.
>> - *
>> - * If the user specifies "SPCR" earlycon, then we need to update
>> - * the console name so that it also says "qdf2400_e44". Parameter
>> - * "earlycon" is true.
>> - *
>> - * For consistency, if we change the console name, then we do it
>> - * for everyone, not just earlycon.
>> - */
>> - if (qdf2400_erratum_44_present(&table->header)) {
>> - qdf2400_e44_present = true;
>> - if (earlycon)
>> - uart = "qdf2400_e44";
>> + switch (table->interface_type) {
>> + case ACPI_DBG2_16550_COMPATIBLE:
>> + case ACPI_DBG2_16550_SUBSET:
>> + snprintf(uart, ACPI_SPCR_BUF_SIZE, "uart");
>> + break;
>> + default:
>> + break;
>> }
>>
>> - if (xgene_8250_erratum_present(table)) {
>> - iotype = "mmio32";
>> + if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
>> + u8 width = ACPI_ACCESS_BIT_WIDTH((
>> + table->serial_port.access_width));
>> + switch (width) {
>> + default:
>> + pr_err("Unexpected SPCR Access Width. Defaulting to byte size\n");
>> + case 8:
>> + snprintf(iotype, ACPI_SPCR_BUF_SIZE, "mmio");
>> + break;
>> + case 16:
>> + case 32:
>> + snprintf(iotype, ACPI_SPCR_BUF_SIZE, "mmio%d", width);
>> + break;
>> + }
>> + } else
>> + snprintf(iotype, ACPI_SPCR_BUF_SIZE, "io");
>>
>> - /* for xgene v1 and v2 we don't know the clock rate of the
>> - * UART so don't attempt to change to the baud rate state
>> - * in the table because driver cannot calculate the dividers
>> - */
>> - snprintf(opts, sizeof(opts), "%s,%s,0x%llx", uart, iotype,
>> - table->serial_port.address);
>> - } else {
>> - snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype,
>> - table->serial_port.address, baud_rate);
>> - }
>> + err = acpi_arch_setup_console(table, opts, uart, iotype, baud_rate,
>> + earlycon);
>> + if (err)
>> + goto done;
>>
>> pr_info("console: %s\n", opts);
>>
>> @@ -209,7 +113,6 @@ int __init parse_spcr(bool earlycon)
>> setup_earlycon(opts);
>>
>> err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);
>> -
>
> Unintended change.
>
>> done:
>> acpi_put_table((struct acpi_table_header *)table);
>> return err;
>> diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
>> index 4c8b80f1c688..b22afb62c7a3 100644
>> --- a/drivers/tty/serial/earlycon.c
>> +++ b/drivers/tty/serial/earlycon.c
>> @@ -196,26 +196,15 @@ int __init setup_earlycon(char *buf)
>> return -ENOENT;
>> }
>>
>> -/*
>> - * When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in
>> - * command line does not start DT earlycon immediately, instead it defers
>> - * starting it until DT/ACPI decision is made. At that time if ACPI is enabled
>> - * call parse_spcr(), else call early_init_dt_scan_chosen_stdout()
>> - */
>> -bool earlycon_init_is_deferred __initdata;
>> -
>> /* early_param wrapper for setup_earlycon() */
>> static int __init param_setup_earlycon(char *buf)
>> {
>> int err;
>>
>> - /*
>> - * Just 'earlycon' is a valid param for devicetree earlycons;
>> - * don't generate a warning from parse_early_params() in that case
>> - */
>> + /* Just 'earlycon' is a valid param for devicetree and ACPI SPCR. */
>> if (!buf || !buf[0]) {
>> if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) {
>> - earlycon_init_is_deferred = true;
>> + console_acpi_spcr_enable = true;
>
> I am not familiar with this code, I would ask Graeme and Mark to check
> if this change is correct, the logic seems correct to me but I may be
> missing some corner cases.
>
>> return 0;
>> } else if (!buf) {
>> return early_init_dt_scan_chosen_stdout();
>> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
>> index dc1ebfeeb5ec..875d7327d91c 100644
>> --- a/include/linux/acpi.h
>> +++ b/include/linux/acpi.h
>> @@ -1241,10 +1241,17 @@ static inline bool acpi_has_watchdog(void) { return false; }
>> #endif
>>
>> #ifdef CONFIG_ACPI_SPCR_TABLE
>> +#define ACPI_SPCR_OPTS_SIZE 64
>> +#define ACPI_SPCR_BUF_SIZE 32
>> extern bool qdf2400_e44_present;
>> -int parse_spcr(bool earlycon);
>> +extern bool console_acpi_spcr_enable __initdata;
>> +extern int acpi_arch_setup_console(struct acpi_table_spcr *table,
>> + char *opts, char *uart, char *iotype,
>> + int baud_rate, bool earlycon);
>> +int acpi_parse_spcr(bool earlycon);
>> #else
>> -static inline int parse_spcr(bool earlycon) { return 0; }
>> +static const bool console_acpi_spcr_enable;
>
> The assignment in param_setup_earlycon won't compile.
Hmm ... I'm pretty sure it did. But I'll check that before resubmitting.
P.
>
> Lorenzo
>
^ permalink raw reply
* [PATCH] perf: arm_dsu_pmu: convert to bitmap_from_arr32
From: Arnd Bergmann @ 2018-01-08 12:48 UTC (permalink / raw)
To: linux-arm-kernel
The bitmap_from_u32array() interface got replaced in a global
change, but the arm_dsu_pmu driver adds another instance,
resulting in a build failure:
drivers/perf/arm_dsu_pmu.c: In function 'dsu_pmu_probe_pmu':
drivers/perf/arm_dsu_pmu.c:661:2: error: implicit declaration of function 'bitmap_from_u32array'; did you mean 'bitmap_from_arr32'? [-Werror=implicit-function-declaration]
This changes the new instance accordingly.
Fixes: mmotm ("bitmap: replace bitmap_{from,to}_u32array")
Fixes: 7520fa99246d ("perf: ARM DynamIQ Shared Unit PMU support")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
The global change is currently in linux-mm, so it should be
possible to just fold this patch into it, without causing
extra work.
---
drivers/perf/arm_dsu_pmu.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c
index 37c0526c93d5..e2700888a7d9 100644
--- a/drivers/perf/arm_dsu_pmu.c
+++ b/drivers/perf/arm_dsu_pmu.c
@@ -658,10 +658,8 @@ static void dsu_pmu_probe_pmu(struct dsu_pmu *dsu_pmu)
return;
cpmceid[0] = __dsu_pmu_read_pmceid(0);
cpmceid[1] = __dsu_pmu_read_pmceid(1);
- bitmap_from_u32array(dsu_pmu->cpmceid_bitmap,
- DSU_PMU_MAX_COMMON_EVENTS,
- cpmceid,
- ARRAY_SIZE(cpmceid));
+ bitmap_from_arr32(dsu_pmu->cpmceid_bitmap, cpmceid,
+ DSU_PMU_MAX_COMMON_EVENTS);
}
static void dsu_pmu_set_active_cpu(int cpu, struct dsu_pmu *dsu_pmu)
--
2.9.0
^ permalink raw reply related
* [PATCH] perf: arm_dsu_pmu: convert to bitmap_from_arr32
From: Yury Norov @ 2018-01-08 12:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180108124902.3854110-1-arnd@arndb.de>
On Mon, Jan 08, 2018 at 01:48:31PM +0100, Arnd Bergmann wrote:
> The bitmap_from_u32array() interface got replaced in a global
> change, but the arm_dsu_pmu driver adds another instance,
> resulting in a build failure:
>
> drivers/perf/arm_dsu_pmu.c: In function 'dsu_pmu_probe_pmu':
> drivers/perf/arm_dsu_pmu.c:661:2: error: implicit declaration of function 'bitmap_from_u32array'; did you mean 'bitmap_from_arr32'? [-Werror=implicit-function-declaration]
>
> This changes the new instance accordingly.
>
> Fixes: mmotm ("bitmap: replace bitmap_{from,to}_u32array")
> Fixes: 7520fa99246d ("perf: ARM DynamIQ Shared Unit PMU support")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> The global change is currently in linux-mm, so it should be
> possible to just fold this patch into it, without causing
> extra work.
> ---
> drivers/perf/arm_dsu_pmu.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c
> index 37c0526c93d5..e2700888a7d9 100644
> --- a/drivers/perf/arm_dsu_pmu.c
> +++ b/drivers/perf/arm_dsu_pmu.c
> @@ -658,10 +658,8 @@ static void dsu_pmu_probe_pmu(struct dsu_pmu *dsu_pmu)
> return;
> cpmceid[0] = __dsu_pmu_read_pmceid(0);
> cpmceid[1] = __dsu_pmu_read_pmceid(1);
> - bitmap_from_u32array(dsu_pmu->cpmceid_bitmap,
> - DSU_PMU_MAX_COMMON_EVENTS,
> - cpmceid,
> - ARRAY_SIZE(cpmceid));
> + bitmap_from_arr32(dsu_pmu->cpmceid_bitmap, cpmceid,
> + DSU_PMU_MAX_COMMON_EVENTS);
> }
>
> static void dsu_pmu_set_active_cpu(int cpu, struct dsu_pmu *dsu_pmu)
Thanks Arnd,
Acked-by: Yury Norov <ynorov@caviumnetworks.com>
^ permalink raw reply
* [PATCH] phy: work around 'phys' references to usb-phy devices
From: Arnd Bergmann @ 2018-01-08 13:01 UTC (permalink / raw)
To: linux-arm-kernel
Stefan Wahren reports a problem with a warning fix that was merged
for v4.15: we had lots of device nodes with a 'phys' property pointing
to a device node that is not compliant with the binding documented in
Documentation/devicetree/bindings/phy/phy-bindings.txt
This generally works because USB HCD drivers that support both the generic
phy subsystem and the older usb-phy subsystem ignore most errors from
phy_get() and related calls and then use the usb-phy driver instead.
However, usb_add_hcd() (along with the respective functions in dwc2 and
dwc3) propagate the EPROBE_DEFER return code so we can try again whenever
the driver gets loaded. In case the driver is written for the usb-phy
subsystem (like usb-generic-phy aka usb-nop-xceiv), we will never load
a generic-phy driver for it, and keep failing here.
There is only a small number of remaining usb-phy drivers that support
device tree, so this adds a workaround by providing a full list of the
potentially affected drivers, and always failing the probe with -ENODEV
here, which is the same behavior that we used to get with incorrect
device tree files. Since we generally want older kernels to also want
to work with the fixed devicetree files, it would be good to backport
the patch into stable kernels as well (3.13+ are possibly affected).
Reverting back to the DTS sources that work would in theory fix USB
support for now, but in the long run we'd run into the same problem
again when the drivers get ported from usb-phy to generic-phy.
Fixes: 014d6da6cb25 ("ARM: dts: bcm283x: Fix DTC warnings about missing phy-cells")
Link: https://marc.info/?l=linux-usb&m=151518314314753&w=2
Cc: stable at vger.kernel.org
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
This obviously needs to be tested, I wrote this up as a reply to
Stefan's bug report. I'm fairly sure that I covered all usb-phy
driver strings here. My goal is to have a fix merged into 4.15
rather than reverting all the DT fixes.
---
drivers/phy/phy-core.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index b4964b067aec..bb4dd2a2de2d 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -387,6 +387,24 @@ int phy_calibrate(struct phy *phy)
}
EXPORT_SYMBOL_GPL(phy_calibrate);
+static struct of_device_id __maybe_unused legacy_usbphy[] = {
+ { .compatible = "fsl,imx23-usbphy" },
+ { .compatible = "fsl,imx6q-usbphy" },
+ { .compatible = "fsl,imx6sl-usbphy" },
+ { .compatible = "fsl,imx6sx-usbphy" },
+ { .compatible = "fsl,imx6ul-usbphy" },
+ { .compatible = "fsl,vf610-usbphy" },
+ { .compatible = "nvidia,tegra20-usb-phy" },
+ { .compatible = "nvidia,tegra30-usb-phy" },
+ { .compatible = "nxp,isp1301" },
+ { .compatible = "ti,am335x-usb-ctrl-module" },
+ { .compatible = "ti,am335x-usb-phy" },
+ { .compatible = "ti,keystone-usbphy" },
+ { .compatible = "ti,twl6030-usb" },
+ { .compatible = "usb-nop-xceiv" },
+ {},
+};
+
/**
* _of_phy_get() - lookup and obtain a reference to a phy by phandle
* @np: device_node for which to get the phy
@@ -410,6 +428,15 @@ static struct phy *_of_phy_get(struct device_node *np, int index)
if (ret)
return ERR_PTR(-ENODEV);
+ /*
+ * Some USB host controllers use a "phys" property to refer to
+ * a device that does not have a generic phy driver but that
+ * has a driver for the older usb-phy framework.
+ * We must not return -EPROBE_DEFER for those, so bail out early.
+ */
+ if (of_match_node(legacy_usbphy, args.np))
+ return ERR_PTR(-ENODEV);
+
mutex_lock(&phy_provider_mutex);
phy_provider = of_phy_provider_lookup(args.np);
if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) {
--
2.9.0
^ permalink raw reply related
* [GIT PULL] ARM64: Xilinx ZynqMP SoC patches for v4.16
From: Michal Simek @ 2018-01-08 13:02 UTC (permalink / raw)
To: linux-arm-kernel
Hi guys,
please consider to pull these 3 patches to your tree. I have discussed
it with Arnd that this could be probably fine even it is a little bit late.
Thanks,
Michal
The following changes since commit 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323:
Linux 4.15-rc1 (2017-11-26 16:01:47 -0800)
are available in the git repository at:
https://github.com/Xilinx/linux-xlnx.git tags/zynqmp-soc-for-4.16
for you to fetch changes up to cee8113a295acfc4cd25728d7c3d44e6bc3bbff9:
soc: xilinx: xlnx_vcu: Add Xilinx ZYNQMP VCU logicoreIP init driver
(2018-01-08 13:42:47 +0100)
----------------------------------------------------------------
arm: Xilinx ZynqMP SoC patches for v4.16
- Create drivers/soc/xilinx folder structure
- Add ZynqMP vcu init driver
----------------------------------------------------------------
Dhaval Shah (2):
dt-bindings: soc: xilinx: Add DT bindings to xlnx_vcu driver
soc: xilinx: xlnx_vcu: Add Xilinx ZYNQMP VCU logicoreIP init driver
Michal Simek (1):
soc: xilinx: Create folder structure for soc specific drivers
Documentation/devicetree/bindings/soc/xilinx/xlnx,vcu.txt | 31 ++++++++
drivers/soc/Kconfig | 1 +
drivers/soc/Makefile | 1 +
drivers/soc/xilinx/Kconfig | 19 +++++
drivers/soc/xilinx/Makefile | 2 +
drivers/soc/xilinx/xlnx_vcu.c | 630
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 684 insertions(+)
create mode 100644
Documentation/devicetree/bindings/soc/xilinx/xlnx,vcu.txt
create mode 100644 drivers/soc/xilinx/Kconfig
create mode 100644 drivers/soc/xilinx/Makefile
create mode 100644 drivers/soc/xilinx/xlnx_vcu.c
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180108/739c9cba/attachment.sig>
^ permalink raw reply
* [PATCH] [v2] ARM: B15: fix unused label warnings
From: Arnd Bergmann @ 2018-01-08 13:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180102173308.GF28752@n2100.armlinux.org.uk>
On Tue, Jan 2, 2018 at 6:33 PM, Russell King - ARM Linux
<linux@armlinux.org.uk> wrote:
> On Mon, Dec 18, 2017 at 05:21:24PM -0800, Florian Fainelli wrote:
>> On 12/18/2017 08:52 AM, Arnd Bergmann wrote:
>> > The new conditionally compiled code leaves some labels and one
>> > variable unreferenced when CONFIG_HOTPLUG_CPU and CONFIG_PM_SLEEP
>> > are disabled:
>> >
>> > arch/arm/mm/cache-b15-rac.c: In function 'b15_rac_init':
>> > arch/arm/mm/cache-b15-rac.c:353:1: error: label 'out_unmap' defined but not used [-Werror=unused-label]
>> > out_unmap:
>> > ^~~~~~~~~
>> > arch/arm/mm/cache-b15-rac.c:351:1: error: label 'out_cpu_dead' defined but not used [-Werror=unused-label]
>> > out_cpu_dead:
>> > ^~~~~~~~~~~~
>> > At top level:
>> > arch/arm/mm/cache-b15-rac.c:53:12: error: 'rac_config0_reg' defined but not used [-Werror=unused-variable]
>> >
>> > This replaces the existing #ifdef conditionals with IS_ENABLED()
>> > checks that let the compiler figure out for itself which code to
>> > drop.
>> >
>> > Fixes: 55de88778f4b ("ARM: 8726/1: B15: Add CPU hotplug awareness")
>> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>>
>> Acked-by: Florian Fainelli <f.fainelli@gmail.com>
>>
>> Thanks Arnd!
>> --
>> Florian
>
> Arnd, can you throw this at the patch system please?
>
> Note that its now possible to add the "KernelVersion" tag in the email
> headers as well as anywhere in the body. The difference is that git
> tools can add headers via standard options.
Sent now as 8741/1, sorry for the delay.
Arnd
^ permalink raw reply
* [PATCH 01/20] dt-bindings: timer: Add Actions Semi S700
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1bbaef2e-4080-3f54-7db3-a8989acfd691@free.fr>
From: Andreas F?rber <afaerber@suse.de>
Define a compatible string for the Actions Semi S700 SoC timer.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Andreas F?rber <afaerber@suse.de>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
Documentation/devicetree/bindings/timer/actions,owl-timer.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/timer/actions,owl-timer.txt b/Documentation/devicetree/bindings/timer/actions,owl-timer.txt
index e3c28da..977054f 100644
--- a/Documentation/devicetree/bindings/timer/actions,owl-timer.txt
+++ b/Documentation/devicetree/bindings/timer/actions,owl-timer.txt
@@ -2,6 +2,7 @@ Actions Semi Owl Timer
Required properties:
- compatible : "actions,s500-timer" for S500
+ "actions,s700-timer" for S700
"actions,s900-timer" for S900
- reg : Offset and length of the register set for the device.
- interrupts : Should contain the interrupts.
--
2.7.4
^ permalink raw reply related
* [PATCH 02/20] clocksource/drivers/owl: Adopt TIMER_OF_DECLARE()
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
From: Andreas F?rber <afaerber@suse.de>
Commit 1727339590fdb5a1ded881b540cd32121278d414 ("clocksource/drivers:
Rename CLOCKSOURCE_OF_DECLARE to TIMER_OF_DECLARE") deprecated
CLOCKSOURCE_OF_DECLARE(), so adopt the new macro TIMER_OF_DECLARE().
Reported-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Andreas F?rber <afaerber@suse.de>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/owl-timer.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clocksource/owl-timer.c b/drivers/clocksource/owl-timer.c
index c686305..9fb4333 100644
--- a/drivers/clocksource/owl-timer.c
+++ b/drivers/clocksource/owl-timer.c
@@ -168,5 +168,5 @@ static int __init owl_timer_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init);
-CLOCKSOURCE_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init);
+TIMER_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init);
+TIMER_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init);
--
2.7.4
^ permalink raw reply related
* [PATCH 03/20] clocksource/drivers/owl: Add the S700
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
From: Andreas F?rber <afaerber@suse.de>
Actions S700 has two 2Hz timers like S500, and four TIMx timers like S900.
Signed-off-by: Andreas F?rber <afaerber@suse.de>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/owl-timer.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/clocksource/owl-timer.c b/drivers/clocksource/owl-timer.c
index 9fb4333..ea00a5e 100644
--- a/drivers/clocksource/owl-timer.c
+++ b/drivers/clocksource/owl-timer.c
@@ -169,4 +169,5 @@ static int __init owl_timer_init(struct device_node *node)
return 0;
}
TIMER_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init);
+TIMER_OF_DECLARE(owl_s700, "actions,s700-timer", owl_timer_init);
TIMER_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init);
--
2.7.4
^ permalink raw reply related
* [PATCH 04/20] clocksource/drivers/tcb_clksrc: Fix clock speed message
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
From: Romain Izard <romain.izard.pro@gmail.com>
The clock speed displayed at boot in an information message was 500 kHz
too high compared to its real value. As the value is not used anywhere,
there is no functional impact.
Fix the rounding formula to display the correct value.
Signed-off-by: Romain Izard <romain.izard.pro@gmail.com>
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/tcb_clksrc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index 9de47d4..43f4d5c 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -384,7 +384,7 @@ static int __init tcb_clksrc_init(void)
printk(bootinfo, clksrc.name, CONFIG_ATMEL_TCB_CLKSRC_BLOCK,
divided_rate / 1000000,
- ((divided_rate + 500000) % 1000000) / 1000);
+ ((divided_rate % 1000000) + 500) / 1000);
if (tc->tcb_config && tc->tcb_config->counter_width == 32) {
/* use apropriate function to read 32 bit counter */
--
2.7.4
^ permalink raw reply related
* [PATCH 11/20] clocksource/drivers/stm32: Fix kernel panic with multiple timers
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
The current code hides a couple of bugs.
- The global variable 'clock_event_ddata' is overwritten each time the
init function is invoked.
This is fixed with a kmemdup instead of assigning the global variable. That
prevents a memory corruption when several timers are defined in the DT.
- The clockevent's event_handler is NULL if the time framework does
not select the clockevent when registering it, this is fine but the init
code generates in any case an interrupt leading to dereference this
NULL pointer.
The stm32 timer works with shadow registers, a mechanism to cache the
registers. When a change is done in one buffered register, we need to
artificially generate an event to force the timer to copy the content
of the register to the shadowed register.
The auto-reload register (ARR) is one of the shadowed register as well as
the prescaler register (PSC), so in order to force the copy, we issue an
event which in turn leads to an interrupt and the NULL dereference.
This is fixed by inverting two lines where we clear the status register
before enabling the update event interrupt.
As this kernel crash is resulting from the combination of these two bugs,
the fixes are grouped into a single patch.
Cc: stable at vger.kernel.org
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
drivers/clocksource/timer-stm32.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 8f24237..4bfeb99 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -106,6 +106,10 @@ static int __init stm32_clockevent_init(struct device_node *np)
unsigned long rate, max_delta;
int irq, ret, bits, prescaler = 1;
+ data = kmemdup(&clock_event_ddata, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
clk = of_clk_get(np, 0);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
@@ -156,8 +160,8 @@ static int __init stm32_clockevent_init(struct device_node *np)
writel_relaxed(prescaler - 1, data->base + TIM_PSC);
writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR);
- writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
writel_relaxed(0, data->base + TIM_SR);
+ writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ);
@@ -184,6 +188,7 @@ static int __init stm32_clockevent_init(struct device_node *np)
err_clk_enable:
clk_put(clk);
err_clk_get:
+ kfree(data);
return ret;
}
--
2.7.4
^ permalink raw reply related
* [PATCH 12/20] clocksource/drivers/stm32: Convert the driver to timer-of
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
From: Benjamin Gaignard <benjamin.gaignard@st.com>
Convert the driver to use the timer_of helpers. This allows to remove custom
proprietary structure, factors out and simplifies the code.
[Daniel Lezcano] : Respin against the critical fix patch and massaged the
changelog.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/timer-stm32.c | 187 +++++++++++++++-----------------------
2 files changed, 74 insertions(+), 114 deletions(-)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 9a6b087..786db7a 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -269,6 +269,7 @@ config CLKSRC_STM32
bool "Clocksource for STM32 SoCs" if !ARCH_STM32
depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
select CLKSRC_MMIO
+ select TIMER_OF
config CLKSRC_MPS2
bool "Clocksource for MPS2 SoCs" if COMPILE_TEST
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 4bfeb99..3e4ab07 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -16,6 +16,9 @@
#include <linux/of_irq.h>
#include <linux/clk.h>
#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include "timer-of.h"
#define TIM_CR1 0x00
#define TIM_DIER 0x0c
@@ -34,162 +37,118 @@
#define TIM_EGR_UG BIT(0)
-struct stm32_clock_event_ddata {
- struct clock_event_device evtdev;
- unsigned periodic_top;
- void __iomem *base;
-};
-
-static int stm32_clock_event_shutdown(struct clock_event_device *evtdev)
+static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
{
- struct stm32_clock_event_ddata *data =
- container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
- void *base = data->base;
+ struct timer_of *to = to_timer_of(clkevt);
+
+ writel_relaxed(0, timer_of_base(to) + TIM_CR1);
- writel_relaxed(0, base + TIM_CR1);
return 0;
}
-static int stm32_clock_event_set_periodic(struct clock_event_device *evtdev)
+static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
{
- struct stm32_clock_event_ddata *data =
- container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
- void *base = data->base;
+ struct timer_of *to = to_timer_of(clkevt);
+
+ writel_relaxed(timer_of_period(to), timer_of_base(to) + TIM_ARR);
+ writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
- writel_relaxed(data->periodic_top, base + TIM_ARR);
- writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, base + TIM_CR1);
return 0;
}
static int stm32_clock_event_set_next_event(unsigned long evt,
- struct clock_event_device *evtdev)
+ struct clock_event_device *clkevt)
{
- struct stm32_clock_event_ddata *data =
- container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
+ struct timer_of *to = to_timer_of(clkevt);
- writel_relaxed(evt, data->base + TIM_ARR);
+ writel_relaxed(evt, timer_of_base(to) + TIM_ARR);
writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN,
- data->base + TIM_CR1);
+ timer_of_base(to) + TIM_CR1);
return 0;
}
static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
{
- struct stm32_clock_event_ddata *data = dev_id;
+ struct clock_event_device *clkevt = (struct clock_event_device *)dev_id;
+ struct timer_of *to = to_timer_of(clkevt);
- writel_relaxed(0, data->base + TIM_SR);
+ writel_relaxed(0, timer_of_base(to) + TIM_SR);
- data->evtdev.event_handler(&data->evtdev);
+ clkevt->event_handler(clkevt);
return IRQ_HANDLED;
}
-static struct stm32_clock_event_ddata clock_event_ddata = {
- .evtdev = {
- .name = "stm32 clockevent",
- .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
- .set_state_shutdown = stm32_clock_event_shutdown,
- .set_state_periodic = stm32_clock_event_set_periodic,
- .set_state_oneshot = stm32_clock_event_shutdown,
- .tick_resume = stm32_clock_event_shutdown,
- .set_next_event = stm32_clock_event_set_next_event,
- .rating = 200,
- },
-};
-
-static int __init stm32_clockevent_init(struct device_node *np)
+static void __init stm32_clockevent_init(struct timer_of *to)
{
- struct stm32_clock_event_ddata *data = &clock_event_ddata;
- struct clk *clk;
- struct reset_control *rstc;
- unsigned long rate, max_delta;
- int irq, ret, bits, prescaler = 1;
-
- data = kmemdup(&clock_event_ddata, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- clk = of_clk_get(np, 0);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- pr_err("failed to get clock for clockevent (%d)\n", ret);
- goto err_clk_get;
- }
-
- ret = clk_prepare_enable(clk);
- if (ret) {
- pr_err("failed to enable timer clock for clockevent (%d)\n",
- ret);
- goto err_clk_enable;
- }
-
- rate = clk_get_rate(clk);
-
- rstc = of_reset_control_get(np, NULL);
- if (!IS_ERR(rstc)) {
- reset_control_assert(rstc);
- reset_control_deassert(rstc);
- }
-
- data->base = of_iomap(np, 0);
- if (!data->base) {
- ret = -ENXIO;
- pr_err("failed to map registers for clockevent\n");
- goto err_iomap;
- }
+ unsigned long max_delta;
+ int prescaler;
- irq = irq_of_parse_and_map(np, 0);
- if (!irq) {
- ret = -EINVAL;
- pr_err("%pOF: failed to get irq.\n", np);
- goto err_get_irq;
- }
+ to->clkevt.name = "stm32_clockevent";
+ to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
+ to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
+ to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
+ to->clkevt.set_state_oneshot = stm32_clock_event_shutdown;
+ to->clkevt.tick_resume = stm32_clock_event_shutdown;
+ to->clkevt.set_next_event = stm32_clock_event_set_next_event;
/* Detect whether the timer is 16 or 32 bits */
- writel_relaxed(~0U, data->base + TIM_ARR);
- max_delta = readl_relaxed(data->base + TIM_ARR);
+ writel_relaxed(~0U, timer_of_base(to) + TIM_ARR);
+ max_delta = readl_relaxed(timer_of_base(to) + TIM_ARR);
if (max_delta == ~0U) {
prescaler = 1;
- bits = 32;
+ to->clkevt.rating = 250;
} else {
prescaler = 1024;
- bits = 16;
+ to->clkevt.rating = 100;
}
- writel_relaxed(0, data->base + TIM_ARR);
+ writel_relaxed(0, timer_of_base(to) + TIM_ARR);
- writel_relaxed(prescaler - 1, data->base + TIM_PSC);
- writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR);
- writel_relaxed(0, data->base + TIM_SR);
- writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
+ writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
+ writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
+ writel_relaxed(0, timer_of_base(to) + TIM_SR);
+ writel_relaxed(TIM_DIER_UIE, timer_of_base(to) + TIM_DIER);
- data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ);
+ /* Adjust rate and period given the prescaler value */
+ to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
+ to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
- clockevents_config_and_register(&data->evtdev,
- DIV_ROUND_CLOSEST(rate, prescaler),
- 0x1, max_delta);
-
- ret = request_irq(irq, stm32_clock_event_handler, IRQF_TIMER,
- "stm32 clockevent", data);
- if (ret) {
- pr_err("%pOF: failed to request irq.\n", np);
- goto err_get_irq;
- }
+ clockevents_config_and_register(&to->clkevt,
+ timer_of_rate(to), 0x1, max_delta);
pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
- np, bits);
+ to->np, max_delta == UINT_MAX ? 32 : 16);
+}
- return ret;
+static int __init stm32_timer_init(struct device_node *node)
+{
+ struct reset_control *rstc;
+ struct timer_of *to;
+ int ret;
+
+ to = kzalloc(sizeof(*to), GFP_KERNEL);
+ if (!to)
+ return -ENOMEM;
+
+ to->flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE;
+ to->of_irq.handler = stm32_clock_event_handler;
+
+ ret = timer_of_init(node, to);
+ if (ret)
+ goto err;
-err_get_irq:
- iounmap(data->base);
-err_iomap:
- clk_disable_unprepare(clk);
-err_clk_enable:
- clk_put(clk);
-err_clk_get:
- kfree(data);
+ rstc = of_reset_control_get(node, NULL);
+ if (!IS_ERR(rstc)) {
+ reset_control_assert(rstc);
+ reset_control_deassert(rstc);
+ }
+
+ stm32_clockevent_init(to);
+ return 0;
+err:
+ kfree(to);
return ret;
}
-TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init);
+TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_timer_init);
--
2.7.4
^ permalink raw reply related
* [PATCH 13/20] clocksource/drivers/stm32: Use the node name as timer name
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
As there are different timers on the stm32, use the node name for the timer
name in order to give the indication of which timer the kernel is using.
The /proc/timer_list gives all the information with the right name, otherwise
we end up digging in the kernel log and /proc/interrupt to do the connection
between the used timer.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
drivers/clocksource/timer-stm32.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 3e4ab07..14b7a2b 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -85,7 +85,7 @@ static void __init stm32_clockevent_init(struct timer_of *to)
unsigned long max_delta;
int prescaler;
- to->clkevt.name = "stm32_clockevent";
+ to->clkevt.name = to->np->full_name;
to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
--
2.7.4
^ permalink raw reply related
* [PATCH 14/20] clocksource/drivers/stm32: Encapsulate the timer width sorting out function
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
In order to clarify and encapsulate the code for the next changes move the
timer width check into a function and add some documentation.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
drivers/clocksource/timer-stm32.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 14b7a2b..862134e 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -80,9 +80,27 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+/**
+ * stm32_timer_width - Sort out the timer width (32/16)
+ * @to: a pointer to a timer-of structure
+ *
+ * Write the 32bits max value and read/return the result. If the timer
+ * is a 32bits width, the result will be UINT_MAX, otherwise it will
+ * be truncated by the 16bits register to USHRT_MAX.
+ *
+ * Returns UINT_MAX if the timer is 32bits width, USHRT_MAX if it is a
+ * 16bits width.
+ */
+static u32 __init stm32_timer_width(struct timer_of *to)
+{
+ writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
+
+ return readl_relaxed(timer_of_base(to) + TIM_ARR);
+}
+
static void __init stm32_clockevent_init(struct timer_of *to)
{
- unsigned long max_delta;
+ u32 width = 0;
int prescaler;
to->clkevt.name = to->np->full_name;
@@ -93,10 +111,8 @@ static void __init stm32_clockevent_init(struct timer_of *to)
to->clkevt.tick_resume = stm32_clock_event_shutdown;
to->clkevt.set_next_event = stm32_clock_event_set_next_event;
- /* Detect whether the timer is 16 or 32 bits */
- writel_relaxed(~0U, timer_of_base(to) + TIM_ARR);
- max_delta = readl_relaxed(timer_of_base(to) + TIM_ARR);
- if (max_delta == ~0U) {
+ width = stm32_timer_width(to);
+ if (width == UINT_MAX) {
prescaler = 1;
to->clkevt.rating = 250;
} else {
@@ -115,10 +131,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
clockevents_config_and_register(&to->clkevt,
- timer_of_rate(to), 0x1, max_delta);
+ timer_of_rate(to), 0x1, width);
pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
- to->np, max_delta == UINT_MAX ? 32 : 16);
+ to->np, width == UINT_MAX ? 32 : 16);
}
static int __init stm32_timer_init(struct device_node *node)
--
2.7.4
^ permalink raw reply related
* [PATCH 15/20] clocksource/drivers/stm32: Compute a prescaler value with a targeted rate
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
From: Benjamin Gaignard <benjamin.gaignard@st.com>
The prescaler value is arbitrarily set to 1024 without any regard to the
timer frequency. For 32bits timers, there is no need to set a prescaler
value as they wrap in an acceptable interval and give the opportunity to
have precise timers on this platform. However, for 16bits timers a prescaler
value is needed if we don't want to wrap too often per second which is
unefficient and adds more and more error margin. With a targeted clock
of 10MHz, the 16bits are precise enough whatever the timer frequency is
as we will compute the prescaler.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
drivers/clocksource/timer-stm32.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 862134e..ac55896 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -37,6 +37,9 @@
#define TIM_EGR_UG BIT(0)
+#define TIM_PSC_MAX USHRT_MAX
+#define TIM_PSC_CLKRATE 10000
+
static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
@@ -116,7 +119,14 @@ static void __init stm32_clockevent_init(struct timer_of *to)
prescaler = 1;
to->clkevt.rating = 250;
} else {
- prescaler = 1024;
+ prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to),
+ TIM_PSC_CLKRATE);
+ /*
+ * The prescaler register is an u16, the variable
+ * can't be greater than TIM_PSC_MAX, let's cap it in
+ * this case.
+ */
+ prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
to->clkevt.rating = 100;
}
writel_relaxed(0, timer_of_base(to) + TIM_ARR);
--
2.7.4
^ permalink raw reply related
* [PATCH 16/20] clocksource/drivers/stm32: Add the oneshot mode
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
From: Benjamin Gaignard <benjamin.gaignard@st.com>
The stm32 timer block is able to have a counter and a comparator.
Instead of using the auto-reload register for periodic event, we switch
to the oneshot mode by using the comparator register.
The timer is able to generate an interrupt when the counter overflows but
we don't want that as this counter will be use as a clocksource in the next
patches. So it is disabled by the UDIS bit of the control register.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
drivers/clocksource/timer-stm32.c | 56 ++++++++++++++++++++++++++++++---------
1 file changed, 44 insertions(+), 12 deletions(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index ac55896..baca42c 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -24,14 +24,18 @@
#define TIM_DIER 0x0c
#define TIM_SR 0x10
#define TIM_EGR 0x14
+#define TIM_CNT 0x24
#define TIM_PSC 0x28
#define TIM_ARR 0x2c
+#define TIM_CCR1 0x34
#define TIM_CR1_CEN BIT(0)
+#define TIM_CR1_UDIS BIT(1)
#define TIM_CR1_OPM BIT(3)
#define TIM_CR1_ARPE BIT(7)
#define TIM_DIER_UIE BIT(0)
+#define TIM_DIER_CC1IE BIT(1)
#define TIM_SR_UIF BIT(0)
@@ -40,33 +44,57 @@
#define TIM_PSC_MAX USHRT_MAX
#define TIM_PSC_CLKRATE 10000
+static void stm32_clock_event_disable(struct timer_of *to)
+{
+ writel_relaxed(0, timer_of_base(to) + TIM_DIER);
+}
+
+static void stm32_clock_event_enable(struct timer_of *to)
+{
+ writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
+}
+
static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
- writel_relaxed(0, timer_of_base(to) + TIM_CR1);
+ stm32_clock_event_disable(to);
return 0;
}
-static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
+static int stm32_clock_event_set_next_event(unsigned long evt,
+ struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
+ unsigned long now, next;
+
+ next = readl_relaxed(timer_of_base(to) + TIM_CNT) + evt;
+ writel_relaxed(next, timer_of_base(to) + TIM_CCR1);
+ now = readl_relaxed(timer_of_base(to) + TIM_CNT);
+
+ if ((next - now) > evt)
+ return -ETIME;
- writel_relaxed(timer_of_period(to), timer_of_base(to) + TIM_ARR);
- writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
+ writel_relaxed(TIM_DIER_CC1IE, timer_of_base(to) + TIM_DIER);
return 0;
}
-static int stm32_clock_event_set_next_event(unsigned long evt,
- struct clock_event_device *clkevt)
+static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
+{
+ struct timer_of *to = to_timer_of(clkevt);
+
+ stm32_clock_event_enable(to);
+
+ return stm32_clock_event_set_next_event(timer_of_period(to), clkevt);
+}
+
+static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
- writel_relaxed(evt, timer_of_base(to) + TIM_ARR);
- writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN,
- timer_of_base(to) + TIM_CR1);
+ stm32_clock_event_enable(to);
return 0;
}
@@ -78,6 +106,11 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
writel_relaxed(0, timer_of_base(to) + TIM_SR);
+ if (clockevent_state_periodic(clkevt))
+ stm32_clock_event_set_periodic(clkevt);
+ else
+ stm32_clock_event_shutdown(clkevt);
+
clkevt->event_handler(clkevt);
return IRQ_HANDLED;
@@ -108,9 +141,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
to->clkevt.name = to->np->full_name;
to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
+ to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
- to->clkevt.set_state_oneshot = stm32_clock_event_shutdown;
+ to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
to->clkevt.tick_resume = stm32_clock_event_shutdown;
to->clkevt.set_next_event = stm32_clock_event_set_next_event;
@@ -129,12 +163,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
to->clkevt.rating = 100;
}
- writel_relaxed(0, timer_of_base(to) + TIM_ARR);
writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
writel_relaxed(0, timer_of_base(to) + TIM_SR);
- writel_relaxed(TIM_DIER_UIE, timer_of_base(to) + TIM_DIER);
/* Adjust rate and period given the prescaler value */
to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
--
2.7.4
^ permalink raw reply related
* [PATCH 17/20] clocksource/drivers/stm32: Encapsulate more the clockevent code
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
In order to prepare the clocksource code, let's encapsulate the clockevent
code, split the prescaler and timer width code into separate functions.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
drivers/clocksource/timer-stm32.c | 107 +++++++++++++++++++++++++++++---------
1 file changed, 82 insertions(+), 25 deletions(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index baca42c..1891924 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -44,6 +44,42 @@
#define TIM_PSC_MAX USHRT_MAX
#define TIM_PSC_CLKRATE 10000
+struct stm32_timer_private {
+ int bits;
+};
+
+/**
+ * stm32_timer_of_bits_set - set accessor helper
+ * @to: a timer_of structure pointer
+ * @bits: the number of bits (16 or 32)
+ *
+ * Accessor helper to set the number of bits in the timer-of private
+ * structure.
+ *
+ */
+static void stm32_timer_of_bits_set(struct timer_of *to, int bits)
+{
+ struct stm32_timer_private *pd = to->private_data;
+
+ pd->bits = bits;
+}
+
+/**
+ * stm32_timer_of_bits_get - get accessor helper
+ * @to: a timer_of structure pointer
+ *
+ * Accessor helper to get the number of bits in the timer-of private
+ * structure.
+ *
+ * Returns an integer corresponding to the number of bits.
+ */
+static int stm32_timer_of_bits_get(struct timer_of *to)
+{
+ struct stm32_timer_private *pd = to->private_data;
+
+ return pd->bits;
+}
+
static void stm32_clock_event_disable(struct timer_of *to)
{
writel_relaxed(0, timer_of_base(to) + TIM_DIER);
@@ -124,35 +160,31 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
* is a 32bits width, the result will be UINT_MAX, otherwise it will
* be truncated by the 16bits register to USHRT_MAX.
*
- * Returns UINT_MAX if the timer is 32bits width, USHRT_MAX if it is a
- * 16bits width.
*/
-static u32 __init stm32_timer_width(struct timer_of *to)
+static void __init stm32_timer_set_width(struct timer_of *to)
{
+ u32 width;
+
writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
- return readl_relaxed(timer_of_base(to) + TIM_ARR);
+ width = readl_relaxed(timer_of_base(to) + TIM_ARR);
+
+ stm32_timer_of_bits_set(to, width == UINT_MAX ? 32 : 16);
}
-static void __init stm32_clockevent_init(struct timer_of *to)
+/**
+ * stm32_timer_set_prescaler - Compute and set the prescaler register
+ * @to: a pointer to a timer-of structure
+ *
+ * Depending on the timer width, compute the prescaler to always
+ * target a 10MHz timer rate for the 16bits. 32bits timers are
+ * considered precise and long enough to not use the prescaler.
+ */
+static void __init stm32_timer_set_prescaler(struct timer_of *to)
{
- u32 width = 0;
- int prescaler;
+ int prescaler = 1;
- to->clkevt.name = to->np->full_name;
- to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
- to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
- to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
- to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
- to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
- to->clkevt.tick_resume = stm32_clock_event_shutdown;
- to->clkevt.set_next_event = stm32_clock_event_set_next_event;
-
- width = stm32_timer_width(to);
- if (width == UINT_MAX) {
- prescaler = 1;
- to->clkevt.rating = 250;
- } else {
+ if (stm32_timer_of_bits_get(to) != 32) {
prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to),
TIM_PSC_CLKRATE);
/*
@@ -161,7 +193,6 @@ static void __init stm32_clockevent_init(struct timer_of *to)
* this case.
*/
prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
- to->clkevt.rating = 100;
}
writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
@@ -171,12 +202,26 @@ static void __init stm32_clockevent_init(struct timer_of *to)
/* Adjust rate and period given the prescaler value */
to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
+}
+
+static void __init stm32_clockevent_init(struct timer_of *to)
+{
+ u32 bits = stm32_timer_of_bits_get(to);
- clockevents_config_and_register(&to->clkevt,
- timer_of_rate(to), 0x1, width);
+ to->clkevt.name = to->np->full_name;
+ to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
+ to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
+ to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
+ to->clkevt.tick_resume = stm32_clock_event_shutdown;
+ to->clkevt.set_next_event = stm32_clock_event_set_next_event;
+ to->clkevt.rating = bits == 32 ? 250 : 100;
+
+ clockevents_config_and_register(&to->clkevt, timer_of_rate(to), 0x1,
+ (1 << bits) - 1);
pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
- to->np, width == UINT_MAX ? 32 : 16);
+ to->np, bits);
}
static int __init stm32_timer_init(struct device_node *node)
@@ -196,14 +241,26 @@ static int __init stm32_timer_init(struct device_node *node)
if (ret)
goto err;
+ to->private_data = kzalloc(sizeof(struct stm32_timer_private),
+ GFP_KERNEL);
+ if (!to->private_data)
+ goto deinit;
+
rstc = of_reset_control_get(node, NULL);
if (!IS_ERR(rstc)) {
reset_control_assert(rstc);
reset_control_deassert(rstc);
}
+ stm32_timer_set_width(to);
+
+ stm32_timer_set_prescaler(to);
+
stm32_clockevent_init(to);
return 0;
+
+deinit:
+ timer_of_cleanup(to);
err:
kfree(to);
return ret;
--
2.7.4
^ permalink raw reply related
* [PATCH 18/20] clocksource/drivers/stm32: Add the clocksource
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
From: Benjamin Gaignard <benjamin.gaignard@st.com>
The scene is set for the clocksource, let's add it for this driver.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
drivers/clocksource/timer-stm32.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 1891924..4634f4d 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -16,6 +16,7 @@
#include <linux/of_irq.h>
#include <linux/clk.h>
#include <linux/reset.h>
+#include <linux/sched_clock.h>
#include <linux/slab.h>
#include "timer-of.h"
@@ -80,6 +81,13 @@ static int stm32_timer_of_bits_get(struct timer_of *to)
return pd->bits;
}
+static void __iomem *stm32_timer_cnt __read_mostly;
+
+static u64 notrace stm32_read_sched_clock(void)
+{
+ return readl_relaxed(stm32_timer_cnt);
+}
+
static void stm32_clock_event_disable(struct timer_of *to)
{
writel_relaxed(0, timer_of_base(to) + TIM_DIER);
@@ -204,6 +212,31 @@ static void __init stm32_timer_set_prescaler(struct timer_of *to)
to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
}
+static int __init stm32_clocksource_init(struct timer_of *to)
+{
+ u32 bits = stm32_timer_of_bits_get(to);
+ const char *name = to->np->full_name;
+
+ /*
+ * This driver allows to register several timers and relies on
+ * the generic time framework to select the right one.
+ * However, nothing allows to do the same for the
+ * sched_clock. We are not interested in a sched_clock for the
+ * 16bits timers but only for the 32bits, so if no 32bits
+ * timer registered yet, we select this 32bits timer as a
+ * sched_clock.
+ */
+ if (bits == 32 && !stm32_timer_cnt) {
+ stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
+ sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
+ pr_info("%s: STM32 sched_clock registered\n", name);
+ }
+
+ return clocksource_mmio_init(timer_of_base(to) + TIM_CNT, name,
+ timer_of_rate(to), bits == 32 ? 250 : 100,
+ bits, clocksource_mmio_readl_up);
+}
+
static void __init stm32_clockevent_init(struct timer_of *to)
{
u32 bits = stm32_timer_of_bits_get(to);
@@ -256,6 +289,10 @@ static int __init stm32_timer_init(struct device_node *node)
stm32_timer_set_prescaler(to);
+ ret = stm32_clocksource_init(to);
+ if (ret)
+ goto deinit;
+
stm32_clockevent_init(to);
return 0;
--
2.7.4
^ permalink raw reply related
* [PATCH 19/20] clocksource/drivers/stm32: Add the timer delay
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
Add the timer delay, that saves us ~90ms of boot time.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
drivers/clocksource/timer-stm32.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 4634f4d..dcf8445 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
+#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/of.h>
@@ -88,6 +89,13 @@ static u64 notrace stm32_read_sched_clock(void)
return readl_relaxed(stm32_timer_cnt);
}
+static struct delay_timer stm32_timer_delay;
+
+static unsigned long stm32_read_delay(void)
+{
+ return readl_relaxed(stm32_timer_cnt);
+}
+
static void stm32_clock_event_disable(struct timer_of *to)
{
writel_relaxed(0, timer_of_base(to) + TIM_DIER);
@@ -230,6 +238,11 @@ static int __init stm32_clocksource_init(struct timer_of *to)
stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
pr_info("%s: STM32 sched_clock registered\n", name);
+
+ stm32_timer_delay.read_current_timer = stm32_read_delay;
+ stm32_timer_delay.freq = timer_of_rate(to);
+ register_current_timer_delay(&stm32_timer_delay);
+ pr_info("%s: STM32 delay timer registered\n", name);
}
return clocksource_mmio_init(timer_of_base(to) + TIM_CNT, name,
--
2.7.4
^ permalink raw reply related
* [PATCH 20/20] clocksource/drivers/stm32: Start the timer's counter sooner
From: Daniel Lezcano @ 2018-01-08 13:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515418139-23276-1-git-send-email-daniel.lezcano@linaro.org>
As we have a lot of timers on this platform, we can have potentially all the
timers enabled in the DT, so we don't want to start the timer for every probe
otherwise they will be running for nothing as only one will be used.
Start the timer only when setting the mode or when the clocksource is
enabled.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@st.com>
---
drivers/clocksource/timer-stm32.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index dcf8445..4ce2345 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -101,7 +101,15 @@ static void stm32_clock_event_disable(struct timer_of *to)
writel_relaxed(0, timer_of_base(to) + TIM_DIER);
}
-static void stm32_clock_event_enable(struct timer_of *to)
+/**
+ * stm32_timer_start - Start the counter without event
+ * @to: a timer_of structure pointer
+ *
+ * Start the timer in order to have the counter reset and start
+ * incrementing but disable interrupt event when there is a counter
+ * overflow. By default, the counter direction is used as upcounter.
+ */
+static void stm32_timer_start(struct timer_of *to)
{
writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
}
@@ -137,7 +145,7 @@ static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
- stm32_clock_event_enable(to);
+ stm32_timer_start(to);
return stm32_clock_event_set_next_event(timer_of_period(to), clkevt);
}
@@ -146,7 +154,7 @@ static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
- stm32_clock_event_enable(to);
+ stm32_timer_start(to);
return 0;
}
@@ -235,6 +243,13 @@ static int __init stm32_clocksource_init(struct timer_of *to)
* sched_clock.
*/
if (bits == 32 && !stm32_timer_cnt) {
+
+ /*
+ * Start immediately the counter as we will be using
+ * it right after.
+ */
+ stm32_timer_start(to);
+
stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
pr_info("%s: STM32 sched_clock registered\n", name);
--
2.7.4
^ permalink raw reply related
* [PATCH v5 01/44] dt-bindings: clock: Add new bindings for TI Davinci PLL clocks
From: Sekhar Nori @ 2018-01-08 14:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515377863-20358-2-git-send-email-david@lechnology.com>
On Monday 08 January 2018 07:47 AM, David Lechner wrote:
> This adds a new binding for the PLL IP blocks in the mach-davinci family
> of processors. Currently, only the SYSCLKn and AUXCLK outputs are needed,
> but in the future additional child nodes could be added for OBSCLK and
> BPDIV.
>
> Note: Although these PLL controllers are very similar to the TI Keystone
> SoCs, we are not re-using those bindings. The Keystone bindings use a
> legacy one-node-per-clock binding. Furthermore, the mach-davinici SoCs
Not sure what is meant by "legacy one-node-per-clock binding"
> have a slightly different PLL register layout and a number of quirks that
> can't be handled by the existing bindings, so the keystone bindings could
> not be used as-is anyway.
Right, I think different register layout between the processors is the
main reason for a new driver. This should be sufficient reason IMO.
>
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
> .../devicetree/bindings/clock/ti/davinci/pll.txt | 47 ++++++++++++++++++++++
> 1 file changed, 47 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
>
> diff --git a/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
> new file mode 100644
> index 0000000..99bf5da
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/ti/davinci/pll.txt
> @@ -0,0 +1,47 @@
> +Binding for TI DaVinci PLL Controllers
> +
> +The PLL provides clocks to most of the components on the SoC. In addition
> +to the PLL itself, this controller also contains bypasses, gates, dividers,
> +an multiplexers for various clock signals.
> +
> +Required properties:
> +- compatible: shall be one of:
> + - "ti,da850-pll0" for PLL0 on DA850/OMAP-L138/AM18XX
> + - "ti,da850-pll1" for PLL1 on DA850/OMAP-L138/AM18XX
These PLLs are same IP so they should use the same compatible. You can
initialize both PLLs for DA850 based on the same compatible.
Thanks,
Sekhar
^ permalink raw reply
* [RFC PATCH 2/5] perf jevents: add support for arch recommended events
From: Jiri Olsa @ 2018-01-08 14:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <850a0774-9442-c836-f457-69e1e0d72fb2@huawei.com>
On Thu, Jan 04, 2018 at 05:17:56PM +0000, John Garry wrote:
SNIP
>
>
> Hi Jirka,
>
> Sorry for the slow reply.
np, just got back from holidays anyway ;-)
>
> > > > Won't this all potentially have a big maintainence cost?
> > as Andi said it's mostly just the disk space,
> > which is not big deal
> >
> > I'm not doing JSON file updates, but I think having
> > simple single dir for platform/cpu could save us some
> > confusion in future
>
> Understood. But for ARM, which has very standardised architecture events, it
> is good to reduce this event duplication between platforms.
>
> >
> > however I won't oppose if you want to add this logic,
> > but please:
> > - use the list_head ;-)
>
> Of course
>
> > - leave the process_one_file function simple
> > and separate the level0 processing
>
> ok, this is how it should look already, albeit a couple of
> process_one_file() modifications. I'll re-check this.
>
> > - you are using 'EventCode' as an unique ID to find
> > the base, but it's not unique for x86, you'll need
> > to add some other ID scheme that fits to all archs
>
> Right, so you mentioned earlier using a new keyword token to identify
> whether we use the standard event, so we can go his way - ok?
yes, something like that
> I would also like to mention at this point why I did the event
> pre-processing in jevents, and not a separate script:
> - current build does not transverse the arch tree
> - tree transversal for JSON processing is done in jevents
> - a script would mean derived objects, which means:
> - makefile changes for derived objects
> - jevents would have to deal with derived objects
> - jevents already has support for JSON processing
>
> The advantage of using a script is that we keep the JSON processing in
> jevents simple.
I don't mind the extra functionality in jevents as long as the current
one keeps on working and the new one works for all archs ;-)
thanks,
jirka
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox