Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/6] Documentation: dt-bindings: Document STM32 ADC DT bindings
From: Jonathan Cameron @ 2016-11-19 11:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161116151549.m6phclc6cqy4lj2y@rob-hp-laptop>

On 16/11/16 15:15, Rob Herring wrote:
> On Tue, Nov 15, 2016 at 04:30:56PM +0100, Fabrice Gasnier wrote:
>> This patch adds documentation of device tree bindings for the STM32 ADC.
>>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>> ---
>>  .../devicetree/bindings/iio/adc/st,stm32-adc.txt   | 83 ++++++++++++++++++++++
>>  1 file changed, 83 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
> 
> Acked-by: Rob Herring <robh@kernel.org>
Applied to the togreg branch of iio.git.

Thanks,

Jonathan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" 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

* [RFC 2/6] drm/etnaviv: allow building etnaviv on omap devices
From: Joshua Clayton @ 2016-11-19 11:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161118163342.5t2tbsw54k2gmqe3@rob-hp-laptop>

On Friday, November 18, 2016 10:33:42 AM Rob Herring wrote:
> On Thu, Nov 17, 2016 at 08:44:32PM -0600, Robert Nelson wrote:
> > Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
> > CC: Christian Gmeiner <christian.gmeiner@gmail.com>
> > CC: Russell King <rmk+kernel@arm.linux.org.uk>
> > CC: Lucas Stach <l.stach@pengutronix.de>
> > ---
> >  drivers/gpu/drm/etnaviv/Kconfig | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/etnaviv/Kconfig b/drivers/gpu/drm/etnaviv/Kconfig
> > index 2cde7a5..b776f41 100644
> > --- a/drivers/gpu/drm/etnaviv/Kconfig
> > +++ b/drivers/gpu/drm/etnaviv/Kconfig
> > @@ -2,7 +2,7 @@
> >  config DRM_ETNAVIV
> >  	tristate "ETNAVIV (DRM support for Vivante GPU IP cores)"
> >  	depends on DRM
> > -	depends on ARCH_MXC || ARCH_DOVE
> > +	depends on ARCH_MXC || ARCH_DOVE || ARCH_OMAP2PLUS
> 
> Why not just drop this line. Then it will get better build testing, too.
> 
> >  	select SHMEM
> >  	select TMPFS
> >  	select IOMMU_API
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
...building with ARCH=x86_64
            ^
drivers/gpu/drm/etnaviv/etnaviv_gpu.c: In function ?etnaviv_gpu_init?:
drivers/gpu/drm/etnaviv/etnaviv_gpu.c:633:18: error: ?PHYS_OFFSET? undeclared (first use in this function)
   if (dma_mask < PHYS_OFFSET + SZ_2G)
                  ^
drivers/gpu/drm/etnaviv/etnaviv_gpu.c:633:18: note: each undeclared identifier is reported only once for each function it appears in
make[4]: *** [scripts/Makefile.build:290: drivers/gpu/drm/etnaviv/etnaviv_gpu.o] Error 1
make[3]: *** [scripts/Makefile.build:440: drivers/gpu/drm/etnaviv] Error 2
make[2]: *** [scripts/Makefile.build:440: drivers/gpu/drm] Error 2
make[1]: *** [scripts/Makefile.build:440: drivers/gpu] Error 2
make: *** [Makefile:968: drivers] Error 2


...looks like this snippit is the only (compile time) problem:
 
 622         /*
 623          * Set the GPU linear window to be@the end of the DMA window, where
 624          * the CMA area is likely to reside. This ensures that we are able to
 625          * map the command buffers while having the linear window overlap as
 626          * much RAM as possible, so we can optimize mappings for other buffers.
 627          *
 628          * For 3D cores only do this if MC2.0 is present, as with MC1.0 it leads
 629          * to different views of the memory on the individual engines.
 630          */
 631         if (!(gpu->identity.features & chipFeatures_PIPE_3D) ||
 632             (gpu->identity.minor_features0 & chipMinorFeatures0_MC20)) {
 633                 u32 dma_mask = (u32)dma_get_required_mask(gpu->dev);
 634                 if (dma_mask < PHYS_OFFSET + SZ_2G)
 635                         gpu->memory_base = PHYS_OFFSET;
 636                 else
 637                         gpu->memory_base = dma_mask - SZ_2G + 1;
 638         }

Joshua

^ permalink raw reply

* [PATCH v3 2/6] iio: adc: Add support for STM32 ADC core
From: Jonathan Cameron @ 2016-11-19 12:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479223861-21747-3-git-send-email-fabrice.gasnier@st.com>

On 15/11/16 15:30, Fabrice Gasnier wrote:
> Add core driver for STMicroelectronics STM32 ADC (Analog to Digital
> Converter). STM32 ADC can be composed of up to 3 ADCs with shared
> resources like clock prescaler, common interrupt line and analog
> reference voltage.
> This core driver basically manages shared resources.
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>

There is nothing in here that demands selecting a fixed regulator.
I've also switched the select regulator over to depends on inline with
other drivers in IIO that have a hard dependency on regulators.
Other than that which showed up during build tests, looks good to me.
Shout if I've broken anything with this change.

Applied to the togreg branch of iio.git and pushed out as testing for
the autobuilders to play with it.

Thanks,

Jonathan
> ---
>  drivers/iio/adc/Kconfig          |  13 ++
>  drivers/iio/adc/Makefile         |   1 +
>  drivers/iio/adc/stm32-adc-core.c | 303 +++++++++++++++++++++++++++++++++++++++
>  drivers/iio/adc/stm32-adc-core.h |  52 +++++++
>  4 files changed, 369 insertions(+)
>  create mode 100644 drivers/iio/adc/stm32-adc-core.c
>  create mode 100644 drivers/iio/adc/stm32-adc-core.h
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 7edcf32..ff30239 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -419,6 +419,19 @@ config ROCKCHIP_SARADC
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called rockchip_saradc.
>  
> +config STM32_ADC_CORE
> +	tristate "STMicroelectronics STM32 adc core"
> +	depends on ARCH_STM32 || COMPILE_TEST
> +	depends on OF
> +	select REGULATOR
> +	select REGULATOR_FIXED_VOLTAGE
> +	help
> +	  Select this option to enable the core driver for STMicroelectronics
> +	  STM32 analog-to-digital converter (ADC).
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called stm32-adc-core.
> +
>  config STX104
>  	tristate "Apex Embedded Systems STX104 driver"
>  	depends on X86 && ISA_BUS_API
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 7a40c04..a1e8f44 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -41,6 +41,7 @@ obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
>  obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
>  obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
>  obj-$(CONFIG_STX104) += stx104.o
> +obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
>  obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
>  obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
>  obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o
> diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
> new file mode 100644
> index 0000000..4214b0c
> --- /dev/null
> +++ b/drivers/iio/adc/stm32-adc-core.c
> @@ -0,0 +1,303 @@
> +/*
> + * This file is part of STM32 ADC driver
> + *
> + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
> + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
> + *
> + * Inspired from: fsl-imx25-tsadc
> + *
> + * License type: GPLv2
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE.
> + * See the GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/irqdesc.h>
> +#include <linux/irqdomain.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +
> +#include "stm32-adc-core.h"
> +
> +/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
> +#define STM32F4_ADC_CSR			(STM32_ADCX_COMN_OFFSET + 0x00)
> +#define STM32F4_ADC_CCR			(STM32_ADCX_COMN_OFFSET + 0x04)
> +
> +/* STM32F4_ADC_CSR - bit fields */
> +#define STM32F4_EOC3			BIT(17)
> +#define STM32F4_EOC2			BIT(9)
> +#define STM32F4_EOC1			BIT(1)
> +
> +/* STM32F4_ADC_CCR - bit fields */
> +#define STM32F4_ADC_ADCPRE_SHIFT	16
> +#define STM32F4_ADC_ADCPRE_MASK		GENMASK(17, 16)
> +
> +/* STM32 F4 maximum analog clock rate (from datasheet) */
> +#define STM32F4_ADC_MAX_CLK_RATE	36000000
> +
> +/**
> + * struct stm32_adc_priv - stm32 ADC core private data
> + * @irq:		irq for ADC block
> + * @domain:		irq domain reference
> + * @aclk:		clock reference for the analog circuitry
> + * @vref:		regulator reference
> + * @common:		common data for all ADC instances
> + */
> +struct stm32_adc_priv {
> +	int				irq;
> +	struct irq_domain		*domain;
> +	struct clk			*aclk;
> +	struct regulator		*vref;
> +	struct stm32_adc_common		common;
> +};
> +
> +static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com)
> +{
> +	return container_of(com, struct stm32_adc_priv, common);
> +}
> +
> +/* STM32F4 ADC internal common clock prescaler division ratios */
> +static int stm32f4_pclk_div[] = {2, 4, 6, 8};
> +
> +/**
> + * stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler
> + * @priv: stm32 ADC core private data
> + * Select clock prescaler used for analog conversions, before using ADC.
> + */
> +static int stm32f4_adc_clk_sel(struct platform_device *pdev,
> +			       struct stm32_adc_priv *priv)
> +{
> +	unsigned long rate;
> +	u32 val;
> +	int i;
> +
> +	rate = clk_get_rate(priv->aclk);
> +	for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
> +		if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE)
> +			break;
> +	}
> +	if (i >= ARRAY_SIZE(stm32f4_pclk_div))
> +		return -EINVAL;
> +
> +	val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR);
> +	val &= ~STM32F4_ADC_ADCPRE_MASK;
> +	val |= i << STM32F4_ADC_ADCPRE_SHIFT;
> +	writel_relaxed(val, priv->common.base + STM32F4_ADC_CCR);
> +
> +	dev_dbg(&pdev->dev, "Using analog clock source at %ld kHz\n",
> +		rate / (stm32f4_pclk_div[i] * 1000));
> +
> +	return 0;
> +}
> +
> +/* ADC common interrupt for all instances */
> +static void stm32_adc_irq_handler(struct irq_desc *desc)
> +{
> +	struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc);
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	u32 status;
> +
> +	chained_irq_enter(chip, desc);
> +	status = readl_relaxed(priv->common.base + STM32F4_ADC_CSR);
> +
> +	if (status & STM32F4_EOC1)
> +		generic_handle_irq(irq_find_mapping(priv->domain, 0));
> +
> +	if (status & STM32F4_EOC2)
> +		generic_handle_irq(irq_find_mapping(priv->domain, 1));
> +
> +	if (status & STM32F4_EOC3)
> +		generic_handle_irq(irq_find_mapping(priv->domain, 2));
> +
> +	chained_irq_exit(chip, desc);
> +};
> +
> +static int stm32_adc_domain_map(struct irq_domain *d, unsigned int irq,
> +				irq_hw_number_t hwirq)
> +{
> +	irq_set_chip_data(irq, d->host_data);
> +	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq);
> +
> +	return 0;
> +}
> +
> +static void stm32_adc_domain_unmap(struct irq_domain *d, unsigned int irq)
> +{
> +	irq_set_chip_and_handler(irq, NULL, NULL);
> +	irq_set_chip_data(irq, NULL);
> +}
> +
> +static const struct irq_domain_ops stm32_adc_domain_ops = {
> +	.map = stm32_adc_domain_map,
> +	.unmap  = stm32_adc_domain_unmap,
> +	.xlate = irq_domain_xlate_onecell,
> +};
> +
> +static int stm32_adc_irq_probe(struct platform_device *pdev,
> +			       struct stm32_adc_priv *priv)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +
> +	priv->irq = platform_get_irq(pdev, 0);
> +	if (priv->irq < 0) {
> +		dev_err(&pdev->dev, "failed to get irq\n");
> +		return priv->irq;
> +	}
> +
> +	priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
> +					     &stm32_adc_domain_ops,
> +					     priv);
> +	if (!priv->domain) {
> +		dev_err(&pdev->dev, "Failed to add irq domain\n");
> +		return -ENOMEM;
> +	}
> +
> +	irq_set_chained_handler(priv->irq, stm32_adc_irq_handler);
> +	irq_set_handler_data(priv->irq, priv);
> +
> +	return 0;
> +}
> +
> +static void stm32_adc_irq_remove(struct platform_device *pdev,
> +				 struct stm32_adc_priv *priv)
> +{
> +	int hwirq;
> +
> +	for (hwirq = 0; hwirq < STM32_ADC_MAX_ADCS; hwirq++)
> +		irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
> +	irq_domain_remove(priv->domain);
> +	irq_set_chained_handler(priv->irq, NULL);
> +}
> +
> +static int stm32_adc_probe(struct platform_device *pdev)
> +{
> +	struct stm32_adc_priv *priv;
> +	struct device_node *np = pdev->dev.of_node;
> +	struct resource *res;
> +	int ret;
> +
> +	if (!pdev->dev.of_node)
> +		return -ENODEV;
> +
> +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	priv->common.base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(priv->common.base))
> +		return PTR_ERR(priv->common.base);
> +
> +	priv->vref = devm_regulator_get(&pdev->dev, "vref");
> +	if (IS_ERR(priv->vref)) {
> +		ret = PTR_ERR(priv->vref);
> +		dev_err(&pdev->dev, "vref get failed, %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = regulator_enable(priv->vref);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "vref enable failed\n");
> +		return ret;
> +	}
> +
> +	ret = regulator_get_voltage(priv->vref);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret);
> +		goto err_regulator_disable;
> +	}
> +	priv->common.vref_mv = ret / 1000;
> +	dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv);
> +
> +	priv->aclk = devm_clk_get(&pdev->dev, "adc");
> +	if (IS_ERR(priv->aclk)) {
> +		ret = PTR_ERR(priv->aclk);
> +		dev_err(&pdev->dev, "Can't get 'adc' clock\n");
> +		goto err_regulator_disable;
> +	}
> +
> +	ret = clk_prepare_enable(priv->aclk);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "adc clk enable failed\n");
> +		goto err_regulator_disable;
> +	}
> +
> +	ret = stm32f4_adc_clk_sel(pdev, priv);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "adc clk selection failed\n");
> +		goto err_clk_disable;
> +	}
> +
> +	ret = stm32_adc_irq_probe(pdev, priv);
> +	if (ret < 0)
> +		goto err_clk_disable;
> +
> +	platform_set_drvdata(pdev, &priv->common);
> +
> +	ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "failed to populate DT children\n");
> +		goto err_irq_remove;
> +	}
> +
> +	return 0;
> +
> +err_irq_remove:
> +	stm32_adc_irq_remove(pdev, priv);
> +
> +err_clk_disable:
> +	clk_disable_unprepare(priv->aclk);
> +
> +err_regulator_disable:
> +	regulator_disable(priv->vref);
> +
> +	return ret;
> +}
> +
> +static int stm32_adc_remove(struct platform_device *pdev)
> +{
> +	struct stm32_adc_common *common = platform_get_drvdata(pdev);
> +	struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
> +
> +	of_platform_depopulate(&pdev->dev);
> +	stm32_adc_irq_remove(pdev, priv);
> +	clk_disable_unprepare(priv->aclk);
> +	regulator_disable(priv->vref);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id stm32_adc_of_match[] = {
> +	{ .compatible = "st,stm32f4-adc-core" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
> +
> +static struct platform_driver stm32_adc_driver = {
> +	.probe = stm32_adc_probe,
> +	.remove = stm32_adc_remove,
> +	.driver = {
> +		.name = "stm32-adc-core",
> +		.of_match_table = stm32_adc_of_match,
> +	},
> +};
> +module_platform_driver(stm32_adc_driver);
> +
> +MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 ADC core driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:stm32-adc-core");
> diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h
> new file mode 100644
> index 0000000..081fa5f
> --- /dev/null
> +++ b/drivers/iio/adc/stm32-adc-core.h
> @@ -0,0 +1,52 @@
> +/*
> + * This file is part of STM32 ADC driver
> + *
> + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
> + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
> + *
> + * License type: GPLv2
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE.
> + * See the GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __STM32_ADC_H
> +#define __STM32_ADC_H
> +
> +/*
> + * STM32 - ADC global register map
> + * ________________________________________________________
> + * | Offset |                 Register                    |
> + * --------------------------------------------------------
> + * | 0x000  |                Master ADC1                  |
> + * --------------------------------------------------------
> + * | 0x100  |                Slave ADC2                   |
> + * --------------------------------------------------------
> + * | 0x200  |                Slave ADC3                   |
> + * --------------------------------------------------------
> + * | 0x300  |         Master & Slave common regs          |
> + * --------------------------------------------------------
> + */
> +#define STM32_ADC_MAX_ADCS		3
> +#define STM32_ADCX_COMN_OFFSET		0x300
> +
> +/**
> + * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
> + * @base:		control registers base cpu addr
> + * @vref_mv:		vref voltage (mv)
> + */
> +struct stm32_adc_common {
> +	void __iomem			*base;
> +	int				vref_mv;
> +};
> +
> +#endif
> 

^ permalink raw reply

* [PATCH v3 3/6] iio: adc: Add support for STM32 ADC
From: Jonathan Cameron @ 2016-11-19 12:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479223861-21747-4-git-send-email-fabrice.gasnier@st.com>

On 15/11/16 15:30, Fabrice Gasnier wrote:
> This patch adds support for STMicroelectronics STM32 MCU's analog to
> digital converter.
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Applied to the togreg branch of iio.git and pushed out as testing
for the autobuilders to play with it.

Very nice driver!

Thanks,

Jonathan
> ---
>  drivers/iio/adc/Kconfig     |  10 +
>  drivers/iio/adc/Makefile    |   1 +
>  drivers/iio/adc/stm32-adc.c | 518 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 529 insertions(+)
>  create mode 100644 drivers/iio/adc/stm32-adc.c
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index ff30239..f93b990 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -432,6 +432,16 @@ config STM32_ADC_CORE
>  	  This driver can also be built as a module.  If so, the module
>  	  will be called stm32-adc-core.
>  
> +config STM32_ADC
> +	tristate "STMicroelectronics STM32 adc"
> +	depends on STM32_ADC_CORE
> +	help
> +	  Say yes here to build support for STMicroelectronics stm32 Analog
> +	  to Digital Converter (ADC).
> +
> +	  This driver can also be built as a module.  If so, the module
> +	  will be called stm32-adc.
> +
>  config STX104
>  	tristate "Apex Embedded Systems STX104 driver"
>  	depends on X86 && ISA_BUS_API
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index a1e8f44..8e02a94 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -42,6 +42,7 @@ obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
>  obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
>  obj-$(CONFIG_STX104) += stx104.o
>  obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
> +obj-$(CONFIG_STM32_ADC) += stm32-adc.o
>  obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
>  obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
>  obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o
> diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
> new file mode 100644
> index 0000000..5715e79
> --- /dev/null
> +++ b/drivers/iio/adc/stm32-adc.c
> @@ -0,0 +1,518 @@
> +/*
> + * This file is part of STM32 ADC driver
> + *
> + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
> + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
> + *
> + * License type: GPLv2
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE.
> + * See the GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/iio/iio.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +
> +#include "stm32-adc-core.h"
> +
> +/* STM32F4 - Registers for each ADC instance */
> +#define STM32F4_ADC_SR			0x00
> +#define STM32F4_ADC_CR1			0x04
> +#define STM32F4_ADC_CR2			0x08
> +#define STM32F4_ADC_SMPR1		0x0C
> +#define STM32F4_ADC_SMPR2		0x10
> +#define STM32F4_ADC_HTR			0x24
> +#define STM32F4_ADC_LTR			0x28
> +#define STM32F4_ADC_SQR1		0x2C
> +#define STM32F4_ADC_SQR2		0x30
> +#define STM32F4_ADC_SQR3		0x34
> +#define STM32F4_ADC_JSQR		0x38
> +#define STM32F4_ADC_JDR1		0x3C
> +#define STM32F4_ADC_JDR2		0x40
> +#define STM32F4_ADC_JDR3		0x44
> +#define STM32F4_ADC_JDR4		0x48
> +#define STM32F4_ADC_DR			0x4C
> +
> +/* STM32F4_ADC_SR - bit fields */
> +#define STM32F4_STRT			BIT(4)
> +#define STM32F4_EOC			BIT(1)
> +
> +/* STM32F4_ADC_CR1 - bit fields */
> +#define STM32F4_SCAN			BIT(8)
> +#define STM32F4_EOCIE			BIT(5)
> +
> +/* STM32F4_ADC_CR2 - bit fields */
> +#define STM32F4_SWSTART			BIT(30)
> +#define STM32F4_EXTEN_MASK		GENMASK(29, 28)
> +#define STM32F4_EOCS			BIT(10)
> +#define STM32F4_ADON			BIT(0)
> +
> +/* STM32F4_ADC_SQR1 - bit fields */
> +#define STM32F4_L_SHIFT			20
> +#define STM32F4_L_MASK			GENMASK(23, 20)
> +
> +/* STM32F4_ADC_SQR3 - bit fields */
> +#define STM32F4_SQ1_SHIFT		0
> +#define STM32F4_SQ1_MASK		GENMASK(4, 0)
> +
> +#define STM32_ADC_TIMEOUT_US		100000
> +#define STM32_ADC_TIMEOUT	(msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
> +
> +/**
> + * struct stm32_adc - private data of each ADC IIO instance
> + * @common:		reference to ADC block common data
> + * @offset:		ADC instance register offset in ADC block
> + * @completion:		end of single conversion completion
> + * @buffer:		data buffer
> + * @clk:		clock for this adc instance
> + * @irq:		interrupt for this adc instance
> + * @lock:		spinlock
> + */
> +struct stm32_adc {
> +	struct stm32_adc_common	*common;
> +	u32			offset;
> +	struct completion	completion;
> +	u16			*buffer;
> +	struct clk		*clk;
> +	int			irq;
> +	spinlock_t		lock;		/* interrupt lock */
> +};
> +
> +/**
> + * struct stm32_adc_chan_spec - specification of stm32 adc channel
> + * @type:	IIO channel type
> + * @channel:	channel number (single ended)
> + * @name:	channel name (single ended)
> + */
> +struct stm32_adc_chan_spec {
> +	enum iio_chan_type	type;
> +	int			channel;
> +	const char		*name;
> +};
> +
> +/* Input definitions common for all STM32F4 instances */
> +static const struct stm32_adc_chan_spec stm32f4_adc123_channels[] = {
> +	{ IIO_VOLTAGE, 0, "in0" },
> +	{ IIO_VOLTAGE, 1, "in1" },
> +	{ IIO_VOLTAGE, 2, "in2" },
> +	{ IIO_VOLTAGE, 3, "in3" },
> +	{ IIO_VOLTAGE, 4, "in4" },
> +	{ IIO_VOLTAGE, 5, "in5" },
> +	{ IIO_VOLTAGE, 6, "in6" },
> +	{ IIO_VOLTAGE, 7, "in7" },
> +	{ IIO_VOLTAGE, 8, "in8" },
> +	{ IIO_VOLTAGE, 9, "in9" },
> +	{ IIO_VOLTAGE, 10, "in10" },
> +	{ IIO_VOLTAGE, 11, "in11" },
> +	{ IIO_VOLTAGE, 12, "in12" },
> +	{ IIO_VOLTAGE, 13, "in13" },
> +	{ IIO_VOLTAGE, 14, "in14" },
> +	{ IIO_VOLTAGE, 15, "in15" },
> +};
> +
> +/**
> + * STM32 ADC registers access routines
> + * @adc: stm32 adc instance
> + * @reg: reg offset in adc instance
> + *
> + * Note: All instances share same base, with 0x0, 0x100 or 0x200 offset resp.
> + * for adc1, adc2 and adc3.
> + */
> +static u32 stm32_adc_readl(struct stm32_adc *adc, u32 reg)
> +{
> +	return readl_relaxed(adc->common->base + adc->offset + reg);
> +}
> +
> +static u16 stm32_adc_readw(struct stm32_adc *adc, u32 reg)
> +{
> +	return readw_relaxed(adc->common->base + adc->offset + reg);
> +}
> +
> +static void stm32_adc_writel(struct stm32_adc *adc, u32 reg, u32 val)
> +{
> +	writel_relaxed(val, adc->common->base + adc->offset + reg);
> +}
> +
> +static void stm32_adc_set_bits(struct stm32_adc *adc, u32 reg, u32 bits)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +	stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) | bits);
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
> +
> +static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&adc->lock, flags);
> +	stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) & ~bits);
> +	spin_unlock_irqrestore(&adc->lock, flags);
> +}
> +
> +/**
> + * stm32_adc_conv_irq_enable() - Enable end of conversion interrupt
> + * @adc: stm32 adc instance
> + */
> +static void stm32_adc_conv_irq_enable(struct stm32_adc *adc)
> +{
> +	stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE);
> +};
> +
> +/**
> + * stm32_adc_conv_irq_disable() - Disable end of conversion interrupt
> + * @adc: stm32 adc instance
> + */
> +static void stm32_adc_conv_irq_disable(struct stm32_adc *adc)
> +{
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE);
> +}
> +
> +/**
> + * stm32_adc_start_conv() - Start conversions for regular channels.
> + * @adc: stm32 adc instance
> + */
> +static void stm32_adc_start_conv(struct stm32_adc *adc)
> +{
> +	stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
> +	stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_EOCS | STM32F4_ADON);
> +
> +	/* Wait for Power-up time (tSTAB from datasheet) */
> +	usleep_range(2, 3);
> +
> +	/* Software start ? (e.g. trigger detection disabled ?) */
> +	if (!(stm32_adc_readl(adc, STM32F4_ADC_CR2) & STM32F4_EXTEN_MASK))
> +		stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART);
> +}
> +
> +static void stm32_adc_stop_conv(struct stm32_adc *adc)
> +{
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT);
> +
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_ADON);
> +}
> +
> +/**
> + * stm32_adc_single_conv() - Performs a single conversion
> + * @indio_dev: IIO device
> + * @chan: IIO channel
> + * @res: conversion result
> + *
> + * The function performs a single conversion on a given channel:
> + * - Program sequencer with one channel (e.g. in SQ1 with len = 1)
> + * - Use SW trigger
> + * - Start conversion, then wait for interrupt completion.
> + */
> +static int stm32_adc_single_conv(struct iio_dev *indio_dev,
> +				 const struct iio_chan_spec *chan,
> +				 int *res)
> +{
> +	struct stm32_adc *adc = iio_priv(indio_dev);
> +	long timeout;
> +	u32 val;
> +	u16 result;
> +	int ret;
> +
> +	reinit_completion(&adc->completion);
> +
> +	adc->buffer = &result;
> +
> +	/* Program chan number in regular sequence */
> +	val = stm32_adc_readl(adc, STM32F4_ADC_SQR3);
> +	val &= ~STM32F4_SQ1_MASK;
> +	val |= chan->channel << STM32F4_SQ1_SHIFT;
> +	stm32_adc_writel(adc, STM32F4_ADC_SQR3, val);
> +
> +	/* Set regular sequence len (0 for 1 conversion) */
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_SQR1, STM32F4_L_MASK);
> +
> +	/* Trigger detection disabled (conversion can be launched in SW) */
> +	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
> +
> +	stm32_adc_conv_irq_enable(adc);
> +
> +	stm32_adc_start_conv(adc);
> +
> +	timeout = wait_for_completion_interruptible_timeout(
> +					&adc->completion, STM32_ADC_TIMEOUT);
> +	if (timeout == 0) {
> +		ret = -ETIMEDOUT;
> +	} else if (timeout < 0) {
> +		ret = timeout;
> +	} else {
> +		*res = result;
> +		ret = IIO_VAL_INT;
> +	}
> +
> +	stm32_adc_stop_conv(adc);
> +
> +	stm32_adc_conv_irq_disable(adc);
> +
> +	return ret;
> +}
> +
> +static int stm32_adc_read_raw(struct iio_dev *indio_dev,
> +			      struct iio_chan_spec const *chan,
> +			      int *val, int *val2, long mask)
> +{
> +	struct stm32_adc *adc = iio_priv(indio_dev);
> +	int ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		ret = iio_device_claim_direct_mode(indio_dev);
> +		if (ret)
> +			return ret;
> +		if (chan->type == IIO_VOLTAGE)
> +			ret = stm32_adc_single_conv(indio_dev, chan, val);
> +		else
> +			ret = -EINVAL;
> +		iio_device_release_direct_mode(indio_dev);
> +		return ret;
> +
> +	case IIO_CHAN_INFO_SCALE:
> +		*val = adc->common->vref_mv;
> +		*val2 = chan->scan_type.realbits;
> +		return IIO_VAL_FRACTIONAL_LOG2;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static irqreturn_t stm32_adc_isr(int irq, void *data)
> +{
> +	struct stm32_adc *adc = data;
> +	u32 status = stm32_adc_readl(adc, STM32F4_ADC_SR);
> +
> +	if (status & STM32F4_EOC) {
> +		*adc->buffer = stm32_adc_readw(adc, STM32F4_ADC_DR);
> +		complete(&adc->completion);
> +		return IRQ_HANDLED;
> +	}
> +
> +	return IRQ_NONE;
> +}
> +
> +static int stm32_adc_of_xlate(struct iio_dev *indio_dev,
> +			      const struct of_phandle_args *iiospec)
> +{
> +	int i;
> +
> +	for (i = 0; i < indio_dev->num_channels; i++)
> +		if (indio_dev->channels[i].channel == iiospec->args[0])
> +			return i;
> +
> +	return -EINVAL;
> +}
> +
> +/**
> + * stm32_adc_debugfs_reg_access - read or write register value
> + *
> + * To read a value from an ADC register:
> + *   echo [ADC reg offset] > direct_reg_access
> + *   cat direct_reg_access
> + *
> + * To write a value in a ADC register:
> + *   echo [ADC_reg_offset] [value] > direct_reg_access
> + */
> +static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
> +					unsigned reg, unsigned writeval,
> +					unsigned *readval)
> +{
> +	struct stm32_adc *adc = iio_priv(indio_dev);
> +
> +	if (!readval)
> +		stm32_adc_writel(adc, reg, writeval);
> +	else
> +		*readval = stm32_adc_readl(adc, reg);
> +
> +	return 0;
> +}
> +
> +static const struct iio_info stm32_adc_iio_info = {
> +	.read_raw = stm32_adc_read_raw,
> +	.debugfs_reg_access = stm32_adc_debugfs_reg_access,
> +	.of_xlate = stm32_adc_of_xlate,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
> +				    struct iio_chan_spec *chan,
> +				    const struct stm32_adc_chan_spec *channel,
> +				    int scan_index)
> +{
> +	chan->type = channel->type;
> +	chan->channel = channel->channel;
> +	chan->datasheet_name = channel->name;
> +	chan->scan_index = scan_index;
> +	chan->indexed = 1;
> +	chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
> +	chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
> +	chan->scan_type.sign = 'u';
> +	chan->scan_type.realbits = 12;
> +	chan->scan_type.storagebits = 16;
> +}
> +
> +static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
> +{
> +	struct device_node *node = indio_dev->dev.of_node;
> +	struct property *prop;
> +	const __be32 *cur;
> +	struct iio_chan_spec *channels;
> +	int scan_index = 0, num_channels;
> +	u32 val;
> +
> +	num_channels = of_property_count_u32_elems(node, "st,adc-channels");
> +	if (num_channels < 0 ||
> +	    num_channels >= ARRAY_SIZE(stm32f4_adc123_channels)) {
> +		dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
> +		return num_channels < 0 ? num_channels : -EINVAL;
> +	}
> +
> +	channels = devm_kcalloc(&indio_dev->dev, num_channels,
> +				sizeof(struct iio_chan_spec), GFP_KERNEL);
> +	if (!channels)
> +		return -ENOMEM;
> +
> +	of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) {
> +		if (val >= ARRAY_SIZE(stm32f4_adc123_channels)) {
> +			dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
> +			return -EINVAL;
> +		}
> +		stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
> +					&stm32f4_adc123_channels[val],
> +					scan_index);
> +		scan_index++;
> +	}
> +
> +	indio_dev->num_channels = scan_index;
> +	indio_dev->channels = channels;
> +
> +	return 0;
> +}
> +
> +static int stm32_adc_probe(struct platform_device *pdev)
> +{
> +	struct iio_dev *indio_dev;
> +	struct stm32_adc *adc;
> +	int ret;
> +
> +	if (!pdev->dev.of_node)
> +		return -ENODEV;
> +
> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	adc = iio_priv(indio_dev);
> +	adc->common = dev_get_drvdata(pdev->dev.parent);
> +	spin_lock_init(&adc->lock);
> +	init_completion(&adc->completion);
> +
> +	indio_dev->name = dev_name(&pdev->dev);
> +	indio_dev->dev.parent = &pdev->dev;
> +	indio_dev->dev.of_node = pdev->dev.of_node;
> +	indio_dev->info = &stm32_adc_iio_info;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +
> +	platform_set_drvdata(pdev, adc);
> +
> +	ret = of_property_read_u32(pdev->dev.of_node, "reg", &adc->offset);
> +	if (ret != 0) {
> +		dev_err(&pdev->dev, "missing reg property\n");
> +		return -EINVAL;
> +	}
> +
> +	adc->irq = platform_get_irq(pdev, 0);
> +	if (adc->irq < 0) {
> +		dev_err(&pdev->dev, "failed to get irq\n");
> +		return adc->irq;
> +	}
> +
> +	ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr,
> +			       0, pdev->name, adc);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to request IRQ\n");
> +		return ret;
> +	}
> +
> +	adc->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(adc->clk)) {
> +		dev_err(&pdev->dev, "Can't get clock\n");
> +		return PTR_ERR(adc->clk);
> +	}
> +
> +	ret = clk_prepare_enable(adc->clk);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "clk enable failed\n");
> +		return ret;
> +	}
> +
> +	ret = stm32_adc_chan_of_init(indio_dev);
> +	if (ret < 0)
> +		goto err_clk_disable;
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "iio dev register failed\n");
> +		goto err_clk_disable;
> +	}
> +
> +	return 0;
> +
> +err_clk_disable:
> +	clk_disable_unprepare(adc->clk);
> +
> +	return ret;
> +}
> +
> +static int stm32_adc_remove(struct platform_device *pdev)
> +{
> +	struct stm32_adc *adc = platform_get_drvdata(pdev);
> +	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
> +
> +	iio_device_unregister(indio_dev);
> +	clk_disable_unprepare(adc->clk);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id stm32_adc_of_match[] = {
> +	{ .compatible = "st,stm32f4-adc" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
> +
> +static struct platform_driver stm32_adc_driver = {
> +	.probe = stm32_adc_probe,
> +	.remove = stm32_adc_remove,
> +	.driver = {
> +		.name = "stm32-adc",
> +		.of_match_table = stm32_adc_of_match,
> +	},
> +};
> +module_platform_driver(stm32_adc_driver);
> +
> +MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 ADC IIO driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:stm32-adc");
> 

^ permalink raw reply

* [PATCH v3 4/6] ARM: configs: stm32: enable ADC driver
From: Jonathan Cameron @ 2016-11-19 12:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479223861-21747-5-git-send-email-fabrice.gasnier@st.com>

On 15/11/16 15:30, Fabrice Gasnier wrote:
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
The driver is now on it's way in.  I'm assuming this and the two device tree patches
will go via the relevant route to arm-soc.

Thanks,

Jonathan
> ---
>  arch/arm/configs/stm32_defconfig | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/arm/configs/stm32_defconfig b/arch/arm/configs/stm32_defconfig
> index 1e5ec2a..5d241e0 100644
> --- a/arch/arm/configs/stm32_defconfig
> +++ b/arch/arm/configs/stm32_defconfig
> @@ -57,6 +57,9 @@ CONFIG_LEDS_TRIGGERS=y
>  CONFIG_LEDS_TRIGGER_HEARTBEAT=y
>  CONFIG_DMADEVICES=y
>  CONFIG_STM32_DMA=y
> +CONFIG_IIO=y
> +CONFIG_STM32_ADC_CORE=y
> +CONFIG_STM32_ADC=y
>  # CONFIG_FILE_LOCKING is not set
>  # CONFIG_DNOTIFY is not set
>  # CONFIG_INOTIFY_USER is not set
> 

^ permalink raw reply

* [PATCH 0/6] ASoC: samsung: Minor cleanup for old machines
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Few patches removing dead code (machines not supported).

The third patch ([RFT 3/6] ASoC: samsung: smdk_wm8580: Remove machine
specific quirks) requires testing. I hope I understood the code
correctly.

The last ARM patch is independent. I will take it through samsung-soc
tree. I put it here for reference.

Best regards,
Krzysztof

Krzysztof Kozlowski (6):
  ASoC: samsung: Remove non-existing MACH dependencies
  ASoC: samsung: smdk_wm8580: Remove old platforms and drop mach-types
    usage
  ASoC: samsung: smdk_wm8580: Remove machine specific quirks
  ASoC: samsung: Enable COMPILE_TEST for SmartQ and WM8580
  ASoC: samsung: Enable COMPILE_TEST for entire Samsung ASoc
  ARM: s5pv210_defconfig: Remove old MACHs

 arch/arm/configs/s5pv210_defconfig |  4 ----
 sound/soc/samsung/Kconfig          |  8 +++++---
 sound/soc/samsung/smdk_wm8580.c    | 17 ++---------------
 3 files changed, 7 insertions(+), 22 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH 1/6] ASoC: samsung: Remove non-existing MACH dependencies
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479566911-5580-1-git-send-email-krzk@kernel.org>

MACH_SMDKC100 was removed in commit b8529ec1c1b0 ("ARM: S5PC100: no more
support S5PC100 SoC"). MACH_SMDKV210 and MACH_SMDKC110 in commit
28c8331d386 ("ARM: S5PV210: Remove support for board files").

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 sound/soc/samsung/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 79ae6a7c93ff..ea0fa9971a0c 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -49,7 +49,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750
 
 config SND_SOC_SAMSUNG_SMDK_WM8580
 	tristate "SoC I2S Audio support for WM8580 on SMDK"
-	depends on MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110
+	depends on MACH_SMDK6410
 	depends on I2C
 	select SND_SOC_WM8580
 	select SND_SAMSUNG_I2S
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/6] ASoC: samsung: smdk_wm8580: Remove old platforms and drop mach-types usage
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479566911-5580-1-git-send-email-krzk@kernel.org>

MACH_SMDKC100, MACH_SMDKV210 and MACH_SMDKC110 are no longer supported
so drop the dead code.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 sound/soc/samsung/smdk_wm8580.c | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index 548bfd993788..59fd3b8fd414 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -14,8 +14,6 @@
 #include <sound/soc.h>
 #include <sound/pcm_params.h>
 
-#include <asm/mach-types.h>
-
 #include "../codecs/wm8580.h"
 #include "i2s.h"
 
@@ -206,15 +204,10 @@ static int __init smdk_audio_init(void)
 	int ret;
 	char *str;
 
-	if (machine_is_smdkc100()
-			|| machine_is_smdkv210() || machine_is_smdkc110()) {
-		smdk.num_links = 3;
-	} else if (machine_is_smdk6410()) {
-		str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
-		str[strlen(str) - 1] = '2';
-		str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
-		str[strlen(str) - 1] = '2';
-	}
+	str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
+	str[strlen(str) - 1] = '2';
+	str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
+	str[strlen(str) - 1] = '2';
 
 	smdk_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!smdk_snd_device)
-- 
2.7.4

^ permalink raw reply related

* [RFT 3/6] ASoC: samsung: smdk_wm8580: Remove machine specific quirks
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479566911-5580-1-git-send-email-krzk@kernel.org>

The driver no longer differentiates between machines (S3C24xx machines
are not supported by it) so there is no need to override I2S device id
in cpu_dai_name.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>

---

Not tested. The driver did not override .platform_name which looks
suspicious to me. However I did not want to add changes which could have
some visible impact on output code.
---
 sound/soc/samsung/smdk_wm8580.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index 59fd3b8fd414..3bf33387dfeb 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -155,7 +155,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
 	[PRI_PLAYBACK] = { /* Primary Playback i/f */
 		.name = "WM8580 PAIF RX",
 		.stream_name = "Playback",
-		.cpu_dai_name = "samsung-i2s.0",
+		.cpu_dai_name = "samsung-i2s.2",
 		.codec_dai_name = "wm8580-hifi-playback",
 		.platform_name = "samsung-i2s.0",
 		.codec_name = "wm8580.0-001b",
@@ -165,7 +165,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
 	[PRI_CAPTURE] = { /* Primary Capture i/f */
 		.name = "WM8580 PAIF TX",
 		.stream_name = "Capture",
-		.cpu_dai_name = "samsung-i2s.0",
+		.cpu_dai_name = "samsung-i2s.2",
 		.codec_dai_name = "wm8580-hifi-capture",
 		.platform_name = "samsung-i2s.0",
 		.codec_name = "wm8580.0-001b",
@@ -202,12 +202,6 @@ static struct platform_device *smdk_snd_device;
 static int __init smdk_audio_init(void)
 {
 	int ret;
-	char *str;
-
-	str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
-	str[strlen(str) - 1] = '2';
-	str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
-	str[strlen(str) - 1] = '2';
 
 	smdk_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!smdk_snd_device)
-- 
2.7.4

^ permalink raw reply related

* [PATCH 4/6] ASoC: samsung: Enable COMPILE_TEST for SmartQ and WM8580
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479566911-5580-1-git-send-email-krzk@kernel.org>

The I2S sound drivers for SmartQ board and WM8580 codec can be compile
tested to increase build coverage.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 sound/soc/samsung/Kconfig | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index ea0fa9971a0c..426ef1c7b265 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -49,7 +49,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750
 
 config SND_SOC_SAMSUNG_SMDK_WM8580
 	tristate "SoC I2S Audio support for WM8580 on SMDK"
-	depends on MACH_SMDK6410
+	depends on MACH_SMDK6410 || COMPILE_TEST
 	depends on I2C
 	select SND_SOC_WM8580
 	select SND_SAMSUNG_I2S
@@ -109,7 +109,8 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380
 
 config SND_SOC_SMARTQ
 	tristate "SoC I2S Audio support for SmartQ board"
-	depends on MACH_SMARTQ && I2C
+	depends on MACH_SMARTQ || COMPILE_TEST
+	depends on I2C
 	select SND_SAMSUNG_I2S
 	select SND_SOC_WM8750
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH 5/6] ASoC: samsung: Enable COMPILE_TEST for entire Samsung ASoc
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479566911-5580-1-git-send-email-krzk@kernel.org>

Instead of build time, Samsung ASoC drivers have rather runtime
dependency on Exynos or other Samsung platforms.  For building they
require Common Clock Framework.  If it is provided they could be compile
tested to increase build coverage.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 sound/soc/samsung/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 426ef1c7b265..a6cc6ca93fa7 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -1,6 +1,7 @@
 menuconfig SND_SOC_SAMSUNG
 	tristate "ASoC support for Samsung"
-	depends on (PLAT_SAMSUNG || ARCH_EXYNOS)
+	depends on PLAT_SAMSUNG || ARCH_EXYNOS || COMPILE_TEST
+	depends on COMMON_CLK
 	select SND_SOC_GENERIC_DMAENGINE_PCM
 	---help---
 	  Say Y or M if you want to add support for codecs attached to
-- 
2.7.4

^ permalink raw reply related

* [PATCH 6/6] ARM: s5pv210_defconfig: Remove old MACHs
From: Krzysztof Kozlowski @ 2016-11-19 14:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479566911-5580-1-git-send-email-krzk@kernel.org>

Remove non-existing MACH symbols from S5PV210 defconfig.

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
 arch/arm/configs/s5pv210_defconfig | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/arm/configs/s5pv210_defconfig b/arch/arm/configs/s5pv210_defconfig
index fa989902236d..c51f0f02012b 100644
--- a/arch/arm/configs/s5pv210_defconfig
+++ b/arch/arm/configs/s5pv210_defconfig
@@ -9,10 +9,6 @@ CONFIG_ARCH_S5PV210=y
 CONFIG_S3C_LOWLEVEL_UART_PORT=1
 CONFIG_S3C_DEV_FB=y
 CONFIG_S5PV210_SETUP_FB_24BPP=y
-CONFIG_MACH_AQUILA=y
-CONFIG_MACH_GONI=y
-CONFIG_MACH_SMDKC110=y
-CONFIG_MACH_SMDKV210=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_VMSPLIT_2G=y
-- 
2.7.4

^ permalink raw reply related

* [GIT PULL] Integrator DTS and defconfig changes
From: Linus Walleij @ 2016-11-19 15:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161118175301.GA8882@localhost>

On Fri, Nov 18, 2016 at 6:53 PM, Olof Johansson <olof@lixom.net> wrote:
> On Fri, Nov 18, 2016 at 09:26:56AM +0100, Linus Walleij wrote:
>> On Fri, Nov 18, 2016 at 8:25 AM, Olof Johansson <olof@lixom.net> wrote:
>>
>> > I also sympathize that it's extra annoying having to split just three
>> > patches across two branches. So, if it's easier we can just cherry-pick
>> > apart the patches here across the branches (your comment about next
>> > coverage makes me suspect you have no direct downstream users of this
>> > branch). If that's OK, let me know and I'll do that tomorrow.
>>
>> It's fine to cherry-pick, I can also send two separate branches (or
>> just 2+1 stand-alone patches).
>>
>> Any way you like it :) just tell me what to do, all I want is to get this
>> in for v4.10.
>
> Cherry-picking is actually faster on our side than merging, so I've done that
> now. Queued into next/dt and next/defconfig for 4.10.

Thanks Olof, much appreciated!

Yours,
Linus Walleij

^ permalink raw reply

* [GIT PULL] Allwinner late DT changes for 4.10
From: Linus Walleij @ 2016-11-19 15:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161119002733.GA15902@localhost>

On Sat, Nov 19, 2016 at 1:27 AM, Olof Johansson <olof@lixom.net> wrote:

> Also, this won't work since this branch does not contain the required
> pinctrl changes. If we merge this without basing it on those changes we lose
> bisectability.

I usually operate on the assumption that arch/*/boot/dts/* and drivers/*
do not need to be boot-time bisectable sync:ed, because of the ambition
to maintaining DTS files outside of the kernel in the long run, and at that
point they would be versioned orthogonally anyways.

On the other hand, that does look like a pipe dream, so maybe I should
just stop pretending.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH 2/6] ASoC: samsung: smdk_wm8580: Remove old platforms and drop mach-types usage
From: Lars-Peter Clausen @ 2016-11-19 15:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479566911-5580-3-git-send-email-krzk@kernel.org>

On 11/19/2016 03:48 PM, Krzysztof Kozlowski wrote:
[...]
> @@ -206,15 +204,10 @@ static int __init smdk_audio_init(void)
>  	int ret;
>  	char *str;
>  
> -	if (machine_is_smdkc100()
> -			|| machine_is_smdkv210() || machine_is_smdkc110()) {
> -		smdk.num_links = 3;
> -	} else if (machine_is_smdk6410()) {
> -		str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
> -		str[strlen(str) - 1] = '2';
> -		str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
> -		str[strlen(str) - 1] = '2';
> -	}
> +	str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
> +	str[strlen(str) - 1] = '2';
> +	str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
> +	str[strlen(str) - 1] = '2';

This could be further simplified by just updating the initial cpu_dai_name
string in the dai_link struct.

Especially considering that the cpu_dai_name is a string literal and the ARM
kernel now has rodata write protection enabled by default, so modifying it
will crash the kernel.

^ permalink raw reply

* [PATCH 2/6] ASoC: samsung: smdk_wm8580: Remove old platforms and drop mach-types usage
From: Lars-Peter Clausen @ 2016-11-19 15:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <8248c49a-1108-7fce-ed99-01653e11c670@metafoo.de>

On 11/19/2016 04:42 PM, Lars-Peter Clausen wrote:
> On 11/19/2016 03:48 PM, Krzysztof Kozlowski wrote:
> [...]
>> @@ -206,15 +204,10 @@ static int __init smdk_audio_init(void)
>>  	int ret;
>>  	char *str;
>>  
>> -	if (machine_is_smdkc100()
>> -			|| machine_is_smdkv210() || machine_is_smdkc110()) {
>> -		smdk.num_links = 3;
>> -	} else if (machine_is_smdk6410()) {
>> -		str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
>> -		str[strlen(str) - 1] = '2';
>> -		str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
>> -		str[strlen(str) - 1] = '2';
>> -	}
>> +	str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
>> +	str[strlen(str) - 1] = '2';
>> +	str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
>> +	str[strlen(str) - 1] = '2';
> 
> This could be further simplified by just updating the initial cpu_dai_name
> string in the dai_link struct.
> 
> Especially considering that the cpu_dai_name is a string literal and the ARM
> kernel now has rodata write protection enabled by default, so modifying it
> will crash the kernel.

Spoke too soon, you fix this up in the next patch. But I'd just squash that
change into this patch. I think it is pretty safe to assume that it is correct.

^ permalink raw reply

* [PATCH 2/6] ASoC: samsung: smdk_wm8580: Remove old platforms and drop mach-types usage
From: Lars-Peter Clausen @ 2016-11-19 15:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <90e0f455-fa24-f643-fa07-67efe217188a@metafoo.de>

On 11/19/2016 04:45 PM, Lars-Peter Clausen wrote:
> On 11/19/2016 04:42 PM, Lars-Peter Clausen wrote:
>> On 11/19/2016 03:48 PM, Krzysztof Kozlowski wrote:
>> [...]
>>> @@ -206,15 +204,10 @@ static int __init smdk_audio_init(void)
>>>  	int ret;
>>>  	char *str;
>>>  
>>> -	if (machine_is_smdkc100()
>>> -			|| machine_is_smdkv210() || machine_is_smdkc110()) {
>>> -		smdk.num_links = 3;
>>> -	} else if (machine_is_smdk6410()) {
>>> -		str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
>>> -		str[strlen(str) - 1] = '2';
>>> -		str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
>>> -		str[strlen(str) - 1] = '2';
>>> -	}
>>> +	str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
>>> +	str[strlen(str) - 1] = '2';
>>> +	str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
>>> +	str[strlen(str) - 1] = '2';
>>
>> This could be further simplified by just updating the initial cpu_dai_name
>> string in the dai_link struct.
>>
>> Especially considering that the cpu_dai_name is a string literal and the ARM
>> kernel now has rodata write protection enabled by default, so modifying it
>> will crash the kernel.
> 
> Spoke too soon, you fix this up in the next patch. But I'd just squash that
> change into this patch. I think it is pretty safe to assume that it is correct.
> 

And another thing. Since num_links is always 2 now the last entry from the
smdk_dai array can be removed and num_links can be initialized using
ARRAY_SIZE().

^ permalink raw reply

* [GIT PULL] Allwinner late DT changes for 4.10
From: Olof Johansson @ 2016-11-19 17:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdbw3AUj510wPGFG55cKnOyEOX7Syz1BnJx-ygo1eAqzGg@mail.gmail.com>

On Sat, Nov 19, 2016 at 7:28 AM, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Sat, Nov 19, 2016 at 1:27 AM, Olof Johansson <olof@lixom.net> wrote:
>
>> Also, this won't work since this branch does not contain the required
>> pinctrl changes. If we merge this without basing it on those changes we lose
>> bisectability.
>
> I usually operate on the assumption that arch/*/boot/dts/* and drivers/*
> do not need to be boot-time bisectable sync:ed, because of the ambition
> to maintaining DTS files outside of the kernel in the long run, and at that
> point they would be versioned orthogonally anyways.
>
> On the other hand, that does look like a pipe dream, so maybe I should
> just stop pretending.

For new features/drivers/platforms that is definitely the case: Merge
code through the suitable tree and it'll come together when the code
is all merged.

For a cleanup it's a bit different, since you shouldn't regress and
break existing support on the individual branches. I.e. it's OK to not
make things work for the first time until all comes together, but
things that is already working shouldn't break.


-Olof

^ permalink raw reply

* [PATCH] coresight: perf: Add a missing call to etm_free_aux
From: Quentin Lambert @ 2016-11-19 17:41 UTC (permalink / raw)
  To: linux-arm-kernel

Most error branches following the call to alloc_event_data contain a call to
etm_free_aux. This patch add a call to etm_free_aux to an error branch
that does not call it.

This issue was found with Hector.

Signed-off-by: Quentin Lambert <lambert.quentin@gmail.com>
---
 drivers/hwtracing/coresight/coresight-etm-perf.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -215,7 +215,7 @@ static void *etm_setup_aux(int event_cpu
 	 */
 	sink = coresight_get_enabled_sink(true);
 	if (!sink)
-		return NULL;
+		goto err;
 
 	INIT_WORK(&event_data->work, free_event_data);
 

^ permalink raw reply

* [PATCH 2/6] ASoC: samsung: smdk_wm8580: Remove old platforms and drop mach-types usage
From: Krzysztof Kozlowski @ 2016-11-19 18:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <9ef6c39c-e7a2-4591-380f-07f92317313b@metafoo.de>

On Sat, Nov 19, 2016 at 04:48:26PM +0100, Lars-Peter Clausen wrote:
> On 11/19/2016 04:45 PM, Lars-Peter Clausen wrote:
> > On 11/19/2016 04:42 PM, Lars-Peter Clausen wrote:
> >> On 11/19/2016 03:48 PM, Krzysztof Kozlowski wrote:
> >> [...]
> >>> @@ -206,15 +204,10 @@ static int __init smdk_audio_init(void)
> >>>  	int ret;
> >>>  	char *str;
> >>>  
> >>> -	if (machine_is_smdkc100()
> >>> -			|| machine_is_smdkv210() || machine_is_smdkc110()) {
> >>> -		smdk.num_links = 3;
> >>> -	} else if (machine_is_smdk6410()) {
> >>> -		str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
> >>> -		str[strlen(str) - 1] = '2';
> >>> -		str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
> >>> -		str[strlen(str) - 1] = '2';
> >>> -	}
> >>> +	str = (char *)smdk_dai[PRI_PLAYBACK].cpu_dai_name;
> >>> +	str[strlen(str) - 1] = '2';
> >>> +	str = (char *)smdk_dai[PRI_CAPTURE].cpu_dai_name;
> >>> +	str[strlen(str) - 1] = '2';
> >>
> >> This could be further simplified by just updating the initial cpu_dai_name
> >> string in the dai_link struct.
> >>
> >> Especially considering that the cpu_dai_name is a string literal and the ARM
> >> kernel now has rodata write protection enabled by default, so modifying it
> >> will crash the kernel.
> > 
> > Spoke too soon, you fix this up in the next patch. But I'd just squash that
> > change into this patch. I think it is pretty safe to assume that it is correct.

Yes, I wanted to split trivial change from something which would be nice
to test (I did not test it). However you're right that logically this is
the same change.

> And another thing. Since num_links is always 2 now the last entry from the
> smdk_dai array can be removed and num_links can be initialized using
> ARRAY_SIZE().

Ahh, indeed. The third DAI link (SEC_PLAYBACK) could be removed now.

Thanks for feedback,
Krzysztof

^ permalink raw reply

* [PATCH] coresight: perf: Add a missing call to etm_free_aux
From: Quentin Lambert @ 2016-11-19 18:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161119174124.20136-1-lambert.quentin@gmail.com>


On 11/19/2016 06:41 PM, Quentin Lambert wrote:
> Most error branches following the call to alloc_event_data contain a call to
> etm_free_aux. This patch add a call to etm_free_aux to an error branch
> that does not call it.
>
> This issue was found with Hector.
>
> Signed-off-by: Quentin Lambert <lambert.quentin@gmail.com>
> ---
>   drivers/hwtracing/coresight/coresight-etm-perf.c |    2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> --- a/drivers/hwtracing/coresight/coresight-etm-perf.c
> +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
> @@ -215,7 +215,7 @@ static void *etm_setup_aux(int event_cpu
>   	 */
>   	sink = coresight_get_enabled_sink(true);
>   	if (!sink)
> -		return NULL;
> +		goto err;
>   
>   	INIT_WORK(&event_data->work, free_event_data);
>   
I realized that I hadn't try to compile after having sent this patch and
I wasn't able to compile it.
Therefore, please ignore it for now.

Quentin

^ permalink raw reply

* [PATCH] arm: spin one more cycle in timer-based delays
From: Mason @ 2016-11-19 18:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161119110301.GQ1041@n2100.armlinux.org.uk>

On 19/11/2016 12:03, Russell King - ARM Linux wrote:

> Linus, please see the comment and patch at the bottom of this mail.
> Thanks.
> 
> On Sat, Nov 19, 2016 at 12:47:02PM +0530, Afzal Mohammed wrote:
>> Hi Mason,
>>
>> On Fri, Nov 18, 2016 at 03:18:58PM +0100, Mason wrote:
>>> On 18/11/2016 13:54, Russell King - ARM Linux wrote:
>>
>>>> So, NAK on this change.  udelay is not super-accurate.
>>>
>>> usleep_range() fixed this issue recently.
>>> 6c5e9059692567740a4ee51530dffe51a4b9584d
>>> https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/commit/?h=timers/core&id=6c5e9059692567740a4ee51530dffe51a4b9584d
>>
>> But the above "timers: Fix usleep_range() in the context of
>> wake_up_process()" is to avoid wakeup causing premature return than
>> about being precise, no ?
> 
> usleep*() is different from udelay().  usleep*() is not based on looping
> a certain number of times, and doesn't involve calibration of such a
> loop.

You keep saying that udelay is loop-based. That's merely the fall-back,
when nothing better is available. As you know, there are several better
arch-specific options available (peterz described some on x86).

On my platform, udelay polls a platform tick counter. (In fact, you
were the one to recommend that solution to me years ago). This tick
counter is tied to a high-precision crystal, the error of which is
measured in parts per million. The memory bus to this device offers
some guarantees for the access latency.

IIUC, arm and arm64 even have an architected counter that is
guaranteed to tick at constant frequency, and is accessible
without leaving the CPU core.


> usleep*() is based on the scheduler, which has tighter
> requirements laid down in POSIX amongst other standards, such as "not
> timing out before this specified time" (due to things like select(),
> poll(), etc.)  udelay() is purely a kernel thing, unspecified by any
> standard.

The "problem" with udelay is that the same API exists on every single
kernel ever written, and users have implicit expectations about the
implementation. (Principle of least astonishment)


>> With conflicting opinion on delay/sleep fn's from the players, the one
>> in gallery would get confused.
>>
>> But Linus has mentioned udelay as not meant to be precise, okay ?
> 
> Exactly - and the reason for that (as I've explained several times in
> the past) the "standard" software delay loop calibrated against the
> timer interrupt is _always_ going to be short.

OK, so loop-based delays are known to be short. Would you or Linus
accept a patch that adds a X% cushion *in the implementation* ?

You are saying "people shouldn't expect udelay(10) to delay at least
10 ?s, thus they should write udelay(10+N)".

Why not hide that implementation detail inside the implementation,
so as not to force the pessimization on every other implementation
behind the udelay/ndelay wrapper?

void loop_based_udelay(long us) {
  spin_for_some_us(us + us/8);
}


> I explain why this is in the message to which Linus replied:
> 
>   http://lists.openwall.net/linux-kernel/2011/01/09/56
> 
> A consequence of the formula that I give in (2) in that mail is that
> the higher the HZ value, the more error in the resulting value of
> loops_per_jiffy, and the shorter udelay(1) than 1us will be, since
> "timer_interrupt_usec" is a constant but "usec_per_jiffy" reduces.
> 
> So folk need to put the idea that "udelay(1) will always be at least
> 1us" out of their minds - that's simply not guaranteed by the kernel.
> Linus' reply also indicates that we don't care if it's out by 5%,
> and probably more than that too.
> 
> If someone can show that our timer-based udelay() produces an error
> more than 5%, then I'll apply the patch.

I gave an example where ndelay had a 60% error (37 instead of 100 ns).

If one is using a 1 MHz clock for timer-based delays, udelay(1)
will randomly return immediately (100% error).


> What I don't want to do is
> to apply the patch because someone thinks that udelay() should not
> return early.  Applying it in that case has the effect of re-inforcing
> what is an incorrect assumption, leading to people writing buggy drivers
> that have delays which are too finely "tuned" - which may work with a
> timer-based udelay() but cause failures with a loop-based udelay().

Again, I think it would be much smarter to hide this quirk within
the loop-based delay implementation.

Why is it unacceptable to "fix" the API, instead of fixing the
expectations of driver writers?


> This is all about ensuring that driver authors do the right thing.

What is the rationale behind the devm managed resources?
Driver writers were getting things wrong, and the kernel
provided a framework to help them with the hard part.

Likewise, instead of setting them up to fail with a quirky
delay routine, why not help them by writing an implementation
to match their expectation?


> Linus, how about we add something like this to linux/delay.h to document
> this fact?
> 
>  include/linux/delay.h | 12 +++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/include/linux/delay.h b/include/linux/delay.h
> index a6ecb34cf547..2ecb3c46b20a 100644
> --- a/include/linux/delay.h
> +++ b/include/linux/delay.h
> @@ -5,6 +5,18 @@
>   * Copyright (C) 1993 Linus Torvalds
>   *
>   * Delay routines, using a pre-computed "loops_per_jiffy" value.
> + *
> + * Please note that ndelay(), udelay() and mdelay() may return early for
> + * several reasons:
> + *  1. computed loops_per_jiffy too low (due to the time taken to
> + *     execute the timer interrupt.)
> + *  2. cache behaviour affecting the time it takes to execute the
> + *     loop function.
> + *  3. CPU clock rate changes.
> + * As a result, delays should always be over-stated.
> + *
> + * Please see this thread:
> + *   http://lists.openwall.net/linux-kernel/2011/01/09/56

(None of the reasons you stated affect a tick-counter-based delay.)

If one wants a 100 ns delay, what should one write?
If one wants a 1 ?s delay, what should one write?
If one wants a 100 ?s delay, what should one write?
Is the relative error constant?
Is there a constant component in the error, independent of requested delay?

It seems to me you're saying "on platform A, udelay has 50%
error, so driver writers should write udelay(N+N/2);"

The code is now unnecessarily pessimized on hundreds of platform
that don't have that behavior.

Why not fix the implementation of that platform's udelay to
add the padding itself? That way, other platforms are not
hampered by that platform's ineptitude.

Regards.

^ permalink raw reply

* [PATCH] coresight: perf: Add a missing call to etm_free_aux
From: Quentin Lambert @ 2016-11-19 18:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3e105f1d-c984-358f-a996-b9d3a2d01e0d@gmail.com>



On 11/19/2016 07:22 PM, Quentin Lambert wrote:
>
> On 11/19/2016 06:41 PM, Quentin Lambert wrote:
>> Most error branches following the call to alloc_event_data contain a 
>> call to
>> etm_free_aux. This patch add a call to etm_free_aux to an error branch
>> that does not call it.
>>
>> This issue was found with Hector.
>>
>> Signed-off-by: Quentin Lambert <lambert.quentin@gmail.com>
>> ---
>>   drivers/hwtracing/coresight/coresight-etm-perf.c |    2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> --- a/drivers/hwtracing/coresight/coresight-etm-perf.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
>> @@ -215,7 +215,7 @@ static void *etm_setup_aux(int event_cpu
>>        */
>>       sink = coresight_get_enabled_sink(true);
>>       if (!sink)
>> -        return NULL;
>> +        goto err;
>>         INIT_WORK(&event_data->work, free_event_data);
> I realized that I hadn't try to compile after having sent this patch and
> I wasn't able to compile it.
> Therefore, please ignore it for now.
I have just confirmed that it compiles.

Quentin

^ permalink raw reply

* [PULL] KVM/ARM updates for 4.9-rc6
From: Radim Krčmář @ 2016-11-19 19:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479461966-20136-1-git-send-email-marc.zyngier@arm.com>

2016-11-18 09:39+0000, Marc Zyngier:
> Paolo, Radim,
> 
> Please find below the pull request for a couple of fixes for the
> PMU emulation, courtesy of Wei. Both patches are candidates for stable.

Pulled, thanks.

^ permalink raw reply

* [PATCH] dmaengine: qcom_hidma: autoload while probing ACPI
From: Sinan Kaya @ 2016-11-19 19:28 UTC (permalink / raw)
  To: linux-arm-kernel

MODULE_DEVICE_TABLE is used by the kernel to determine which device driver
should be loaded for which platform device. MODULE_DEVICE_TABLE has been
only defined for the device-tree based platforms in the current code.
Defining it also for ACPI based platforms.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
 drivers/dma/qcom/hidma.c      | 1 +
 drivers/dma/qcom/hidma_mgmt.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index 248e74b..3c982c9 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -895,6 +895,7 @@ static int hidma_remove(struct platform_device *pdev)
 	{"QCOM8062"},
 	{},
 };
+MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
 #endif
 
 static const struct of_device_id hidma_match[] = {
diff --git a/drivers/dma/qcom/hidma_mgmt.c b/drivers/dma/qcom/hidma_mgmt.c
index 985f5ac..f847d32 100644
--- a/drivers/dma/qcom/hidma_mgmt.c
+++ b/drivers/dma/qcom/hidma_mgmt.c
@@ -282,6 +282,7 @@ static int hidma_mgmt_probe(struct platform_device *pdev)
 	{"QCOM8060"},
 	{},
 };
+MODULE_DEVICE_TABLE(acpi, hidma_mgmt_acpi_ids);
 #endif
 
 static const struct of_device_id hidma_mgmt_match[] = {
-- 
1.9.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox