Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2, 3/9] arm64: dts: ls1043a: fix typo of MSI compatible string
From: Minghuan Lian @ 2017-01-05  8:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483603837-4629-1-git-send-email-Minghuan.Lian@nxp.com>

"1" should be replaced by "l". This is a typo.
The patch is to fix it.

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v2-v1:
- None

 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index ec13a6e..692fc35 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -589,21 +589,21 @@
 		};
 
 		msi1: msi-controller1 at 1571000 {
-			compatible = "fsl,1s1043a-msi";
+			compatible = "fsl,ls1043a-msi";
 			reg = <0x0 0x1571000 0x0 0x8>;
 			msi-controller;
 			interrupts = <0 116 0x4>;
 		};
 
 		msi2: msi-controller2 at 1572000 {
-			compatible = "fsl,1s1043a-msi";
+			compatible = "fsl,ls1043a-msi";
 			reg = <0x0 0x1572000 0x0 0x8>;
 			msi-controller;
 			interrupts = <0 126 0x4>;
 		};
 
 		msi3: msi-controller3 at 1573000 {
-			compatible = "fsl,1s1043a-msi";
+			compatible = "fsl,ls1043a-msi";
 			reg = <0x0 0x1573000 0x0 0x8>;
 			msi-controller;
 			interrupts = <0 160 0x4>;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2,2/9] arm: dts: ls1021a: fix typo of MSI compatible string
From: Minghuan Lian @ 2017-01-05  8:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483603837-4629-1-git-send-email-Minghuan.Lian@nxp.com>

"1" should be replaced by "l". This is a typo.
The patch is to fix it.

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
---
v2-v1:
- None

 arch/arm/boot/dts/ls1021a.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index 282d854..6651938 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -122,14 +122,14 @@
 		};
 
 		msi1: msi-controller at 1570e00 {
-			compatible = "fsl,1s1021a-msi";
+			compatible = "fsl,ls1021a-msi";
 			reg = <0x0 0x1570e00 0x0 0x8>;
 			msi-controller;
 			interrupts =  <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		msi2: msi-controller at 1570e08 {
-			compatible = "fsl,1s1021a-msi";
+			compatible = "fsl,ls1021a-msi";
 			reg = <0x0 0x1570e08 0x0 0x8>;
 			msi-controller;
 			interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2, 1/9] irqchip/ls-scfg-msi: fix typo of MSI compatible strings
From: Minghuan Lian @ 2017-01-05  8:10 UTC (permalink / raw)
  To: linux-arm-kernel

The patch is to fix typo of the Layerscape SCFG MSI dts compatible
strings. "1" is replaced by "l".

Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
Acked-by: Rob Herring <robh@kernel.org>
---
v2-v1:
- None

 .../devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt    | 6 +++---
 drivers/irqchip/irq-ls-scfg-msi.c                                   | 6 ++++--
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
index 9e38949..2755cd1 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
@@ -4,8 +4,8 @@ Required properties:
 
 - compatible: should be "fsl,<soc-name>-msi" to identify
 	      Layerscape PCIe MSI controller block such as:
-              "fsl,1s1021a-msi"
-              "fsl,1s1043a-msi"
+              "fsl,ls1021a-msi"
+              "fsl,ls1043a-msi"
 - msi-controller: indicates that this is a PCIe MSI controller node
 - reg: physical base address of the controller and length of memory mapped.
 - interrupts: an interrupt to the parent interrupt controller.
@@ -23,7 +23,7 @@ MSI controller node
 Examples:
 
 	msi1: msi-controller at 1571000 {
-		compatible = "fsl,1s1043a-msi";
+		compatible = "fsl,ls1043a-msi";
 		reg = <0x0 0x1571000 0x0 0x8>,
 		msi-controller;
 		interrupts = <0 116 0x4>;
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 02cca74c..cef67cc 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -219,8 +219,10 @@ static int ls_scfg_msi_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id ls_scfg_msi_id[] = {
-	{ .compatible = "fsl,1s1021a-msi", },
-	{ .compatible = "fsl,1s1043a-msi", },
+	{ .compatible = "fsl,1s1021a-msi", }, /* a typo */
+	{ .compatible = "fsl,1s1043a-msi", }, /* a typo */
+	{ .compatible = "fsl,ls1021a-msi", },
+	{ .compatible = "fsl,ls1043a-msi", },
 	{},
 };
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH RESEND] dmaengine: stm32-dma: Add error messages if xlate fails
From: M'boumba Cedric Madianga @ 2017-01-05  8:09 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds some error messages when a slave device fails to request a
channel.

Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
Reviewed-by: Ludovic BARRE <ludovic.barre@st.com>
---
Resolve conflicts issue
---
 drivers/dma/stm32-dma.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c
index fc9738e..4eacd9d 100644
--- a/drivers/dma/stm32-dma.c
+++ b/drivers/dma/stm32-dma.c
@@ -987,30 +987,36 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
 					   struct of_dma *ofdma)
 {
 	struct stm32_dma_device *dmadev = ofdma->of_dma_data;
+	struct device *dev = dmadev->ddev.dev;
 	struct stm32_dma_cfg cfg;
 	struct stm32_dma_chan *chan;
 	struct dma_chan *c;
 
-	if (dma_spec->args_count < 3)
+	if (dma_spec->args_count < 4) {
+		dev_err(dev, "Bad number of cells\n");
 		return NULL;
+	}
 
 	cfg.channel_id = dma_spec->args[0];
 	cfg.request_line = dma_spec->args[1];
 	cfg.stream_config = dma_spec->args[2];
-	cfg.threshold = 0;
+	cfg.threshold = dma_spec->args[3];
 
-	if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >=
-				STM32_DMA_MAX_REQUEST_ID))
+	if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) ||
+	    (cfg.request_line >= STM32_DMA_MAX_REQUEST_ID)) {
+		dev_err(dev, "Bad channel and/or request id\n");
 		return NULL;
-
-	if (dma_spec->args_count > 3)
-		cfg.threshold = dma_spec->args[3];
+	}
 
 	chan = &dmadev->chan[cfg.channel_id];
 
 	c = dma_get_slave_channel(&chan->vchan.chan);
-	if (c)
-		stm32_dma_set_config(chan, &cfg);
+	if (!c) {
+		dev_err(dev, "No more channel avalaible\n");
+		return NULL;
+	}
+
+	stm32_dma_set_config(chan, &cfg);
 
 	return c;
 }
-- 
1.9.1

^ permalink raw reply related

* [PATCH 05/22] ARM: dtsi: axp209: add AXP209 ADC subnode
From: Quentin Schulz @ 2017-01-05  8:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGb2v66dw=DECuHpLDzHnMP-O4UwZ+RkPsH0RofOGdBa7z7OHw@mail.gmail.com>

On 05/01/2017 06:51, Chen-Yu Tsai wrote:
> On Tue, Jan 3, 2017 at 12:37 AM, Quentin Schulz
> <quentin.schulz@free-electrons.com> wrote:
>> X-Powers AXP209 PMIC has multiple ADCs, each one exposing data from the
>> different power supplies connected to the PMIC.
>>
>> This adds the ADC subnode for AXP20X PMIC.
>>
>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
>> ---
>>  arch/arm/boot/dts/axp209.dtsi | 5 +++++
>>  1 file changed, 5 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/axp209.dtsi b/arch/arm/boot/dts/axp209.dtsi
>> index 675bb0f..2a4e8ee 100644
>> --- a/arch/arm/boot/dts/axp209.dtsi
>> +++ b/arch/arm/boot/dts/axp209.dtsi
>> @@ -53,6 +53,11 @@
>>         interrupt-controller;
>>         #interrupt-cells = <1>;
>>
>> +       axp209_adc: axp209_adc {
> 
> Node name should be generic. Please change it to "adc".
> 

OK, do I keep the label as is?

axp209_adc: adc {

Thanks,
Quentin

-- 
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH 03/22] iio: adc: add support for X-Powers AXP20X and AXP22X PMICs ADCs
From: Quentin Schulz @ 2017-01-05  8:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGb2v67S==AG=jZA=mO-bB4u1F2TOwhmBXg385W1xhUa3RAFbA@mail.gmail.com>

Hi Chen-Yu,

On 05/01/2017 06:42, Chen-Yu Tsai wrote:
> On Tue, Jan 3, 2017 at 12:37 AM, Quentin Schulz
> <quentin.schulz@free-electrons.com> wrote:
[...]
>> +
>> +#define AXP20X_ADC_RATE_MASK                   (3 << 6)
>> +#define AXP20X_ADC_RATE_25HZ                   (0 << 6)
>> +#define AXP20X_ADC_RATE_50HZ                   BIT(6)
> 
> Please be consistent with the format.
> 
>> +#define AXP20X_ADC_RATE_100HZ                  (2 << 6)
>> +#define AXP20X_ADC_RATE_200HZ                  (3 << 6)
>> +
>> +#define AXP22X_ADC_RATE_100HZ                  (0 << 6)
>> +#define AXP22X_ADC_RATE_200HZ                  BIT(6)
>> +#define AXP22X_ADC_RATE_400HZ                  (2 << 6)
>> +#define AXP22X_ADC_RATE_800HZ                  (3 << 6)
> 
> These are power-of-2 multiples of some base rate. May I suggest
> a formula macro instead. Either way, you seem to be using only
> one value. Will this be made configurable in the future?
> 

Yes, I could use a formula macro instead. No plan to make it
configurable, should I make it configurable?

>> +
>> +#define AXP20X_ADC_CHANNEL(_channel, _name, _type, _reg)       \
>> +       {                                                       \
>> +               .type = _type,                                  \
>> +               .indexed = 1,                                   \
>> +               .channel = _channel,                            \
>> +               .address = _reg,                                \
>> +               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |  \
>> +                                     BIT(IIO_CHAN_INFO_SCALE), \
>> +               .datasheet_name = _name,                        \
>> +       }
>> +
>> +#define AXP20X_ADC_CHANNEL_OFFSET(_channel, _name, _type, _reg) \
>> +       {                                                       \
>> +               .type = _type,                                  \
>> +               .indexed = 1,                                   \
>> +               .channel = _channel,                            \
>> +               .address = _reg,                                \
>> +               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |  \
>> +                                     BIT(IIO_CHAN_INFO_SCALE) |\
>> +                                     BIT(IIO_CHAN_INFO_OFFSET),\
>> +               .datasheet_name = _name,                        \
>> +       }
>> +
>> +struct axp20x_adc_iio {
>> +       struct iio_dev          *indio_dev;
>> +       struct regmap           *regmap;
>> +};
>> +
>> +enum axp20x_adc_channel {
>> +       AXP20X_ACIN_V = 0,
>> +       AXP20X_ACIN_I,
>> +       AXP20X_VBUS_V,
>> +       AXP20X_VBUS_I,
>> +       AXP20X_TEMP_ADC,
> 
> PMIC_TEMP would be better. And please save a slot for TS input.
> 

ACK.

Hum.. I'm wondering what should be the IIO type of the TS input channel
then? The TS Pin can be used in two modes: either to monitor the
temperature of the battery or as an external ADC, at least that's what I
understand from the datasheet.

>> +       AXP20X_GPIO0_V,
>> +       AXP20X_GPIO1_V,
> 
> Please skip a slot for "battery instantaneous power".
> 
>> +       AXP20X_BATT_V,
>> +       AXP20X_BATT_CHRG_I,
>> +       AXP20X_BATT_DISCHRG_I,
>> +       AXP20X_IPSOUT_V,
>> +};
>> +
>> +enum axp22x_adc_channel {
>> +       AXP22X_TEMP_ADC = 0,
> 
> Same comments as AXP20X_TEMP_ADC.
> 
>> +       AXP22X_BATT_V,
>> +       AXP22X_BATT_CHRG_I,
>> +       AXP22X_BATT_DISCHRG_I,
>> +};
> 
> Shouldn't these channel numbers be exported as part of the device tree
> bindings? At the very least, they shouldn't be changed.
> 

I don't understand what you mean by that. Do you mean you want a
consistent numbering between the AXP20X and the AXP22X, so that
AXP22X_BATT_V would have the same channel number than AXP20X_BATT_V?

Could you explain a bit more your thoughts on the channel numbers being
exported as part of the device tree bindings?

> Also please add a comment saying that the channels are numbered
> in the order of their respective registers, and not the table
> describing the ADCs in the datasheet (9.7 Signal Capture for AXP209
> and 9.5 E-Gauge for AXP221).
> 

Yes I can.

What about Rob wanting channel numbers to start at zero for each
different IIO type (i.e., today we have AXP22X_BATT_CHRG_I being
exported as in_current1_raw whereas he wants in_current0_raw).
[...]
>> +static int axp22x_adc_read_raw(struct iio_dev *indio_dev,
>> +                              struct iio_chan_spec const *channel, int *val,
>> +                              int *val2)
>> +{
>> +       struct axp20x_adc_iio *info = iio_priv(indio_dev);
>> +       int size = 12, ret;
>> +
>> +       switch (channel->channel) {
>> +       case AXP22X_BATT_DISCHRG_I:
>> +               size = 13;
>> +       case AXP22X_TEMP_ADC:
>> +       case AXP22X_BATT_V:
>> +       case AXP22X_BATT_CHRG_I:
> 
> According to the datasheet, AXP22X_BATT_CHRG_I is also 13 bits wide.
> 

Where did you get that?

Also, the datasheet is inconsistent:
 - 9.5 E-Gauge Fuel Gauge system => the min value is at 0x0 and the max
value at 0xfff for all channels, that's 12 bits.
 - 10.1.4 ADC Data => all channels except battery discharge current are
on 12 bits (8 high, 4 low).

[...]
>> +static int axp22x_read_raw(struct iio_dev *indio_dev,
>> +                          struct iio_chan_spec const *chan, int *val,
>> +                          int *val2, long mask)
>> +{
>> +       switch (mask) {
>> +       case IIO_CHAN_INFO_OFFSET:
>> +               *val = -2667;
> 
> Datasheet says -267.7 C, or -2677 here.
> 

The formula in the datasheet is (in milli Celsius):
 processed = raw * 100 - 266700;

while the IIO framework asks for a scale and an offset which are then
applied as:
 processed = (raw + offset) * scale;

Thus by factorizing, we get:
 processed = (raw - 2667) * 100;

[...]
>> +static int axp20x_remove(struct platform_device *pdev)
>> +{
>> +       struct axp20x_adc_iio *info;
>> +       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>> +
>> +       info = iio_priv(indio_dev);
> 
> Nit: you could just reverse the 2 declarations above and join this
> line after struct axp20x_adc_iio *info;
> 
>> +       regmap_write(info->regmap, AXP20X_ADC_EN1, 0);
>> +       regmap_write(info->regmap, AXP20X_ADC_EN2, 0);
> 
> The existing VBUS power supply driver enables the VBUS ADC bits itself,
> and does not check them later on. This means if one were to remove this
> axp20x-adc module, the voltage/current readings in the VBUS power supply
> would be invalid. Some sort of workaround would be needed here in this
> driver of the VBUS driver.
> 

That would be one reason to migrate the VBUS driver to use the IIO
channels, wouldn't it?

But ACK, I'll think about something to work around this issue.

>> +
>> +       return 0;
>> +}
>> +
>> +static struct platform_driver axp20x_adc_driver = {
>> +       .driver = {
>> +               .name = "axp20x-adc",
>> +               .of_match_table = axp20x_adc_of_match,
>> +       },
>> +       .probe = axp20x_probe,
>> +       .remove = axp20x_remove,
>> +};
>> +
>> +module_platform_driver(axp20x_adc_driver);
>> +
>> +MODULE_DESCRIPTION("ADC driver for AXP20X and AXP22X PMICs");
>> +MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
>> +MODULE_LICENSE("GPL");
>> diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
>> index a4860bc..650c6f6 100644
>> --- a/include/linux/mfd/axp20x.h
>> +++ b/include/linux/mfd/axp20x.h
>> @@ -150,6 +150,10 @@ enum {
>>  #define AXP20X_VBUS_I_ADC_L            0x5d
>>  #define AXP20X_TEMP_ADC_H              0x5e
>>  #define AXP20X_TEMP_ADC_L              0x5f
>> +
>> +#define AXP22X_TEMP_ADC_H              0x56
>> +#define AXP22X_TEMP_ADC_L              0x57
>> +
> 
> This is in the wrong patch. Also we already have
> 
> /* AXP22X specific registers */
> #define AXP22X_PMIC_ADC_H               0x56
> #define AXP22X_PMIC_ADC_L               0x57
> #define AXP22X_TS_ADC_H                 0x58
> #define AXP22X_TS_ADC_L                 0x59
> 
> If you want, you could just rename them to be consistent.
> 

ACK.

Thanks,
Quentin

-- 
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH 6/9] arm64: dts: ls1046a: add MSI dts node
From: M.H. Lian @ 2017-01-05  8:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170103171258.h5djzsarokjjldjx@rob-hp-laptop>

Hi Rob,

Thanks for your comment.
I will change whitespace.

Thanks,
Minghuan

> -----Original Message-----
> From: Rob Herring [mailto:robh at kernel.org]
> Sent: Wednesday, January 04, 2017 1:13 AM
> To: M.H. Lian <minghuan.lian@nxp.com>
> Cc: linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> devicetree at vger.kernel.org; Marc Zyngier <marc.zyngier@arm.com>; Jason
> Cooper <jason@lakedaemon.net>; Roy Zang <roy.zang@nxp.com>; Mingkai
> Hu <mingkai.hu@nxp.com>; Stuart Yoder <stuart.yoder@nxp.com>; Leo Li
> <leoyang.li@nxp.com>; Scott Wood <scott.wood@nxp.com>
> Subject: Re: [PATCH 6/9] arm64: dts: ls1046a: add MSI dts node
> 
> On Tue, Dec 27, 2016 at 05:13:02PM +0800, Minghuan Lian wrote:
> > LS1046a includes 3 MSI controllers.
> > Each controller supports 128 interrupts.
> >
> > Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
> > ---
> >  .../interrupt-controller/fsl,ls-scfg-msi.txt       |  1 +
> >  arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi     | 31
> ++++++++++++++++++++++
> >  2 files changed, 32 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-
> scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-
> controller/fsl,ls-scfg-msi.txt
> > index 2755cd1..54597b0 100644
> > --- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-
> msi.txt
> > +++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-
> msi.txt
> > @@ -6,6 +6,7 @@ Required properties:
> >  	      Layerscape PCIe MSI controller block such as:
> >                "fsl,ls1021a-msi"
> >                "fsl,ls1043a-msi"
> > +	      "fsl,ls1046a-msi"
> 
> Differing whitespace.
> 
> Otherwise,
> 
> Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply

* [GIT PULL] Renesas ARM Based SoC Fixes for v4.10
From: Simon Horman @ 2017-01-05  7:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3426031.nFTgvuDslP@wuerfel>

On Wed, Jan 04, 2017 at 04:10:09PM +0100, Arnd Bergmann wrote:
> On Monday, December 12, 2016 9:30:00 AM CET Simon Horman wrote:
> > This provides an sd0_uhs node rather than duplicate sdh0 nodes
> > resolving an error introduced in a clean-up patch.
> > 
> > This pull request is based on "Second Round of Renesas ARM Based SoC DT
> > Updates for v4.10", tagged as renesas-arm64-dt2-for-v4.10,
> > which you have already pulled. The error corrected by this change
> > was introduced in that pull-request.
> > 
> 
> Pulled into fixes, sorry for the delay.

Great, thanks!

^ permalink raw reply

* [PATCH v2] mfd: mc13xxx: Set the irq type.
From: Lee Jones @ 2017-01-05  7:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAM=E1R59oKhT3b8=nJ3Utg4cPi0Z6oiLkj8DU7grg6T+2CoMAw@mail.gmail.com>

Thomas,

On Wed, 04 Jan 2017, Magnus Lilja wrote:
> On 4 January 2017 at 12:09, Lee Jones <lee.jones@linaro.org> wrote:
> > On Fri, 30 Dec 2016, Magnus Lilja wrote:
> >
> >> Commit 10f9edaeaa30 ("mfd: mc13xxx: Use regmap irq framework for
> >> interrupts") removed the passing of the IRQF_TRIGGER_HIGH flag when
> >> registering the interrupt.
> >> This commit fixes that problem by setting the IRQF_TRIGGER_HIGH flag in
> >> case no irq type is set via irqd framework (e.g. device tree). In the
> >> latter case the irq flag from irqd is used.
> >
> > This looks like a hack.
> >
> > Why can't you set the trigger type in Device Tree instead?
> 
> The i.MX31 PDK board has not, like many (all?) i.MX31 boards, not been
> converted to use device tree yet. I think there is work in progress in
> this area. However, as the IRQF_TRIGGER problem also affects several
> stable kernel series (since 3.18.x) I thought it was worthwhile to fix
> this.

I would like Thomas' advice on this.

> >> Tested on i.MX31 PDK hardware.
> >>
> >> Fixes: 10f9edaeaa30 ("mfd: mc13xxx: Use regmap irq framework for interrupts")
> >> Cc: <stable@vger.kernel.org> # 3.18.x
> >> Cc: Lee Jones <lee.jones@linaro.org>
> >> Signed-off-by: Magnus Lilja <lilja.magnus@gmail.com>
> >> ---
> >> Changes from v1 (which was part of a patch series):
> >>   - Now uses irqd_-functions to check if irq type is defined
> >>   - Added Fixes: and Cc: to stable kernel.
> >>
> >>  drivers/mfd/mc13xxx-core.c | 8 +++++++-
> >>  1 file changed, 7 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
> >> index d7f54e4..e1757ea 100644
> >> --- a/drivers/mfd/mc13xxx-core.c
> >> +++ b/drivers/mfd/mc13xxx-core.c
> >> @@ -15,6 +15,7 @@
> >>  #include <linux/of_device.h>
> >>  #include <linux/platform_device.h>
> >>  #include <linux/mfd/core.h>
> >> +#include <linux/irq.h>
> >>
> >>  #include "mc13xxx.h"
> >>
> >> @@ -410,6 +411,7 @@ int mc13xxx_common_init(struct device *dev)
> >>       struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
> >>       u32 revision;
> >>       int i, ret;
> >> +     unsigned int flags;
> >>
> >>       mc13xxx->dev = dev;
> >>
> >> @@ -440,7 +442,11 @@ int mc13xxx_common_init(struct device *dev)
> >>       mc13xxx->irq_chip.irqs = mc13xxx->irqs;
> >>       mc13xxx->irq_chip.num_irqs = ARRAY_SIZE(mc13xxx->irqs);
> >>
> >> -     ret = regmap_add_irq_chip(mc13xxx->regmap, mc13xxx->irq, IRQF_ONESHOT,
> >> +     flags = irqd_get_trigger_type(irq_get_irq_data(mc13xxx->irq));
> >> +     flags = (flags == IRQ_TYPE_NONE) ? IRQF_TRIGGER_HIGH : flags;
> >> +
> >> +     ret = regmap_add_irq_chip(mc13xxx->regmap, mc13xxx->irq,
> >> +                               IRQF_ONESHOT | flags,
> >>                                 0, &mc13xxx->irq_chip, &mc13xxx->irq_data);
> >>       if (ret)
> >>               return ret;
> >

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH V7 3/4] drm/bridge: Add driver for GE B850v3 LVDS/DP++ Bridge
From: Archit Taneja @ 2017-01-05  7:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4232c88a99f44a24287d04d74b891e2eb139864c.1483301745.git.peter.senna@collabora.com>

Hi,

Some comments below.

On 01/02/2017 01:54 AM, Peter Senna Tschudin wrote:
> Add a driver that create a drm_bridge and a drm_connector for the LVDS
> to DP++ display bridge of the GE B850v3.
>
> There are two physical bridges on the video signal pipeline: a
> STDP4028(LVDS to DP) and a STDP2690(DP to DP++).  The hardware and
> firmware made it complicated for this binding to comprise two device
> tree nodes, as the design goal is to configure both bridges based on
> the LVDS signal, which leave the driver powerless to control the video
> processing pipeline. The two bridges behaves as a single bridge, and
> the driver is only needed for telling the host about EDID / HPD, and
> for giving the host powers to ack interrupts. The video signal pipeline
> is as follows:
>
>   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
>
> Cc: Martyn Welch <martyn.welch@collabora.co.uk>
> Cc: Martin Donnelly <martin.donnelly@ge.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Rob Herring <robh@kernel.org>
> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> CC: David Airlie <airlied@linux.ie>
> CC: Thierry Reding <treding@nvidia.com>
> CC: Thierry Reding <thierry.reding@gmail.com>
> CC: Archit Taneja <architt@codeaurora.org>
> Reviewed-by: Enric Balletbo <enric.balletbo@collabora.com>
> Signed-off-by: Peter Senna Tschudin <peter.senna@collabora.com>
> ---
>  drivers/gpu/drm/bridge/Kconfig             |  11 +
>  drivers/gpu/drm/bridge/Makefile            |   1 +
>  drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c | 384 +++++++++++++++++++++++++++++
>  3 files changed, 396 insertions(+)
>  create mode 100644 drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
>
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index eb8688e..e3e1f3b 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -48,6 +48,17 @@ config DRM_DW_HDMI_I2S_AUDIO
>  	  Support the I2S Audio interface which is part of the Synopsis
>  	  Designware HDMI block.
>
> +config DRM_GE_B850V3_LVDS_DP
> +	tristate "GE B850v3 LVDS to DP++ display bridge"
> +	depends on OF
> +	select DRM_KMS_HELPER
> +	select DRM_PANEL
> +	---help---
> +          This is a driver for the display bridge of
> +          GE B850v3 that convert dual channel LVDS
> +          to DP++. This is used with the i.MX6 imx-ldb
> +          driver.
> +
>  config DRM_NXP_PTN3460
>  	tristate "NXP PTN3460 DP/LVDS bridge"
>  	depends on OF
> diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
> index 2e83a785..886d0fd 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -5,6 +5,7 @@ obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
>  obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
>  obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
>  obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
> +obj-$(CONFIG_DRM_GE_B850V3_LVDS_DP) += ge_b850v3_lvds_dp.o
>  obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
>  obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
>  obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
> diff --git a/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c b/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
> new file mode 100644
> index 0000000..4574f6e
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/ge_b850v3_lvds_dp.c
> @@ -0,0 +1,384 @@
> +/*
> + * Driver for GE B850v3 DP display bridge

Mentioning LVDS to DP++ here would be nice.

> +
> + * Copyright (c) 2016, Collabora Ltd.
> + * Copyright (c) 2016, General Electric Company
> +
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> +
> + * This program is distributed in the hope 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/>.
> +
> + * This driver creates a drm_bridge and a drm_connector for the LVDS to DP++
> + * display bridge of the GE B850v3. There are two physical bridges on the video
> + * signal pipeline: a STDP4028(LVDS to DP) and a STDP2690(DP to DP++). However
> + * the physical bridges are automatically configured by the input video signal,
> + * and the driver has no access to the video processing pipeline. The driver is
> + * only needed to read EDID from the STDP2690 and to handle HPD events from the
> + * STDP4028. The driver communicates with both bridges over i2c. The video
> + * signal pipeline is as follows:
> + *
> + *   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
> + *
> + */
> +
> +#include <linux/gpio.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_edid.h>
> +#include <drm/drmP.h>
> +
> +#define DEFAULT_EDID_REG 0x72
> +#define DEFAULT_EDID_REG_NAME "edid"
> +
> +#define EDID_EXT_BLOCK_CNT 0x7E
> +
> +#define STDP4028_IRQ_OUT_CONF_REG 0x02
> +#define STDP4028_DPTX_IRQ_EN_REG 0x3C
> +#define STDP4028_DPTX_IRQ_STS_REG 0x3D
> +#define STDP4028_DPTX_STS_REG 0x3E
> +
> +#define STDP4028_DPTX_DP_IRQ_EN 0x1000
> +
> +#define STDP4028_DPTX_HOTPLUG_IRQ_EN 0x0400
> +#define STDP4028_DPTX_LINK_CH_IRQ_EN 0x2000
> +#define STDP4028_DPTX_IRQ_CONFIG \
> +		(STDP4028_DPTX_LINK_CH_IRQ_EN | STDP4028_DPTX_HOTPLUG_IRQ_EN)
> +
> +#define STDP4028_DPTX_HOTPLUG_STS 0x0200
> +#define STDP4028_DPTX_LINK_STS 0x1000
> +#define STDP4028_CON_STATE_CONNECTED \
> +		(STDP4028_DPTX_HOTPLUG_STS | STDP4028_DPTX_LINK_STS)
> +
> +#define STDP4028_DPTX_HOTPLUG_CH_STS 0x0400
> +#define STDP4028_DPTX_LINK_CH_STS 0x2000
> +#define STDP4028_DPTX_IRQ_CLEAR \
> +		(STDP4028_DPTX_LINK_CH_STS | STDP4028_DPTX_HOTPLUG_CH_STS)
> +
> +struct ge_b850v3_lvds_dp {
> +	struct drm_connector connector;
> +	struct drm_bridge bridge;
> +	struct i2c_client *ge_b850v3_lvds_dp_i2c;
> +	struct i2c_client *edid_i2c;
> +	struct edid *edid;
> +	struct mutex edid_mutex;
> +	struct mutex irq_reg_mutex;
> +};
> +
> +static inline struct ge_b850v3_lvds_dp *
> +		bridge_to_ge_b850v3_lvds_dp(struct drm_bridge *bridge)
> +{
> +	return container_of(bridge, struct ge_b850v3_lvds_dp, bridge);
> +}
> +
> +static inline struct ge_b850v3_lvds_dp *
> +		connector_to_ge_b850v3_lvds_dp(struct drm_connector *connector)
> +{
> +	return container_of(connector, struct ge_b850v3_lvds_dp, connector);
> +}
> +
> +u8 *stdp2690_get_edid(struct i2c_client *client)
> +{
> +	struct i2c_adapter *adapter = client->adapter;
> +	unsigned char start = 0x00;
> +	unsigned int total_size;
> +	u8 *block = kmalloc(EDID_LENGTH, GFP_KERNEL);
> +
> +	struct i2c_msg msgs[] = {
> +		{
> +			.addr	= client->addr,
> +			.flags	= 0,
> +			.len	= 1,
> +			.buf	= &start,
> +		}, {
> +			.addr	= client->addr,
> +			.flags	= I2C_M_RD,
> +			.len	= EDID_LENGTH,
> +			.buf	= block,
> +		}
> +	};
> +
> +	if (!block)
> +		return NULL;
> +
> +	if (i2c_transfer(adapter, msgs, 2) != 2) {
> +		DRM_ERROR("Unable to read EDID.\n");
> +		goto err;
> +	}
> +
> +	if (!drm_edid_block_valid(block, 0, false, NULL)) {
> +		DRM_ERROR("Invalid EDID block\n");
> +		goto err;
> +	}
> +
> +	total_size = (block[EDID_EXT_BLOCK_CNT] + 1) * EDID_LENGTH;
> +	if (total_size > EDID_LENGTH) {
> +		kfree(block);
> +		block = kmalloc(total_size, GFP_KERNEL);
> +		if (!block)
> +			return NULL;
> +
> +		/* Yes, read the entire buffer, and do not skip the first
> +		 * EDID_LENGTH bytes.
> +		 */

Is this the reason why you aren't using drm_do_get_edid()?

> +		start = 0x00;
> +		msgs[1].len = total_size;
> +		msgs[1].buf = block;
> +
> +		if (i2c_transfer(adapter, msgs, 2) != 2) {
> +			DRM_ERROR("Unable to read EDID extension blocks.\n");
> +			goto err;
> +		}

We should ideally check if the extension blocks are valid too.

> +	}
> +
> +	return block;
> +
> +err:
> +	kfree(block);
> +	return NULL;
> +}
> +
> +static int ge_b850v3_lvds_dp_get_modes(struct drm_connector *connector)
> +{
> +	struct ge_b850v3_lvds_dp *ptn_bridge;

Why are the bridge pointers named ptn_bridge? I'm guessing it's because you
used nxp-ptn3460 bridge driver as reference. You should use something relevant
to your device.

> +	struct i2c_client *client;
> +	int num_modes = 0;
> +
> +	ptn_bridge = connector_to_ge_b850v3_lvds_dp(connector);
> +	client = ptn_bridge->edid_i2c;
> +
> +	mutex_lock(&ptn_bridge->edid_mutex);

Do we really need this mutex? All the paths that call a connector's get_modes
hold the drm device's dev->mode_config.mutex lock anyway.

> +
> +	kfree(ptn_bridge->edid);
> +	ptn_bridge->edid = (struct edid *) stdp2690_get_edid(client);
> +
> +	if (ptn_bridge->edid) {
> +		drm_mode_connector_update_edid_property(connector,
> +				ptn_bridge->edid);
> +		num_modes = drm_add_edid_modes(connector, ptn_bridge->edid);
> +	}
> +
> +	mutex_unlock(&ptn_bridge->edid_mutex);
> +
> +	return num_modes;
> +}
> +
> +
> +static enum drm_mode_status ge_b850v3_lvds_dp_mode_valid(
> +		struct drm_connector *connector, struct drm_display_mode *mode)
> +{
> +	return MODE_OK;
> +}
> +
> +static const struct
> +drm_connector_helper_funcs ge_b850v3_lvds_dp_connector_helper_funcs = {
> +	.get_modes = ge_b850v3_lvds_dp_get_modes,
> +	.mode_valid = ge_b850v3_lvds_dp_mode_valid,
> +};
> +
> +static enum drm_connector_status ge_b850v3_lvds_dp_detect(
> +		struct drm_connector *connector, bool force)
> +{
> +	struct ge_b850v3_lvds_dp *ptn_bridge =
> +			connector_to_ge_b850v3_lvds_dp(connector);
> +	struct i2c_client *ge_b850v3_lvds_dp_i2c =
> +			ptn_bridge->ge_b850v3_lvds_dp_i2c;
> +	s32 link_state;
> +
> +	link_state = i2c_smbus_read_word_data(ge_b850v3_lvds_dp_i2c,
> +			STDP4028_DPTX_STS_REG);
> +
> +	if (link_state == STDP4028_CON_STATE_CONNECTED)
> +		return connector_status_connected;
> +
> +	if (link_state == 0)
> +		return connector_status_disconnected;
> +
> +	return connector_status_unknown;
> +}
> +
> +static const struct drm_connector_funcs ge_b850v3_lvds_dp_connector_funcs = {
> +	.dpms = drm_atomic_helper_connector_dpms,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.detect = ge_b850v3_lvds_dp_detect,
> +	.destroy = drm_connector_cleanup,
> +	.reset = drm_atomic_helper_connector_reset,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static irqreturn_t ge_b850v3_lvds_dp_irq_handler(int irq, void *dev_id)
> +{
> +	struct ge_b850v3_lvds_dp *ptn_bridge = dev_id;
> +	struct i2c_client *ge_b850v3_lvds_dp_i2c
> +			= ptn_bridge->ge_b850v3_lvds_dp_i2c;
> +
> +	mutex_lock(&ptn_bridge->irq_reg_mutex);

Do we need this mutex? The handler is registered with the IRQF_ONESHOT
flag, so we won't get another interrupt until this handler returns.

> +
> +	i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> +			STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR);
> +
> +	mutex_unlock(&ptn_bridge->irq_reg_mutex);
> +
> +	if (ptn_bridge->connector.dev)
> +		drm_kms_helper_hotplug_event(ptn_bridge->connector.dev);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int ge_b850v3_lvds_dp_attach(struct drm_bridge *bridge)
> +{
> +	struct ge_b850v3_lvds_dp *ptn_bridge
> +			= bridge_to_ge_b850v3_lvds_dp(bridge);
> +	struct drm_connector *connector = &ptn_bridge->connector;
> +	struct i2c_client *ge_b850v3_lvds_dp_i2c
> +			= ptn_bridge->ge_b850v3_lvds_dp_i2c;
> +	int ret;
> +
> +	if (!bridge->encoder) {
> +		DRM_ERROR("Parent encoder object not found");
> +		return -ENODEV;
> +	}
> +
> +	connector->polled = DRM_CONNECTOR_POLL_HPD;
> +
> +	drm_connector_helper_add(connector,
> +			&ge_b850v3_lvds_dp_connector_helper_funcs);
> +
> +	ret = drm_connector_init(bridge->dev, connector,
> +			&ge_b850v3_lvds_dp_connector_funcs,
> +			DRM_MODE_CONNECTOR_DisplayPort);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize connector with drm\n");
> +		return ret;
> +	}
> +
> +	ret = drm_mode_connector_attach_encoder(connector, bridge->encoder);
> +	if (ret)
> +		return ret;
> +
> +	drm_helper_hpd_irq_event(connector->dev);

This call doesn't serve any purpose for a connector until it is registered.
You can drop this.

> +
> +	/* Configures the bridge to re-enable interrupts after each ack. */
> +	i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> +			STDP4028_IRQ_OUT_CONF_REG, STDP4028_DPTX_DP_IRQ_EN);
> +
> +	/* Enable interrupts */
> +	i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> +			STDP4028_DPTX_IRQ_EN_REG, STDP4028_DPTX_IRQ_CONFIG);
> +
> +	return 0;
> +}
> +
> +static void ge_b850v3_lvds_dp_detach(struct drm_bridge *bridge)
> +{
> +	struct ge_b850v3_lvds_dp *ptn_bridge
> +			= bridge_to_ge_b850v3_lvds_dp(bridge);
> +	struct i2c_client *ge_b850v3_lvds_dp_i2c
> +			= ptn_bridge->ge_b850v3_lvds_dp_i2c;
> +
> +	/* Disable interrupts */
> +	i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> +			STDP4028_DPTX_IRQ_EN_REG, ~STDP4028_DPTX_IRQ_CONFIG);
> +}
> +
> +static const struct drm_bridge_funcs ge_b850v3_lvds_dp_funcs = {
> +	.attach = ge_b850v3_lvds_dp_attach,
> +	.detach = ge_b850v3_lvds_dp_detach,
> +};
> +
> +static int ge_b850v3_lvds_dp_probe(struct i2c_client *ge_b850v3_lvds_dp_i2c,
> +				const struct i2c_device_id *id)
> +{
> +	struct device *dev = &ge_b850v3_lvds_dp_i2c->dev;
> +	struct ge_b850v3_lvds_dp *ptn_bridge;
> +
> +	ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
> +	if (!ptn_bridge)
> +		return -ENOMEM;
> +
> +	mutex_init(&ptn_bridge->edid_mutex);
> +	mutex_init(&ptn_bridge->irq_reg_mutex);
> +
> +	ptn_bridge->ge_b850v3_lvds_dp_i2c = ge_b850v3_lvds_dp_i2c;
> +	ptn_bridge->bridge.driver_private = ptn_bridge;

bridge->driver_private isn't used by the driver anywhere. It's probably
better to drop it until it is used.

> +	i2c_set_clientdata(ge_b850v3_lvds_dp_i2c, ptn_bridge);
> +
> +	ptn_bridge->edid_i2c = i2c_new_secondary_device(ge_b850v3_lvds_dp_i2c,
> +			DEFAULT_EDID_REG_NAME, DEFAULT_EDID_REG);
> +
> +	if (!ptn_bridge->edid_i2c) {
> +		dev_err(dev, "Error registering edid i2c_client, aborting...\n");
> +		return -ENODEV;
> +	}
> +
> +	ptn_bridge->bridge.funcs = &ge_b850v3_lvds_dp_funcs;
> +	ptn_bridge->bridge.of_node = dev->of_node;
> +	drm_bridge_add(&ptn_bridge->bridge);
> +
> +	/* Clear pending interrupts since power up. */
> +	i2c_smbus_write_word_data(ge_b850v3_lvds_dp_i2c,
> +			STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR);
> +
> +	if (!ge_b850v3_lvds_dp_i2c->irq)
> +		return 0;
> +
> +	return devm_request_threaded_irq(&ge_b850v3_lvds_dp_i2c->dev,
> +			ge_b850v3_lvds_dp_i2c->irq, NULL,
> +			ge_b850v3_lvds_dp_irq_handler,
> +			IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
> +			"ge-b850v3-lvds-dp", ptn_bridge);
> +}
> +
> +static int ge_b850v3_lvds_dp_remove(struct i2c_client *ge_b850v3_lvds_dp_i2c)
> +{
> +	struct ge_b850v3_lvds_dp *ptn_bridge =
> +		i2c_get_clientdata(ge_b850v3_lvds_dp_i2c);
> +
> +	i2c_unregister_device(ptn_bridge->edid_i2c);
> +
> +	drm_bridge_remove(&ptn_bridge->bridge);
> +
> +	kfree(ptn_bridge->edid);
> +
> +	return 0;
> +}
> +
> +static const struct i2c_device_id ge_b850v3_lvds_dp_i2c_table[] = {
> +	{"b850v3-lvds-dp", 0},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(i2c, ge_b850v3_lvds_dp_i2c_table);
> +
> +static const struct of_device_id ge_b850v3_lvds_dp_match[] = {
> +	{ .compatible = "ge,b850v3-lvds-dp" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, ge_b850v3_lvds_dp_match);
> +
> +static struct i2c_driver ge_b850v3_lvds_dp_driver = {
> +	.id_table	= ge_b850v3_lvds_dp_i2c_table,
> +	.probe		= ge_b850v3_lvds_dp_probe,
> +	.remove		= ge_b850v3_lvds_dp_remove,
> +	.driver		= {
> +		.name		= "b850v3-lvds-dp",
> +		.of_match_table = ge_b850v3_lvds_dp_match,
> +	},
> +};
> +module_i2c_driver(ge_b850v3_lvds_dp_driver);
> +
> +MODULE_AUTHOR("Peter Senna Tschudin <peter.senna@collabora.com>");
> +MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.co.uk>");
> +MODULE_DESCRIPTION("GE LVDS to DP++ display bridge)");
> +MODULE_LICENSE("GPL v2");
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH 1/2] mfd: micon: Add Buffalo Kurobox Pro, Terastation II Pro/Live driver
From: Lee Jones @ 2017-01-05  7:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3e9b7bfe-8305-64fc-f175-e612576d58a7@gmail.com>

On Wed, 04 Jan 2017, Florian Fainelli wrote:

> Le 01/04/17 ? 03:22, Lee Jones a ?crit :
> > On Wed, 28 Dec 2016, Florian Fainelli wrote:
> > 
> >> This driver is currently only used to reboot the devices, but the
> >> microcontroller hanging off UART1 on the Buffalo Kurobox Pro and
> >> Terastation II Pro/Live is capable of a lot more than that, which we
> >> will support in subsequent patches. For now, just add the reboot
> >> functionality to make the kernel reboot correctly.
> > 
> > This is not an MFD driver.  You have written a UART driver.
> > 
> > Please relocate it to drivers/char/tty/serial.
> 
> Not that simple, and as explained in the cover letter the UART attached
> micro controller can do a lot more than just reboot the machine, but

That's fine.  This is precisely why we have MFD.  But the core (MFD)
driver should only conduct set-up of shared resources, registration of
child devices and maybe some shared functionality required by >1 child
device.  All child device (i.e. UART) capability should be handled by
the child drivers.

> someone else is working on the driver, so this patch series can be ignored.

Okay.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH v6 5/5] soc: zte: pm_domains: Add support for zx296718
From: Shawn Guo @ 2017-01-05  7:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483530494-14177-5-git-send-email-baoyou.xie@linaro.org>

On Wed, Jan 04, 2017 at 07:48:14PM +0800, Baoyou Xie wrote:
> This patch introduces the power domain driver of zx296718
> which belongs to zte's zx2967 family.
> 
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> Reviewed-by: Jun Nie <jun.nie@linaro.org>
> ---
>  drivers/soc/zte/Makefile              |   1 +
>  drivers/soc/zte/zx296718_pm_domains.c | 181 ++++++++++++++++++++++++++++++++++
>  2 files changed, 182 insertions(+)
>  create mode 100644 drivers/soc/zte/zx296718_pm_domains.c
> 
> diff --git a/drivers/soc/zte/Makefile b/drivers/soc/zte/Makefile
> index 8a37f2f..96b7cd4 100644
> --- a/drivers/soc/zte/Makefile
> +++ b/drivers/soc/zte/Makefile
> @@ -2,3 +2,4 @@
>  # ZTE SOC drivers
>  #
>  obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx2967_pm_domains.o
> +obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx296718_pm_domains.o
> diff --git a/drivers/soc/zte/zx296718_pm_domains.c b/drivers/soc/zte/zx296718_pm_domains.c
> new file mode 100644
> index 0000000..52003ee
> --- /dev/null
> +++ b/drivers/soc/zte/zx296718_pm_domains.c
> @@ -0,0 +1,181 @@
> +/*
> + * Copyright (C) 2017 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + * License terms: GNU General Public License (GPL) version 2
> + */

Please have a newline between licence declaration and headers to improve
the readability.  Same for zx2967_pm_domains.c.

> +#include <dt-bindings/soc/zte,pm_domains.h>
> +#include "zx2967_pm_domains.h"
> +
> +static u16 zx296718_offsets[REG_ARRAY_SIZE] = {
> +	[REG_CLKEN] = 0x18,
> +	[REG_ISOEN] = 0x1c,
> +	[REG_RSTEN] = 0x20,
> +	[REG_PWREN] = 0x24,
> +	[REG_ACK_SYNC] = 0x28,
> +};
> +
> +enum {
> +	PCU_DM_VOU = 0,
> +	PCU_DM_SAPPU,
> +	PCU_DM_VDE,
> +	PCU_DM_VCE,
> +	PCU_DM_HDE,
> +	PCU_DM_VIU,
> +	PCU_DM_USB20,
> +	PCU_DM_USB21,
> +	PCU_DM_USB30,
> +	PCU_DM_HSIC,
> +	PCU_DM_GMAC,
> +	PCU_DM_TS,
> +};

I think we can save this enum completely by defining those
DM_ZX296718_xxx constants in zte,pm_domains.h in the same order of this
enum (hardware bit position order), so that DM_ZX296718_xxx can directly
be used as .bit field of struct zx2967_pm_domain.

#define DM_ZX296718_VOU 	0
#define DM_ZX296718_SAPPU	1
#define DM_ZX296718_VDE		2  /* g1v6 */
#define DM_ZX296718_VCE		3  /* h1v6 */
#define DM_ZX296718_HDE		4  /* g2v2 */
#define DM_ZX296718_VIU		5
#define DM_ZX296718_USB20	6
#define DM_ZX296718_USB21	7
#define DM_ZX296718_USB30	8
#define DM_ZX296718_HSIC	9
#define DM_ZX296718_GMAC	10
#define DM_ZX296718_TS		11

> +
> +static struct zx2967_pm_domain vou_domain = {
> +	.dm = {
> +		.name		= "vou_domain",
> +	},
> +	.bit = PCU_DM_VOU,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain sappu_domain = {
> +	.dm = {
> +		.name		= "sappu_domain",
> +	},
> +	.bit = PCU_DM_SAPPU,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain vde_domain = {
> +	.dm = {
> +		.name		= "vde_domain",
> +	},
> +	.bit = PCU_DM_VDE,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain vce_domain = {
> +	.dm = {
> +		.name		= "vce_domain",
> +	},
> +	.bit = PCU_DM_VCE,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain hde_domain = {
> +	.dm = {
> +		.name		= "hde_domain",
> +	},
> +	.bit = PCU_DM_HDE,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain viu_domain = {
> +	.dm = {
> +		.name		= "viu_domain",
> +	},
> +	.bit = PCU_DM_VIU,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain usb20_domain = {
> +	.dm = {
> +		.name		= "usb20_domain",
> +	},
> +	.bit = PCU_DM_USB20,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain usb21_domain = {
> +	.dm = {
> +		.name		= "usb21_domain",
> +	},
> +	.bit = PCU_DM_USB21,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain usb30_domain = {
> +	.dm = {
> +		.name		= "usb30_domain",
> +	},
> +	.bit = PCU_DM_USB30,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain hsic_domain = {
> +	.dm = {
> +		.name		= "hsic_domain",
> +	},
> +	.bit = PCU_DM_HSIC,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain gmac_domain = {
> +	.dm = {
> +		.name		= "gmac_domain",
> +	},
> +	.bit = PCU_DM_GMAC,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct zx2967_pm_domain ts_domain = {
> +	.dm = {
> +		.name		= "ts_domain",
> +	},
> +	.bit = PCU_DM_TS,
> +	.polarity = PWREN,
> +	.reg_offset = zx296718_offsets,
> +};
> +
> +static struct generic_pm_domain *zx296718_pm_domains[] = {
> +	[DM_ZX296718_SAPPU] = &sappu_domain.dm,
> +	[DM_ZX296718_VDE] = &vde_domain.dm,
> +	[DM_ZX296718_VCE] = &vce_domain.dm,
> +	[DM_ZX296718_HDE] = &hde_domain.dm,
> +	[DM_ZX296718_VIU] = &viu_domain.dm,
> +	[DM_ZX296718_USB20] = &usb20_domain.dm,
> +	[DM_ZX296718_USB21] = &usb21_domain.dm,
> +	[DM_ZX296718_USB30] = &usb30_domain.dm,
> +	[DM_ZX296718_HSIC] = &hsic_domain.dm,
> +	[DM_ZX296718_GMAC] = &gmac_domain.dm,
> +	[DM_ZX296718_TS] = &ts_domain.dm,
> +	[DM_ZX296718_VOU] = &vou_domain.dm,

If you update the order of DM_ZX296718_xxx in zte,pm_domains.h, it would
be nice to update this list accordingly as well.

> +};
> +
> +static int zx296718_pd_probe(struct platform_device *pdev)
> +{
> +	return zx2967_pd_probe(pdev,
> +			  zx296718_pm_domains,
> +			  ARRAY_SIZE(zx296718_pm_domains));
> +}
> +
> +static const struct of_device_id zx296718_pm_domain_matches[] = {
> +	{ .compatible = "zte,zx296718-pcu", },
> +	{ },
> +};
> +
> +static struct platform_driver zx296718_pd_driver = {
> +	.driver = {
> +		.name = "zx-powerdomain",

This is a zx296718 specific driver.  So zx296718-powerdomain should
be a better name?

Shawn

> +		.owner = THIS_MODULE,
> +		.of_match_table = zx296718_pm_domain_matches,
> +	},
> +	.probe = zx296718_pd_probe,
> +};
> +
> +static int __init zx296718_pd_init(void)
> +{
> +	return platform_driver_register(&zx296718_pd_driver);
> +}
> +subsys_initcall(zx296718_pd_init);
> -- 
> 2.7.4
> 

^ permalink raw reply

* [PATCH v3 2/3] drm: zte: add .atomic_disable hook to disable graphic layer
From: Sean Paul @ 2017-01-05  7:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482979048-32037-3-git-send-email-shawnguo@kernel.org>

On Wed, Dec 28, 2016 at 9:37 PM, Shawn Guo <shawnguo@kernel.org> wrote:
> From: Shawn Guo <shawn.guo@linaro.org>
>
> There are a few hardware bits for each graphic layer to control main/aux
> channel and clock selection, as well as the layer enabling.  These bits
> sit outside the layer block itself, but in VOU control glue block.  We
> currently set these bits up at CRTC initialization for once, and do not
> support disabling the layer.
>
> This patch creates a pair of functions zx_vou_layer_enable[disable] to
> be invoked from plane hooks .atomic_update and .atomic_disable to set up
> and tear down the layer.  This is generic for both graphic and video
> layers, so it will make the overlay plane support to be added later much
> easier.
>

This feels ever so slightly awkward since the plane is calling back to
the crtc in enable/disable, but i suppose this is a byproduct of
defining the atomic plane hooks in zx_plane. I think we just need to
be careful not to introduce more of these cross-block/file
dependencies, as that might signify that zx_plane should be merged
into zx_vou. At the moment, I feel like this is fine, so,

Reviewed-by: Sean Paul <seanpaul@chromium.org>


> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
>  drivers/gpu/drm/zte/zx_plane.c | 15 +++++++++
>  drivers/gpu/drm/zte/zx_plane.h |  1 +
>  drivers/gpu/drm/zte/zx_vou.c   | 70 ++++++++++++++++++++++++++++++------------
>  drivers/gpu/drm/zte/zx_vou.h   |  3 ++
>  4 files changed, 69 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
> index 78d29b1db91c..5445eebf830f 100644
> --- a/drivers/gpu/drm/zte/zx_plane.c
> +++ b/drivers/gpu/drm/zte/zx_plane.c
> @@ -197,12 +197,27 @@ static void zx_gl_plane_atomic_update(struct drm_plane *plane,
>         /* Enable HBSC block */
>         zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
>
> +       zx_vou_layer_enable(plane);
> +
>         zx_gl_set_update(zplane);
>  }
>
> +static void zx_plane_atomic_disable(struct drm_plane *plane,
> +                                   struct drm_plane_state *old_state)
> +{
> +       struct zx_plane *zplane = to_zx_plane(plane);
> +       void __iomem *hbsc = zplane->hbsc;
> +
> +       zx_vou_layer_disable(plane);
> +
> +       /* Disable HBSC block */
> +       zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, 0);
> +}
> +
>  static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
>         .atomic_check = zx_gl_plane_atomic_check,
>         .atomic_update = zx_gl_plane_atomic_update,
> +       .atomic_disable = zx_plane_atomic_disable,
>  };
>
>  static void zx_plane_destroy(struct drm_plane *plane)
> diff --git a/drivers/gpu/drm/zte/zx_plane.h b/drivers/gpu/drm/zte/zx_plane.h
> index 264a92e0b532..933611ddffd0 100644
> --- a/drivers/gpu/drm/zte/zx_plane.h
> +++ b/drivers/gpu/drm/zte/zx_plane.h
> @@ -18,6 +18,7 @@ struct zx_plane {
>         void __iomem *csc;
>         void __iomem *hbsc;
>         void __iomem *rsz;
> +       const struct vou_layer_bits *bits;
>  };
>
>  #define to_zx_plane(plane) container_of(plane, struct zx_plane, plane)
> diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c
> index d5c801f6f97b..3fb4fc04e693 100644
> --- a/drivers/gpu/drm/zte/zx_vou.c
> +++ b/drivers/gpu/drm/zte/zx_vou.c
> @@ -65,7 +65,6 @@ struct zx_crtc_bits {
>         u32 polarity_shift;
>         u32 int_frame_mask;
>         u32 tc_enable;
> -       u32 gl_enable;
>  };
>
>  static const struct zx_crtc_bits main_crtc_bits = {
> @@ -73,7 +72,6 @@ struct zx_crtc_bits {
>         .polarity_shift = MAIN_POL_SHIFT,
>         .int_frame_mask = TIMING_INT_MAIN_FRAME,
>         .tc_enable = MAIN_TC_EN,
> -       .gl_enable = OSD_CTRL0_GL0_EN,
>  };
>
>  static const struct zx_crtc_bits aux_crtc_bits = {
> @@ -81,7 +79,6 @@ struct zx_crtc_bits {
>         .polarity_shift = AUX_POL_SHIFT,
>         .int_frame_mask = TIMING_INT_AUX_FRAME,
>         .tc_enable = AUX_TC_EN,
> -       .gl_enable = OSD_CTRL0_GL1_EN,
>  };
>
>  struct zx_crtc {
> @@ -97,6 +94,24 @@ struct zx_crtc {
>
>  #define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
>
> +struct vou_layer_bits {
> +       u32 enable;
> +       u32 chnsel;
> +       u32 clksel;
> +};
> +
> +static const struct vou_layer_bits zx_gl_bits[GL_NUM] = {
> +       {
> +               .enable = OSD_CTRL0_GL0_EN,
> +               .chnsel = OSD_CTRL0_GL0_SEL,
> +               .clksel = VOU_CLK_GL0_SEL,
> +       }, {
> +               .enable = OSD_CTRL0_GL1_EN,
> +               .chnsel = OSD_CTRL0_GL1_SEL,
> +               .clksel = VOU_CLK_GL1_SEL,
> +       },
> +};
> +
>  struct zx_vou_hw {
>         struct device *dev;
>         void __iomem *osd;
> @@ -220,10 +235,6 @@ static void zx_crtc_enable(struct drm_crtc *crtc)
>         /* Enable channel */
>         zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
>
> -       /* Enable Graphic Layer */
> -       zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable,
> -                      bits->gl_enable);
> -
>         drm_crtc_vblank_on(crtc);
>
>         ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
> @@ -247,9 +258,6 @@ static void zx_crtc_disable(struct drm_crtc *crtc)
>
>         drm_crtc_vblank_off(crtc);
>
> -       /* Disable Graphic Layer */
> -       zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable, 0);
> -
>         /* Disable channel */
>         zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
>
> @@ -316,6 +324,7 @@ static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
>                 zplane->csc = vou->osd + MAIN_CSC_OFFSET;
>                 zplane->hbsc = vou->osd + MAIN_HBSC_OFFSET;
>                 zplane->rsz = vou->otfppu + MAIN_RSZ_OFFSET;
> +               zplane->bits = &zx_gl_bits[0];
>                 zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
>                 zcrtc->regs = &main_crtc_regs;
>                 zcrtc->bits = &main_crtc_bits;
> @@ -324,6 +333,7 @@ static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
>                 zplane->csc = vou->osd + AUX_CSC_OFFSET;
>                 zplane->hbsc = vou->osd + AUX_HBSC_OFFSET;
>                 zplane->rsz = vou->otfppu + AUX_RSZ_OFFSET;
> +               zplane->bits = &zx_gl_bits[1];
>                 zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
>                 zcrtc->regs = &aux_crtc_regs;
>                 zcrtc->bits = &aux_crtc_bits;
> @@ -411,6 +421,36 @@ void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe)
>                        zcrtc->bits->int_frame_mask, 0);
>  }
>
> +void zx_vou_layer_enable(struct drm_plane *plane)
> +{
> +       struct zx_crtc *zcrtc = to_zx_crtc(plane->state->crtc);
> +       struct zx_vou_hw *vou = zcrtc->vou;
> +       struct zx_plane *zplane = to_zx_plane(plane);
> +       const struct vou_layer_bits *bits = zplane->bits;
> +
> +       if (zcrtc->chn_type == VOU_CHN_MAIN) {
> +               zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel, 0);
> +               zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel, 0);
> +       } else {
> +               zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel,
> +                              bits->chnsel);
> +               zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel,
> +                              bits->clksel);
> +       }
> +
> +       zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, bits->enable);
> +}
> +
> +void zx_vou_layer_disable(struct drm_plane *plane)
> +{
> +       struct zx_crtc *zcrtc = to_zx_crtc(plane->crtc);
> +       struct zx_vou_hw *vou = zcrtc->vou;
> +       struct zx_plane *zplane = to_zx_plane(plane);
> +       const struct vou_layer_bits *bits = zplane->bits;
> +
> +       zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, 0);
> +}
> +
>  static irqreturn_t vou_irq_handler(int irq, void *dev_id)
>  {
>         struct zx_vou_hw *vou = dev_id;
> @@ -469,19 +509,9 @@ static void vou_dtrc_init(struct zx_vou_hw *vou)
>
>  static void vou_hw_init(struct zx_vou_hw *vou)
>  {
> -       /* Set GL0 to main channel and GL1 to aux channel */
> -       zx_writel_mask(vou->osd + OSD_CTRL0, OSD_CTRL0_GL0_SEL, 0);
> -       zx_writel_mask(vou->osd + OSD_CTRL0, OSD_CTRL0_GL1_SEL,
> -                      OSD_CTRL0_GL1_SEL);
> -
>         /* Release reset for all VOU modules */
>         zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
>
> -       /* Select main clock for GL0 and aux clock for GL1 module */
> -       zx_writel_mask(vou->vouctl + VOU_CLK_SEL, VOU_CLK_GL0_SEL, 0);
> -       zx_writel_mask(vou->vouctl + VOU_CLK_SEL, VOU_CLK_GL1_SEL,
> -                      VOU_CLK_GL1_SEL);
> -
>         /* Enable clock auto-gating for all VOU modules */
>         zx_writel(vou->vouctl + VOU_CLK_REQEN, ~0);
>
> diff --git a/drivers/gpu/drm/zte/zx_vou.h b/drivers/gpu/drm/zte/zx_vou.h
> index 349e06cd86f4..4b4339be641b 100644
> --- a/drivers/gpu/drm/zte/zx_vou.h
> +++ b/drivers/gpu/drm/zte/zx_vou.h
> @@ -43,4 +43,7 @@ struct vou_inf {
>  int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe);
>  void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe);
>
> +void zx_vou_layer_enable(struct drm_plane *plane);
> +void zx_vou_layer_disable(struct drm_plane *plane);
> +
>  #endif /* __ZX_VOU_H__ */
> --
> 1.9.1
>



-- 
Sean Paul, Software Engineer, Google / Chromium OS

^ permalink raw reply

* [PATCH v3 1/3] drm: zte: make zx_plane accessible from zx_vou driver
From: Sean Paul @ 2017-01-05  7:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482979048-32037-2-git-send-email-shawnguo@kernel.org>

On Wed, Dec 28, 2016 at 9:37 PM, Shawn Guo <shawnguo@kernel.org> wrote:
> From: Shawn Guo <shawn.guo@linaro.org>
>
> Move struct zx_plane from zx_plane.c to zx_plane.h, so that it can be
> accessed from zx_vou driver, and we can save the use of struct
> zx_layer_data completely.  More importantly, those additional data used
> by VOU controller to enable/disable graphic and video layers can later
> be added and accessed much more easily from zx_vou driver.
>
> While at it, we make two changes to zx_plane_init() interface:
>
>  - Encode struct device pointer in zx_plane, so that we do not need to
>    pass it as a parameter.
>  - Change return of zx_plane_init() from struct drm_plane pointer to
>    error code, since we can get the pointer from zx_plane in zx_vou
>    driver now.
>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
>  drivers/gpu/drm/zte/zx_plane.c | 36 +++++++-----------------------------
>  drivers/gpu/drm/zte/zx_plane.h | 11 +++++++----
>  drivers/gpu/drm/zte/zx_vou.c   | 31 +++++++++++++++++++------------
>  3 files changed, 33 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
> index 546eb92a94e8..78d29b1db91c 100644
> --- a/drivers/gpu/drm/zte/zx_plane.c
> +++ b/drivers/gpu/drm/zte/zx_plane.c
> @@ -21,16 +21,6 @@
>  #include "zx_plane_regs.h"
>  #include "zx_vou.h"
>
> -struct zx_plane {
> -       struct drm_plane plane;
> -       void __iomem *layer;
> -       void __iomem *csc;
> -       void __iomem *hbsc;
> -       void __iomem *rsz;
> -};
> -
> -#define to_zx_plane(plane)     container_of(plane, struct zx_plane, plane)
> -
>  static const uint32_t gl_formats[] = {
>         DRM_FORMAT_ARGB8888,
>         DRM_FORMAT_XRGB8888,
> @@ -248,28 +238,16 @@ static void zx_plane_hbsc_init(struct zx_plane *zplane)
>         zx_writel(hbsc + HBSC_THRESHOLD_COL3, (0x3c0 << 16) | 0x40);
>  }
>
> -struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
> -                               struct zx_layer_data *data,
> -                               enum drm_plane_type type)
> +int zx_plane_init(struct drm_device *drm, struct zx_plane *zplane,
> +                 enum drm_plane_type type)
>  {
>         const struct drm_plane_helper_funcs *helper;
> -       struct zx_plane *zplane;
> -       struct drm_plane *plane;
> +       struct drm_plane *plane = &zplane->plane;
> +       struct device *dev = zplane->dev;
>         const uint32_t *formats;
>         unsigned int format_count;
>         int ret;
>
> -       zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
> -       if (!zplane)
> -               return ERR_PTR(-ENOMEM);
> -
> -       plane = &zplane->plane;
> -
> -       zplane->layer = data->layer;
> -       zplane->hbsc = data->hbsc;
> -       zplane->csc = data->csc;
> -       zplane->rsz = data->rsz;
> -
>         zx_plane_hbsc_init(zplane);
>
>         switch (type) {
> @@ -282,7 +260,7 @@ struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
>                 /* TODO: add video layer (vl) support */
>                 break;
>         default:
> -               return ERR_PTR(-ENODEV);
> +               return -ENODEV;
>         }
>
>         ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
> @@ -290,10 +268,10 @@ struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
>                                        type, NULL);
>         if (ret) {
>                 DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret);
> -               return ERR_PTR(ret);
> +               return ret;
>         }
>
>         drm_plane_helper_add(plane, helper);
>
> -       return plane;
> +       return 0;
>  }
> diff --git a/drivers/gpu/drm/zte/zx_plane.h b/drivers/gpu/drm/zte/zx_plane.h
> index 2b82cd558d9d..264a92e0b532 100644
> --- a/drivers/gpu/drm/zte/zx_plane.h
> +++ b/drivers/gpu/drm/zte/zx_plane.h
> @@ -11,16 +11,19 @@
>  #ifndef __ZX_PLANE_H__
>  #define __ZX_PLANE_H__
>
> -struct zx_layer_data {
> +struct zx_plane {
> +       struct drm_plane plane;
> +       struct device *dev;
>         void __iomem *layer;
>         void __iomem *csc;
>         void __iomem *hbsc;
>         void __iomem *rsz;
>  };
>
> -struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
> -                               struct zx_layer_data *data,
> -                               enum drm_plane_type type);
> +#define to_zx_plane(plane) container_of(plane, struct zx_plane, plane)
> +
> +int zx_plane_init(struct drm_device *drm, struct zx_plane *zplane,
> +                 enum drm_plane_type type);
>  void zx_plane_set_update(struct drm_plane *plane);
>
>  #endif /* __ZX_PLANE_H__ */
> diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c
> index 73fe15c17c32..d5c801f6f97b 100644
> --- a/drivers/gpu/drm/zte/zx_vou.c
> +++ b/drivers/gpu/drm/zte/zx_vou.c
> @@ -294,7 +294,7 @@ static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
>                         enum vou_chn_type chn_type)
>  {
>         struct device *dev = vou->dev;
> -       struct zx_layer_data data;
> +       struct zx_plane *zplane;
>         struct zx_crtc *zcrtc;
>         int ret;
>
> @@ -305,19 +305,25 @@ static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
>         zcrtc->vou = vou;
>         zcrtc->chn_type = chn_type;
>
> +       zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
> +       if (!zplane)
> +               return -ENOMEM;
> +
> +       zplane->dev = dev;
> +
>         if (chn_type == VOU_CHN_MAIN) {
> -               data.layer = vou->osd + MAIN_GL_OFFSET;
> -               data.csc = vou->osd + MAIN_CSC_OFFSET;
> -               data.hbsc = vou->osd + MAIN_HBSC_OFFSET;
> -               data.rsz = vou->otfppu + MAIN_RSZ_OFFSET;
> +               zplane->layer = vou->osd + MAIN_GL_OFFSET;
> +               zplane->csc = vou->osd + MAIN_CSC_OFFSET;
> +               zplane->hbsc = vou->osd + MAIN_HBSC_OFFSET;
> +               zplane->rsz = vou->otfppu + MAIN_RSZ_OFFSET;
>                 zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
>                 zcrtc->regs = &main_crtc_regs;
>                 zcrtc->bits = &main_crtc_bits;
>         } else {
> -               data.layer = vou->osd + AUX_GL_OFFSET;
> -               data.csc = vou->osd + AUX_CSC_OFFSET;
> -               data.hbsc = vou->osd + AUX_HBSC_OFFSET;
> -               data.rsz = vou->otfppu + AUX_RSZ_OFFSET;
> +               zplane->layer = vou->osd + AUX_GL_OFFSET;
> +               zplane->csc = vou->osd + AUX_CSC_OFFSET;
> +               zplane->hbsc = vou->osd + AUX_HBSC_OFFSET;
> +               zplane->rsz = vou->otfppu + AUX_RSZ_OFFSET;
>                 zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
>                 zcrtc->regs = &aux_crtc_regs;
>                 zcrtc->bits = &aux_crtc_bits;
> @@ -331,13 +337,14 @@ static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
>                 return ret;
>         }
>
> -       zcrtc->primary = zx_plane_init(drm, dev, &data, DRM_PLANE_TYPE_PRIMARY);
> -       if (IS_ERR(zcrtc->primary)) {
> -               ret = PTR_ERR(zcrtc->primary);
> +       ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_PRIMARY);
> +       if (ret) {
>                 DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
>                 return ret;
>         }
>
> +       zcrtc->primary = &zplane->plane;
> +
>         ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
>                                         &zx_crtc_funcs, NULL);
>         if (ret) {
> --
> 1.9.1
>



-- 
Sean Paul, Software Engineer, Google / Chromium OS

^ permalink raw reply

* [PATCH v3 3/3] drm: zte: add overlay plane support
From: Sean Paul @ 2017-01-05  7:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1482979048-32037-4-git-send-email-shawnguo@kernel.org>

On Wed, Dec 28, 2016 at 9:37 PM, Shawn Guo <shawnguo@kernel.org> wrote:
> From: Shawn Guo <shawn.guo@linaro.org>
>
> It enables VOU VL (Video Layer) to support overlay plane with scaling
> function.  VL0 has some quirks on scaling support.  We choose to skip it
> and only adds VL1 and VL2 into DRM core for now.
>
> Function zx_plane_atomic_disable() gets moved around with no changes to
> save a forward declaration.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
>  drivers/gpu/drm/zte/zx_plane.c      | 311 +++++++++++++++++++++++++++++++++---
>  drivers/gpu/drm/zte/zx_plane_regs.h |  51 ++++++
>  drivers/gpu/drm/zte/zx_vou.c        |  80 +++++++++-
>  drivers/gpu/drm/zte/zx_vou_regs.h   |  18 +++
>  4 files changed, 431 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c
> index 5445eebf830f..c5ac42647735 100644
> --- a/drivers/gpu/drm/zte/zx_plane.c
> +++ b/drivers/gpu/drm/zte/zx_plane.c
> @@ -30,6 +30,275 @@
>         DRM_FORMAT_ARGB4444,
>  };
>
> +static const uint32_t vl_formats[] = {
> +       DRM_FORMAT_NV12,        /* Semi-planar YUV420 */
> +       DRM_FORMAT_YUV420,      /* Planar YUV420 */
> +       DRM_FORMAT_YUYV,        /* Packed YUV422 */
> +       DRM_FORMAT_YVYU,
> +       DRM_FORMAT_UYVY,
> +       DRM_FORMAT_VYUY,
> +       DRM_FORMAT_YUV444,      /* YUV444 8bit */
> +       /*
> +        * TODO: add formats below that HW supports:
> +        *  - YUV420 P010
> +        *  - YUV420 Hantro
> +        *  - YUV444 10bit
> +        */
> +};
> +
> +#define FRAC_16_16(mult, div)    (((mult) << 16) / (div))
> +
> +static int zx_vl_plane_atomic_check(struct drm_plane *plane,
> +                                   struct drm_plane_state *plane_state)
> +{
> +       struct drm_framebuffer *fb = plane_state->fb;
> +       struct drm_crtc *crtc = plane_state->crtc;
> +       struct drm_crtc_state *crtc_state;
> +       struct drm_rect clip;
> +       int min_scale = FRAC_16_16(1, 8);
> +       int max_scale = FRAC_16_16(8, 1);
> +
> +       if (!crtc || !fb)
> +               return 0;
> +
> +       crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
> +                                                       crtc);
> +       if (WARN_ON(!crtc_state))
> +               return -EINVAL;
> +
> +       /* nothing to check when disabling or disabled */
> +       if (!crtc_state->enable)
> +               return 0;
> +
> +       /* plane must be enabled */
> +       if (!plane_state->crtc)
> +               return -EINVAL;
> +
> +       clip.x1 = 0;
> +       clip.y1 = 0;
> +       clip.x2 = crtc_state->adjusted_mode.hdisplay;
> +       clip.y2 = crtc_state->adjusted_mode.vdisplay;
> +
> +       return drm_plane_helper_check_state(plane_state, &clip,
> +                                           min_scale, max_scale,
> +                                           true, true);
> +}
> +
> +static u32 zx_vl_get_fmt(uint32_t format)
> +{
> +       u32 val = 0;
> +
> +       switch (format) {
> +       case DRM_FORMAT_NV12:
> +               val = VL_FMT_YUV420;
> +               break;
> +       case DRM_FORMAT_YUV420:
> +               val = VL_YUV420_PLANAR | VL_FMT_YUV420;
> +               break;
> +       case DRM_FORMAT_YUYV:
> +               val = VL_YUV422_YUYV | VL_FMT_YUV422;
> +               break;
> +       case DRM_FORMAT_YVYU:
> +               val = VL_YUV422_YVYU | VL_FMT_YUV422;
> +               break;
> +       case DRM_FORMAT_UYVY:
> +               val = VL_YUV422_UYVY | VL_FMT_YUV422;
> +               break;
> +       case DRM_FORMAT_VYUY:
> +               val = VL_YUV422_VYUY | VL_FMT_YUV422;
> +               break;
> +       case DRM_FORMAT_YUV444:
> +               val = VL_FMT_YUV444_8BIT;

Minor nit: You could have eliminated val and just returned directly
from all of the cases. Seems like there are a few other functions this
is also true for.

> +               break;
> +       default:
> +               WARN_ONCE(1, "invalid pixel format %d\n", format);
> +       }
> +
> +       return val;
> +}
> +
> +static inline void zx_vl_set_update(struct zx_plane *zplane)
> +{
> +       void __iomem *layer = zplane->layer;
> +
> +       zx_writel_mask(layer + VL_CTRL0, VL_UPDATE, VL_UPDATE);
> +}
> +
> +static inline void zx_vl_rsz_set_update(struct zx_plane *zplane)
> +{
> +       zx_writel(zplane->rsz + RSZ_VL_ENABLE_CFG, 1);
> +}
> +
> +static u32 zx_vl_rsz_get_fmt(uint32_t format)
> +{
> +       u32 val = 0;
> +
> +       switch (format) {
> +       case DRM_FORMAT_NV12:
> +       case DRM_FORMAT_YUV420:
> +               val = RSZ_VL_FMT_YCBCR420;
> +               break;
> +       case DRM_FORMAT_YUYV:
> +       case DRM_FORMAT_YVYU:
> +       case DRM_FORMAT_UYVY:
> +       case DRM_FORMAT_VYUY:
> +               val = RSZ_VL_FMT_YCBCR422;
> +               break;
> +       case DRM_FORMAT_YUV444:
> +               val = RSZ_VL_FMT_YCBCR444;
> +               break;
> +       default:
> +               WARN_ONCE(1, "invalid pixel format %d\n", format);
> +       }
> +
> +       return val;
> +}
> +
> +static inline u32 rsz_step_value(u32 src, u32 dst)
> +{
> +       u32 val = 0;
> +
> +       if (src == dst)
> +               val = 0;
> +       else if (src < dst)
> +               val = RSZ_PARA_STEP((src << 16) / dst);
> +       else if (src > dst)
> +               val = RSZ_DATA_STEP(src / dst) |
> +                     RSZ_PARA_STEP(((src << 16) / dst) & 0xffff);
> +
> +       return val;
> +}
> +
> +static void zx_vl_rsz_setup(struct zx_plane *zplane, uint32_t format,
> +                           u32 src_w, u32 src_h, u32 dst_w, u32 dst_h)
> +{
> +       void __iomem *rsz = zplane->rsz;
> +       u32 src_chroma_w = src_w;
> +       u32 src_chroma_h = src_h;
> +       u32 fmt;
> +
> +       /* Set up source and destination resolution */
> +       zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
> +       zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1));
> +
> +       /* Configure data format for VL RSZ */
> +       fmt = zx_vl_rsz_get_fmt(format);
> +       zx_writel_mask(rsz + RSZ_VL_CTRL_CFG, RSZ_VL_FMT_MASK, fmt);
> +
> +       /* Calculate Chroma heigth and width */

s/heigth/height/

> +       if (fmt == RSZ_VL_FMT_YCBCR420) {
> +               src_chroma_w = src_w >> 1;
> +               src_chroma_h = src_h >> 1;
> +       } else if (fmt == RSZ_VL_FMT_YCBCR422) {
> +               src_chroma_w = src_w >> 1;
> +       }
> +
> +       /* Set up Luma and Chroma step registers */
> +       zx_writel(rsz + RSZ_VL_LUMA_HOR, rsz_step_value(src_w, dst_w));
> +       zx_writel(rsz + RSZ_VL_LUMA_VER, rsz_step_value(src_h, dst_h));
> +       zx_writel(rsz + RSZ_VL_CHROMA_HOR, rsz_step_value(src_chroma_w, dst_w));
> +       zx_writel(rsz + RSZ_VL_CHROMA_VER, rsz_step_value(src_chroma_h, dst_h));
> +
> +       zx_vl_rsz_set_update(zplane);
> +}
> +
> +static void zx_vl_plane_atomic_update(struct drm_plane *plane,
> +                                     struct drm_plane_state *old_state)
> +{
> +       struct zx_plane *zplane = to_zx_plane(plane);
> +       struct drm_plane_state *state = plane->state;
> +       struct drm_framebuffer *fb = state->fb;
> +       struct drm_rect *src = &state->src;
> +       struct drm_rect *dst = &state->dst;
> +       struct drm_gem_cma_object *cma_obj;
> +       void __iomem *layer = zplane->layer;
> +       void __iomem *hbsc = zplane->hbsc;
> +       void __iomem *paddr_reg;
> +       dma_addr_t paddr;
> +       u32 src_x, src_y, src_w, src_h;
> +       u32 dst_x, dst_y, dst_w, dst_h;
> +       uint32_t format;
> +       u32 fmt;
> +       int num_planes;
> +       int i;
> +
> +       if (!fb)
> +               return;
> +
> +       format = fb->pixel_format;
> +
> +       src_x = src->x1 >> 16;
> +       src_y = src->y1 >> 16;
> +       src_w = drm_rect_width(src) >> 16;
> +       src_h = drm_rect_height(src) >> 16;
> +
> +       dst_x = dst->x1;
> +       dst_y = dst->y1;
> +       dst_w = drm_rect_width(dst);
> +       dst_h = drm_rect_height(dst);
> +
> +       /* Set up data address registers for Y, Cb and Cr planes */
> +       num_planes = drm_format_num_planes(format);
> +       paddr_reg = layer + VL_Y;
> +       for (i = 0; i < num_planes; i++) {
> +               cma_obj = drm_fb_cma_get_gem_obj(fb, i);
> +               paddr = cma_obj->paddr + fb->offsets[i];
> +               paddr += src_y * fb->pitches[i];
> +               paddr += src_x * drm_format_plane_cpp(format, i);
> +               zx_writel(paddr_reg, paddr);
> +               paddr_reg += 4;
> +       }
> +
> +       /* Set up source height/width register */
> +       zx_writel(layer + VL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h));
> +
> +       /* Set up start position register */
> +       zx_writel(layer + VL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y));
> +
> +       /* Set up end position register */
> +       zx_writel(layer + VL_POS_END,
> +                 GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h));
> +
> +       /* Strides of Cb and Cr planes should be identical */
> +       zx_writel(layer + VL_STRIDE, LUMA_STRIDE(fb->pitches[0]) |
> +                 CHROMA_STRIDE(fb->pitches[1]));
> +
> +       /* Set up video layer data format */
> +       fmt = zx_vl_get_fmt(format);
> +       zx_writel(layer + VL_CTRL1, fmt);
> +
> +       /* Always use scaler since it exists (set for not bypass) */
> +       zx_writel_mask(layer + VL_CTRL2, VL_SCALER_BYPASS_MODE,
> +                      VL_SCALER_BYPASS_MODE);
> +
> +       zx_vl_rsz_setup(zplane, format, src_w, src_h, dst_w, dst_h);
> +
> +       /* Enable HBSC block */
> +       zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
> +
> +       zx_vou_layer_enable(plane);
> +
> +       zx_vl_set_update(zplane);
> +}
> +
> +static void zx_plane_atomic_disable(struct drm_plane *plane,
> +                                   struct drm_plane_state *old_state)
> +{
> +       struct zx_plane *zplane = to_zx_plane(plane);
> +       void __iomem *hbsc = zplane->hbsc;
> +
> +       zx_vou_layer_disable(plane);
> +
> +       /* Disable HBSC block */
> +       zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, 0);
> +}
> +
> +static const struct drm_plane_helper_funcs zx_vl_plane_helper_funcs = {
> +       .atomic_check = zx_vl_plane_atomic_check,
> +       .atomic_update = zx_vl_plane_atomic_update,
> +       .atomic_disable = zx_plane_atomic_disable,
> +};
> +
>  static int zx_gl_plane_atomic_check(struct drm_plane *plane,
>                                     struct drm_plane_state *plane_state)
>  {
> @@ -97,14 +366,6 @@ static inline void zx_gl_rsz_set_update(struct zx_plane *zplane)
>         zx_writel(zplane->rsz + RSZ_ENABLE_CFG, 1);
>  }
>
> -void zx_plane_set_update(struct drm_plane *plane)
> -{
> -       struct zx_plane *zplane = to_zx_plane(plane);
> -
> -       zx_gl_rsz_set_update(zplane);
> -       zx_gl_set_update(zplane);
> -}
> -
>  static void zx_gl_rsz_setup(struct zx_plane *zplane, u32 src_w, u32 src_h,
>                             u32 dst_w, u32 dst_h)
>  {
> @@ -202,18 +463,6 @@ static void zx_gl_plane_atomic_update(struct drm_plane *plane,
>         zx_gl_set_update(zplane);
>  }
>
> -static void zx_plane_atomic_disable(struct drm_plane *plane,
> -                                   struct drm_plane_state *old_state)
> -{
> -       struct zx_plane *zplane = to_zx_plane(plane);
> -       void __iomem *hbsc = zplane->hbsc;
> -
> -       zx_vou_layer_disable(plane);
> -
> -       /* Disable HBSC block */
> -       zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, 0);
> -}
> -
>  static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
>         .atomic_check = zx_gl_plane_atomic_check,
>         .atomic_update = zx_gl_plane_atomic_update,
> @@ -235,6 +484,24 @@ static void zx_plane_destroy(struct drm_plane *plane)
>         .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
>  };
>
> +void zx_plane_set_update(struct drm_plane *plane)
> +{
> +       struct zx_plane *zplane = to_zx_plane(plane);
> +
> +       switch (plane->type) {
> +       case DRM_PLANE_TYPE_PRIMARY:
> +               zx_gl_rsz_set_update(zplane);
> +               zx_gl_set_update(zplane);
> +               break;
> +       case DRM_PLANE_TYPE_OVERLAY:
> +               zx_vl_rsz_set_update(zplane);
> +               zx_vl_set_update(zplane);
> +               break;
> +       default:
> +               WARN_ONCE(1, "unsupported plane type %d\n", plane->type);
> +       }
> +}
> +
>  static void zx_plane_hbsc_init(struct zx_plane *zplane)
>  {
>         void __iomem *hbsc = zplane->hbsc;
> @@ -272,7 +539,9 @@ int zx_plane_init(struct drm_device *drm, struct zx_plane *zplane,
>                 format_count = ARRAY_SIZE(gl_formats);
>                 break;
>         case DRM_PLANE_TYPE_OVERLAY:
> -               /* TODO: add video layer (vl) support */
> +               helper = &zx_vl_plane_helper_funcs;
> +               formats = vl_formats;
> +               format_count = ARRAY_SIZE(vl_formats);
>                 break;
>         default:
>                 return -ENODEV;
> diff --git a/drivers/gpu/drm/zte/zx_plane_regs.h b/drivers/gpu/drm/zte/zx_plane_regs.h
> index 3dde6716a558..65f271aeabed 100644
> --- a/drivers/gpu/drm/zte/zx_plane_regs.h
> +++ b/drivers/gpu/drm/zte/zx_plane_regs.h
> @@ -46,6 +46,37 @@
>  #define GL_POS_X(x)    (((x) << GL_POS_X_SHIFT) & GL_POS_X_MASK)
>  #define GL_POS_Y(x)    (((x) << GL_POS_Y_SHIFT) & GL_POS_Y_MASK)
>
> +/* VL registers */
> +#define VL_CTRL0                       0x00
> +#define VL_UPDATE                      BIT(3)
> +#define VL_CTRL1                       0x04
> +#define VL_YUV420_PLANAR               BIT(5)
> +#define VL_YUV422_SHIFT                        3
> +#define VL_YUV422_YUYV                 (0 << VL_YUV422_SHIFT)
> +#define VL_YUV422_YVYU                 (1 << VL_YUV422_SHIFT)
> +#define VL_YUV422_UYVY                 (2 << VL_YUV422_SHIFT)
> +#define VL_YUV422_VYUY                 (3 << VL_YUV422_SHIFT)
> +#define VL_FMT_YUV420                  0
> +#define VL_FMT_YUV422                  1
> +#define VL_FMT_YUV420_P010             2
> +#define VL_FMT_YUV420_HANTRO           3
> +#define VL_FMT_YUV444_8BIT             4
> +#define VL_FMT_YUV444_10BIT            5
> +#define VL_CTRL2                       0x08
> +#define VL_SCALER_BYPASS_MODE          BIT(0)
> +#define VL_STRIDE                      0x0c
> +#define LUMA_STRIDE_SHIFT              16
> +#define LUMA_STRIDE_MASK               (0xffff << LUMA_STRIDE_SHIFT)
> +#define CHROMA_STRIDE_SHIFT            0
> +#define CHROMA_STRIDE_MASK             (0xffff << CHROMA_STRIDE_SHIFT)
> +#define VL_SRC_SIZE                    0x10
> +#define VL_Y                           0x14
> +#define VL_POS_START                   0x30
> +#define VL_POS_END                     0x34
> +
> +#define LUMA_STRIDE(x)  (((x) << LUMA_STRIDE_SHIFT) & LUMA_STRIDE_MASK)
> +#define CHROMA_STRIDE(x) (((x) << CHROMA_STRIDE_SHIFT) & CHROMA_STRIDE_MASK)
> +
>  /* CSC registers */
>  #define CSC_CTRL0                      0x30
>  #define CSC_COV_MODE_SHIFT             16
> @@ -69,6 +100,18 @@
>  #define RSZ_DEST_CFG                   0x04
>  #define RSZ_ENABLE_CFG                 0x14
>
> +#define RSZ_VL_LUMA_HOR                        0x08
> +#define RSZ_VL_LUMA_VER                        0x0c
> +#define RSZ_VL_CHROMA_HOR              0x10
> +#define RSZ_VL_CHROMA_VER              0x14
> +#define RSZ_VL_CTRL_CFG                        0x18
> +#define RSZ_VL_FMT_SHIFT               3
> +#define RSZ_VL_FMT_MASK                        (0x3 << RSZ_VL_FMT_SHIFT)
> +#define RSZ_VL_FMT_YCBCR420            (0x0 << RSZ_VL_FMT_SHIFT)
> +#define RSZ_VL_FMT_YCBCR422            (0x1 << RSZ_VL_FMT_SHIFT)
> +#define RSZ_VL_FMT_YCBCR444            (0x2 << RSZ_VL_FMT_SHIFT)
> +#define RSZ_VL_ENABLE_CFG              0x1c
> +
>  #define RSZ_VER_SHIFT                  16
>  #define RSZ_VER_MASK                   (0xffff << RSZ_VER_SHIFT)
>  #define RSZ_HOR_SHIFT                  0
> @@ -77,6 +120,14 @@
>  #define RSZ_VER(x)     (((x) << RSZ_VER_SHIFT) & RSZ_VER_MASK)
>  #define RSZ_HOR(x)     (((x) << RSZ_HOR_SHIFT) & RSZ_HOR_MASK)
>
> +#define RSZ_DATA_STEP_SHIFT            16
> +#define RSZ_DATA_STEP_MASK             (0xffff << RSZ_DATA_STEP_SHIFT)
> +#define RSZ_PARA_STEP_SHIFT            0
> +#define RSZ_PARA_STEP_MASK             (0xffff << RSZ_PARA_STEP_SHIFT)
> +
> +#define RSZ_DATA_STEP(x) (((x) << RSZ_DATA_STEP_SHIFT) & RSZ_DATA_STEP_MASK)
> +#define RSZ_PARA_STEP(x) (((x) << RSZ_PARA_STEP_SHIFT) & RSZ_PARA_STEP_MASK)
> +
>  /* HBSC registers */
>  #define HBSC_SATURATION                        0x00
>  #define HBSC_HUE                       0x04
> diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c
> index 3fb4fc04e693..e832c2ec3156 100644
> --- a/drivers/gpu/drm/zte/zx_vou.c
> +++ b/drivers/gpu/drm/zte/zx_vou.c
> @@ -84,6 +84,8 @@ struct zx_crtc_bits {
>  struct zx_crtc {
>         struct drm_crtc crtc;
>         struct drm_plane *primary;
> +       struct drm_plane *overlay_active[VL_NUM];
> +       unsigned int overlay_active_num;

I don't think this belongs here. You can instead add an active (or
enabled) bool to the zx_plane struct and keep track of it via
atomic_plane_update/disable. This allows you to call
zx_plane_set_update unconditionally in the vou irq handler and check
active/enabled in zx_plane_set_update.

This also seems potentially racey, so be careful.


>         struct zx_vou_hw *vou;
>         void __iomem *chnreg;
>         const struct zx_crtc_regs *regs;
> @@ -112,6 +114,22 @@ struct vou_layer_bits {
>         },
>  };
>
> +static const struct vou_layer_bits zx_vl_bits[VL_NUM] = {
> +       {
> +               .enable = OSD_CTRL0_VL0_EN,
> +               .chnsel = OSD_CTRL0_VL0_SEL,
> +               .clksel = VOU_CLK_VL0_SEL,
> +       }, {
> +               .enable = OSD_CTRL0_VL1_EN,
> +               .chnsel = OSD_CTRL0_VL1_SEL,
> +               .clksel = VOU_CLK_VL1_SEL,
> +       }, {
> +               .enable = OSD_CTRL0_VL2_EN,
> +               .chnsel = OSD_CTRL0_VL2_SEL,
> +               .clksel = VOU_CLK_VL2_SEL,
> +       },
> +};
> +
>  struct zx_vou_hw {
>         struct device *dev;
>         void __iomem *osd;
> @@ -439,6 +457,9 @@ void zx_vou_layer_enable(struct drm_plane *plane)
>         }
>
>         zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, bits->enable);
> +
> +       if (plane->type == DRM_PLANE_TYPE_OVERLAY)
> +               zcrtc->overlay_active[zcrtc->overlay_active_num++] = plane;
>  }
>
>  void zx_vou_layer_disable(struct drm_plane *plane)
> @@ -449,6 +470,51 @@ void zx_vou_layer_disable(struct drm_plane *plane)
>         const struct vou_layer_bits *bits = zplane->bits;
>
>         zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, 0);
> +
> +       if (plane->type == DRM_PLANE_TYPE_OVERLAY)
> +               zcrtc->overlay_active[zcrtc->overlay_active_num--] = NULL;
> +}
> +
> +static void zx_overlay_init(struct drm_device *drm, struct zx_vou_hw *vou)
> +{
> +       struct device *dev = vou->dev;
> +       struct zx_plane *zplane;
> +       int i;
> +       int ret;
> +
> +       /*
> +        * VL0 has some quirks on scaling support which need special handling.
> +        * Let's leave it out for now.
> +        */
> +       for (i = 1; i < VL_NUM; i++) {
> +               zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
> +               if (!zplane) {
> +                       DRM_DEV_ERROR(dev, "failed to allocate zplane %d\n", i);
> +                       return;
> +               }
> +
> +               zplane->layer = vou->osd + OSD_VL_OFFSET(i);
> +               zplane->hbsc = vou->osd + HBSC_VL_OFFSET(i);
> +               zplane->rsz = vou->otfppu + RSZ_VL_OFFSET(i);
> +               zplane->bits = &zx_vl_bits[i];
> +
> +               ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_OVERLAY);
> +               if (ret) {
> +                       DRM_DEV_ERROR(dev, "failed to init overlay %d\n", i);
> +                       continue;
> +               }
> +       }
> +}
> +
> +static inline void zx_osd_int_update(struct zx_crtc *zcrtc)
> +{
> +       int i;
> +
> +       vou_chn_set_update(zcrtc);
> +       zx_plane_set_update(zcrtc->primary);
> +
> +       for (i = 0; i < zcrtc->overlay_active_num; i++)
> +               zx_plane_set_update(zcrtc->overlay_active[i]);
>  }
>
>  static irqreturn_t vou_irq_handler(int irq, void *dev_id)
> @@ -470,15 +536,11 @@ static irqreturn_t vou_irq_handler(int irq, void *dev_id)
>         state = zx_readl(vou->osd + OSD_INT_STA);
>         zx_writel(vou->osd + OSD_INT_CLRSTA, state);
>
> -       if (state & OSD_INT_MAIN_UPT) {
> -               vou_chn_set_update(vou->main_crtc);
> -               zx_plane_set_update(vou->main_crtc->primary);
> -       }
> +       if (state & OSD_INT_MAIN_UPT)
> +               zx_osd_int_update(vou->main_crtc);
>
> -       if (state & OSD_INT_AUX_UPT) {
> -               vou_chn_set_update(vou->aux_crtc);
> -               zx_plane_set_update(vou->aux_crtc->primary);
> -       }
> +       if (state & OSD_INT_AUX_UPT)
> +               zx_osd_int_update(vou->aux_crtc);
>
>         if (state & OSD_INT_ERROR)
>                 DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
> @@ -648,6 +710,8 @@ static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
>                 goto disable_ppu_clk;
>         }
>
> +       zx_overlay_init(drm, vou);
> +
>         return 0;
>
>  disable_ppu_clk:
> diff --git a/drivers/gpu/drm/zte/zx_vou_regs.h b/drivers/gpu/drm/zte/zx_vou_regs.h
> index f44e7a4ae441..193c1ce01fe7 100644
> --- a/drivers/gpu/drm/zte/zx_vou_regs.h
> +++ b/drivers/gpu/drm/zte/zx_vou_regs.h
> @@ -22,6 +22,15 @@
>  #define AUX_HBSC_OFFSET                        0x860
>  #define AUX_RSZ_OFFSET                 0x800
>
> +#define OSD_VL0_OFFSET                 0x040
> +#define OSD_VL_OFFSET(i)               (OSD_VL0_OFFSET + 0x050 * (i))
> +
> +#define HBSC_VL0_OFFSET                        0x760
> +#define HBSC_VL_OFFSET(i)              (HBSC_VL0_OFFSET + 0x040 * (i))
> +
> +#define RSZ_VL1_U0                     0xa00
> +#define RSZ_VL_OFFSET(i)               (RSZ_VL1_U0 + 0x200 * (i))
> +
>  /* OSD (GPC_GLOBAL) registers */
>  #define OSD_INT_STA                    0x04
>  #define OSD_INT_CLRSTA                 0x08
> @@ -42,6 +51,12 @@
>  )
>  #define OSD_INT_ENABLE (OSD_INT_ERROR | OSD_INT_AUX_UPT | OSD_INT_MAIN_UPT)
>  #define OSD_CTRL0                      0x10
> +#define OSD_CTRL0_VL0_EN               BIT(13)
> +#define OSD_CTRL0_VL0_SEL              BIT(12)
> +#define OSD_CTRL0_VL1_EN               BIT(11)
> +#define OSD_CTRL0_VL1_SEL              BIT(10)
> +#define OSD_CTRL0_VL2_EN               BIT(9)
> +#define OSD_CTRL0_VL2_SEL              BIT(8)
>  #define OSD_CTRL0_GL0_EN               BIT(7)
>  #define OSD_CTRL0_GL0_SEL              BIT(6)
>  #define OSD_CTRL0_GL1_EN               BIT(5)
> @@ -146,6 +161,9 @@
>  #define VOU_INF_DATA_SEL               0x08
>  #define VOU_SOFT_RST                   0x14
>  #define VOU_CLK_SEL                    0x18
> +#define VOU_CLK_VL2_SEL                        BIT(8)
> +#define VOU_CLK_VL1_SEL                        BIT(7)
> +#define VOU_CLK_VL0_SEL                        BIT(6)
>  #define VOU_CLK_GL1_SEL                        BIT(5)
>  #define VOU_CLK_GL0_SEL                        BIT(4)
>  #define VOU_CLK_REQEN                  0x20
> --
> 1.9.1
>



-- 
Sean Paul, Software Engineer, Google / Chromium OS

^ permalink raw reply

* [PATCH v6 4/5] soc: zte: pm_domains: Prepare for supporting ARMv8 zx2967 family
From: Shawn Guo @ 2017-01-05  7:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483530494-14177-4-git-send-email-baoyou.xie@linaro.org>

On Wed, Jan 04, 2017 at 07:48:13PM +0800, Baoyou Xie wrote:
> The ARMv8 zx2967 family (296718, 296716 etc) uses different value
> for controlling the power domain on/off registers, Choose the
> value depending on the compatible.
> 
> Multiple domains are prepared for the family, this patch prepares
> the common functions.
> 
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
>  drivers/soc/Kconfig                 |   1 +
>  drivers/soc/Makefile                |   1 +
>  drivers/soc/zte/Kconfig             |  13 ++++
>  drivers/soc/zte/Makefile            |   4 +
>  drivers/soc/zte/zx2967_pm_domains.c | 142 ++++++++++++++++++++++++++++++++++++
>  drivers/soc/zte/zx2967_pm_domains.h |  44 +++++++++++
>  6 files changed, 205 insertions(+)
>  create mode 100644 drivers/soc/zte/Kconfig
>  create mode 100644 drivers/soc/zte/Makefile
>  create mode 100644 drivers/soc/zte/zx2967_pm_domains.c
>  create mode 100644 drivers/soc/zte/zx2967_pm_domains.h
> 
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index f31bceb..f09023f 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -11,5 +11,6 @@ source "drivers/soc/tegra/Kconfig"
>  source "drivers/soc/ti/Kconfig"
>  source "drivers/soc/ux500/Kconfig"
>  source "drivers/soc/versatile/Kconfig"
> +source "drivers/soc/zte/Kconfig"
>  
>  endmenu
> diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> index 50c23d0..05eae52 100644
> --- a/drivers/soc/Makefile
> +++ b/drivers/soc/Makefile
> @@ -16,3 +16,4 @@ obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
>  obj-$(CONFIG_SOC_TI)		+= ti/
>  obj-$(CONFIG_ARCH_U8500)	+= ux500/
>  obj-$(CONFIG_PLAT_VERSATILE)	+= versatile/
> +obj-$(CONFIG_ARCH_ZX)		+= zte/
> diff --git a/drivers/soc/zte/Kconfig b/drivers/soc/zte/Kconfig
> new file mode 100644
> index 0000000..20bde38
> --- /dev/null
> +++ b/drivers/soc/zte/Kconfig
> @@ -0,0 +1,13 @@
> +#
> +# ZTE SoC drivers
> +#
> +menuconfig SOC_ZTE
> +	bool "ZTE SoC driver support"
> +
> +if SOC_ZTE
> +
> +config ZX2967_PM_DOMAINS
> +	bool "ZX2967 PM domains"
> +	depends on PM_GENERIC_DOMAINS
> +
> +endif
> diff --git a/drivers/soc/zte/Makefile b/drivers/soc/zte/Makefile
> new file mode 100644
> index 0000000..8a37f2f
> --- /dev/null
> +++ b/drivers/soc/zte/Makefile
> @@ -0,0 +1,4 @@
> +#
> +# ZTE SOC drivers
> +#
> +obj-$(CONFIG_ZX2967_PM_DOMAINS) += zx2967_pm_domains.o
> diff --git a/drivers/soc/zte/zx2967_pm_domains.c b/drivers/soc/zte/zx2967_pm_domains.c
> new file mode 100644
> index 0000000..f190a62
> --- /dev/null
> +++ b/drivers/soc/zte/zx2967_pm_domains.c
> @@ -0,0 +1,142 @@
> +/*
> + * Copyright (C) 2017 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +
> +#include "zx2967_pm_domains.h"
> +
> +#define PCU_DM_CLKEN(zpd)	((zpd)->reg_offset[REG_CLKEN])
> +#define PCU_DM_ISOEN(zpd)	((zpd)->reg_offset[REG_ISOEN])
> +#define PCU_DM_RSTEN(zpd)	((zpd)->reg_offset[REG_RSTEN])
> +#define PCU_DM_PWREN(zpd)	((zpd)->reg_offset[REG_PWREN])
> +#define PCU_DM_ACK_SYNC(zpd)	((zpd)->reg_offset[REG_ACK_SYNC])
> +
> +static void __iomem *pcubase;
> +
> +int zx2967_power_on(struct generic_pm_domain *domain)

The function is now used only in this file, so it can be static.

> +{
> +	struct zx2967_pm_domain *zpd = (struct zx2967_pm_domain *)domain;
> +	unsigned long loop = 1000;
> +	u32 val;
> +
> +	val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd));
> +	if (zpd->polarity == PWREN)
> +		val |= BIT(zpd->bit);
> +	else
> +		val &= ~BIT(zpd->bit);
> +	writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd));
> +
> +	do {
> +		udelay(1);
> +		val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC(zpd))
> +				   & BIT(zpd->bit);
> +	} while (--loop && !val);
> +
> +	if (!loop) {
> +		pr_err("Error: %s %s fail\n", __func__, domain->name);
> +		return -EIO;
> +	}
> +
> +	val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd));
> +	val |= BIT(zpd->bit);
> +	writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd));
> +	udelay(5);
> +
> +	val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd));
> +	val &= ~BIT(zpd->bit);
> +	writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd));
> +	udelay(5);
> +
> +	val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd));
> +	val |= BIT(zpd->bit);
> +	writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd));
> +	udelay(5);
> +
> +	pr_debug("poweron %s\n", domain->name);
> +
> +	return 0;
> +}
> +
> +int zx2967_power_off(struct generic_pm_domain *domain)

Ditto

Shawn

> +{
> +	struct zx2967_pm_domain *zpd = (struct zx2967_pm_domain *)domain;
> +	unsigned long loop = 1000;
> +	u32 val;
> +
> +	val = readl_relaxed(pcubase + PCU_DM_CLKEN(zpd));
> +	val &= ~BIT(zpd->bit);
> +	writel_relaxed(val, pcubase + PCU_DM_CLKEN(zpd));
> +	udelay(5);
> +
> +	val = readl_relaxed(pcubase + PCU_DM_ISOEN(zpd));
> +	val |= BIT(zpd->bit);
> +	writel_relaxed(val, pcubase + PCU_DM_ISOEN(zpd));
> +	udelay(5);
> +
> +	val = readl_relaxed(pcubase + PCU_DM_RSTEN(zpd));
> +	val &= ~BIT(zpd->bit);
> +	writel_relaxed(val, pcubase + PCU_DM_RSTEN(zpd));
> +	udelay(5);
> +
> +	val = readl_relaxed(pcubase + PCU_DM_PWREN(zpd));
> +	if (zpd->polarity == PWREN)
> +		val &= ~BIT(zpd->bit);
> +	else
> +		val |= BIT(zpd->bit);
> +	writel_relaxed(val, pcubase + PCU_DM_PWREN(zpd));
> +
> +	do {
> +		udelay(1);
> +		val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC(zpd))
> +				   & BIT(zpd->bit);
> +	} while (--loop && val);
> +
> +	if (!loop) {
> +		pr_err("Error: %s %s fail\n", __func__, domain->name);
> +		return -EIO;
> +	}
> +
> +	pr_debug("poweroff %s\n", domain->name);
> +
> +	return 0;
> +}
> +
> +int zx2967_pd_probe(struct platform_device *pdev,
> +		    struct generic_pm_domain **zx_pm_domains,
> +		    int domain_num)
> +{
> +	struct genpd_onecell_data *genpd_data;
> +	struct resource *res;
> +	int i;
> +
> +	genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL);
> +	if (!genpd_data)
> +		return -ENOMEM;
> +
> +	genpd_data->domains = zx_pm_domains;
> +	genpd_data->num_domains = domain_num;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	pcubase = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(pcubase)) {
> +		dev_err(&pdev->dev, "ioremap fail.\n");
> +		return PTR_ERR(pcubase);
> +	}
> +
> +	for (i = 0; i < domain_num; ++i) {
> +		zx_pm_domains[i]->power_on = zx2967_power_on;
> +		zx_pm_domains[i]->power_off = zx2967_power_off;
> +
> +		pm_genpd_init(zx_pm_domains[i], NULL, false);
> +	}
> +
> +	of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data);
> +	dev_info(&pdev->dev, "powerdomain init ok\n");
> +	return 0;
> +}
> diff --git a/drivers/soc/zte/zx2967_pm_domains.h b/drivers/soc/zte/zx2967_pm_domains.h
> new file mode 100644
> index 0000000..cb46595
> --- /dev/null
> +++ b/drivers/soc/zte/zx2967_pm_domains.h
> @@ -0,0 +1,44 @@
> +/*
> + * Header for ZTE's Power Domain Driver support
> + *
> + * Copyright (C) 2017 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +
> +#ifndef __ZTE_ZX2967_PM_DOMAIN_H
> +#define __ZTE_ZX2967_PM_DOMAIN_H
> +
> +#include <linux/platform_device.h>
> +#include <linux/pm_domain.h>
> +
> +enum {
> +	REG_CLKEN,
> +	REG_ISOEN,
> +	REG_RSTEN,
> +	REG_PWREN,
> +	REG_PWRDN,
> +	REG_ACK_SYNC,
> +
> +	/* The size of the array - must be last */
> +	REG_ARRAY_SIZE,
> +};
> +
> +enum zx2967_power_polarity {
> +	PWREN,
> +	PWRDN,
> +};
> +
> +struct zx2967_pm_domain {
> +	struct generic_pm_domain dm;
> +	const u16 bit;
> +	const enum zx2967_power_polarity polarity;
> +	const u16 *reg_offset;
> +};
> +
> +int zx2967_pd_probe(struct platform_device *pdev,
> +		    struct generic_pm_domain **zx_pm_domains,
> +		    int domain_num);
> +
> +#endif /* __ZTE_ZX2967_PM_DOMAIN_H */
> -- 
> 2.7.4
> 

^ permalink raw reply

* [PATCH v6 2/5] MAINTAINERS: add zx2967 SoC drivers to ARM ZTE architecture
From: Shawn Guo @ 2017-01-05  6:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483530494-14177-2-git-send-email-baoyou.xie@linaro.org>

On Wed, Jan 04, 2017 at 07:48:11PM +0800, Baoyou Xie wrote:
> Add the ZTE SoC drivers as maintained by ARM ZTE
> architecture maintainers, as they're parts of the core IP.
> 
> By the way, this patch adds the maintainer for ARM
> ZTE architecture to Baoyou Xie.
> 
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
>  MAINTAINERS | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ad199da..2593296 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1975,12 +1975,17 @@ F:	arch/arm/mach-pxa/include/mach/z2.h
>  
>  ARM/ZTE ARCHITECTURE
>  M:	Jun Nie <jun.nie@linaro.org>
> +M:	Baoyou Xie <baoyou.xie@linaro.org>
>  L:	linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
>  S:	Maintained
>  F:	arch/arm/mach-zx/
>  F:	drivers/clk/zte/
> +F:	drivers/soc/zte/
> +F:	drivers/thermal/zx*

This line is about thermal support, and shouldn't be added in this
patch series.

Shawn

>  F:	Documentation/devicetree/bindings/arm/zte.txt
>  F:	Documentation/devicetree/bindings/clock/zx296702-clk.txt
> +F:	Documentation/devicetree/bindings/soc/zte/
> +F:	include/dt-bindings/soc/zx*.h
>  
>  ARM/ZYNQ ARCHITECTURE
>  M:	Michal Simek <michal.simek@xilinx.com>
> -- 
> 2.7.4
> 

^ permalink raw reply

* [PATCH v6 1/5] dt-bindings: zte: documents zx2967 power domain driver bindings
From: Shawn Guo @ 2017-01-05  6:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483530494-14177-1-git-send-email-baoyou.xie@linaro.org>

On Wed, Jan 04, 2017 at 07:48:10PM +0800, Baoyou Xie wrote:
> This patch documents devicetree tree bindings for the ZTE zx2967

'devicetree' is good enough, and the 'tree' after it is redundant.

> power domain driver.

DT bindings is to describe hardware block not software, so the word like
'driver' is not appropriate.  So please drop it from here and the patch
subject.

> 
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
>  Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt
> 
> diff --git a/Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt b/Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt
> new file mode 100644
> index 0000000..1476318
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/soc/zte/pd-2967xx.txt
> @@ -0,0 +1,17 @@
> +* ZTE 2967 SoC Power Domains

ZTE ZX2967 family.  And this is a bindings document for PCU, IMO.  And
do we know the full name of abbreviation 'PCU'?  Power Control Unit?

> +
> +2967 processors include support for multiple power domains which are used

ZX2967 family

> +to gate power to one or more peripherals on the processor.
> +
> +Required Properties:
> +- compatible: should be one of the following.
> +    * zte,zx296718-pcu - for zx296718 board's power domain.

Drop 'board's'.

> +- reg: physical base address of the controller and length of memory mapped
> +    region.
> +
> +Example:
> +
> +	pcu_domain: pcu at 0x00117000 {

The unit-address in node name shouldn't have 0x and leading zeros.

	pcu_domain: pcu at 117000 {

Shawn

> +		compatible = "zte,zx296718-pcu";
> +		reg = <0x00117000 0x1000>;
> +	};
> -- 
> 2.7.4
> 

^ permalink raw reply

* [PATCH v2 2/2] phy: sun4i-usb: Replace the deprecated extcon API
From: Chen-Yu Tsai @ 2017-01-05  6:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483071089-8362-3-git-send-email-cw00.choi@samsung.com>

On Fri, Dec 30, 2016 at 12:11 PM, Chanwoo Choi <cw00.choi@samsung.com> wrote:
> This patch replaces the deprecated extcon API as following:
> - extcon_set_cable_state_() -> extcon_set_state_sync()
>
> Cc: Kishon Vijay Abraham I <kishon@ti.com>
> Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
> Cc: Chen-Yu Tsai <wens@csie.org>
> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>

Acked-by: Chen-Yu Tsai <wens@csie.org>

> ---
>  drivers/phy/phy-sun4i-usb.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
> index bf28a0fdd569..eae171e18043 100644
> --- a/drivers/phy/phy-sun4i-usb.c
> +++ b/drivers/phy/phy-sun4i-usb.c
> @@ -534,7 +534,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
>         mutex_unlock(&phy0->mutex);
>
>         if (id_notify) {
> -               extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST,
> +               extcon_set_state_sync(data->extcon, EXTCON_USB_HOST,
>                                         !id_det);
>                 /* When leaving host mode force end the session here */
>                 if (force_session_end && id_det == 1) {
> @@ -547,7 +547,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
>         }
>
>         if (vbus_notify)
> -               extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det);
> +               extcon_set_state_sync(data->extcon, EXTCON_USB, vbus_det);
>
>         if (sun4i_usb_phy0_poll(data))
>                 queue_delayed_work(system_wq, &data->detect, POLL_TIME);
> --
> 1.9.1
>

^ permalink raw reply

* [PATCH v5 13/17] irqdomain: irq_domain_check_msi_remap
From: kbuild test robot @ 2017-01-05  6:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483536746-2725-14-git-send-email-eric.auger@redhat.com>

Hi Eric,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.10-rc2 next-20170105]
[cannot apply to iommu/next]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Eric-Auger/KVM-PCIe-MSI-passthrough-on-ARM-ARM64-and-IOVA-reserved-regions/20170105-132853
config: i386-randconfig-x003-201701 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   kernel/irq/irqdomain.c: In function 'irq_domain_is_msi_remap':
>> kernel/irq/irqdomain.c:289:17: error: 'struct irq_domain' has no member named 'parent'
     for (; h; h = h->parent) {
                    ^~

vim +289 kernel/irq/irqdomain.c

   283	 * @domain: domain pointer
   284	 */
   285	static bool irq_domain_is_msi_remap(struct irq_domain *domain)
   286	{
   287		struct irq_domain *h = domain;
   288	
 > 289		for (; h; h = h->parent) {
   290			if (h->flags & IRQ_DOMAIN_FLAG_MSI_REMAP)
   291				return true;
   292		}

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 25534 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170105/89886e81/attachment-0001.gz>

^ permalink raw reply

* [PATCH 07/22] dt-bindings: power: supply: add AXP20X/AXP22X AC power supply
From: Chen-Yu Tsai @ 2017-01-05  6:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170104131410.mni7opxnouzagypu@rob-hp-laptop>

Hi Quentin,

On Wed, Jan 4, 2017 at 9:14 PM, Rob Herring <robh@kernel.org> wrote:
> On Mon, Jan 02, 2017 at 05:37:07PM +0100, Quentin Schulz wrote:
>> The X-Powers AXP20X and AXP22X PMICs have an AC entry to supply power to
>> the board. They have a few registers dedicated to the status of the AC
>> power supply.
>>
>> This adds the DT binding documentation for the AC power supply for
>> AXP20X and AXP22X PMICs.
>>
>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
>> ---
>>  .../bindings/power/supply/axp20x_ac_power.txt      | 28 ++++++++++++++++++++++
>>  1 file changed, 28 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt
>>
>> diff --git a/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt b/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt
>> new file mode 100644
>> index 0000000..16d0de4
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/power/supply/axp20x_ac_power.txt
>> @@ -0,0 +1,28 @@
>> +AXP20X and AXP22X PMICs' AC power supply
>> +
>> +Required Properties:
>> + - compatible: One of:
>> +                     "x-powers,axp202-ac-power-supply"
>> +                     "x-powers,axp221-ac-power-supply"
>> +
>> +More Required Properties for AXP20X PMICs:
>> + - io-channels: phandles to ACIN voltage and current ADC channels
>> + - io-channel-names = "acin_v", "acin_i";
>> +
>> +This node is a subnode of the axp20x PMIC.
>> +
>> +The AXP20X can read the current current and voltage supplied by AC by
>> +reading ADC channels from the AXP20X ADC.
>> +
>> +The AXP22X is only able to tell if an AC power supply is present and
>> +usable.
>> +
>> +Example:
>> +
>> +&axp209 {
>> +     ac_power_supply: ac_power_supply {
>
> power-supply {
>
>> +             compatible = "x-powers,axp202-ac-power-supply";
>> +             io-channels = <&axp209_adc 0>, <&axp209_adc 1>;
>
> Is this assignment fixed? If so, then it doesn't need to be in DT.

Is there any case that we actually need to use the IIO channels
from the device tree? Seems to me its limited to the other AXP
sub-devices.

If so you could use struct iio_map to map the channels to other
devices by name. See axp288_adc for an example.

Regards
ChenYu

>> +             io-channel-names = "acin_v", "acin_i";
>> +     };
>> +};
>> --
>> 2.9.3
>>

^ permalink raw reply

* [PATCH 15/22] mfd: axp20x: add CHRG_CTRL1 to writeable regs for AXP20X/AXP22X
From: Chen-Yu Tsai @ 2017-01-05  6:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170102163723.7939-16-quentin.schulz@free-electrons.com>

On Tue, Jan 3, 2017 at 12:37 AM, Quentin Schulz
<quentin.schulz@free-electrons.com> wrote:
> The CHR_CTRL1 register is made of 7 read-write bits with one being used
> to set the target voltage for battery charging.

The description is incorrect.

All 8 bits are read-write:

  - The highest bit enables the charger module
  - Bits [6:5] set the target voltage
  - Bits [4:3] set when the charge cycle ends, based on percentage
    of charge current
  - Bits [2:0] set the charge current

Feel free to use the above in the commit message.

>
> This adds the CHRG_CTRL1 register to the list of writeable registers for
> AXP20X and AXP22X PMICs.

You might want to add up to CHRG_CTRL3 for the AXP22x and CHRG_CTRL2
for the AXP20x. These control additional aspects of the charger.

AXP20X_CHRG_BAK_CTRL controls the charger for the RTC battery. You
could add this now, or let the person doing the RTC battery driver
add it.

Regards
ChenYu

>
> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
> ---
>  drivers/mfd/axp20x.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
> index 65c57d0..19bdba3 100644
> --- a/drivers/mfd/axp20x.c
> +++ b/drivers/mfd/axp20x.c
> @@ -66,6 +66,7 @@ static const struct regmap_access_table axp152_volatile_table = {
>  static const struct regmap_range axp20x_writeable_ranges[] = {
>         regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
>         regmap_reg_range(AXP20X_VBUS_IPSOUT_MGMT, AXP20X_VBUS_IPSOUT_MGMT),
> +       regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL1),
>         regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
>         regmap_reg_range(AXP20X_RDC_H, AXP20X_OCV(AXP20X_OCV_MAX)),
>  };
> @@ -94,6 +95,7 @@ static const struct regmap_access_table axp20x_volatile_table = {
>  static const struct regmap_range axp22x_writeable_ranges[] = {
>         regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
>         regmap_reg_range(AXP20X_VBUS_IPSOUT_MGMT, AXP20X_VBUS_IPSOUT_MGMT),
> +       regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL1),
>         regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
>  };
>
> --
> 2.9.3
>

^ permalink raw reply

* [PATCH v6 03/14] ACPI: ARM64: IORT: add missing comment for iort_dev_find_its_id()
From: Hanjun Guo @ 2017-01-05  6:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170104143442.GA8604@red-moon>

On 2017/1/4 22:34, Lorenzo Pieralisi wrote:
> On Mon, Jan 02, 2017 at 09:31:34PM +0800, Hanjun Guo wrote:
>> We are missing req_id's comment for iort_dev_find_its_id(),
>> add it back.
>
> "Add missing req_id parameter to the iort_dev_find_its_id() function
> kernel-doc comment."
>
>> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
>> Tested-by: Majun <majun258@huawei.com>
>> Tested-by: Xinwei Kong <kong.kongxinwei@hisilicon.com>
>> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
>> Cc: Tomasz Nowicki <tn@semihalf.com>
>> ---
>>  drivers/acpi/arm64/iort.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
>> index 46e2d82..174e983 100644
>> --- a/drivers/acpi/arm64/iort.c
>> +++ b/drivers/acpi/arm64/iort.c
>> @@ -446,6 +446,7 @@ u32 iort_msi_map_rid(struct device *dev, u32 req_id)
>>  /**
>>   * iort_dev_find_its_id() - Find the ITS identifier for a device
>>   * @dev: The device.
>> + * @req_id: Device's Requster ID
>
> s/Requster/Requester
>
> We can send it upstream independently along with some other patches
> in this series but I will have a look at the whole series first.

Do you mean go to 4.10-rcx?

Thanks
Hanjun

^ permalink raw reply

* [PATCH 16/22] mfd: axp20x: add V_OFF to writeable regs for AXP20X and AXP22X
From: Chen-Yu Tsai @ 2017-01-05  6:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170104115731.GF24058@dell>

On Wed, Jan 4, 2017 at 7:57 PM, Lee Jones <lee.jones@linaro.org> wrote:
> On Mon, 02 Jan 2017, Quentin Schulz wrote:
>
>> The V_OFF register has its first 3 read-write bits for the minimal
>> voltage (Voff) of the battery before the system is automatically shut
>> down due to the power being too low.
>>
>> This adds V_OFF register to the writeable registers of AXP20X and AXP22X
>> PMICs.
>>
>> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
>> ---
>>  drivers/mfd/axp20x.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> For my own reference:
>   Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>

Acked-by: Chen-Yu Tsai <wens@csie.org>

>
>> diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
>> index 19bdba3..7f0f05f 100644
>> --- a/drivers/mfd/axp20x.c
>> +++ b/drivers/mfd/axp20x.c
>> @@ -65,7 +65,7 @@ static const struct regmap_access_table axp152_volatile_table = {
>>
>>  static const struct regmap_range axp20x_writeable_ranges[] = {
>>       regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
>> -     regmap_reg_range(AXP20X_VBUS_IPSOUT_MGMT, AXP20X_VBUS_IPSOUT_MGMT),
>> +     regmap_reg_range(AXP20X_VBUS_IPSOUT_MGMT, AXP20X_V_OFF),
>>       regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL1),
>>       regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
>>       regmap_reg_range(AXP20X_RDC_H, AXP20X_OCV(AXP20X_OCV_MAX)),
>> @@ -94,7 +94,7 @@ static const struct regmap_access_table axp20x_volatile_table = {
>>  /* AXP22x ranges are shared with the AXP809, as they cover the same range */
>>  static const struct regmap_range axp22x_writeable_ranges[] = {
>>       regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
>> -     regmap_reg_range(AXP20X_VBUS_IPSOUT_MGMT, AXP20X_VBUS_IPSOUT_MGMT),
>> +     regmap_reg_range(AXP20X_VBUS_IPSOUT_MGMT, AXP20X_V_OFF),
>>       regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL1),
>>       regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
>>  };
>
> --
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org ? Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH v11 8/8] ARM: dts: imx6q-evi: Fix onboard hub reset line
From: Peter Chen @ 2017-01-05  6:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483596119-27508-1-git-send-email-peter.chen@nxp.com>

From: Joshua Clayton <stillcompiling@gmail.com>

Previously the onboard hub was made to work by treating its
reset gpio as a regulator enable.
Get rid of that kludge now that pwseq has added reset gpio support
Move pin muxing the hub reset pin into the usbh1 group

Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
---
 arch/arm/boot/dts/imx6q-evi.dts | 25 +++++++------------------
 1 file changed, 7 insertions(+), 18 deletions(-)

diff --git a/arch/arm/boot/dts/imx6q-evi.dts b/arch/arm/boot/dts/imx6q-evi.dts
index 7c7c1a8..79a0bd5 100644
--- a/arch/arm/boot/dts/imx6q-evi.dts
+++ b/arch/arm/boot/dts/imx6q-evi.dts
@@ -54,18 +54,6 @@
 		reg = <0x10000000 0x40000000>;
 	};
 
-	reg_usbh1_vbus: regulator-usbhubreset {
-		compatible = "regulator-fixed";
-		regulator-name = "usbh1_vbus";
-		regulator-min-microvolt = <5000000>;
-		regulator-max-microvolt = <5000000>;
-		enable-active-high;
-		startup-delay-us = <2>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_usbh1_hubreset>;
-		gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
-	};
-
 	reg_usb_otg_vbus: regulator-usbotgvbus {
 		compatible = "regulator-fixed";
 		regulator-name = "usb_otg_vbus";
@@ -207,12 +195,18 @@
 };
 
 &usbh1 {
-	vbus-supply = <&reg_usbh1_vbus>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usbh1>;
 	dr_mode = "host";
 	disable-over-current;
 	status = "okay";
+
+	usb2415host: hub at 1 {
+		compatible = "usb424,2513";
+		reg = <1>;
+		reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>;
+		reset-duration-us = <3000>;
+	};
 };
 
 &usbotg {
@@ -468,11 +462,6 @@
 			MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0
 			/* usbh1_b OC */
 			MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0
-		>;
-	};
-
-	pinctrl_usbh1_hubreset: usbh1hubresetgrp {
-		fsl,pins = <
 			MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0
 		>;
 	};
-- 
2.7.4

^ permalink raw reply related


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