* RE: [PATCH v4 4/5] scsi: ufs-exynos: add UFS host support for Exynos SoCs
From: Alim Akhtar @ 2020-04-02 15:08 UTC (permalink / raw)
To: 'Avri Altman', robh+dt, devicetree, linux-scsi
Cc: krzk, martin.petersen, kwmad.kim, stanley.chu, cang,
linux-samsung-soc, linux-arm-kernel, linux-kernel
In-Reply-To: <SN6PR04MB4640B92BC9EA5CFEB74BE5EAFCCD0@SN6PR04MB4640.namprd04.prod.outlook.com>
Hi Avri
> -----Original Message-----
> From: Avri Altman <Avri.Altman@wdc.com>
> Sent: 28 March 2020 16:58
> To: Alim Akhtar <alim.akhtar@samsung.com>; robh+dt@kernel.org;
> devicetree@vger.kernel.org; linux-scsi@vger.kernel.org
> Cc: krzk@kernel.org; martin.petersen@oracle.com; kwmad.kim@samsung.com;
> stanley.chu@mediatek.com; cang@codeaurora.org; linux-samsung-
> soc@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org
> Subject: RE: [PATCH v4 4/5] scsi: ufs-exynos: add UFS host support for Exynos
> SoCs
>
> Hi,
>
> > +
> > +long exynos_ufs_calc_time_cntr(struct exynos_ufs *ufs, long period) {
> > + const int precise = 10;
> > + long pclk_rate = ufs->pclk_rate;
> > + long clk_period, fraction;
> > +
> > + clk_period = UNIPRO_PCLK_PERIOD(ufs);
> > + fraction = ((NSEC_PER_SEC % pclk_rate) * precise) / pclk_rate;
> > +
> > + return (period * precise) / ((clk_period * precise) +
> > +fraction); }
> This helper essentially calculates a factor f, and returns period x f.
> Why not do that regardless of period?
>
The period can be different for different timing attributes, so this helper function takes the period and returns the timer counter value based on the pclk_rate.
> > +extern long exynos_ufs_calc_time_cntr(struct exynos_ufs *, long);
> Why this factor needed to be exported?
Yes, not needed, will correct this in next version, which I am planning to post soon.
Thanks for your time and review, let me know if you have more inputs.
^ permalink raw reply
* Re: [PATCH v4 9/9] arm64: dts: renesas: salvator: add a connection from adv748x codec (HDMI input) to the R-Car SoC
From: Alex Riesen @ 2020-04-02 14:16 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Kieran Bingham, Mauro Carvalho Chehab, Hans Verkuil,
Laurent Pinchart, Rob Herring, Mark Rutland, Kuninori Morimoto,
driverdevel, Linux Media Mailing List, Linux Kernel Mailing List,
OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS, Linux-Renesas
In-Reply-To: <CAMuHMdV+joeNWJotKySVPHNW9OoT8+iODBwhK5fACspq2SX_eg@mail.gmail.com>
Hi Geert,
I'm sorry for late reply. Some unrelated happenings here in south Germany.
Geert Uytterhoeven, Mon, Mar 30, 2020 10:32:47 +0200:
> On Thu, Mar 26, 2020 at 11:55 AM Alex Riesen <alexander.riesen@cetitec.com> wrote:
> > --- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi
> > +++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
> > @@ -510,6 +511,15 @@ adv7482_txb: endpoint {
> > remote-endpoint = <&csi20_in>;
> > };
> > };
> > +
> > + port@c {
> > + reg = <12>;
> > +
> > + adv7482_i2s: endpoint {
> > + remote-endpoint = <&rsnd_endpoint3>;
> > + system-clock-direction-out;
> > + };
> > + };
>
> As the adv748x driver just ignores "invalid" endpoints...
>
> > @@ -758,8 +769,19 @@ &rcar_sound {
> > <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
> > <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
> > <&audio_clk_a>, <&cs2000>,
> > - <&audio_clk_c>,
> > + <&adv7482_hdmi_in>,
> > <&cpg CPG_CORE CPG_AUDIO_CLK_I>;
>
> ... and the rsnd driver ignores nonexistent-clocks, the DT change has no
> hard dependency on the driver change, and won't introduce regressions
> when included, right?
Well, it maybe won't, but isn't it a little ... implicit?
And I'm no haste to include the changes, if you mean I can (or should) submit
the device tree patch separately.
> > @@ -777,6 +799,21 @@ rsnd_endpoint0: endpoint {
> > capture = <&ssi1 &src1 &dvc1>;
> > };
> > };
> > + rsnd_port3: port@3 {
> > + reg = <3>;
> > + rsnd_endpoint3: endpoint {
> > + remote-endpoint = <&adv7482_i2s>;
> > +
> > + dai-tdm-slot-num = <8>;
> > + dai-tdm-slot-width = <32>;
> > + dai-format = "left_j";
> > + mclk-fs = <256>;
> > + bitclock-master = <&adv7482_i2s>;
> > + frame-master = <&adv7482_i2s>;
> > +
> > + capture = <&ssi4>;
> > + };
> > + };
> > };
> > };
>
> However, as salvator-common.dtsi is shared by all Salvator-X(S) variants,
> you'll have to add a dummy ssi4 node to r8a77961.dtsi first.
I see. There are even two dummy SSI nodes already. I would prefer to submit
the change together with other Salvator device tree changes. Is that alright?
Regards,
Alex
^ permalink raw reply
* Re: [PATCH v1 5/6] dt-bindings: ARM: tegra: Add ASUS Google Nexus 7
From: Dmitry Osipenko @ 2020-04-02 14:52 UTC (permalink / raw)
To: Michał Mirosław
Cc: Rob Herring, Thierry Reding, Jonathan Hunter, David Heidelberg,
Peter Geis, Stephen Warren, Nicolas Chauvet, Pedro Ângelo,
Matt Merhar, linux-tegra, devicetree, linux-kernel
In-Reply-To: <20200402045008.GB11124@qmqm.qmqm.pl>
02.04.2020 07:50, Michał Mirosław пишет:
> On Wed, Apr 01, 2020 at 12:43:26AM +0300, Dmitry Osipenko wrote:
>> Add a binding for the Tegra30-based ASUS Google Nexus 7 tablet device.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>> Documentation/devicetree/bindings/arm/tegra.yaml | 7 +++++++
>> 1 file changed, 7 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/tegra.yaml b/Documentation/devicetree/bindings/arm/tegra.yaml
>> index 7fd0b66c69b2..fb3bbf7a5fb4 100644
>> --- a/Documentation/devicetree/bindings/arm/tegra.yaml
>> +++ b/Documentation/devicetree/bindings/arm/tegra.yaml
>> @@ -62,6 +62,13 @@ properties:
>> - toradex,colibri_t30-eval-v3
>> - const: toradex,colibri_t30
>> - const: nvidia,tegra30
>> + - items:
>> + - const: asus,grouper
>> + - const: nvidia,tegra30
>> + - items:
>> + - const: asus,tilapia
>> + - const: asus,grouper
>> + - const: nvidia,tegra30
>> - items:
>> - enum:
>> - nvidia,dalmore
>
> Is it really necessary to list every possible device using a SoC chip?
Yes, otherwise make dtbs_check will give you a warning about the unknown
compatible.
> Wouldn't it be enough to just list SoC value nvidia,tegraXYZ and allow
> any other supplemental "compatibles"?
I don't know what was the initial intention of having boards defined in
a way it's currently done, maybe Rob;Thierry;Stephen;Jon could clarify?
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: rockchip: add rx0 mipi-phy for rk3399
From: Heiko Stübner @ 2020-04-02 14:49 UTC (permalink / raw)
To: Johan Jonker
Cc: helen.koike, dafna.hirschfeld, devel, devicetree, ezequiel,
hverkuil-cisco, karthik.poduval, kernel, linux-kernel,
linux-media, linux-rockchip, mark.rutland, robh+dt
In-Reply-To: <76211530-73ff-5f36-8915-8bdc036d4369@gmail.com>
Am Donnerstag, 2. April 2020, 16:37:52 CEST schrieb Johan Jonker:
> On 4/2/20 4:31 PM, Heiko Stübner wrote:
> > Am Donnerstag, 2. April 2020, 15:48:02 CEST schrieb Johan Jonker:
> >> Hi Helen,
> >>
> >>> From: Helen Koike <helen.koike@collabora.com>
> >>
> >>> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> >>> index 33cc21fcf4c10..fc0295d2a65a1 100644
> >>> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> >>> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> >>> @@ -1394,6 +1394,17 @@ io_domains: io-domains {
> >>> status = "disabled";
> >>> };
> >>>
> >>
> >>> + mipi_dphy_rx0: mipi-dphy-rx0 {
> >>
> >> For Heiko sort syscon@ff770000 subnodes alphabetical or reg value first?
> >
> > Similar to main nodes ... so things without reg alphabetical,
> > the rest by reg address
> >
> alphabetical first:
>
> io-domains
> mipi-dphy-rx0
> usb2-phy@e450
like this ... aka similar to what we do in the core nodes.
For the record, pinctrl at the bottom of a soc.dtsi is ok.
Heiko
> .@..
>
> or
>
> with reg values first:
>
> .@..
> emmc_phy: phy@f780
> mipi-dphy-rx0
> pcie-phy
>
> >
> >>
> >>> + compatible = "rockchip,rk3399-mipi-dphy-rx0";
> >>> + clocks = <&cru SCLK_MIPIDPHY_REF>,
> >>
> >>> + <&cru SCLK_DPHY_RX0_CFG>,
> >>> + <&cru PCLK_VIO_GRF>;
> >>
> >> Align ^
> >>
> >>> + clock-names = "dphy-ref", "dphy-cfg", "grf";
> >>> + power-domains = <&power RK3399_PD_VIO>;
> >>> + #phy-cells = <0>;
> >>> + status = "disabled";
> >>> + };
> >>> +
> >>> u2phy0: usb2-phy@e450 {
> >>> compatible = "rockchip,rk3399-usb2phy";
> >>> reg = <0xe450 0x10>;
> >>
> >>
> >
> >
> >
> >
>
>
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: rockchip: add rx0 mipi-phy for rk3399
From: Helen Koike @ 2020-04-02 14:43 UTC (permalink / raw)
To: Heiko Stübner, Johan Jonker
Cc: helen.koike, dafna.hirschfeld, devel, devicetree, ezequiel,
hverkuil-cisco, karthik.poduval, kernel, linux-kernel,
linux-media, linux-rockchip, mark.rutland, robh+dt
In-Reply-To: <105956984.FXDh2DO4ZE@diego>
Hi,
On 4/2/20 11:31 AM, Heiko Stübner wrote:
> Am Donnerstag, 2. April 2020, 15:48:02 CEST schrieb Johan Jonker:
>> Hi Helen,
>>
>>> From: Helen Koike <helen.koike@collabora.com>
>>
>>> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>>> index 33cc21fcf4c10..fc0295d2a65a1 100644
>>> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>>> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>>> @@ -1394,6 +1394,17 @@ io_domains: io-domains {
>>> status = "disabled";
>>> };
>>>
>>
>>> + mipi_dphy_rx0: mipi-dphy-rx0 {
>>
>> For Heiko sort syscon@ff770000 subnodes alphabetical or reg value first?
>
> Similar to main nodes ... so things without reg alphabetical,
> the rest by reg address
>
>
>>
>>> + compatible = "rockchip,rk3399-mipi-dphy-rx0";
>>> + clocks = <&cru SCLK_MIPIDPHY_REF>,
>>
>>> + <&cru SCLK_DPHY_RX0_CFG>,
>>> + <&cru PCLK_VIO_GRF>;
>>
>> Align ^
ack.
Thanks
Helen
>>
>>> + clock-names = "dphy-ref", "dphy-cfg", "grf";
>>> + power-domains = <&power RK3399_PD_VIO>;
>>> + #phy-cells = <0>;
>>> + status = "disabled";
>>> + };
>>> +
>>> u2phy0: usb2-phy@e450 {
>>> compatible = "rockchip,rk3399-usb2phy";
>>> reg = <0xe450 0x10>;
>>
>>
>
>
>
>
^ permalink raw reply
* Re: [PATCH 1/4] dt-bindings: phy: phy-rockchip-dphy-rx0: move rockchip dphy rx0 bindings out of staging
From: Helen Koike @ 2020-04-02 14:42 UTC (permalink / raw)
To: Johan Jonker
Cc: dafna.hirschfeld, devel, devicetree, ezequiel, heiko,
hverkuil-cisco, karthik.poduval, kernel, linux-kernel,
linux-media, linux-rockchip, mark.rutland, robh+dt
In-Reply-To: <bfefe00c-5673-ddcb-4e2a-425eb4771002@gmail.com>
Hi Johan,
On 4/2/20 9:16 AM, Johan Jonker wrote:
> Hi Helen,
>
>> # SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> %YAML 1.2
>> ---
>> $id: http://devicetree.org/schemas/phy/rockchip-mipi-dphy-rx0.yaml#
>> $schema: http://devicetree.org/meta-schemas/core.yaml#
>>
>> title: Rockchip SoC MIPI RX0 D-PHY Device Tree Bindings
>>
>> maintainers:
>> - Helen Koike <helen.koike@collabora.com>
>> - Ezequiel Garcia <ezequiel@collabora.com>
>>
>> description: |
>> The Rockchip SoC has a MIPI D-PHY bus with an RX0 entry which connects to
>> the ISP1 (Image Signal Processing unit v1.0) for CSI cameras.
>>
>> properties:
>> compatible:
>> const: rockchip,rk3399-mipi-dphy-rx0
>>
>
>> reg:
>> maxItems: 1
>
> If 'reg' is not used => remove it.
ok, I'll add a patch removing it.
Thanks,
Helen
>
>>
>> clocks:
>> items:
>> - description: MIPI D-PHY ref clock
>> - description: MIPI D-PHY RX0 cfg clock
>> - description: Video in/out general register file clock
>>
>> clock-names:
>> items:
>> - const: dphy-ref
>> - const: dphy-cfg
>> - const: grf
>>
>> '#phy-cells':
>> const: 0
>>
>> power-domains:
>> description: Video in/out power domain.
>> maxItems: 1
>>
>> required:
>> - compatible
>> - clocks
>> - clock-names
>> - '#phy-cells'
>> - power-domains
>>
>> additionalProperties: false
>>
>> examples:
>> - |
>>
>> /*
>> * MIPI D-PHY RX0 use registers in "general register files", it
>> * should be a child of the GRF.
>> *
>> * grf: syscon@ff770000 {
>> * compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
>> * ...
>> * };
>> */
>>
>> #include <dt-bindings/clock/rk3399-cru.h>
>> #include <dt-bindings/power/rk3399-power.h>
>>
>> mipi_dphy_rx0: mipi-dphy-rx0 {
>> compatible = "rockchip,rk3399-mipi-dphy-rx0";
>> clocks = <&cru SCLK_MIPIDPHY_REF>,
>> <&cru SCLK_DPHY_RX0_CFG>,
>> <&cru PCLK_VIO_GRF>;
>> clock-names = "dphy-ref", "dphy-cfg", "grf";
>> power-domains = <&power RK3399_PD_VIO>;
>> #phy-cells = <0>;
>> };
^ permalink raw reply
* Re: [PATCH 2/4] dt-bindings: media: rkisp1: move rockchip-isp1 bindings out of staging
From: Helen Koike @ 2020-04-02 14:42 UTC (permalink / raw)
To: Johan Jonker
Cc: dafna.hirschfeld, devel, devicetree, ezequiel, heiko,
hverkuil-cisco, karthik.poduval, kernel, linux-kernel,
linux-media, linux-rockchip, mark.rutland, robh+dt
In-Reply-To: <7e53ec1e-33bd-3385-40a0-de3fd00ad1a1@gmail.com>
Hi Johan,
Thanks for your review.
On 4/2/20 8:35 AM, Johan Jonker wrote:
> Hi Helen,
>
>> # SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> %YAML 1.2
>> ---
>> $id: http://devicetree.org/schemas/media/rockchip-isp1.yaml#
>> $schema: http://devicetree.org/meta-schemas/core.yaml#
>>
>
>> title: Rockchip SoC Image Signal Processing unit v1
>
> Where do we need 'v1' for? Is there a 'v2'?
ISPv1 is the Rockchip's name for the IP block.
>
>>
>> maintainers:
>> - Helen Koike <helen.koike@collabora.com>
>>
>> description: |
>> Rockchip ISP1 is the Camera interface for the Rockchip series of SoCs
>> which contains image processing, scaling, and compression functions.
>>
>> properties:
>> compatible:
>> const: rockchip,rk3399-cif-isp
>>
>> reg:
>> maxItems: 1
>>
>> interrupts:
>> maxItems: 1
>>
>> iommus:
>> maxItems: 1
>>
>> power-domains:
>> maxItems: 1
>>
>> phys:
>> maxItems: 1
>> description: phandle for the PHY port
>>
>> phy-names:
>> const: dphy
>>
>> clocks:
>> items:
>> - description: ISP clock
>> - description: ISP AXI clock clock
>> - description: ISP AXI clock wrapper clock
>> - description: ISP AHB clock clock
>> - description: ISP AHB wrapper clock
>>
>> clock-names:
>> items:
>> - const: clk_isp
>> - const: aclk_isp
>> - const: aclk_isp_wrap
>> - const: hclk_isp
>> - const: hclk_isp_wrap
>>
>> # See ./video-interfaces.txt for details
>> ports:
>> type: object
>> additionalProperties: false
>>
>> properties:
>> "#address-cells":
>> const: 1
>>
>> "#size-cells":
>> const: 0
>>
>> port@0:
>> type: object
>> description: connection point for sensors at MIPI-DPHY RX0
>
>> additionalProperties: false
>
> Nothing required here?
I was thinking that if there is no endpoint, then nothing is required.
But if there is, then #address-cells, #size-cells and reg are. I guess
I can just add them as required.
I'll add it in the patchseries.
>
>>
>> properties:
>> "#address-cells":
>> const: 1
>>
>> "#size-cells":
>> const: 0
>>
>> reg:
>> const: 0
>>
>> patternProperties:
>> endpoint:
>> type: object
>> additionalProperties: false
>>
>> properties:
>> reg:
>> maxItems: 1
>>
>> data-lanes:
>> minItems: 1
>> maxItems: 4
>>
>> remote-endpoint: true
>>
>> required:
>
>> - port@0
>
> The use of '@0' makes "#address-cells" and "#size-cells" also a requirement.
>
> - "#address-cells"
> - "#size-cells"
Ok, I'll add it.
>
>>
>> required:
>> - compatible
>
> How about 'reg'?
>
> - reg
ack, I'll add another patch in the series fixing this.
>
>> - interrupts
>> - clocks
>> - clock-names
>> - power-domains
>> - iommus
>> - phys
>> - phy-names
>> - ports
>>
>> additionalProperties: false
>>
>> examples:
>> - |
>>
>> #include <dt-bindings/clock/rk3399-cru.h>
>> #include <dt-bindings/interrupt-controller/arm-gic.h>
>> #include <dt-bindings/power/rk3399-power.h>
>>
>> parent0: parent@0 {
>> #address-cells = <2>;
>> #size-cells = <2>;
>>
>> isp0: isp0@ff910000 {
>> compatible = "rockchip,rk3399-cif-isp";
>> reg = <0x0 0xff910000 0x0 0x4000>;
>> interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH 0>;
>> clocks = <&cru SCLK_ISP0>,
>> <&cru ACLK_ISP0>, <&cru ACLK_ISP0_WRAPPER>,
>> <&cru HCLK_ISP0>, <&cru HCLK_ISP0_WRAPPER>;
>> clock-names = "clk_isp",
>> "aclk_isp", "aclk_isp_wrap",
>> "hclk_isp", "hclk_isp_wrap";
>> power-domains = <&power RK3399_PD_ISP0>;
>> iommus = <&isp0_mmu>;
>> phys = <&dphy>;
>> phy-names = "dphy";
>>
>> ports {
>> #address-cells = <1>;
>> #size-cells = <0>;
>>
>> port@0 {
>> #address-cells = <1>;
>> #size-cells = <0>;
>> reg = <0>;
>>
>> mipi_in_wcam: endpoint@0 {
>> reg = <0>;
>> remote-endpoint = <&wcam_out>;
>> data-lanes = <1 2>;
>> };
>>
>> mipi_in_ucam: endpoint@1 {
>> reg = <1>;
>> remote-endpoint = <&ucam_out>;
>> data-lanes = <1>;
>> };
>> };
>> };
>> };
>>
>
>> i2c7: i2c@ff160000 {
>> clock-frequency = <400000>;
>> #address-cells = <1>;
>> #size-cells = <0>;
>
> Incomplete example.
> From i2c-rk3x.yaml:
>
> required:
> - compatible
> - reg
> - interrupts
> - clocks
> - clock-names
The idea was to exemplify how to connect to the sensor nodes below.
But I don't see a problem adding a complete i2c example, I'll add it.
Thanks
Helen
>
>>
>> wcam: camera@36 {
>> compatible = "ovti,ov5695";
>> reg = <0x36>;
>>
>> port {
>> wcam_out: endpoint {
>> remote-endpoint = <&mipi_in_wcam>;
>> data-lanes = <1 2>;
>> };
>> };
>> };
>>
>> ucam: camera@3c {
>> compatible = "ovti,ov2685";
>> reg = <0x3c>;
>>
>> port {
>> ucam_out: endpoint {
>> remote-endpoint = <&mipi_in_ucam>;
>> data-lanes = <1>;
>> };
>> };
>> };
>> };
>> };
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: rockchip: add rx0 mipi-phy for rk3399
From: Johan Jonker @ 2020-04-02 14:37 UTC (permalink / raw)
To: Heiko Stübner
Cc: helen.koike, dafna.hirschfeld, devel, devicetree, ezequiel,
hverkuil-cisco, karthik.poduval, kernel, linux-kernel,
linux-media, linux-rockchip, mark.rutland, robh+dt
In-Reply-To: <105956984.FXDh2DO4ZE@diego>
On 4/2/20 4:31 PM, Heiko Stübner wrote:
> Am Donnerstag, 2. April 2020, 15:48:02 CEST schrieb Johan Jonker:
>> Hi Helen,
>>
>>> From: Helen Koike <helen.koike@collabora.com>
>>
>>> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>>> index 33cc21fcf4c10..fc0295d2a65a1 100644
>>> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>>> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
>>> @@ -1394,6 +1394,17 @@ io_domains: io-domains {
>>> status = "disabled";
>>> };
>>>
>>
>>> + mipi_dphy_rx0: mipi-dphy-rx0 {
>>
>> For Heiko sort syscon@ff770000 subnodes alphabetical or reg value first?
>
> Similar to main nodes ... so things without reg alphabetical,
> the rest by reg address
>
alphabetical first:
io-domains
mipi-dphy-rx0
usb2-phy@e450
.@..
or
with reg values first:
.@..
emmc_phy: phy@f780
mipi-dphy-rx0
pcie-phy
>
>>
>>> + compatible = "rockchip,rk3399-mipi-dphy-rx0";
>>> + clocks = <&cru SCLK_MIPIDPHY_REF>,
>>
>>> + <&cru SCLK_DPHY_RX0_CFG>,
>>> + <&cru PCLK_VIO_GRF>;
>>
>> Align ^
>>
>>> + clock-names = "dphy-ref", "dphy-cfg", "grf";
>>> + power-domains = <&power RK3399_PD_VIO>;
>>> + #phy-cells = <0>;
>>> + status = "disabled";
>>> + };
>>> +
>>> u2phy0: usb2-phy@e450 {
>>> compatible = "rockchip,rk3399-usb2phy";
>>> reg = <0xe450 0x10>;
>>
>>
>
>
>
>
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: rockchip: add rx0 mipi-phy for rk3399
From: Heiko Stübner @ 2020-04-02 14:31 UTC (permalink / raw)
To: Johan Jonker
Cc: helen.koike, dafna.hirschfeld, devel, devicetree, ezequiel,
hverkuil-cisco, karthik.poduval, kernel, linux-kernel,
linux-media, linux-rockchip, mark.rutland, robh+dt
In-Reply-To: <970b9e48-e38f-7e7a-3472-7dc5a4737e58@gmail.com>
Am Donnerstag, 2. April 2020, 15:48:02 CEST schrieb Johan Jonker:
> Hi Helen,
>
> > From: Helen Koike <helen.koike@collabora.com>
>
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> > index 33cc21fcf4c10..fc0295d2a65a1 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> > @@ -1394,6 +1394,17 @@ io_domains: io-domains {
> > status = "disabled";
> > };
> >
>
> > + mipi_dphy_rx0: mipi-dphy-rx0 {
>
> For Heiko sort syscon@ff770000 subnodes alphabetical or reg value first?
Similar to main nodes ... so things without reg alphabetical,
the rest by reg address
>
> > + compatible = "rockchip,rk3399-mipi-dphy-rx0";
> > + clocks = <&cru SCLK_MIPIDPHY_REF>,
>
> > + <&cru SCLK_DPHY_RX0_CFG>,
> > + <&cru PCLK_VIO_GRF>;
>
> Align ^
>
> > + clock-names = "dphy-ref", "dphy-cfg", "grf";
> > + power-domains = <&power RK3399_PD_VIO>;
> > + #phy-cells = <0>;
> > + status = "disabled";
> > + };
> > +
> > u2phy0: usb2-phy@e450 {
> > compatible = "rockchip,rk3399-usb2phy";
> > reg = <0xe450 0x10>;
>
>
^ permalink raw reply
* [PATCH v8] ARM: dts: aspeed: Adding Facebook Yosemite V2 BMC
From: Manikandan Elumalai @ 2020-04-02 14:11 UTC (permalink / raw)
To: andrew, joel
Cc: sdasari, vijaykhemka, linux-kernel, devicetree, linux-aspeed,
openbmc, manikandan.e
The Yosemite V2 is a facebook multi-node server
platform that host four OCP server. The BMC
in the Yosemite V2 platform based on AST2500 SoC.
This patch adds linux device tree entry related to
Yosemite V2 specific devices connected to BMC SoC.
Signed-off-by: Manikandan Elumalai <manikandan.hcl.ers.epl@gmail.com>
Acked-by : Andrew Jeffery <andrew@aj.id.au>
Reviewed-by : Vijay Khemka <vkhemka@fb.com>
---
--- v8 - Added dtb entry in Makefile as review comment.
--- -Added IPMB bridge device details as review comment.
--- v7 - Added multi-host SOL feature.
--- v6 - Added device tree property for multi-host Mellanox NIC in the ncsi driver.
--- v5 - Spell and contributor name correction.
--- - License identifier changed to GPL-2.0-or-later.
--- - aspeed-gpio.h removed.
--- - FAN2 tacho channel changed.
--- v4 - Bootargs removed.
--- v3 - Uart1 Debug removed .
--- v2 - LPC and VUART removed .
--- v1 - Initial draft.
---
---
arch/arm/boot/dts/Makefile | 1 +
.../boot/dts/aspeed-bmc-facebook-yosemitev2.dts | 231 +++++++++++++++++++++
2 files changed, 232 insertions(+)
create mode 100644 arch/arm/boot/dts/aspeed-bmc-facebook-yosemitev2.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index fcd607f..00b6649 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -1289,6 +1289,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-bmc-facebook-wedge40.dtb \
aspeed-bmc-facebook-wedge100.dtb \
aspeed-bmc-facebook-yamp.dtb \
+ aspeed-bmc-facebook-yosemitev2.dtb \
aspeed-bmc-ibm-rainier.dtb \
aspeed-bmc-intel-s2600wf.dtb \
aspeed-bmc-inspur-fp5280g2.dtb \
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-yosemitev2.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-yosemitev2.dts
new file mode 100644
index 0000000..8864e9c
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-yosemitev2.dts
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright (c) 2018 Facebook Inc.
+/dts-v1/;
+#include "aspeed-g5.dtsi"
+#include <dt-bindings/i2c/i2c.h>
+
+/ {
+ model = "Facebook Yosemitev2 BMC";
+ compatible = "facebook,yosemitev2-bmc", "aspeed,ast2500";
+ aliases {
+ serial4 = &uart5;
+ };
+ chosen {
+ stdout-path = &uart5;
+ };
+
+ memory@80000000 {
+ reg = <0x80000000 0x20000000>;
+ };
+
+ iio-hwmon {
+ // VOLATAGE SENSOR
+ compatible = "iio-hwmon";
+ io-channels = <&adc 0> , <&adc 1> , <&adc 2> , <&adc 3> ,
+ <&adc 4> , <&adc 5> , <&adc 6> , <&adc 7> ,
+ <&adc 8> , <&adc 9> , <&adc 10>, <&adc 11> ,
+ <&adc 12> , <&adc 13> , <&adc 14> , <&adc 15> ;
+ };
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+#include "openbmc-flash-layout.dtsi"
+ };
+};
+
+&spi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1_default>;
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "pnor";
+ };
+};
+&uart1 {
+ // Host1 Console
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd1_default
+ &pinctrl_rxd1_default>;
+};
+
+&uart2 {
+ // Host2 Console
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd2_default
+ &pinctrl_rxd2_default>;
+
+};
+
+&uart3 {
+ // Host3 Console
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd3_default
+ &pinctrl_rxd3_default>;
+};
+
+&uart4 {
+ // Host4 Console
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd4_default
+ &pinctrl_rxd4_default>;
+};
+
+&uart5 {
+ // BMC Console
+ status = "okay";
+};
+
+&vuart {
+ // Virtual UART
+ status = "okay";
+};
+
+&mac0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii1_default>;
+ use-ncsi;
+ mlx,multi-host;
+};
+
+&adc {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc0_default
+ &pinctrl_adc1_default
+ &pinctrl_adc2_default
+ &pinctrl_adc3_default
+ &pinctrl_adc4_default
+ &pinctrl_adc5_default
+ &pinctrl_adc6_default
+ &pinctrl_adc7_default
+ &pinctrl_adc8_default
+ &pinctrl_adc9_default
+ &pinctrl_adc10_default
+ &pinctrl_adc11_default
+ &pinctrl_adc12_default
+ &pinctrl_adc13_default
+ &pinctrl_adc14_default
+ &pinctrl_adc15_default>;
+};
+
+&i2c1 {
+ //Host1 IPMB bus
+ status = "okay";
+ multi-master;
+ ipmb1@10 {
+ compatible = "ipmb-dev";
+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+ i2c-protocol;
+ };
+};
+
+&i2c3 {
+ //Host2 IPMB bus
+ status = "okay";
+ multi-master;
+ ipmb3@10 {
+ compatible = "ipmb-dev";
+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+ i2c-protocol;
+ };
+};
+
+&i2c5 {
+ //Host3 IPMB bus
+ status = "okay";
+ multi-master;
+ ipmb5@10 {
+ compatible = "ipmb-dev";
+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+ i2c-protocol;
+ };
+};
+
+&i2c7 {
+ //Host4 IPMB bus
+ status = "okay";
+ multi-master;
+ ipmb7@10 {
+ compatible = "ipmb-dev";
+ reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
+ i2c-protocol;
+ };
+};
+
+&i2c8 {
+ status = "okay";
+ //FRU EEPROM
+ eeprom@51 {
+ compatible = "atmel,24c64";
+ reg = <0x51>;
+ pagesize = <32>;
+ };
+};
+
+&i2c9 {
+ status = "okay";
+ tmp421@4e {
+ //INLET TEMP
+ compatible = "ti,tmp421";
+ reg = <0x4e>;
+ };
+ //OUTLET TEMP
+ tmp421@4f {
+ compatible = "ti,tmp421";
+ reg = <0x4f>;
+ };
+};
+
+&i2c10 {
+ status = "okay";
+ //HSC
+ adm1278@40 {
+ compatible = "adi,adm1278";
+ reg = <0x40>;
+ };
+};
+
+&i2c11 {
+ status = "okay";
+ //MEZZ_TEMP_SENSOR
+ tmp421@1f {
+ compatible = "ti,tmp421";
+ reg = <0x1f>;
+ };
+};
+
+&i2c12 {
+ status = "okay";
+ //MEZZ_FRU
+ eeprom@51 {
+ compatible = "atmel,24c64";
+ reg = <0x51>;
+ pagesize = <32>;
+ };
+};
+
+&pwm_tacho {
+ status = "okay";
+ //FSC
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default>;
+ fan@0 {
+ reg = <0x00>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x00>;
+ };
+ fan@1 {
+ reg = <0x01>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x01>;
+ };
+};
--
2.7.4
^ permalink raw reply related
* [PATCH v3 2/4] ARM: dts: imx6: Use gpc for FEC interrupt controller to fix wake on LAN.
From: Martin Fuzzey @ 2020-04-02 13:51 UTC (permalink / raw)
To: Fugang Duan, Rob Herring, Shawn Guo, David S. Miller
Cc: netdev, Fabio Estevam, linux-kernel, Sascha Hauer, NXP Linux Team,
devicetree, Andrew Lunn
In-Reply-To: <1585835490-3813-1-git-send-email-martin.fuzzey@flowbird.group>
In order to wake from suspend by ethernet magic packets the GPC
must be used as intc does not have wakeup functionality.
But the FEC DT node currently uses interrupt-extended,
specificying intc, thus breaking WoL.
This problem is probably fallout from the stacked domain conversion
as intc used to chain to GPC.
So replace "interrupts-extended" by "interrupts" to use the default
parent which is GPC.
Fixes: b923ff6af0d5 ("ARM: imx6: convert GPC to stacked domains")
Signed-off-by: Martin Fuzzey <martin.fuzzey@flowbird.group>
---
arch/arm/boot/dts/imx6qdl.dtsi | 5 ++---
arch/arm/boot/dts/imx6qp.dtsi | 1 -
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index e6b4b85..bc488df 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1039,9 +1039,8 @@
compatible = "fsl,imx6q-fec";
reg = <0x02188000 0x4000>;
interrupt-names = "int0", "pps";
- interrupts-extended =
- <&intc 0 118 IRQ_TYPE_LEVEL_HIGH>,
- <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>,
+ <0 119 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_ENET>,
<&clks IMX6QDL_CLK_ENET>,
<&clks IMX6QDL_CLK_ENET_REF>;
diff --git a/arch/arm/boot/dts/imx6qp.dtsi b/arch/arm/boot/dts/imx6qp.dtsi
index 5f51f8e..d91f92f 100644
--- a/arch/arm/boot/dts/imx6qp.dtsi
+++ b/arch/arm/boot/dts/imx6qp.dtsi
@@ -77,7 +77,6 @@
};
&fec {
- /delete-property/interrupts-extended;
interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>,
<0 119 IRQ_TYPE_LEVEL_HIGH>;
};
--
1.9.1
^ permalink raw reply related
* [PATCH v3 4/4] ARM: dts: imx6: add fec gpr property.
From: Martin Fuzzey @ 2020-04-02 13:51 UTC (permalink / raw)
To: Fugang Duan, Rob Herring, Shawn Guo, David S. Miller
Cc: netdev, Fabio Estevam, linux-kernel, Sascha Hauer, NXP Linux Team,
devicetree, Andrew Lunn
In-Reply-To: <1585835490-3813-1-git-send-email-martin.fuzzey@flowbird.group>
This is required for wake on lan on i.MX6
Signed-off-by: Martin Fuzzey <martin.fuzzey@flowbird.group>
Reviewed-by: Fugang Duan <fugang.duan@nxp.com>
---
arch/arm/boot/dts/imx6qdl.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index bc488df..65b0c8a 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1045,6 +1045,7 @@
<&clks IMX6QDL_CLK_ENET>,
<&clks IMX6QDL_CLK_ENET_REF>;
clock-names = "ipg", "ahb", "ptp";
+ gpr = <&gpr>;
status = "disabled";
};
--
1.9.1
^ permalink raw reply related
* [PATCH v3 3/4] dt-bindings: fec: document the new gpr property.
From: Martin Fuzzey @ 2020-04-02 13:51 UTC (permalink / raw)
To: Fugang Duan, Rob Herring, Shawn Guo, David S. Miller
Cc: netdev, Fabio Estevam, linux-kernel, Sascha Hauer, NXP Linux Team,
devicetree, Andrew Lunn
In-Reply-To: <1585835490-3813-1-git-send-email-martin.fuzzey@flowbird.group>
This property allows the gpr register bit to be defined
for wake on lan support.
Signed-off-by: Martin Fuzzey <martin.fuzzey@flowbird.group>
Reviewed-by: Fugang Duan <fugang.duan@nxp.com>
Acked-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/net/fsl-fec.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index 5b88fae0..ff8b0f2 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -22,6 +22,8 @@ Optional properties:
- fsl,err006687-workaround-present: If present indicates that the system has
the hardware workaround for ERR006687 applied and does not need a software
workaround.
+- gpr: phandle of SoC general purpose register mode. Required for wake on LAN
+ on some SoCs
-interrupt-names: names of the interrupts listed in interrupts property in
the same order. The defaults if not specified are
__Number of interrupts__ __Default__
--
1.9.1
^ permalink raw reply related
* [PATCH v3 1/4] net: fec: set GPR bit on suspend by DT configuration.
From: Martin Fuzzey @ 2020-04-02 13:51 UTC (permalink / raw)
To: Fugang Duan, Rob Herring, Shawn Guo, David S. Miller
Cc: netdev, Fabio Estevam, linux-kernel, Sascha Hauer, NXP Linux Team,
devicetree, Andrew Lunn
In-Reply-To: <1585835490-3813-1-git-send-email-martin.fuzzey@flowbird.group>
On some SoCs, such as the i.MX6, it is necessary to set a bit
in the SoC level GPR register before suspending for wake on lan
to work.
The fec platform callback sleep_mode_enable was intended to allow this
but the platform implementation was NAK'd back in 2015 [1]
This means that, currently, wake on lan is broken on mainline for
the i.MX6 at least.
So implement the required bit setting in the fec driver by itself
by adding a new optional DT property indicating the GPR register
and adding the offset and bit information to the driver.
[1] https://www.spinics.net/lists/netdev/msg310922.html
Signed-off-by: Martin Fuzzey <martin.fuzzey@flowbird.group>
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
---
drivers/net/ethernet/freescale/fec.h | 7 ++
drivers/net/ethernet/freescale/fec_main.c | 149 ++++++++++++++++++++++++------
2 files changed, 127 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index f79e57f..d89568f 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -488,6 +488,12 @@ struct fec_enet_priv_rx_q {
struct sk_buff *rx_skbuff[RX_RING_SIZE];
};
+struct fec_stop_mode_gpr {
+ struct regmap *gpr;
+ u8 reg;
+ u8 bit;
+};
+
/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
* tx_bd_base always point to the base of the buffer descriptors. The
* cur_rx and cur_tx point to the currently available buffer.
@@ -562,6 +568,7 @@ struct fec_enet_private {
int hwts_tx_en;
struct delayed_work time_keep;
struct regulator *reg_phy;
+ struct fec_stop_mode_gpr stop_gpr;
unsigned int tx_align;
unsigned int rx_align;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 23c5fef..869efbb 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -62,6 +62,8 @@
#include <linux/if_vlan.h>
#include <linux/pinctrl/consumer.h>
#include <linux/prefetch.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
#include <soc/imx/cpuidle.h>
#include <asm/cacheflush.h>
@@ -84,6 +86,56 @@
#define FEC_ENET_OPD_V 0xFFF0
#define FEC_MDIO_PM_TIMEOUT 100 /* ms */
+struct fec_devinfo {
+ u32 quirks;
+ u8 stop_gpr_reg;
+ u8 stop_gpr_bit;
+};
+
+static const struct fec_devinfo fec_imx25_info = {
+ .quirks = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR |
+ FEC_QUIRK_HAS_FRREG,
+};
+
+static const struct fec_devinfo fec_imx27_info = {
+ .quirks = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG,
+};
+
+static const struct fec_devinfo fec_imx28_info = {
+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
+ FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
+ FEC_QUIRK_HAS_FRREG,
+};
+
+static const struct fec_devinfo fec_imx6q_info = {
+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+ FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
+ FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
+ FEC_QUIRK_HAS_RACC,
+ .stop_gpr_reg = 0x34,
+ .stop_gpr_bit = 27,
+};
+
+static const struct fec_devinfo fec_mvf600_info = {
+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
+};
+
+static const struct fec_devinfo fec_imx6x_info = {
+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+ FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
+ FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
+ FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
+ FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE,
+};
+
+static const struct fec_devinfo fec_imx6ul_info = {
+ .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+ FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
+ FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
+ FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
+ FEC_QUIRK_HAS_COALESCE,
+};
+
static struct platform_device_id fec_devtype[] = {
{
/* keep it for coldfire */
@@ -91,39 +143,25 @@
.driver_data = 0,
}, {
.name = "imx25-fec",
- .driver_data = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR |
- FEC_QUIRK_HAS_FRREG,
+ .driver_data = (kernel_ulong_t)&fec_imx25_info,
}, {
.name = "imx27-fec",
- .driver_data = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG,
+ .driver_data = (kernel_ulong_t)&fec_imx27_info,
}, {
.name = "imx28-fec",
- .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
- FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
- FEC_QUIRK_HAS_FRREG,
+ .driver_data = (kernel_ulong_t)&fec_imx28_info,
}, {
.name = "imx6q-fec",
- .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
- FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
- FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
- FEC_QUIRK_HAS_RACC,
+ .driver_data = (kernel_ulong_t)&fec_imx6q_info,
}, {
.name = "mvf600-fec",
- .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
+ .driver_data = (kernel_ulong_t)&fec_mvf600_info,
}, {
.name = "imx6sx-fec",
- .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
- FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
- FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
- FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
- FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE,
+ .driver_data = (kernel_ulong_t)&fec_imx6x_info,
}, {
.name = "imx6ul-fec",
- .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
- FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
- FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
- FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
- FEC_QUIRK_HAS_COALESCE,
+ .driver_data = (kernel_ulong_t)&fec_imx6ul_info,
}, {
/* sentinel */
}
@@ -1092,11 +1130,28 @@ static void fec_enet_reset_skb(struct net_device *ndev)
}
+static void fec_enet_stop_mode(struct fec_enet_private *fep, bool enabled)
+{
+ struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
+ struct fec_stop_mode_gpr *stop_gpr = &fep->stop_gpr;
+
+ if (stop_gpr->gpr) {
+ if (enabled)
+ regmap_update_bits(stop_gpr->gpr, stop_gpr->reg,
+ BIT(stop_gpr->bit),
+ BIT(stop_gpr->bit));
+ else
+ regmap_update_bits(stop_gpr->gpr, stop_gpr->reg,
+ BIT(stop_gpr->bit), 0);
+ } else if (pdata && pdata->sleep_mode_enable) {
+ pdata->sleep_mode_enable(enabled);
+ }
+}
+
static void
fec_stop(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
- struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
u32 val;
@@ -1125,9 +1180,7 @@ static void fec_enet_reset_skb(struct net_device *ndev)
val = readl(fep->hwp + FEC_ECNTRL);
val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
writel(val, fep->hwp + FEC_ECNTRL);
-
- if (pdata && pdata->sleep_mode_enable)
- pdata->sleep_mode_enable(true);
+ fec_enet_stop_mode(fep, true);
}
writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
@@ -3397,6 +3450,37 @@ static int fec_enet_get_irq_cnt(struct platform_device *pdev)
return irq_cnt;
}
+static int fec_enet_init_stop_mode(struct fec_enet_private *fep,
+ struct fec_devinfo *dev_info,
+ struct device_node *np)
+{
+ struct device_node *gpr_np;
+ int ret = 0;
+
+ if (!dev_info)
+ return 0;
+
+ gpr_np = of_parse_phandle(np, "gpr", 0);
+ if (!gpr_np)
+ return 0;
+
+ fep->stop_gpr.gpr = syscon_node_to_regmap(gpr_np);
+ if (IS_ERR(fep->stop_gpr.gpr)) {
+ dev_err(&fep->pdev->dev, "could not find gpr regmap\n");
+ ret = PTR_ERR(fep->stop_gpr.gpr);
+ fep->stop_gpr.gpr = NULL;
+ goto out;
+ }
+
+ fep->stop_gpr.reg = dev_info->stop_gpr_reg;
+ fep->stop_gpr.bit = dev_info->stop_gpr_bit;
+
+out:
+ of_node_put(gpr_np);
+
+ return ret;
+}
+
static int
fec_probe(struct platform_device *pdev)
{
@@ -3412,6 +3496,7 @@ static int fec_enet_get_irq_cnt(struct platform_device *pdev)
int num_rx_qs;
char irq_name[8];
int irq_cnt;
+ struct fec_devinfo *dev_info;
fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
@@ -3429,7 +3514,9 @@ static int fec_enet_get_irq_cnt(struct platform_device *pdev)
of_id = of_match_device(fec_dt_ids, &pdev->dev);
if (of_id)
pdev->id_entry = of_id->data;
- fep->quirks = pdev->id_entry->driver_data;
+ dev_info = (struct fec_devinfo *)pdev->id_entry->driver_data;
+ if (dev_info)
+ fep->quirks = dev_info->quirks;
fep->netdev = ndev;
fep->num_rx_queues = num_rx_qs;
@@ -3463,6 +3550,10 @@ static int fec_enet_get_irq_cnt(struct platform_device *pdev)
if (of_get_property(np, "fsl,magic-packet", NULL))
fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;
+ ret = fec_enet_init_stop_mode(fep, dev_info, np);
+ if (ret)
+ goto failed_stop_mode;
+
phy_node = of_parse_phandle(np, "phy-handle", 0);
if (!phy_node && of_phy_is_fixed_link(np)) {
ret = of_phy_register_fixed_link(np);
@@ -3631,6 +3722,7 @@ static int fec_enet_get_irq_cnt(struct platform_device *pdev)
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
of_node_put(phy_node);
+failed_stop_mode:
failed_phy:
dev_id--;
failed_ioremap:
@@ -3708,7 +3800,6 @@ static int __maybe_unused fec_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct fec_enet_private *fep = netdev_priv(ndev);
- struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
int ret;
int val;
@@ -3726,8 +3817,8 @@ static int __maybe_unused fec_resume(struct device *dev)
goto failed_clk;
}
if (fep->wol_flag & FEC_WOL_FLAG_ENABLE) {
- if (pdata && pdata->sleep_mode_enable)
- pdata->sleep_mode_enable(false);
+ fec_enet_stop_mode(fep, false);
+
val = readl(fep->hwp + FEC_ECNTRL);
val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
writel(val, fep->hwp + FEC_ECNTRL);
--
1.9.1
^ permalink raw reply related
* [PATCH v3 0/4] Fix Wake on lan with FEC on i.MX6
From: Martin Fuzzey @ 2020-04-02 13:51 UTC (permalink / raw)
To: Fugang Duan, Rob Herring, Shawn Guo, David S. Miller
Cc: netdev, Fabio Estevam, linux-kernel, Sascha Hauer, NXP Linux Team,
devicetree, Andrew Lunn
This series fixes WoL support with the FEC on i.MX6
The support was already in mainline but seems to have bitrotted
somewhat.
Only tested with i.MX6DL
Changes V2->V3
Patch 1:
fix non initialized variable introduced in V2 causing
probe to sometimes fail.
Patch 2:
remove /delete-property/interrupts-extended in
arch/arm/boot/dts/imx6qp.dtsi.
Patches 3 and 4:
Add received Acked-by and RB tags.
Changes V1->V2
Move the register offset and bit number from the DT to driver code
Add SOB from Fugang Duan for the NXP code on which this is based
Martin Fuzzey (4):
net: fec: set GPR bit on suspend by DT configuration.
ARM: dts: imx6: Use gpc for FEC interrupt controller to fix wake on
LAN.
dt-bindings: fec: document the new gpr property.
ARM: dts: imx6: add fec gpr property.
Documentation/devicetree/bindings/net/fsl-fec.txt | 2 +
arch/arm/boot/dts/imx6qdl.dtsi | 6 +-
arch/arm/boot/dts/imx6qp.dtsi | 1 -
drivers/net/ethernet/freescale/fec.h | 7 +
drivers/net/ethernet/freescale/fec_main.c | 149 +++++++++++++++++-----
5 files changed, 132 insertions(+), 33 deletions(-)
--
1.9.1
^ permalink raw reply
* Re: [PATCH v4 3/5] drivers/soc/litex: add LiteX SoC Controller driver
From: Mateusz Holenko @ 2020-04-02 13:50 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Rob Herring, Mark Rutland, Jiri Slaby, devicetree,
open list:SERIAL DRIVERS, Stafford Horne, Karol Gugala,
Mauro Carvalho Chehab, David S. Miller, Paul E. McKenney,
Filip Kokosinski, Pawel Czarnecki, Joel Stanley, Jonathan Cameron,
Maxime Ripard, Shawn Guo, Heiko Stuebner, Sam Ravnborg,
Icenowy Zheng, Laurent Pinchart, linux-kernel
In-Reply-To: <20200402074259.GC2755501@kroah.com>
On Thu, Apr 2, 2020 at 9:43 AM Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>
> On Thu, Apr 02, 2020 at 08:50:40AM +0200, Mateusz Holenko wrote:
> > On Thu, Apr 2, 2020 at 8:46 AM Mateusz Holenko <mholenko@antmicro.com> wrote:
> > >
> > > From: Pawel Czarnecki <pczarnecki@internships.antmicro.com>
> > >
> > > This commit adds driver for the FPGA-based LiteX SoC
> > > Controller from LiteX SoC builder.
> > >
> > > Co-developed-by: Mateusz Holenko <mholenko@antmicro.com>
> > > Signed-off-by: Mateusz Holenko <mholenko@antmicro.com>
> > > Signed-off-by: Pawel Czarnecki <pczarnecki@internships.antmicro.com>
> > > ---
> > >
> > > Notes:
> > > Changes in v4:
> > > - fixed indent in Kconfig's help section
> > > - fixed copyright header
> > > - changed compatible to "litex,soc-controller"
> > > - simplified litex_soc_ctrl_probe
> > > - removed unnecessary litex_soc_ctrl_remove
> > >
> > > This commit has been introduced in v3 of the patchset.
> > >
> > > It includes a simplified version of common 'litex.h'
> > > header introduced in v2 of the patchset.
> > >
> > > MAINTAINERS | 2 +
> > > drivers/soc/Kconfig | 1 +
> > > drivers/soc/Makefile | 1 +
> > > drivers/soc/litex/Kconfig | 14 ++
> > > drivers/soc/litex/Makefile | 3 +
> > > drivers/soc/litex/litex_soc_ctrl.c | 217 +++++++++++++++++++++++++++++
> > > include/linux/litex.h | 45 ++++++
> > > 7 files changed, 283 insertions(+)
> > > create mode 100644 drivers/soc/litex/Kconfig
> > > create mode 100644 drivers/soc/litex/Makefile
> > > create mode 100644 drivers/soc/litex/litex_soc_ctrl.c
> > > create mode 100644 include/linux/litex.h
> > >
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index 2f5ede8a08aa..a35be1be90d5 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -9729,6 +9729,8 @@ M: Karol Gugala <kgugala@antmicro.com>
> > > M: Mateusz Holenko <mholenko@antmicro.com>
> > > S: Maintained
> > > F: Documentation/devicetree/bindings/*/litex,*.yaml
> > > +F: drivers/soc/litex/litex_soc_ctrl.c
> > > +F: include/linux/litex.h
> > >
> > > LIVE PATCHING
> > > M: Josh Poimboeuf <jpoimboe@redhat.com>
> > > diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> > > index 1778f8c62861..78add2a163be 100644
> > > --- a/drivers/soc/Kconfig
> > > +++ b/drivers/soc/Kconfig
> > > @@ -9,6 +9,7 @@ source "drivers/soc/bcm/Kconfig"
> > > source "drivers/soc/fsl/Kconfig"
> > > source "drivers/soc/imx/Kconfig"
> > > source "drivers/soc/ixp4xx/Kconfig"
> > > +source "drivers/soc/litex/Kconfig"
> > > source "drivers/soc/mediatek/Kconfig"
> > > source "drivers/soc/qcom/Kconfig"
> > > source "drivers/soc/renesas/Kconfig"
> > > diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> > > index 8b49d782a1ab..fd016b51cddd 100644
> > > --- a/drivers/soc/Makefile
> > > +++ b/drivers/soc/Makefile
> > > @@ -14,6 +14,7 @@ obj-$(CONFIG_ARCH_GEMINI) += gemini/
> > > obj-$(CONFIG_ARCH_MXC) += imx/
> > > obj-$(CONFIG_ARCH_IXP4XX) += ixp4xx/
> > > obj-$(CONFIG_SOC_XWAY) += lantiq/
> > > +obj-$(CONFIG_LITEX_SOC_CONTROLLER) += litex/
> > > obj-y += mediatek/
> > > obj-y += amlogic/
> > > obj-y += qcom/
> > > diff --git a/drivers/soc/litex/Kconfig b/drivers/soc/litex/Kconfig
> > > new file mode 100644
> > > index 000000000000..71264c0e1d6c
> > > --- /dev/null
> > > +++ b/drivers/soc/litex/Kconfig
> > > @@ -0,0 +1,14 @@
> > > +# SPDX-License_Identifier: GPL-2.0
> > > +
> > > +menu "Enable LiteX SoC Builder specific drivers"
> > > +
> > > +config LITEX_SOC_CONTROLLER
> > > + tristate "Enable LiteX SoC Controller driver"
> > > + help
> > > + This option enables the SoC Controller Driver which verifies
> > > + LiteX CSR access and provides common litex_get_reg/litex_set_reg
> > > + accessors.
> > > + All drivers that use functions from litex.h must depend on
> > > + LITEX_SOC_CONTROLLER.
> > > +
> > > +endmenu
> > > diff --git a/drivers/soc/litex/Makefile b/drivers/soc/litex/Makefile
> > > new file mode 100644
> > > index 000000000000..98ff7325b1c0
> > > --- /dev/null
> > > +++ b/drivers/soc/litex/Makefile
> > > @@ -0,0 +1,3 @@
> > > +# SPDX-License_Identifier: GPL-2.0
> > > +
> > > +obj-$(CONFIG_LITEX_SOC_CONTROLLER) += litex_soc_ctrl.o
> > > diff --git a/drivers/soc/litex/litex_soc_ctrl.c b/drivers/soc/litex/litex_soc_ctrl.c
> > > new file mode 100644
> > > index 000000000000..5defba000fd4
> > > --- /dev/null
> > > +++ b/drivers/soc/litex/litex_soc_ctrl.c
> > > @@ -0,0 +1,217 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * LiteX SoC Controller Driver
> > > + *
> > > + * Copyright (C) 2020 Antmicro <www.antmicro.com>
> > > + *
> > > + */
> > > +
> > > +#include <linux/litex.h>
> > > +#include <linux/device.h>
> > > +#include <linux/errno.h>
> > > +#include <linux/of.h>
> > > +#include <linux/of_platform.h>
> > > +#include <linux/platform_device.h>
> > > +#include <linux/printk.h>
> > > +#include <linux/module.h>
> > > +#include <linux/errno.h>
> > > +#include <linux/io.h>
> > > +
> > > +/*
> > > + * The parameters below are true for LiteX SoC
> > > + * configured for 8-bit CSR Bus, 32-bit aligned.
> > > + *
> > > + * Supporting other configurations will require
> > > + * extending the logic in this header.
> > > + */
> > > +#define LITEX_REG_SIZE 0x4
> > > +#define LITEX_SUBREG_SIZE 0x1
> > > +#define LITEX_SUBREG_SIZE_BIT (LITEX_SUBREG_SIZE * 8)
> > > +
> > > +static DEFINE_SPINLOCK(csr_lock);
> > > +
> > > +static inline unsigned long read_pointer_with_barrier(
> > > + const volatile void __iomem *addr)
> > > +{
> > > + unsigned long val;
> > > +
> > > + __io_br();
> > > + val = *(const volatile unsigned long __force *)addr;
> > > + __io_ar();
> > > + return val;
> > > +}
> > > +
> > > +static inline void write_pointer_with_barrier(
> > > + volatile void __iomem *addr, unsigned long val)
> > > +{
> > > + __io_br();
> > > + *(volatile unsigned long __force *)addr = val;
> > > + __io_ar();
> > > +}
> > > +
> >
> > I'm defining read_pointer_with_barrier/write_pointer_with_barrier in
> > order to make sure that a series of reads/writes to a single CSR
> > register will not be reordered by the compiler.
>
> Please do not do this, there are core kernel calls for this, otherwise
> this would be required by every individual driver, which would be crazy.
>
> > Does __raw_readl/__raw_writel guarantee this property? If so, I could
> > drop my functions and use the system ones instead.
>
> Try it and see.
Since I want to avoid read/write reordering caused by the compiler
optimizations I don't want to rely on a single manual test.
What I mean is that even if it works now for me, it does not guarantee
that it will in the future version of the compiler/using different
compilation flags/etc, right?
> What's wrong with the normal iomem read/write
> functions?
What I want to achieve here is to access the register in the CPU
"native" endianness and make sure that the value I see there is the
same as a predefined pattern.
LiteX is a soft SoC generator - it generates the logic of the whole
SoC (CPU+peripherals) in a form that can be later synthesized and
loaded onto the FPGA/turned into an ASIC/etc. Since it generates the
system as a whole, it gives guarantees on how those elements are
interconnected. It can generate CPUs of different architectures (some
of them being little-, other big-endiann) and I want to have a single
driver to target them all.
In this driver I just want to verify that the interconnection between
CPU and the peripheral is ok - I don't want to adjust dynamically
(i.e., translate endianness in case a mismatch is detected). If what I
see in the register is not what I expect it means that there is
something wrong in the design and the generator should be fixed.
I'm not using ioread32/iowrite32 functions as they reorder bytes
depending on the CPU endianness so the returned value might not
reflect the order of bytes read directly from the peripheral. I could
use ifdefs checking the value of __LITTLE_ENDIAN (and that's in fact
was what we started with), but
(a) it was discouraged in the previous round of the review,
(b) it requires more code - checking __LITTLE_ENDIAN and using
ioread32/ioread32be accordingly.
That's why I ended up with raw pointer access.
>
> Also, just writing to a pointer like you did above is not how to do
> this, please use the normal function calls, that way your driver will
> work properly.
Instead of accessing pointer directly I could call __raw_readl/__raw_writel
- is that what you mean?
>
> thanks,
>
> greg k-h
Thank you very much for the comments!
--
Mateusz Holenko
Antmicro Ltd | www.antmicro.com
Roosevelta 22, 60-829 Poznan, Poland
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: rockchip: add rx0 mipi-phy for rk3399
From: Johan Jonker @ 2020-04-02 13:48 UTC (permalink / raw)
To: helen.koike
Cc: dafna.hirschfeld, devel, devicetree, ezequiel, heiko,
hverkuil-cisco, karthik.poduval, kernel, linux-kernel,
linux-media, linux-rockchip, mark.rutland, robh+dt
In-Reply-To: <20200402000234.226466-4-helen.koike@collabora.com>
Hi Helen,
> From: Helen Koike <helen.koike@collabora.com>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> index 33cc21fcf4c10..fc0295d2a65a1 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -1394,6 +1394,17 @@ io_domains: io-domains {
> status = "disabled";
> };
>
> + mipi_dphy_rx0: mipi-dphy-rx0 {
For Heiko sort syscon@ff770000 subnodes alphabetical or reg value first?
> + compatible = "rockchip,rk3399-mipi-dphy-rx0";
> + clocks = <&cru SCLK_MIPIDPHY_REF>,
> + <&cru SCLK_DPHY_RX0_CFG>,
> + <&cru PCLK_VIO_GRF>;
Align ^
> + clock-names = "dphy-ref", "dphy-cfg", "grf";
> + power-domains = <&power RK3399_PD_VIO>;
> + #phy-cells = <0>;
> + status = "disabled";
> + };
> +
> u2phy0: usb2-phy@e450 {
> compatible = "rockchip,rk3399-usb2phy";
> reg = <0xe450 0x10>;
> --
> 2.26.0
^ permalink raw reply
* Re: [PATCH V3 2/8] soc: qcom: geni: Support for ICC voting
From: Akash Asthana @ 2020-04-02 13:46 UTC (permalink / raw)
To: Matthias Kaehlcke
Cc: gregkh, agross, bjorn.andersson, wsa, broonie, mark.rutland,
robh+dt, georgi.djakov, linux-i2c, linux-spi, devicetree, swboyd,
mgautam, linux-arm-msm, linux-serial, dianders, evgreen
In-Reply-To: <20200331175207.GG199755@google.com>
Hi Matthias,
On 3/31/2020 11:22 PM, Matthias Kaehlcke wrote:
> Hi Akash,
>
> On Tue, Mar 31, 2020 at 04:39:30PM +0530, Akash Asthana wrote:
>> Add necessary macros and structure variables to support ICC BW
>> voting from individual SE drivers.
>>
>> Signed-off-by: Akash Asthana <akashast@codeaurora.org>
>> ---
>> Changes in V2:
>> - As per Bjorn's comment dropped enums for ICC paths, given the three
>> paths individual members
>>
>> Changes in V3:
>> - Add geni_icc_get, geni_icc_vote_on and geni_icc_vote_off as helper API.
>> - Add geni_icc_path structure in common header
>>
>> drivers/soc/qcom/qcom-geni-se.c | 98 +++++++++++++++++++++++++++++++++++++++++
>> include/linux/qcom-geni-se.h | 36 +++++++++++++++
>> 2 files changed, 134 insertions(+)
>>
>> diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
>> index 7d622ea..9344c14 100644
>> --- a/drivers/soc/qcom/qcom-geni-se.c
>> +++ b/drivers/soc/qcom/qcom-geni-se.c
>> @@ -720,6 +720,104 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
>> }
>> EXPORT_SYMBOL(geni_se_rx_dma_unprep);
>>
>> +int geni_icc_get(struct geni_se *se, const char *icc_core, const char *icc_cpu,
>> + const char *icc_ddr)
>> +{
>> + if (icc_core) {
>> + se->to_core.path = devm_of_icc_get(se->dev, "qup-core");
>> + if (IS_ERR(se->to_core.path))
>> + return PTR_ERR(se->to_core.path);
>> + }
>> +
>> + if (icc_cpu) {
>> + se->from_cpu.path = devm_of_icc_get(se->dev, "qup-config");
>> + if (IS_ERR(se->from_cpu.path))
>> + return PTR_ERR(se->from_cpu.path);
>> + }
>> +
>> + if (icc_ddr) {
>> + se->to_ddr.path = devm_of_icc_get(se->dev, "qup-memory");
>> + if (IS_ERR(se->to_ddr.path))
>> + return PTR_ERR(se->to_ddr.path);
>> + }
>> +
>> + return 0;
>> +}
>> +EXPORT_SYMBOL(geni_icc_get);
>> +
>> +int geni_icc_vote_on(struct geni_se *se)
>> +{
>> + int ret;
>> +
>> + if (se->to_core.path) {
>> + ret = icc_set_bw(se->to_core.path, se->to_core.avg_bw,
>> + se->to_core.peak_bw);
>> + if (ret) {
>> + dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for core\n",
>> + __func__);
>> + return ret;
>> + }
>> + }
>> +
>> + if (se->from_cpu.path) {
>> + ret = icc_set_bw(se->from_cpu.path, se->from_cpu.avg_bw,
>> + se->from_cpu.peak_bw);
>> + if (ret) {
>> + dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for cpu\n",
>> + __func__);
>> + return ret;
>> + }
>> + }
>> +
>> + if (se->to_ddr.path) {
>> + ret = icc_set_bw(se->to_ddr.path, se->to_ddr.avg_bw,
>> + se->to_ddr.peak_bw);
>> + if (ret) {
>> + dev_err_ratelimited(se->dev, "%s: ICC BW voting failed for ddr\n",
>> + __func__);
>> + return ret;
>> + }
>> + }
>
> With an array of 'struct geni_icc_path' pointers the above could be
> reduced to:
>
> for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
> if (!se->icc_paths[i])
> continue;
>
> ret = icc_set_bw(se->icc_paths[i]->path, se->icc_paths[i]->avg_bw,
> se->icc_paths[i]->peak_bw);
> if (ret) {
> dev_err_ratelimited(se->dev, "%s: ICC BW voting failed\n",
> __func__);
> return ret;
> }
> }
>
> similar for geni_icc_vote_off()
>
> It's just a suggestion, looks also good to me as is.
I thought giving individual path name will increase readability. But
that doesn't seems to be adding much value on cost of repeated code.
So, I will make the suggested change in next version.
Thanks,
Akash
>
> Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,\na Linux Foundation Collaborative Project
^ permalink raw reply
* [v3 1/3] [Do not pick] drm/msm/dpu: add support for clk and bw scaling for display
From: Krishna Manikandan @ 2020-04-02 13:30 UTC (permalink / raw)
To: dri-devel, linux-arm-msm, freedreno, devicetree
Cc: Krishna Manikandan, linux-kernel, robdclark, seanpaul, hoegsberg,
kalyan_t, nganji
Do not pick this patch as this patch was added by
mistake. This patch is already uploaded in the
patchwork link mentioned below.
https://patchwork.kernel.org/patch/11468783/
---
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 106 +++++++++++++++++++++----
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 5 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 +
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 37 ++++++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 +
drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 9 ++-
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 82 +++++++++++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 4 +
8 files changed, 228 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index 11f2beb..24874f6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -29,6 +29,73 @@ enum dpu_perf_mode {
DPU_PERF_MODE_MAX
};
+/**
+ * @_dpu_core_perf_calc_bw() - to calculate BW per crtc
+ * @kms - pointer to the dpu_kms
+ * @crtc - pointer to a crtc
+ * Return: returns aggregated BW for all planes in crtc.
+ */
+static u64 _dpu_core_perf_calc_bw(struct dpu_kms *kms,
+ struct drm_crtc *crtc)
+{
+ struct drm_plane *plane;
+ struct dpu_plane_state *pstate;
+ u64 crtc_plane_bw = 0;
+ u32 bw_factor;
+
+ drm_atomic_crtc_for_each_plane(plane, crtc) {
+ pstate = to_dpu_plane_state(plane->state);
+
+ if (!pstate)
+ continue;
+
+ crtc_plane_bw += pstate->plane_fetch_bw;
+ }
+
+ bw_factor = kms->catalog->perf.bw_inefficiency_factor;
+ if (bw_factor)
+ crtc_plane_bw = mult_frac(crtc_plane_bw, bw_factor, 100);
+
+ return crtc_plane_bw;
+}
+
+/**
+ * _dpu_core_perf_calc_clk() - to calculate clock per crtc
+ * @kms - pointer to the dpu_kms
+ * @crtc - pointer to a crtc
+ * @state - pointer to a crtc state
+ * Return: returns max clk for all planes in crtc.
+ */
+static u64 _dpu_core_perf_calc_clk(struct dpu_kms *kms,
+ struct drm_crtc *crtc, struct drm_crtc_state *state)
+{
+ struct drm_plane *plane;
+ struct dpu_plane_state *pstate;
+ struct drm_display_mode *mode;
+ u64 crtc_clk;
+ u32 clk_factor;
+
+ mode = &state->adjusted_mode;
+
+ crtc_clk = mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode);
+
+ drm_atomic_crtc_for_each_plane(plane, crtc) {
+ pstate = to_dpu_plane_state(plane->state);
+
+ if (!pstate)
+ continue;
+
+ crtc_clk = max(pstate->plane_clk, crtc_clk);
+ }
+
+ clk_factor = kms->catalog->perf.clk_inefficiency_factor;
+ if (clk_factor)
+ crtc_clk = mult_frac(crtc_clk, clk_factor, 100);
+
+ return crtc_clk;
+}
+
+
static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
{
struct msm_drm_private *priv;
@@ -67,12 +134,7 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms,
dpu_cstate = to_dpu_crtc_state(state);
memset(perf, 0, sizeof(struct dpu_core_perf_params));
- if (!dpu_cstate->bw_control) {
- perf->bw_ctl = kms->catalog->perf.max_bw_high *
- 1000ULL;
- perf->max_per_pipe_ib = perf->bw_ctl;
- perf->core_clk_rate = kms->perf.max_core_clk_rate;
- } else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) {
+ if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) {
perf->bw_ctl = 0;
perf->max_per_pipe_ib = 0;
perf->core_clk_rate = 0;
@@ -80,6 +142,10 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms,
perf->bw_ctl = kms->perf.fix_core_ab_vote;
perf->max_per_pipe_ib = kms->perf.fix_core_ib_vote;
perf->core_clk_rate = kms->perf.fix_core_clk_rate;
+ } else {
+ perf->bw_ctl = _dpu_core_perf_calc_bw(kms, crtc);
+ perf->max_per_pipe_ib = kms->catalog->perf.min_dram_ib;
+ perf->core_clk_rate = _dpu_core_perf_calc_clk(kms, crtc, state);
}
DPU_DEBUG(
@@ -132,11 +198,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
DPU_DEBUG("crtc:%d bw:%llu ctrl:%d\n",
tmp_crtc->base.id, tmp_cstate->new_perf.bw_ctl,
tmp_cstate->bw_control);
- /*
- * For bw check only use the bw if the
- * atomic property has been already set
- */
- if (tmp_cstate->bw_control)
+
bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl;
}
@@ -152,9 +214,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
DPU_DEBUG("final threshold bw limit = %d\n", threshold);
- if (!dpu_cstate->bw_control) {
- DPU_DEBUG("bypass bandwidth check\n");
- } else if (!threshold) {
+ if (!threshold) {
DPU_ERROR("no bandwidth limits specified\n");
return -E2BIG;
} else if (bw > threshold) {
@@ -175,7 +235,8 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms,
= dpu_crtc_get_client_type(crtc);
struct drm_crtc *tmp_crtc;
struct dpu_crtc_state *dpu_cstate;
- int ret = 0;
+ int i, ret = 0;
+ u64 avg_bw;
drm_for_each_crtc(tmp_crtc, crtc->dev) {
if (tmp_crtc->enabled &&
@@ -186,10 +247,21 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms,
perf.max_per_pipe_ib = max(perf.max_per_pipe_ib,
dpu_cstate->new_perf.max_per_pipe_ib);
- DPU_DEBUG("crtc=%d bw=%llu\n", tmp_crtc->base.id,
- dpu_cstate->new_perf.bw_ctl);
+ perf.bw_ctl += dpu_cstate->new_perf.bw_ctl;
+
+ DPU_DEBUG("crtc=%d bw=%llu paths:%d\n",
+ tmp_crtc->base.id,
+ dpu_cstate->new_perf.bw_ctl, kms->num_paths);
}
}
+
+ avg_bw = kms->num_paths ?
+ perf.bw_ctl / kms->num_paths : 0;
+
+ for (i = 0; i < kms->num_paths; i++)
+ icc_set_bw(kms->path[i],
+ Bps_to_icc(avg_bw), (perf.max_per_pipe_ib));
+
return ret;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index c567917..9c6b10a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -519,7 +519,8 @@
.max_bw_high = 5500000,
.min_core_ib = 2400000,
.min_llcc_ib = 800000,
- .min_dram_ib = 800000,
+ .min_dram_ib = 1600000,
+ .min_prefill_lines = 24,
.danger_lut_tbl = {0xff, 0xffff, 0x0},
.qos_lut_tbl = {
{.nentry = ARRAY_SIZE(sc7180_qos_linear),
@@ -536,6 +537,8 @@
{.rd_enable = 1, .wr_enable = 1},
{.rd_enable = 1, .wr_enable = 0}
},
+ .clk_inefficiency_factor = 105,
+ .bw_inefficiency_factor = 120,
};
/*************************************************************
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 09df7d8..b47e0e6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -616,6 +616,8 @@ struct dpu_perf_cdp_cfg {
* @downscaling_prefill_lines downscaling latency in lines
* @amortizable_theshold minimum y position for traffic shaping prefill
* @min_prefill_lines minimum pipeline latency in lines
+ * @clk_inefficiency_factor DPU src clock inefficiency factor
+ * @bw_inefficiency_factor DPU axi bus bw inefficiency factor
* @safe_lut_tbl: LUT tables for safe signals
* @danger_lut_tbl: LUT tables for danger signals
* @qos_lut_tbl: LUT tables for QoS signals
@@ -640,6 +642,8 @@ struct dpu_perf_cfg {
u32 downscaling_prefill_lines;
u32 amortizable_threshold;
u32 min_prefill_lines;
+ u32 clk_inefficiency_factor;
+ u32 bw_inefficiency_factor;
u32 safe_lut_tbl[DPU_QOS_LUT_USAGE_MAX];
u32 danger_lut_tbl[DPU_QOS_LUT_USAGE_MAX];
struct dpu_qos_lut_tbl qos_lut_tbl[DPU_QOS_LUT_USAGE_MAX];
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index cb08faf..3c3a838 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -228,6 +228,28 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
}
#endif
+static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms)
+{
+ struct icc_path *path0;
+ struct icc_path *path1;
+ struct drm_device *dev = dpu_kms->dev;
+
+ path0 = of_icc_get(dev->dev, "mdp0-mem");
+ path1 = of_icc_get(dev->dev, "mdp1-mem");
+
+ if (IS_ERR_OR_NULL(path0))
+ return PTR_ERR_OR_ZERO(path0);
+
+ dpu_kms->path[0] = path0;
+ dpu_kms->num_paths = 1;
+
+ if (!IS_ERR_OR_NULL(path1)) {
+ dpu_kms->path[1] = path1;
+ dpu_kms->num_paths++;
+ }
+ return 0;
+}
+
static int dpu_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc)
{
return dpu_crtc_vblank(crtc, true);
@@ -910,6 +932,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
dpu_vbif_init_memtypes(dpu_kms);
+ if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss"))
+ dpu_kms_parse_data_bus_icc_path(dpu_kms);
+
pm_runtime_put_sync(&dpu_kms->pdev->dev);
return 0;
@@ -1015,7 +1040,7 @@ static int dpu_dev_remove(struct platform_device *pdev)
static int __maybe_unused dpu_runtime_suspend(struct device *dev)
{
- int rc = -1;
+ int i, rc = -1;
struct platform_device *pdev = to_platform_device(dev);
struct dpu_kms *dpu_kms = platform_get_drvdata(pdev);
struct drm_device *ddev;
@@ -1026,6 +1051,9 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev)
if (rc)
DPU_ERROR("clock disable failed rc:%d\n", rc);
+ for (i = 0; i < dpu_kms->num_paths; i++)
+ icc_set_bw(dpu_kms->path[i], 0, 0);
+
return rc;
}
@@ -1037,8 +1065,15 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)
struct drm_encoder *encoder;
struct drm_device *ddev;
struct dss_module_power *mp = &dpu_kms->mp;
+ int i;
ddev = dpu_kms->dev;
+
+ /* Min vote of BW is required before turning on AXI clk */
+ for (i = 0; i < dpu_kms->num_paths; i++)
+ icc_set_bw(dpu_kms->path[i], 0,
+ dpu_kms->catalog->perf.min_dram_ib);
+
rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
if (rc) {
DPU_ERROR("clock enable failed rc:%d\n", rc);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index c6169e7..fc1d303 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -8,6 +8,8 @@
#ifndef __DPU_KMS_H__
#define __DPU_KMS_H__
+#include <linux/interconnect.h>
+
#include <drm/drm_drv.h>
#include "msm_drv.h"
@@ -130,6 +132,8 @@ struct dpu_kms {
* when disabled.
*/
atomic_t bandwidth_ref;
+ struct icc_path *path[2];
+ u32 num_paths;
};
struct vsync_info {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index 80d3cfc..df0a983 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -8,7 +8,6 @@
#include <linux/irqdesc.h>
#include <linux/irqchip/chained_irq.h>
#include "dpu_kms.h"
-#include <linux/interconnect.h>
#define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
@@ -315,9 +314,11 @@ int dpu_mdss_init(struct drm_device *dev)
}
dpu_mdss->mmio_len = resource_size(res);
- ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss);
- if (ret)
- return ret;
+ if (!of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) {
+ ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss);
+ if (ret)
+ return ret;
+ }
mp = &dpu_mdss->mp;
ret = msm_dss_parse_clock(pdev, mp);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 3b9c33e..c2a6e3d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -132,6 +132,84 @@ static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane)
}
/**
+ * _dpu_plane_calc_bw - calculate bandwidth required for a plane
+ * @Plane: Pointer to drm plane.
+ * Result: Updates calculated bandwidth in the plane state.
+ * BW Equation: src_w * src_h * bpp * fps * (v_total / v_dest)
+ * Prefill BW Equation: line src bytes * line_time
+ */
+static void _dpu_plane_calc_bw(struct drm_plane *plane,
+ struct drm_framebuffer *fb)
+{
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct dpu_plane_state *pstate;
+ struct drm_display_mode *mode;
+ const struct dpu_format *fmt = NULL;
+ struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
+ int src_width, src_height, dst_height, fps;
+ u64 plane_prefill_bw;
+ u64 plane_bw;
+ u32 hw_latency_lines;
+ u32 scale_factor;
+ int vbp, vpw;
+
+ pstate = to_dpu_plane_state(plane->state);
+ mode = &plane->state->crtc->mode;
+
+ fmt = dpu_get_dpu_format_ext(fb->format->format, fb->modifier);
+
+ src_width = drm_rect_width(&pdpu->pipe_cfg.src_rect);
+ src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect);
+ dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect);
+ fps = drm_mode_vrefresh(mode);
+ vbp = mode->vtotal - mode->vsync_end;
+ vpw = mode->vsync_end - mode->vsync_start;
+ hw_latency_lines = dpu_kms->catalog->perf.min_prefill_lines;
+ scale_factor = src_height > dst_height ?
+ mult_frac(src_height, 1, dst_height) : 1;
+
+ plane_bw =
+ src_width * mode->vtotal * fps * fmt->bpp * scale_factor;
+
+ plane_prefill_bw =
+ src_width * hw_latency_lines * fps * fmt->bpp * scale_factor;
+
+ plane_prefill_bw = mult_frac(plane_prefill_bw, mode->vtotal, (vbp+vpw));
+
+ pstate->plane_fetch_bw = max(plane_bw, plane_prefill_bw);
+}
+
+
+/**
+ * _dpu_plane_calc_clk - calculate clock required for a plane
+ * @Plane: Pointer to drm plane.
+ * Result: Updates calculated clock in the plane state.
+ * Clock equation: dst_w * v_total * fps * (src_h / dst_h)
+ */
+static void _dpu_plane_calc_clk(struct drm_plane *plane)
+{
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct dpu_plane_state *pstate;
+ struct drm_display_mode *mode;
+ int dst_width, src_height, dst_height, fps;
+
+ pstate = to_dpu_plane_state(plane->state);
+ mode = &plane->state->crtc->mode;
+
+ src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect);
+ dst_width = drm_rect_width(&pdpu->pipe_cfg.dst_rect);
+ dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect);
+ fps = drm_mode_vrefresh(mode);
+
+ pstate->plane_clk =
+ dst_width * mode->vtotal * fps;
+
+ if (src_height > dst_height)
+ pstate->plane_clk = mult_frac(pstate->plane_clk,
+ src_height, dst_height);
+}
+
+/**
* _dpu_plane_calc_fill_level - calculate fill level of the given source format
* @plane: Pointer to drm plane
* @fmt: Pointer to source buffer format
@@ -1102,6 +1180,10 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
}
_dpu_plane_set_qos_remap(plane);
+
+ _dpu_plane_calc_bw(plane, fb);
+
+ _dpu_plane_calc_clk(plane);
}
static void _dpu_plane_atomic_disable(struct drm_plane *plane)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
index 4569497..ca83b87 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
@@ -25,6 +25,8 @@
* @scaler3_cfg: configuration data for scaler3
* @pixel_ext: configuration data for pixel extensions
* @cdp_cfg: CDP configuration
+ * @plane_fetch_bw: calculated BW per plane
+ * @plane_clk: calculated clk per plane
*/
struct dpu_plane_state {
struct drm_plane_state base;
@@ -39,6 +41,8 @@ struct dpu_plane_state {
struct dpu_hw_pixel_ext pixel_ext;
struct dpu_hw_pipe_cdp_cfg cdp_cfg;
+ u64 plane_fetch_bw;
+ u64 plane_clk;
};
/**
--
1.9.1
^ permalink raw reply related
* [v3 3/3] arm64: dts: sc7180: add interconnect bindings for display
From: Krishna Manikandan @ 2020-04-02 13:30 UTC (permalink / raw)
To: dri-devel, linux-arm-msm, freedreno, devicetree
Cc: Krishna Manikandan, linux-kernel, robdclark, seanpaul, hoegsberg,
kalyan_t, nganji
In-Reply-To: <1585834239-8895-1-git-send-email-mkrishn@codeaurora.org>
This change adds the interconnect bindings to the
MDSS node. This will establish Display to DDR path
for bus bandwidth voting.
Changes in v2:
- Change in commit message(Matthias Kaehlcke)
Changes in v3:
- Updated commit message to include
reviewer's name in v2
Signed-off-by: Krishna Manikandan <mkrishn@codeaurora.org>
---
arch/arm64/boot/dts/qcom/sc7180.dtsi | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
index ea1b0cd..31fed6d 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -1521,6 +1521,9 @@
interrupt-controller;
#interrupt-cells = <1>;
+ interconnects = <&mmss_noc MASTER_MDP0 &mc_virt SLAVE_EBI1>;
+ interconnect-names = "mdp0-mem";
+
iommus = <&apps_smmu 0x800 0x2>;
#address-cells = <2>;
--
1.9.1
^ permalink raw reply related
* [v3 2/3] arm64: dts: sc7180: add bus clock to mdp node for sc7180 target
From: Krishna Manikandan @ 2020-04-02 13:30 UTC (permalink / raw)
To: dri-devel, linux-arm-msm, freedreno, devicetree
Cc: Krishna Manikandan, linux-kernel, robdclark, seanpaul, hoegsberg,
kalyan_t, nganji
In-Reply-To: <1585834239-8895-1-git-send-email-mkrishn@codeaurora.org>
Move the bus clock to mdp device node,in order
to facilitate bus band width scaling on sc7180
target.
The parent device MDSS will not vote for bus bw,
instead the vote will be triggered by mdp device
node. Since a minimum vote is required to turn
on bus clock, move the clock node to mdp device
from where the votes are requested.
This patch has dependency on the below series
https://patchwork.kernel.org/patch/11468783/
Signed-off-by: Krishna Manikandan <mkrishn@codeaurora.org>
---
arch/arm64/boot/dts/qcom/sc7180.dtsi | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
index 998f101..ea1b0cd 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -1510,10 +1510,9 @@
power-domains = <&dispcc MDSS_GDSC>;
clocks = <&gcc GCC_DISP_AHB_CLK>,
- <&gcc GCC_DISP_HF_AXI_CLK>,
<&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>;
- clock-names = "iface", "bus", "ahb", "core";
+ clock-names = "iface", "ahb", "core";
assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>;
assigned-clock-rates = <300000000>;
@@ -1536,12 +1535,13 @@
<0 0x0aeb0000 0 0x2008>;
reg-names = "mdp", "vbif";
- clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
<&dispcc DISP_CC_MDSS_ROT_CLK>,
<&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
<&dispcc DISP_CC_MDSS_MDP_CLK>,
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
- clock-names = "iface", "rot", "lut", "core",
+ clock-names = "bus", "iface", "rot", "lut", "core",
"vsync";
assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>,
<&dispcc DISP_CC_MDSS_VSYNC_CLK>;
--
1.9.1
^ permalink raw reply related
* Re: [PATCH v6 2/2] iio: proximity: Add driver support for vcnl3020 proximity sensor
From: Andy Shevchenko @ 2020-04-02 12:42 UTC (permalink / raw)
To: Ivan Mikhaylov
Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, linux-iio, Linux Kernel Mailing List,
devicetree, Mark Rutland, Rob Herring
In-Reply-To: <1e2c9b590a3626abee330a28cca86cbae7affb39.camel@yadro.com>
On Thu, Apr 2, 2020 at 11:24 AM Ivan Mikhaylov <i.mikhaylov@yadro.com> wrote:
>
> On Wed, 2020-04-01 at 19:35 +0300, Andy Shevchenko wrote:
> > On Wed, Apr 1, 2020 at 7:24 PM Ivan Mikhaylov <i.mikhaylov@yadro.com> wrote:
> > > Proximity sensor driver based on light/vcnl4000.c code.
> > > For now supports only the single on-demand measurement.
> > >
> > > The VCNL3020 is a fully integrated proximity sensor. Fully
> > > integrated means that the infrared emitter is included in the
> > > package. It has 16-bit resolution. It includes a signal
> > > processing IC and features standard I2C communication
> > > interface. It features an interrupt function.
> >
> > Thank you for an update, my comments below.
> >
> > ...
> >
> > > +static int get_and_apply_property(struct vcnl3020_data *data, const char
> > > *prop,
> > > + u32 reg)
> > > +{
> > > + int rc;
> > > + u32 val;
> > > +
> > > + rc = device_property_read_u32(data->dev, prop, &val);
> > > + if (rc)
> > > + return 0;
> > > +
> > > + rc = regmap_write(data->regmap, reg, val);
> > > + if (rc)
> > > + dev_err(data->dev, "Error (%d) setting property (%s)",
> > > + rc, prop);
> >
> > This requires {} according to the coding style
>
> checkpatch.pl doesn't say anything bad on this spot. Do you mean to make
> something like this?
>
> rc = regmap_write(data->regmap, reg, val);
> if (rc) {
> dev_err(data->dev, "Error (%d) setting property (%s)",
> rc, prop);
> }
Yes. Checkpatch is neither strict nor fully comprehensive tool.
> In previous notes you said to remove them.
When it's one line, it fine, otherwise you need {} surround.
https://www.kernel.org/doc/html/latest/process/coding-style.html#placing-braces-and-spaces
> > > + return rc;
> > > +}
> >
> > ...
> >
> > > +static int vcnl3020_probe(struct i2c_client *client)
> > > +{
> > > + indio_dev->name = VCNL_DRV_NAME;
> >
> > It's definitely not a driver name. You have to put part number here.
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/iio/light/tsl4531.c?h=v5.6#n199
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/iio/light/max44009.c?h=v5.6#n507
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/iio/light/vl6180.c?h=v5.6#n515
Let's Jonathan speak up.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [V4, 2/2] media: i2c: Add DW9768 VCM driver
From: Sakari Ailus @ 2020-04-02 12:32 UTC (permalink / raw)
To: Dongchun Zhu
Cc: mchehab, andriy.shevchenko, robh+dt, mark.rutland, drinkcat,
tfiga, matthias.bgg, bingbu.cao, srv_heupstream, linux-mediatek,
linux-arm-kernel, sj.huang, linux-media, devicetree, louis.kuo,
shengnan.wang
In-Reply-To: <20200330123634.363-3-dongchun.zhu@mediatek.com>
Hi Dongchun,
On Mon, Mar 30, 2020 at 08:36:34PM +0800, Dongchun Zhu wrote:
> This patch adds a V4L2 sub-device driver for DW9768 voice coil moter,
> providing control to set the desired focus via I2C serial interface.
>
> Signed-off-by: Dongchun Zhu <dongchun.zhu@mediatek.com>
> ---
> MAINTAINERS | 1 +
> drivers/media/i2c/Kconfig | 11 ++
> drivers/media/i2c/Makefile | 1 +
> drivers/media/i2c/dw9768.c | 432 +++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 445 insertions(+)
> create mode 100644 drivers/media/i2c/dw9768.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5e124d2..e007a1b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5140,6 +5140,7 @@ L: linux-media@vger.kernel.org
> S: Maintained
> T: git git://linuxtv.org/media_tree.git
> F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9768.yaml
> +F: drivers/media/i2c/dw9768.c
>
> DONGWOON DW9807 LENS VOICE COIL DRIVER
> M: Sakari Ailus <sakari.ailus@linux.intel.com>
> diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
> index c68e002..b759d3d 100644
> --- a/drivers/media/i2c/Kconfig
> +++ b/drivers/media/i2c/Kconfig
> @@ -1024,6 +1024,17 @@ config VIDEO_DW9714
> capability. This is designed for linear control of
> voice coil motors, controlled via I2C serial interface.
>
> +config VIDEO_DW9768
> + tristate "DW9768 lens voice coil support"
> + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
> + depends on VIDEO_V4L2_SUBDEV_API
> + depends on PM
> + help
> + This is a driver for the DW9768 camera lens voice coil.
> + DW9768 is a 10 bit DAC with 100mA output current sink
> + capability. This is designed for linear control of
> + voice coil motors, controlled via I2C serial interface.
> +
> config VIDEO_DW9807_VCM
> tristate "DW9807 lens voice coil support"
> depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
> diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
> index c147bb9..ec94434 100644
> --- a/drivers/media/i2c/Makefile
> +++ b/drivers/media/i2c/Makefile
> @@ -24,6 +24,7 @@ obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
> obj-$(CONFIG_VIDEO_AD5820) += ad5820.o
> obj-$(CONFIG_VIDEO_AK7375) += ak7375.o
> obj-$(CONFIG_VIDEO_DW9714) += dw9714.o
> +obj-$(CONFIG_VIDEO_DW9768) += dw9768.o
> obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
> obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
> obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
> diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c
> new file mode 100644
> index 0000000..f63afa1
> --- /dev/null
> +++ b/drivers/media/i2c/dw9768.c
> @@ -0,0 +1,432 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2020 MediaTek Inc.
> +
> +#include <linux/delay.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regulator/consumer.h>
> +#include <media/v4l2-async.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-subdev.h>
> +
> +#define DW9768_NAME "dw9768"
> +#define DW9768_MAX_FOCUS_POS (1024 - 1)
> +/*
> + * This sets the minimum granularity for the focus positions.
> + * A value of 1 gives maximum accuracy for a desired focus position
> + */
> +#define DW9768_FOCUS_STEPS 1
> +
> +/*
> + * Ring control and Power control register
> + * Bit[1] RING_EN
> + * 0: Direct mode
> + * 1: AAC mode (ringing control mode)
> + * Bit[0] PD
> + * 0: Normal operation mode
> + * 1: Power down mode
> + * DW9768 requires waiting time of Topr after PD reset takes place.
> + */
> +#define DW9768_RING_PD_CONTROL_REG 0x02
> +#define DW9768_PD_MODE_OFF 0x00
> +#define DW9768_PD_MODE_EN BIT(0)
> +#define DW9768_AAC_MODE_EN BIT(1)
> +
> +/*
> + * DW9768 separates two registers to control the VCM position.
> + * One for MSB value, another is LSB value.
> + * DAC_MSB: D[9:8] (ADD: 0x03)
> + * DAC_LSB: D[7:0] (ADD: 0x04)
> + * D[9:0] DAC data input: positive output current = D[9:0] / 1023 * 100[mA]
> + */
> +#define DW9768_MSB_ADDR 0x03
> +#define DW9768_LSB_ADDR 0x04
> +#define DW9768_STATUS_ADDR 0x05
> +
> +/*
> + * AAC mode control & prescale register
> + * Bit[7:5] Namely AC[2:0], decide the VCM mode and operation time.
> + * 000 Direct(default)
> + * 001 AAC2 0.48xTvib
> + * 010 AAC3 0.70xTvib
> + * 011 AAC4 0.75xTvib
> + * 100 Reserved
> + * 101 AAC8 1.13xTvib
> + * 110 Reserved
> + * 111 Reserved
> + * Bit[2:0] Namely PRESC[2:0], set the internal clock dividing rate as follow.
> + * 000 2
> + * 001 1(default)
> + * 010 1/2
> + * 011 1/4
> + * 100 8
> + * 101 4
> + * 110 Reserved
> + * 111 Reserved
> + */
> +#define DW9768_AAC_PRESC_REG 0x06
> +#define DW9768_AAC3_SELECT_DIVIDING_RATE_1 0x41
> +
> +/*
> + * VCM period of vibration register
> + * Bit[5:0] Defined as VCM rising periodic time (Tvib) together with PRESC[2:0]
> + * Tvib = (6.3ms + AACT[5:0] * 0.1ms) * Dividing Rate
> + * Dividing Rate is the internal clock dividing rate that is defined at
> + * PRESCALE register (ADD: 0x06)
> + */
> +#define DW9768_AAC_TIME_REG 0x07
> +#define DW9768_AACT_CNT 0x39
> +
> +/*
> + * DW9768 requires waiting time (delay time) of t_OPR after power-up,
> + * or in the case of PD reset taking place.
> + */
> +#define DW9768_T_OPR_US 1000
> +
> +/*
> + * This acts as the minimum granularity of lens movement.
> + * Keep this value power of 2, so the control steps can be
> + * uniformly adjusted for gradual lens movement, with desired
> + * number of control steps.
> + */
> +#define DW9768_MOVE_STEPS 16
> +
> +/*
> + * DW9768_AAC_PRESC_REG & DW9768_AAC_TIME_REG determine VCM operation time.
> + * If DW9768_AAC_PRESC_REG is 0x41, and DW9768_AAC_TIME_REG is 0x39, VCM mode
> + * would be AAC3, Operation Time would be 0.70xTvib, that is 8.40ms.
> + */
> +#define DW9768_MOVE_DELAY_US 8400
> +#define DW9768_STABLE_TIME_US 20000
> +
> +static const char * const dw9768_supply_names[] = {
> + "vin", /* I2C I/O interface power */
> + "vdd", /* VCM power */
> +};
> +
> +/* dw9768 device structure */
> +struct dw9768 {
> + struct regulator_bulk_data supplies[ARRAY_SIZE(dw9768_supply_names)];
> + struct v4l2_ctrl_handler ctrls;
> + struct v4l2_ctrl *focus;
> + struct v4l2_subdev sd;
> +};
> +
> +static inline struct dw9768 *to_dw9768(struct v4l2_ctrl *ctrl)
> +{
> + return container_of(ctrl->handler, struct dw9768, ctrls);
> +}
> +
> +static inline struct dw9768 *sd_to_dw9768(struct v4l2_subdev *subdev)
> +{
> + return container_of(subdev, struct dw9768, sd);
> +}
> +
> +struct regval_list {
> + u8 reg_num;
> + u8 value;
> +};
> +
> +static const struct regval_list dw9768_init_regs[] = {
> + {DW9768_RING_PD_CONTROL_REG, DW9768_AAC_MODE_EN},
> + {DW9768_AAC_PRESC_REG, DW9768_AAC3_SELECT_DIVIDING_RATE_1},
> + {DW9768_AAC_TIME_REG, DW9768_AACT_CNT},
Apologies for missing to follow the earlier discussion related to this.
I wonder if these values are specific to a given lens or a module.
Presumably so, as they're changed from the defaults.
In that case I'd put them to DT.
> +};
> +
> +static int dw9768_write_array(struct dw9768 *dw9768,
> + const struct regval_list *vals, size_t len)
> +{
> + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd);
> + unsigned int i;
> + int ret;
> +
> + for (i = 0; i < len; i++) {
> + ret = i2c_smbus_write_byte_data(client, vals[i].reg_num,
> + vals[i].value);
> + if (ret < 0)
> + return ret;
> + }
> + return 0;
> +}
> +
> +static int dw9768_set_dac(struct dw9768 *dw9768, u16 val)
> +{
> + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd);
> +
> + /* Write VCM position to registers */
> + return i2c_smbus_write_word_swapped(client, DW9768_MSB_ADDR, val);
> +}
> +
> +static int dw9768_init(struct dw9768 *dw9768)
> +{
> + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd);
> + int ret, val;
> +
> + /* Reset DW9768_RING_PD_CONTROL_REG to default status 0x00 */
> + ret = i2c_smbus_write_byte_data(client, DW9768_RING_PD_CONTROL_REG,
> + DW9768_PD_MODE_OFF);
> + if (ret < 0)
> + return ret;
> +
> + /*
> + * DW9769 requires waiting delay time of t_OPR
> + * after PD reset takes place.
> + */
> + usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100);
> +
> + ret = dw9768_write_array(dw9768, dw9768_init_regs,
> + ARRAY_SIZE(dw9768_init_regs));
> + if (ret)
> + return ret;
> +
> + for (val = dw9768->focus->val % DW9768_MOVE_STEPS;
> + val <= dw9768->focus->val;
> + val += DW9768_MOVE_STEPS) {
> + ret = dw9768_set_dac(dw9768, val);
> + if (ret) {
> + dev_err(&client->dev, "I2C write fail: %d", ret);
> + return ret;
> + }
> + usleep_range(DW9768_MOVE_DELAY_US, DW9768_MOVE_DELAY_US + 1000);
> + }
> +
> + return 0;
> +}
> +
> +static int dw9768_release(struct dw9768 *dw9768)
> +{
> + struct i2c_client *client = v4l2_get_subdevdata(&dw9768->sd);
> + int ret, val;
> +
> + val = round_down(dw9768->focus->val, DW9768_MOVE_STEPS);
> + for ( ; val >= 0; val -= DW9768_MOVE_STEPS) {
> + ret = dw9768_set_dac(dw9768, val);
> + if (ret) {
> + dev_err(&client->dev, "I2C write fail: %d", ret);
> + return ret;
> + }
> + usleep_range(DW9768_MOVE_DELAY_US, DW9768_MOVE_DELAY_US + 1000);
> + }
> +
> + /*
> + * Wait for the motor to stabilize after the last movement
> + * to prevent the motor from shaking.
> + */
> + usleep_range(DW9768_STABLE_TIME_US - DW9768_MOVE_DELAY_US,
> + DW9768_STABLE_TIME_US - DW9768_MOVE_DELAY_US + 1000);
> +
> + ret = i2c_smbus_write_byte_data(client, DW9768_RING_PD_CONTROL_REG,
> + DW9768_PD_MODE_EN);
> + if (ret < 0)
> + return ret;
> +
> + /*
> + * DW9769 requires waiting delay time of t_OPR
> + * after PD reset takes place.
> + */
> + usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused dw9768_runtime_suspend(struct device *dev)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> + struct dw9768 *dw9768 = sd_to_dw9768(sd);
> +
> + dw9768_release(dw9768);
> + regulator_bulk_disable(ARRAY_SIZE(dw9768_supply_names),
> + dw9768->supplies);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused dw9768_runtime_resume(struct device *dev)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> + struct dw9768 *dw9768 = sd_to_dw9768(sd);
> + int ret;
> +
> + ret = regulator_bulk_enable(ARRAY_SIZE(dw9768_supply_names),
> + dw9768->supplies);
> + if (ret < 0) {
> + dev_err(dev, "failed to enable regulators\n");
> + return ret;
> + }
> +
> + /*
> + * The datasheet refers to t_OPR that needs to be waited before sending
> + * I2C commands after power-up.
> + */
> + usleep_range(DW9768_T_OPR_US, DW9768_T_OPR_US + 100);
> +
> + ret = dw9768_init(dw9768);
> + if (ret < 0)
> + goto disable_regulator;
> +
> + return 0;
> +
> +disable_regulator:
> + regulator_bulk_disable(ARRAY_SIZE(dw9768_supply_names),
> + dw9768->supplies);
> +
> + return ret;
> +}
> +
> +static int dw9768_set_ctrl(struct v4l2_ctrl *ctrl)
> +{
> + struct dw9768 *dw9768 = to_dw9768(ctrl);
> +
> + if (ctrl->id == V4L2_CID_FOCUS_ABSOLUTE)
> + return dw9768_set_dac(dw9768, ctrl->val);
> +
> + return 0;
> +}
> +
> +static const struct v4l2_ctrl_ops dw9768_ctrl_ops = {
> + .s_ctrl = dw9768_set_ctrl,
> +};
> +
> +static int dw9768_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> + int ret;
> +
> + ret = pm_runtime_get_sync(sd->dev);
> + if (ret < 0) {
> + pm_runtime_put_noidle(sd->dev);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int dw9768_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
> +{
> + pm_runtime_put(sd->dev);
> +
> + return 0;
> +}
> +
> +static const struct v4l2_subdev_internal_ops dw9768_int_ops = {
> + .open = dw9768_open,
> + .close = dw9768_close,
> +};
> +
> +static const struct v4l2_subdev_ops dw9768_ops = { };
> +
> +static int dw9768_init_controls(struct dw9768 *dw9768)
> +{
> + struct v4l2_ctrl_handler *hdl = &dw9768->ctrls;
> + const struct v4l2_ctrl_ops *ops = &dw9768_ctrl_ops;
> +
> + v4l2_ctrl_handler_init(hdl, 1);
> +
> + dw9768->focus = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE, 0,
> + DW9768_MAX_FOCUS_POS,
> + DW9768_FOCUS_STEPS, 0);
> +
> + if (hdl->error)
> + return hdl->error;
> +
> + dw9768->sd.ctrl_handler = hdl;
> +
> + return 0;
> +}
> +
> +static int dw9768_probe(struct i2c_client *client)
> +{
> + struct device *dev = &client->dev;
> + struct dw9768 *dw9768;
> + unsigned int i;
> + int ret;
> +
> + dw9768 = devm_kzalloc(dev, sizeof(*dw9768), GFP_KERNEL);
> + if (!dw9768)
> + return -ENOMEM;
> +
> + v4l2_i2c_subdev_init(&dw9768->sd, client, &dw9768_ops);
> +
> + for (i = 0; i < ARRAY_SIZE(dw9768_supply_names); i++)
> + dw9768->supplies[i].supply = dw9768_supply_names[i];
> +
> + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dw9768_supply_names),
> + dw9768->supplies);
> + if (ret) {
> + dev_err(dev, "failed to get regulators\n");
> + return ret;
> + }
> +
> + ret = dw9768_init_controls(dw9768);
> + if (ret)
> + goto entity_cleanup;
> +
> + dw9768->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> + dw9768->sd.internal_ops = &dw9768_int_ops;
> +
> + ret = media_entity_pads_init(&dw9768->sd.entity, 0, NULL);
> + if (ret < 0)
> + goto entity_cleanup;
> +
> + dw9768->sd.entity.function = MEDIA_ENT_F_LENS;
> +
> + ret = v4l2_async_register_subdev(&dw9768->sd);
> + if (ret < 0)
> + goto entity_cleanup;
> +
> + pm_runtime_enable(dev);
Note that here, the device node may be already created before runtime PM is
enabled.
Could you reverse order of enabling runtime PM and registering the async
subdev to fix that?
> +
> + return 0;
> +
> +entity_cleanup:
> + v4l2_ctrl_handler_free(&dw9768->ctrls);
> + media_entity_cleanup(&dw9768->sd.entity);
> + return ret;
> +}
> +
> +static int dw9768_remove(struct i2c_client *client)
> +{
> + struct v4l2_subdev *sd = i2c_get_clientdata(client);
> + struct dw9768 *dw9768 = sd_to_dw9768(sd);
> +
> + pm_runtime_disable(&client->dev);
> + v4l2_async_unregister_subdev(&dw9768->sd);
> + v4l2_ctrl_handler_free(&dw9768->ctrls);
> + media_entity_cleanup(&dw9768->sd.entity);
> + if (!pm_runtime_status_suspended(&client->dev))
> + dw9768_runtime_suspend(&client->dev);
> + pm_runtime_set_suspended(&client->dev);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id dw9768_of_table[] = {
> + { .compatible = "dongwoon,dw9768" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, dw9768_of_table);
> +
> +static const struct dev_pm_ops dw9768_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> + pm_runtime_force_resume)
> + SET_RUNTIME_PM_OPS(dw9768_runtime_suspend, dw9768_runtime_resume, NULL)
> +};
> +
> +static struct i2c_driver dw9768_i2c_driver = {
> + .driver = {
> + .name = DW9768_NAME,
> + .pm = IS_ENABLED(CONFIG_PM) ? &dw9768_pm_ops : NULL,
You can drop the condition as the driver depends on CONFIG_PM.
> + .of_match_table = dw9768_of_table,
> + },
> + .probe_new = dw9768_probe,
> + .remove = dw9768_remove,
> +};
> +
> +module_i2c_driver(dw9768_i2c_driver);
> +
> +MODULE_AUTHOR("Dongchun Zhu <dongchun.zhu@mediatek.com>");
> +MODULE_DESCRIPTION("DW9768 VCM driver");
> +MODULE_LICENSE("GPL v2");
--
Regards,
Sakari Ailus
^ permalink raw reply
* Re: [PATCH 1/4] dt-bindings: phy: phy-rockchip-dphy-rx0: move rockchip dphy rx0 bindings out of staging
From: Johan Jonker @ 2020-04-02 12:16 UTC (permalink / raw)
To: helen.koike
Cc: dafna.hirschfeld, devel, devicetree, ezequiel, heiko,
hverkuil-cisco, karthik.poduval, kernel, linux-kernel,
linux-media, linux-rockchip, mark.rutland, robh+dt
In-Reply-To: <20200402000234.226466-2-helen.koike@collabora.com>
Hi Helen,
> # SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> %YAML 1.2
> ---
> $id: http://devicetree.org/schemas/phy/rockchip-mipi-dphy-rx0.yaml#
> $schema: http://devicetree.org/meta-schemas/core.yaml#
>
> title: Rockchip SoC MIPI RX0 D-PHY Device Tree Bindings
>
> maintainers:
> - Helen Koike <helen.koike@collabora.com>
> - Ezequiel Garcia <ezequiel@collabora.com>
>
> description: |
> The Rockchip SoC has a MIPI D-PHY bus with an RX0 entry which connects to
> the ISP1 (Image Signal Processing unit v1.0) for CSI cameras.
>
> properties:
> compatible:
> const: rockchip,rk3399-mipi-dphy-rx0
>
> reg:
> maxItems: 1
If 'reg' is not used => remove it.
>
> clocks:
> items:
> - description: MIPI D-PHY ref clock
> - description: MIPI D-PHY RX0 cfg clock
> - description: Video in/out general register file clock
>
> clock-names:
> items:
> - const: dphy-ref
> - const: dphy-cfg
> - const: grf
>
> '#phy-cells':
> const: 0
>
> power-domains:
> description: Video in/out power domain.
> maxItems: 1
>
> required:
> - compatible
> - clocks
> - clock-names
> - '#phy-cells'
> - power-domains
>
> additionalProperties: false
>
> examples:
> - |
>
> /*
> * MIPI D-PHY RX0 use registers in "general register files", it
> * should be a child of the GRF.
> *
> * grf: syscon@ff770000 {
> * compatible = "rockchip,rk3399-grf", "syscon", "simple-mfd";
> * ...
> * };
> */
>
> #include <dt-bindings/clock/rk3399-cru.h>
> #include <dt-bindings/power/rk3399-power.h>
>
> mipi_dphy_rx0: mipi-dphy-rx0 {
> compatible = "rockchip,rk3399-mipi-dphy-rx0";
> clocks = <&cru SCLK_MIPIDPHY_REF>,
> <&cru SCLK_DPHY_RX0_CFG>,
> <&cru PCLK_VIO_GRF>;
> clock-names = "dphy-ref", "dphy-cfg", "grf";
> power-domains = <&power RK3399_PD_VIO>;
> #phy-cells = <0>;
> };
^ permalink raw reply
* [PATCH v2 01/10] PCIe: qcom: add missing ipq806x clocks in PCIe driver
From: Ansuel Smith @ 2020-04-02 12:11 UTC (permalink / raw)
To: Andy Gross
Cc: Ansuel Smith, Sham Muthayyan, Bjorn Andersson, Bjorn Helgaas,
Rob Herring, Mark Rutland, Stanimir Varbanov, Lorenzo Pieralisi,
Andrew Murray, Philipp Zabel, linux-arm-msm, linux-pci,
devicetree, linux-kernel
In-Reply-To: <20200402121148.1767-1-ansuelsmth@gmail.com>
Aux and Ref clk are missing in pcie qcom driver.
Add support in the driver to fix pcie inizialization in ipq806x.
Fixes: 82a82383 PCI: qcom: Add Qualcomm PCIe controller driver
Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org>
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
---
drivers/pci/controller/dwc/pcie-qcom.c | 38 ++++++++++++++++++++++----
1 file changed, 33 insertions(+), 5 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index 5ea527a6bd9f..f958c535de6e 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -88,6 +88,8 @@ struct qcom_pcie_resources_2_1_0 {
struct clk *iface_clk;
struct clk *core_clk;
struct clk *phy_clk;
+ struct clk *aux_clk;
+ struct clk *ref_clk;
struct reset_control *pci_reset;
struct reset_control *axi_reset;
struct reset_control *ahb_reset;
@@ -246,6 +248,14 @@ static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie)
if (IS_ERR(res->phy_clk))
return PTR_ERR(res->phy_clk);
+ res->aux_clk = devm_clk_get(dev, "aux");
+ if (IS_ERR(res->aux_clk))
+ return PTR_ERR(res->aux_clk);
+
+ res->ref_clk = devm_clk_get(dev, "ref");
+ if (IS_ERR(res->ref_clk))
+ return PTR_ERR(res->ref_clk);
+
res->pci_reset = devm_reset_control_get_exclusive(dev, "pci");
if (IS_ERR(res->pci_reset))
return PTR_ERR(res->pci_reset);
@@ -278,6 +288,8 @@ static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie)
clk_disable_unprepare(res->iface_clk);
clk_disable_unprepare(res->core_clk);
clk_disable_unprepare(res->phy_clk);
+ clk_disable_unprepare(res->aux_clk);
+ clk_disable_unprepare(res->ref_clk);
regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
}
@@ -307,16 +319,28 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie)
goto err_assert_ahb;
}
+ ret = clk_prepare_enable(res->core_clk);
+ if (ret) {
+ dev_err(dev, "cannot prepare/enable core clock\n");
+ goto err_clk_core;
+ }
+
ret = clk_prepare_enable(res->phy_clk);
if (ret) {
dev_err(dev, "cannot prepare/enable phy clock\n");
goto err_clk_phy;
}
- ret = clk_prepare_enable(res->core_clk);
+ ret = clk_prepare_enable(res->aux_clk);
if (ret) {
- dev_err(dev, "cannot prepare/enable core clock\n");
- goto err_clk_core;
+ dev_err(dev, "cannot prepare/enable aux clock\n");
+ goto err_clk_aux;
+ }
+
+ ret = clk_prepare_enable(res->ref_clk);
+ if (ret) {
+ dev_err(dev, "cannot prepare/enable ref clock\n");
+ goto err_clk_ref;
}
ret = reset_control_deassert(res->ahb_reset);
@@ -372,10 +396,14 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie)
return 0;
err_deassert_ahb:
- clk_disable_unprepare(res->core_clk);
-err_clk_core:
+ clk_disable_unprepare(res->ref_clk);
+err_clk_ref:
+ clk_disable_unprepare(res->aux_clk);
+err_clk_aux:
clk_disable_unprepare(res->phy_clk);
err_clk_phy:
+ clk_disable_unprepare(res->core_clk);
+err_clk_core:
clk_disable_unprepare(res->iface_clk);
err_assert_ahb:
regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
--
2.25.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox