* Re: [PATCH v2 6/6] dt-bindings: drm: bridge: adi,adv7511.txt: convert to yaml
From: Ricardo Cañuelo @ 2020-05-25 7:43 UTC (permalink / raw)
To: Laurent Pinchart
Cc: kernel, devicetree, linux-arm-kernel, geert+renesas, robh+dt,
xuwei5
In-Reply-To: <20200514152239.GG5955@pendragon.ideasonboard.com>
Hi Laurent,
On jue 14-05-2020 18:22:39, Laurent Pinchart wrote:
> > If we want to be more strict and require the definition of all the
> > supplies, there will be many more DTs changes in the series, and I'm not
> > sure I'll be able to do that in a reasonable amount of time. I'm looking
> > at them and it's not always clear which regulators to use or if they are
> > even defined.
>
> We can decouple the two though (I think). The bindings should reflect
> what we consider right, and the dts files could be fixed on top.
Do you have a suggestion on how to do this? If we decouple the two
tasks most of the work would be searching for DTs to fix and finding a
way to fix each one of them, and unless I do this _before_ the binding
conversion I'll get a lot of dtbs_check errors.
The binding conversion itself is done, if we go this route the only
additional change would be to make the supplies required.
Cheers,
Ricardo
^ permalink raw reply
* Re: [PATCH v3 1/5] dt-bindings: iio: imu: bmi160: convert txt format to yaml
From: Jonathan Albrieux @ 2020-05-25 7:27 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-kernel, ~postmarketos/upstreaming, daniel.baluta,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Hartmut Knaack, Lars-Peter Clausen,
open list:IIO SUBSYSTEM AND DRIVERS, Peter Meerwald-Stadler,
Rob Herring
In-Reply-To: <20200524124114.7f4e785d@archlinux>
On Sun, May 24, 2020 at 12:41:14PM +0100, Jonathan Cameron wrote:
> On Wed, 20 May 2020 21:46:40 +0200
> Jonathan Albrieux <jonathan.albrieux@gmail.com> wrote:
>
> > Converts documentation from txt format to yaml.
> >
> > Signed-off-by: Jonathan Albrieux <jonathan.albrieux@gmail.com>
>
> A reminder on the maintainer bit as that thread crossed with
> this one. Also, drop the spi-max-frequency as we don't need
> to mention it explicitly for this device.
>
> Thanks,
>
> Jonathan
>
Thank you, I'll remove it today.
>
> > ---
> > .../devicetree/bindings/iio/imu/bmi160.txt | 37 ---------
> > .../bindings/iio/imu/bosch,bmi160.yaml | 76 +++++++++++++++++++
> > 2 files changed, 76 insertions(+), 37 deletions(-)
> > delete mode 100644 Documentation/devicetree/bindings/iio/imu/bmi160.txt
> > create mode 100644 Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/iio/imu/bmi160.txt b/Documentation/devicetree/bindings/iio/imu/bmi160.txt
> > deleted file mode 100644
> > index 900c169de00f..000000000000
> > --- a/Documentation/devicetree/bindings/iio/imu/bmi160.txt
> > +++ /dev/null
> > @@ -1,37 +0,0 @@
> > -Bosch BMI160 - Inertial Measurement Unit with Accelerometer, Gyroscope
> > -and externally connectable Magnetometer
> > -
> > -https://www.bosch-sensortec.com/bst/products/all_products/bmi160
> > -
> > -Required properties:
> > - - compatible : should be "bosch,bmi160"
> > - - reg : the I2C address or SPI chip select number of the sensor
> > - - spi-max-frequency : set maximum clock frequency (only for SPI)
> > -
> > -Optional properties:
> > - - interrupts : interrupt mapping for IRQ
> > - - interrupt-names : set to "INT1" if INT1 pin should be used as interrupt
> > - input, set to "INT2" if INT2 pin should be used instead
> > - - drive-open-drain : set if the specified interrupt pin should be configured as
> > - open drain. If not set, defaults to push-pull.
> > -
> > -Examples:
> > -
> > -bmi160@68 {
> > - compatible = "bosch,bmi160";
> > - reg = <0x68>;
> > -
> > - interrupt-parent = <&gpio4>;
> > - interrupts = <12 IRQ_TYPE_EDGE_RISING>;
> > - interrupt-names = "INT1";
> > -};
> > -
> > -bmi160@0 {
> > - compatible = "bosch,bmi160";
> > - reg = <0>;
> > - spi-max-frequency = <10000000>;
> > -
> > - interrupt-parent = <&gpio2>;
> > - interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
> > - interrupt-names = "INT2";
> > -};
> > diff --git a/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml b/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml
> > new file mode 100644
> > index 000000000000..46cb4fde1165
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml
> > @@ -0,0 +1,76 @@
> > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/iio/imu/bosch,bmi160.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Bosch BMI160
> > +
> > +maintainers:
> > + - Daniel Baluta <daniel.baluta@nxp.com> (?)
>
> Daniel's reply crossed with this. Given he's moved on to other things
> he's not happy to be listed as maintainer here.
>
> Given other threads, either put yourself here if you are happy to maintain
> the binding, or fall back to me but use my kernel.org address.
>
> Jonathan Cameron <jic23@kernel.org>
>
> I don't mind either way.
>
Thank you, I'll add you then for this binding.
Thank for your help,
Best regards,
Jonathan Albrieux
>
> > +
> > +description: |
> > + Inertial Measurement Unit with Accelerometer, Gyroscope and externally
> > + connectable Magnetometer
> > + https://www.bosch-sensortec.com/bst/products/all_products/bmi160
> > +
> > +properties:
> > + compatible:
> > + const: bosch,bmi160
> > +
> > + reg:
> > + maxItems: 1
> > +
> > + spi-max-frequency:
> > + maxItems: 1
>
> spi-max-frequency doesn't need to be here at all. We aren't trying to list
> all of the properties that might be present - but rather those that
> are either required or that are part of the description of the device.
> This one is a generic spi binding that may or may not be present.
>
> > +
> > + interrupts:
> > + maxItems: 1
> > +
> > + interrupt-names:
> > + enum:
> > + - INT1
> > + - INT2
> > + description: |
> > + set to "INT1" if INT1 pin should be used as interrupt input, set
> > + to "INT2" if INT2 pin should be used instead
> > +
> > + drive-open-drain:
> > + description: |
> > + set if the specified interrupt pin should be configured as
> > + open drain. If not set, defaults to push-pull.
> > +
> > +required:
> > + - compatible
> > + - reg
> > +
> > +examples:
> > + - |
> > + // Example for I2C
> > + i2c {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > +
> > + bmi160@68 {
> > + compatible = "bosch,bmi160";
> > + reg = <0x68>;
> > + interrupt-parent = <&gpio4>;
> > + interrupts = <12 1>;
> > + interrupt-names = "INT1";
> > + };
> > + };
> > + - |
> > + // Example for SPI
> > + spi {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > +
> > + bmi160@0 {
> > + compatible = "bosch,bmi160";
> > + reg = <0>;
> > + spi-max-frequency = <10000000>;
> > + interrupt-parent = <&gpio2>;
> > + interrupts = <12 1>;
> > + interrupt-names = "INT2";
> > + };
> > + };
>
^ permalink raw reply
* [PATCH net v2 4/4] ARM: dts: imx6qdl-sabresd: enable fec wake-on-lan
From: fugang.duan @ 2020-05-25 7:09 UTC (permalink / raw)
To: andrew, martin.fuzzey, davem
Cc: netdev, robh+dt, shawnguo, devicetree, kuba, fugang.duan
In-Reply-To: <1590390569-4394-1-git-send-email-fugang.duan@nxp.com>
From: Fugang Duan <fugang.duan@nxp.com>
Enable ethernet wake-on-lan feature for imx6q/dl/qp sabresd
boards since the PHY clock is supplied by exteranl osc.
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
---
arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index fe59dde..28b35cc 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -204,6 +204,7 @@
pinctrl-0 = <&pinctrl_enet>;
phy-mode = "rgmii-id";
phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+ fsl,magic-packet;
status = "okay";
};
--
2.7.4
^ permalink raw reply related
* [PATCH net v2 3/4] ARM: dts: imx: add ethernet stop mode property
From: fugang.duan @ 2020-05-25 7:09 UTC (permalink / raw)
To: andrew, martin.fuzzey, davem
Cc: netdev, robh+dt, shawnguo, devicetree, kuba, fugang.duan
In-Reply-To: <1590390569-4394-1-git-send-email-fugang.duan@nxp.com>
From: Fugang Duan <fugang.duan@nxp.com>
- Update the imx6qdl gpr property to define gpr register
offset and bit in DT.
- Add imx6sx/imx6ul/imx7d ethernet stop mode property.
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
---
arch/arm/boot/dts/imx6qdl.dtsi | 2 +-
arch/arm/boot/dts/imx6sx.dtsi | 2 ++
arch/arm/boot/dts/imx6ul.dtsi | 2 ++
arch/arm/boot/dts/imx7d.dtsi | 1 +
arch/arm/boot/dts/imx7s.dtsi | 1 +
5 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 98da446..48f5016 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1045,7 +1045,7 @@
<&clks IMX6QDL_CLK_ENET>,
<&clks IMX6QDL_CLK_ENET_REF>;
clock-names = "ipg", "ahb", "ptp";
- gpr = <&gpr>;
+ fsl,stop-mode = <&gpr 0x34 27>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index d6f8317..09f21aa 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -930,6 +930,7 @@
"enet_clk_ref", "enet_out";
fsl,num-tx-queues = <3>;
fsl,num-rx-queues = <3>;
+ fsl,stop-mode = <&gpr 0x10 3>;
status = "disabled";
};
@@ -1039,6 +1040,7 @@
<&clks IMX6SX_CLK_ENET_PTP>;
clock-names = "ipg", "ahb", "ptp",
"enet_clk_ref", "enet_out";
+ fsl,stop-mode = <&gpr 0x10 4>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index 2ccf67c..345ae9b 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -520,6 +520,7 @@
"enet_clk_ref", "enet_out";
fsl,num-tx-queues = <1>;
fsl,num-rx-queues = <1>;
+ fsl,stop-mode = <&gpr 0x10 4>;
status = "disabled";
};
@@ -856,6 +857,7 @@
"enet_clk_ref", "enet_out";
fsl,num-tx-queues = <1>;
fsl,num-rx-queues = <1>;
+ fsl,stop-mode = <&gpr 0x10 3>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
index 4c22828..cff875b 100644
--- a/arch/arm/boot/dts/imx7d.dtsi
+++ b/arch/arm/boot/dts/imx7d.dtsi
@@ -153,6 +153,7 @@
"enet_clk_ref", "enet_out";
fsl,num-tx-queues = <3>;
fsl,num-rx-queues = <3>;
+ fsl,stop-mode = <&gpr 0x10 4>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 76e3ffb..5bf0b39 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -1190,6 +1190,7 @@
"enet_clk_ref", "enet_out";
fsl,num-tx-queues = <3>;
fsl,num-rx-queues = <3>;
+ fsl,stop-mode = <&gpr 0x10 3>;
status = "disabled";
};
};
--
2.7.4
^ permalink raw reply related
* [PATCH net v2 2/4] dt-bindings: fec: update the gpr property
From: fugang.duan @ 2020-05-25 7:09 UTC (permalink / raw)
To: andrew, martin.fuzzey, davem
Cc: netdev, robh+dt, shawnguo, devicetree, kuba, fugang.duan
In-Reply-To: <1590390569-4394-1-git-send-email-fugang.duan@nxp.com>
From: Fugang Duan <fugang.duan@nxp.com>
- rename the 'gpr' property string to 'fsl,stop-mode'.
- Update the property to define gpr register offset and
bit in DT, since different instance have different gpr bit.
v2:
* rename 'gpr' property string to 'fsl,stop-mode'.
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
---
Documentation/devicetree/bindings/net/fsl-fec.txt | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index 26c492a..9b54378 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -22,8 +22,11 @@ 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
+- fsl,stop-mode: register bits of stop mode control, the format is
+ <&gpr req_gpr req_bit>.
+ gpr is the phandle to general purpose register node.
+ req_gpr is the gpr register offset for ENET stop request.
+ req_bit is the gpr bit offset for ENET stop request.
-interrupt-names: names of the interrupts listed in interrupts property in
the same order. The defaults if not specified are
__Number of interrupts__ __Default__
--
2.7.4
^ permalink raw reply related
* [PATCH net v2 1/4] net: ethernet: fec: move GPR register offset and bit into DT
From: fugang.duan @ 2020-05-25 7:09 UTC (permalink / raw)
To: andrew, martin.fuzzey, davem
Cc: netdev, robh+dt, shawnguo, devicetree, kuba, fugang.duan
In-Reply-To: <1590390569-4394-1-git-send-email-fugang.duan@nxp.com>
From: Fugang Duan <fugang.duan@nxp.com>
The commit da722186f654 (net: fec: set GPR bit on suspend by DT
configuration) set the GPR reigster offset and bit in driver for
wake on lan feature.
But it introduces two issues here:
- one SOC has two instances, they have different bit
- different SOCs may have different offset and bit
So to support wake-on-lan feature on other i.MX platforms, it should
configure the GPR reigster offset and bit from DT.
So the patch is to improve the commit da722186f654 (net: fec: set GPR
bit on suspend by DT configuration) to support multiple ethernet
instances on i.MX series.
v2:
* switch back to store the quirks bitmask in driver_data
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
---
drivers/net/ethernet/freescale/fec_main.c | 103 ++++++++++--------------------
1 file changed, 34 insertions(+), 69 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 2e20914..4f55d30 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -86,56 +86,6 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
#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 */
@@ -143,25 +93,39 @@ static struct platform_device_id fec_devtype[] = {
.driver_data = 0,
}, {
.name = "imx25-fec",
- .driver_data = (kernel_ulong_t)&fec_imx25_info,
+ .driver_data = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR |
+ FEC_QUIRK_HAS_FRREG,
}, {
.name = "imx27-fec",
- .driver_data = (kernel_ulong_t)&fec_imx27_info,
+ .driver_data = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG,
}, {
.name = "imx28-fec",
- .driver_data = (kernel_ulong_t)&fec_imx28_info,
+ .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
+ FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
+ FEC_QUIRK_HAS_FRREG,
}, {
.name = "imx6q-fec",
- .driver_data = (kernel_ulong_t)&fec_imx6q_info,
+ .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,
}, {
.name = "mvf600-fec",
- .driver_data = (kernel_ulong_t)&fec_mvf600_info,
+ .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
}, {
.name = "imx6sx-fec",
- .driver_data = (kernel_ulong_t)&fec_imx6x_info,
+ .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,
}, {
.name = "imx6ul-fec",
- .driver_data = (kernel_ulong_t)&fec_imx6ul_info,
+ .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,
}, {
/* sentinel */
}
@@ -3476,19 +3440,23 @@ static int fec_enet_get_irq_cnt(struct platform_device *pdev)
}
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;
+ u32 out_val[3];
int ret = 0;
- if (!dev_info)
- return 0;
-
- gpr_np = of_parse_phandle(np, "gpr", 0);
+ gpr_np = of_parse_phandle(np, "fsl,stop-mode", 0);
if (!gpr_np)
return 0;
+ ret = of_property_read_u32_array(np, "fsl,stop-mode", out_val,
+ ARRAY_SIZE(out_val));
+ if (ret) {
+ dev_dbg(&fep->pdev->dev, "no stop mode property\n");
+ return ret;
+ }
+
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");
@@ -3497,8 +3465,8 @@ static int fec_enet_init_stop_mode(struct fec_enet_private *fep,
goto out;
}
- fep->stop_gpr.reg = dev_info->stop_gpr_reg;
- fep->stop_gpr.bit = dev_info->stop_gpr_bit;
+ fep->stop_gpr.reg = out_val[1];
+ fep->stop_gpr.bit = out_val[2];
out:
of_node_put(gpr_np);
@@ -3521,7 +3489,6 @@ fec_probe(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);
@@ -3539,9 +3506,7 @@ fec_probe(struct platform_device *pdev)
of_id = of_match_device(fec_dt_ids, &pdev->dev);
if (of_id)
pdev->id_entry = of_id->data;
- dev_info = (struct fec_devinfo *)pdev->id_entry->driver_data;
- if (dev_info)
- fep->quirks = dev_info->quirks;
+ fep->quirks = pdev->id_entry->driver_data;
fep->netdev = ndev;
fep->num_rx_queues = num_rx_qs;
@@ -3575,7 +3540,7 @@ fec_probe(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);
+ ret = fec_enet_init_stop_mode(fep, np);
if (ret)
goto failed_stop_mode;
--
2.7.4
^ permalink raw reply related
* [PATCH net v2 0/4] net: ethernet: fec: move GPR reigster offset and bit into DT
From: fugang.duan @ 2020-05-25 7:09 UTC (permalink / raw)
To: andrew, martin.fuzzey, davem
Cc: netdev, robh+dt, shawnguo, devicetree, kuba, fugang.duan
From: Fugang Duan <fugang.duan@nxp.com>
The commit da722186f654 (net: fec: set GPR bit on suspend by DT configuration) set the GPR reigster offset and bit in driver for wol feature.
It bring trouble to enable wol feature on imx6sx/imx6ul/imx7d platforms that have multiple ethernet instances with different GPR bit for stop mode control. So the patch set is to move GPR reigster offset and bit define into DT, and enable imx6q/imx6dl/imx6sx/imx6ul/imx7d stop mode support.
Currently, below NXP i.MX boards support wol:
- imx6q/imx6dl sabresd
- imx6sx sabreauto
- imx7d sdb
imx6q/imx6dl sarebsd board dts file miss the property "fsl,magic-packet;", so patch#4 is to add the property for stop mode support.
v1 -> v2:
- driver: switch back to store the quirks bitmask in driver_data
- dt-bindings: rename 'gpr' property string to 'fsl,stop-mode'
- imx6/7 dtsi: add imx6sx/imx6ul/imx7d ethernet stop mode property
Thanks Martin and Andrew for the review.
Fugang Duan (4):
net: ethernet: fec: move GPR register offset and bit into DT
dt-bindings: fec: update the gpr property
ARM: dts: imx: add ethernet stop mode property
ARM: dts: imx6qdl-sabresd: enable fec wake-on-lan
Documentation/devicetree/bindings/net/fsl-fec.txt | 7 +-
arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 1 +
arch/arm/boot/dts/imx6qdl.dtsi | 2 +-
arch/arm/boot/dts/imx6sx.dtsi | 2 +
arch/arm/boot/dts/imx6ul.dtsi | 2 +
arch/arm/boot/dts/imx7d.dtsi | 1 +
arch/arm/boot/dts/imx7s.dtsi | 1 +
drivers/net/ethernet/freescale/fec_main.c | 103 +++++++---------------
8 files changed, 47 insertions(+), 72 deletions(-)
--
2.7.4
^ permalink raw reply
* Re: [PATCH v3 7/7] iommu/mediatek: Add mt6779 basic support
From: Yong Wu @ 2020-05-25 6:54 UTC (permalink / raw)
To: Chao Hao
Cc: Joerg Roedel, Rob Herring, Matthias Brugger, iommu, devicetree,
linux-kernel, linux-arm-kernel, linux-mediatek, wsd_upstream,
FY Yang, Jun Yan
In-Reply-To: <20200509083654.5178-8-chao.hao@mediatek.com>
On Sat, 2020-05-09 at 16:36 +0800, Chao Hao wrote:
> 1. Start from mt6779, INVLDT_SEL move to offset=0x2c, so we add
> REG_MMU_INV_SEL_GEN2 definition and mt6779 uses it.
> 2. Change PROTECT_PA_ALIGN from 128 byte to 256 byte.
> 3. For REG_MMU_CTRL_REG register, we only need to change bit[2:0],
> others bits keep default value, ex: enable victim tlb.
> 4. Add mt6779_data to support mm_iommu HW init.
>
> Signed-off-by: Chao Hao <chao.hao@mediatek.com>
> ---
> drivers/iommu/mtk_iommu.c | 18 +++++++++++++++---
> drivers/iommu/mtk_iommu.h | 1 +
> 2 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index dc9ae944e712..34c4ffb77c73 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -37,6 +37,7 @@
> #define REG_MMU_INVLD_START_A 0x024
> #define REG_MMU_INVLD_END_A 0x028
>
> +#define REG_MMU_INV_SEL_GEN2 0x02c
> #define REG_MMU_INV_SEL_GEN1 0x038
Normally the register name comes from the CODA. In the lasted CODA,
this is called "MMU_INVLDT_SEL". But it's same with the previous 0x38
totally. Using _GEN1, _GEN2 is ok for me. Please add its coda name in
the comment. like:
#define REG_MMU_INV_SEL_GEN2 0x02c /* MMU_INVLDT_SEL */
> #define F_INVLD_EN0 BIT(0)
> #define F_INVLD_EN1 BIT(1)
> @@ -97,7 +98,7 @@
> #define F_MMU_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
> #define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)
>
> -#define MTK_PROTECT_PA_ALIGN 128
> +#define MTK_PROTECT_PA_ALIGN 256
>
> /*
> * Get the local arbiter ID and the portid within the larb arbiter
> @@ -554,11 +555,12 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> return ret;
> }
>
> + regval = readl_relaxed(data->base + REG_MMU_CTRL_REG);
> if (data->plat_data->m4u_plat == M4U_MT8173)
> - regval = F_MMU_PREFETCH_RT_REPLACE_MOD |
> + regval |= F_MMU_PREFETCH_RT_REPLACE_MOD |
The default value is not ok for mt8173(Its bit9 is in_order_write_en, we
could not use its default 1'b1). thus, Don't touch this line.
> F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173;
> else
> - regval = F_MMU_TF_PROT_TO_PROGRAM_ADDR;
> + regval |= F_MMU_TF_PROT_TO_PROGRAM_ADDR;
> writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
>
> regval = F_L2_MULIT_HIT_EN |
> @@ -804,6 +806,15 @@ static const struct mtk_iommu_plat_data mt2712_data = {
> .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}},
> };
>
> +static const struct mtk_iommu_plat_data mt6779_data = {
> + .m4u_plat = M4U_MT6779,
> + .larbid_remap = {{0}, {1}, {2}, {3}, {5}, {7, 8}, {10}, {9}},
> + .has_sub_comm = true,
> + .has_wr_len = true,
> + .has_misc_ctrl = true,
> + .inv_sel_reg = REG_MMU_INV_SEL_GEN2,
align '=' a bit.
> +};
> +
> static const struct mtk_iommu_plat_data mt8173_data = {
> .m4u_plat = M4U_MT8173,
> .has_4gb_mode = true,
> @@ -822,6 +833,7 @@ static const struct mtk_iommu_plat_data mt8183_data = {
>
> static const struct of_device_id mtk_iommu_of_ids[] = {
> { .compatible = "mediatek,mt2712-m4u", .data = &mt2712_data},
> + { .compatible = "mediatek,mt6779-m4u", .data = &mt6779_data},
> { .compatible = "mediatek,mt8173-m4u", .data = &mt8173_data},
> { .compatible = "mediatek,mt8183-m4u", .data = &mt8183_data},
> {}
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index 9971cedd72ea..fb79e710c8d9 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -31,6 +31,7 @@ struct mtk_iommu_suspend_reg {
> enum mtk_iommu_plat {
> M4U_MT2701,
> M4U_MT2712,
> + M4U_MT6779,
> M4U_MT8173,
> M4U_MT8183,
> };
^ permalink raw reply
* Re: [PATCH 3/3] usb: dwc3: keystone: Turn on USB3 PHY before controller
From: Roger Quadros @ 2020-05-25 6:41 UTC (permalink / raw)
To: Felipe Balbi, Chunfeng Yun
Cc: robh+dt, vigneshr, linux-usb, devicetree, linux-kernel
In-Reply-To: <debe1c1d-8e84-8047-d387-42d4f6e03f91@ti.com>
On 25/05/2020 09:39, Roger Quadros wrote:
> Felipe,
>
> On 14/05/2020 13:21, Felipe Balbi wrote:
>> Roger Quadros <rogerq@ti.com> writes:
>>
>>> On 14/05/2020 04:37, Chunfeng Yun wrote:
>>>> On Wed, 2020-05-13 at 16:07 +0300, Roger Quadros wrote:
>>>>> The Local Power Sleep Controller (LPSC) dependency on AM65
>>>>> requires SERDES0 to be powered on before USB.
>>>>>
>>>>> We need to power up SERDES0 power domain and hold it on
>>>>> throughout the reset, init, power on sequence.
>>>>>
>>>>> Signed-off-by: Roger Quadros <rogerq@ti.com>
>>>>> ---
>>>>> drivers/usb/dwc3/dwc3-keystone.c | 47 +++++++++++++++++++++++++++++++-
>>>>> 1 file changed, 46 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c
>>>>> index 1e14a6f4884b..46d46f3507fc 100644
>>>>> --- a/drivers/usb/dwc3/dwc3-keystone.c
>>>>> +++ b/drivers/usb/dwc3/dwc3-keystone.c
>>>>> @@ -14,6 +14,7 @@
>>>>> #include <linux/dma-mapping.h>
>>>>> #include <linux/io.h>
>>>>> #include <linux/of_platform.h>
>>>>> +#include <linux/phy/phy.h>
>>>>> #include <linux/pm_runtime.h>
>>>>> /* USBSS register offsets */
>>>>> @@ -34,6 +35,7 @@
>>>>> struct dwc3_keystone {
>>>>> struct device *dev;
>>>>> void __iomem *usbss;
>>>>> + struct phy *usb3_phy;
>>>>> };
>>>>> static inline u32 kdwc3_readl(void __iomem *base, u32 offset)
>>>>> @@ -95,8 +97,44 @@ static int kdwc3_probe(struct platform_device *pdev)
>>>>> if (IS_ERR(kdwc->usbss))
>>>>> return PTR_ERR(kdwc->usbss);
>>>>> - pm_runtime_enable(kdwc->dev);
>>>>> + /* PSC dependency on AM65 needs SERDES0 to be powered before USB0 */
>>>>> + kdwc->usb3_phy = devm_phy_get(dev, "usb3-phy");
>>>> Use devm_phy_optional_get() instead?
>>>
>>> Indeed, it seems better suited.
>>
>> patches 1 and 2 are in testing/next
>>
>
> Could you please drop them as I need to make changes to make the PHY optional.
> I will send v2 of entire series.
Actually only patch 2 and 3 need to be revised. Patch 1 is fine.
cheers,
-roger
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
^ permalink raw reply
* Re: [PATCH 3/3] usb: dwc3: keystone: Turn on USB3 PHY before controller
From: Roger Quadros @ 2020-05-25 6:39 UTC (permalink / raw)
To: Felipe Balbi, Chunfeng Yun
Cc: robh+dt, vigneshr, linux-usb, devicetree, linux-kernel
In-Reply-To: <87tv0i4y0v.fsf@kernel.org>
Felipe,
On 14/05/2020 13:21, Felipe Balbi wrote:
> Roger Quadros <rogerq@ti.com> writes:
>
>> On 14/05/2020 04:37, Chunfeng Yun wrote:
>>> On Wed, 2020-05-13 at 16:07 +0300, Roger Quadros wrote:
>>>> The Local Power Sleep Controller (LPSC) dependency on AM65
>>>> requires SERDES0 to be powered on before USB.
>>>>
>>>> We need to power up SERDES0 power domain and hold it on
>>>> throughout the reset, init, power on sequence.
>>>>
>>>> Signed-off-by: Roger Quadros <rogerq@ti.com>
>>>> ---
>>>> drivers/usb/dwc3/dwc3-keystone.c | 47 +++++++++++++++++++++++++++++++-
>>>> 1 file changed, 46 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c
>>>> index 1e14a6f4884b..46d46f3507fc 100644
>>>> --- a/drivers/usb/dwc3/dwc3-keystone.c
>>>> +++ b/drivers/usb/dwc3/dwc3-keystone.c
>>>> @@ -14,6 +14,7 @@
>>>> #include <linux/dma-mapping.h>
>>>> #include <linux/io.h>
>>>> #include <linux/of_platform.h>
>>>> +#include <linux/phy/phy.h>
>>>> #include <linux/pm_runtime.h>
>>>>
>>>> /* USBSS register offsets */
>>>> @@ -34,6 +35,7 @@
>>>> struct dwc3_keystone {
>>>> struct device *dev;
>>>> void __iomem *usbss;
>>>> + struct phy *usb3_phy;
>>>> };
>>>>
>>>> static inline u32 kdwc3_readl(void __iomem *base, u32 offset)
>>>> @@ -95,8 +97,44 @@ static int kdwc3_probe(struct platform_device *pdev)
>>>> if (IS_ERR(kdwc->usbss))
>>>> return PTR_ERR(kdwc->usbss);
>>>>
>>>> - pm_runtime_enable(kdwc->dev);
>>>> + /* PSC dependency on AM65 needs SERDES0 to be powered before USB0 */
>>>> + kdwc->usb3_phy = devm_phy_get(dev, "usb3-phy");
>>> Use devm_phy_optional_get() instead?
>>
>> Indeed, it seems better suited.
>
> patches 1 and 2 are in testing/next
>
Could you please drop them as I need to make changes to make the PHY optional.
I will send v2 of entire series.
cheers,
-roger
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
^ permalink raw reply
* Re: [PATCH v3 5/7] iommu/mediatek: Add sub_comm id in translation fault
From: Yong Wu @ 2020-05-25 6:31 UTC (permalink / raw)
To: Chao Hao
Cc: Joerg Roedel, Rob Herring, Matthias Brugger, iommu, devicetree,
linux-kernel, linux-arm-kernel, linux-mediatek, wsd_upstream,
FY Yang, Jun Yan
In-Reply-To: <20200509083654.5178-6-chao.hao@mediatek.com>
On Sat, 2020-05-09 at 16:36 +0800, Chao Hao wrote:
> The max larb number that a iommu HW support is 8(larb0~larb7 in the below
> diagram).
> If the larb's number is over 8, we use a sub_common for merging
> several larbs into one larb. At this case, we will extend larb_id:
> bit[11:9] means common-id;
> bit[8:7] means subcommon-id;
> From these two variable, we could get the real larb number when
> translation fault happen.
> The diagram is as below:
> EMI
> |
> IOMMU
> |
> -----------------
> | |
> common1 common0
> | |
> -----------------
> |
> smi common
> |
> ------------------------------------
> | | | | | |
> 3'd0 3'd1 3'd2 3'd3 ... 3'd7 <-common_id(max is 8)
> | | | | | |
> Larb0 Larb1 | Larb3 ... Larb7
> |
> smi sub common
> |
> --------------------------
> | | | |
> 2'd0 2'd1 2'd2 2'd3 <-sub_common_id(max is 4)
> | | | |
> Larb8 Larb9 Larb10 Larb11
>
> In this patch we extern larb_remap[] to larb_remap[8][4] for this.
> larb_remap[x][y]: x mean common-id above, y means subcommon_id above.
>
> We can also distinguish if the M4U HW has sub_common by has_sub_comm
> property.
>
> Signed-off-by: Chao Hao <chao.hao@mediatek.com>
> ---
> drivers/iommu/mtk_iommu.c | 20 +++++++++++++-------
> drivers/iommu/mtk_iommu.h | 3 ++-
> 2 files changed, 15 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index d73de987f8be..3914c418d1b0 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -90,6 +90,8 @@
> #define REG_MMU1_INVLD_PA 0x148
> #define REG_MMU0_INT_ID 0x150
> #define REG_MMU1_INT_ID 0x154
> +#define F_MMU_INT_ID_COMM_ID(a) (((a) >> 9) & 0x7)
> +#define F_MMU_INT_ID_SUB_COMM_ID(a) (((a) >> 7) & 0x3)
> #define F_MMU_INT_ID_LARB_ID(a) (((a) >> 7) & 0x7)
> #define F_MMU_INT_ID_PORT_ID(a) (((a) >> 2) & 0x1f)
>
> @@ -228,7 +230,7 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
> struct mtk_iommu_data *data = dev_id;
> struct mtk_iommu_domain *dom = data->m4u_dom;
> u32 int_state, regval, fault_iova, fault_pa;
> - unsigned int fault_larb, fault_port;
> + unsigned int fault_larb, fault_port, sub_comm = 0;
> bool layer, write;
>
> /* Read error info from registers */
> @@ -244,10 +246,14 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
> }
> layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT;
> write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
> - fault_larb = F_MMU_INT_ID_LARB_ID(regval);
> fault_port = F_MMU_INT_ID_PORT_ID(regval);
> -
> - fault_larb = data->plat_data->larbid_remap[fault_larb];
> + if (data->plat_data->has_sub_comm) {
> + fault_larb = F_MMU_INT_ID_COMM_ID(regval);
> + sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval);
> + } else {
> + fault_larb = F_MMU_INT_ID_LARB_ID(regval);
> + }
> + fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm];
>
> if (report_iommu_fault(&dom->domain, data->dev, fault_iova,
> write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
> @@ -785,7 +791,7 @@ static const struct mtk_iommu_plat_data mt2712_data = {
> .has_bclk = true,
> .has_vld_pa_rng = true,
> .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
> - .larbid_remap = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
> + .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}},
The original mt2712 has 10 larbs, but it actually has 2 IOMMU HWs.
For each a smi-common, The max larb number could only be 8. So it is
right here.
Thus,
Reviewed-by: Yong Wu <yong.wu@mediatek.com>
> };
>
> static const struct mtk_iommu_plat_data mt8173_data = {
> @@ -794,14 +800,14 @@ static const struct mtk_iommu_plat_data mt8173_data = {
> .has_bclk = true,
> .reset_axi = true,
> .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
> - .larbid_remap = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
> + .larbid_remap = {{0}, {1}, {2}, {3}, {4}, {5}}, /* Linear mapping. */
> };
>
> static const struct mtk_iommu_plat_data mt8183_data = {
> .m4u_plat = M4U_MT8183,
> .reset_axi = true,
> .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
> - .larbid_remap = {0, 4, 5, 6, 7, 2, 3, 1},
> + .larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}},
> };
>
> static const struct of_device_id mtk_iommu_of_ids[] = {
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index afd7a2de5c1e..d51ff99c2c71 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -41,10 +41,11 @@ struct mtk_iommu_plat_data {
> /* HW will use the EMI clock if there isn't the "bclk". */
> bool has_bclk;
> bool has_misc_ctrl;
> + bool has_sub_comm;
> bool has_vld_pa_rng;
> bool reset_axi;
> u32 inv_sel_reg;
> - unsigned char larbid_remap[MTK_LARB_NR_MAX];
> + unsigned char larbid_remap[8][4];
> };
>
> struct mtk_iommu_domain;
^ permalink raw reply
* Re: [PATCH v3 4/7] iommu/mediatek: Move inv_sel_reg into the plat_data
From: Yong Wu @ 2020-05-25 6:22 UTC (permalink / raw)
To: Chao Hao
Cc: Joerg Roedel, Rob Herring, Matthias Brugger, iommu, devicetree,
linux-kernel, linux-arm-kernel, linux-mediatek, wsd_upstream,
FY Yang, Jun Yan
In-Reply-To: <20200509083654.5178-5-chao.hao@mediatek.com>
On Sat, 2020-05-09 at 16:36 +0800, Chao Hao wrote:
> For mt6779, MMU_INVLDT_SEL register's offset is changed from
At this patch, the register is still called by "MMU_INV_SEL".
> 0x38 to 0x2c, so we can put inv_sel_reg in the plat_data to
> use it.
> In addition, we renamed it to REG_MMU_INV_SEL_GEN1 and use it
> before mt6779.
>
> Signed-off-by: Chao Hao <chao.hao@mediatek.com>
> ---
> drivers/iommu/mtk_iommu.c | 9 ++++++---
> drivers/iommu/mtk_iommu.h | 1 +
> 2 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 9ede327a418d..d73de987f8be 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -37,7 +37,7 @@
> #define REG_MMU_INVLD_START_A 0x024
> #define REG_MMU_INVLD_END_A 0x028
>
> -#define REG_MMU_INV_SEL 0x038
> +#define REG_MMU_INV_SEL_GEN1 0x038
> #define F_INVLD_EN0 BIT(0)
> #define F_INVLD_EN1 BIT(1)
>
> @@ -167,7 +167,7 @@ static void mtk_iommu_tlb_flush_all(void *cookie)
>
> for_each_m4u(data) {
> writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
> - data->base + REG_MMU_INV_SEL);
> + data->base + data->plat_data->inv_sel_reg);
> writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
> wmb(); /* Make sure the tlb flush all done */
> }
> @@ -184,7 +184,7 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
> for_each_m4u(data) {
> spin_lock_irqsave(&data->tlb_lock, flags);
> writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
> - data->base + REG_MMU_INV_SEL);
> + data->base + data->plat_data->inv_sel_reg);
>
> writel_relaxed(iova, data->base + REG_MMU_INVLD_START_A);
> writel_relaxed(iova + size - 1,
> @@ -784,6 +784,7 @@ static const struct mtk_iommu_plat_data mt2712_data = {
> .has_4gb_mode = true,
> .has_bclk = true,
> .has_vld_pa_rng = true,
> + .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
nitpick: align '=' with the next line.
> .larbid_remap = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
> };
>
> @@ -792,12 +793,14 @@ static const struct mtk_iommu_plat_data mt8173_data = {
> .has_4gb_mode = true,
> .has_bclk = true,
> .reset_axi = true,
> + .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
align '='
> .larbid_remap = {0, 1, 2, 3, 4, 5}, /* Linear mapping. */
> };
>
> static const struct mtk_iommu_plat_data mt8183_data = {
> .m4u_plat = M4U_MT8183,
> .reset_axi = true,
> + .inv_sel_reg = REG_MMU_INV_SEL_GEN1,
> .larbid_remap = {0, 4, 5, 6, 7, 2, 3, 1},
> };
>
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index d711ac630037..afd7a2de5c1e 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -43,6 +43,7 @@ struct mtk_iommu_plat_data {
> bool has_misc_ctrl;
> bool has_vld_pa_rng;
> bool reset_axi;
> + u32 inv_sel_reg;
> unsigned char larbid_remap[MTK_LARB_NR_MAX];
> };
>
^ permalink raw reply
* Re: [PATCH v3 3/7] iommu/mediatek: Disable STANDARD_AXI_MODE in MISC_CTRL
From: Yong Wu @ 2020-05-25 6:14 UTC (permalink / raw)
To: Chao Hao
Cc: Joerg Roedel, Rob Herring, Matthias Brugger, iommu, devicetree,
linux-kernel, linux-arm-kernel, linux-mediatek, wsd_upstream,
FY Yang, Jun Yan
In-Reply-To: <20200509083654.5178-4-chao.hao@mediatek.com>
On Sat, 2020-05-09 at 16:36 +0800, Chao Hao wrote:
> In order to improve performance, we always disable STANDARD_AXI_MODE in
> MISC_CTRL.
>
> Signed-off-by: Chao Hao <chao.hao@mediatek.com>
> ---
> drivers/iommu/mtk_iommu.c | 8 +++++++-
> drivers/iommu/mtk_iommu.h | 1 +
> 2 files changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index e7e7c7695ed1..9ede327a418d 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -42,6 +42,8 @@
> #define F_INVLD_EN1 BIT(1)
>
> #define REG_MMU_MISC_CTRL 0x048
> +#define F_MMU_STANDARD_AXI_MODE_BIT (BIT(3) | BIT(19))
> +
> #define REG_MMU_DCM_DIS 0x050
>
> #define REG_MMU_CTRL_REG 0x110
> @@ -585,7 +587,11 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> }
> writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
>
> - if (data->plat_data->reset_axi) {
> + if (data->plat_data->has_misc_ctrl) {
> + regval = readl_relaxed(data->base + REG_MMU_MISC_CTRL);
> + regval &= ~F_MMU_STANDARD_AXI_MODE_BIT;
> + writel_relaxed(regval, data->base + REG_MMU_MISC_CTRL);
> + } else if (data->plat_data->reset_axi) {
> /* The register is called STANDARD_AXI_MODE in this case */
> writel_relaxed(0, data->base + REG_MMU_MISC_CTRL);
> }
0x48 is either STANDARD_AXI_MODE or MISC_CTRL.
Thus,
if (data->plat_data->reset_axi) {
xxx
} else { /* MISC_CTRL */
xxx
}
No need add "has_misc_ctrl".
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index 1b6ea839b92c..d711ac630037 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -40,6 +40,7 @@ struct mtk_iommu_plat_data {
>
> /* HW will use the EMI clock if there isn't the "bclk". */
> bool has_bclk;
> + bool has_misc_ctrl;
> bool has_vld_pa_rng;
> bool reset_axi;
> unsigned char larbid_remap[MTK_LARB_NR_MAX];
^ permalink raw reply
* Re: [PATCH v3 2/7] iommu/mediatek: Rename the register STANDARD_AXI_MODE(0x48) to MISC_CTRL
From: Yong Wu @ 2020-05-25 6:11 UTC (permalink / raw)
To: Chao Hao
Cc: Joerg Roedel, Rob Herring, Matthias Brugger, iommu, devicetree,
linux-kernel, linux-arm-kernel, linux-mediatek, wsd_upstream,
FY Yang, Jun Yan
In-Reply-To: <20200509083654.5178-3-chao.hao@mediatek.com>
On Sat, 2020-05-09 at 16:36 +0800, Chao Hao wrote:
> For iommu offset=0x48 register, only the previous mt8173/mt8183 use the
> name STANDARD_AXI_MODE, all the latest SoC extend the register more
> feature by different bits, for example: axi_mode, in_order_en, coherent_en
> and so on. So rename REG_MMU_MISC_CTRL may be more proper.
>
> This patch only rename the register name, no functional change.
>
> Signed-off-by: Chao Hao <chao.hao@mediatek.com>
Reviewed-by: Yong Wu <yong.wu@mediatek.com>
> ---
> drivers/iommu/mtk_iommu.c | 14 +++++++-------
> drivers/iommu/mtk_iommu.h | 2 +-
> 2 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 5f4d6df59cf6..e7e7c7695ed1 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -41,7 +41,7 @@
> #define F_INVLD_EN0 BIT(0)
> #define F_INVLD_EN1 BIT(1)
>
> -#define REG_MMU_STANDARD_AXI_MODE 0x048
> +#define REG_MMU_MISC_CTRL 0x048
> #define REG_MMU_DCM_DIS 0x050
>
> #define REG_MMU_CTRL_REG 0x110
> @@ -585,8 +585,10 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
> }
> writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
>
> - if (data->plat_data->reset_axi)
> - writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE);
> + if (data->plat_data->reset_axi) {
> + /* The register is called STANDARD_AXI_MODE in this case */
> + writel_relaxed(0, data->base + REG_MMU_MISC_CTRL);
> + }
>
> if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
> dev_name(data->dev), (void *)data)) {
> @@ -730,8 +732,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device *dev)
> struct mtk_iommu_suspend_reg *reg = &data->reg;
> void __iomem *base = data->base;
>
> - reg->standard_axi_mode = readl_relaxed(base +
> - REG_MMU_STANDARD_AXI_MODE);
> + reg->misc_ctrl = readl_relaxed(base + REG_MMU_MISC_CTRL);
> reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM_DIS);
> reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG);
> reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0);
> @@ -755,8 +756,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
> dev_err(data->dev, "Failed to enable clk(%d) in resume\n", ret);
> return ret;
> }
> - writel_relaxed(reg->standard_axi_mode,
> - base + REG_MMU_STANDARD_AXI_MODE);
> + writel_relaxed(reg->misc_ctrl, base + REG_MMU_MISC_CTRL);
> writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS);
> writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG);
> writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
> diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
> index ea949a324e33..1b6ea839b92c 100644
> --- a/drivers/iommu/mtk_iommu.h
> +++ b/drivers/iommu/mtk_iommu.h
> @@ -18,7 +18,7 @@
> #include <soc/mediatek/smi.h>
>
> struct mtk_iommu_suspend_reg {
> - u32 standard_axi_mode;
> + u32 misc_ctrl;
> u32 dcm_dis;
> u32 ctrl_reg;
> u32 int_control0;
^ permalink raw reply
* Re: [PATCH V2 3/3] mmc: sdhci: Allow platform controlled voltage switching
From: Adrian Hunter @ 2020-05-25 5:42 UTC (permalink / raw)
To: Veerabhadrarao Badiganti, ulf.hansson, bjorn.andersson, robh+dt
Cc: linux-mmc, linux-kernel, linux-arm-msm, devicetree,
Vijay Viswanath
In-Reply-To: <1590074615-10787-4-git-send-email-vbadigan@codeaurora.org>
On 21/05/20 6:23 pm, Veerabhadrarao Badiganti wrote:
> From: Vijay Viswanath <vviswana@codeaurora.org>
>
> If vendor platform drivers are controlling whole logic of voltage
> switching, then sdhci driver no need control vqmmc regulator.
> So skip enabling/disable vqmmc from SDHC driver.
>
> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
> Signed-off-by: Veerabhadrarao Badiganti <vbadigan@codeaurora.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
> drivers/mmc/host/sdhci.c | 32 +++++++++++++++++++-------------
> drivers/mmc/host/sdhci.h | 1 +
> 2 files changed, 20 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 1bb6b67..88e5312 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -4098,6 +4098,7 @@ int sdhci_setup_host(struct sdhci_host *host)
> unsigned int override_timeout_clk;
> u32 max_clk;
> int ret;
> + bool enable_vqmmc = false;
>
> WARN_ON(host == NULL);
> if (host == NULL)
> @@ -4111,9 +4112,12 @@ int sdhci_setup_host(struct sdhci_host *host)
> * the host can take the appropriate action if regulators are not
> * available.
> */
> - ret = mmc_regulator_get_supply(mmc);
> - if (ret)
> - return ret;
> + if (!mmc->supply.vqmmc) {
> + ret = mmc_regulator_get_supply(mmc);
> + if (ret)
> + return ret;
> + enable_vqmmc = true;
> + }
>
> DBG("Version: 0x%08x | Present: 0x%08x\n",
> sdhci_readw(host, SDHCI_HOST_VERSION),
> @@ -4373,7 +4377,15 @@ int sdhci_setup_host(struct sdhci_host *host)
> mmc->caps |= MMC_CAP_NEEDS_POLL;
>
> if (!IS_ERR(mmc->supply.vqmmc)) {
> - ret = regulator_enable(mmc->supply.vqmmc);
> + if (enable_vqmmc) {
> + ret = regulator_enable(mmc->supply.vqmmc);
> + if (ret) {
> + pr_warn("%s: Failed to enable vqmmc regulator: %d\n",
> + mmc_hostname(mmc), ret);
> + mmc->supply.vqmmc = ERR_PTR(-EINVAL);
> + }
> + host->sdhci_core_to_disable_vqmmc = !ret;
> + }
>
> /* If vqmmc provides no 1.8V signalling, then there's no UHS */
> if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
> @@ -4386,12 +4398,6 @@ int sdhci_setup_host(struct sdhci_host *host)
> if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 2700000,
> 3600000))
> host->flags &= ~SDHCI_SIGNALING_330;
> -
> - if (ret) {
> - pr_warn("%s: Failed to enable vqmmc regulator: %d\n",
> - mmc_hostname(mmc), ret);
> - mmc->supply.vqmmc = ERR_PTR(-EINVAL);
> - }
> }
>
> if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V) {
> @@ -4625,7 +4631,7 @@ int sdhci_setup_host(struct sdhci_host *host)
> return 0;
>
> unreg:
> - if (!IS_ERR(mmc->supply.vqmmc))
> + if (host->sdhci_core_to_disable_vqmmc)
> regulator_disable(mmc->supply.vqmmc);
> undma:
> if (host->align_buffer)
> @@ -4643,7 +4649,7 @@ void sdhci_cleanup_host(struct sdhci_host *host)
> {
> struct mmc_host *mmc = host->mmc;
>
> - if (!IS_ERR(mmc->supply.vqmmc))
> + if (host->sdhci_core_to_disable_vqmmc)
> regulator_disable(mmc->supply.vqmmc);
>
> if (host->align_buffer)
> @@ -4780,7 +4786,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
>
> destroy_workqueue(host->complete_wq);
>
> - if (!IS_ERR(mmc->supply.vqmmc))
> + if (host->sdhci_core_to_disable_vqmmc)
> regulator_disable(mmc->supply.vqmmc);
>
> if (host->align_buffer)
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 8d2a096..c7dbc68 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -570,6 +570,7 @@ struct sdhci_host {
> u32 caps1; /* CAPABILITY_1 */
> bool read_caps; /* Capability flags have been read */
>
> + bool sdhci_core_to_disable_vqmmc; /* sdhci core can disable vqmmc */
> unsigned int ocr_avail_sdio; /* OCR bit masks */
> unsigned int ocr_avail_sd;
> unsigned int ocr_avail_mmc;
>
^ permalink raw reply
* [PATCH v2 2/9] irqchip/sun6i-r: Add wakeup support
From: Samuel Holland @ 2020-05-25 4:12 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
Maxime Ripard, Chen-Yu Tsai, Russell King, Catalin Marinas,
Will Deacon
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
Samuel Holland
In-Reply-To: <20200525041302.51213-1-samuel@sholland.org>
Maintain a mask of wake-enabled IRQs, and enable them in hardware
during the syscore phase of suspend. The restore the original mask
of enabled IRQs (just the NMI) during resume.
This serves two purposes. First, it lets power management firmware
running on the ARISC coprocessor know which wakeup sources Linux wants
to have enabled. That way, it can avoid turning them off when it shuts
down the remainder of the clock tree. Second, it preconfigures the
coprocessor's interrupt controller, so the firmware's wakeup logic
is as simple as waiting for an interrupt to arrive.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/irqchip/irq-sun6i-r.c | 51 +++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/drivers/irqchip/irq-sun6i-r.c b/drivers/irqchip/irq-sun6i-r.c
index f8bfa5515f20..a5deea92057f 100644
--- a/drivers/irqchip/irq-sun6i-r.c
+++ b/drivers/irqchip/irq-sun6i-r.c
@@ -3,12 +3,14 @@
// Allwinner A31 and newer SoCs R_INTC driver
//
+#include <linux/atomic.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/syscore_ops.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -24,6 +26,9 @@
static void __iomem *base;
static irq_hw_number_t parent_offset;
static u32 parent_type;
+#ifdef CONFIG_PM_SLEEP
+static atomic_t wake_mask;
+#endif
static struct irq_chip sun6i_r_intc_edge;
static struct irq_chip sun6i_r_intc_level;
@@ -106,6 +111,20 @@ static int sun6i_r_intc_irq_set_type(struct irq_data *data, unsigned int type)
return irq_chip_set_type_parent(data, type);
}
+#ifdef CONFIG_PM_SLEEP
+static int sun6i_r_intc_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+ if (on)
+ atomic_or(BIT(data->hwirq), &wake_mask);
+ else
+ atomic_andnot(BIT(data->hwirq), &wake_mask);
+
+ return 0;
+}
+#else
+#define sun6i_r_intc_irq_set_wake NULL
+#endif
+
static struct irq_chip sun6i_r_intc_edge = {
.name = "sun6i-r-intc",
.irq_ack = sun6i_r_intc_irq_ack,
@@ -116,6 +135,7 @@ static struct irq_chip sun6i_r_intc_edge = {
.irq_set_type = sun6i_r_intc_irq_set_type,
.irq_get_irqchip_state = irq_chip_get_parent_state,
.irq_set_irqchip_state = irq_chip_set_parent_state,
+ .irq_set_wake = sun6i_r_intc_irq_set_wake,
.irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
.flags = IRQCHIP_SET_TYPE_MASKED,
};
@@ -129,6 +149,7 @@ static struct irq_chip sun6i_r_intc_level = {
.irq_set_type = sun6i_r_intc_irq_set_type,
.irq_get_irqchip_state = irq_chip_get_parent_state,
.irq_set_irqchip_state = irq_chip_set_parent_state,
+ .irq_set_wake = sun6i_r_intc_irq_set_wake,
.irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
.flags = IRQCHIP_SET_TYPE_MASKED |
IRQCHIP_EOI_THREADED,
@@ -170,6 +191,34 @@ static const struct irq_domain_ops sun6i_r_intc_domain_ops = {
.free = irq_domain_free_irqs_common,
};
+#ifdef CONFIG_PM_SLEEP
+static int sun6i_r_intc_suspend(void)
+{
+ /* All wake IRQs are enabled during system sleep. */
+ writel_relaxed(atomic_read(&wake_mask), base + SUN6I_R_INTC_ENABLE);
+
+ return 0;
+}
+
+static void sun6i_r_intc_resume(void)
+{
+ /* Only the NMI is relevant during normal operation. */
+ writel_relaxed(NMI_HWIRQ_BIT, base + SUN6I_R_INTC_ENABLE);
+}
+
+static struct syscore_ops sun6i_r_intc_syscore_ops = {
+ .suspend = sun6i_r_intc_suspend,
+ .resume = sun6i_r_intc_resume,
+};
+
+static void sun6i_r_intc_syscore_init(void)
+{
+ register_syscore_ops(&sun6i_r_intc_syscore_ops);
+}
+#else
+static inline void sun6i_r_intc_syscore_init(void) {}
+#endif
+
static int __init sun6i_r_intc_init(struct device_node *node,
struct device_node *parent)
{
@@ -211,6 +260,8 @@ static int __init sun6i_r_intc_init(struct device_node *node,
writel_relaxed(NMI_HWIRQ_BIT, base + SUN6I_R_INTC_PENDING);
writel_relaxed(NMI_HWIRQ_BIT, base + SUN6I_R_INTC_ENABLE);
+ sun6i_r_intc_syscore_init();
+
return 0;
}
IRQCHIP_DECLARE(sun6i_r_intc, "allwinner,sun6i-a31-r-intc", sun6i_r_intc_init);
--
2.24.1
^ permalink raw reply related
* [PATCH v2 4/9] ARM: dts: sunxi: h3/h5: Add r_intc node
From: Samuel Holland @ 2020-05-25 4:12 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
Maxime Ripard, Chen-Yu Tsai, Russell King, Catalin Marinas,
Will Deacon
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
Samuel Holland
In-Reply-To: <20200525041302.51213-1-samuel@sholland.org>
The H3 and H5 SoCs have an additional interrupt controller in the RTC
power domain that can be used to enable wakeup for certain IRQs.
Add a node for it.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 01a5df9aa71b..94f648ad1c9e 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -836,6 +836,15 @@ rtc: rtc@1f00000 {
#clock-cells = <1>;
};
+ r_intc: interrupt-controller@1f00c00 {
+ compatible = "allwinner,sun8i-h3-r-intc",
+ "allwinner,sun6i-a31-r-intc";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0x01f00c00 0x400>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
r_ccu: clock@1f01400 {
compatible = "allwinner,sun8i-h3-r-ccu";
reg = <0x01f01400 0x100>;
--
2.24.1
^ permalink raw reply related
* [PATCH v2 1/9] irqchip/sun6i-r: Use a stacked irqchip driver
From: Samuel Holland @ 2020-05-25 4:12 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
Maxime Ripard, Chen-Yu Tsai, Russell King, Catalin Marinas,
Will Deacon
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
Samuel Holland
In-Reply-To: <20200525041302.51213-1-samuel@sholland.org>
The R_INTC in the A31 and newer sun8i/sun50i SoCs is more similar to the
original sun4i interrupt controller than the sun7i/sun9i NMI controller.
It is used for two distinct purposes:
1) To control the trigger, latch, and mask for the NMI input pin
2) To provide the interrupt input for the ARISC coprocessor
As this interrupt controller is not documented, information about it
comes from vendor-provided ARISC firmware and from experimentation.
Like the original sun4i interrupt controller, it has:
- A VECTOR_REG at 0x00 (configurable via the BASE_ADDR_REG at 0x04)
- A NMI_CTRL_REG, PENDING_REG, and ENABLE_REG as used by both the
sun4i and sunxi-nmi drivers
- A MASK_REG at 0x50
- A RESP_REG at 0x60
Differences from the sun4i interrupt controller appear to be:
- It is only known to have one register of each kind (max 32 inputs)
- There is no FIQ-related logic
- There is no interrupt priority logic
In order to fulfill its two purposes, this hardware block combines two
types of IRQs. First, the NMI pin is routed to the "IRQ 0" input on this
chip, with a trigger type controlled by the NMI_CTRL_REG. The "IRQ 0
pending" output from this chip, if enabled, is then routed to a SPI IRQ
input on the GIC, as IRQ_TYPE_LEVEL_HIGH. In other words, bit 0 of
ENABLE_REG *does* affect the NMI IRQ seen at the GIC.
The NMI is then followed by a contiguous block of (at least) 15 IRQ
inputs that are connected in parallel to both R_INTC and the GIC. Or
in other words, the other bits of ENABLE_REG *do not* affect the IRQs
seen at the GIC.
Finally, the global "IRQ pending" output from R_INTC, after being masked
by MASK_REG and RESP_REG, is connected to the "external interrupt" input
of the ARISC CPU (an OR1200). This path is not relevant to Linux.
Because of the 1:1 correspondence between R_INTC and GIC inputs, this is
a perfect scenario for using a stacked irqchip driver. We want to hook
into enabling/disabling IRQs to add more features to the GIC
(specifically to allow masking the NMI and setting its trigger type),
but we don't need to actually handle the IRQ in this driver.
And since R_INTC is in the always-on power domain, and its output is
connected directly in to the power management coprocessor, a stacked
irqchip driver provides a simple way to add wakeup support to this set
of IRQs. That is a future patch; for now, just the NMI is moved over.
This driver keeps the same DT binding as the existing driver. The
"interrupt" property of the R_INTC node is used to determine 1) the
offset between GIC and R_INTC hwirq numbers and 2) the type of trigger
between the R_INTC "IRQ 0 pending" output and the GIC NMI input.
This commit mostly reverts commit 173bda53b340 ("irqchip/sunxi-nmi:
Support sun6i-a31-r-intc compatible").
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/mach-sunxi/Kconfig | 4 +
arch/arm64/Kconfig.platforms | 2 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-sun6i-r.c | 216 ++++++++++++++++++++++++++++++++
drivers/irqchip/irq-sunxi-nmi.c | 26 +---
5 files changed, 226 insertions(+), 23 deletions(-)
create mode 100644 drivers/irqchip/irq-sun6i-r.c
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index eeadb1a4dcfe..216b5954d6a9 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -30,6 +30,8 @@ config MACH_SUN6I
bool "Allwinner A31 (sun6i) SoCs support"
default ARCH_SUNXI
select ARM_GIC
+ select IRQ_DOMAIN_HIERARCHY
+ select IRQ_FASTEOI_HIERARCHY_HANDLERS
select MFD_SUN6I_PRCM
select SUN5I_HSTIMER
@@ -46,6 +48,8 @@ config MACH_SUN8I
bool "Allwinner sun8i Family SoCs support"
default ARCH_SUNXI
select ARM_GIC
+ select IRQ_DOMAIN_HIERARCHY
+ select IRQ_FASTEOI_HIERARCHY_HANDLERS
select MFD_SUN6I_PRCM
config MACH_SUN9I
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 55d70cfe0f9e..b9c3a7118a2c 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -17,6 +17,8 @@ config ARCH_SUNXI
bool "Allwinner sunxi 64-bit SoC Family"
select ARCH_HAS_RESET_CONTROLLER
select GENERIC_IRQ_CHIP
+ select IRQ_DOMAIN_HIERARCHY
+ select IRQ_FASTEOI_HIERARCHY_HANDLERS
select PINCTRL
select RESET_CONTROLLER
help
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 37bbe39bf909..c9692bdaabfa 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_OR1K_PIC) += irq-or1k-pic.o
obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o
obj-$(CONFIG_OMAP_IRQCHIP) += irq-omap-intc.o
obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
+obj-$(CONFIG_ARCH_SUNXI) += irq-sun6i-r.o
obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o
diff --git a/drivers/irqchip/irq-sun6i-r.c b/drivers/irqchip/irq-sun6i-r.c
new file mode 100644
index 000000000000..f8bfa5515f20
--- /dev/null
+++ b/drivers/irqchip/irq-sun6i-r.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Allwinner A31 and newer SoCs R_INTC driver
+//
+
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#define NMI_HWIRQ 0
+#define NMI_HWIRQ_BIT BIT(NMI_HWIRQ)
+
+#define SUN6I_R_INTC_NR_IRQS 16
+
+#define SUN6I_R_INTC_NMI_CTRL 0x0c
+#define SUN6I_R_INTC_PENDING 0x10
+#define SUN6I_R_INTC_ENABLE 0x40
+
+static void __iomem *base;
+static irq_hw_number_t parent_offset;
+static u32 parent_type;
+
+static struct irq_chip sun6i_r_intc_edge;
+static struct irq_chip sun6i_r_intc_level;
+
+static void sun6i_r_intc_nmi_ack(void)
+{
+ /*
+ * The NMI IRQ channel has a latch, separate from its trigger.
+ * This latch must be cleared to clear the output to the GIC.
+ */
+ writel_relaxed(NMI_HWIRQ_BIT, base + SUN6I_R_INTC_PENDING);
+}
+
+static void sun6i_r_intc_irq_ack(struct irq_data *data)
+{
+ if (data->hwirq == NMI_HWIRQ)
+ sun6i_r_intc_nmi_ack();
+}
+
+static void sun6i_r_intc_irq_eoi(struct irq_data *data)
+{
+ if (data->hwirq == NMI_HWIRQ)
+ sun6i_r_intc_nmi_ack();
+
+ irq_chip_eoi_parent(data);
+}
+
+static int sun6i_r_intc_irq_set_type(struct irq_data *data, unsigned int type)
+{
+ /*
+ * Only the NMI IRQ is routed through this interrupt controller on its
+ * way to the GIC. Other IRQs are routed to the GIC in parallel and
+ * must have a trigger type appropriate for the GIC.
+ *
+ * The "External NMI" input to the GIC actually comes from bit 0 of
+ * this device's PENDING register. So the IRQ type of the NMI, as seen
+ * by the GIC, does not depend on the IRQ type of the NMI pin itself.
+ */
+ if (data->hwirq == NMI_HWIRQ) {
+ u32 nmi_src_type;
+
+ switch (type) {
+ case IRQ_TYPE_LEVEL_LOW:
+ nmi_src_type = 0;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ nmi_src_type = 1;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ nmi_src_type = 2;
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ nmi_src_type = 3;
+ break;
+ default:
+ pr_err("%pOF: invalid trigger type %d for IRQ %d\n",
+ irq_domain_get_of_node(data->domain), type,
+ data->irq);
+ return -EBADR;
+ }
+
+ if (type & IRQ_TYPE_EDGE_BOTH) {
+ irq_set_chip_handler_name_locked(data,
+ &sun6i_r_intc_edge,
+ handle_fasteoi_ack_irq,
+ NULL);
+ } else {
+ irq_set_chip_handler_name_locked(data,
+ &sun6i_r_intc_level,
+ handle_fasteoi_irq,
+ NULL);
+ }
+
+ writel_relaxed(nmi_src_type, base + SUN6I_R_INTC_NMI_CTRL);
+
+ /* Send the R_INTC -> GIC trigger type to the GIC driver. */
+ type = parent_type;
+ }
+
+ return irq_chip_set_type_parent(data, type);
+}
+
+static struct irq_chip sun6i_r_intc_edge = {
+ .name = "sun6i-r-intc",
+ .irq_ack = sun6i_r_intc_irq_ack,
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .irq_set_type = sun6i_r_intc_irq_set_type,
+ .irq_get_irqchip_state = irq_chip_get_parent_state,
+ .irq_set_irqchip_state = irq_chip_set_parent_state,
+ .irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
+ .flags = IRQCHIP_SET_TYPE_MASKED,
+};
+
+static struct irq_chip sun6i_r_intc_level = {
+ .name = "sun6i-r-intc",
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_eoi = sun6i_r_intc_irq_eoi,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+ .irq_set_type = sun6i_r_intc_irq_set_type,
+ .irq_get_irqchip_state = irq_chip_get_parent_state,
+ .irq_set_irqchip_state = irq_chip_set_parent_state,
+ .irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent,
+ .flags = IRQCHIP_SET_TYPE_MASKED |
+ IRQCHIP_EOI_THREADED,
+};
+
+static int sun6i_r_intc_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs, void *arg)
+{
+ struct irq_fwspec *fwspec = arg;
+ struct irq_fwspec gic_fwspec;
+ irq_hw_number_t hwirq;
+ unsigned int type;
+ int i, ret;
+
+ ret = irq_domain_translate_twocell(domain, fwspec, &hwirq, &type);
+ if (ret)
+ return ret;
+ if (hwirq + nr_irqs > SUN6I_R_INTC_NR_IRQS)
+ return -EINVAL;
+
+ /* Construct a GIC-compatible fwspec from this fwspec. */
+ gic_fwspec = (struct irq_fwspec) {
+ .fwnode = domain->parent->fwnode,
+ .param_count = 3,
+ .param = { GIC_SPI, parent_offset + hwirq, type },
+ };
+
+ for (i = 0; i < nr_irqs; ++i)
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+ &sun6i_r_intc_level, NULL);
+
+ return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_fwspec);
+}
+
+static const struct irq_domain_ops sun6i_r_intc_domain_ops = {
+ .translate = irq_domain_translate_twocell,
+ .alloc = sun6i_r_intc_domain_alloc,
+ .free = irq_domain_free_irqs_common,
+};
+
+static int __init sun6i_r_intc_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_domain *domain, *parent_domain;
+ struct of_phandle_args parent_irq;
+ int ret;
+
+ /* Extract the R_INTC -> GIC mapping from the OF node. */
+ ret = of_irq_parse_one(node, 0, &parent_irq);
+ if (ret)
+ return ret;
+ if (parent_irq.args_count != 3 || parent_irq.args[0] != GIC_SPI)
+ return -EINVAL;
+ parent_offset = parent_irq.args[1];
+ parent_type = parent_irq.args[2];
+
+ parent_domain = irq_find_host(parent);
+ if (!parent_domain) {
+ pr_err("%pOF: Failed to obtain parent domain\n", node);
+ return -ENXIO;
+ }
+
+ base = of_io_request_and_map(node, 0, NULL);
+ if (IS_ERR(base)) {
+ pr_err("%pOF: Failed to map MMIO region\n", node);
+ return PTR_ERR(base);
+ }
+
+ domain = irq_domain_add_hierarchy(parent_domain, 0,
+ SUN6I_R_INTC_NR_IRQS, node,
+ &sun6i_r_intc_domain_ops, NULL);
+ if (!domain) {
+ pr_err("%pOF: Failed to allocate domain\n", node);
+ iounmap(base);
+ return -ENOMEM;
+ }
+
+ /* Clear and enable the NMI. */
+ writel_relaxed(NMI_HWIRQ_BIT, base + SUN6I_R_INTC_PENDING);
+ writel_relaxed(NMI_HWIRQ_BIT, base + SUN6I_R_INTC_ENABLE);
+
+ return 0;
+}
+IRQCHIP_DECLARE(sun6i_r_intc, "allwinner,sun6i-a31-r-intc", sun6i_r_intc_init);
diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c
index a412b5d5d0fa..9f2bd0c5d289 100644
--- a/drivers/irqchip/irq-sunxi-nmi.c
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -27,18 +27,12 @@
#define SUNXI_NMI_IRQ_BIT BIT(0)
-#define SUN6I_R_INTC_CTRL 0x0c
-#define SUN6I_R_INTC_PENDING 0x10
-#define SUN6I_R_INTC_ENABLE 0x40
-
/*
* For deprecated sun6i-a31-sc-nmi compatible.
- * Registers are offset by 0x0c.
*/
-#define SUN6I_R_INTC_NMI_OFFSET 0x0c
-#define SUN6I_NMI_CTRL (SUN6I_R_INTC_CTRL - SUN6I_R_INTC_NMI_OFFSET)
-#define SUN6I_NMI_PENDING (SUN6I_R_INTC_PENDING - SUN6I_R_INTC_NMI_OFFSET)
-#define SUN6I_NMI_ENABLE (SUN6I_R_INTC_ENABLE - SUN6I_R_INTC_NMI_OFFSET)
+#define SUN6I_NMI_CTRL 0x00
+#define SUN6I_NMI_PENDING 0x04
+#define SUN6I_NMI_ENABLE 0x34
#define SUN7I_NMI_CTRL 0x00
#define SUN7I_NMI_PENDING 0x04
@@ -61,12 +55,6 @@ struct sunxi_sc_nmi_reg_offs {
u32 enable;
};
-static const struct sunxi_sc_nmi_reg_offs sun6i_r_intc_reg_offs __initconst = {
- .ctrl = SUN6I_R_INTC_CTRL,
- .pend = SUN6I_R_INTC_PENDING,
- .enable = SUN6I_R_INTC_ENABLE,
-};
-
static const struct sunxi_sc_nmi_reg_offs sun6i_reg_offs __initconst = {
.ctrl = SUN6I_NMI_CTRL,
.pend = SUN6I_NMI_PENDING,
@@ -232,14 +220,6 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
return ret;
}
-static int __init sun6i_r_intc_irq_init(struct device_node *node,
- struct device_node *parent)
-{
- return sunxi_sc_nmi_irq_init(node, &sun6i_r_intc_reg_offs);
-}
-IRQCHIP_DECLARE(sun6i_r_intc, "allwinner,sun6i-a31-r-intc",
- sun6i_r_intc_irq_init);
-
static int __init sun6i_sc_nmi_irq_init(struct device_node *node,
struct device_node *parent)
{
--
2.24.1
^ permalink raw reply related
* [PATCH v2 5/9] ARM: dts: sunxi: h3/h5: Move wakeup-capable IRQs to r_intc
From: Samuel Holland @ 2020-05-25 4:12 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
Maxime Ripard, Chen-Yu Tsai, Russell King, Catalin Marinas,
Will Deacon
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
Samuel Holland
In-Reply-To: <20200525041302.51213-1-samuel@sholland.org>
All IRQs that can be used to wake up the system must be routed through
r_intc, so they are visible to firmware while the system is suspended.
For the H3/H5, r_intc IRQ numbers are offset by 32 from the GIC IRQ
numbers.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 94f648ad1c9e..93e7ce60a64b 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -829,8 +829,9 @@ hdmi_phy: hdmi-phy@1ef0000 {
rtc: rtc@1f00000 {
/* compatible is in per SoC .dtsi file */
reg = <0x01f00000 0x400>;
- interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <8 IRQ_TYPE_LEVEL_HIGH>,
+ <9 IRQ_TYPE_LEVEL_HIGH>;
clock-output-names = "osc32k", "osc32k-out", "iosc";
clocks = <&osc32k>;
#clock-cells = <1>;
@@ -865,7 +866,8 @@ ir: ir@1f02000 {
clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>;
clock-names = "apb", "ir";
resets = <&r_ccu RST_APB0_IR>;
- interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
reg = <0x01f02000 0x400>;
status = "disabled";
};
@@ -886,7 +888,8 @@ r_i2c: i2c@1f02400 {
r_pio: pinctrl@1f02c00 {
compatible = "allwinner,sun8i-h3-r-pinctrl";
reg = <0x01f02c00 0x400>;
- interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&r_ccu CLK_APB0_PIO>, <&osc24M>, <&rtc 0>;
clock-names = "apb", "hosc", "losc";
gpio-controller;
--
2.24.1
^ permalink raw reply related
* [PATCH v2 8/9] arm64: dts: allwinner: h6: Fix indentation of IR node
From: Samuel Holland @ 2020-05-25 4:13 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
Maxime Ripard, Chen-Yu Tsai, Russell King, Catalin Marinas,
Will Deacon
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
Samuel Holland
In-Reply-To: <20200525041302.51213-1-samuel@sholland.org>
This node was indented by two tabs when added instead of one.
Remove the extra tab.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 22 ++++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index b9ab7d8fa8af..d912188dc6ea 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -901,17 +901,17 @@ r_ir_rx_pin: r-ir-rx-pin {
};
r_ir: ir@7040000 {
- compatible = "allwinner,sun50i-h6-ir",
- "allwinner,sun6i-a31-ir";
- reg = <0x07040000 0x400>;
- interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&r_ccu CLK_R_APB1_IR>,
- <&r_ccu CLK_IR>;
- clock-names = "apb", "ir";
- resets = <&r_ccu RST_R_APB1_IR>;
- pinctrl-names = "default";
- pinctrl-0 = <&r_ir_rx_pin>;
- status = "disabled";
+ compatible = "allwinner,sun50i-h6-ir",
+ "allwinner,sun6i-a31-ir";
+ reg = <0x07040000 0x400>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB1_IR>,
+ <&r_ccu CLK_IR>;
+ clock-names = "apb", "ir";
+ resets = <&r_ccu RST_R_APB1_IR>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_ir_rx_pin>;
+ status = "disabled";
};
r_i2c: i2c@7081400 {
--
2.24.1
^ permalink raw reply related
* [PATCH v2 7/9] arm64: dts: allwinner: a64: Move wakeup-capable IRQs to r_intc
From: Samuel Holland @ 2020-05-25 4:13 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
Maxime Ripard, Chen-Yu Tsai, Russell King, Catalin Marinas,
Will Deacon
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
Samuel Holland
In-Reply-To: <20200525041302.51213-1-samuel@sholland.org>
All IRQs that can be used to wake up the system must be routed through
r_intc, so they are visible to firmware while the system is suspended.
For the A64, r_intc IRQ numbers are offset by 32 from the GIC IRQ
numbers.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index c26cc1fcaffd..33f2ce0d93aa 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -1176,8 +1176,9 @@ rtc: rtc@1f00000 {
compatible = "allwinner,sun50i-a64-rtc",
"allwinner,sun8i-h3-rtc";
reg = <0x01f00000 0x400>;
- interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <8 IRQ_TYPE_LEVEL_HIGH>,
+ <9 IRQ_TYPE_LEVEL_HIGH>;
clock-output-names = "osc32k", "osc32k-out", "iosc";
clocks = <&osc32k>;
#clock-cells = <1>;
@@ -1227,7 +1228,8 @@ r_ir: ir@1f02000 {
clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>;
clock-names = "apb", "ir";
resets = <&r_ccu RST_APB0_IR>;
- interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&r_ir_rx_pin>;
status = "disabled";
@@ -1247,7 +1249,8 @@ r_pwm: pwm@1f03800 {
r_pio: pinctrl@1f02c00 {
compatible = "allwinner,sun50i-a64-r-pinctrl";
reg = <0x01f02c00 0x400>;
- interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&r_ccu CLK_APB0_PIO>, <&osc24M>, <&osc32k>;
clock-names = "apb", "hosc", "losc";
gpio-controller;
--
2.24.1
^ permalink raw reply related
* [PATCH v2 9/9] arm64: dts: allwinner: h6: Move wakeup-capable IRQs to r_intc
From: Samuel Holland @ 2020-05-25 4:13 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
Maxime Ripard, Chen-Yu Tsai, Russell King, Catalin Marinas,
Will Deacon
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
Samuel Holland
In-Reply-To: <20200525041302.51213-1-samuel@sholland.org>
All IRQs that can be used to wake up the system must be routed through
r_intc, so they are visible to firmware while the system is suspended.
For the H6, r_intc IRQ numbers are offset by 96 from the GIC IRQ
numbers.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index d912188dc6ea..188699f47dea 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -844,8 +844,9 @@ tcon_tv_out_tcon_top: endpoint@1 {
rtc: rtc@7000000 {
compatible = "allwinner,sun50i-h6-rtc";
reg = <0x07000000 0x400>;
- interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>,
+ <6 IRQ_TYPE_LEVEL_HIGH>;
clock-output-names = "osc32k", "osc32k-out", "iosc";
#clock-cells = <1>;
};
@@ -880,8 +881,9 @@ r_intc: interrupt-controller@7021000 {
r_pio: pinctrl@7022000 {
compatible = "allwinner,sun50i-h6-r-pinctrl";
reg = <0x07022000 0x400>;
- interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = < 9 IRQ_TYPE_LEVEL_HIGH>,
+ <15 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>;
clock-names = "apb", "hosc", "losc";
gpio-controller;
@@ -904,7 +906,8 @@ r_ir: ir@7040000 {
compatible = "allwinner,sun50i-h6-ir",
"allwinner,sun6i-a31-ir";
reg = <0x07040000 0x400>;
- interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&r_ccu CLK_R_APB1_IR>,
<&r_ccu CLK_IR>;
clock-names = "apb", "ir";
--
2.24.1
^ permalink raw reply related
* [PATCH v2 6/9] ARM: dts: sunxi: a83t: Move wakeup-capable IRQs to r_intc
From: Samuel Holland @ 2020-05-25 4:12 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
Maxime Ripard, Chen-Yu Tsai, Russell King, Catalin Marinas,
Will Deacon
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
Samuel Holland
In-Reply-To: <20200525041302.51213-1-samuel@sholland.org>
All IRQs that can be used to wake up the system must be routed through
r_intc, so they are visible to firmware while the system is suspended.
For the A83T, r_intc IRQ numbers are offset by 32 from the GIC IRQ
numbers.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/boot/dts/sun8i-a83t.dtsi | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 655404d6d3a3..fcfc573eb96d 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -1130,7 +1130,8 @@ r_cir: ir@1f02000 {
clocks = <&r_ccu CLK_APB0_IR>, <&r_ccu CLK_IR>;
clock-names = "apb", "ir";
resets = <&r_ccu RST_APB0_IR>;
- interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
reg = <0x01f02000 0x400>;
pinctrl-names = "default";
pinctrl-0 = <&r_cir_pin>;
@@ -1140,14 +1141,16 @@ r_cir: ir@1f02000 {
r_lradc: lradc@1f03c00 {
compatible = "allwinner,sun8i-a83t-r-lradc";
reg = <0x01f03c00 0x100>;
- interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <10 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
r_pio: pinctrl@1f02c00 {
compatible = "allwinner,sun8i-a83t-r-pinctrl";
reg = <0x01f02c00 0x400>;
- interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&r_ccu CLK_APB0_PIO>, <&osc24M>,
<&osc16Md512>;
clock-names = "apb", "hosc", "losc";
--
2.24.1
^ permalink raw reply related
* [PATCH v2 3/9] dt-bindings: irq: Add a compatible for the H3 R_INTC
From: Samuel Holland @ 2020-05-25 4:12 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
Maxime Ripard, Chen-Yu Tsai, Russell King, Catalin Marinas,
Will Deacon
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
Samuel Holland
In-Reply-To: <20200525041302.51213-1-samuel@sholland.org>
The Allwinner H3 SoC contains an R_INTC that is, as far as we know,
compatible with the R_INTC present in other sun8i/sun50i SoCs starting
with the A31. Since the R_INTC hardware is undocumented, introduce a new
compatible for the R_INTC variant in this SoC, in case there turns out
to be some difference.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
.../allwinner,sun7i-a20-sc-nmi.yaml | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
index cf09055da78b..973fe5d17af0 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
@@ -26,15 +26,13 @@ properties:
- const: allwinner,sun6i-a31-sc-nmi
deprecated: true
- const: allwinner,sun7i-a20-sc-nmi
- - items:
- - const: allwinner,sun8i-a83t-r-intc
- - const: allwinner,sun6i-a31-r-intc
- const: allwinner,sun9i-a80-sc-nmi
- items:
- - const: allwinner,sun50i-a64-r-intc
- - const: allwinner,sun6i-a31-r-intc
- - items:
- - const: allwinner,sun50i-h6-r-intc
+ - enum:
+ - allwinner,sun8i-a83t-r-intc
+ - allwinner,sun8i-h3-r-intc
+ - allwinner,sun50i-a64-r-intc
+ - allwinner,sun50i-h6-r-intc
- const: allwinner,sun6i-a31-r-intc
reg:
--
2.24.1
^ permalink raw reply related
* [PATCH v2 0/9] sunxi: Support IRQ wakeup from deep sleep
From: Samuel Holland @ 2020-05-25 4:12 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
Maxime Ripard, Chen-Yu Tsai, Russell King, Catalin Marinas,
Will Deacon
Cc: devicetree, linux-arm-kernel, linux-kernel, linux-sunxi,
Samuel Holland
Allwinner sun8i/sun50i SoCs (A31 and newer) have two interrupt
controllers: GIC and R_INTC. GIC does not support wakeup. R_INTC handles
the external NMI pin, and provides 16-32 IRQs to the ARISC. At least the
first 16 of these correspond 1:1 to a block of GIC IRQs starting with
the NMI.
This series replaces the existing chained irqchip driver used only to
control the NMI, with a stacked irqchip driver that also provides wakeup
capability for those 16 IRQs. The idea is that we preconfigure the
ARISC's IRQ controller, and then the ARISC firmware knows to wake up as
soon as it receives an IRQ.
I went back and forth about updating the existing driver versus writing
a new one. Since the hardware really is different from the NMI-only
controller on the A20, ultimately I went with a new driver. It may be
useful to separately do the chained->stacked conversion on the sunxi-nmi
driver as well.
Patch 1 adds the new driver.
Patch 2 adds wakeup capability.
The other patches update the DT+bindings to use R_INTC where beneficial.
With appropriate firmware, this series allows waking from RTC, NMI/PMIC,
(power button, plugging in USB, etc.), and Port L GPIO (lid switch, BT,
WiFi, modem, etc.).
Changes from v1:
- Use writel_relaxed() instead if writel().
- Remove use of the MASK register, as it doesn't affect the NMI as seen
by the GIC. It only affects the IRQs seen by the coprocessor.
- Leave NMI_HWIRQ enabled at all times, since it can be masked at the
GIC level (removed .irq_enable and .irq_disable).
- Use .irq_ack vs .irq_eoi depending on the trigger type, to avoid
missing interrupts or double interrupts.
- Because of this change, the driver needs two "irq_chip"s, one
with .irq_eoi set to our function and one without.
- Also because of this, we need IRQ_FASTEOI_HIERARCHY_HANDLERS for
handle_fasteoi_ack_irq(), so our .irq_ack function gets called
while the GIC driver works as if handle_fasteoi_irq() was used.
- Inline the SUNXI_SRC_TYPE_* enum into sun6i_r_intc_irq_set_type().
- Add a comment explaining how the trigger type is used.
- Don't call irqd_set_trigger_type().
- Set IRQCHIP_SET_TYPE_MASKED to match the GIC (since flags from this
driver mask flags from that one).
- Set IRQCHIP_EOI_THREADED to avoid doubled level interrupts, since the
latch will be set again as long as the trigger is met.
- Replace sun6i_r_intc_domain_translate() with
irq_domain_translate_twocell().
- Use an enum for the device tree binding.
- Update commit messages for accuracy and typos.
Samuel Holland (9):
irqchip/sun6i-r: Use a stacked irqchip driver
irqchip/sun6i-r: Add wakeup support
dt-bindings: irq: Add a compatible for the H3 R_INTC
ARM: dts: sunxi: h3/h5: Add r_intc node
ARM: dts: sunxi: h3/h5: Move wakeup-capable IRQs to r_intc
ARM: dts: sunxi: a83t: Move wakeup-capable IRQs to r_intc
arm64: dts: allwinner: a64: Move wakeup-capable IRQs to r_intc
arm64: dts: allwinner: h6: Fix indentation of IR node
arm64: dts: allwinner: h6: Move wakeup-capable IRQs to r_intc
.../allwinner,sun7i-a20-sc-nmi.yaml | 12 +-
arch/arm/boot/dts/sun8i-a83t.dtsi | 9 +-
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 20 +-
arch/arm/mach-sunxi/Kconfig | 4 +
arch/arm64/Kconfig.platforms | 2 +
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 11 +-
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 33 ++-
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-sun6i-r.c | 267 ++++++++++++++++++
drivers/irqchip/irq-sunxi-nmi.c | 26 +-
10 files changed, 329 insertions(+), 56 deletions(-)
create mode 100644 drivers/irqchip/irq-sun6i-r.c
--
2.24.1
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox