* [PATCH v2 2/2] soc: zte: pm_domains: Add support for zx296718 board
From: Jun Nie @ 2016-12-06 11:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480987828-20549-2-git-send-email-baoyou.xie@linaro.org>
2016-12-06 9:30 GMT+08:00 Baoyou Xie <baoyou.xie@linaro.org>:
> This patch introduces the power domain driver of zx296718
> which belongs to zte's 2967 family.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
> drivers/soc/zte/Makefile | 2 +-
> drivers/soc/zte/zx296718_pm_domains.c | 182 ++++++++++++++++++++++++++++++++++
> 2 files changed, 183 insertions(+), 1 deletion(-)
> create mode 100644 drivers/soc/zte/zx296718_pm_domains.c
>
> diff --git a/drivers/soc/zte/Makefile b/drivers/soc/zte/Makefile
> index 97ac8ea..2d2a2cc 100644
> --- a/drivers/soc/zte/Makefile
> +++ b/drivers/soc/zte/Makefile
> @@ -1,4 +1,4 @@
> #
> # zx SOC drivers
> #
> -obj-$(CONFIG_ZX_PM_DOMAINS) += pm_domains.o
> +obj-$(CONFIG_ZX_PM_DOMAINS) += pm_domains.o zx296718_pm_domains.o
> diff --git a/drivers/soc/zte/zx296718_pm_domains.c b/drivers/soc/zte/zx296718_pm_domains.c
> new file mode 100644
> index 0000000..ed18b33
> --- /dev/null
> +++ b/drivers/soc/zte/zx296718_pm_domains.c
> @@ -0,0 +1,182 @@
> +/*
> + * Copyright (C) 2015 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +#include <dt-bindings/arm/zte_pm_domains.h>
> +#include "pm_domains.h"
> +
> +static u16 zx296718_offsets[REG_ARRAY_SIZE] = {
> + [REG_CLKEN] = 0x18,
> + [REG_ISOEN] = 0x1c,
> + [REG_RSTEN] = 0x20,
> + [REG_PWREN] = 0x24,
> + [REG_ACK_SYNC] = 0x28,
> +};
> +
> +enum {
> + PCU_DM_VOU = 0,
> + PCU_DM_SAPPU,
> + PCU_DM_VDE,
> + PCU_DM_VCE,
> + PCU_DM_HDE,
> + PCU_DM_VIU,
> + PCU_DM_USB20,
> + PCU_DM_USB21,
> + PCU_DM_USB30,
> + PCU_DM_HSIC,
> + PCU_DM_GMAC,
> + PCU_DM_TS,
> +};
> +
> +static struct zx_pm_domain vou_domain = {
> + .dm = {
> + .name = "vou_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_VOU,
> + .reg_offset = zx296718_offsets,
> +};
> +static struct zx_pm_domain sappu_domain = {
> + .dm = {
> + .name = "sappu_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_SAPPU,
> + .reg_offset = zx296718_offsets,
> +};
> +static struct zx_pm_domain vde_domain = {
> + .dm = {
> + .name = "vde_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_VDE,
> + .reg_offset = zx296718_offsets,
> +};
> +static struct zx_pm_domain vce_domain = {
> + .dm = {
> + .name = "vce_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_VCE,
> + .reg_offset = zx296718_offsets,
> +};
> +static struct zx_pm_domain hde_domain = {
> + .dm = {
> + .name = "hde_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_HDE,
> + .reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx_pm_domain viu_domain = {
> + .dm = {
> + .name = "viu_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_VIU,
> + .reg_offset = zx296718_offsets,
> +};
> +static struct zx_pm_domain usb20_domain = {
> + .dm = {
> + .name = "usb20_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_USB20,
> + .reg_offset = zx296718_offsets,
> +};
> +static struct zx_pm_domain usb21_domain = {
> + .dm = {
> + .name = "usb21_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_USB21,
> + .reg_offset = zx296718_offsets,
> +};
> +static struct zx_pm_domain usb30_domain = {
> + .dm = {
> + .name = "usb30_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_USB30,
> + .reg_offset = zx296718_offsets,
> +};
> +static struct zx_pm_domain hsic_domain = {
> + .dm = {
> + .name = "hsic_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_HSIC,
> + .reg_offset = zx296718_offsets,
> +};
> +static struct zx_pm_domain gmac_domain = {
> + .dm = {
> + .name = "gmac_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_GMAC,
> + .reg_offset = zx296718_offsets,
> +};
> +static struct zx_pm_domain ts_domain = {
> + .dm = {
> + .name = "ts_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_TS,
> + .reg_offset = zx296718_offsets,
> +};
> +struct generic_pm_domain *zx296718_pm_domains[] = {
> + [DM_ZX296718_SAPPU] = &sappu_domain.dm,
> + [DM_ZX296718_VDE] = &vde_domain.dm,
> + [DM_ZX296718_VCE] = &vce_domain.dm,
> + [DM_ZX296718_HDE] = &hde_domain.dm,
> + [DM_ZX296718_VIU] = &viu_domain.dm,
> + [DM_ZX296718_USB20] = &usb20_domain.dm,
> + [DM_ZX296718_USB21] = &usb21_domain.dm,
> + [DM_ZX296718_USB30] = &usb30_domain.dm,
> + [DM_ZX296718_HSIC] = &hsic_domain.dm,
> + [DM_ZX296718_GMAC] = &gmac_domain.dm,
> + [DM_ZX296718_TS] = &ts_domain.dm,
> + [DM_ZX296718_VOU] = &vou_domain.dm,
> +};
> +
> +static int zx296718_pd_probe(struct platform_device *pdev)
> +{
> + return zx_pd_probe(pdev,
> + zx296718_pm_domains,
> + ARRAY_SIZE(zx296718_pm_domains));
> +}
> +
> +static const struct of_device_id zx296718_pm_domain_matches[] = {
> + { .compatible = "zte,zx296718-pcu", },
> + { },
> +};
> +
> +static struct platform_driver zx296718_pd_driver = {
> + .driver = {
> + .name = "zx-powerdomain",
> + .owner = THIS_MODULE,
> + .of_match_table = zx296718_pm_domain_matches,
> + },
> + .probe = zx296718_pd_probe,
> +};
> +
> +static int __init zx296718_pd_init(void)
> +{
> + return platform_driver_register(&zx296718_pd_driver);
> +}
> +subsys_initcall(zx296718_pd_init);
> --
> 2.7.4
>
Reviewed-by: Jun Nie <jun.nie@linaro.org>
^ permalink raw reply
* [PATCH 8/9] mfd: wm97xx-core: core support for wm97xx Codec
From: Mark Brown @ 2016-12-06 11:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87y406ppjl.fsf@belgarion.home>
On Sat, Nov 26, 2016 at 10:18:38AM +0100, Robert Jarzmik wrote:
> >> >> +#define WM9705_VENDOR_ID 0x574d4c05
> >> >> +#define WM9712_VENDOR_ID 0x574d4c12
> >> >> +#define WM9713_VENDOR_ID 0x574d4c13
> >> >> +#define WM97xx_VENDOR_ID_MASK 0xffffffff
> >> > These are probably better represented as enums.
> >> These are ids, just as devicetree ids, or PCI ids, I don't think an enum will
> >> fit.
> > That's fine. We can use enums to simply group items of a similar
> > type. Representing these as enums would only serve to benefit code
> > cleanliness. What makes you think they won't fit?
That would be like having all PCI or USB identifiers in an enum, it's
doable but it means having one big table that all drivers need to
modify.
> >> >> +static int wm97xx_ac97_probe(struct ac97_codec_device *adev)
> >> As for the "sound specific part", it's because AC97 bus is mainly used in sound
> >> oriented drivers, but still the codec IPs provide more than just sound, as the
> >> Wolfson codecs for instance.
> > I'd like to get Mark Brown's opinion on this.
I'm not sure what the question is, sorry.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161206/bb87a688/attachment.sig>
^ permalink raw reply
* [PATCH v2 1/2] soc: zte: pm_domains: Prepare for supporting ARMv8 2967 family
From: Jun Nie @ 2016-12-06 11:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480987828-20549-1-git-send-email-baoyou.xie@linaro.org>
2016-12-06 9:30 GMT+08:00 Baoyou Xie <baoyou.xie@linaro.org>:
> The ARMv8 2967 family (296718, 296716 etc) uses different value
> for controlling the power domain on/off registers, Choose the
> value depending on the compatible.
>
> Multiple domains are prepared for the family, they'are privated
> by the drivers of boards.
Domains are SoC specific, not board, right?
>
> This patch prepares the common functions.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
> drivers/soc/Kconfig | 1 +
> drivers/soc/Makefile | 1 +
> drivers/soc/zte/Kconfig | 13 ++++
> drivers/soc/zte/Makefile | 4 ++
> drivers/soc/zte/pm_domains.c | 140 +++++++++++++++++++++++++++++++++++++++++++
> drivers/soc/zte/pm_domains.h | 41 +++++++++++++
> 6 files changed, 200 insertions(+)
> create mode 100644 drivers/soc/zte/Kconfig
> create mode 100644 drivers/soc/zte/Makefile
> create mode 100644 drivers/soc/zte/pm_domains.c
> create mode 100644 drivers/soc/zte/pm_domains.h
>
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index f31bceb..f09023f 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -11,5 +11,6 @@ source "drivers/soc/tegra/Kconfig"
> source "drivers/soc/ti/Kconfig"
> source "drivers/soc/ux500/Kconfig"
> source "drivers/soc/versatile/Kconfig"
> +source "drivers/soc/zte/Kconfig"
>
> endmenu
> diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> index 50c23d0..05eae52 100644
> --- a/drivers/soc/Makefile
> +++ b/drivers/soc/Makefile
> @@ -16,3 +16,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
> obj-$(CONFIG_SOC_TI) += ti/
> obj-$(CONFIG_ARCH_U8500) += ux500/
> obj-$(CONFIG_PLAT_VERSATILE) += versatile/
> +obj-$(CONFIG_ARCH_ZX) += zte/
> diff --git a/drivers/soc/zte/Kconfig b/drivers/soc/zte/Kconfig
> new file mode 100644
> index 0000000..4953c3fa
> --- /dev/null
> +++ b/drivers/soc/zte/Kconfig
> @@ -0,0 +1,13 @@
> +#
> +# zx SoC drivers
> +#
> +menuconfig SOC_ZX
> + bool "zx SoC driver support"
> +
> +if SOC_ZX
> +
> +config ZX_PM_DOMAINS
> + bool "zx PM domains"
> + depends on PM_GENERIC_DOMAINS
> +
> +endif
> diff --git a/drivers/soc/zte/Makefile b/drivers/soc/zte/Makefile
> new file mode 100644
> index 0000000..97ac8ea
> --- /dev/null
> +++ b/drivers/soc/zte/Makefile
> @@ -0,0 +1,4 @@
> +#
> +# zx SOC drivers
> +#
> +obj-$(CONFIG_ZX_PM_DOMAINS) += pm_domains.o
> diff --git a/drivers/soc/zte/pm_domains.c b/drivers/soc/zte/pm_domains.c
> new file mode 100644
> index 0000000..956c963
> --- /dev/null
> +++ b/drivers/soc/zte/pm_domains.c
> @@ -0,0 +1,140 @@
> +/*
> + * Copyright (C) 2015 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include "pm_domains.h"
> +
> +#define PCU_DM_CLKEN(zpd) ((zpd)->reg_offset[REG_CLKEN])
> +#define PCU_DM_ISOEN(zpd) ((zpd)->reg_offset[REG_ISOEN])
> +#define PCU_DM_RSTEN(zpd) ((zpd)->reg_offset[REG_RSTEN])
> +#define PCU_DM_PWREN(zpd) ((zpd)->reg_offset[REG_PWREN])
> +#define PCU_DM_ACK_SYNC(zpd) ((zpd)->reg_offset[REG_ACK_SYNC])
> +
> +static void __iomem *pcubase;
> +
> +int zx_normal_power_on(struct generic_pm_domain *domain)
> +{
> + struct zx_pm_domain *zpd = (struct zx_pm_domain *)domain;
> + unsigned long loop = 20000;
> + u32 val;
> +
> + loop = 1000;
Why change loop value here? You can initialize it to 1000 above.
> + do {
> + val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd));
> + val |= BIT(zpd->bit);
> + writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd));
Can we put this bit set out of loop?
Suggest to support 6702 with this driver via supporting PWREN
polarity, because all other logic are shared among these ZX SoCs.
> +
> + udelay(1);
> + val = readl_relaxed(pcubase
> + + PCU_DM_ACK_SYNC(zpd)) & BIT(zpd->bit);
> + } while (--loop && !val);
> +
> + if (!loop) {
> + pr_err("Error: %s %s fail\n", __func__, domain->name);
> + return -EIO;
> + }
> +
> + val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd));
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val | BIT(zpd->bit), pcubase + PCU_DM_RSTEN(zpd));
> + udelay(5);
> +
> + val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd));
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd));
> + udelay(5);
> +
> + val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd));
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val | BIT(zpd->bit), pcubase + PCU_DM_CLKEN(zpd));
> + udelay(5);
> +
> + pr_info("normal poweron %s\n", domain->name);
> +
> + return 0;
> +}
> +
> +int zx_normal_power_off(struct generic_pm_domain *domain)
> +{
> + struct zx_pm_domain *zpd = (struct zx_pm_domain *)domain;
> + unsigned long loop = 1000;
> + u32 val;
> +
> + val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd));
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd));
> + udelay(5);
> +
> + val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd));
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val | BIT(zpd->bit), pcubase + PCU_DM_ISOEN(zpd));
> + udelay(5);
> +
> + val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd));
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd));
> + udelay(5);
> +
> + loop = 1000;
> + do {
> + val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd));
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd));
Ditto.
> +
> + udelay(1);
> +
> + val = readl_relaxed(pcubase
> + + PCU_DM_ACK_SYNC(zpd)) & BIT(zpd->bit);
> + } while (--loop && val);
> +
> + if (!loop) {
> + pr_err("Error: %s %s fail\n", __func__, domain->name);
> + return -EIO;
> + }
> +
> + pr_info("normal poweroff %s\n", domain->name);
> +
> + return 0;
> +}
> +
> +int
> +zx_pd_probe(struct platform_device *pdev,
> + struct generic_pm_domain **zx_pm_domains,
> + int domain_num)
> +{
> + struct genpd_onecell_data *genpd_data;
> + struct resource *res;
> + int i;
> +
> + genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL);
> + if (!genpd_data)
> + return -ENOMEM;
> +
> + genpd_data->domains = zx_pm_domains;
> + genpd_data->num_domains = domain_num;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "no memory resource defined\n");
> + return -ENODEV;
> + }
> +
> + pcubase = devm_ioremap_resource(&pdev->dev, res);
> + if (!pcubase) {
Check error with:
if (IS_ERR(pcubase) {
> + dev_err(&pdev->dev, "ioremap fail.\n");
> + return -EIO;
> + }
> +
> + for (i = 0; i < domain_num; ++i)
> + pm_genpd_init(zx_pm_domains[i], NULL, false);
> +
> + of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data);
> + dev_info(&pdev->dev, "powerdomain init ok\n");
> + return 0;
> +}
> diff --git a/drivers/soc/zte/pm_domains.h b/drivers/soc/zte/pm_domains.h
> new file mode 100644
> index 0000000..e02518e
> --- /dev/null
> +++ b/drivers/soc/zte/pm_domains.h
> @@ -0,0 +1,41 @@
> +/*
> + * Copyright (c) 2015 ZTE Co., Ltd.
> + * http://www.zte.com.cn
> + *
> + * Header for ZTE's Power Domain Driver support
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __ZTE_PM_DOMAIN_H
> +#define __ZTE_PM_DOMAIN_H
> +
> +#include <linux/platform_device.h>
> +#include <linux/pm_domain.h>
> +
> +enum {
> + REG_CLKEN,
> + REG_ISOEN,
> + REG_RSTEN,
> + REG_PWREN,
> + REG_ACK_SYNC,
> +
> + /* The size of the array - must be last */
> + REG_ARRAY_SIZE,
> +};
> +
> +struct zx_pm_domain {
> + struct generic_pm_domain dm;
> + const u16 bit;
> + const u16 *reg_offset;
> +};
> +
> +extern int zx_normal_power_on(struct generic_pm_domain *domain);
> +extern int zx_normal_power_off(struct generic_pm_domain *domain);
> +extern int
> +zx_pd_probe(struct platform_device *pdev,
> + struct generic_pm_domain **zx_pm_domains,
> + int domain_num);
> +#endif /* __ZTE_PM_DOMAIN_H */
> --
> 2.7.4
>
^ permalink raw reply
* [LINUX RFC v4 3/4] mtd: spi-nor: add stripe support
From: Cyrille Pitchen @ 2016-12-06 11:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <DA6901612C71B84D91459DE817C418AE26E0C61B@XAP-PVEXMBX01.xlnx.xilinx.com>
Le 06/12/2016 ? 07:54, Naga Sureshkumar Relli a ?crit :
> Hi Cyrille,
>
>> -----Original Message-----
>> From: Cyrille Pitchen [mailto:cyrille.pitchen at atmel.com]
>> Sent: Monday, December 05, 2016 6:34 PM
>> To: Naga Sureshkumar Relli <nagasure@xilinx.com>; broonie at kernel.org;
>> michal.simek at xilinx.com; Soren Brinkmann <sorenb@xilinx.com>; Harini
>> Katakam <harinik@xilinx.com>; Punnaiah Choudary Kalluri
>> <punnaia@xilinx.com>
>> Cc: linux-spi at vger.kernel.org; linux-arm-kernel at lists.infradead.org; linux-
>> kernel at vger.kernel.org; linux-mtd at lists.infradead.org
>> Subject: Re: [LINUX RFC v4 3/4] mtd: spi-nor: add stripe support
>>
>> Hi Naga,
>>
>> Le 05/12/2016 ? 08:02, Naga Sureshkumar Relli a ?crit :
>>> Hi Cyrille,
>>>
>>>>> Hi Cyrille,
>>>>>
>>>>>> I have not finished to review the whole series yet but here some
>>>>>> first
>>>>>> comments:
>>>>>
>>>>> Thanks for reviewing these patch series.
>>>>>
>>>>>>
>>>>>> Le 27/11/2016 ? 09:33, Naga Sureshkumar Relli a ?crit :
>>>>>>> This patch adds stripe support and it is needed for GQSPI parallel
>>>>>>> configuration mode by:
>>>>>>>
>>>>>>> - Adding required parameters like stripe and shift to spi_nor
>>>>>>> structure.
>>>>>>> - Initializing all added parameters in spi_nor_scan()
>>>>>>> - Updating read_sr() and read_fsr() for getting status from both
>>>>>>> flashes
>>>>>>> - Increasing page_size, sector_size, erase_size and toatal flash
>>>>>>> size as and when required.
>>>>>>> - Dividing address by 2
>>>>>>> - Updating spi->master->flags for qspi driver to change CS
>>>>>>>
>>>>>>> Signed-off-by: Naga Sureshkumar Relli <nagasure@xilinx.com>
>>>>>>> ---
>>>>>>> Changes for v4:
>>>>>>> - rename isparallel to stripe
>>>>>>> Changes for v3:
>>>>>>> - No change
>>>>>>> Changes for v2:
>>>>>>> - Splitted to separate MTD layer changes from SPI core changes
>>>>>>> ---
>>>>>>> drivers/mtd/spi-nor/spi-nor.c | 130
>>>>>> ++++++++++++++++++++++++++++++++----------
>>>>>>> include/linux/mtd/spi-nor.h | 2 +
>>>>>>> 2 files changed, 103 insertions(+), 29 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/mtd/spi-nor/spi-nor.c
>>>>>>> b/drivers/mtd/spi-nor/spi-nor.c index d0fc165..4252239 100644
>>>>>>> --- a/drivers/mtd/spi-nor/spi-nor.c
>>>>>>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>>>>>>> @@ -22,6 +22,7 @@
>>>>>>> #include <linux/of_platform.h>
>>>>>>> #include <linux/spi/flash.h>
>>>>>>> #include <linux/mtd/spi-nor.h>
>>>>>>> +#include <linux/spi/spi.h>
>>>>>>>
>>>>>>> /* Define max times to check status register before we give up.
>>>>>>> */
>>>>>>>
>>>>>>> @@ -89,15 +90,24 @@ static const struct flash_info
>>>>>>> *spi_nor_match_id(const char *name); static int read_sr(struct
>>>>>>> spi_nor *nor) {
>>>>>>> int ret;
>>>>>>> - u8 val;
>>>>>>> + u8 val[2];
>>>>>>>
>>>>>>> - ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1);
>>>>>>> - if (ret < 0) {
>>>>>>> - pr_err("error %d reading SR\n", (int) ret);
>>>>>>> - return ret;
>>>>>>> + if (nor->stripe) {
>>>>>>> + ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val[0], 2);
>>>>>>> + if (ret < 0) {
>>>>>>> + pr_err("error %d reading SR\n", (int) ret);
>>>>>>> + return ret;
>>>>>>> + }
>>>>>>> + val[0] |= val[1];
>>>>>> Why '|' rather than '&' ?
>>>>>> I guess because of the 'Write In Progress/Busy' bit: when called by
>>>>>> spi_nor_sr_ready(), you want to be sure that this 'BUSY' bit is
>>>>>> cleared on both memories.
>>>>>>
>>>>>> But what about when the Status Register is read for purpose other
>>>>>> than checking the state of the 'BUSY' bit?
>>>>>>
>>>>> Yes you are correct, I will change this.
>>>>>
>>>>>> What about SPI controllers supporting more than 2 memories in
>> parallel?
>>>>>>
>>>>>> This solution might fit the ZynqMP controller but doesn't look so
>> generic.
>>>>>>
>>>>>>> + } else {
>>>>>>> + ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val[0], 1);
>>>>>>> + if (ret < 0) {
>>>>>>> + pr_err("error %d reading SR\n", (int) ret);
>>>>>>> + return ret;
>>>>>>> + }
>>>>>>> }
>>>>>>>
>>>>>>> - return val;
>>>>>>> + return val[0];
>>>>>>> }
>>>>>>>
>>>>>>> /*
>>>>>>> @@ -108,15 +118,24 @@ static int read_sr(struct spi_nor *nor)
>>>>>>> static int read_fsr(struct spi_nor *nor) {
>>>>>>> int ret;
>>>>>>> - u8 val;
>>>>>>> + u8 val[2];
>>>>>>>
>>>>>>> - ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1);
>>>>>>> - if (ret < 0) {
>>>>>>> - pr_err("error %d reading FSR\n", ret);
>>>>>>> - return ret;
>>>>>>> + if (nor->stripe) {
>>>>>>> + ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val[0], 2);
>>>>>>> + if (ret < 0) {
>>>>>>> + pr_err("error %d reading FSR\n", ret);
>>>>>>> + return ret;
>>>>>>> + }
>>>>>>> + val[0] &= val[1];
>>>>>> Same comment here: why '&' rather than '|'?
>>>>>> Surely because of the the 'READY' bit which should be set for both
>>>> memories.
>>>>> I will update this also.
>>>>>>
>>>>>>> + } else {
>>>>>>> + ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val[0], 1);
>>>>>>> + if (ret < 0) {
>>>>>>> + pr_err("error %d reading FSR\n", ret);
>>>>>>> + return ret;
>>>>>>> + }
>>>>>>> }
>>>>>>>
>>>>>>> - return val;
>>>>>>> + return val[0];
>>>>>>> }
>>>>>>>
>>>>>>> /*
>>>>>>> @@ -290,9 +309,16 @@ static int spi_nor_wait_till_ready(struct
>>>>>>> spi_nor
>>>>>> *nor)
>>>>>>> */
>>>>>>> static int erase_chip(struct spi_nor *nor) {
>>>>>>> + u32 ret;
>>>>>>> +
>>>>>>> dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >>
>>>>>>> 10));
>>>>>>>
>>>>>>> - return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0);
>>>>>>> + ret = nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0); if
>>>>>>> + (ret)
>>>>>>> + return ret;
>>>>>>> +
>>>>>>> + return ret;
>>>>>>> +
>>>>>>
>>>>>> if (ret)
>>>>>> return ret;
>>>>>> else
>>>>>> return ret;
>>>>>>
>>>>>> This chunk should be removed, it doesn't ease the patch review ;)
>>>>> Ok, I will remove.
>>>>>>
>>>>>>> }
>>>>>>>
>>>>>>> static int spi_nor_lock_and_prep(struct spi_nor *nor, enum
>>>>>>> spi_nor_ops ops) @@ -349,7 +375,7 @@ static int
>>>>>>> spi_nor_erase_sector(struct spi_nor *nor, u32 addr) static int
>>>>>>> spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) {
>>>>>>> struct spi_nor *nor = mtd_to_spi_nor(mtd);
>>>>>>> - u32 addr, len;
>>>>>>> + u32 addr, len, offset;
>>>>>>> uint32_t rem;
>>>>>>> int ret;
>>>>>>>
>>>>>>> @@ -399,9 +425,13 @@ static int spi_nor_erase(struct mtd_info
>>>>>>> *mtd,
>>>>>> struct erase_info *instr)
>>>>>>> /* "sector"-at-a-time erase */
>>>>>>> } else {
>>>>>>> while (len) {
>>>>>>> +
>>>>>>> write_enable(nor);
>>>>>>> + offset = addr;
>>>>>>> + if (nor->stripe)
>>>>>>> + offset /= 2;
>>>>>>
>>>>>> I guess this should be /= 4 for controllers supporting 4 memories
>>>>>> in
>>>> parallel.
>>>>>> Shouldn't you use nor->shift and define shift as an unsigned int
>>>>>> instead of a bool?
>>>>>> offset >>= nor->shift;
>>>>>>
>>>>> Yes we can use this shift, I will update
>>>>>
>>>>>> Anyway, by tuning the address here in spi-nor.c rather than in the
>>>>>> SPI controller driver, you impose a model to support parallel
>>>>>> memories that might not be suited to other controllers.
>>>>>
>>>>> For this ZynqMP GQSPI controller parallel configuration, globally
>>>>> spi-nor should know about this stripe feature And based on that
>>>>> address
>>>> has to change.
>>>>> As I mentioned in cover letter, this controller in parallel
>>>>> configuration will
>>>> work with even addresses only.
>>>>> i.e. Before creating address format(m25p_addr2cmd) in mtd layer,
>>>>> spi-nor
>>>> should change that address based on stripe option.
>>>>>
>>>>> I am updating this offset based on stripe option, and stripe option
>>>>> will
>>>> update by reading dt property in nor_scan().
>>>>> So the controller which doesn't support, then the stripe will be zero.
>>>>> Or Can you please suggest any other way?
>>>>>
>>>>>>
>>>>>>>
>>>>>>> - ret = spi_nor_erase_sector(nor, addr);
>>>>>>> + ret = spi_nor_erase_sector(nor, offset);
>>>>>>> if (ret)
>>>>>>> goto erase_err;
>>>>>>>
>>>>>>> @@ -525,6 +555,8 @@ static int stm_lock(struct spi_nor *nor,
>>>>>>> loff_t ofs,
>>>>>> uint64_t len)
>>>>>>> bool use_top;
>>>>>>> int ret;
>>>>>>>
>>>>>>> + ofs = ofs >> nor->shift;
>>>>>>> +
>>>>>>> status_old = read_sr(nor);
>>>>>>> if (status_old < 0)
>>>>>>> return status_old;
>>>>>>> @@ -610,6 +642,8 @@ static int stm_unlock(struct spi_nor *nor,
>>>>>>> loff_t ofs,
>>>>>> uint64_t len)
>>>>>>> bool use_top;
>>>>>>> int ret;
>>>>>>>
>>>>>>> + ofs = ofs >> nor->shift;
>>>>>>> +
>>>>>>> status_old = read_sr(nor);
>>>>>>> if (status_old < 0)
>>>>>>> return status_old;
>>>>>>> @@ -709,6 +743,8 @@ static int spi_nor_lock(struct mtd_info *mtd,
>>>>>>> loff_t
>>>>>> ofs, uint64_t len)
>>>>>>> if (ret)
>>>>>>> return ret;
>>>>>>>
>>>>>>> + ofs = ofs >> nor->shift;
>>>>>>> +
>>>>>>> ret = nor->flash_lock(nor, ofs, len);
>>>>>>>
>>>>>>> spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); @@ -
>>>>>> 724,6 +760,8
>>>>>>> @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs,
>>>>>>> uint64_t
>>>>>> len)
>>>>>>> if (ret)
>>>>>>> return ret;
>>>>>>>
>>>>>>> + ofs = ofs >> nor->shift;
>>>>>>> +
>>>>>>> ret = nor->flash_unlock(nor, ofs, len);
>>>>>>>
>>>>>>> spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); @@ -
>>>>>> 1018,6 +1056,9
>>>>>>> @@ static const struct flash_info *spi_nor_read_id(struct spi_nor
>> *nor)
>>>>>>> u8 id[SPI_NOR_MAX_ID_LEN];
>>>>>>> const struct flash_info *info;
>>>>>>>
>>>>>>> + nor->spi->master->flags &= ~(SPI_MASTER_BOTH_CS |
>>>>>>> + SPI_MASTER_DATA_STRIPE);
>>>>>>> +
>>>>>>> tmp = nor->read_reg(nor, SPINOR_OP_RDID, id,
>>>>>> SPI_NOR_MAX_ID_LEN);
>>>>>>> if (tmp < 0) {
>>>>>>> dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp);
>>>>>> @@ -1041,6
>>>>>>> +1082,7 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t
>>>>>>> +from,
>>>>>>> size_t len, {
>>>>>>> struct spi_nor *nor = mtd_to_spi_nor(mtd);
>>>>>>> int ret;
>>>>>>> + u32 offset = from;
>>>>>>>
>>>>>>> dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
>>>>>>>
>>>>>>> @@ -1049,7 +1091,13 @@ static int spi_nor_read(struct mtd_info
>>>>>>> *mtd,
>>>>>> loff_t from, size_t len,
>>>>>>> return ret;
>>>>>>>
>>>>>>> while (len) {
>>>>>>> - ret = nor->read(nor, from, len, buf);
>>>>>>> +
>>>>>>> + offset = from;
>>>>>>> +
>>>>>>> + if (nor->stripe)
>>>>>>> + offset /= 2;
>>>>>>> +
>>>>>>> + ret = nor->read(nor, offset, len, buf);
>>>>>>> if (ret == 0) {
>>>>>>> /* We shouldn't see 0-length reads */
>>>>>>> ret = -EIO;
>>>>>>> @@ -1161,6 +1209,7 @@ static int spi_nor_write(struct mtd_info
>>>>>>> *mtd,
>>>>>> loff_t to, size_t len,
>>>>>>> struct spi_nor *nor = mtd_to_spi_nor(mtd);
>>>>>>> size_t page_offset, page_remain, i;
>>>>>>> ssize_t ret;
>>>>>>> + u32 offset;
>>>>>>>
>>>>>>> dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
>>>>>>>
>>>>>>> @@ -1178,9 +1227,13 @@ static int spi_nor_write(struct mtd_info
>>>>>>> *mtd,
>>>>>> loff_t to, size_t len,
>>>>>>> /* the size of data remaining on the first page */
>>>>>>> page_remain = min_t(size_t,
>>>>>>> nor->page_size - page_offset, len -
>>>>>>> i);
>>>>>>> + offset = (to + i);
>>>>>>> +
>>>>>>> + if (nor->stripe)
>>>>>>> + offset /= 2;
>>>>>>>
>>>>>>> write_enable(nor);
>>>>>>> - ret = nor->write(nor, to + i, page_remain, buf + i);
>>>>>>> + ret = nor->write(nor, (offset), page_remain, buf + i);
>>>>>>> if (ret < 0)
>>>>>>> goto write_err;
>>>>>>> written = ret;
>>>>>>> @@ -1302,22 +1355,22 @@ static int spi_nor_check(struct spi_nor
>>>>>>> *nor)
>>>>>>>
>>>>>>> int spi_nor_scan(struct spi_nor *nor, const char *name, enum
>>>>>>> read_mode mode) {
>>>>>>> - const struct flash_info *info = NULL;
>>>>>>> + struct flash_info *info = NULL;
>>>>>>
>>>>>> You should not remove the const and should not try to modify
>>>>>> members of *info.
>>>>>>
>>>>>>> struct device *dev = nor->dev;
>>>>>>> struct mtd_info *mtd = &nor->mtd;
>>>>>>> struct device_node *np = spi_nor_get_flash_node(nor);
>>>>>>> - int ret;
>>>>>>> - int i;
>>>>>>> + struct device_node *np_spi;
>>>>>>> + int ret, i, xlnx_qspi_mode;
>>>>>>>
>>>>>>> ret = spi_nor_check(nor);
>>>>>>> if (ret)
>>>>>>> return ret;
>>>>>>>
>>>>>>> if (name)
>>>>>>> - info = spi_nor_match_id(name);
>>>>>>> + info = (struct flash_info *)spi_nor_match_id(name);
>>>>>>> /* Try to auto-detect if chip name wasn't specified or not found */
>>>>>>> if (!info)
>>>>>>> - info = spi_nor_read_id(nor);
>>>>>>> + info = (struct flash_info *)spi_nor_read_id(nor);
>>>>>>> if (IS_ERR_OR_NULL(info))
>>>>>>> return -ENOENT;
>>>>>>>
>>>>>> Both spi_nor_match_id() and spi_nor_read_id(), when they succeed,
>>>>>> return a pointer to an entry of the spi_nor_ids[] array, which is
>>>>>> located in a read- only memory area.
>>>>>>
>>>>>> Since your patch doesn't remove the const attribute of the
>>>>>> spi_nor_ids[], I wonder whether it has been tested. I expect it not
>>>>>> to work on most architecture.
>>>>>>
>>>>>> Anyway spi_nor_ids[] should remain const. Let's take the case of
>>>>>> eXecution In Place (XIP) from an external memory: if spi_nor_ids[]
>>>>>> is const, it can be read directly from this external (read-only)
>>>>>> memory and we never need to copy the array in RAM, so we save
>> some
>>>>>> KB of
>>>> RAM.
>>>>>> This is just an example but I guess we can find other reasons to
>>>>>> keep this array const.
>>>>>>
>>>>>>> @@ -1341,7 +1394,7 @@ int spi_nor_scan(struct spi_nor *nor, const
>>>>>>> char
>>>>>> *name, enum read_mode mode)
>>>>>>> */
>>>>>>> dev_warn(dev, "found %s, expected %s\n",
>>>>>>> jinfo->name, info->name);
>>>>>>> - info = jinfo;
>>>>>>> + info = (struct flash_info *)jinfo;
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> @@ -1370,6 +1423,27 @@ int spi_nor_scan(struct spi_nor *nor, const
>>>>>>> char
>>>>>> *name, enum read_mode mode)
>>>>>>> mtd->size = info->sector_size * info->n_sectors;
>>>>>>> mtd->_erase = spi_nor_erase;
>>>>>>> mtd->_read = spi_nor_read;
>>>>>>> +#ifdef CONFIG_OF
>>>>>>> + np_spi = of_get_next_parent(np);
>>>>>>> +
>>>>>>> + if (of_property_read_u32(np_spi, "xlnx,qspi-mode",
>>>>>>> + &xlnx_qspi_mode) < 0) {
>>>>>> This really looks controller specific so should not be placed in
>>>>>> the generic spi- nor.c file.
>>>>>
>>>>> Const is removed in info struct, because to update info members
>>>>> based
>>>> parallel configuration.
>>>>> As I mentioned above, for this parallel configuration, mtd and
>>>>> spi-nor should know the details like
>>>>> mtd->size, info->sectors, sector_size and page_size.
>>>>
>>>> You can tune the values of nor->mtd.size, nor->mtd.erasesize, nor-
>>>>> page_size or whatever member of nor/nor.mtd as needed without ever
>>>> modifying members of *info.
>>>>
>>>> If you modify *info then spi_nor_scan() is called a 2nd time to probe
>>>> and configure SPI memories of the same part but connected to another
>>>> controller, the values of the modified members in this *info would
>>>> not be those expected.
>>>> So *info and the spi_nor_ids[] array must remain const.
>>>>
>>>> The *info structure is not used outside spi_nor_scan(); none of
>>>> spi_nor_read(),
>>>> spi_nor_write() and spi_nor_erase() refers to *info hence every
>>>> relevant value can be set only nor or nor->mtd members.
>>>>
>>>>
>>>> Anyway, I think OR'ing or AND'ing values of memory registers
>>>> depending on the relevant bit we want to check is not the right solution.
>>>> If done in spi-nor.c, there would be a specific case for each memory
>>>> register we read, each register bit would have to be handled differently.
>>>>
>>>> spi-nor.c tries to support as much memory parts as possible, it deals
>>>> with many registers and bits: Status/Control registers, Quad Enable bits...
>>>>
>>>> If we start to OR or AND each of these register values to support the
>>>> stripping mode, spi-nor will become really hard to maintain.
>>>>
>>>> I don't know whether it could be done with the xilinx controller but
>>>> I thought about first configuring the two memories independently
>>>> calling
>>>> spi_nor_scan() twice; one call for each memory.
>>>>
>>>> Then the xilinx driver could register only one struct mtd_info,
>>>> overriding
>>>> mtd->_read() [and likely mtd->_write() and mtd->_erase() too] set by
>>>> spi_nor_scan() with a xilinx driver custom implementation so this
>>>> driver supports its controller stripping mode as it wants.
>>>>
>>>> Of course, this solution assumes that the SPI controller has one
>>>> dedicated chip-select line for each memory and not a single
>>>> chip-select line shared by both memories. The memories should be
>>>> configured independently: you can't assume multiple instances of the
>>>> very same memory part always return the exact same value when reading
>>>> one of their register. Logical AND/OR is not a generic solution, IMHO.
>>>>
>>>> If the xilinx controller has only one shared chip-select line then
>>>> let's see whether 2 GPIO lines could be used as independent chip-select
>> lines.
>>>>
>>>>
>>> In parallel configuration, Physically we have two flashes but mtd will
>>> see as single flash memory (sum of both memories) If we call
>> spi_nor_scan(), twice then read/write will override but nor->mtd.size, nor-
>>> mtd.erasesize, nor->page_size will remain same, I,e they will also override,
>> they won't append.
>>> I tried calling spi_nor_scan() twice by some hacks but nor->mtd.size,
>>> nor->mtd.erasesize, nor->page_size are not changing Also the same issue
>> we are getting for flash address, need to shift the address to work in this
>> configuration.
>>> Also to tune nor->mtd.size, nor->mtd.erasesize, nor->page_size, we
>>> need to touch this spi-nor.c
>>>
>>> Please kindly suggest, if I am wrong.
>>>
>>
>> What I've been suggesting is:
>>
>> {
>> struct spi_nor *nor1, *nor2;
>> struct mtd_info *mtd;
>> enum read_mode mode = SPI_NOR_QUAD;
>> int err;
>>
>> [...]
>>
>> err = spi_nor_scan(nor1, NULL, mode);
>> if (err)
>> return err; /* or handle error properly. */
>>
>> err = spi_nor_scan(nor2, NULL, mode);
>> if (err)
>> return err;
>>
>> mtd = &nor1->mtd;
>> mtd->erasesize <<= 1;
>> mtd->size <<= 1;
>> mtd->writebufsize <<= 1;
>> nor1->page_size <<= 1;
>> /* tune all other relevant members of nor1/mtd. */
>>
>> /* override relevant mtd hooks. */
>> mtd->_read = stripping_read;
>> mtd->_erase = stripping_erase;
>> mtd->_write = stripping_write;
>> mtd->_lock = ...;
>> mtd->_unlock = ...;
>> mtd->_is_lock = ...;
>>
>> /* register a single mtd_info structure. */
>> err = mtd_device_register(mtd, NULL, 0);
>> if (err)
>> return err;
>>
>> [...]
>> }
>>
>
> It's really good for us to have our controller specific mtd hooks instead of changing the layer calls and thanks for this suggestion.
> But spi-zynqmp-gqspi.c is spi driver and all above mentioned parameters and function pointers are related to flash layer.
> So is it ok to update and change flash related stuff in our spi driver?
>
Check with the SPI sub-system people, especially Mark Brown, but I don't
think would be good to put too much mtd/spi-nor stuff in the SPI sub-system.
Anyway, the solution I've proposed is not suited if you use m25p80.c as an
adaptation layer between spi-nor.c and the SPI controller driver.
Indeed, in that case, spi_nor_scan() is called from m25p_probe() in
m25p80.c and I still think there would be too many side effects if we
modified either spi-nor.c or m25p80.c the way you propose to compute
logical operations on register values. This solution is not maintainable
regarding the number memory registers we already manage.
You might need to develop a new driver to substitute m25p80.c and make the
link between spi-nor, mostly spi_nor_scan(), and you SPI controller driver.
Honestly I have no real idea how you could proceed to add support to such a
feature: accessing 2 SPI flashes at the time to perform stripping
operations doesn't sound really reliable to me because I don't see how you
plan to handle errors properly and also cover all the features provided by
SPI flash memory and supported by spi-nor.c (sector/block protection, ...).
>> Best regards,
>>
>> Cyrille
>>
> Thanks,
> Naga Sureshkumar Relli
>
>
> This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
>
>
^ permalink raw reply
* [RFC PATCH 3/3] ARM: dts: at91: sama5d2_xplained: add pin muxing and enable classd
From: Nicolas Ferre @ 2016-12-06 10:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1481021115.git.nicolas.ferre@atmel.com>
From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
This patch adds the pin muxing for classd and enables it.
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index 0b9a59d5fdac..c9a8939ba1ef 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -332,6 +332,14 @@
bias-pull-up;
};
+ pinctrl_classd_default: classd_default {
+ pinmux = <PIN_PB1__CLASSD_R0>,
+ <PIN_PB2__CLASSD_R1>,
+ <PIN_PB3__CLASSD_R2>,
+ <PIN_PB4__CLASSD_R3>;
+ bias-pull-up;
+ };
+
pinctrl_flx0_default: flx0_default {
pinmux = <PIN_PB28__FLEXCOM0_IO0>,
<PIN_PB29__FLEXCOM0_IO1>;
@@ -464,6 +472,14 @@
};
};
+
+ classd: classd at fc048000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_classd_default>;
+ atmel,pwm-type = "diff";
+ atmel,non-overlap-time = <10>;
+ status = "okay";
+ };
};
};
--
2.9.0
^ permalink raw reply related
* [RFC PATCH 2/3] ARM: dts: at91: sama5d2: add classd nodes
From: Nicolas Ferre @ 2016-12-06 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1481021115.git.nicolas.ferre@atmel.com>
From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
This patch adds nodes for the classd device and its generated clock.
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
arch/arm/boot/dts/sama5d2.dtsi | 39 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index ceb9783ff7e1..d6b8d59a913b 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -447,6 +447,24 @@
clocks = <&plla>;
};
+ audio_pll_frac: audiopll_fracck {
+ compatible = "atmel,sama5d2-clk-audio-pll-frac";
+ #clock-cells = <0>;
+ clocks = <&main>;
+ };
+
+ audio_pll_pad: audiopll_padck {
+ compatible = "atmel,sama5d2-clk-audio-pll-pad";
+ #clock-cells = <0>;
+ clocks = <&audio_pll_frac>;
+ };
+
+ audio_pll_pmc: audiopll_pmcck {
+ compatible = "atmel,sama5d2-clk-audio-pll-pmc";
+ #clock-cells = <0>;
+ clocks = <&audio_pll_frac>;
+ };
+
utmi: utmick {
compatible = "atmel,at91sam9x5-clk-utmi";
#clock-cells = <0>;
@@ -836,7 +854,7 @@
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&pmc>;
- clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>;
+ clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>, <&audio_pll_pmc>;
sdmmc0_gclk: sdmmc0_gclk {
#clock-cells = <0>;
@@ -880,6 +898,12 @@
#clock-cells = <0>;
reg = <55>;
};
+
+ classd_gclk: classd_gclk {
+ #clock-cells = <0>;
+ reg = <59>;
+ atmel,clk-output-range = <0 100000000>;
+ };
};
};
@@ -1279,6 +1303,19 @@
status = "okay";
};
+ classd: classd at fc048000 {
+ compatible = "atmel,sama5d2-classd";
+ reg = <0xfc048000 0x100>;
+ interrupts = <59 IRQ_TYPE_LEVEL_HIGH 7>;
+ dmas = <&dma0
+ (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
+ AT91_XDMAC_DT_PERID(47))>;
+ dma-names = "tx";
+ clocks = <&classd_clk>, <&classd_gclk>, <&audio_pll_pmc>;
+ clock-names = "pclk", "gclk", "aclk";
+ status = "disabled";
+ };
+
chipid at fc069000 {
compatible = "atmel,sama5d2-chipid";
reg = <0xfc069000 0x8>;
--
2.9.0
^ permalink raw reply related
* [RFC PATCH 1/3] clk: at91: add audio pll clock driver
From: Nicolas Ferre @ 2016-12-06 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1481021115.git.nicolas.ferre@atmel.com>
This new clock driver set allows to have a fractional divided clock that
would generate a precise clock particularly suitable for audio applications.
The main audio pll clock has two children clocks: one that is connected to
the PMC, the other that can directly drive a pad. As these two routes have
different enable bits and different dividers and divider formula, they are
handled by two different drivers. Each of them would modify the rate of
the main audio pll parent.
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
.../devicetree/bindings/clock/at91-clock.txt | 10 +
arch/arm/mach-at91/Kconfig | 4 +
drivers/clk/at91/Makefile | 2 +
drivers/clk/at91/clk-audio-pll-pad.c | 238 +++++++++++++++++++
drivers/clk/at91/clk-audio-pll-pmc.c | 184 +++++++++++++++
drivers/clk/at91/clk-audio-pll.c | 253 +++++++++++++++++++++
include/linux/clk/at91_pmc.h | 25 ++
7 files changed, 716 insertions(+)
create mode 100644 drivers/clk/at91/clk-audio-pll-pad.c
create mode 100644 drivers/clk/at91/clk-audio-pll-pmc.c
create mode 100644 drivers/clk/at91/clk-audio-pll.c
diff --git a/Documentation/devicetree/bindings/clock/at91-clock.txt b/Documentation/devicetree/bindings/clock/at91-clock.txt
index 5f3ad65daf69..bbf3ed9d9166 100644
--- a/Documentation/devicetree/bindings/clock/at91-clock.txt
+++ b/Documentation/devicetree/bindings/clock/at91-clock.txt
@@ -81,6 +81,16 @@ Required properties:
"atmel,sama5d2-clk-generated":
at91 generated clock
+ "atmel,sama5d2-clk-audio-pll-frac":
+ at91 audio fractional pll
+
+ "atmel,sama5d2-clk-audio-pll-pad":
+ at91 audio pll CLK_AUDIO output pin
+
+ "atmel,sama5d2-clk-audio-pll-pmc"
+ at91 audio pll ouput on AUDIOPLLCLK that feeds the PMC
+ and can be used by peripheral clock or generic clock
+
Required properties for SCKC node:
- reg : defines the IO memory reserved for the SCKC.
- #size-cells : shall be 0 (reg is used to encode clk id).
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 841e924143f9..bc1f56dcda8a 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -17,6 +17,7 @@ config SOC_SAMA5D2
select HAVE_AT91_USB_CLK
select HAVE_AT91_H32MX
select HAVE_AT91_GENERATED_CLK
+ select HAVE_AT91_AUDIO_PLL
select PINCTRL_AT91PIO4
help
Select this if ou are using one of Atmel's SAMA5D2 family SoC.
@@ -114,6 +115,9 @@ config HAVE_AT91_H32MX
config HAVE_AT91_GENERATED_CLK
bool
+config HAVE_AT91_AUDIO_PLL
+ bool
+
config SOC_SAM_V4_V5
bool
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
index 13e67bd35cff..c9353d17763a 100644
--- a/drivers/clk/at91/Makefile
+++ b/drivers/clk/at91/Makefile
@@ -6,6 +6,8 @@ obj-y += pmc.o sckc.o
obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o
obj-y += clk-system.o clk-peripheral.o clk-programmable.o
+obj-$(CONFIG_HAVE_AT91_AUDIO_PLL) += clk-audio-pll.o
+obj-$(CONFIG_HAVE_AT91_AUDIO_PLL) += clk-audio-pll-pmc.o clk-audio-pll-pad.o
obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o
obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o
obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o
diff --git a/drivers/clk/at91/clk-audio-pll-pad.c b/drivers/clk/at91/clk-audio-pll-pad.c
new file mode 100644
index 000000000000..39cee71f15c6
--- /dev/null
+++ b/drivers/clk/at91/clk-audio-pll-pad.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation,
+ * Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include "pmc.h"
+
+/*
+ * DOC: PAD output for fractional PLL clock for audio
+ *
+ * Traits of this clock:
+ * enable - clk_enable writes qdpad (which is ext_div and (div2,div3)),
+ * and enables PAD output
+ * rate - rate is adjustable.
+ * clk->rate = parent->rate / (ext_div * (div2,div3))
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+#define AUDIO_PLL_FOUT_MIN 620000000
+#define AUDIO_PLL_FOUT_MAX 700000000
+#define AUDIO_PLL_REFERENCE_FOUT 660000000
+
+#define AUDIO_PLL_QDPAD_MAX ((AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK >> \
+ AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET) * \
+ AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX)
+#define AUDIO_PLL_QDPAD_EXTDIV_OFFSET (AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET - \
+ AT91_PMC_AUDIO_PLL_QDPAD_OFFSET)
+#define AUDIO_PLL_DIV2QD(div, ext_div) ((div) | ((ext_div) << \
+ AUDIO_PLL_QDPAD_EXTDIV_OFFSET))
+#define AUDIO_PLL_QD2DIV(qd) ((qd) & (AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK >> \
+ AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET))
+#define AUDIO_PLL_QD2EXTDIV(qd) (((qd) >> AUDIO_PLL_QDPAD_EXTDIV_OFFSET) \
+ & (AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK >> \
+ AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET))
+
+struct clk_audio_pad {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ spinlock_t *lock;
+ u8 qdpad;
+};
+
+#define to_clk_audio_pad(hw) container_of(hw, struct clk_audio_pad, hw)
+
+static int clk_audio_pll_pad_enable(struct clk_hw *hw)
+{
+ struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(apad_ck->lock, flags);
+ regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL1,
+ AT91_PMC_AUDIO_PLL_QDPAD_MASK,
+ AT91_PMC_AUDIO_PLL_QDPAD(apad_ck->qdpad));
+ regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0,
+ AT91_PMC_AUDIO_PLL_PADEN, AT91_PMC_AUDIO_PLL_PADEN);
+ spin_unlock_irqrestore(apad_ck->lock, flags);
+ return 0;
+}
+
+static void clk_audio_pll_pad_disable(struct clk_hw *hw)
+{
+ struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
+
+ regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0,
+ AT91_PMC_AUDIO_PLL_PADEN, 0);
+}
+
+static unsigned long clk_audio_pll_pad_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
+ unsigned long apad_rate = 0;
+ u8 tmp_div = AUDIO_PLL_QD2DIV(apad_ck->qdpad);
+ u8 tmp_ext_div = AUDIO_PLL_QD2EXTDIV(apad_ck->qdpad);
+
+ if (tmp_div && tmp_ext_div)
+ apad_rate = parent_rate / (tmp_div * tmp_ext_div);
+
+ pr_debug("A PLL/PAD: %s, apad_rate = %lu (div = %u, ext_div = %u)\n" ,
+ __func__ , apad_rate, tmp_div, tmp_ext_div);
+
+ return apad_rate;
+}
+
+static int clk_audio_pll_compute_qdpad(unsigned long q_rate, unsigned long rate,
+ unsigned long *qd, u8 *div, u8 *ext_div)
+{
+ unsigned long tmp_qd;
+ unsigned long rem2, rem3;
+ unsigned long ldiv, lext_div;;
+
+ if (!rate)
+ return -EINVAL;
+
+ tmp_qd = q_rate / rate;
+ if (!tmp_qd || tmp_qd > AUDIO_PLL_QDPAD_MAX)
+ return -EINVAL;
+
+ if (tmp_qd <= AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX) {
+ ldiv = 1;
+ lext_div = tmp_qd;
+ } else {
+ rem2 = tmp_qd % 2;
+ rem3 = tmp_qd % 3;
+
+ if (rem3 == 0 ||
+ tmp_qd > AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX * 2 ||
+ rem3 < rem2) {
+ ldiv = 3;
+ lext_div = tmp_qd / 3;
+ } else {
+ ldiv = 2;
+ lext_div = tmp_qd >> 1;
+ }
+ }
+
+ pr_debug("A PLL/PAD: %s, qd = %lu (div = %lu, ext_div = %lu)\n" ,
+ __func__ , ldiv * lext_div, ldiv, lext_div);
+
+ /* if we were given variable to store, we can provide them */
+ if (qd)
+ *qd = ldiv * lext_div;
+ if (div && ext_div) {
+ /* we can cast here as we verified the bounds just above */
+ *div = (u8)ldiv;
+ *ext_div = (u8)lext_div;
+ }
+
+ return 0;
+}
+
+static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk_hw *pclk = clk_hw_get_parent(hw);
+ long best_rate = -EINVAL;
+ unsigned long best_parent_rate = 0;
+ unsigned long tmp_qd;
+
+ pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n" ,
+ __func__ , rate, *parent_rate);
+
+ if (clk_audio_pll_compute_qdpad(AUDIO_PLL_REFERENCE_FOUT, rate,
+ &tmp_qd, NULL, NULL))
+ return -EINVAL;
+
+ best_parent_rate = clk_hw_round_rate(pclk, rate * tmp_qd);
+ best_rate = best_parent_rate / tmp_qd;
+
+ pr_debug("A PLL/PAD: %s, best_rate = %ld, best_parent_rate = %lu\n",
+ __func__, best_rate, best_parent_rate);
+
+ *parent_rate = best_parent_rate;
+ return best_rate;
+}
+
+static int clk_audio_pll_pad_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
+ u8 tmp_div, tmp_ext_div;
+ int ret;
+
+ pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n" ,
+ __func__ , rate, parent_rate);
+
+ ret = clk_audio_pll_compute_qdpad(parent_rate, rate, NULL,
+ &tmp_div, &tmp_ext_div);
+ if (!ret)
+ apad_ck->qdpad = AUDIO_PLL_DIV2QD(tmp_div, tmp_ext_div);
+
+ return ret;
+}
+
+static const struct clk_ops audio_pll_pad_ops = {
+ .enable = clk_audio_pll_pad_enable,
+ .disable = clk_audio_pll_pad_disable,
+ .recalc_rate = clk_audio_pll_pad_recalc_rate,
+ .round_rate = clk_audio_pll_pad_round_rate,
+ .set_rate = clk_audio_pll_pad_set_rate,
+};
+
+static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)
+{
+ struct clk_audio_pad *apad_ck;
+ struct clk_init_data init;
+ struct regmap *regmap;
+ const char *parent_name;
+ const char *name = np->name;
+ int ret;
+
+ parent_name = of_clk_get_parent_name(np, 0);
+
+ of_property_read_string(np, "clock-output-names", &name);
+
+ regmap = syscon_node_to_regmap(of_get_parent(np));
+ if (IS_ERR(regmap))
+ return;
+
+ apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL);
+ if (!apad_ck)
+ return;
+
+ init.name = name;
+ init.ops = &audio_pll_pad_ops;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_GATE |
+ CLK_SET_PARENT_GATE | CLK_SET_RATE_PARENT;
+
+ apad_ck->hw.init = &init;
+ apad_ck->regmap = regmap;
+ apad_ck->lock = &pmc_pcr_lock;
+
+ ret = clk_hw_register(NULL, &apad_ck->hw);
+ if (ret)
+ kfree(apad_ck);
+ else
+ of_clk_add_hw_provider(np, of_clk_hw_simple_get, &apad_ck->hw);
+
+ return;
+}
+CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
+ "atmel,sama5d2-clk-audio-pll-pad",
+ of_sama5d2_clk_audio_pll_pad_setup);
diff --git a/drivers/clk/at91/clk-audio-pll-pmc.c b/drivers/clk/at91/clk-audio-pll-pmc.c
new file mode 100644
index 000000000000..fadc51e25bac
--- /dev/null
+++ b/drivers/clk/at91/clk-audio-pll-pmc.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation,
+ * Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include "pmc.h"
+
+/*
+ * DOC: PMC output for fractional PLL clock for audio
+ *
+ * Traits of this clock:
+ * enable - clk_enable writes qdpmc, and enables PMC output
+ * rate - rate is adjustable.
+ * clk->rate = parent->rate / (qdpmc + 1)
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+#define AUDIO_PLL_FOUT_MIN 620000000
+#define AUDIO_PLL_FOUT_MAX 700000000
+#define AUDIO_PLL_REFERENCE_FOUT 660000000
+#define AUDIO_PLL_QDPMC_MAX (AT91_PMC_AUDIO_PLL_QDPMC_MASK >> \
+ AT91_PMC_AUDIO_PLL_QDPMC_OFFSET)
+struct clk_audio_pmc {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ u8 qdpmc;
+};
+
+#define to_clk_audio_pmc(hw) container_of(hw, struct clk_audio_pmc, hw)
+
+static int clk_audio_pll_pmc_enable(struct clk_hw *hw)
+{
+ struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
+
+ regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0,
+ AT91_PMC_AUDIO_PLL_PMCEN |
+ AT91_PMC_AUDIO_PLL_QDPMC_MASK,
+ AT91_PMC_AUDIO_PLL_PMCEN |
+ AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc));
+ return 0;
+}
+
+static void clk_audio_pll_pmc_disable(struct clk_hw *hw)
+{
+ struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
+
+ regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0,
+ AT91_PMC_AUDIO_PLL_PMCEN, 0);
+}
+
+static unsigned long clk_audio_pll_pmc_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
+ unsigned long apmc_rate = 0;
+
+ apmc_rate = parent_rate / (apmc_ck->qdpmc + 1);
+
+ pr_debug("A PLL/PMC: %s, apmc_rate = %lu (qdpmc = %u)\n" ,
+ __func__ , apmc_rate, apmc_ck->qdpmc);
+
+ return apmc_rate;
+}
+
+static int clk_audio_pll_compute_qdpmc(unsigned long q_rate, unsigned long rate,
+ unsigned long *qd)
+{
+ unsigned long tmp_qd;
+
+ if (!rate)
+ return -EINVAL;
+
+ tmp_qd = q_rate / rate;
+ if (!tmp_qd || tmp_qd > AUDIO_PLL_QDPMC_MAX)
+ return -EINVAL;
+
+ *qd = tmp_qd;
+ return 0;
+}
+
+static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk_hw *pclk = clk_hw_get_parent(hw);
+ long best_rate = -EINVAL;
+ unsigned long best_parent_rate = 0;
+ unsigned long tmp_qd;
+
+ pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n" ,
+ __func__ , rate, *parent_rate);
+
+ if (clk_audio_pll_compute_qdpmc(AUDIO_PLL_REFERENCE_FOUT, rate, &tmp_qd))
+ return -EINVAL;
+
+ best_parent_rate = clk_hw_round_rate(pclk, rate * tmp_qd);
+ best_rate = best_parent_rate / tmp_qd;
+
+ pr_debug("A PLL/PMC: %s, best_rate = %ld, best_parent_rate = %lu (qd = %lu)\n",
+ __func__, best_rate, best_parent_rate, tmp_qd - 1);
+
+ *parent_rate = best_parent_rate;
+ return best_rate;
+}
+
+static int clk_audio_pll_pmc_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
+ unsigned long tmp_qd;
+ int ret;
+
+ pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n" ,
+ __func__ , rate, parent_rate);
+
+ ret = clk_audio_pll_compute_qdpmc(parent_rate, rate, &tmp_qd);
+ if (!ret)
+ apmc_ck->qdpmc = tmp_qd - 1;
+
+ return ret;
+}
+
+static const struct clk_ops audio_pll_pmc_ops = {
+ .enable = clk_audio_pll_pmc_enable,
+ .disable = clk_audio_pll_pmc_disable,
+ .recalc_rate = clk_audio_pll_pmc_recalc_rate,
+ .round_rate = clk_audio_pll_pmc_round_rate,
+ .set_rate = clk_audio_pll_pmc_set_rate,
+};
+
+static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)
+{
+ struct clk_audio_pmc *apmc_ck;
+ struct clk_init_data init;
+ struct regmap *regmap;
+ const char *parent_name;
+ const char *name = np->name;
+ int ret;
+
+ parent_name = of_clk_get_parent_name(np, 0);
+
+ of_property_read_string(np, "clock-output-names", &name);
+
+ regmap = syscon_node_to_regmap(of_get_parent(np));
+ if (IS_ERR(regmap))
+ return;
+
+ apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL);
+ if (!apmc_ck)
+ return;
+
+ init.name = name;
+ init.ops = &audio_pll_pmc_ops;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_GATE |
+ CLK_SET_PARENT_GATE | CLK_SET_RATE_PARENT;
+
+ apmc_ck->hw.init = &init;
+ apmc_ck->regmap = regmap;
+
+ ret = clk_hw_register(NULL, &apmc_ck->hw);
+ if (ret)
+ kfree(apmc_ck);
+ else
+ of_clk_add_hw_provider(np, of_clk_hw_simple_get, &apmc_ck->hw);
+
+ return;
+}
+CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
+ "atmel,sama5d2-clk-audio-pll-pmc",
+ of_sama5d2_clk_audio_pll_pmc_setup);
diff --git a/drivers/clk/at91/clk-audio-pll.c b/drivers/clk/at91/clk-audio-pll.c
new file mode 100644
index 000000000000..76261bcb204f
--- /dev/null
+++ b/drivers/clk/at91/clk-audio-pll.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2016 Atmel Corporation,
+ * Songjun Wu <songjun.wu@atmel.com>,
+ * Nicolas Ferre <nicolas.ferre@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
+#include <linux/of.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include "pmc.h"
+
+/*
+ * DOC: Fractional PLL clock for audio
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare puts audio PLL in reset state
+ * enable - clk_enable writes nd, fracr parameters and enables PLL
+ * rate - rate is adjustable.
+ * clk->rate = parent->rate * ((nd + 1) + (fracr / 2^22))
+ * parent - fixed parent. No clk_set_parent support
+ */
+
+#define AUDIO_PLL_DIV_FRAC (1 << 22)
+#define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \
+ AT91_PMC_AUDIO_PLL_ND_OFFSET)
+
+struct clk_audio_frac {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ spinlock_t *lock;
+ u32 fracr;
+ u8 nd;
+};
+
+#define to_clk_audio_frac(hw) container_of(hw, struct clk_audio_frac, hw)
+
+/* make sure that pll is in reset state beforehand */
+static int clk_audio_pll_prepare(struct clk_hw *hw)
+{
+ struct clk_audio_frac *fck = to_clk_audio_frac(hw);
+
+ regmap_update_bits(fck->regmap, AT91_PMC_AUDIO_PLL0,
+ AT91_PMC_AUDIO_PLL_RESETN, 0);
+ return 0;
+}
+
+static void clk_audio_pll_unprepare(struct clk_hw *hw)
+{
+ clk_audio_pll_prepare(hw);
+}
+
+static int clk_audio_pll_enable(struct clk_hw *hw)
+{
+ struct clk_audio_frac *fck = to_clk_audio_frac(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(fck->lock, flags);
+ regmap_update_bits(fck->regmap, AT91_PMC_AUDIO_PLL0,
+ AT91_PMC_AUDIO_PLL_RESETN,
+ AT91_PMC_AUDIO_PLL_RESETN);
+ regmap_update_bits(fck->regmap, AT91_PMC_AUDIO_PLL1,
+ AT91_PMC_AUDIO_PLL_FRACR_MASK, fck->fracr);
+
+ /*
+ * reset and enable have to be done in 2 separated writes
+ * for AT91_PMC_AUDIO_PLL0
+ */
+ regmap_update_bits(fck->regmap, AT91_PMC_AUDIO_PLL0,
+ AT91_PMC_AUDIO_PLL_PLLEN |
+ AT91_PMC_AUDIO_PLL_ND_MASK,
+ AT91_PMC_AUDIO_PLL_PLLEN |
+ AT91_PMC_AUDIO_PLL_ND(fck->nd));
+ spin_unlock_irqrestore(fck->lock, flags);
+ return 0;
+}
+
+static void clk_audio_pll_disable(struct clk_hw *hw)
+{
+ struct clk_audio_frac *fck = to_clk_audio_frac(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(fck->lock, flags);
+ regmap_update_bits(fck->regmap, AT91_PMC_AUDIO_PLL0,
+ AT91_PMC_AUDIO_PLL_PLLEN, 0);
+ /* do it in 2 separated writes */
+ regmap_update_bits(fck->regmap, AT91_PMC_AUDIO_PLL0,
+ AT91_PMC_AUDIO_PLL_RESETN, 0);
+ spin_unlock_irqrestore(fck->lock, flags);
+}
+
+static unsigned long clk_audio_pll_fout(unsigned long parent_rate,
+ unsigned long nd, unsigned long fracr)
+{
+ unsigned long long fr = (unsigned long long)parent_rate *
+ (unsigned long long)fracr;
+
+ pr_debug("A PLL: %s, fr = %llu\n" ,
+ __func__ , fr);
+
+ fr = DIV_ROUND_CLOSEST_ULL(fr, AUDIO_PLL_DIV_FRAC);
+
+ pr_debug("A PLL: %s, fr = %llu\n" ,
+ __func__ , fr);
+
+ return parent_rate * (nd + 1) + fr;
+}
+
+static unsigned long clk_audio_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_audio_frac *fck = to_clk_audio_frac(hw);
+ unsigned long fout;
+
+ fout = clk_audio_pll_fout(parent_rate, fck->nd, fck->fracr);
+
+ pr_debug("A PLL: %s, fout = %lu (nd = %u, fracr = %lu)\n" ,
+ __func__ , fout, fck->nd, (unsigned long)fck->fracr);
+
+ return fout;
+}
+
+static int clk_audio_pll_compute_frac(unsigned long rate, unsigned long parent_rate,
+ unsigned long *nd, unsigned long *fracr)
+{
+ unsigned long long tmp;
+ unsigned long long r;
+
+ if (!rate)
+ return -EINVAL;
+
+ tmp = rate;
+ r = do_div(tmp, parent_rate);
+ if (tmp == 0 || (tmp - 1) > AUDIO_PLL_ND_MAX)
+ return -EINVAL;
+
+ *nd = tmp - 1;
+
+ tmp = r * AUDIO_PLL_DIV_FRAC;
+ tmp = DIV_ROUND_CLOSEST_ULL(tmp, parent_rate);
+ if (tmp > AT91_PMC_AUDIO_PLL_FRACR_MASK)
+ return -EINVAL;
+
+ /* we can cast here as we verified the bounds just above */
+ *fracr = (unsigned long)tmp;
+
+ return 0;
+}
+
+static long clk_audio_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ long best_rate = -EINVAL;
+ unsigned long fracr;
+ unsigned long nd;
+ int ret;
+
+ pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n" ,
+ __func__ , rate, *parent_rate);
+
+ ret = clk_audio_pll_compute_frac(rate, *parent_rate, &nd, &fracr);
+ if (ret)
+ return ret;
+
+ best_rate = clk_audio_pll_fout(*parent_rate, nd, fracr);
+
+ pr_debug("A PLL: %s, best_rate = %lu (nd = %lu, fracr = %lu)\n" ,
+ __func__ , best_rate, nd, fracr);
+
+ return best_rate;
+}
+
+static int clk_audio_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_audio_frac *fck = to_clk_audio_frac(hw);
+ unsigned long fracr;
+ unsigned long nd;
+ int ret;
+
+ pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n" ,
+ __func__ , rate, parent_rate);
+
+ ret = clk_audio_pll_compute_frac(rate, parent_rate, &nd, &fracr);
+ if (ret)
+ return ret;
+
+ fck->nd = nd;
+ fck->fracr = fracr;
+
+ return 0;
+}
+
+static const struct clk_ops audio_pll_ops = {
+ .prepare = clk_audio_pll_prepare,
+ .unprepare = clk_audio_pll_unprepare,
+ .enable = clk_audio_pll_enable,
+ .disable = clk_audio_pll_disable,
+ .recalc_rate = clk_audio_pll_recalc_rate,
+ .round_rate = clk_audio_pll_round_rate,
+ .set_rate = clk_audio_pll_set_rate,
+};
+
+static void __init of_sama5d2_clk_audio_pll_setup(struct device_node *np)
+{
+ struct clk_audio_frac *fck;
+ struct clk_init_data init;
+ struct regmap *regmap;
+ const char *parent_name;
+ const char *name = np->name;
+ int ret;
+
+ parent_name = of_clk_get_parent_name(np, 0);
+
+ of_property_read_string(np, "clock-output-names", &name);
+
+ regmap = syscon_node_to_regmap(of_get_parent(np));
+ if (IS_ERR(regmap))
+ return;
+
+ fck = kzalloc(sizeof(*fck), GFP_KERNEL);
+ if (!fck)
+ return;
+
+ init.name = name;
+ init.ops = &audio_pll_ops;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_GATE;
+
+ fck->hw.init = &init;
+ fck->regmap = regmap;
+ fck->lock = &pmc_pcr_lock;
+
+ ret = clk_hw_register(NULL, &fck->hw);
+ if (ret)
+ kfree(fck);
+ else
+ of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fck->hw);
+
+ return;
+}
+CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_setup,
+ "atmel,sama5d2-clk-audio-pll-frac",
+ of_sama5d2_clk_audio_pll_setup);
diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h
index 17f413bbbedf..6aca5ce8a99a 100644
--- a/include/linux/clk/at91_pmc.h
+++ b/include/linux/clk/at91_pmc.h
@@ -185,4 +185,29 @@
#define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */
#define AT91_PMC_PCR_GCKEN (0x1 << 29) /* GCK Enable */
+#define AT91_PMC_AUDIO_PLL0 0x14c
+#define AT91_PMC_AUDIO_PLL_PLLEN (1 << 0)
+#define AT91_PMC_AUDIO_PLL_PADEN (1 << 1)
+#define AT91_PMC_AUDIO_PLL_PMCEN (1 << 2)
+#define AT91_PMC_AUDIO_PLL_RESETN (1 << 3)
+#define AT91_PMC_AUDIO_PLL_ND_OFFSET 8
+#define AT91_PMC_AUDIO_PLL_ND_MASK (0x7f << AT91_PMC_AUDIO_PLL_ND_OFFSET)
+#define AT91_PMC_AUDIO_PLL_ND(n) ((n) << AT91_PMC_AUDIO_PLL_ND_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPMC_OFFSET 16
+#define AT91_PMC_AUDIO_PLL_QDPMC_MASK (0x7f << AT91_PMC_AUDIO_PLL_QDPMC_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPMC(n) ((n) << AT91_PMC_AUDIO_PLL_QDPMC_OFFSET)
+
+#define AT91_PMC_AUDIO_PLL1 0x150
+#define AT91_PMC_AUDIO_PLL_FRACR_MASK 0x3fffff
+#define AT91_PMC_AUDIO_PLL_QDPAD_OFFSET 24
+#define AT91_PMC_AUDIO_PLL_QDPAD_MASK (0x7f << AT91_PMC_AUDIO_PLL_QDPAD_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPAD(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET AT91_PMC_AUDIO_PLL_QDPAD_OFFSET
+#define AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK (0x3 << AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPAD_DIV(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET 26
+#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX 0x1f
+#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK (AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX << AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET)
+
#endif
--
2.9.0
^ permalink raw reply related
* [RFC PATCH 0/3] clk: at91: audio PLL clock
From: Nicolas Ferre @ 2016-12-06 10:55 UTC (permalink / raw)
To: linux-arm-kernel
This series covers the addition of the Audio PLL clock found on AT91 SoCs like
the SAMA5D2.
I also added the use of these clocks by the ClassD audi amplifier in both SoC
and board DT.
The Audio PLL is described in the sama5d2 datasheet chapter "29.8 Audio PLL".
Even if "it works" (!), note that I'm not satisfied with the current code and
would need some advice from people more accustomed with the CCF and
particularly composite audio PLL/clocks like these. For example, I do not take
into account the limits of these clocks (as described in the datasheet) and the
dependency between the PAD and the PMC child clocks.
Thanks in advance for your inputs.
Best regards,
Nicolas
Cyrille Pitchen (2):
ARM: dts: at91: sama5d2: add classd nodes
ARM: dts: at91: sama5d2_xplained: add pin muxing and enable classd
Nicolas Ferre (1):
clk: at91: add audio pll clock driver
.../devicetree/bindings/clock/at91-clock.txt | 10 +
arch/arm/boot/dts/at91-sama5d2_xplained.dts | 16 ++
arch/arm/boot/dts/sama5d2.dtsi | 39 +++-
arch/arm/mach-at91/Kconfig | 4 +
drivers/clk/at91/Makefile | 2 +
drivers/clk/at91/clk-audio-pll-pad.c | 238 +++++++++++++++++++
drivers/clk/at91/clk-audio-pll-pmc.c | 184 +++++++++++++++
drivers/clk/at91/clk-audio-pll.c | 253 +++++++++++++++++++++
include/linux/clk/at91_pmc.h | 25 ++
9 files changed, 770 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/at91/clk-audio-pll-pad.c
create mode 100644 drivers/clk/at91/clk-audio-pll-pmc.c
create mode 100644 drivers/clk/at91/clk-audio-pll.c
--
2.9.0
^ permalink raw reply
* [PATCH v2 0/3] ARM: dts: imx6: Support Poslab Savageboard dual & quad
From: Milo Kim @ 2016-12-06 10:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5APWxuRmo5=QgNskxtmU-UN-P1pR1kFMZkHFMb2BPrJBQ@mail.gmail.com>
On 12/06/2016 06:42 PM, Fabio Estevam wrote:
> You missed to add imx6q-savageboard.dtb and imx6dl-savageboard.dtb
> entries into arch/arm/boot/dts/Makefile
Oh, I didn't notice because I build the dtbs manually.
Thanks for catching this.
And do you think other patches look OK?
Best regards,
Milo
^ permalink raw reply
* [PATCH v3 0/4] mm: fix the "counter.sh" failure for libhugetlbfs
From: Huang Shijie @ 2016-12-06 10:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161205093100.GF30758@dhcp22.suse.cz>
On Mon, Dec 05, 2016 at 05:31:01PM +0800, Michal Hocko wrote:
> On Mon 05-12-16 17:17:07, Huang Shijie wrote:
> [...]
> > The failure is caused by:
> > 1) kernel fails to allocate a gigantic page for the surplus case.
> > And the gather_surplus_pages() will return NULL in the end.
> >
> > 2) The condition checks for some functions are wrong:
> > return_unused_surplus_pages()
> > nr_overcommit_hugepages_store()
> > hugetlb_overcommit_handler()
>
> OK, so how is this any different from gigantic (1G) hugetlb pages on
I think there is no different from gigantic (1G) hugetlb pages on
x86_64. Do anyone ever tested the 1G hugetlb pages in x86_64 with the "counter.sh"
before?
> x86_64? Do we need the same functionality or is it just 32MB not being
> handled in the same way as 1G?
Yes, we need this functionality for gigantic pages, no matter it is
X86_64 or S390 or arm64, no matter it is 32MB or 1G. :)
But anyway, I will try to find some machine and try the 1G gigantic page
on ARM64.
Thanks
Huang Shijie
^ permalink raw reply
* [PATCH v5] ARM: davinci: da8xx: Fix sleeping function called from invalid context
From: Sekhar Nori @ 2016-12-06 9:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cbf4b99b-e453-acd5-d864-f709708fbab0@baylibre.com>
On Tuesday 06 December 2016 03:21 PM, Alexandre Bailon wrote:
> On 12/06/2016 10:33 AM, Sekhar Nori wrote:
>> On Monday 05 December 2016 07:43 PM, Alexandre Bailon wrote:
>>> Everytime the usb20 phy is enabled, there is a
>>> "sleeping function called from invalid context" BUG.
>>>
>>> clk_enable() from arch/arm/mach-davinci/clock.c uses spin_lock_irqsave()
>>> before to invoke the callback usb20_phy_clk_enable().
>>> usb20_phy_clk_enable() uses clk_get() and clk_enable_prepapre()
>>> which may sleep.
>>> Move clk_get() to da8xx_register_usb20_phy_clk() and
>>> replace clk_prepare_enable() by clk_enable().
>>>
>>> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
>>
>> This will still cause the recursive locking problem reported by David.
>> Not sure what the point of sending this version was.
>>
>> Thanks,
>> Sekhar
>>
> What am I supposed to do ?
That needs to be resolved between you and David. Perhaps convert the fix
sent by David into a proper patch and base this patch on that. Or wait
for David to send it himself and let him also make the modifications
needed in this patch.
David ?
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v3 7/7] ARM: dts: stm32: add stm32 general purpose timer driver in DT
From: Alexandre Torgue @ 2016-12-06 9:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161206094835.GB25385@dell.home>
Hi Lee,
On 12/06/2016 10:48 AM, Lee Jones wrote:
> On Mon, 05 Dec 2016, Alexandre Torgue wrote:
>> On 12/02/2016 02:22 PM, Lee Jones wrote:
>>> On Fri, 02 Dec 2016, Benjamin Gaignard wrote:
>>>
>>>> Add general purpose timers and it sub-nodes into DT for stm32f4.
>>>> Define and enable pwm1 and pwm3 for stm32f469 discovery board
>>>>
>>>> version 3:
>>>> - use "st,stm32-timer-trigger" in DT
>>>>
>>>> version 2:
>>>> - use parameters to describe hardware capabilities
>>>> - do not use references for pwm and iio timer subnodes
>>>>
>>>> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
>>>> ---
>>>> arch/arm/boot/dts/stm32f429.dtsi | 333 +++++++++++++++++++++++++++++++++-
>>>> arch/arm/boot/dts/stm32f469-disco.dts | 28 +++
>>>> 2 files changed, 360 insertions(+), 1 deletion(-)
>
> [...]
>
> If you're only commenting on a little piece of the patch, it's always
> a good idea to trim the rest.
>
>>>> diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
>>>> index 8a163d7..df4ca7e 100644
>>>> --- a/arch/arm/boot/dts/stm32f469-disco.dts
>>>> +++ b/arch/arm/boot/dts/stm32f469-disco.dts
>>>> @@ -81,3 +81,31 @@
>>>> &usart3 {
>>>> status = "okay";
>>>> };
>>>> +
>>>> +&gptimer1 {
>>>> + status = "okay";
>>>> +
>>>> + pwm1 at 0 {
>>>> + pinctrl-0 = <&pwm1_pins>;
>>>> + pinctrl-names = "default";
>>>> + status = "okay";
>>>> + };
>>>> +
>>>> + timer1 at 0 {
>>>> + status = "okay";
>>>> + };
>>>> +};
>>>
>>> This is a much *better* format than before.
>>>
>>> I still don't like the '&' syntax though.
>>
>> Please keep "&" format to match with existing nodes.
>
> Right. I wasn't suggesting that he differs from the current format in
> *this* set. I am suggesting that we change the format in a subsequent
> set though.
Why change? Looking at Linux ARM kernel patchwork, new DT board file
contains this format. Did you already discuss with Arnd or Olof about it
?
regards
Alex
>
>>>> +&gptimer3 {
>>>> + status = "okay";
>>>> +
>>>> + pwm3 at 0 {
>>>> + pinctrl-0 = <&pwm3_pins>;
>>>> + pinctrl-names = "default";
>>>> + status = "okay";
>>>> + };
>>>> +
>>>> + timer3 at 0 {
>>>> + status = "okay";
>>>> + };
>>>> +};
>>>
>
^ permalink raw reply
* [bug report v4.8] fs/locks.c: kernel oops during posix lock stress test
From: Ming Lei @ 2016-12-06 9:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201113031.GB5813@arm.com>
Hi Will,
On Thu, Dec 1, 2016 at 7:30 PM, Will Deacon <will.deacon@arm.com> wrote:
> On Mon, Nov 28, 2016 at 11:10:14AM +0800, Ming Lei wrote:
>> When I run stress-ng via the following steps on one ARM64 dual
>> socket system(Cavium Thunder), the kernel oops[1] can often be
>> triggered after running the stress test for several hours(sometimes
>> it may take longer):
>>
>> - git clone git://kernel.ubuntu.com/cking/stress-ng.git
>> - apply the attachment patch which just makes the posix file
>> lock stress test more aggressive
>> - run the test via '~/git/stress-ng$./stress-ng --lockf 128 --aggressive'
>>
>>
>> From the oops log, looks one garbage file_lock node is got
>> from the linked list of 'ctx->flc_posix' when the issue happens.
>>
>> BTW, the issue isn't observed on single socket Cavium Thunder yet,
>> and the same issue can be seen on Ubuntu Xenial(v4.4 based kernel)
>> too.
>
> FWIW, I've been running this on Seattle for 24 hours with your patch applied
> and not seen any problems yet. That said, Thomas did just fix an rt_mutex
> race which only seemed to pop up on Thunder, so you could give those
> patches a try.
>
> https://lkml.kernel.org/r/20161130205431.629977871 at linutronix.de
I applied the patch against Ubuntu Yakkety kernel(v4.8 based), and run
the test again on one dual-socket Cavium ThunderX system, and the
issue can still be triggered.
So looks not a same issue with David Daney's.
Anyway, thank you for providing this input!
Thanks,
Ming
^ permalink raw reply
* [PATCH v5] ARM: davinci: da8xx: Fix sleeping function called from invalid context
From: Alexandre Bailon @ 2016-12-06 9:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2fc7a4ef-02ad-fc15-66ea-9f75756086f8@ti.com>
On 12/06/2016 10:33 AM, Sekhar Nori wrote:
> On Monday 05 December 2016 07:43 PM, Alexandre Bailon wrote:
>> Everytime the usb20 phy is enabled, there is a
>> "sleeping function called from invalid context" BUG.
>>
>> clk_enable() from arch/arm/mach-davinci/clock.c uses spin_lock_irqsave()
>> before to invoke the callback usb20_phy_clk_enable().
>> usb20_phy_clk_enable() uses clk_get() and clk_enable_prepapre()
>> which may sleep.
>> Move clk_get() to da8xx_register_usb20_phy_clk() and
>> replace clk_prepare_enable() by clk_enable().
>>
>> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
>
> This will still cause the recursive locking problem reported by David.
> Not sure what the point of sending this version was.
>
> Thanks,
> Sekhar
>
What am I supposed to do ?
Thanks,
Alexandre
^ permalink raw reply
* [PATCH v3 7/7] ARM: dts: stm32: add stm32 general purpose timer driver in DT
From: Lee Jones @ 2016-12-06 9:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e15186cb-a93e-c2e7-13bb-6704be5e8949@st.com>
On Mon, 05 Dec 2016, Alexandre Torgue wrote:
> On 12/02/2016 02:22 PM, Lee Jones wrote:
> > On Fri, 02 Dec 2016, Benjamin Gaignard wrote:
> >
> > > Add general purpose timers and it sub-nodes into DT for stm32f4.
> > > Define and enable pwm1 and pwm3 for stm32f469 discovery board
> > >
> > > version 3:
> > > - use "st,stm32-timer-trigger" in DT
> > >
> > > version 2:
> > > - use parameters to describe hardware capabilities
> > > - do not use references for pwm and iio timer subnodes
> > >
> > > Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
> > > ---
> > > arch/arm/boot/dts/stm32f429.dtsi | 333 +++++++++++++++++++++++++++++++++-
> > > arch/arm/boot/dts/stm32f469-disco.dts | 28 +++
> > > 2 files changed, 360 insertions(+), 1 deletion(-)
[...]
If you're only commenting on a little piece of the patch, it's always
a good idea to trim the rest.
> > > diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
> > > index 8a163d7..df4ca7e 100644
> > > --- a/arch/arm/boot/dts/stm32f469-disco.dts
> > > +++ b/arch/arm/boot/dts/stm32f469-disco.dts
> > > @@ -81,3 +81,31 @@
> > > &usart3 {
> > > status = "okay";
> > > };
> > > +
> > > +&gptimer1 {
> > > + status = "okay";
> > > +
> > > + pwm1 at 0 {
> > > + pinctrl-0 = <&pwm1_pins>;
> > > + pinctrl-names = "default";
> > > + status = "okay";
> > > + };
> > > +
> > > + timer1 at 0 {
> > > + status = "okay";
> > > + };
> > > +};
> >
> > This is a much *better* format than before.
> >
> > I still don't like the '&' syntax though.
>
> Please keep "&" format to match with existing nodes.
Right. I wasn't suggesting that he differs from the current format in
*this* set. I am suggesting that we change the format in a subsequent
set though.
> > > +&gptimer3 {
> > > + status = "okay";
> > > +
> > > + pwm3 at 0 {
> > > + pinctrl-0 = <&pwm3_pins>;
> > > + pinctrl-names = "default";
> > > + status = "okay";
> > > + };
> > > +
> > > + timer3 at 0 {
> > > + status = "okay";
> > > + };
> > > +};
> >
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH] ACPI/IORT: Make dma masks set-up IORT specific
From: Will Deacon @ 2016-12-06 9:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161205122619.25045-1-lorenzo.pieralisi@arm.com>
On Mon, Dec 05, 2016 at 12:26:19PM +0000, Lorenzo Pieralisi wrote:
> The introduction of acpi_dma_configure() allows to configure DMA
> and related IOMMU for any device that is DMA capable. To achieve
> that goal it ensures DMA masks are set-up to sane default values
> before proceeding with IOMMU and DMA ops configuration.
>
> On x86/ia64 systems, through acpi_bind_one(), acpi_dma_configure() is
> called for every device that has an ACPI companion, in that every device
> is considered DMA capable on x86/ia64 systems (ie acpi_get_dma_attr() API),
> which has the side effect of initializing dma masks also for
> pseudo-devices (eg CPUs and memory nodes) and potentially for devices
> whose dma masks were not set-up before the acpi_dma_configure() API was
> introduced, which may have noxious side effects.
>
> Therefore, in preparation for IORT firmware specific DMA masks set-up,
> wrap the default DMA masks set-up in acpi_dma_configure() inside an IORT
> specific wrapper that reverts to a NOP on x86/ia64 systems, restoring the
> default expected behaviour on x86/ia64 systems and keeping DMA default
> masks set-up on IORT based (ie ARM) arch configurations.
>
> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Cc: Tomasz Nowicki <tn@semihalf.com>
> Cc: Joerg Roedel <joro@8bytes.org>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> Cc: Sricharan R <sricharan@codeaurora.org>
> ---
> Joerg,
>
> pending Rafael's ACK on it, given the 4.10 release timing and that the
> series is queued via the IOMMU tree please consider applying this patch to
> your arm/smmu branch for 4.10, it is not fixing a bug but it is modifying
> the x86/ia64 code path; I prefer preventing any issue related to default
> dma masks on x86/ia64 so I hope it can get merged along with the rest of
> the ACPI IORT SMMU series.
>
> Thanks a lot and apologies,
> Lorenzo
>
> drivers/acpi/arm64/iort.c | 22 ++++++++++++++++++++++
> drivers/acpi/scan.c | 14 +-------------
> include/linux/acpi_iort.h | 2 ++
> 3 files changed, 25 insertions(+), 13 deletions(-)
Looks straightforward to me:
Acked-by: Will Deacon <will.deacon@arm.com>
Joerg can probably just pick this on top of his queue.
Will
^ permalink raw reply
* [PATCH v2 0/3] ARM: dts: imx6: Support Poslab Savageboard dual & quad
From: Fabio Estevam @ 2016-12-06 9:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161206070829.24098-1-woogyom.kim@gmail.com>
Hi Milo,
On Tue, Dec 6, 2016 at 5:08 AM, Milo Kim <woogyom.kim@gmail.com> wrote:
> Poslab Savageboard is i.MX6 SoC base, but BSP code from the vendor is
> not mainline u-boot and kernel. Personal reason of using this board is
> testing etnaviv user-space driver, so I re-write device tree files based on
> mainline kernel for the first step.
>
> This patchset includes common DT file, dual and quad board files.
>
> Supported components are
> - Display: HDMI and LVDS panel
> - eMMC and SD card
> - Ethernet
> - Pinmux configuration
> - SATA: only for Savageboard quad
> - UART1 for debug console
> - USB host
>
> Missing features are
> - Audio (WM8903)
> - USB OTG
> - PMIC WM8326: default settings are used so no issue to bring-up the system
> - MIPI DSI, CSI
>
> Patches are tested on the Savageboard quad but the dual version should work
> because the only difference between dual and quad is SATA support.
>
> More information in http://www.savageboard.org
>
> v2:
> Fix DT node for regulator, phy-reset-gpios and iomuxc node.
>
> Milo Kim (3):
> ARM: dts: imx6: Add Savageboard common file
> ARM: dts: imx6: Support Savageboard dual
> ARM: dts: imx6: Support Savageboard quad
>
> arch/arm/boot/dts/imx6dl-savageboard.dts | 50 ++++++
> arch/arm/boot/dts/imx6q-savageboard.dts | 54 ++++++
> arch/arm/boot/dts/imx6qdl-savageboard.dtsi | 262 +++++++++++++++++++++++++++++
You missed to add imx6q-savageboard.dtb and imx6dl-savageboard.dtb
entries into arch/arm/boot/dts/Makefile
^ permalink raw reply
* [PATCH] ACPI/IORT: Make dma masks set-up IORT specific
From: Lorenzo Pieralisi @ 2016-12-06 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAJZ5v0hbc61=QCYDgHZ_KbxR7VkSSWrHVGvU47fG6hsQrSJKhw@mail.gmail.com>
Hi Joerg,
On Mon, Dec 05, 2016 at 11:18:56PM +0100, Rafael J. Wysocki wrote:
> On Mon, Dec 5, 2016 at 1:26 PM, Lorenzo Pieralisi
> <lorenzo.pieralisi@arm.com> wrote:
> > The introduction of acpi_dma_configure() allows to configure DMA
> > and related IOMMU for any device that is DMA capable. To achieve
> > that goal it ensures DMA masks are set-up to sane default values
> > before proceeding with IOMMU and DMA ops configuration.
> >
> > On x86/ia64 systems, through acpi_bind_one(), acpi_dma_configure() is
> > called for every device that has an ACPI companion, in that every device
> > is considered DMA capable on x86/ia64 systems (ie acpi_get_dma_attr() API),
> > which has the side effect of initializing dma masks also for
> > pseudo-devices (eg CPUs and memory nodes) and potentially for devices
> > whose dma masks were not set-up before the acpi_dma_configure() API was
> > introduced, which may have noxious side effects.
> >
> > Therefore, in preparation for IORT firmware specific DMA masks set-up,
> > wrap the default DMA masks set-up in acpi_dma_configure() inside an IORT
> > specific wrapper that reverts to a NOP on x86/ia64 systems, restoring the
> > default expected behaviour on x86/ia64 systems and keeping DMA default
> > masks set-up on IORT based (ie ARM) arch configurations.
> >
> > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Hanjun Guo <hanjun.guo@linaro.org>
> > Cc: Bjorn Helgaas <bhelgaas@google.com>
> > Cc: Robin Murphy <robin.murphy@arm.com>
> > Cc: Tomasz Nowicki <tn@semihalf.com>
> > Cc: Joerg Roedel <joro@8bytes.org>
> > Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> > Cc: Sricharan R <sricharan@codeaurora.org>
>
> Acked -by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> > ---
> > Joerg,
> >
> > pending Rafael's ACK on it, given the 4.10 release timing and that the
> > series is queued via the IOMMU tree please consider applying this patch to
> > your arm/smmu branch for 4.10, it is not fixing a bug but it is modifying
> > the x86/ia64 code path; I prefer preventing any issue related to default
> > dma masks on x86/ia64 so I hope it can get merged along with the rest of
> > the ACPI IORT SMMU series.
I can apply Rafael and Hanjun's tags and resend a v2 to you if you
prefer, it would be great if you could apply this patch to your arm/smmu
branch for v4.10 as per description above, please let me know.
Thank you !
Lorenzo
> >
> > Thanks a lot and apologies,
> > Lorenzo
> >
> > drivers/acpi/arm64/iort.c | 22 ++++++++++++++++++++++
> > drivers/acpi/scan.c | 14 +-------------
> > include/linux/acpi_iort.h | 2 ++
> > 3 files changed, 25 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> > index 47bace8..e0d2e6e 100644
> > --- a/drivers/acpi/arm64/iort.c
> > +++ b/drivers/acpi/arm64/iort.c
> > @@ -547,6 +547,28 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
> > }
> >
> > /**
> > + * iort_set_dma_mask - Set-up dma mask for a device.
> > + *
> > + * @dev: device to configure
> > + */
> > +void iort_set_dma_mask(struct device *dev)
> > +{
> > + /*
> > + * Set default coherent_dma_mask to 32 bit. Drivers are expected to
> > + * setup the correct supported mask.
> > + */
> > + if (!dev->coherent_dma_mask)
> > + dev->coherent_dma_mask = DMA_BIT_MASK(32);
> > +
> > + /*
> > + * Set it to coherent_dma_mask by default if the architecture
> > + * code has not set it.
> > + */
> > + if (!dev->dma_mask)
> > + dev->dma_mask = &dev->coherent_dma_mask;
> > +}
> > +
> > +/**
> > * iort_iommu_configure - Set-up IOMMU configuration for a device.
> > *
> > * @dev: device to configure
> > diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> > index 80698d3..93b00cf 100644
> > --- a/drivers/acpi/scan.c
> > +++ b/drivers/acpi/scan.c
> > @@ -1380,19 +1380,7 @@ void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
> > {
> > const struct iommu_ops *iommu;
> >
> > - /*
> > - * Set default coherent_dma_mask to 32 bit. Drivers are expected to
> > - * setup the correct supported mask.
> > - */
> > - if (!dev->coherent_dma_mask)
> > - dev->coherent_dma_mask = DMA_BIT_MASK(32);
> > -
> > - /*
> > - * Set it to coherent_dma_mask by default if the architecture
> > - * code has not set it.
> > - */
> > - if (!dev->dma_mask)
> > - dev->dma_mask = &dev->coherent_dma_mask;
> > + iort_set_dma_mask(dev);
> >
> > iommu = iort_iommu_configure(dev);
> >
> > diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> > index dcb2b60..77e0809 100644
> > --- a/include/linux/acpi_iort.h
> > +++ b/include/linux/acpi_iort.h
> > @@ -35,6 +35,7 @@ bool iort_node_match(u8 type);
> > u32 iort_msi_map_rid(struct device *dev, u32 req_id);
> > struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
> > /* IOMMU interface */
> > +void iort_set_dma_mask(struct device *dev);
> > const struct iommu_ops *iort_iommu_configure(struct device *dev);
> > #else
> > static inline void acpi_iort_init(void) { }
> > @@ -45,6 +46,7 @@ static inline struct irq_domain *iort_get_device_domain(struct device *dev,
> > u32 req_id)
> > { return NULL; }
> > /* IOMMU interface */
> > +static inline void iort_set_dma_mask(struct device *dev) { }
> > static inline
> > const struct iommu_ops *iort_iommu_configure(struct device *dev)
> > { return NULL; }
> > --
> > 2.10.0
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 14/18] arm64: signal32: move ilp32 and aarch32 common code to separated file
From: Yury Norov @ 2016-12-06 9:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161205161823.GF14429@e104818-lin.cambridge.arm.com>
On Mon, Dec 05, 2016 at 04:18:24PM +0000, Catalin Marinas wrote:
> On Fri, Oct 21, 2016 at 11:33:13PM +0300, Yury Norov wrote:
> > Signed-off-by: Yury Norov <ynorov@caviumnetworks.com>
>
> Please add some description, even if it means copying the subject.
>
> > ---
> > arch/arm64/include/asm/signal32.h | 3 +
> > arch/arm64/include/asm/signal32_common.h | 27 +++++++
> > arch/arm64/kernel/Makefile | 2 +-
> > arch/arm64/kernel/signal32.c | 107 ------------------------
> > arch/arm64/kernel/signal32_common.c | 135 +++++++++++++++++++++++++++++++
> > 5 files changed, 166 insertions(+), 108 deletions(-)
> > create mode 100644 arch/arm64/include/asm/signal32_common.h
> > create mode 100644 arch/arm64/kernel/signal32_common.c
>
> I wonder whether you can make such patches more readable by setting
> "diff.renames" to "copy" in your gitconfig (unless it's set already and
> Git cannot detect partial file code moving/copying).
I tried "git format-patch -C --find-copies-harder" - the same result.
Yury
^ permalink raw reply
* [PATCH] ARM: dts: da850: enable high speed for mmc
From: Sekhar Nori @ 2016-12-06 9:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161201141041.31386-1-ahaslam@baylibre.com>
On Thursday 01 December 2016 07:40 PM, Axel Haslam wrote:
> The mmc controller in da850 supports high speed modes
> so add cap-sd-highspeed and cap-mmc-highspeed.
>
> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
Forgot to reply earlier, but this was applied.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v5] ARM: davinci: da8xx: Fix sleeping function called from invalid context
From: Sekhar Nori @ 2016-12-06 9:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480947224-26222-1-git-send-email-abailon@baylibre.com>
On Monday 05 December 2016 07:43 PM, Alexandre Bailon wrote:
> Everytime the usb20 phy is enabled, there is a
> "sleeping function called from invalid context" BUG.
>
> clk_enable() from arch/arm/mach-davinci/clock.c uses spin_lock_irqsave()
> before to invoke the callback usb20_phy_clk_enable().
> usb20_phy_clk_enable() uses clk_get() and clk_enable_prepapre()
> which may sleep.
> Move clk_get() to da8xx_register_usb20_phy_clk() and
> replace clk_prepare_enable() by clk_enable().
>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
This will still cause the recursive locking problem reported by David.
Not sure what the point of sending this version was.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH 1/1] arm/module: maximum utilization of module area.
From: Ard Biesheuvel @ 2016-12-06 9:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481012975-44478-1-git-send-email-maninder1.s@samsung.com>
On 6 December 2016 at 08:29, Maninder Singh <maninder1.s@samsung.com> wrote:
> This patch defines new macro MODULE_START to ensure kernel text
> and module remains within 32 MB of address range.
>
> Tried this patch by inserting 20 MB size module on 4.1 kernel:-
>
> Earlier:-
> ==========
> sh# insmod size.ko
> ....
> insmod: ERROR: could not insert module size.ko: Cannot allocate memory
> sh#
>
> With this patch
> ===============
> sh# insmod size.ko
> ...
> sh# lsmod
> Module Size Used by
> size 20972425 0
>
> Signed-off-by: Vaneet Narang <v.narang@samsung.com>
> Signed-off-by: Maninder Singh <maninder1.s@samsung.com>
> Reviewed-by: Ajeet Yadav <ajeet.y@samsung.com>
> ---
> arch/arm/include/asm/memory.h | 4 ++--
> arch/arm/kernel/module.c | 9 ++++++++-
> 2 files changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
> index 76cbd9c..1a0a6e5 100644
> --- a/arch/arm/include/asm/memory.h
> +++ b/arch/arm/include/asm/memory.h
> @@ -37,7 +37,7 @@
> * TASK_SIZE - the maximum size of a user space task.
> * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
> */
> -#define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M))
> +#define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_32M))
> #define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M)
>
> /*
> @@ -50,7 +50,7 @@
> * and PAGE_OFFSET - it must be within 32MB of the kernel text.
> */
> #ifndef CONFIG_THUMB2_KERNEL
> -#define MODULES_VADDR (PAGE_OFFSET - SZ_16M)
> +#define MODULES_VADDR (PAGE_OFFSET - SZ_32M)
> #else
> /* smaller range for Thumb-2 symbols relocation (2^24)*/
> #define MODULES_VADDR (PAGE_OFFSET - SZ_8M)
> diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
> index 4f14b5c..b8e1f9c 100644
> --- a/arch/arm/kernel/module.c
> +++ b/arch/arm/kernel/module.c
> @@ -35,12 +35,19 @@
> */
> #undef MODULES_VADDR
> #define MODULES_VADDR (((unsigned long)_exiprom + ~PMD_MASK) & PMD_MASK)
> +#define MODULES_START MODULES_VADDR
> +#else
> +#ifndef CONFIG_THUMB2_KERNEL
> +#define MODULES_START ALIGN((unsigned long)_etext - SZ_32M, PAGE_SIZE)
On a multi_v7_defconfig kernel, the text size is >8 MB, which means
you are only adding ~7 MB to the module area, while consuming 16 MB of
additional address space. Given that 20 MB modules are very uncommon,
I think it is better to enable CONFIG_ARM_MODULE_PLTS instead. That
way, there is no need to update these defaults for everyone.
> +#else
> +#define MODULES_START MODULES_VADDR
> +#endif
> #endif
>
> #ifdef CONFIG_MMU
> void *module_alloc(unsigned long size)
> {
> - void *p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
> + void *p = __vmalloc_node_range(size, 1, MODULES_START, MODULES_END,
> GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
> __builtin_return_address(0));
> if (!IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || p)
> --
> 1.9.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 1/3] ARM: dts: STiH410-b2260: Identify the UART RTS line
From: Patrice Chotard @ 2016-12-06 8:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202141146.31281-1-lee.jones@linaro.org>
Hi Lee
Except the typo in patch 2
Acked-by: Patrice Chotard <patrice.chotard@st.com>
Thanks
On 12/02/2016 03:11 PM, Lee Jones wrote:
> Configure the UART RTS line as a GPIO for manipulation within the UART driver.
>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
> arch/arm/boot/dts/stih410-b2260.dts | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/boot/dts/stih410-b2260.dts b/arch/arm/boot/dts/stih410-b2260.dts
> index 7fb507f..f46603f 100644
> --- a/arch/arm/boot/dts/stih410-b2260.dts
> +++ b/arch/arm/boot/dts/stih410-b2260.dts
> @@ -63,6 +63,7 @@
> uart0: serial at 9830000 {
> label = "LS-UART0";
> status = "okay";
> + rts-gpios = <&pio17 3 GPIO_ACTIVE_LOW>;
> };
>
> /* Low speed expansion connector */
>
^ permalink raw reply
* [PATCH 06/11] ARM: dts: imx: Add imx6sll EVK board dts support
From: Jacky Bai @ 2016-12-06 8:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5C5-tq-OWTYcmzJt=_57wOyXzNMUes1mctwwyoegwzJyQ@mail.gmail.com>
Hi Fabio,
Please see below.
> Subject: Re: [PATCH 06/11] ARM: dts: imx: Add imx6sll EVK board dts support
>
> On Fri, Dec 2, 2016 at 4:39 AM, Bai Ping <ping.bai@nxp.com> wrote:
> > Add basic dts support for imx6sll EVK baoard.
>
> s/baord/board
ok, I will fix this typo.
>
> > + battery: max8903 at 0 {
> > + compatible = "fsl,max8903-charger";
> > + pinctrl-names = "default";
> > + dok_input = <&gpio4 13 1>;
> > + uok_input = <&gpio4 13 1>;
> > + chg_input = <&gpio4 15 1>;
> > + flt_input = <&gpio4 14 1>;
> > + fsl,dcm_always_high;
> > + fsl,dc_valid;
> > + fsl,adc_disable;
>
> These properties do not exist in mainline, please remove them.
ok, thanks for you comment.
>
>
> > + status = "okay";
> > + };
> > +
> > + pxp_v4l2_out {
> > + compatible = "fsl,imx6sl-pxp-v4l2";
> > + status = "okay";
> > + };
>
> We don't have pxp support in mainline kernel, please remove it.
Ok, I will remove it.
>
> > +
> > + regulators {
> > + compatible = "simple-bus";
> > + #address-cells = <1>;
> > + #size-cells = <0>;
>
>
> Please remove it and place the regulator nodes directly as below:
ok, I will fix it.
>
>
> > +
> > + reg_usb_otg1_vbus: regulator at 0 {
> > + compatible = "regulator-fixed";
> > + reg = <0>;
> > + regulator-name = "usb_otg1_vbus";
> > + regulator-min-microvolt = <5000000>;
> > + regulator-max-microvolt = <5000000>;
> > + gpio = <&gpio4 0 GPIO_ACTIVE_HIGH>;
> > + enable-active-high;
> > + };
>
> reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
> compatible = "regulator-fixed";
> regulator-name = "usb_otg1_vbus";
> regulator-min-microvolt = <5000000>;
> regulator-max-microvolt = <5000000>;
> gpio = <&gpio4 0 GPIO_ACTIVE_HIGH>;
> enable-active-high;
> };
>
> > +&cpu0 {
> > + arm-supply = <&sw1a_reg>;
> > + soc-supply = <&sw1c_reg>;
> > +};
>
> This is only for LDO bypass mode, right? We don't support LDO-bypass in
> mainline.
>
On i.MX6SLL, no internal LDO for ARM and SOC. We can only use external regulator for DVFS.
> > +&gpc {
> > + fsl,ldo-bypass = <1>;
>
> We don't support ldo-bypass in mainline, please remove it.
>
> > +&pxp {
> > + status = "okay";
> > +};
>
> We don't support PXP in mainline, please remove it.
ok I will remove it.
BR
Jacky Bai
^ permalink raw reply
* [PATCH 2/2] arm64: dts: NS2: add support for XMC form factor
From: kbuild test robot @ 2016-12-06 8:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480979542-26871-3-git-send-email-jon.mason@broadcom.com>
Hi Jon,
[auto build test ERROR on robh/for-next]
[also build test ERROR on v4.9-rc8]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Jon-Mason/arm64-dts-NS2-reserve-memory-for-Nitro-firmware/20161206-125631
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: arm64-allmodconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm64
All errors (new ones prefixed by >>):
>> Error: arch/arm64/boot/dts/broadcom/ns2-xmc.dts:56.1-6 Label or path enet not found
>> Error: arch/arm64/boot/dts/broadcom/ns2-xmc.dts:132.1-7 Label or path pcie8 not found
>> Error: arch/arm64/boot/dts/broadcom/ns2-xmc.dts:148.1-6 Label or path qspi not found
>> FATAL ERROR: Syntax error parsing input tree
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 52465 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161206/fc197763/attachment-0001.gz>
^ 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