Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH 02/19] phy: stih41x-usb: Remove usb phy driver and dt binding documentation.
From: Kishon Vijay Abraham I @ 2016-11-15 13:07 UTC (permalink / raw)
  To: Peter Griffin, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, patrice.chotard-qxv4g6HH51o,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: lee.jones-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <1473859677-9231-3-git-send-email-peter.griffin-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Hi,

On Wednesday 14 September 2016 06:57 PM, Peter Griffin wrote:
> This phy is only used on STiH415/6 based silicon, and support for
> these SoC's is being removed from the kernel.
> 
> Signed-off-by: Peter Griffin <peter.griffin-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: <kishon-l0cyMroinI0@public.gmane.org>

I've merged the 1st 2 patches of this series. Since Patrice has already
mentioned that he's merged the MAINTAINERS patch, I'm not merging it.
Please let me know if you know of any problems.

Thanks
Kishon

> ---
>  .../devicetree/bindings/phy/phy-stih41x-usb.txt    |  24 ---
>  drivers/phy/Kconfig                                |   8 -
>  drivers/phy/Makefile                               |   1 -
>  drivers/phy/phy-stih41x-usb.c                      | 188 ---------------------
>  4 files changed, 221 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt
>  delete mode 100644 drivers/phy/phy-stih41x-usb.c
> 
> diff --git a/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt b/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt
> deleted file mode 100644
> index 744b480..0000000
> --- a/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt
> +++ /dev/null
> @@ -1,24 +0,0 @@
> -STMicroelectronics STiH41x USB PHY binding
> -------------------------------------------
> -
> -This file contains documentation for the usb phy found in STiH415/6 SoCs from
> -STMicroelectronics.
> -
> -Required properties:
> -- compatible	: should be "st,stih416-usb-phy" or "st,stih415-usb-phy"
> -- st,syscfg	: should be a phandle of the syscfg node
> -- clock-names	: must contain "osc_phy"
> -- clocks	: must contain an entry for each name in clock-names.
> -See: Documentation/devicetree/bindings/clock/clock-bindings.txt
> -- #phy-cells	: must be 0 for this phy
> -See: Documentation/devicetree/bindings/phy/phy-bindings.txt
> -
> -Example:
> -
> -usb2_phy: usb2phy@0 {
> -	compatible	= "st,stih416-usb-phy";
> -	#phy-cells	= <0>;
> -	st,syscfg	= <&syscfg_rear>;
> -	clocks		= <&clk_sysin>;
> -	clock-names	= "osc_phy";
> -};
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index d1f22ac..b4aa039 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -392,14 +392,6 @@ config PHY_STIH407_USB
>  	  Enable this support to enable the picoPHY device used by USB2
>  	  and USB3 controllers on STMicroelectronics STiH407 SoC families.
>  
> -config PHY_STIH41X_USB
> -	tristate "STMicroelectronics USB2 PHY driver for STiH41x series"
> -	depends on ARCH_STI
> -	select GENERIC_PHY
> -	help
> -	  Enable this to support the USB transceiver that is part of
> -	  STMicroelectronics STiH41x SoC series.
> -
>  config PHY_QCOM_UFS
>  	tristate "Qualcomm UFS PHY driver"
>  	depends on OF && ARCH_QCOM
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index d169d80..5e48741 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -45,7 +45,6 @@ obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY)	+= phy-spear1310-miphy.o
>  obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)	+= phy-spear1340-miphy.o
>  obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
>  obj-$(CONFIG_PHY_STIH407_USB)		+= phy-stih407-usb.o
> -obj-$(CONFIG_PHY_STIH41X_USB)		+= phy-stih41x-usb.o
>  obj-$(CONFIG_PHY_QCOM_UFS) 	+= phy-qcom-ufs.o
>  obj-$(CONFIG_PHY_QCOM_UFS) 	+= phy-qcom-ufs-qmp-20nm.o
>  obj-$(CONFIG_PHY_QCOM_UFS) 	+= phy-qcom-ufs-qmp-14nm.o
> diff --git a/drivers/phy/phy-stih41x-usb.c b/drivers/phy/phy-stih41x-usb.c
> deleted file mode 100644
> index 0ac7463..0000000
> --- a/drivers/phy/phy-stih41x-usb.c
> +++ /dev/null
> @@ -1,188 +0,0 @@
> -/*
> - * Copyright (C) 2014 STMicroelectronics
> - *
> - * STMicroelectronics PHY driver for STiH41x USB.
> - *
> - * Author: Maxime Coquelin <maxime.coquelin-qxv4g6HH51o@public.gmane.org>
> - *
> - * 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.
> - *
> - */
> -
> -#include <linux/platform_device.h>
> -#include <linux/io.h>
> -#include <linux/kernel.h>
> -#include <linux/module.h>
> -#include <linux/of.h>
> -#include <linux/of_platform.h>
> -#include <linux/clk.h>
> -#include <linux/phy/phy.h>
> -#include <linux/regmap.h>
> -#include <linux/mfd/syscon.h>
> -
> -#define SYSCFG332  0x80
> -#define SYSCFG2520 0x820
> -
> -/**
> - * struct stih41x_usb_cfg - SoC specific PHY register mapping
> - * @syscfg: Offset in syscfg registers bank
> - * @cfg_mask: Bits mask for PHY configuration
> - * @cfg: Static configuration value for PHY
> - * @oscok: Notify the PHY oscillator clock is ready
> - *	   Setting this bit enable the PHY
> - */
> -struct stih41x_usb_cfg {
> -	u32 syscfg;
> -	u32 cfg_mask;
> -	u32 cfg;
> -	u32 oscok;
> -};
> -
> -/**
> - * struct stih41x_usb_phy - Private data for the PHY
> - * @dev: device for this controller
> - * @regmap: Syscfg registers bank in which PHY is configured
> - * @cfg: SoC specific PHY register mapping
> - * @clk: Oscillator used by the PHY
> - */
> -struct stih41x_usb_phy {
> -	struct device *dev;
> -	struct regmap *regmap;
> -	const struct stih41x_usb_cfg *cfg;
> -	struct clk *clk;
> -};
> -
> -static struct stih41x_usb_cfg stih415_usb_phy_cfg = {
> -	.syscfg = SYSCFG332,
> -	.cfg_mask = 0x3f,
> -	.cfg = 0x38,
> -	.oscok = BIT(6),
> -};
> -
> -static struct stih41x_usb_cfg stih416_usb_phy_cfg = {
> -	.syscfg = SYSCFG2520,
> -	.cfg_mask = 0x33f,
> -	.cfg = 0x238,
> -	.oscok = BIT(6),
> -};
> -
> -static int stih41x_usb_phy_init(struct phy *phy)
> -{
> -	struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy);
> -
> -	return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
> -			   phy_dev->cfg->cfg_mask, phy_dev->cfg->cfg);
> -}
> -
> -static int stih41x_usb_phy_power_on(struct phy *phy)
> -{
> -	struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy);
> -	int ret;
> -
> -	ret = clk_prepare_enable(phy_dev->clk);
> -	if (ret) {
> -		dev_err(phy_dev->dev, "Failed to enable osc_phy clock\n");
> -		return ret;
> -	}
> -
> -	ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
> -				 phy_dev->cfg->oscok, phy_dev->cfg->oscok);
> -	if (ret)
> -		clk_disable_unprepare(phy_dev->clk);
> -
> -	return ret;
> -}
> -
> -static int stih41x_usb_phy_power_off(struct phy *phy)
> -{
> -	struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy);
> -	int ret;
> -
> -	ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
> -			phy_dev->cfg->oscok, 0);
> -	if (ret) {
> -		dev_err(phy_dev->dev, "Failed to clear oscok bit\n");
> -		return ret;
> -	}
> -
> -	clk_disable_unprepare(phy_dev->clk);
> -
> -	return 0;
> -}
> -
> -static const struct phy_ops stih41x_usb_phy_ops = {
> -	.init		= stih41x_usb_phy_init,
> -	.power_on	= stih41x_usb_phy_power_on,
> -	.power_off	= stih41x_usb_phy_power_off,
> -	.owner		= THIS_MODULE,
> -};
> -
> -static const struct of_device_id stih41x_usb_phy_of_match[];
> -
> -static int stih41x_usb_phy_probe(struct platform_device *pdev)
> -{
> -	struct device_node *np = pdev->dev.of_node;
> -	const struct of_device_id *match;
> -	struct stih41x_usb_phy *phy_dev;
> -	struct device *dev = &pdev->dev;
> -	struct phy_provider *phy_provider;
> -	struct phy *phy;
> -
> -	phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL);
> -	if (!phy_dev)
> -		return -ENOMEM;
> -
> -	match = of_match_device(stih41x_usb_phy_of_match, &pdev->dev);
> -	if (!match)
> -		return -ENODEV;
> -
> -	phy_dev->cfg = match->data;
> -
> -	phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
> -	if (IS_ERR(phy_dev->regmap)) {
> -		dev_err(dev, "No syscfg phandle specified\n");
> -		return PTR_ERR(phy_dev->regmap);
> -	}
> -
> -	phy_dev->clk = devm_clk_get(dev, "osc_phy");
> -	if (IS_ERR(phy_dev->clk)) {
> -		dev_err(dev, "osc_phy clk not found\n");
> -		return PTR_ERR(phy_dev->clk);
> -	}
> -
> -	phy = devm_phy_create(dev, NULL, &stih41x_usb_phy_ops);
> -
> -	if (IS_ERR(phy)) {
> -		dev_err(dev, "failed to create phy\n");
> -		return PTR_ERR(phy);
> -	}
> -
> -	phy_dev->dev = dev;
> -
> -	phy_set_drvdata(phy, phy_dev);
> -
> -	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> -	return PTR_ERR_OR_ZERO(phy_provider);
> -}
> -
> -static const struct of_device_id stih41x_usb_phy_of_match[] = {
> -	{ .compatible = "st,stih415-usb-phy", .data = &stih415_usb_phy_cfg },
> -	{ .compatible = "st,stih416-usb-phy", .data = &stih416_usb_phy_cfg },
> -	{ /* sentinel */ },
> -};
> -MODULE_DEVICE_TABLE(of, stih41x_usb_phy_of_match);
> -
> -static struct platform_driver stih41x_usb_phy_driver = {
> -	.probe	= stih41x_usb_phy_probe,
> -	.driver = {
> -		.name	= "stih41x-usb-phy",
> -		.of_match_table	= stih41x_usb_phy_of_match,
> -	}
> -};
> -module_platform_driver(stih41x_usb_phy_driver);
> -
> -MODULE_AUTHOR("Maxime Coquelin <maxime.coquelin-qxv4g6HH51o@public.gmane.org>");
> -MODULE_DESCRIPTION("STMicroelectronics USB PHY driver for STiH41x series");
> -MODULE_LICENSE("GPL v2");
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 2/6] mfd: stm32-adc: Add support for stm32 ADC
From: Jonathan Cameron @ 2016-11-15 13:17 UTC (permalink / raw)
  To: Fabrice Gasnier, Lee Jones, Jonathan Cameron
  Cc: linux-iio, linux-arm-kernel, devicetree, linux-kernel, linux,
	robh+dt, mark.rutland, mcoquelin.stm32, alexandre.torgue, lars,
	knaack.h, pmeerw
In-Reply-To: <687b2001-c658-d0fb-a205-e5b6743fa9bc@st.com>



On 15 November 2016 10:47:52 GMT+00:00, Fabrice Gasnier <fabrice.gasnier@st.com> wrote:
>On 11/14/2016 05:47 PM, Lee Jones wrote:
>> On Sat, 12 Nov 2016, Jonathan Cameron wrote:
>>
>>> On 10/11/16 16:18, 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>
>>> Looks good to me (other than the build issue obviously ;)
>
>Hi Jonathan,
>Thanks for your review.
>I'll fix build issue, sure ;-)
>
>>>
>>> The fun bit will be trying to keep the whole thing this clean as you
>>> add the more 'interesting' functionality.  *fingers crossed*
>Yes... But in the end, splitting shared resources in core driver makes 
>it more simple.
>Not sure there will be more complexity here.
>
>>>
>>> Acked-by: Jonathan Cameron <jic23@kernel.org>
>> There isn't anything MFD about this driver.
>>
>> Please move it into IIO.
>
>Hmm, there is no other sub sysbtem that may be used here, ADC driver 
>belongs to IIO.
>Also, of_platform_populate() is being used here. This can perfectly be 
>called from within IIO.
>
>Jonathan, can this "stm32-adc-core" driver be moved to, and live in 
>drivers/iio/adc ?
>(e.g. in addition to stm32-adc iio driver)
>Is it ok for you ?
Yes. That's ideal. 
>
>Please advise,
>Best Regards,
>Fabrice
>
>>
>>>> ---
>>>>   drivers/mfd/Kconfig                |  14 ++
>>>>   drivers/mfd/Makefile               |   1 +
>>>>   drivers/mfd/stm32-adc-core.c       | 301
>+++++++++++++++++++++++++++++++++++++
>>>>   include/linux/mfd/stm32-adc-core.h |  52 +++++++
>>>>   4 files changed, 368 insertions(+)
>>>>   create mode 100644 drivers/mfd/stm32-adc-core.c
>>>>   create mode 100644 include/linux/mfd/stm32-adc-core.h
>>>>
>>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>>>> index c6df644..2580cee 100644
>>>> --- a/drivers/mfd/Kconfig
>>>> +++ b/drivers/mfd/Kconfig
>>>> @@ -1152,6 +1152,20 @@ config MFD_PALMAS
>>>>   	  If you say yes here you get support for the Palmas
>>>>   	  series of PMIC chips from Texas Instruments.
>>>>   
>>>> +config MFD_STM32_ADC
>>>> +	tristate "STMicroelectronics STM32 adc"
>>>> +	depends on ARCH_STM32 || COMPILE_TEST
>>>> +	depends on OF
>>>> +	select MFD_CORE
>>>> +	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 TPS6105X
>>>>   	tristate "TI TPS61050/61052 Boost Converters"
>>>>   	depends on I2C
>>>> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
>>>> index 9834e66..4571506 100644
>>>> --- a/drivers/mfd/Makefile
>>>> +++ b/drivers/mfd/Makefile
>>>> @@ -185,6 +185,7 @@ obj-$(CONFIG_MFD_INTEL_LPSS_PCI)	+=
>intel-lpss-pci.o
>>>>   obj-$(CONFIG_MFD_INTEL_LPSS_ACPI)	+= intel-lpss-acpi.o
>>>>   obj-$(CONFIG_MFD_INTEL_MSIC)	+= intel_msic.o
>>>>   obj-$(CONFIG_MFD_PALMAS)	+= palmas.o
>>>> +obj-$(CONFIG_MFD_STM32_ADC) 	+= stm32-adc-core.o
>>>>   obj-$(CONFIG_MFD_VIPERBOARD)    += viperboard.o
>>>>   obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
>>>>   obj-$(CONFIG_MFD_RK808)		+= rk808.o
>>>> diff --git a/drivers/mfd/stm32-adc-core.c
>b/drivers/mfd/stm32-adc-core.c
>>>> new file mode 100644
>>>> index 0000000..bcf52fb
>>>> --- /dev/null
>>>> +++ b/drivers/mfd/stm32-adc-core.c
>>>> @@ -0,0 +1,301 @@
>>>> +/*
>>>> + * 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/mfd/stm32-adc-core.h>
>>>> +#include <linux/module.h>
>>>> +#include <linux/of_device.h>
>>>> +#include <linux/regulator/consumer.h>
>>>> +#include <linux/slab.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 MFD driver");
>>>> +MODULE_LICENSE("GPL v2");
>>>> +MODULE_ALIAS("platform:stm32-adc-core");
>>>> diff --git a/include/linux/mfd/stm32-adc-core.h
>b/include/linux/mfd/stm32-adc-core.h
>>>> new file mode 100644
>>>> index 0000000..081fa5f
>>>> --- /dev/null
>>>> +++ b/include/linux/mfd/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
>>>>
>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply

* Re: [PATCH v4 2/3] PCI: qcom: add support to msm8996 PCIE controller
From: Srinivas Kandagatla @ 2016-11-15 13:22 UTC (permalink / raw)
  To: Stanimir Varbanov, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <aa135735-4ff4-06e3-7899-1255a21edfb4-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org>



On 15/11/16 12:24, Stanimir Varbanov wrote:
> Hi Srini,
>
> On 11/14/2016 01:15 PM, Srinivas Kandagatla wrote:
>> This patch adds support to msm8996/apq8096 pcie, MSM8996 supports
>> Gen 1/2, One lane, 3 pcie root-complex with support to MSI and
>> legacy interrupts and it conforms to PCI Express Base 2.1 specification.
>>
>> This patch adds post_init callback to qcom_pcie_ops, as this is pcie
>> pipe clocks are only setup after the phy is powered on.
>> It also adds ltssm_enable callback as it is very much different to other
>> supported SOCs in the driver.
>>
>> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> With below comments addressed:
>
> Acked-by: Stanimir Varbanov <svarbanov-NEYub+7Iv8PQT0dZR+AlfA@public.gmane.org>
Thanks for the ack.
>
>> ---
>>  .../devicetree/bindings/pci/qcom,pcie.txt          |  67 +++++++-
>>  drivers/pci/host/pcie-qcom.c                       | 177 ++++++++++++++++++++-
>>  2 files changed, 238 insertions(+), 6 deletions(-)
>>
>
> <snip>
>
>> diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/host/pcie-qcom.c
>> index 3593640..03ba6b1 100644
>> --- a/drivers/pci/host/pcie-qcom.c
>> +++ b/drivers/pci/host/pcie-qcom.c
>> @@ -36,11 +36,19 @@
>>
>>  #include "pcie-designware.h"
>>
>> +#define PCIE20_PARF_DBI_BASE_ADDR	0x168
>
> This is already defined few rows below, please drop it.
>
Yep, will remove this.
>> +
>> +#define PCIE20_PARF_SYS_CTRL			0x00
>>  #define PCIE20_PARF_PHY_CTRL			0x40
>>  #define PCIE20_PARF_PHY_REFCLK			0x4C
>>  #define PCIE20_PARF_DBI_BASE_ADDR		0x168
>>  #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE		0x16c
>> +#define PCIE20_PARF_MHI_CLOCK_RESET_CTRL	0x174
>>  #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT	0x178
>> +#define MSM8996_PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT   0x1A8
>
> I don't like MSM8996_ prefix. Could you invent a macro which depending
> on controller selects proper offset?

maybe some like this ??

#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2    0x1A8


--srini
>
>> +#define PCIE20_PARF_LTSSM			0x1B0
>> +#define PCIE20_PARF_SID_OFFSET			0x234
>> +#define PCIE20_PARF_BDF_TRANSLATE_CFG		0x24C
>>
>>  #define PCIE20_ELBI_SYS_CTRL			0x04
>>  #define PCIE20_ELBI_SYS_CTRL_LT_ENABLE		BIT(0)
>> @@ -72,9 +80,18 @@ struct qcom_pcie_resources_v1 {
>>  	struct regulator *vdda;
>>  };
>>
>> +struct qcom_pcie_resources_v2 {
>> +	struct clk *aux_clk;
>> +	struct clk *master_clk;
>> +	struct clk *slave_clk;
>> +	struct clk *cfg_clk;
>> +	struct clk *pipe_clk;
>> +};
>
> <snip>
>
> regards,
> Stan
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 3/6] iio: adc: Add support for STM32 ADC
From: Fabrice Gasnier @ 2016-11-15 13:24 UTC (permalink / raw)
  To: Jonathan Cameron, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: lee.jones-QSEj5FYQhm4dnm+yROfE0A, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w,
	alexandre.torgue-qxv4g6HH51o, lars-Qo5EllUWu/uELgA04lAiVw,
	knaack.h-Mmb7MZpHnFY, pmeerw-jW+XmwGofnusTnJN9+BGXg
In-Reply-To: <4c5cd26d-97a5-f7a8-fdb6-9413975a3b10-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

On 11/12/2016 06:08 PM, Jonathan Cameron wrote:
> On 10/11/16 16:18, Fabrice Gasnier wrote:
>> This patch adds support for STMicroelectronics STM32 MCU's analog to
>> digital converter.
>>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier-qxv4g6HH51o@public.gmane.org>
> Nice and clean - few minor things inline.
>
> Jonathan
>> ---
>>   drivers/iio/adc/Kconfig     |  10 +
>>   drivers/iio/adc/Makefile    |   1 +
>>   drivers/iio/adc/stm32-adc.c | 525 ++++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 536 insertions(+)
>>   create mode 100644 drivers/iio/adc/stm32-adc.c
>>
>> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
>> index 7edcf32..61ba674 100644
>> --- a/drivers/iio/adc/Kconfig
>> +++ b/drivers/iio/adc/Kconfig
>> @@ -419,6 +419,16 @@ config ROCKCHIP_SARADC
>>   	  To compile this driver as a module, choose M here: the
>>   	  module will be called rockchip_saradc.
>>   
>> +config STM32_ADC
>> +	tristate "STMicroelectronics STM32 adc"
>> +	depends on MFD_STM32_ADC
>> +	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 7a40c04..df7a221 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) += 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..2be5fee
>> --- /dev/null
>> +++ b/drivers/iio/adc/stm32-adc.c
>> @@ -0,0 +1,525 @@
>> +/*
>> + * This file is part of STM32 ADC driver
>> + *
>> + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
>> + * Author: Fabrice Gasnier <fabrice.gasnier-qxv4g6HH51o@public.gmane.org>.
>> + *
>> + * 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/mfd/stm32-adc-core.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/of.h>
>> +
>> +/* STM32F4 - Registers for each ADC instance */
> Not really sure the X adds anything in these, but doesn't do much harm
> I guess ;)
You're right. I'll remove the X. I initially added that to remind this 
stands for ADC1, 2 or 3...
Moreover, removing it will make register name match with reference manual.
>> +#define STM32F4_ADCX_SR			0x00
>> +#define STM32F4_ADCX_CR1		0x04
>> +#define STM32F4_ADCX_CR2		0x08
>> +#define STM32F4_ADCX_SMPR1		0x0C
>> +#define STM32F4_ADCX_SMPR2		0x10
>> +#define STM32F4_ADCX_HTR		0x24
>> +#define STM32F4_ADCX_LTR		0x28
>> +#define STM32F4_ADCX_SQR1		0x2C
>> +#define STM32F4_ADCX_SQR2		0x30
>> +#define STM32F4_ADCX_SQR3		0x34
>> +#define STM32F4_ADCX_JSQR		0x38
>> +#define STM32F4_ADCX_JDR1		0x3C
>> +#define STM32F4_ADCX_JDR2		0x40
>> +#define STM32F4_ADCX_JDR3		0x44
>> +#define STM32F4_ADCX_JDR4		0x48
>> +#define STM32F4_ADCX_DR			0x4C
>> +
>> +/* STM32F4_ADCX_SR - bit fields */
>> +#define STM32F4_OVR			BIT(5)
>> +#define STM32F4_STRT			BIT(4)
>> +#define STM32F4_EOC			BIT(1)
>> +
>> +/* STM32F4_ADCX_CR1 - bit fields */
>> +#define STM32F4_OVRIE			BIT(26)
>> +#define STM32F4_SCAN			BIT(8)
>> +#define STM32F4_EOCIE			BIT(5)
>> +
>> +/* STM32F4_ADCX_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_ADCX_SQR1 - bit fields */
>> +#define STM32F4_L_SHIFT			20
>> +#define STM32F4_L_MASK			GENMASK(23, 20)
>> +
>> +/* STM32F4_ADCX_SQR3 - bit fields */
>> +#define STM32F4_SQ1_SHIFT		0
>> +#define STM32F4_SQ1_MASK		GENMASK(4, 0)
>> +
>> +#define STM32_ADC_MAX_SQ		16	/* SQ1..SQ16 */
>> +#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:		optional adc 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 u32 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_ADCX_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_ADCX_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_ADCX_CR1, STM32F4_SCAN);
>> +	stm32_adc_set_bits(adc, STM32F4_ADCX_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_ADCX_CR2) & STM32F4_EXTEN_MASK))
>> +		stm32_adc_set_bits(adc, STM32F4_ADCX_CR2, STM32F4_SWSTART);
>> +}
>> +
>> +static void stm32_adc_stop_conv(struct stm32_adc *adc)
>> +{
>> +	stm32_adc_clr_bits(adc, STM32F4_ADCX_CR2, STM32F4_EXTEN_MASK);
>> +	stm32_adc_clr_bits(adc, STM32F4_ADCX_SR, STM32F4_STRT);
>> +
>> +	stm32_adc_clr_bits(adc, STM32F4_ADCX_CR1, STM32F4_SCAN);
>> +	stm32_adc_clr_bits(adc, STM32F4_ADCX_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_ADCX_SQR3);
>> +	val &= ~STM32F4_SQ1_MASK;
>> +	val |= chan->channel << STM32F4_SQ1_SHIFT;
>> +	stm32_adc_writel(adc, STM32F4_ADCX_SQR3, val);
>> +
>> +	/* Set regular sequence len (0 for 1 conversion) */
>> +	stm32_adc_clr_bits(adc, STM32F4_ADCX_SQR1, STM32F4_L_MASK);
>> +
>> +	/* Trigger detection disabled (conversion can be launched in SW) */
>> +	stm32_adc_clr_bits(adc, STM32F4_ADCX_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) {
>> +		dev_warn(&indio_dev->dev, "Conversion timed out!\n");
>> +		ret = -ETIMEDOUT;
>> +	} else if (timeout < 0) {
>> +		dev_warn(&indio_dev->dev, "Interrupted conversion!\n");
>> +		ret = -EINTR;
>> +	} 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 = -EINVAL;
>> +
>> +	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 directly here.  Basically always preferred to return directly if
> there is not cleanup to be done.
I will fix it.
>> +		break;
>> +	case IIO_CHAN_INFO_SCALE:
>> +		*val = adc->common->vref_mv;
>> +		*val2 = chan->scan_type.realbits;
>> +		ret = IIO_VAL_FRACTIONAL_LOG2;
> return directly here.
I will fix it.
>> +		break;
>> +	default:
> return -EINVAL here.
I will fix it.
>> +		break;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static irqreturn_t stm32_adc_isr(int irq, void *data)
>> +{
>> +	struct stm32_adc *adc = data;
>> +	u32 status = stm32_adc_readl(adc, STM32F4_ADCX_SR);
>> +	irqreturn_t ret = IRQ_NONE;
>> +
>> +	if (status & STM32F4_EOC) {
>> +		*adc->buffer = stm32_adc_readw(adc, STM32F4_ADCX_DR);
>> +		complete(&adc->completion);
>> +		ret = IRQ_HANDLED;
> Slightly tidier to return IRQ_HANDLED here and directly return
> IRQ_NONE below.
I will fix it.
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +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->extend_name = channel->name;
> Don't set extend_name. That name doesn't add sufficient information to
> make it worth adding custom ABI to the userspace interface.
I will fix it.
>
>
>> +	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)) {
> Could it concievably be deferred?  Would be happier if this explicitly
> checked for -ENODEV or whatever gets returned when not clock has
> been specified.
I will fix it.
>> +		adc->clk = NULL;
>> +		dev_dbg(&pdev->dev, "No child clk found\n");
>> +	} else {
>> +		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 = devm_iio_device_register(&pdev->dev, indio_dev);
> This use of devm registration is going to cause a race in the remove.
> The userspace interface will not be removed until after the remove
> function has run.  That disables the clock thus leaving us a window
> where we could try and access the device with no clock enabled.
>
> Basic rule of thumb is that use of devm must not effect the ordering
> of unrolling what you do in probe when it comes to remove.
> (which more or less means that you can't use devm_iio_device_register
> unless you have no remove at all).
I will fix it.

Thanks,
Fabrice
>> +	if (ret) {
>> +		dev_err(&pdev->dev, "iio dev register failed\n");
>> +		goto err_clk_disable;
>> +	}
>> +
>> +	return 0;
>> +
>> +err_clk_disable:
>> +	if (adc->clk)
>> +		clk_disable_unprepare(adc->clk);
>> +
>> +	return ret;
>> +}
>> +
>> +static int stm32_adc_remove(struct platform_device *pdev)
>> +{
>> +	struct stm32_adc *adc = platform_get_drvdata(pdev);
>> +
>> +	if (adc->clk)
>> +		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-qxv4g6HH51o@public.gmane.org>");
>> +MODULE_DESCRIPTION("STMicroelectronics STM32 ADC IIO driver");
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_ALIAS("platform:stm32-adc");
>>

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 3/6] iio: adc: Add support for STM32 ADC
From: Fabrice Gasnier @ 2016-11-15 13:26 UTC (permalink / raw)
  To: Lars-Peter Clausen, linux-iio, linux-arm-kernel, devicetree,
	linux-kernel
  Cc: jic23, lee.jones, linux, robh+dt, mark.rutland, mcoquelin.stm32,
	alexandre.torgue, knaack.h, pmeerw
In-Reply-To: <535ffb14-a92f-1556-a4cb-f2be0508289a@metafoo.de>

On 11/14/2016 01:11 PM, Lars-Peter Clausen wrote:
> On 11/10/2016 05:18 PM, Fabrice Gasnier wrote:
> [...]
>> + 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_ADCX_SQR3);
>> +	val &= ~STM32F4_SQ1_MASK;
>> +	val |= chan->channel << STM32F4_SQ1_SHIFT;
>> +	stm32_adc_writel(adc, STM32F4_ADCX_SQR3, val);
>> +
>> +	/* Set regular sequence len (0 for 1 conversion) */
>> +	stm32_adc_clr_bits(adc, STM32F4_ADCX_SQR1, STM32F4_L_MASK);
>> +
>> +	/* Trigger detection disabled (conversion can be launched in SW) */
>> +	stm32_adc_clr_bits(adc, STM32F4_ADCX_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) {
>> +		dev_warn(&indio_dev->dev, "Conversion timed out!\n");
> This should be dev_dbg() at most. This out of band reporting is not
> particular useful for applications as it is impossible to match the error to
> the action that triggered it. And you also report the error through the
> error code, so the applications knows what is going on.
>
>> +		ret = -ETIMEDOUT;
>> +	} else if (timeout < 0) {
>> +		dev_warn(&indio_dev->dev, "Interrupted conversion!\n");
>> +		ret = -EINTR;
> This should just propagate the error returned by wait_for_completion...().
> This will make sure that the right behavior occurs based on the SA_RESTART
> policy.
Hi Lars,

Thanks for reviewing.
I'll update this in next revision.

Regards,
Fabrice

>
>> +	} else {
>> +		*res = result;
>> +		ret = IIO_VAL_INT;
>> +	}
>> +
>> +	stm32_adc_stop_conv(adc);
>> +
>> +	stm32_adc_conv_irq_disable(adc);
>> +
>> +	return ret;

^ permalink raw reply

* Re: [PATCH v3 1/2] phy: rockchip-inno-usb2: support otg-port for rk3399
From: Kishon Vijay Abraham I @ 2016-11-15 13:39 UTC (permalink / raw)
  To: William Wu, heiko-4mtYJXux2i+zQB+pC5nmwQ
  Cc: huangtao-TNX95d0MmH7DzftRWevZcw,
	devicetree-u79uwXL29TY76Z2rM5mHXA, groeck-hpIqsD4AKlfQT0dZR+AlfA,
	frank.wang-TNX95d0MmH7DzftRWevZcw,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dianders-hpIqsD4AKlfQT0dZR+AlfA,
	linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	briannorris-hpIqsD4AKlfQT0dZR+AlfA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <1478520529-8869-2-git-send-email-wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>



On Monday 07 November 2016 05:38 PM, William Wu wrote:
> The rk3399 SoC USB2 PHY is comprised of one Host port and
> one OTG port. And OTG port is for USB2.0 part of USB3.0 OTG
> controller, as a part to construct a fully feature Type-C
> subsystem.
> 
> With this patch, we can support OTG port with the following
> functions:
> - Support BC1.2 charger detect, and use extcon notifier to
>   send USB charger types to power driver.
> - Support PHY suspend for power management.
> - Support OTG Host only mode.
> 
> Signed-off-by: William Wu <wulf-TNX95d0MmH7DzftRWevZcw@public.gmane.org>

merged.

Thanks
Kishon
> ---
> Changes in v3:
> - split the clock fix into a separate patch 
> 
> Changes in v2:
> - remove wakelock
> 
>  drivers/phy/phy-rockchip-inno-usb2.c | 591 +++++++++++++++++++++++++++++++++--
>  1 file changed, 561 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/phy-rockchip-inno-usb2.c
> index ac20310..ecfd7d1 100644
> --- a/drivers/phy/phy-rockchip-inno-usb2.c
> +++ b/drivers/phy/phy-rockchip-inno-usb2.c
> @@ -17,6 +17,7 @@
>  #include <linux/clk.h>
>  #include <linux/clk-provider.h>
>  #include <linux/delay.h>
> +#include <linux/extcon.h>
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
>  #include <linux/gpio/consumer.h>
> @@ -30,11 +31,15 @@
>  #include <linux/of_platform.h>
>  #include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
> +#include <linux/power_supply.h>
>  #include <linux/regmap.h>
>  #include <linux/mfd/syscon.h>
> +#include <linux/usb/of.h>
> +#include <linux/usb/otg.h>
>  
>  #define BIT_WRITEABLE_SHIFT	16
> -#define SCHEDULE_DELAY	(60 * HZ)
> +#define SCHEDULE_DELAY		(60 * HZ)
> +#define OTG_SCHEDULE_DELAY	(2 * HZ)
>  
>  enum rockchip_usb2phy_port_id {
>  	USB2PHY_PORT_OTG,
> @@ -49,6 +54,37 @@ enum rockchip_usb2phy_host_state {
>  	PHY_STATE_FS_LS_ONLINE	= 4,
>  };
>  
> +/**
> + * Different states involved in USB charger detection.
> + * USB_CHG_STATE_UNDEFINED	USB charger is not connected or detection
> + *				process is not yet started.
> + * USB_CHG_STATE_WAIT_FOR_DCD	Waiting for Data pins contact.
> + * USB_CHG_STATE_DCD_DONE	Data pin contact is detected.
> + * USB_CHG_STATE_PRIMARY_DONE	Primary detection is completed (Detects
> + *				between SDP and DCP/CDP).
> + * USB_CHG_STATE_SECONDARY_DONE	Secondary detection is completed (Detects
> + *				between DCP and CDP).
> + * USB_CHG_STATE_DETECTED	USB charger type is determined.
> + */
> +enum usb_chg_state {
> +	USB_CHG_STATE_UNDEFINED = 0,
> +	USB_CHG_STATE_WAIT_FOR_DCD,
> +	USB_CHG_STATE_DCD_DONE,
> +	USB_CHG_STATE_PRIMARY_DONE,
> +	USB_CHG_STATE_SECONDARY_DONE,
> +	USB_CHG_STATE_DETECTED,
> +};
> +
> +static const unsigned int rockchip_usb2phy_extcon_cable[] = {
> +	EXTCON_USB,
> +	EXTCON_USB_HOST,
> +	EXTCON_CHG_USB_SDP,
> +	EXTCON_CHG_USB_CDP,
> +	EXTCON_CHG_USB_DCP,
> +	EXTCON_CHG_USB_SLOW,
> +	EXTCON_NONE,
> +};
> +
>  struct usb2phy_reg {
>  	unsigned int	offset;
>  	unsigned int	bitend;
> @@ -58,19 +94,55 @@ struct usb2phy_reg {
>  };
>  
>  /**
> + * struct rockchip_chg_det_reg: usb charger detect registers
> + * @cp_det: charging port detected successfully.
> + * @dcp_det: dedicated charging port detected successfully.
> + * @dp_det: assert data pin connect successfully.
> + * @idm_sink_en: open dm sink curren.
> + * @idp_sink_en: open dp sink current.
> + * @idp_src_en: open dm source current.
> + * @rdm_pdwn_en: open dm pull down resistor.
> + * @vdm_src_en: open dm voltage source.
> + * @vdp_src_en: open dp voltage source.
> + * @opmode: utmi operational mode.
> + */
> +struct rockchip_chg_det_reg {
> +	struct usb2phy_reg	cp_det;
> +	struct usb2phy_reg	dcp_det;
> +	struct usb2phy_reg	dp_det;
> +	struct usb2phy_reg	idm_sink_en;
> +	struct usb2phy_reg	idp_sink_en;
> +	struct usb2phy_reg	idp_src_en;
> +	struct usb2phy_reg	rdm_pdwn_en;
> +	struct usb2phy_reg	vdm_src_en;
> +	struct usb2phy_reg	vdp_src_en;
> +	struct usb2phy_reg	opmode;
> +};
> +
> +/**
>   * struct rockchip_usb2phy_port_cfg: usb-phy port configuration.
>   * @phy_sus: phy suspend register.
> + * @bvalid_det_en: vbus valid rise detection enable register.
> + * @bvalid_det_st: vbus valid rise detection status register.
> + * @bvalid_det_clr: vbus valid rise detection clear register.
>   * @ls_det_en: linestate detection enable register.
>   * @ls_det_st: linestate detection state register.
>   * @ls_det_clr: linestate detection clear register.
> + * @utmi_avalid: utmi vbus avalid status register.
> + * @utmi_bvalid: utmi vbus bvalid status register.
>   * @utmi_ls: utmi linestate state register.
>   * @utmi_hstdet: utmi host disconnect register.
>   */
>  struct rockchip_usb2phy_port_cfg {
>  	struct usb2phy_reg	phy_sus;
> +	struct usb2phy_reg	bvalid_det_en;
> +	struct usb2phy_reg	bvalid_det_st;
> +	struct usb2phy_reg	bvalid_det_clr;
>  	struct usb2phy_reg	ls_det_en;
>  	struct usb2phy_reg	ls_det_st;
>  	struct usb2phy_reg	ls_det_clr;
> +	struct usb2phy_reg	utmi_avalid;
> +	struct usb2phy_reg	utmi_bvalid;
>  	struct usb2phy_reg	utmi_ls;
>  	struct usb2phy_reg	utmi_hstdet;
>  };
> @@ -80,31 +152,51 @@ struct rockchip_usb2phy_port_cfg {
>   * @reg: the address offset of grf for usb-phy config.
>   * @num_ports: specify how many ports that the phy has.
>   * @clkout_ctl: keep on/turn off output clk of phy.
> + * @chg_det: charger detection registers.
>   */
>  struct rockchip_usb2phy_cfg {
>  	unsigned int	reg;
>  	unsigned int	num_ports;
>  	struct usb2phy_reg	clkout_ctl;
>  	const struct rockchip_usb2phy_port_cfg	port_cfgs[USB2PHY_NUM_PORTS];
> +	const struct rockchip_chg_det_reg	chg_det;
>  };
>  
>  /**
>   * struct rockchip_usb2phy_port: usb-phy port data.
>   * @port_id: flag for otg port or host port.
>   * @suspended: phy suspended flag.
> + * @utmi_avalid: utmi avalid status usage flag.
> + *	true	- use avalid to get vbus status
> + *	flase	- use bvalid to get vbus status
> + * @vbus_attached: otg device vbus status.
> + * @bvalid_irq: IRQ number assigned for vbus valid rise detection.
>   * @ls_irq: IRQ number assigned for linestate detection.
>   * @mutex: for register updating in sm_work.
> - * @sm_work: OTG state machine work.
> + * @chg_work: charge detect work.
> + * @otg_sm_work: OTG state machine work.
> + * @sm_work: HOST state machine work.
>   * @phy_cfg: port register configuration, assigned by driver data.
> + * @event_nb: hold event notification callback.
> + * @state: define OTG enumeration states before device reset.
> + * @mode: the dr_mode of the controller.
>   */
>  struct rockchip_usb2phy_port {
>  	struct phy	*phy;
>  	unsigned int	port_id;
>  	bool		suspended;
> +	bool		utmi_avalid;
> +	bool		vbus_attached;
> +	int		bvalid_irq;
>  	int		ls_irq;
>  	struct mutex	mutex;
> +	struct		delayed_work chg_work;
> +	struct		delayed_work otg_sm_work;
>  	struct		delayed_work sm_work;
>  	const struct	rockchip_usb2phy_port_cfg *port_cfg;
> +	struct notifier_block	event_nb;
> +	enum usb_otg_state	state;
> +	enum usb_dr_mode	mode;
>  };
>  
>  /**
> @@ -113,6 +205,11 @@ struct rockchip_usb2phy_port {
>   * @clk: clock struct of phy input clk.
>   * @clk480m: clock struct of phy output clk.
>   * @clk_hw: clock struct of phy output clk management.
> + * @chg_state: states involved in USB charger detection.
> + * @chg_type: USB charger types.
> + * @dcd_retries: The retry count used to track Data contact
> + *		 detection process.
> + * @edev: extcon device for notification registration
>   * @phy_cfg: phy register configuration, assigned by driver data.
>   * @ports: phy port instance.
>   */
> @@ -122,6 +219,10 @@ struct rockchip_usb2phy {
>  	struct clk	*clk;
>  	struct clk	*clk480m;
>  	struct clk_hw	clk480m_hw;
> +	enum usb_chg_state	chg_state;
> +	enum power_supply_type	chg_type;
> +	u8			dcd_retries;
> +	struct extcon_dev	*edev;
>  	const struct rockchip_usb2phy_cfg	*phy_cfg;
>  	struct rockchip_usb2phy_port	ports[USB2PHY_NUM_PORTS];
>  };
> @@ -263,33 +364,84 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
>  	return ret;
>  }
>  
> -static int rockchip_usb2phy_init(struct phy *phy)
> +static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
>  {
> -	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
> -	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
>  	int ret;
> +	struct device_node *node = rphy->dev->of_node;
> +	struct extcon_dev *edev;
> +
> +	if (of_property_read_bool(node, "extcon")) {
> +		edev = extcon_get_edev_by_phandle(rphy->dev, 0);
> +		if (IS_ERR(edev)) {
> +			if (PTR_ERR(edev) != -EPROBE_DEFER)
> +				dev_err(rphy->dev, "Invalid or missing extcon\n");
> +			return PTR_ERR(edev);
> +		}
> +	} else {
> +		/* Initialize extcon device */
> +		edev = devm_extcon_dev_allocate(rphy->dev,
> +						rockchip_usb2phy_extcon_cable);
>  
> -	if (rport->port_id == USB2PHY_PORT_HOST) {
> -		/* clear linestate and enable linestate detect irq */
> -		mutex_lock(&rport->mutex);
> +		if (IS_ERR(edev))
> +			return -ENOMEM;
>  
> -		ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
> +		ret = devm_extcon_dev_register(rphy->dev, edev);
>  		if (ret) {
> -			mutex_unlock(&rport->mutex);
> +			dev_err(rphy->dev, "failed to register extcon device\n");
>  			return ret;
>  		}
> +	}
>  
> -		ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
> -		if (ret) {
> -			mutex_unlock(&rport->mutex);
> -			return ret;
> +	rphy->edev = edev;
> +
> +	return 0;
> +}
> +
> +static int rockchip_usb2phy_init(struct phy *phy)
> +{
> +	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
> +	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
> +	int ret = 0;
> +
> +	mutex_lock(&rport->mutex);
> +
> +	if (rport->port_id == USB2PHY_PORT_OTG) {
> +		if (rport->mode != USB_DR_MODE_HOST) {
> +			/* clear bvalid status and enable bvalid detect irq */
> +			ret = property_enable(rphy,
> +					      &rport->port_cfg->bvalid_det_clr,
> +					      true);
> +			if (ret)
> +				goto out;
> +
> +			ret = property_enable(rphy,
> +					      &rport->port_cfg->bvalid_det_en,
> +					      true);
> +			if (ret)
> +				goto out;
> +
> +			schedule_delayed_work(&rport->otg_sm_work,
> +					      OTG_SCHEDULE_DELAY);
> +		} else {
> +			/* If OTG works in host only mode, do nothing. */
> +			dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
>  		}
> +	} else if (rport->port_id == USB2PHY_PORT_HOST) {
> +		/* clear linestate and enable linestate detect irq */
> +		ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
> +		if (ret)
> +			goto out;
> +
> +		ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
> +		if (ret)
> +			goto out;
>  
> -		mutex_unlock(&rport->mutex);
>  		schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
>  	}
>  
> -	return 0;
> +out:
> +	mutex_unlock(&rport->mutex);
> +	return ret;
>  }
>  
>  static int rockchip_usb2phy_power_on(struct phy *phy)
> @@ -340,7 +492,11 @@ static int rockchip_usb2phy_exit(struct phy *phy)
>  {
>  	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
>  
> -	if (rport->port_id == USB2PHY_PORT_HOST)
> +	if (rport->port_id == USB2PHY_PORT_OTG &&
> +	    rport->mode != USB_DR_MODE_HOST) {
> +		cancel_delayed_work_sync(&rport->otg_sm_work);
> +		cancel_delayed_work_sync(&rport->chg_work);
> +	} else if (rport->port_id == USB2PHY_PORT_HOST)
>  		cancel_delayed_work_sync(&rport->sm_work);
>  
>  	return 0;
> @@ -354,6 +510,249 @@ static const struct phy_ops rockchip_usb2phy_ops = {
>  	.owner		= THIS_MODULE,
>  };
>  
> +static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
> +{
> +	struct rockchip_usb2phy_port *rport =
> +		container_of(work, struct rockchip_usb2phy_port,
> +			     otg_sm_work.work);
> +	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
> +	static unsigned int cable;
> +	unsigned long delay;
> +	bool vbus_attach, sch_work, notify_charger;
> +
> +	if (rport->utmi_avalid)
> +		vbus_attach =
> +			property_enabled(rphy, &rport->port_cfg->utmi_avalid);
> +	else
> +		vbus_attach =
> +			property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
> +
> +	sch_work = false;
> +	notify_charger = false;
> +	delay = OTG_SCHEDULE_DELAY;
> +	dev_dbg(&rport->phy->dev, "%s otg sm work\n",
> +		usb_otg_state_string(rport->state));
> +
> +	switch (rport->state) {
> +	case OTG_STATE_UNDEFINED:
> +		rport->state = OTG_STATE_B_IDLE;
> +		if (!vbus_attach)
> +			rockchip_usb2phy_power_off(rport->phy);
> +		/* fall through */
> +	case OTG_STATE_B_IDLE:
> +		if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) > 0) {
> +			dev_dbg(&rport->phy->dev, "usb otg host connect\n");
> +			rport->state = OTG_STATE_A_HOST;
> +			rockchip_usb2phy_power_on(rport->phy);
> +			return;
> +		} else if (vbus_attach) {
> +			dev_dbg(&rport->phy->dev, "vbus_attach\n");
> +			switch (rphy->chg_state) {
> +			case USB_CHG_STATE_UNDEFINED:
> +				schedule_delayed_work(&rport->chg_work, 0);
> +				return;
> +			case USB_CHG_STATE_DETECTED:
> +				switch (rphy->chg_type) {
> +				case POWER_SUPPLY_TYPE_USB:
> +					dev_dbg(&rport->phy->dev,
> +						"sdp cable is connecetd\n");
> +					rockchip_usb2phy_power_on(rport->phy);
> +					rport->state = OTG_STATE_B_PERIPHERAL;
> +					notify_charger = true;
> +					sch_work = true;
> +					cable = EXTCON_CHG_USB_SDP;
> +					break;
> +				case POWER_SUPPLY_TYPE_USB_DCP:
> +					dev_dbg(&rport->phy->dev,
> +						"dcp cable is connecetd\n");
> +					rockchip_usb2phy_power_off(rport->phy);
> +					notify_charger = true;
> +					sch_work = true;
> +					cable = EXTCON_CHG_USB_DCP;
> +					break;
> +				case POWER_SUPPLY_TYPE_USB_CDP:
> +					dev_dbg(&rport->phy->dev,
> +						"cdp cable is connecetd\n");
> +					rockchip_usb2phy_power_on(rport->phy);
> +					rport->state = OTG_STATE_B_PERIPHERAL;
> +					notify_charger = true;
> +					sch_work = true;
> +					cable = EXTCON_CHG_USB_CDP;
> +					break;
> +				default:
> +					break;
> +				}
> +				break;
> +			default:
> +				break;
> +			}
> +		} else {
> +			notify_charger = true;
> +			rphy->chg_state = USB_CHG_STATE_UNDEFINED;
> +			rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
> +		}
> +
> +		if (rport->vbus_attached != vbus_attach) {
> +			rport->vbus_attached = vbus_attach;
> +
> +			if (notify_charger && rphy->edev)
> +				extcon_set_cable_state_(rphy->edev,
> +							cable, vbus_attach);
> +		}
> +		break;
> +	case OTG_STATE_B_PERIPHERAL:
> +		if (!vbus_attach) {
> +			dev_dbg(&rport->phy->dev, "usb disconnect\n");
> +			rphy->chg_state = USB_CHG_STATE_UNDEFINED;
> +			rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
> +			rport->state = OTG_STATE_B_IDLE;
> +			delay = 0;
> +			rockchip_usb2phy_power_off(rport->phy);
> +		}
> +		sch_work = true;
> +		break;
> +	case OTG_STATE_A_HOST:
> +		if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) == 0) {
> +			dev_dbg(&rport->phy->dev, "usb otg host disconnect\n");
> +			rport->state = OTG_STATE_B_IDLE;
> +			rockchip_usb2phy_power_off(rport->phy);
> +		}
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	if (sch_work)
> +		schedule_delayed_work(&rport->otg_sm_work, delay);
> +}
> +
> +static const char *chg_to_string(enum power_supply_type chg_type)
> +{
> +	switch (chg_type) {
> +	case POWER_SUPPLY_TYPE_USB:
> +		return "USB_SDP_CHARGER";
> +	case POWER_SUPPLY_TYPE_USB_DCP:
> +		return "USB_DCP_CHARGER";
> +	case POWER_SUPPLY_TYPE_USB_CDP:
> +		return "USB_CDP_CHARGER";
> +	default:
> +		return "INVALID_CHARGER";
> +	}
> +}
> +
> +static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
> +				    bool en)
> +{
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
> +}
> +
> +static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
> +					    bool en)
> +{
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
> +}
> +
> +static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
> +					      bool en)
> +{
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
> +}
> +
> +#define CHG_DCD_POLL_TIME	(100 * HZ / 1000)
> +#define CHG_DCD_MAX_RETRIES	6
> +#define CHG_PRIMARY_DET_TIME	(40 * HZ / 1000)
> +#define CHG_SECONDARY_DET_TIME	(40 * HZ / 1000)
> +static void rockchip_chg_detect_work(struct work_struct *work)
> +{
> +	struct rockchip_usb2phy_port *rport =
> +		container_of(work, struct rockchip_usb2phy_port, chg_work.work);
> +	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
> +	bool is_dcd, tmout, vout;
> +	unsigned long delay;
> +
> +	dev_dbg(&rport->phy->dev, "chg detection work state = %d\n",
> +		rphy->chg_state);
> +	switch (rphy->chg_state) {
> +	case USB_CHG_STATE_UNDEFINED:
> +		if (!rport->suspended)
> +			rockchip_usb2phy_power_off(rport->phy);
> +		/* put the controller in non-driving mode */
> +		property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false);
> +		/* Start DCD processing stage 1 */
> +		rockchip_chg_enable_dcd(rphy, true);
> +		rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
> +		rphy->dcd_retries = 0;
> +		delay = CHG_DCD_POLL_TIME;
> +		break;
> +	case USB_CHG_STATE_WAIT_FOR_DCD:
> +		/* get data contact detection status */
> +		is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det);
> +		tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
> +		/* stage 2 */
> +		if (is_dcd || tmout) {
> +			/* stage 4 */
> +			/* Turn off DCD circuitry */
> +			rockchip_chg_enable_dcd(rphy, false);
> +			/* Voltage Source on DP, Probe on DM */
> +			rockchip_chg_enable_primary_det(rphy, true);
> +			delay = CHG_PRIMARY_DET_TIME;
> +			rphy->chg_state = USB_CHG_STATE_DCD_DONE;
> +		} else {
> +			/* stage 3 */
> +			delay = CHG_DCD_POLL_TIME;
> +		}
> +		break;
> +	case USB_CHG_STATE_DCD_DONE:
> +		vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det);
> +		rockchip_chg_enable_primary_det(rphy, false);
> +		if (vout) {
> +			/* Voltage Source on DM, Probe on DP  */
> +			rockchip_chg_enable_secondary_det(rphy, true);
> +			delay = CHG_SECONDARY_DET_TIME;
> +			rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE;
> +		} else {
> +			if (tmout) {
> +				/* floating charger found */
> +				rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
> +				rphy->chg_state = USB_CHG_STATE_DETECTED;
> +				delay = 0;
> +			} else {
> +				rphy->chg_type = POWER_SUPPLY_TYPE_USB;
> +				rphy->chg_state = USB_CHG_STATE_DETECTED;
> +				delay = 0;
> +			}
> +		}
> +		break;
> +	case USB_CHG_STATE_PRIMARY_DONE:
> +		vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det);
> +		/* Turn off voltage source */
> +		rockchip_chg_enable_secondary_det(rphy, false);
> +		if (vout)
> +			rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
> +		else
> +			rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP;
> +		/* fall through */
> +	case USB_CHG_STATE_SECONDARY_DONE:
> +		rphy->chg_state = USB_CHG_STATE_DETECTED;
> +		delay = 0;
> +		/* fall through */
> +	case USB_CHG_STATE_DETECTED:
> +		/* put the controller in normal mode */
> +		property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true);
> +		rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
> +		dev_info(&rport->phy->dev, "charger = %s\n",
> +			 chg_to_string(rphy->chg_type));
> +		return;
> +	default:
> +		return;
> +	}
> +
> +	schedule_delayed_work(&rport->chg_work, delay);
> +}
> +
>  /*
>   * The function manage host-phy port state and suspend/resume phy port
>   * to save power.
> @@ -485,6 +884,26 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
>  	return IRQ_HANDLED;
>  }
>  
> +static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
> +{
> +	struct rockchip_usb2phy_port *rport = data;
> +	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
> +
> +	if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st))
> +		return IRQ_NONE;
> +
> +	mutex_lock(&rport->mutex);
> +
> +	/* clear bvalid detect irq pending status */
> +	property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true);
> +
> +	mutex_unlock(&rport->mutex);
> +
> +	rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
>  					   struct rockchip_usb2phy_port *rport,
>  					   struct device_node *child_np)
> @@ -509,13 +928,86 @@ static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
>  					IRQF_ONESHOT,
>  					"rockchip_usb2phy", rport);
>  	if (ret) {
> -		dev_err(rphy->dev, "failed to request irq handle\n");
> +		dev_err(rphy->dev, "failed to request linestate irq handle\n");
>  		return ret;
>  	}
>  
>  	return 0;
>  }
>  
> +static int rockchip_otg_event(struct notifier_block *nb,
> +			      unsigned long event, void *ptr)
> +{
> +	struct rockchip_usb2phy_port *rport =
> +		container_of(nb, struct rockchip_usb2phy_port, event_nb);
> +
> +	schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
> +
> +	return NOTIFY_DONE;
> +}
> +
> +static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
> +					  struct rockchip_usb2phy_port *rport,
> +					  struct device_node *child_np)
> +{
> +	int ret;
> +
> +	rport->port_id = USB2PHY_PORT_OTG;
> +	rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG];
> +	rport->state = OTG_STATE_UNDEFINED;
> +
> +	/*
> +	 * set suspended flag to true, but actually don't
> +	 * put phy in suspend mode, it aims to enable usb
> +	 * phy and clock in power_on() called by usb controller
> +	 * driver during probe.
> +	 */
> +	rport->suspended = true;
> +	rport->vbus_attached = false;
> +
> +	mutex_init(&rport->mutex);
> +
> +	rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
> +	if (rport->mode == USB_DR_MODE_HOST) {
> +		ret = 0;
> +		goto out;
> +	}
> +
> +	INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
> +	INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work);
> +
> +	rport->utmi_avalid =
> +		of_property_read_bool(child_np, "rockchip,utmi-avalid");
> +
> +	rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
> +	if (rport->bvalid_irq < 0) {
> +		dev_err(rphy->dev, "no vbus valid irq provided\n");
> +		ret = rport->bvalid_irq;
> +		goto out;
> +	}
> +
> +	ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, NULL,
> +					rockchip_usb2phy_bvalid_irq,
> +					IRQF_ONESHOT,
> +					"rockchip_usb2phy_bvalid", rport);
> +	if (ret) {
> +		dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n");
> +		goto out;
> +	}
> +
> +	if (!IS_ERR(rphy->edev)) {
> +		rport->event_nb.notifier_call = rockchip_otg_event;
> +
> +		ret = extcon_register_notifier(rphy->edev, EXTCON_USB_HOST,
> +					       &rport->event_nb);
> +		if (ret)
> +			dev_err(rphy->dev, "register USB HOST notifier failed\n");
> +	}
> +
> +out:
> +	return ret;
> +}
> +
>  static int rockchip_usb2phy_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -553,8 +1045,14 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>  
>  	rphy->dev = dev;
>  	phy_cfgs = match->data;
> +	rphy->chg_state = USB_CHG_STATE_UNDEFINED;
> +	rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
>  	platform_set_drvdata(pdev, rphy);
>  
> +	ret = rockchip_usb2phy_extcon_register(rphy);
> +	if (ret)
> +		return ret;
> +
>  	/* find out a proper config which can be matched with dt. */
>  	index = 0;
>  	while (phy_cfgs[index].reg) {
> @@ -591,13 +1089,9 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>  		struct rockchip_usb2phy_port *rport = &rphy->ports[index];
>  		struct phy *phy;
>  
> -		/*
> -		 * This driver aim to support both otg-port and host-port,
> -		 * but unfortunately, the otg part is not ready in current,
> -		 * so this comments and below codes are interim, which should
> -		 * be changed after otg-port is supplied soon.
> -		 */
> -		if (of_node_cmp(child_np->name, "host-port"))
> +		/* This driver aims to support both otg-port and host-port */
> +		if (of_node_cmp(child_np->name, "host-port") &&
> +		    of_node_cmp(child_np->name, "otg-port"))
>  			goto next_child;
>  
>  		phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
> @@ -610,9 +1104,18 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>  		rport->phy = phy;
>  		phy_set_drvdata(rport->phy, rport);
>  
> -		ret = rockchip_usb2phy_host_port_init(rphy, rport, child_np);
> -		if (ret)
> -			goto put_child;
> +		/* initialize otg/host port separately */
> +		if (!of_node_cmp(child_np->name, "host-port")) {
> +			ret = rockchip_usb2phy_host_port_init(rphy, rport,
> +							      child_np);
> +			if (ret)
> +				goto put_child;
> +		} else {
> +			ret = rockchip_usb2phy_otg_port_init(rphy, rport,
> +							     child_np);
> +			if (ret)
> +				goto put_child;
> +		}
>  
>  next_child:
>  		/* to prevent out of boundary */
> @@ -654,10 +1157,18 @@ static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = {
>  
>  static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
>  	{
> -		.reg = 0xe450,
> +		.reg		= 0xe450,
>  		.num_ports	= 2,
>  		.clkout_ctl	= { 0xe450, 4, 4, 1, 0 },
>  		.port_cfgs	= {
> +			[USB2PHY_PORT_OTG] = {
> +				.phy_sus	= { 0xe454, 1, 0, 2, 1 },
> +				.bvalid_det_en	= { 0xe3c0, 3, 3, 0, 1 },
> +				.bvalid_det_st	= { 0xe3e0, 3, 3, 0, 1 },
> +				.bvalid_det_clr	= { 0xe3d0, 3, 3, 0, 1 },
> +				.utmi_avalid	= { 0xe2ac, 7, 7, 0, 1 },
> +				.utmi_bvalid	= { 0xe2ac, 12, 12, 0, 1 },
> +			},
>  			[USB2PHY_PORT_HOST] = {
>  				.phy_sus	= { 0xe458, 1, 0, 0x2, 0x1 },
>  				.ls_det_en	= { 0xe3c0, 6, 6, 0, 1 },
> @@ -667,12 +1178,32 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
>  				.utmi_hstdet	= { 0xe2ac, 23, 23, 0, 1 }
>  			}
>  		},
> +		.chg_det = {
> +			.opmode		= { 0xe454, 3, 0, 5, 1 },
> +			.cp_det		= { 0xe2ac, 2, 2, 0, 1 },
> +			.dcp_det	= { 0xe2ac, 1, 1, 0, 1 },
> +			.dp_det		= { 0xe2ac, 0, 0, 0, 1 },
> +			.idm_sink_en	= { 0xe450, 8, 8, 0, 1 },
> +			.idp_sink_en	= { 0xe450, 7, 7, 0, 1 },
> +			.idp_src_en	= { 0xe450, 9, 9, 0, 1 },
> +			.rdm_pdwn_en	= { 0xe450, 10, 10, 0, 1 },
> +			.vdm_src_en	= { 0xe450, 12, 12, 0, 1 },
> +			.vdp_src_en	= { 0xe450, 11, 11, 0, 1 },
> +		},
>  	},
>  	{
> -		.reg = 0xe460,
> +		.reg		= 0xe460,
>  		.num_ports	= 2,
>  		.clkout_ctl	= { 0xe460, 4, 4, 1, 0 },
>  		.port_cfgs	= {
> +			[USB2PHY_PORT_OTG] = {
> +				.phy_sus        = { 0xe464, 1, 0, 2, 1 },
> +				.bvalid_det_en  = { 0xe3c0, 8, 8, 0, 1 },
> +				.bvalid_det_st  = { 0xe3e0, 8, 8, 0, 1 },
> +				.bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 },
> +				.utmi_avalid	= { 0xe2ac, 10, 10, 0, 1 },
> +				.utmi_bvalid    = { 0xe2ac, 16, 16, 0, 1 },
> +			},
>  			[USB2PHY_PORT_HOST] = {
>  				.phy_sus	= { 0xe468, 1, 0, 0x2, 0x1 },
>  				.ls_det_en	= { 0xe3c0, 11, 11, 0, 1 },
> 

^ permalink raw reply

* Re: [PATCH 3/4] dt: bindings: add new dt entry for BTCOEX feature in qcom, ath10k.txt
From: Valo, Kalle @ 2016-11-15 13:39 UTC (permalink / raw)
  To: Raja, Tamizh Chelvam
  Cc: ath10k-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	tamizhchelvam-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1478617462-28188-1-git-send-email-c_traja-Rm6X0d1/PG5y9aJCnZT0Uw@public.gmane.org>

(Adding devicetree list)

<c_traja-Rm6X0d1/PG5y9aJCnZT0Uw@public.gmane.org> writes:

> From: Tamizh chelvam <tamizhchelvam-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
>
> There two things done in this patch.
>
> 1) 'btcoex_support' flag for BTCOEX feature support by the hardware.
> 2) 'wlan_btcoex_gpio' is used to fill wlan priority pin number for
>    BTCOEX priority feature support.
>
> Signed-off-by: Tamizh chelvam <tamizhchelvam-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
> ---
>  .../bindings/net/wireless/qcom,ath10k.txt          |    4 ++++
>  1 file changed, 4 insertions(+)

As this changes the device tree bindings you need to CC the device tree
list. Please resend the whole patchset (and mark it as v2).

-- 
Kalle Valo--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v4 2/2] Add support for OV5647 sensor
From: Guenter Roeck @ 2016-11-15 13:50 UTC (permalink / raw)
  To: Pavel Machek, Ramiro Oliveira
  Cc: mchehab, linux-kernel, linux-media, robh+dt, devicetree, davem,
	gregkh, geert+renesas, akpm, hverkuil, dheitmueller, slongerbeam,
	lars, robert.jarzmik, pali.rohar, sakari.ailus, mark.rutland,
	CARLOS.PALMINHA
In-Reply-To: <20161115121032.GB7018@amd>

On 11/15/2016 04:10 AM, Pavel Machek wrote:
> Hi!
>
>> Add support for OV5647 sensor.
>>
>
>> +static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val)
>> +{
>> +	int ret;
>> +	unsigned char data[3] = { reg >> 8, reg & 0xff, val};
>> +	struct i2c_client *client = v4l2_get_subdevdata(sd);
>> +
>> +	ret = i2c_master_send(client, data, 3);
>> +	if (ret != 3) {
>> +		dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n",
>> +				__func__, reg);
>> +		return ret < 0 ? ret : -EIO;
>> +	}
>> +	return 0;
>> +}
>
> Sorry, this is wrong. It should something <0 any time error is detected.
>

It seems to me that it does return a value < 0 each time an error is detected.

Guenter

^ permalink raw reply

* [PATCH v2 0/3] ARM: dts: sun7i: BPI-M1+ USB support
From: Chen-Yu Tsai @ 2016-11-15 13:51 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: Chen-Yu Tsai, devicetree, linux-arm-kernel, linux-kernel

Hi Maxime,

These are the remaining patches of my BPI-M1+ fixes series from July.

Changes since v1:

  - Split out USB PHY enable patch.

  - Dropped custom OPP table. Tested the A20 default one with
    cpufreq-ljt-stress-test and it seemed stable.

  - Dropped voltage range for cpu supply regulator to normal 1.0V ~ 1.4V.

  - Dropped pinmux setting for OTG ID pin.


Please have a look.

Regards
ChenYu

Chen-Yu Tsai (3):
  ARM: dts: sun7i: bananapi-m1-plus: Enable USB PHY for USB host support
  ARM: dts: sun7i: bananapi-m1-plus: Add PMIC regulators
  ARM: dts: sun7i: bananapi-m1-plus: Enable USB OTG

 arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts | 60 ++++++++++++++++++++++--
 1 file changed, 56 insertions(+), 4 deletions(-)

-- 
2.10.2

^ permalink raw reply

* [PATCH v2 1/3] ARM: dts: sun7i: bananapi-m1-plus: Enable USB PHY for USB host support
From: Chen-Yu Tsai @ 2016-11-15 13:51 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: Chen-Yu Tsai, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20161115135106.438-1-wens@csie.org>

The 2 USB host ports are directly tied to the 2 USB hosts in the SoC.
The 2 host pairs were already enabled, but the USB PHY wasn't.
VBUS on the 2 ports are always on.

Enable the USB PHY.

Fixes: 04c85ecad32a ("ARM: dts: sun7i: Add dts file for Bananapi M1 Plus
		      board")
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
index ba5bca0fe997..44377a98cc89 100644
--- a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
+++ b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
@@ -227,3 +227,8 @@
 	pinctrl-0 = <&uart0_pins_a>;
 	status = "okay";
 };
+
+&usbphy {
+	/* VBUS on usb host ports are tied to DC5V and therefore always on */
+	status = "okay";
+};
-- 
2.10.2

^ permalink raw reply related

* [PATCH v2 2/3] ARM: dts: sun7i: bananapi-m1-plus: Add PMIC regulators
From: Chen-Yu Tsai @ 2016-11-15 13:51 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: Chen-Yu Tsai, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20161115135106.438-1-wens@csie.org>

The Bananapi M1+, like other Allwinner A20 based boards, uses the
AXP209 PMIC to supply its power.

Add the AXP209 regulators.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts | 35 +++++++++++++++++++++---
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
index 44377a98cc89..ac19630c1c23 100644
--- a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
+++ b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
@@ -105,6 +105,10 @@
 	status = "okay";
 };
 
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
 &ehci0 {
 	status = "okay";
 };
@@ -132,16 +136,14 @@
 	status = "okay";
 
 	axp209: pmic@34 {
-		compatible = "x-powers,axp209";
 		reg = <0x34>;
 		interrupt-parent = <&nmi_intc>;
 		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
-
-		interrupt-controller;
-		#interrupt-cells = <1>;
 	};
 };
 
+#include "axp209.dtsi"
+
 &ir0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&ir0_rx_pins_a>;
@@ -222,6 +224,31 @@
 	};
 };
 
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc3 {
+	regulator-always-on;
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-int-dll";
+};
+
+&reg_ldo1 {
+	regulator-name = "vdd-rtc";
+};
+
+&reg_ldo2 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "avcc";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
-- 
2.10.2

^ permalink raw reply related

* [PATCH v2 3/3] ARM: dts: sun7i: bananapi-m1-plus: Enable USB OTG
From: Chen-Yu Tsai @ 2016-11-15 13:51 UTC (permalink / raw)
  To: Maxime Ripard; +Cc: Chen-Yu Tsai, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20161115135106.438-1-wens@csie.org>

The Bananapi M1+ supports USB OTG, with the PMIC doing VBUS sensing.
Enable the USB OTG related functions.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
index ac19630c1c23..5f7114e13850 100644
--- a/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
+++ b/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
@@ -194,6 +194,10 @@
 	status = "okay";
 };
 
+&otg_sram {
+	status = "okay";
+};
+
 &pio {
 	gmac_power_pin_bpi_m1p: gmac_power_pin@0 {
 		allwinner,pins = "PH23";
@@ -249,13 +253,29 @@
 	regulator-name = "avcc";
 };
 
+&reg_usb0_vbus {
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
 	status = "okay";
 };
 
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usb_power_supply {
+	status = "okay";
+};
+
 &usbphy {
+	usb0_id_det-gpios = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+	usb0_vbus_power-supply = <&usb_power_supply>;
+	usb0_vbus-supply = <&reg_usb0_vbus>;
 	/* VBUS on usb host ports are tied to DC5V and therefore always on */
 	status = "okay";
 };
-- 
2.10.2

^ permalink raw reply related

* Re: [PATCH v4 0/8] IIO wrapper drivers, dpot-dac and envelope-detector
From: Peter Rosin @ 2016-11-15 14:03 UTC (permalink / raw)
  To: Jonathan Cameron, linux-kernel
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Rob Herring, Mark Rutland, Daniel Baluta, Slawomir Stepien,
	Thomas Gleixner, linux-iio, devicetree
In-Reply-To: <9d0ddee1-6f50-0fe9-2efa-a31f1e239aa6@kernel.org>

On 2016-11-12 18:15, Jonathan Cameron wrote:
> On 08/11/16 11:58, Peter Rosin wrote:
>> I also wonder if the "new" *_available ABI should perhaps be documented
>> for all variants directly in sysfs-bus-iio instead of doing it in a driver
>> specific maner that I did? But that can be fixed later by someone more
>> capable than me :-)
> You doubt yourself too much ;)  Some one with fewer inhibitions you mean!

Maybe so, I just find that file long and confusing. I do not have a mental
picture of what fits where...

> Anyhow, just thought I'd add that I like this series very much.
> It's a nice interesting use of the infrastructures.  Good to see people
> are getting more adventurous all the time.

Thanks for the confidence boost! And also thanks for taking care of the
bot fallout...

Cheers,
Peter

^ permalink raw reply

* [PATCH] ARM64: zynqmp: Fix W=1 dtc 1.4 warnings
From: Michal Simek @ 2016-11-15 14:04 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Sören Brinkmann, Punnaiah Choudary Kalluri, monstr,
	Alexander Graf, Carlo Caione, devicetree, Bharat Kumar Gogada,
	linux-kernel, Marc Zyngier, Rob Herring, Will Deacon,
	Catalin Marinas, Mark Rutland

The patch removes these warnings reported by dtc 1.4:
Warning (unit_address_vs_reg): Node /amba_apu has a reg or ranges
property, but no unit name
Warning (unit_address_vs_reg): Node /memory has a reg or ranges
property, but no unit name

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---

 arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts | 2 +-
 arch/arm64/boot/dts/xilinx/zynqmp.dtsi      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
index 358089687a69..ef1b9e573af0 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
@@ -27,7 +27,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x40000000>;
 	};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 68a908334c7b..83791eadff41 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -72,7 +72,7 @@
 			     <1 10 0xf08>;
 	};
 
-	amba_apu {
+	amba_apu: amba_apu@0 {
 		compatible = "simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/2] ARM: zynq: Remove skeleton.dtsi
From: Michal Simek @ 2016-11-15 14:07 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Sören Brinkmann, devicetree-u79uwXL29TY76Z2rM5mHXA,
	monstr-pSz03upnqPeHXe+LvDLADg, Steffen Trumtrar,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Peter Crosthwaite,
	Rob Herring, Rob Herring, Mark Rutland, Josh Cartwright,
	Russell King

Based on
"ARM: dts: explicitly mark skeleton.dtsi as deprecated"
(sha1: 9c0da3cc61f1233c2782e2d3d91e3d0707dd4ba5)
skeleton.dtsi is deprecated.
Move address and size-cells directly to zynq-7000.dtsi.

Signed-off-by: Michal Simek <michal.simek-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
---

 arch/arm/boot/dts/zynq-7000.dtsi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index f283ff08381c..f47a6c1cc752 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -10,9 +10,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-/include/ "skeleton.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
 	compatible = "xlnx,zynq-7000";
 
 	cpus {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH 2/2] ARM: zynq: Fix W=1 dtc 1.4 warnings
From: Michal Simek @ 2016-11-15 14:07 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
  Cc: Sören Brinkmann, devicetree-u79uwXL29TY76Z2rM5mHXA,
	monstr-pSz03upnqPeHXe+LvDLADg, Steffen Trumtrar,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Peter Crosthwaite,
	Rob Herring, Rob Herring, Mark Rutland, Josh Cartwright,
	Russell King
In-Reply-To: <2d42e25d7dd03e562e12e71fd037837737115940.1479218844.git.michal.simek-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>

The patch removes these warnings reported by dtc 1.4:
Warning (unit_address_vs_reg): Node /pmu has a reg or ranges property,
but no unit name
Warning (unit_address_vs_reg): Node /fixedregulator@0 has a unit name,
but no reg property
Warning (unit_address_vs_reg): Node /memory has a reg or ranges
property, but no unit name

Signed-off-by: Michal Simek <michal.simek-gjFFaj9aHVfQT0dZR+AlfA@public.gmane.org>
---

 arch/arm/boot/dts/zynq-7000.dtsi      | 4 ++--
 arch/arm/boot/dts/zynq-parallella.dts | 2 +-
 arch/arm/boot/dts/zynq-zc702.dts      | 2 +-
 arch/arm/boot/dts/zynq-zc706.dts      | 2 +-
 arch/arm/boot/dts/zynq-zed.dts        | 2 +-
 arch/arm/boot/dts/zynq-zybo.dts       | 2 +-
 6 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index f47a6c1cc752..402b5bbe3b5b 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -42,14 +42,14 @@
 		};
 	};
 
-	pmu {
+	pmu@f8891000 {
 		compatible = "arm,cortex-a9-pmu";
 		interrupts = <0 5 4>, <0 6 4>;
 		interrupt-parent = <&intc>;
 		reg = < 0xf8891000 0x1000 0xf8893000 0x1000 >;
 	};
 
-	regulator_vccpint: fixedregulator@0 {
+	regulator_vccpint: fixedregulator {
 		compatible = "regulator-fixed";
 		regulator-name = "VCCPINT";
 		regulator-min-microvolt = <1000000>;
diff --git a/arch/arm/boot/dts/zynq-parallella.dts b/arch/arm/boot/dts/zynq-parallella.dts
index 307ed201d658..64a6390fc501 100644
--- a/arch/arm/boot/dts/zynq-parallella.dts
+++ b/arch/arm/boot/dts/zynq-parallella.dts
@@ -28,7 +28,7 @@
 		serial0 = &uart1;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x40000000>;
 	};
diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts
index e96959b2e67a..0cdad2cc8b78 100644
--- a/arch/arm/boot/dts/zynq-zc702.dts
+++ b/arch/arm/boot/dts/zynq-zc702.dts
@@ -24,7 +24,7 @@
 		serial0 = &uart1;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x40000000>;
 	};
diff --git a/arch/arm/boot/dts/zynq-zc706.dts b/arch/arm/boot/dts/zynq-zc706.dts
index be6a986bbbd8..ad4bb06dba25 100644
--- a/arch/arm/boot/dts/zynq-zc706.dts
+++ b/arch/arm/boot/dts/zynq-zc706.dts
@@ -24,7 +24,7 @@
 		serial0 = &uart1;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x40000000>;
 	};
diff --git a/arch/arm/boot/dts/zynq-zed.dts b/arch/arm/boot/dts/zynq-zed.dts
index 7250c1eac7f9..325379f7983c 100644
--- a/arch/arm/boot/dts/zynq-zed.dts
+++ b/arch/arm/boot/dts/zynq-zed.dts
@@ -23,7 +23,7 @@
 		serial0 = &uart1;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x20000000>;
 	};
diff --git a/arch/arm/boot/dts/zynq-zybo.dts b/arch/arm/boot/dts/zynq-zybo.dts
index d9e0f3e70671..590ec24b8749 100644
--- a/arch/arm/boot/dts/zynq-zybo.dts
+++ b/arch/arm/boot/dts/zynq-zybo.dts
@@ -23,7 +23,7 @@
 		serial0 = &uart1;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x20000000>;
 	};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v5] PCI: qcom: add support to msm8996 PCIE controller
From: Srinivas Kandagatla @ 2016-11-15 14:23 UTC (permalink / raw)
  To: svarbanov, linux-pci, bhelgaas
  Cc: robh+dt, linux-arm-msm, srinivas.kandagatla, devicetree

This patch adds support to msm8996/apq8096 pcie, MSM8996 supports
Gen 1/2, One lane, 3 pcie root-complex with support to MSI and
legacy interrupts and it conforms to PCI Express Base 2.1 specification.

This patch adds post_init callback to qcom_pcie_ops, as this is pcie
pipe clocks are only setup after the phy is powered on.
It also adds ltssm_enable callback as it is very much different to other
supported SOCs in the driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Acked-by: Stanimir Varbanov <svarbanov@mm-sol.com>
---

 Changes since v4:
 	- removed duplicate define spotted by Stan.
	- renamed halt register to remove msm8996 suggested by Stan.
	- dropped simple-pm-bus and runtime pm patches as these can
	 potentially go into pm domain provider.

 .../devicetree/bindings/pci/qcom,pcie.txt          |  67 +++++++-
 drivers/pci/host/pcie-qcom.c                       | 175 ++++++++++++++++++++-
 2 files changed, 236 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.txt b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
index 4059a6f..141d8c3 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie.txt
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
@@ -7,6 +7,7 @@
 			- "qcom,pcie-ipq8064" for ipq8064
 			- "qcom,pcie-apq8064" for apq8064
 			- "qcom,pcie-apq8084" for apq8084
+			- "qcom,pcie-msm8996" for msm8996 or apq8096
 
 - reg:
 	Usage: required
@@ -92,6 +93,17 @@
 			- "aux"		Auxiliary (AUX) clock
 			- "bus_master"	Master AXI clock
 			- "bus_slave"	Slave AXI clock
+
+- clock-names:
+	Usage: required for msm8996/apq8096
+	Value type: <stringlist>
+	Definition: Should contain the following entries
+			- "pipe"	Pipe Clock driving internal logic.
+			- "aux"		Auxiliary (AUX) clock.
+			- "cfg"		Configuration clk.
+			- "bus_master"	Master AXI clock.
+			- "bus_slave"	Slave AXI clock.
+
 - resets:
 	Usage: required
 	Value type: <prop-encoded-array>
@@ -115,7 +127,7 @@
 			- "core" Core reset
 
 - power-domains:
-	Usage: required for apq8084
+	Usage: required for apq8084 and msm8996/apq8096
 	Value type: <prop-encoded-array>
 	Definition: A phandle and power domain specifier pair to the
 		    power domain which is responsible for collapsing
@@ -231,3 +243,56 @@
 		pinctrl-0 = <&pcie0_pins_default>;
 		pinctrl-names = "default";
 	};
+
+* Example for apq8096:
+
+	pcie@608000{
+		compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
+		power-domains = <&gcc PCIE1_GDSC>;
+		bus-range = <0x00 0xff>;
+		num-lanes = <1>;
+
+		reg = <0x00608000 0x2000>,
+		      <0x0d000000 0xf1d>,
+		      <0x0d000f20 0xa8>,
+		      <0x0d100000 0x100000>;
+
+		reg-names = "parf", "dbi", "elbi", "config";
+
+		phys = <&pcie_phy 1>;
+		phy-names = "pciephy";
+
+		#address-cells = <3>;
+		#size-cells = <2>;
+		ranges = <0x01000000 0x0 0x0d200000 0x0d200000 0x0 0x100000>,
+			<0x02000000 0x0 0x0d300000 0x0d300000 0x0 0xd00000>;
+
+		interrupts = <GIC_SPI 413 IRQ_TYPE_NONE>;
+		interrupt-names = "msi";
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0x7>;
+		interrupt-map = <0 0 0 1 &intc 0 272 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+				<0 0 0 2 &intc 0 273 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+				<0 0 0 3 &intc 0 274 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+				<0 0 0 4 &intc 0 275 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&pcie1_clkreq_default &pcie1_perst_default &pcie1_wake_default>;
+		pinctrl-1 = <&pcie1_clkreq_sleep &pcie1_perst_default &pcie1_wake_sleep>;
+
+		vdda-1p8-supply = <&pm8994_l12>;
+		vdda-supply = <&pm8994_l28>;
+		linux,pci-domain = <1>;
+
+		clocks = <&gcc GCC_PCIE_1_PIPE_CLK>,
+			<&gcc GCC_PCIE_1_AUX_CLK>,
+			<&gcc GCC_PCIE_1_CFG_AHB_CLK>,
+			<&gcc GCC_PCIE_1_MSTR_AXI_CLK>,
+			<&gcc GCC_PCIE_1_SLV_AXI_CLK>;
+
+		clock-names =  "pipe",
+				"aux",
+				"cfg",
+				"bus_master",
+				"bus_slave";
+	};
diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/host/pcie-qcom.c
index 3593640..25c5556 100644
--- a/drivers/pci/host/pcie-qcom.c
+++ b/drivers/pci/host/pcie-qcom.c
@@ -36,11 +36,17 @@
 
 #include "pcie-designware.h"
 
+#define PCIE20_PARF_SYS_CTRL			0x00
 #define PCIE20_PARF_PHY_CTRL			0x40
 #define PCIE20_PARF_PHY_REFCLK			0x4C
 #define PCIE20_PARF_DBI_BASE_ADDR		0x168
 #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE		0x16c
+#define PCIE20_PARF_MHI_CLOCK_RESET_CTRL	0x174
 #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT	0x178
+#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2	0x1A8
+#define PCIE20_PARF_LTSSM			0x1B0
+#define PCIE20_PARF_SID_OFFSET			0x234
+#define PCIE20_PARF_BDF_TRANSLATE_CFG		0x24C
 
 #define PCIE20_ELBI_SYS_CTRL			0x04
 #define PCIE20_ELBI_SYS_CTRL_LT_ENABLE		BIT(0)
@@ -72,9 +78,18 @@ struct qcom_pcie_resources_v1 {
 	struct regulator *vdda;
 };
 
+struct qcom_pcie_resources_v2 {
+	struct clk *aux_clk;
+	struct clk *master_clk;
+	struct clk *slave_clk;
+	struct clk *cfg_clk;
+	struct clk *pipe_clk;
+};
+
 union qcom_pcie_resources {
 	struct qcom_pcie_resources_v0 v0;
 	struct qcom_pcie_resources_v1 v1;
+	struct qcom_pcie_resources_v2 v2;
 };
 
 struct qcom_pcie;
@@ -82,7 +97,9 @@ struct qcom_pcie;
 struct qcom_pcie_ops {
 	int (*get_resources)(struct qcom_pcie *pcie);
 	int (*init)(struct qcom_pcie *pcie);
+	int (*post_init)(struct qcom_pcie *pcie);
 	void (*deinit)(struct qcom_pcie *pcie);
+	void (*ltssm_enable)(struct qcom_pcie *pcie);
 };
 
 struct qcom_pcie {
@@ -116,17 +133,33 @@ static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg)
 	return dw_handle_msi_irq(pp);
 }
 
-static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
+static void qcom_pcie_v0_v1_ltssm_enable(struct qcom_pcie *pcie)
 {
 	u32 val;
-
-	if (dw_pcie_link_up(&pcie->pp))
-		return 0;
-
 	/* enable link training */
 	val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL);
 	val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE;
 	writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL);
+}
+
+static void qcom_pcie_v2_ltssm_enable(struct qcom_pcie *pcie)
+{
+	u32 val;
+	/* enable link training */
+	val = readl(pcie->parf + PCIE20_PARF_LTSSM);
+	val |= BIT(8);
+	writel(val, pcie->parf + PCIE20_PARF_LTSSM);
+}
+
+static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
+{
+
+	if (dw_pcie_link_up(&pcie->pp))
+		return 0;
+
+	/* Enable Link Training state machine */
+	if (pcie->ops->ltssm_enable)
+		pcie->ops->ltssm_enable(pcie);
 
 	return dw_pcie_wait_for_link(&pcie->pp);
 }
@@ -421,6 +454,113 @@ static int qcom_pcie_init_v1(struct qcom_pcie *pcie)
 	return ret;
 }
 
+static int qcom_pcie_get_resources_v2(struct qcom_pcie *pcie)
+{
+	struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
+	struct device *dev = pcie->pp.dev;
+
+	res->aux_clk = devm_clk_get(dev, "aux");
+	if (IS_ERR(res->aux_clk))
+		return PTR_ERR(res->aux_clk);
+
+	res->cfg_clk = devm_clk_get(dev, "cfg");
+	if (IS_ERR(res->cfg_clk))
+		return PTR_ERR(res->cfg_clk);
+
+	res->master_clk = devm_clk_get(dev, "bus_master");
+	if (IS_ERR(res->master_clk))
+		return PTR_ERR(res->master_clk);
+
+	res->slave_clk = devm_clk_get(dev, "bus_slave");
+	if (IS_ERR(res->slave_clk))
+		return PTR_ERR(res->slave_clk);
+
+	res->pipe_clk = devm_clk_get(dev, "pipe");
+	if (IS_ERR(res->pipe_clk))
+		return PTR_ERR(res->pipe_clk);
+
+	return 0;
+}
+
+static int qcom_pcie_init_v2(struct qcom_pcie *pcie)
+{
+	struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
+	struct device *dev = pcie->pp.dev;
+	u32 val;
+	int ret;
+
+	ret = clk_prepare_enable(res->aux_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable aux clock\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(res->cfg_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable cfg clock\n");
+		goto err_cfg_clk;
+	}
+
+	ret = clk_prepare_enable(res->master_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable master clock\n");
+		goto err_master_clk;
+	}
+
+	ret = clk_prepare_enable(res->slave_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable slave clock\n");
+		goto err_slave_clk;
+	}
+
+	/* enable PCIe clocks and resets */
+	val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
+	val &= ~BIT(0);
+	writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
+
+	/* change DBI base address */
+	writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
+
+	/* MAC PHY_POWERDOWN MUX DISABLE  */
+	val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL);
+	val &= ~BIT(29);
+	writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL);
+
+	val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
+	val |= BIT(4);
+	writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
+
+	val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
+	val |= BIT(31);
+	writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
+
+	return 0;
+
+err_slave_clk:
+	clk_disable_unprepare(res->master_clk);
+err_master_clk:
+	clk_disable_unprepare(res->cfg_clk);
+err_cfg_clk:
+	clk_disable_unprepare(res->aux_clk);
+
+	return ret;
+}
+
+static int qcom_pcie_post_init_v2(struct qcom_pcie *pcie)
+{
+	struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
+	struct device *dev = pcie->pp.dev;
+	int ret;
+
+	ret = clk_prepare_enable(res->pipe_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable pipe clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static int qcom_pcie_link_up(struct pcie_port *pp)
 {
 	struct qcom_pcie *pcie = to_qcom_pcie(pp);
@@ -429,6 +569,17 @@ static int qcom_pcie_link_up(struct pcie_port *pp)
 	return !!(val & PCI_EXP_LNKSTA_DLLLA);
 }
 
+static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie)
+{
+	struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
+
+	clk_disable_unprepare(res->pipe_clk);
+	clk_disable_unprepare(res->slave_clk);
+	clk_disable_unprepare(res->master_clk);
+	clk_disable_unprepare(res->cfg_clk);
+	clk_disable_unprepare(res->aux_clk);
+}
+
 static void qcom_pcie_host_init(struct pcie_port *pp)
 {
 	struct qcom_pcie *pcie = to_qcom_pcie(pp);
@@ -444,6 +595,9 @@ static void qcom_pcie_host_init(struct pcie_port *pp)
 	if (ret)
 		goto err_deinit;
 
+	if (pcie->ops->post_init)
+		pcie->ops->post_init(pcie);
+
 	dw_pcie_setup_rc(pp);
 
 	if (IS_ENABLED(CONFIG_PCI_MSI))
@@ -487,12 +641,22 @@ static const struct qcom_pcie_ops ops_v0 = {
 	.get_resources = qcom_pcie_get_resources_v0,
 	.init = qcom_pcie_init_v0,
 	.deinit = qcom_pcie_deinit_v0,
+	.ltssm_enable = qcom_pcie_v0_v1_ltssm_enable,
 };
 
 static const struct qcom_pcie_ops ops_v1 = {
 	.get_resources = qcom_pcie_get_resources_v1,
 	.init = qcom_pcie_init_v1,
 	.deinit = qcom_pcie_deinit_v1,
+	.ltssm_enable = qcom_pcie_v0_v1_ltssm_enable,
+};
+
+static const struct qcom_pcie_ops ops_v2 = {
+	.get_resources = qcom_pcie_get_resources_v2,
+	.init = qcom_pcie_init_v2,
+	.post_init = qcom_pcie_post_init_v2,
+	.deinit = qcom_pcie_deinit_v2,
+	.ltssm_enable = qcom_pcie_v2_ltssm_enable,
 };
 
 static int qcom_pcie_probe(struct platform_device *pdev)
@@ -572,6 +736,7 @@ static const struct of_device_id qcom_pcie_match[] = {
 	{ .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 },
 	{ .compatible = "qcom,pcie-apq8064", .data = &ops_v0 },
 	{ .compatible = "qcom,pcie-apq8084", .data = &ops_v1 },
+	{ .compatible = "qcom,pcie-msm8996", .data = &ops_v2 },
 	{ }
 };
 
-- 
2.10.1

^ permalink raw reply related

* Re: [PATCH 1/2] regulator: pwm: DT: Add ramp delay for exponential voltage transition
From: Rob Herring @ 2016-11-15 14:27 UTC (permalink / raw)
  To: Laxman Dewangan
  Cc: Mark Brown, Mark Rutland,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Douglas Anderson, Aleksandr Frid
In-Reply-To: <582AF4B7.4050705-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

On Tue, Nov 15, 2016 at 5:42 AM, Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> wrote:
>
> On Monday 14 November 2016 09:18 PM, Rob Herring wrote:
>>
>> On Fri, Nov 04, 2016 at 11:07:54PM +0530, Laxman Dewangan wrote:
>>>
>>> Some PWM regulator has the exponential transition in voltage change as
>>> opposite to fixed slew-rate linear transition on other regulators.
>>> For such PWM regulators, add the property for providing the delay
>>> from DT node.
>>>
>>> Add DT binding details of the new property
>>> "pwm-regulator-voltage-ramp-time-us" added for providing voltage
>>> transition delay.
>>>
>>> Signed-off-by: Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>>> CC: Douglas Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
>>> CC: Aleksandr Frid <afrid-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>>>
>>> ---
>>> This patch is continuation of discussion on patch
>>>         regulator: pwm: Fix regulator ramp delay for continuous mode
>>> https://patchwork.kernel.org/patch/9216857/
>>> where is it discussed to have separate property for PWM which has
>>> exponential voltage transition.
>>> ---
>>>   Documentation/devicetree/bindings/regulator/pwm-regulator.txt | 10
>>> ++++++++++
>>>   1 file changed, 10 insertions(+)
>>>
>>> diff --git
>>> a/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
>>> b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
>>> index 3aeba9f..a163f42 100644
>>> --- a/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
>>> +++ b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
>>> @@ -54,6 +54,16 @@ Optional properties:
>>>   --------------------
>>>   - enable-gpios:               GPIO to use to enable/disable the
>>> regulator
>>>   +- pwm-regulator-voltage-ramp-time-us: Integer, voltage ramp time in
>>
>> This is a really long name. Drop the 'pwm-regulator-' part as it is
>> redundant. The fact that it is PWM reg specific is captured as it is
>> documented that way.
>>
>
> We already have the regulator-ramp-delay from the regulator core.
> Just wanted to make this (pwm-regulator-voltage-ramp-time-us) for pwm
> specific.

Neither of these are very clear that one is linear and one is
exponential. Maybe you should use the existing property to express the
time and just add a boolean property like "voltage-ramp-exponential"?

> Can we have "pwm-regulator-ramp-delay" or "pwm-regulator-settling-time-us"?

How are those better? Same comment applies.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH net 0/3] Fix OdroidC2 Gigabit Tx link issue
From: Jerome Brunet @ 2016-11-15 14:29 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Florian Fainelli
  Cc: Jerome Brunet, Carlo Caione, Kevin Hilman, Giuseppe Cavallaro,
	Alexandre TORGUE, Martin Blumenstingl, Andre Roth, Neil Armstrong,
	linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

This patchset fixes an issue with the OdroidC2 board (DWMAC + RTL8211F).
Initially reported as a low Tx throughput issue at gigabit speed, the
platform enters LPI too often. This eventually break the link (both Tx
and Rx), and require to bring the interface down and up again to get the
Rx path working again.

The root cause of this issue is not fully understood yet but disabling EEE
advertisement on the PHY prevent this feature to be negotiated.
With this change, the link is stable and reliable, with the expected
throughput performance.

The patchset adds options in the realtek phy driver to disable EEE
advertisement, through device tree, for the phy version supporting EEE.
Then EEE is disabled in the OdroidC2 device tree for Gigabit speed.
100M is not affected by this issue.

Jerome Brunet (3):
  net: phy: realtek: add eee advertisement disable options
  dt-bindings: net: add DT bindings for realtek phys
  ARM64: dts: meson: odroidc2: disable 1000t-eee advertisement

 .../devicetree/bindings/net/realtek-phy.txt        | 20 +++++++
 .../arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 15 +++++
 drivers/net/phy/realtek.c                          | 65 +++++++++++++++++++++-
 3 files changed, 99 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/net/realtek-phy.txt

-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH net 1/3] net: phy: realtek: add eee advertisement disable options
From: Jerome Brunet @ 2016-11-15 14:29 UTC (permalink / raw)
  To: netdev, devicetree, Florian Fainelli
  Cc: Jerome Brunet, Carlo Caione, Kevin Hilman, Giuseppe Cavallaro,
	Alexandre TORGUE, Martin Blumenstingl, Andre Roth, Neil Armstrong,
	linux-amlogic, linux-arm-kernel, linux-kernel
In-Reply-To: <1479220154-25851-1-git-send-email-jbrunet@baylibre.com>

On some platforms, energy efficient ethernet with rtl8211 devices is
causing issue, like throughput drop or broken link.

This was reported on the OdroidC2 (DWMAC + RTL8211F). While the issue root
cause is not fully understood yet, disabling EEE advertisement prevent auto
negotiation from enabling EEE.

This patch provides options to disable 1000T and 100TX EEE advertisement
individually for the realtek phys supporting this feature.

Reported-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre TORGUE <alexandre.torgue@st.com>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Tested-by: Andre Roth <neolynx@gmail.com>
---
 drivers/net/phy/realtek.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 64 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index aadd6e9f54ad..77235fd5faaf 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -15,6 +15,12 @@
  */
 #include <linux/phy.h>
 #include <linux/module.h>
+#include <linux/of.h>
+
+struct rtl8211x_phy_priv {
+	bool eee_1000t_disable;
+	bool eee_100tx_disable;
+};
 
 #define RTL821x_PHYSR		0x11
 #define RTL821x_PHYSR_DUPLEX	0x2000
@@ -93,12 +99,44 @@ static int rtl8211f_config_intr(struct phy_device *phydev)
 	return err;
 }
 
+static void rtl8211x_clear_eee_adv(struct phy_device *phydev)
+{
+	struct rtl8211x_phy_priv *priv = phydev->priv;
+	u16 val;
+
+	if (priv->eee_1000t_disable || priv->eee_100tx_disable) {
+		val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
+					    MDIO_MMD_AN);
+
+		if (priv->eee_1000t_disable)
+			val &= ~MDIO_AN_EEE_ADV_1000T;
+		if (priv->eee_100tx_disable)
+			val &= ~MDIO_AN_EEE_ADV_100TX;
+
+		phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
+				       MDIO_MMD_AN, val);
+	}
+}
+
+static int rtl8211x_config_init(struct phy_device *phydev)
+{
+	int ret;
+
+	ret = genphy_config_init(phydev);
+	if (ret < 0)
+		return ret;
+
+	rtl8211x_clear_eee_adv(phydev);
+
+	return 0;
+}
+
 static int rtl8211f_config_init(struct phy_device *phydev)
 {
 	int ret;
 	u16 reg;
 
-	ret = genphy_config_init(phydev);
+	ret = rtl8211x_config_init(phydev);
 	if (ret < 0)
 		return ret;
 
@@ -115,6 +153,26 @@ static int rtl8211f_config_init(struct phy_device *phydev)
 	return 0;
 }
 
+static int rtl8211x_phy_probe(struct phy_device *phydev)
+{
+	struct device *dev = &phydev->mdio.dev;
+	struct device_node *of_node = dev->of_node;
+	struct rtl8211x_phy_priv *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->eee_1000t_disable =
+		of_property_read_bool(of_node, "realtek,disable-eee-1000t");
+	priv->eee_100tx_disable =
+		of_property_read_bool(of_node, "realtek,disable-eee-100tx");
+
+	phydev->priv = priv;
+
+	return 0;
+}
+
 static struct phy_driver realtek_drvs[] = {
 	{
 		.phy_id         = 0x00008201,
@@ -140,7 +198,9 @@ static struct phy_driver realtek_drvs[] = {
 		.phy_id_mask	= 0x001fffff,
 		.features	= PHY_GBIT_FEATURES,
 		.flags		= PHY_HAS_INTERRUPT,
+		.probe		= &rtl8211x_phy_probe,
 		.config_aneg	= genphy_config_aneg,
+		.config_init	= &rtl8211x_config_init,
 		.read_status	= genphy_read_status,
 		.ack_interrupt	= rtl821x_ack_interrupt,
 		.config_intr	= rtl8211e_config_intr,
@@ -152,7 +212,9 @@ static struct phy_driver realtek_drvs[] = {
 		.phy_id_mask	= 0x001fffff,
 		.features	= PHY_GBIT_FEATURES,
 		.flags		= PHY_HAS_INTERRUPT,
+		.probe		= &rtl8211x_phy_probe,
 		.config_aneg	= &genphy_config_aneg,
+		.config_init	= &rtl8211x_config_init,
 		.read_status	= &genphy_read_status,
 		.ack_interrupt	= &rtl821x_ack_interrupt,
 		.config_intr	= &rtl8211e_config_intr,
@@ -164,6 +226,7 @@ static struct phy_driver realtek_drvs[] = {
 		.phy_id_mask	= 0x001fffff,
 		.features	= PHY_GBIT_FEATURES,
 		.flags		= PHY_HAS_INTERRUPT,
+		.probe		= &rtl8211x_phy_probe,
 		.config_aneg	= &genphy_config_aneg,
 		.config_init	= &rtl8211f_config_init,
 		.read_status	= &genphy_read_status,
-- 
2.7.4

^ permalink raw reply related

* [PATCH net 2/3] dt-bindings: net: add DT bindings for realtek phys
From: Jerome Brunet @ 2016-11-15 14:29 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Florian Fainelli
  Cc: Jerome Brunet, Carlo Caione, Kevin Hilman, Giuseppe Cavallaro,
	Alexandre TORGUE, Martin Blumenstingl, Andre Roth, Neil Armstrong,
	linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1479220154-25851-1-git-send-email-jbrunet-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>

Signed-off-by: Jerome Brunet <jbrunet-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
Signed-off-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
---
 .../devicetree/bindings/net/realtek-phy.txt          | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/realtek-phy.txt

diff --git a/Documentation/devicetree/bindings/net/realtek-phy.txt b/Documentation/devicetree/bindings/net/realtek-phy.txt
new file mode 100644
index 000000000000..dc2845a6b387
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/realtek-phy.txt
@@ -0,0 +1,20 @@
+Realtek Ethernet PHY
+
+Some boards require special tuning values of the phy.
+
+Optional properties:
+
+realtek,disable-eee-1000t:
+realtek,disable-eee-100tx:
+  If set, respectively disable 1000-BaseT and 100-BaseTx energy efficient
+  ethernet capabilty advertisement
+  default: Leave the phy default settings unchanged (capabilities advertised)
+
+Example:
+
+&mdio0 {
+	ethernetphy0: ethernet-phy@0 {
+		reg = <0>;
+		realtek,disable-eee-1000t;
+	};
+};
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH net 3/3] ARM64: dts: meson: odroidc2: disable 1000t-eee advertisement
From: Jerome Brunet @ 2016-11-15 14:29 UTC (permalink / raw)
  To: netdev, devicetree, Florian Fainelli
  Cc: Jerome Brunet, Carlo Caione, Kevin Hilman, Giuseppe Cavallaro,
	Alexandre TORGUE, Martin Blumenstingl, Andre Roth, Neil Armstrong,
	linux-amlogic, linux-arm-kernel, linux-kernel
In-Reply-To: <1479220154-25851-1-git-send-email-jbrunet@baylibre.com>

Reported-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre TORGUE <alexandre.torgue@st.com>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Tested-by: Andre Roth <neolynx@gmail.com>
---
 arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index e6e3491d48a5..1f4416ecb183 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -98,3 +98,18 @@
 	pinctrl-0 = <&i2c_a_pins>;
 	pinctrl-names = "default";
 };
+
+&ethmac {
+	phy-handle = <&eth_phy0>;
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		eth_phy0: ethernet-phy@0 {
+			reg = <0>;
+			realtek,disable-eee-1000t;
+		};
+	};
+};
-- 
2.7.4

^ permalink raw reply related

* Re: [RESEND PATCH] regulator: pwm: fix syntax errors in the examples
From: Mark Brown @ 2016-11-15 14:34 UTC (permalink / raw)
  To: Rob Herring
  Cc: Peter Rosin, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Liam Girdwood,
	Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161115014702.3p5d4bxhwcibovnf@rob-hp-laptop>

[-- Attachment #1: Type: text/plain, Size: 280 bytes --]

On Mon, Nov 14, 2016 at 07:47:02PM -0600, Rob Herring wrote:
> qOn Thu, Nov 10, 2016 at 11:25:27AM +0100, Peter Rosin wrote:
> > While at it, clean up some other things as well.

> As this is just DT docs, I've applied.

That's now going to conflict with some updates I've got...

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply

* Re: [PATCH v4 2/2] Add support for OV5647 sensor
From: Pavel Machek @ 2016-11-15 14:52 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Ramiro Oliveira, mchehab-DgEjT+Ai2ygdnm+yROfE0A,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-media-u79uwXL29TY76Z2rM5mHXA,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, devicetree-u79uwXL29TY76Z2rM5mHXA,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	hverkuil-qWit8jRvyhVmR6Xm/wNWPw,
	dheitmueller-eb9eJ82Ua7k9XoPSrs7Ehg,
	slongerbeam-Re5JQEeQqe8AvxtiuMwx3w, lars-Qo5EllUWu/uELgA04lAiVw,
	robert.jarzmik-GANU6spQydw, pali.rohar-Re5JQEeQqe8AvxtiuMwx3w,
	sakari.ailus-VuQAYsv1563Yd54FQh9/CA, mark.rutland-5wv7dgnIgG8,
	CARLOS.PALMINHA-HKixBCOQz3hWk0Htik3J/w
In-Reply-To: <3b6863c4-e239-7b66-1d96-7f0326f507c5-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 977 bytes --]

On Tue 2016-11-15 05:50:32, Guenter Roeck wrote:
> On 11/15/2016 04:10 AM, Pavel Machek wrote:
> >Hi!
> >
> >>Add support for OV5647 sensor.
> >>
> >
> >>+static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val)
> >>+{
> >>+	int ret;
> >>+	unsigned char data[3] = { reg >> 8, reg & 0xff, val};
> >>+	struct i2c_client *client = v4l2_get_subdevdata(sd);
> >>+
> >>+	ret = i2c_master_send(client, data, 3);
> >>+	if (ret != 3) {
> >>+		dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n",
> >>+				__func__, reg);
> >>+		return ret < 0 ? ret : -EIO;
> >>+	}
> >>+	return 0;
> >>+}
> >
> >Sorry, this is wrong. It should something <0 any time error is detected.
> >
> 
> It seems to me that it does return a value < 0 each time an error is detected.

Yep, you are right, sorry, I misparsed the code.

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply

* Re: [v8, 1/3] Documentation: dt: net: add ath9k wireless device binding
From: Kalle Valo @ 2016-11-15 14:56 UTC (permalink / raw)
  Cc: ath9k-devel-xDcbHBWguxHbcTqmT+pZeQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	ath9k-devel-A+ZNKFmMK5xy9aJCnZT0Uw,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mcgrof-3uybbJdB1yH774rrrx3eTA,
	mark.rutland-5wv7dgnIgG8, kvalo-sgV2jX0FEOL9JmXXK+q4OQ,
	chunkeey-gM/Ye1E23mwN+BqQ9rBEUg,
	arend.vanspriel-dY08KVG/lbpWk0Htik3J/w,
	julian.calaby-Re5JQEeQqe8AvxtiuMwx3w, bjorn-yOkvZcmFvRU,
	linux-YEK0n+YFykbzxQdaRaTXBw, nbd-Vt+b4OUoWG0,
	Martin Blumenstingl
In-Reply-To: <20161016205907.19927-2-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote:
> Add documentation how devicetree can be used to configure ath9k based
> devices.
> 
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

3 patches applied to ath-next branch of ath.git, thanks.

fc383ffdb91a Documentation: dt: net: add ath9k wireless device binding
b40ded2ad75c ath9k: add a helper to get the string representation of ath_bus_type
138b41253d9c ath9k: parse the device configuration from an OF node

-- 
https://patchwork.kernel.org/patch/9378317/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply


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