* Re: [PATCH v2 4/6] dmaengine: dw: Print warning if multi-block is unsupported
From: Serge Semin @ 2020-05-21 1:40 UTC (permalink / raw)
To: Vinod Koul
Cc: Serge Semin, Andy Shevchenko, Mark Brown, Viresh Kumar,
Dan Williams, Alexey Malahov, Thomas Bogendoerfer, Paul Burton,
Ralf Baechle, Arnd Bergmann, Rob Herring, linux-mips, devicetree,
dmaengine, Linux Kernel Mailing List
In-Reply-To: <20200519170246.GS374218@vkoul-mobl.Dlink>
On Tue, May 19, 2020 at 10:32:46PM +0530, Vinod Koul wrote:
> On 17-05-20, 22:23, Serge Semin wrote:
> > On Fri, May 15, 2020 at 12:00:39PM +0530, Vinod Koul wrote:
> > > Hi Serge,
> > >
> > > On 12-05-20, 15:42, Serge Semin wrote:
> > > > Vinod,
> > > >
> > > > Could you join the discussion for a little bit?
> > > >
> > > > In order to properly fix the problem discussed in this topic, we need to
> > > > introduce an additional capability exported by DMA channel handlers on per-channel
> > > > basis. It must be a number, which would indicate an upper limitation of the SG list
> > > > entries amount.
> > > > Something like this would do it:
> > > > struct dma_slave_caps {
> > > > ...
> > > > unsigned int max_sg_nents;
> > > > ...
> > >
> > > Looking at the discussion, I agree we should can this up in the
> > > interface. The max_dma_len suggests the length of a descriptor allowed,
> > > it does not convey the sg_nents supported which in the case of nollp is
> > > one.
> > >
> > > Btw is this is a real hardware issue, I have found that value of such
> > > hardware is very less and people did fix it up in subsequent revs to add
> > > llp support.
> >
> > Yes, it is. My DW DMAC doesn't support LLP and there isn't going to be new SoC
> > version produced.(
>
> Ouch
>
> > > Also, another question is why this cannot be handled in driver, I agree
> > > your hardware does not support llp but that does not stop you from
> > > breaking a multi_sg list into N hardware descriptors and keep submitting
> > > them (for this to work submission should be done in isr and not in bh,
> > > unfortunately very few driver take that route).
> >
> > Current DW DMA driver does that, but this isn't enough. The problem is that
> > in order to fix the issue in the DMA hardware driver we need to introduce
> > an inter-dependent channels abstraction and synchronously feed both Tx and
> > Rx DMA channels with hardware descriptors (LLP entries) one-by-one. This hardly
> > needed by any slave device driver rather than SPI, which Tx and Rx buffers are
> > inter-dependent. So Andy's idea was to move the fix to the SPI driver (feed
> > the DMA engine channels with Tx and Rx data buffers synchronously), but DMA
> > engine would provide an info whether such fix is required. This can be
> > determined by the maximum SG entries capability.
>
> Okay but having the sw limitation removed would also be a good idea, you
> can handle any user, I will leave it upto you, either way is okay
>
> >
> > (Note max_sg_ents isn't a limitation on the number of SG entries supported by
> > the DMA driver, but the number of SG entries handled by the DMA engine in a
> > single DMA transaction.)
> >
> > > TBH the max_sg_nents or
> > > max_dma_len are HW restrictions and SW *can* deal with then :-)
> >
> > Yes, it can, but it only works for the cases when individual DMA channels are
> > utilized. DMA hardware driver doesn't know that the target and source slave
> > device buffers (SPI Tx and Rx FIFOs) are inter-dependent, that writing to one
> > you will implicitly push data to another. So due to the interrupts handling
> > latency Tx DMA channel is restarted faster than Rx DMA channel is reinitialized.
> > This causes the SPI Rx FIFO overflow and data loss.
> >
> > >
> > > In an idea world, you should break the sw descriptor submitted into N hw
> > > descriptors and submit to hardware and let user know when the sw
> > > descriptor is completed. Of course we do not do that :(
> >
> > Well, the current Dw DMA driver does that. But due to the two slave device
> > buffers inter-dependency this isn't enough to perform safe DMA transactions.
> > Due to the interrupts handling latency Tx DMA channel pushes data to the slave
> > device buffer faster than Rx DMA channel starts to handle incoming data. This
> > causes the SPI Rx FIFO overflow.
> >
> > >
> > > > };
> > > > As Andy suggested it's value should be interpreted as:
> > > > 0 - unlimited number of entries,
> > > > 1:MAX_UINT - actual limit to the number of entries.
> > >
> >
> > > Hmm why 0, why not MAX_UINT for unlimited?
> >
> > 0 is much better for many reasons. First of all MAX_UINT is a lot, but it's
> > still a number. On x64 platform this might be actual limit if for instance
> > the block-size register is 32-bits wide. Secondly interpreting 0 as unlimited
> > number of entries would be more suitable since most of the drivers support
> > LLP functionality and we wouldn't need to update their code to set MAX_UINT.
> > Thirdly DMA engines, which don't support LLPs would need to set this parameter
> > as 1. So if we do as you say and interpret unlimited number of LLPs as MAX_UINT,
> > then 0 would left unused.
> >
> > To sum up I also think that using 0 as unlimited number SG entries supported is
> > much better.
>
> ok
>
> > > > In addition to that seeing the dma_get_slave_caps() method provide the caps only
> > > > by getting them from the DMA device descriptor, while we need to have an info on
> > > > per-channel basis, it would be good to introduce a new DMA-device callback like:
> > > > struct dma_device {
> > > > ...
> > > > int (*device_caps)(struct dma_chan *chan,
> > > > struct dma_slave_caps *caps);
> > >
> >
> > > Do you have a controller where channel caps are on per-channel basis?
> >
> > Yes, I do. Our DW DMA controller has got the maximum burst length non-uniformly
> > distributed per DMA channels. There are eight channels our controller supports,
> > among which first two channels can burst up to 32 transfer words, but the rest
> > of the channels support bursting up to 4 transfer words.
> >
> > So having such device_caps() callback to customize the device capabilities on
> > per-DMA-channel basis would be very useful! What do you think?
>
> Okay looks like per-ch basis is the way forward!
Great! Thanks. I'll send v3 with updates we've come up to in this discussion.
-Sergey
>
> --
> ~Vinod
^ permalink raw reply
* Re: [PATCH v2 2/6] dt-bindings: dma: dw: Add max burst transaction length property
From: Serge Semin @ 2020-05-21 1:33 UTC (permalink / raw)
To: Vinod Koul
Cc: Serge Semin, Andy Shevchenko, Viresh Kumar, Rob Herring,
Alexey Malahov, Thomas Bogendoerfer, Paul Burton, Ralf Baechle,
Arnd Bergmann, Dan Williams, linux-mips, dmaengine, devicetree,
linux-kernel
In-Reply-To: <20200519171304.GU374218@vkoul-mobl.Dlink>
On Tue, May 19, 2020 at 10:43:04PM +0530, Vinod Koul wrote:
> On 17-05-20, 20:47, Serge Semin wrote:
> > On Fri, May 15, 2020 at 02:11:13PM +0300, Serge Semin wrote:
> > > On Fri, May 15, 2020 at 04:26:58PM +0530, Vinod Koul wrote:
> > > > On 15-05-20, 13:51, Andy Shevchenko wrote:
> > > > > On Fri, May 15, 2020 at 11:39:11AM +0530, Vinod Koul wrote:
> > > > > > On 12-05-20, 15:38, Andy Shevchenko wrote:
> > > > > > > On Tue, May 12, 2020 at 02:49:46PM +0300, Serge Semin wrote:
> > > > > > > > On Tue, May 12, 2020 at 12:08:04PM +0300, Andy Shevchenko wrote:
> > > > > > > > > On Tue, May 12, 2020 at 12:35:31AM +0300, Serge Semin wrote:
> > > > > > > > > > On Tue, May 12, 2020 at 12:01:38AM +0300, Andy Shevchenko wrote:
> > > > > > > > > > > On Mon, May 11, 2020 at 11:05:28PM +0300, Serge Semin wrote:
> > > > > > > > > > > > On Fri, May 08, 2020 at 02:12:42PM +0300, Andy Shevchenko wrote:
> > > > > > > > > > > > > On Fri, May 08, 2020 at 01:53:00PM +0300, Serge Semin wrote:
> > > > >
> > > > > ...
> > > > >
> > > > > > > I leave it to Rob and Vinod.
> > > > > > > It won't break our case, so, feel free with your approach.
> > > > > >
> > > > > > I agree the DT is about describing the hardware and looks like value of
> > > > > > 1 is not allowed. If allowed it should be added..
> > > > >
> > > > > It's allowed at *run time*, it's illegal in *pre-silicon stage* when
> > > > > synthesizing the IP.
> > > >
> > > > Then it should be added ..
> > >
> > > Vinod, max-burst-len is "MAXimum" burst length not "run-time or current or any
> > > other" burst length. It's a constant defined at the IP-core synthesis stage and
> > > according to the Data Book, MAX burst length can't be 1. The allowed values are
> > > exactly as I described in the binding [4, 8, 16, 32, ...]. MAX burst length
> > > defines the upper limit of the run-time burst length. So setting it to 1 isn't
> > > about describing a hardware, but using DT for the software convenience.
> > >
> > > -Sergey
> >
> > Vinod, to make this completely clear. According to the DW DMAC data book:
> > - In general, run-time parameter of the DMA transaction burst length (set in
> > the SRC_MSIZE/DST_MSIZE fields of the channel control register) may belong
> > to the set [1, 4, 8, 16, 32, 64, 128, 256].
>
> so 1 is valid value for msize
Right.
>
> > - Actual upper limit of the burst length run-time parameter is limited by a
> > constant defined at the IP-synthesize stage (it's called DMAH_CHx_MAX_MULT_SIZE)
> > and this constant belongs to the set [4, 8, 16, 32, 64, 128, 256]. (See, no 1
> > in this set).
>
> maximum can be 4 onwards, but in my configuration I can choose 1 as
> value for msize
It's true for all configurations. msize can be at least 0 or 1, which correspond
to 1 and 4 burst length respectively.
>
> > So the run-time burst length in a case of particular DW DMA controller belongs
> > to the range:
> > 1 <= SRC_MSIZE <= DMAH_CHx_MAX_MULT_SIZE
> > and
> > 1 <= DST_MSIZE <= DMAH_CHx_MAX_MULT_SIZE
> >
> > See. No mater which DW DMA controller we get each of them will at least support
> > the burst length of 1 and 4 transfer words. This is determined by design of the
> > DW DMA controller IP since DMAH_CHx_MAX_MULT_SIZE constant set starts with 4.
> >
> > In this patch I suggest to add the max-burst-len property, which specifies
> > the upper limit for the run-time burst length. Since the maximum burst length
> > capable to be set to the SRC_MSIZE/DST_MSIZE fields of the DMA channel control
> > register is determined by the DMAH_CHx_MAX_MULT_SIZE constant (which can't be 1
> > by the DW DMA IP design), max-burst-len property as being also responsible for
> > the maximum burst length setting should be associated with DMAH_CHx_MAX_MULT_SIZE
> > thus should belong to the same set [4, 8, 16, 32, 64, 128, 256].
> >
> > So 1 shouldn't be in the enum of the max-burst-len property constraint, because
> > hardware doesn't support such limitation by design, while setting 1 as
> > max-burst-len would mean incorrect description of the DMA controller.
> >
> > Vinod, could you take a look at the info I provided above and say your final word
> > whether 1 should be really allowed to be in the max-burst-len enum constraints?
> > I'll do as you say in the next version of the patchset.
>
> You are specifying the parameter which will be used to pick, i think
> starting with 4 makes sense as we are specifying maximum allowed values
> for msize. Values lesser than or equal to this would be allowed, I guess
> that should be added to documentation.
Right. Thanks. I'll a proper description to the property in the binding file.
-Sergey
>
> thanks
> --
> ~Vinod
^ permalink raw reply
* [PATCH v3 16/16] dt-bindings: spi: Convert DW SPI binding to DT schema
From: Serge Semin @ 2020-05-21 1:22 UTC (permalink / raw)
To: Mark Brown, Rob Herring
Cc: Serge Semin, Serge Semin, Georgy Vlasov, Ramil Zaripov,
Alexey Malahov, Thomas Bogendoerfer, Paul Burton, Ralf Baechle,
Arnd Bergmann, Andy Shevchenko, linux-mips, Wan Ahmad Zainie,
Gareth Williams, linux-spi, devicetree, linux-kernel
In-Reply-To: <20200521012206.14472-1-Sergey.Semin@baikalelectronics.ru>
Modern device tree bindings are supposed to be created as YAML-files
in accordance with dt-schema. This commit replaces two DW SPI legacy
bare text bindings with YAML file. As before the bindings file states
that the corresponding dts node is supposed to be compatible either
with generic DW APB SSI controller or with Microsemi/Amazon/Renesas/Intel
vendors-specific controllers, to have registers, interrupts and clocks
properties. Though in case of Microsemi version of the controller
there must be two registers resources specified. Properties like
clock-names, reg-io-width, cs-gpio, num-cs, DMA and slave device
sub-nodes are optional.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Cc: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: linux-mips@vger.kernel.org
---
.../bindings/spi/snps,dw-apb-ssi.txt | 44 ------
.../bindings/spi/snps,dw-apb-ssi.yaml | 127 ++++++++++++++++++
.../devicetree/bindings/spi/spi-dw.txt | 24 ----
3 files changed, 127 insertions(+), 68 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
create mode 100644 Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
delete mode 100644 Documentation/devicetree/bindings/spi/spi-dw.txt
diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
deleted file mode 100644
index 020e3168ee41..000000000000
--- a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface.
-
-Required properties:
-- compatible : "snps,dw-apb-ssi" or "mscc,<soc>-spi", where soc is "ocelot" or
- "jaguar2", or "amazon,alpine-dw-apb-ssi", or "snps,dwc-ssi-1.01a" or
- "intel,keembay-ssi"
-- reg : The register base for the controller. For "mscc,<soc>-spi", a second
- register set is required (named ICPU_CFG:SPI_MST)
-- interrupts : One interrupt, used by the controller.
-- #address-cells : <1>, as required by generic SPI binding.
-- #size-cells : <0>, also as required by generic SPI binding.
-- clocks : phandles for the clocks, see the description of clock-names below.
- The phandle for the "ssi_clk" is required. The phandle for the "pclk" clock
- is optional. If a single clock is specified but no clock-name, it is the
- "ssi_clk" clock. If both clocks are listed, the "ssi_clk" must be first.
-
-Optional properties:
-- clock-names : Contains the names of the clocks:
- "ssi_clk", for the core clock used to generate the external SPI clock.
- "pclk", the interface clock, required for register access. If a clock domain
- used to enable this clock then it should be named "pclk_clkdomain".
-- cs-gpios : Specifies the gpio pins to be used for chipselects.
-- num-cs : The number of chipselects. If omitted, this will default to 4.
-- reg-io-width : The I/O register width (in bytes) implemented by this
- device. Supported values are 2 or 4 (the default).
-- dmas : Phandle + identifiers of Tx and Rx DMA channels.
-- dma-names : Contains the names of the DMA channels. Must be "tx" and "rx".
-
-Child nodes as per the generic SPI binding.
-
-Example:
-
- spi@fff00000 {
- compatible = "snps,dw-apb-ssi";
- reg = <0xfff00000 0x1000>;
- interrupts = <0 154 4>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&spi_m_clk>;
- num-cs = <2>;
- cs-gpios = <&gpio0 13 0>,
- <&gpio0 14 0>;
- };
-
diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
new file mode 100644
index 000000000000..1fcab6415136
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
@@ -0,0 +1,127 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/snps,dw-apb-ssi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface
+
+maintainers:
+ - Mark Brown <broonie@kernel.org>
+
+allOf:
+ - $ref: "spi-controller.yaml#"
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - mscc,ocelot-spi
+ - mscc,jaguar2-spi
+ then:
+ properties:
+ reg:
+ minItems: 2
+
+properties:
+ compatible:
+ oneOf:
+ - description: Generic DW SPI Controller
+ enum:
+ - snps,dw-apb-ssi
+ - snps,dwc-ssi-1.01a
+ - description: Microsemi Ocelot/Jaguar2 SoC SPI Controller
+ items:
+ - enum:
+ - mscc,ocelot-spi
+ - mscc,jaguar2-spi
+ - const: snps,dw-apb-ssi
+ - description: Amazon Alpine SPI Controller
+ const: amazon,alpine-dw-apb-ssi
+ - description: Renesas RZ/N1 SPI Controller
+ items:
+ - const: renesas,rzn1-spi
+ - const: snps,dw-apb-ssi
+ - description: Intel Keem Bay SPI Controller
+ const: intel,keembay-ssi
+
+ reg:
+ minItems: 1
+ items:
+ - description: DW APB SSI controller memory mapped registers
+ - description: SPI MST region map
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ minItems: 1
+ items:
+ - description: SPI Controller reference clock source
+ - description: APB interface clock source
+
+ clock-names:
+ minItems: 1
+ items:
+ - const: ssi_clk
+ - const: pclk
+
+ reg-io-width:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: I/O register width (in bytes) implemented by this device
+ default: 4
+ enum: [ 2, 4 ]
+
+ num-cs:
+ default: 4
+ minimum: 1
+ maximum: 4
+
+ dmas:
+ items:
+ - description: TX DMA Channel
+ - description: RX DMA Channel
+
+ dma-names:
+ items:
+ - const: tx
+ - const: rx
+
+patternProperties:
+ "^.*@[0-9a-f]+$":
+ type: object
+ properties:
+ reg:
+ minimum: 0
+ maximum: 3
+
+ spi-rx-bus-width:
+ const: 1
+
+ spi-tx-bus-width:
+ const: 1
+
+unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - "#address-cells"
+ - "#size-cells"
+ - interrupts
+ - clocks
+
+examples:
+ - |
+ spi@fff00000 {
+ compatible = "snps,dw-apb-ssi";
+ reg = <0xfff00000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0 154 4>;
+ clocks = <&spi_m_clk>;
+ num-cs = <2>;
+ cs-gpios = <&gpio0 13 0>,
+ <&gpio0 14 0>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/spi/spi-dw.txt b/Documentation/devicetree/bindings/spi/spi-dw.txt
deleted file mode 100644
index 7b63ed601990..000000000000
--- a/Documentation/devicetree/bindings/spi/spi-dw.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-Synopsys DesignWare SPI master
-
-Required properties:
-- compatible: should be "snps,designware-spi"
-- #address-cells: see spi-bus.txt
-- #size-cells: see spi-bus.txt
-- reg: address and length of the spi master registers
-- interrupts: should contain one interrupt
-- clocks: spi clock phandle
-- num-cs: see spi-bus.txt
-
-Optional properties:
-- cs-gpios: see spi-bus.txt
-
-Example:
-
-spi: spi@4020a000 {
- compatible = "snps,designware-spi";
- interrupts = <11 1>;
- reg = <0x4020a000 0x1000>;
- clocks = <&pclk>;
- num-cs = <2>;
- cs-gpios = <&banka 0 0>;
-};
--
2.25.1
^ permalink raw reply related
* [PATCH v3 14/16] spi: dw: Add DMA support to the DW SPI MMIO driver
From: Serge Semin @ 2020-05-21 1:22 UTC (permalink / raw)
To: Mark Brown
Cc: Serge Semin, Serge Semin, Georgy Vlasov, Ramil Zaripov,
Andy Shevchenko, Alexey Malahov, Thomas Bogendoerfer, Paul Burton,
Ralf Baechle, Arnd Bergmann, Rob Herring, linux-mips, devicetree,
Wan Ahmad Zainie, Gareth Williams, Stephen Boyd, YueHaibing,
Jarkko Nikula, Thomas Gleixner, linux-spi, linux-kernel
In-Reply-To: <20200521012206.14472-1-Sergey.Semin@baikalelectronics.ru>
Since the common code in the spi-dw-dma.c driver is ready to be used
by the MMIO driver and now provides a method to generically (on any
DT or ACPI-based platforms) retrieve the Tx/Rx DMA channel handlers,
we can use it and a set of the common DW SPI DMA callbacks to enable
DMA at least for generic "snps,dw-apb-ssi" and "snps,dwc-ssi-1.01a"
devices.
Co-developed-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Signed-off-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Co-developed-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
drivers/spi/spi-dw-mmio.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 0894b4c09496..e23d0c53a664 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -149,6 +149,8 @@ static int dw_spi_dw_apb_init(struct platform_device *pdev,
/* Register hook to configure CTRLR0 */
dwsmmio->dws.update_cr0 = dw_spi_update_cr0;
+ dw_spi_dma_setup_generic(&dwsmmio->dws);
+
return 0;
}
@@ -158,6 +160,8 @@ static int dw_spi_dwc_ssi_init(struct platform_device *pdev,
/* Register hook to configure CTRLR0 */
dwsmmio->dws.update_cr0 = dw_spi_update_cr0_v1_01a;
+ dw_spi_dma_setup_generic(&dwsmmio->dws);
+
return 0;
}
--
2.25.1
^ permalink raw reply related
* [PATCH v3 12/16] spi: dw: Add DW SPI DMA/PCI/MMIO dependency on the DW SPI core
From: Serge Semin @ 2020-05-21 1:22 UTC (permalink / raw)
To: Mark Brown
Cc: Serge Semin, Serge Semin, Georgy Vlasov, Ramil Zaripov,
Andy Shevchenko, Alexey Malahov, Thomas Bogendoerfer, Paul Burton,
Ralf Baechle, Arnd Bergmann, Rob Herring, linux-mips, devicetree,
John Garry, Chuanhong Guo, Eddie James, Chris Packham,
Masahisa Kojima, Tomer Maimon, Krzysztof Kozlowski, linux-spi,
linux-kernel
In-Reply-To: <20200521012206.14472-1-Sergey.Semin@baikalelectronics.ru>
Seeing all of the DW SPI driver components like DW SPI DMA/PCI/MMIO
depend on the DW SPI core code it's better to use the if-endif
conditional kernel config statement to signify that common dependency.
Co-developed-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Signed-off-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Co-developed-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
drivers/spi/Kconfig | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 6a84f3dad35c..3cdf8310d185 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -226,17 +226,20 @@ config SPI_DESIGNWARE
help
general driver for SPI controller core from DesignWare
+if SPI_DESIGNWARE
+
config SPI_DW_DMA
bool "DMA support for DW SPI controller"
- depends on SPI_DESIGNWARE
config SPI_DW_PCI
tristate "PCI interface driver for DW SPI core"
- depends on SPI_DESIGNWARE && PCI
+ depends on PCI
config SPI_DW_MMIO
tristate "Memory-mapped io interface driver for DW SPI core"
- depends on SPI_DESIGNWARE
+ depends on HAS_IOMEM
+
+endif
config SPI_DLN2
tristate "Diolan DLN-2 USB SPI adapter"
--
2.25.1
^ permalink raw reply related
* [PATCH v3 11/16] spi: dw: Remove DW DMA code dependency from DW_DMAC_PCI
From: Serge Semin @ 2020-05-21 1:22 UTC (permalink / raw)
To: Mark Brown
Cc: Serge Semin, Serge Semin, Georgy Vlasov, Ramil Zaripov,
Andy Shevchenko, Alexey Malahov, Thomas Bogendoerfer, Paul Burton,
Ralf Baechle, Rob Herring, Arnd Bergmann, linux-mips, devicetree,
John Garry, Chuanhong Guo, Krzysztof Kozlowski, Eddie James,
Chris Packham, Masahisa Kojima, Tomer Maimon, linux-spi,
linux-kernel
In-Reply-To: <20200521012206.14472-1-Sergey.Semin@baikalelectronics.ru>
Since there is a generic method available to initialize the DW SPI DMA
interface on any DT and ACPI-based platforms, which in general can be
designed with not only DW DMAC but with any DMA engine on board, we can
freely remove the CONFIG_DW_DMAC_PCI config from dependency list of
CONFIG_SPI_DW_DMA. Especially seeing that we don't use anything DW DMAC
specific in the new driver.
Co-developed-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Signed-off-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Co-developed-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
drivers/spi/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 03b061975f70..6a84f3dad35c 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -228,7 +228,7 @@ config SPI_DESIGNWARE
config SPI_DW_DMA
bool "DMA support for DW SPI controller"
- depends on SPI_DESIGNWARE && DW_DMAC_PCI
+ depends on SPI_DESIGNWARE
config SPI_DW_PCI
tristate "PCI interface driver for DW SPI core"
--
2.25.1
^ permalink raw reply related
* [PATCH v3 07/16] spi: dw: Use DMA max burst to set the request thresholds
From: Serge Semin @ 2020-05-21 1:21 UTC (permalink / raw)
To: Mark Brown
Cc: Serge Semin, Serge Semin, Alexey Malahov, Thomas Bogendoerfer,
Paul Burton, Ralf Baechle, Arnd Bergmann, Andy Shevchenko,
Rob Herring, linux-mips, devicetree, Georgy Vlasov, Ramil Zaripov,
Thomas Gleixner, Wan Ahmad Zainie, Jarkko Nikula, Clement Leger,
linux-spi, linux-kernel
In-Reply-To: <20200521012206.14472-1-Sergey.Semin@baikalelectronics.ru>
Each channel of DMA controller may have a limited length of burst
transaction (number of IO operations performed at ones in a single
DMA client request). This parameter can be used to setup the most
optimal DMA Tx/Rx data level values. In order to avoid the Tx buffer
overrun we can set the DMA Tx level to be of FIFO depth minus the
maximum burst transactions length. To prevent the Rx buffer underflow
the DMA Rx level should be set to the maximum burst transactions length.
This commit setups the DMA channels and the DW SPI DMA Tx/Rx levels
in accordance with these rules.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
Changelog v3:
- Use min() method to calculate the optimal burst values.
---
drivers/spi/spi-dw-mid.c | 37 +++++++++++++++++++++++++++++++++----
drivers/spi/spi-dw.h | 2 ++
2 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index be02fedd87cb..0e95d8bc85c5 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -34,6 +34,31 @@ static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
return true;
}
+static void mid_spi_maxburst_init(struct dw_spi *dws)
+{
+ struct dma_slave_caps caps;
+ u32 max_burst, def_burst;
+ int ret;
+
+ def_burst = dws->fifo_len / 2;
+
+ ret = dma_get_slave_caps(dws->rxchan, &caps);
+ if (!ret && caps.max_burst)
+ max_burst = caps.max_burst;
+ else
+ max_burst = RX_BURST_LEVEL;
+
+ dws->rxburst = min(max_burst, def_burst);
+
+ ret = dma_get_slave_caps(dws->txchan, &caps);
+ if (!ret && caps.max_burst)
+ max_burst = caps.max_burst;
+ else
+ max_burst = TX_BURST_LEVEL;
+
+ dws->txburst = min(max_burst, def_burst);
+}
+
static int mid_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
{
struct dw_dma_slave slave = {
@@ -69,6 +94,8 @@ static int mid_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
dws->master->dma_rx = dws->rxchan;
dws->master->dma_tx = dws->txchan;
+ mid_spi_maxburst_init(dws);
+
return 0;
free_rxchan:
@@ -94,6 +121,8 @@ static int mid_spi_dma_init_generic(struct device *dev, struct dw_spi *dws)
dws->master->dma_rx = dws->rxchan;
dws->master->dma_tx = dws->txchan;
+ mid_spi_maxburst_init(dws);
+
return 0;
}
@@ -216,7 +245,7 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx(struct dw_spi *dws,
memset(&txconf, 0, sizeof(txconf));
txconf.direction = DMA_MEM_TO_DEV;
txconf.dst_addr = dws->dma_addr;
- txconf.dst_maxburst = TX_BURST_LEVEL;
+ txconf.dst_maxburst = dws->txburst;
txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
txconf.dst_addr_width = convert_dma_width(dws->n_bytes);
txconf.device_fc = false;
@@ -290,7 +319,7 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws,
memset(&rxconf, 0, sizeof(rxconf));
rxconf.direction = DMA_DEV_TO_MEM;
rxconf.src_addr = dws->dma_addr;
- rxconf.src_maxburst = RX_BURST_LEVEL;
+ rxconf.src_maxburst = dws->rxburst;
rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
rxconf.src_addr_width = convert_dma_width(dws->n_bytes);
rxconf.device_fc = false;
@@ -315,8 +344,8 @@ static int mid_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer)
{
u16 imr = 0, dma_ctrl = 0;
- dw_writel(dws, DW_SPI_DMARDLR, RX_BURST_LEVEL - 1);
- dw_writel(dws, DW_SPI_DMATDLR, TX_BURST_LEVEL);
+ dw_writel(dws, DW_SPI_DMARDLR, dws->rxburst - 1);
+ dw_writel(dws, DW_SPI_DMATDLR, dws->fifo_len - dws->txburst);
if (xfer->tx_buf) {
dma_ctrl |= SPI_DMA_TDMAE;
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 4902f937c3d7..d0c8b7d3a5d2 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -141,7 +141,9 @@ struct dw_spi {
/* DMA info */
struct dma_chan *txchan;
+ u32 txburst;
struct dma_chan *rxchan;
+ u32 rxburst;
unsigned long dma_chan_busy;
dma_addr_t dma_addr; /* phy address of the Data register */
const struct dw_spi_dma_ops *dma_ops;
--
2.25.1
^ permalink raw reply related
* [PATCH v3 06/16] spi: dw: Parameterize the DMA Rx/Tx burst length
From: Serge Semin @ 2020-05-21 1:21 UTC (permalink / raw)
To: Mark Brown
Cc: Serge Semin, Serge Semin, Georgy Vlasov, Ramil Zaripov,
Alexey Malahov, Thomas Bogendoerfer, Paul Burton, Ralf Baechle,
Arnd Bergmann, Andy Shevchenko, Rob Herring, linux-mips,
devicetree, Thomas Gleixner, Wan Ahmad Zainie, Jarkko Nikula,
linux-spi, linux-kernel
In-Reply-To: <20200521012206.14472-1-Sergey.Semin@baikalelectronics.ru>
It isn't good to have numeric literals in the code especially if there
are multiple of them and they are related. Let's replace the Tx and Rx
burst level literals with the corresponding constants.
Co-developed-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Signed-off-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Co-developed-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
Changelog v3:
- Discard the dws->fifo_len utilization in the Tx FIFO DMA threshold
setting.
---
drivers/spi/spi-dw-mid.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index 7bba774885cd..be02fedd87cb 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -19,7 +19,9 @@
#define WAIT_RETRIES 5
#define RX_BUSY 0
+#define RX_BURST_LEVEL 16
#define TX_BUSY 1
+#define TX_BURST_LEVEL 16
static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
{
@@ -214,7 +216,7 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx(struct dw_spi *dws,
memset(&txconf, 0, sizeof(txconf));
txconf.direction = DMA_MEM_TO_DEV;
txconf.dst_addr = dws->dma_addr;
- txconf.dst_maxburst = 16;
+ txconf.dst_maxburst = TX_BURST_LEVEL;
txconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
txconf.dst_addr_width = convert_dma_width(dws->n_bytes);
txconf.device_fc = false;
@@ -288,7 +290,7 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws,
memset(&rxconf, 0, sizeof(rxconf));
rxconf.direction = DMA_DEV_TO_MEM;
rxconf.src_addr = dws->dma_addr;
- rxconf.src_maxburst = 16;
+ rxconf.src_maxburst = RX_BURST_LEVEL;
rxconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
rxconf.src_addr_width = convert_dma_width(dws->n_bytes);
rxconf.device_fc = false;
@@ -313,8 +315,8 @@ static int mid_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer)
{
u16 imr = 0, dma_ctrl = 0;
- dw_writel(dws, DW_SPI_DMARDLR, 0xf);
- dw_writel(dws, DW_SPI_DMATDLR, 0x10);
+ dw_writel(dws, DW_SPI_DMARDLR, RX_BURST_LEVEL - 1);
+ dw_writel(dws, DW_SPI_DMATDLR, TX_BURST_LEVEL);
if (xfer->tx_buf) {
dma_ctrl |= SPI_DMA_TDMAE;
--
2.25.1
^ permalink raw reply related
* [PATCH v3 00/16] spi: dw: Add generic DW DMA controller support
From: Serge Semin @ 2020-05-21 1:21 UTC (permalink / raw)
To: Mark Brown
Cc: Serge Semin, Serge Semin, Georgy Vlasov, Ramil Zaripov,
Alexey Malahov, Maxim Kaurkin, Pavel Parkhomenko,
Ekaterina Skachko, Vadim Vlasov, Alexey Kolotnikov,
Thomas Bogendoerfer, Paul Burton, Ralf Baechle, Arnd Bergmann,
Andy Shevchenko, Rob Herring, linux-mips, linux-spi, devicetree,
linux-kernel
Baikal-T1 SoC provides a DW DMA controller to perform low-speed peripherals
Mem-to-Dev and Dev-to-Mem transaction. This is also applicable to the DW
APB SSI devices embedded into the SoC. Currently the DMA-based transfers
are supported by the DW APB SPI driver only as a middle layer code for
Intel MID/Elkhart PCI devices. Seeing the same code can be used for normal
platform DMAC device we introduced a set of patches to fix it within this
series.
First of all we need to add the Tx and Rx DMA channels support into the DW
APB SSI binding. Then there are several fixes and cleanups provided as a
initial preparation for the Generic DMA support integration: add Tx/Rx
finish wait methods, clear DMAC register when done or stopped, Fix native
CS being unset, enable interrupts in accordance with DMA xfer mode,
discard static DW DMA slave structures, discard unused void priv pointer
and dma_width member of the dw_spi structure, provide the DMA Tx/Rx burst
length parametrisation and make sure it's optionally set in accordance
with the DMA max-burst capability.
In order to have the DW APB SSI MMIO driver working with DMA we need to
initialize the paddr field with the physical base address of the DW APB SSI
registers space. Then we unpin the Intel MID specific code from the
generic DMA one and placed it into the spi-dw-pci.c driver, which is a
better place for it anyway. After that the naming cleanups are performed
since the code is going to be used for a generic DMAC device. Finally the
Generic DMA initialization can be added to the generic version of the
DW APB SSI IP.
Last but not least we traditionally convert the legacy plain text-based
dt-binding file with yaml-based one and as a cherry on a cake replace
the manually written DebugFS registers read method with a ready-to-use
for the same purpose regset32 DebugFS interface usage.
This patchset is rebased and tested on the spi/for-next (5.7-rc5):
base-commit: fe9fce6b2cf3 ("Merge remote-tracking branch 'spi/for-5.8' into spi-next")
Link: https://lore.kernel.org/linux-spi/20200508132943.9826-1-Sergey.Semin@baikalelectronics.ru/
Changelog v2:
- Rebase on top of the spi repository for-next branch.
- Move bindings conversion patch to the tail of the series.
- Move fixes to the head of the series.
- Apply as many changes as possible to be applied the Generic DMA
functionality support is added and the spi-dw-mid is moved to the
spi-dw-dma driver.
- Discard patch "spi: dw: Fix dma_slave_config used partly uninitialized"
since the problem has already been fixed.
- Add new patch "spi: dw: Discard unused void priv pointer".
- Add new patch "spi: dw: Discard dma_width member of the dw_spi structure".
n_bytes member of the DW SPI data can be used instead.
- Build the DMA functionality into the DW APB SSI core if required instead
of creating a separate kernel module.
- Use conditional statement instead of the ternary operator in the ref
clock getter.
Link: https://lore.kernel.org/linux-spi/20200515104758.6934-1-Sergey.Semin@baikalelectronics.ru/
Changelog v3:
- Use spi_delay_exec() method to wait for the DMA operation completion.
- Explicitly initialize the dw_dma_slave members on stack.
- Discard the dws->fifo_len utilization in the Tx FIFO DMA threshold
setting from the patch where we just add the default burst length
constants.
- Use min() method to calculate the optimal burst values.
- Add new patch which moves the spi-dw.c source file to spi-dw-core.c in
order to preserve the DW APB SSI core driver name.
- Add commas in the debugfs_reg32 structure initializer and after the last
entry of the dw_spi_dbgfs_regs array.
Co-developed-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Signed-off-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Co-developed-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Maxim Kaurkin <Maxim.Kaurkin@baikalelectronics.ru>
Cc: Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>
Cc: Ekaterina Skachko <Ekaterina.Skachko@baikalelectronics.ru>
Cc: Vadim Vlasov <V.Vlasov@baikalelectronics.ru>
Cc: Alexey Kolotnikov <Alexey.Kolotnikov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: linux-spi@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Serge Semin (16):
spi: dw: Add Tx/Rx finish wait methods to the MID DMA
spi: dw: Enable interrupts in accordance with DMA xfer mode
spi: dw: Discard static DW DMA slave structures
spi: dw: Discard unused void priv pointer
spi: dw: Discard dma_width member of the dw_spi structure
spi: dw: Parameterize the DMA Rx/Tx burst length
spi: dw: Use DMA max burst to set the request thresholds
spi: dw: Fix Rx-only DMA transfers
spi: dw: Add core suffix to the DW APB SSI core source file
spi: dw: Move Non-DMA code to the DW PCIe-SPI driver
spi: dw: Remove DW DMA code dependency from DW_DMAC_PCI
spi: dw: Add DW SPI DMA/PCI/MMIO dependency on the DW SPI core
spi: dw: Cleanup generic DW DMA code namings
spi: dw: Add DMA support to the DW SPI MMIO driver
spi: dw: Use regset32 DebugFS method to create regdump file
dt-bindings: spi: Convert DW SPI binding to DT schema
.../bindings/spi/snps,dw-apb-ssi.txt | 44 ---
.../bindings/spi/snps,dw-apb-ssi.yaml | 127 ++++++++
.../devicetree/bindings/spi/spi-dw.txt | 24 --
drivers/spi/Kconfig | 15 +-
drivers/spi/Makefile | 5 +-
drivers/spi/{spi-dw.c => spi-dw-core.c} | 88 ++----
drivers/spi/{spi-dw-mid.c => spi-dw-dma.c} | 276 +++++++++++-------
drivers/spi/spi-dw-mmio.c | 4 +
drivers/spi/spi-dw-pci.c | 50 +++-
drivers/spi/spi-dw.h | 33 ++-
10 files changed, 407 insertions(+), 259 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.txt
create mode 100644 Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
delete mode 100644 Documentation/devicetree/bindings/spi/spi-dw.txt
rename drivers/spi/{spi-dw.c => spi-dw-core.c} (82%)
rename drivers/spi/{spi-dw-mid.c => spi-dw-dma.c} (53%)
--
2.25.1
^ permalink raw reply
* [PATCH v3 03/16] spi: dw: Discard static DW DMA slave structures
From: Serge Semin @ 2020-05-21 1:21 UTC (permalink / raw)
To: Mark Brown
Cc: Serge Semin, Serge Semin, Georgy Vlasov, Ramil Zaripov,
Alexey Malahov, Thomas Bogendoerfer, Paul Burton, Ralf Baechle,
Andy Shevchenko, Arnd Bergmann, Rob Herring, linux-mips,
devicetree, Thomas Gleixner, Wan Ahmad Zainie, Jarkko Nikula,
Clement Leger, linux-spi, linux-kernel
In-Reply-To: <20200521012206.14472-1-Sergey.Semin@baikalelectronics.ru>
Having them declared is redundant since each struct dw_dma_chan has
the same structure embedded and the structure from the passed dma_chan
private pointer will be copied there as a result of the next calls
chain:
dma_request_channel() -> find_candidate() -> dma_chan_get() ->
device_alloc_chan_resources() = dwc_alloc_chan_resources() ->
dw_dma_filter().
So just remove the static dw_dma_chan structures and use a locally
declared data instance with dst_id/src_id set to the same values as
the static copies used to have.
Co-developed-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Signed-off-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Co-developed-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
Changelog v3:
- Explicitly initialize the dw_dma_slave members on stack.
---
drivers/spi/spi-dw-mid.c | 19 ++++++++-----------
drivers/spi/spi-dw.h | 2 --
2 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index cf99832ba271..8446bad0528c 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -21,9 +21,6 @@
#define RX_BUSY 0
#define TX_BUSY 1
-static struct dw_dma_slave mid_dma_tx = { .dst_id = 1 };
-static struct dw_dma_slave mid_dma_rx = { .src_id = 0 };
-
static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
{
struct dw_dma_slave *s = param;
@@ -37,9 +34,11 @@ static bool mid_spi_dma_chan_filter(struct dma_chan *chan, void *param)
static int mid_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
{
+ struct dw_dma_slave slave = {
+ .src_id = 0,
+ .dst_id = 0
+ };
struct pci_dev *dma_dev;
- struct dw_dma_slave *tx = dws->dma_tx;
- struct dw_dma_slave *rx = dws->dma_rx;
dma_cap_mask_t mask;
/*
@@ -54,14 +53,14 @@ static int mid_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
dma_cap_set(DMA_SLAVE, mask);
/* 1. Init rx channel */
- rx->dma_dev = &dma_dev->dev;
- dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, rx);
+ slave.dma_dev = &dma_dev->dev;
+ dws->rxchan = dma_request_channel(mask, mid_spi_dma_chan_filter, &slave);
if (!dws->rxchan)
goto err_exit;
/* 2. Init tx channel */
- tx->dma_dev = &dma_dev->dev;
- dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, tx);
+ slave.dst_id = 1;
+ dws->txchan = dma_request_channel(mask, mid_spi_dma_chan_filter, &slave);
if (!dws->txchan)
goto free_rxchan;
@@ -386,8 +385,6 @@ static const struct dw_spi_dma_ops mfld_dma_ops = {
static void dw_spi_mid_setup_dma_mfld(struct dw_spi *dws)
{
- dws->dma_tx = &mid_dma_tx;
- dws->dma_rx = &mid_dma_rx;
dws->dma_ops = &mfld_dma_ops;
}
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 81364f501b7e..60e9e430ce7b 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -146,8 +146,6 @@ struct dw_spi {
unsigned long dma_chan_busy;
dma_addr_t dma_addr; /* phy address of the Data register */
const struct dw_spi_dma_ops *dma_ops;
- void *dma_tx;
- void *dma_rx;
/* Bus interface info */
void *priv;
--
2.25.1
^ permalink raw reply related
* [PATCH v3 01/16] spi: dw: Add Tx/Rx finish wait methods to the MID DMA
From: Serge Semin @ 2020-05-21 1:21 UTC (permalink / raw)
To: Mark Brown, Grant Likely, Vinod Koul, Feng Tang, Alan Cox,
Linus Walleij
Cc: Serge Semin, Serge Semin, Georgy Vlasov, Ramil Zaripov,
Alexey Malahov, Thomas Bogendoerfer, Paul Burton, Ralf Baechle,
Arnd Bergmann, Andy Shevchenko, Rob Herring, linux-mips,
devicetree, Jarkko Nikula, Thomas Gleixner, Wan Ahmad Zainie,
Linus Walleij, Clement Leger, linux-spi, linux-kernel
In-Reply-To: <20200521012206.14472-1-Sergey.Semin@baikalelectronics.ru>
Since DMA transfers are performed asynchronously with actual SPI
transaction, then even if DMA transfers are finished it doesn't mean
all data is actually pushed to the SPI bus. Some data might still be
in the controller FIFO. This is specifically true for Tx-only
transfers. In this case if the next SPI transfer is recharged while
a tail of the previous one is still in FIFO, we'll loose that tail
data. In order to fix this lets add the wait procedure of the Tx/Rx
SPI transfers completion after the corresponding DMA transactions
are finished.
Co-developed-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Signed-off-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Fixes: 7063c0d942a1 ("spi/dw_spi: add DMA support")
Cc: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
Changelog v2:
- Use conditional statement instead of the ternary operator in the ref
clock getter.
- Move the patch to the head of the series so one could be picked up to
the stable kernels as a fix.
Changelog v3:
- Use spi_delay_exec() method to wait for the current operation completion.
---
drivers/spi/spi-dw-mid.c | 69 ++++++++++++++++++++++++++++++++++++++++
drivers/spi/spi-dw.h | 10 ++++++
2 files changed, 79 insertions(+)
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index f9757a370699..3526b196a7fc 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -17,6 +17,7 @@
#include <linux/pci.h>
#include <linux/platform_data/dma-dw.h>
+#define WAIT_RETRIES 5
#define RX_BUSY 0
#define TX_BUSY 1
@@ -143,6 +144,47 @@ static enum dma_slave_buswidth convert_dma_width(u32 dma_width) {
return DMA_SLAVE_BUSWIDTH_UNDEFINED;
}
+static void dw_spi_dma_calc_delay(struct dw_spi *dws, u32 nents,
+ struct spi_delay *delay)
+{
+ unsigned long ns, us;
+
+ ns = (NSEC_PER_SEC / spi_get_clk(dws)) * nents * dws->n_bytes *
+ BITS_PER_BYTE;
+
+ if (ns <= NSEC_PER_USEC) {
+ delay->unit = SPI_DELAY_UNIT_NSECS;
+ delay->value = ns;
+ } else {
+ us = DIV_ROUND_UP(ns, NSEC_PER_USEC);
+ delay->unit = SPI_DELAY_UNIT_USECS;
+ delay->value = clamp_val(us, 0, USHRT_MAX);
+ }
+}
+
+static inline bool dw_spi_dma_tx_busy(struct dw_spi *dws)
+{
+ return !(dw_readl(dws, DW_SPI_SR) & SR_TF_EMPT);
+}
+
+static void dw_spi_dma_wait_tx_done(struct dw_spi *dws)
+{
+ int retry = WAIT_RETRIES;
+ struct spi_delay delay;
+ u32 nents;
+
+ nents = dw_readl(dws, DW_SPI_TXFLR);
+ dw_spi_dma_calc_delay(dws, nents, &delay);
+
+ while (dw_spi_dma_tx_busy(dws) && retry--)
+ spi_delay_exec(&delay, NULL);
+
+ if (retry < 0) {
+ dev_err(&dws->master->dev, "Tx hanged up\n");
+ dws->master->cur_msg->status = -EIO;
+ }
+}
+
/*
* dws->dma_chan_busy is set before the dma transfer starts, callback for tx
* channel will clear a corresponding bit.
@@ -151,6 +193,8 @@ static void dw_spi_dma_tx_done(void *arg)
{
struct dw_spi *dws = arg;
+ dw_spi_dma_wait_tx_done(dws);
+
clear_bit(TX_BUSY, &dws->dma_chan_busy);
if (test_bit(RX_BUSY, &dws->dma_chan_busy))
return;
@@ -192,6 +236,29 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx(struct dw_spi *dws,
return txdesc;
}
+static inline bool dw_spi_dma_rx_busy(struct dw_spi *dws)
+{
+ return !!(dw_readl(dws, DW_SPI_SR) & SR_RF_NOT_EMPT);
+}
+
+static void dw_spi_dma_wait_rx_done(struct dw_spi *dws)
+{
+ int retry = WAIT_RETRIES;
+ struct spi_delay delay;
+ u32 nents;
+
+ nents = dw_readl(dws, DW_SPI_RXFLR);
+ dw_spi_dma_calc_delay(dws, nents, &delay);
+
+ while (dw_spi_dma_rx_busy(dws) && retry--)
+ spi_delay_exec(&delay, NULL);
+
+ if (retry < 0) {
+ dev_err(&dws->master->dev, "Rx hanged up\n");
+ dws->master->cur_msg->status = -EIO;
+ }
+}
+
/*
* dws->dma_chan_busy is set before the dma transfer starts, callback for rx
* channel will clear a corresponding bit.
@@ -200,6 +267,8 @@ static void dw_spi_dma_rx_done(void *arg)
{
struct dw_spi *dws = arg;
+ dw_spi_dma_wait_rx_done(dws);
+
clear_bit(RX_BUSY, &dws->dma_chan_busy);
if (test_bit(TX_BUSY, &dws->dma_chan_busy))
return;
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index e92d43b9a9e6..81364f501b7e 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -210,6 +210,16 @@ static inline void spi_set_clk(struct dw_spi *dws, u16 div)
dw_writel(dws, DW_SPI_BAUDR, div);
}
+static inline u32 spi_get_clk(struct dw_spi *dws)
+{
+ u32 div = dw_readl(dws, DW_SPI_BAUDR);
+
+ if (!div)
+ return 0;
+
+ return dws->max_freq / div;
+}
+
/* Disable IRQ bits */
static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
{
--
2.25.1
^ permalink raw reply related
* [PATCH v3 02/16] spi: dw: Enable interrupts in accordance with DMA xfer mode
From: Serge Semin @ 2020-05-21 1:21 UTC (permalink / raw)
To: Mark Brown
Cc: Serge Semin, Serge Semin, Georgy Vlasov, Ramil Zaripov,
Alexey Malahov, Thomas Bogendoerfer, Paul Burton, Ralf Baechle,
Arnd Bergmann, Andy Shevchenko, Rob Herring, linux-mips,
devicetree, Jarkko Nikula, Thomas Gleixner, Wan Ahmad Zainie,
linux-spi, linux-kernel
In-Reply-To: <20200521012206.14472-1-Sergey.Semin@baikalelectronics.ru>
It's pointless to track the Tx overrun interrupts if Rx-only SPI
transfer is issued. Similarly there is no need in handling the Rx
overrun/underrun interrupts if Tx-only SPI transfer is executed.
So lets unmask the interrupts only if corresponding SPI
transactions are implied.
Co-developed-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Signed-off-by: Georgy Vlasov <Georgy.Vlasov@baikalelectronics.ru>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
drivers/spi/spi-dw-mid.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
index 3526b196a7fc..cf99832ba271 100644
--- a/drivers/spi/spi-dw-mid.c
+++ b/drivers/spi/spi-dw-mid.c
@@ -312,19 +312,23 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws,
static int mid_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer)
{
- u16 dma_ctrl = 0;
+ u16 imr = 0, dma_ctrl = 0;
dw_writel(dws, DW_SPI_DMARDLR, 0xf);
dw_writel(dws, DW_SPI_DMATDLR, 0x10);
- if (xfer->tx_buf)
+ if (xfer->tx_buf) {
dma_ctrl |= SPI_DMA_TDMAE;
- if (xfer->rx_buf)
+ imr |= SPI_INT_TXOI;
+ }
+ if (xfer->rx_buf) {
dma_ctrl |= SPI_DMA_RDMAE;
+ imr |= SPI_INT_RXUI | SPI_INT_RXOI;
+ }
dw_writel(dws, DW_SPI_DMACR, dma_ctrl);
/* Set the interrupt mask */
- spi_umask_intr(dws, SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI);
+ spi_umask_intr(dws, imr);
dws->transfer_handler = dma_transfer;
--
2.25.1
^ permalink raw reply related
* Re: [PATCH v4 3/9] usb: dwc3: Increase timeout for CmdAct cleared by device controller
From: Thinh Nguyen @ 2020-05-21 1:07 UTC (permalink / raw)
To: Jun Li, Thinh Nguyen, Felipe Balbi, Jun Li
Cc: John Stultz, lkml, Yu Chen, Greg Kroah-Hartman, Rob Herring,
Mark Rutland, ShuFan Lee, Heikki Krogerus, Suzuki K Poulose,
Chunfeng Yun, Hans de Goede, Andy Shevchenko, Valentin Schneider,
Jack Pham, Linux USB List,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Peter Chen
In-Reply-To: <VE1PR04MB65286728B9546B5FAA818A0A89B90@VE1PR04MB6528.eurprd04.prod.outlook.com>
Jun Li wrote:
> Hi
>
>> -----Original Message-----
>> From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
>> Sent: 2020年5月19日 14:46
>> To: Jun Li <jun.li@nxp.com>; Felipe Balbi <balbi@kernel.org>; Jun Li
>> <lijun.kernel@gmail.com>
>> Cc: John Stultz <john.stultz@linaro.org>; lkml <linux-kernel@vger.kernel.org>; Yu
>> Chen <chenyu56@huawei.com>; Greg Kroah-Hartman <gregkh@linuxfoundation.org>; Rob
>> Herring <robh+dt@kernel.org>; Mark Rutland <mark.rutland@arm.com>; ShuFan Lee
>> <shufan_lee@richtek.com>; Heikki Krogerus <heikki.krogerus@linux.intel.com>;
>> Suzuki K Poulose <suzuki.poulose@arm.com>; Chunfeng Yun
>> <chunfeng.yun@mediatek.com>; Hans de Goede <hdegoede@redhat.com>; Andy Shevchenko
>> <andy.shevchenko@gmail.com>; Valentin Schneider <valentin.schneider@arm.com>;
>> Jack Pham <jackp@codeaurora.org>; Linux USB List <linux-usb@vger.kernel.org>; open
>> list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS <devicetree@vger.kernel.org>;
>> Peter Chen <peter.chen@nxp.com>
>> Subject: Re: [PATCH v4 3/9] usb: dwc3: Increase timeout for CmdAct cleared by device
>> controller
>>
>> Thinh Nguyen wrote:
>>> Jun Li wrote:
>>>>> -----Original Message-----
>>>>> From: Felipe Balbi <balbif@gmail.com> On Behalf Of Felipe Balbi
>>>>> Sent: 2020年5月16日 19:57
>>>>> To: Jun Li <jun.li@nxp.com>; Thinh Nguyen
>>>>> <Thinh.Nguyen@synopsys.com>; Jun Li <lijun.kernel@gmail.com>
>>>>> Cc: John Stultz <john.stultz@linaro.org>; lkml
>>>>> <linux-kernel@vger.kernel.org>; Yu Chen <chenyu56@huawei.com>; Greg
>>>>> Kroah-Hartman <gregkh@linuxfoundation.org>; Rob Herring
>>>>> <robh+dt@kernel.org>; Mark Rutland <mark.rutland@arm.com>; ShuFan
>>>>> Lee <shufan_lee@richtek.com>; Heikki Krogerus
>>>>> <heikki.krogerus@linux.intel.com>;
>>>>> Suzuki K Poulose <suzuki.poulose@arm.com>; Chunfeng Yun
>>>>> <chunfeng.yun@mediatek.com>; Hans de Goede <hdegoede@redhat.com>;
>>>>> Andy Shevchenko <andy.shevchenko@gmail.com>; Valentin Schneider
>>>>> <valentin.schneider@arm.com>; Jack Pham <jackp@codeaurora.org>;
>>>>> Linux USB List <linux-usb@vger.kernel.org>; open list:OPEN FIRMWARE
>>>>> AND FLATTENED DEVICE TREE BINDINGS <devicetree@vger.kernel.org>;
>>>>> Peter Chen <peter.chen@nxp.com>; Thinh Nguyen
>>>>> <Thinh.Nguyen@synopsys.com>
>>>>> Subject: RE: [PATCH v4 3/9] usb: dwc3: Increase timeout for CmdAct
>>>>> cleared by device controller
>>>>>
>>>>>
>>>>> Hi,
>>>>>
>>>>> Jun Li <jun.li@nxp.com> writes:
>>>>>>>>> Hi Thinh, could you comment this?
>>>>>>>> You only need to wake up the usb2 phy when issuing the command
>>>>>>>> while running in highspeed or below. If you're running in SS or
>>>>>>>> higher, internally the controller does it for you for usb3 phy.
>>>>>>>> In Jun's case, it seems like it takes longer for his phy to wake up.
>>>>>>>>
>>>>>>>> IMO, in this case, I think it's fine to increase the command timeout.
>>>>>>> Is there an upper limit to this? Is 32k clock the slowest that can
>>>>>>> be fed to the PHY as a suspend clock?
>>>>>> Yes, 32K clock is the slowest, Per DWC3 document on Power Down
>>>>>> Scale (bits 31:19 of GCTL):
>>>>>>
>>>>>> "Power Down Scale (PwrDnScale)
>>>>>> The USB3 suspend_clk input replaces pipe3_rx_pclk as a clock source
>>>>>> to a small part of the USB3 controller that operates when the SS
>>>>>> PHY is in its lowest power (P3) state, and therefore does not provide a clock.
>>>>>> The Power Down Scale field specifies how many suspend_clk periods
>>>>>> fit into a 16 kHz clock period. When performing the division, round
>>>>>> up the remainder.
>>>>>> For example, when using an 8-bit/16-bit/32-bit PHY and 25-MHz
>>>>>> Suspend clock, Power Down Scale = 25000 kHz/16 kHz = 13'd1563
>>>>>> (rounder up)
>>>>>> Note:
>>>>>> - Minimum Suspend clock frequency is 32 kHz
>>>>>> - Maximum Suspend clock frequency is 125 MHz"
>>>>> Cool, now do we have an upper bound for how many clock cycles it
>>>>> takes to wake up the PHY?
>>>> My understanding is this ep command does not wake up the SS PHY, the
>>>> SS PHY still stays at P3 when execute this ep command. The time
>>>> required here is to wait controller complete something for this ep
>>>> command with 32K clock.
>>> Sorry I made a mistake. You're right. Just checked with one of the RTL
>>> engineers, and it doesn't need to wake up the phy. However, if it is
>>> eSS speed, it may take longer time as the command may be completing
>>> with the suspend clock.
>>>
>> What's the value for GCTL[7:6]?
> 2'b00
>
> Thanks
> Li Jun
(Sorry for the delay reply)
If it's 0, then the ram clock should be the same as the bus_clk, which
is odd since you mentioned that the suspend_clk is used instead while in P3.
Anyway, I was looking for a way maybe to improve the speed during
issuing a command. One way is to set GUSB3PIPECTL[17]=0, and it should
wakeup the phy anytime. I think Felipe suggested it. It's odd that it
doesn't work for you. I don't have other ideas beside increasing the
command timeout.
Thanks,
Thinh
^ permalink raw reply
* [PATCH v4 6/7] clocksource: mips-gic-timer: Register as sched_clock
From: Serge Semin @ 2020-05-21 0:53 UTC (permalink / raw)
To: Thomas Gleixner, Thomas Bogendoerfer, Daniel Lezcano
Cc: Serge Semin, Serge Semin, Paul Burton, Alexey Malahov,
Ralf Baechle, Alessandro Zummo, Alexandre Belloni, Arnd Bergmann,
Rob Herring, linux-mips, linux-rtc, devicetree, Vincenzo Frascino,
linux-kernel
In-Reply-To: <20200521005321.12129-1-Sergey.Semin@baikalelectronics.ru>
From: Paul Burton <paulburton@kernel.org>
The MIPS GIC timer is well suited for use as sched_clock, so register it
as such.
Whilst the existing gic_read_count() function matches the prototype
needed by sched_clock_register() already, we split it into 2 functions
in order to remove the need to evaluate the mips_cm_is64 condition
within each call since sched_clock should be as fast as possible.
Note the sched clock framework needs the clock source being stable in
order to rely on it. So we register the MIPS GIC timer as schedule clocks
only if it's, if either the system doesn't have CPU-frequency enabled or
the CPU frequency is changed by means of the CPC core clock divider
available on the platforms with CM3 or newer.
Signed-off-by: Paul Burton <paulburton@kernel.org>
Co-developed-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
[Sergey.Semin@baikalelectronics.ru: Register sched-clock if CM3 or !CPU-freq]
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: linux-rtc@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
Changelog v3:
- Register sched clocks only if MIPS GIC belongs to CM3 or if CPU-freq
isn't supported.
---
drivers/clocksource/mips-gic-timer.c | 31 ++++++++++++++++++++++++----
1 file changed, 27 insertions(+), 4 deletions(-)
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c
index 8b5f8ae723cb..ef12c12c2432 100644
--- a/drivers/clocksource/mips-gic-timer.c
+++ b/drivers/clocksource/mips-gic-timer.c
@@ -16,6 +16,7 @@
#include <linux/notifier.h>
#include <linux/of_irq.h>
#include <linux/percpu.h>
+#include <linux/sched_clock.h>
#include <linux/smp.h>
#include <linux/time.h>
#include <asm/mips-cps.h>
@@ -24,13 +25,10 @@ static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device);
static int gic_timer_irq;
static unsigned int gic_frequency;
-static u64 notrace gic_read_count(void)
+static u64 notrace gic_read_count_2x32(void)
{
unsigned int hi, hi2, lo;
- if (mips_cm_is64)
- return read_gic_counter();
-
do {
hi = read_gic_counter_32h();
lo = read_gic_counter_32l();
@@ -40,6 +38,19 @@ static u64 notrace gic_read_count(void)
return (((u64) hi) << 32) + lo;
}
+static u64 notrace gic_read_count_64(void)
+{
+ return read_gic_counter();
+}
+
+static u64 notrace gic_read_count(void)
+{
+ if (mips_cm_is64)
+ return gic_read_count_64();
+
+ return gic_read_count_2x32();
+}
+
static int gic_next_event(unsigned long delta, struct clock_event_device *evt)
{
int cpu = cpumask_first(evt->cpumask);
@@ -228,6 +239,18 @@ static int __init gic_clocksource_of_init(struct device_node *node)
/* And finally start the counter */
clear_gic_config(GIC_CONFIG_COUNTSTOP);
+ /*
+ * It's safe to use the MIPS GIC timer as a sched clock source only if
+ * its ticks are stable, which is true on either the platforms with
+ * stable CPU frequency or on the platforms with CM3 and CPU frequency
+ * change performed by the CPC core clocks divider.
+ */
+ if (mips_cm_revision() >= CM_REV_CM3 || !IS_ENABLED(CONFIG_CPU_FREQ)) {
+ sched_clock_register(mips_cm_is64 ?
+ gic_read_count_64 : gic_read_count_2x32,
+ 64, gic_frequency);
+ }
+
return 0;
}
TIMER_OF_DECLARE(mips_gic_timer, "mti,gic-timer",
--
2.25.1
^ permalink raw reply related
* [PATCH v4 5/7] clocksource: dw_apb_timer_of: Fix missing clockevent timers
From: Serge Semin @ 2020-05-21 0:53 UTC (permalink / raw)
To: Thomas Gleixner, Thomas Bogendoerfer, Daniel Lezcano, Jamie Iles,
Rob Herring, Dinh Nguyen, Heiko Stuebner, Arnd Bergmann
Cc: Serge Semin, Serge Semin, Alexey Malahov, Paul Burton,
Ralf Baechle, Alessandro Zummo, Alexandre Belloni, Rob Herring,
linux-mips, linux-rtc, devicetree, Allison Randal,
Greg Kroah-Hartman, Alexios Zavras, linux-kernel
In-Reply-To: <20200521005321.12129-1-Sergey.Semin@baikalelectronics.ru>
Commit 100214889973 ("clocksource: dw_apb_timer_of: use
clocksource_of_init") replaced a publicly available driver
initialization method with one called by the timer_probe() method
available after CLKSRC_OF. In current implementation it traverses
all the timers available in the system and calls their initialization
methods if corresponding devices were either in dtb or in acpi. But
if before the commit any number of available timers would be installed
as clockevent and clocksource devices, after that there would be at most
two. The rest are just ignored since default case branch doesn't do
anything. I don't see a reason of such behaviour, neither the commit
message explains it. Moreover this might be wrong if on some platforms
these timers might be used for different purpose, as virtually CPU-local
clockevent timers and as an independent broadcast timer. So in order
to keep the compatibility with the platforms where the order of the
timers detection has some meaning, lets add the secondly discovered
timer to be of clocksource/sched_clock type, while the very first and
the others would provide the clockevents service.
Fixes: 100214889973 ("clocksource: dw_apb_timer_of: use clocksource_of_init")
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: linux-rtc@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
drivers/clocksource/dw_apb_timer_of.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index 0a2505b323d7..0b61b90a525e 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -146,10 +146,6 @@ static int num_called;
static int __init dw_apb_timer_init(struct device_node *timer)
{
switch (num_called) {
- case 0:
- pr_debug("%s: found clockevent timer\n", __func__);
- add_clockevent(timer);
- break;
case 1:
pr_debug("%s: found clocksource timer\n", __func__);
add_clocksource(timer);
@@ -160,6 +156,8 @@ static int __init dw_apb_timer_init(struct device_node *timer)
#endif
break;
default:
+ pr_debug("%s: found clockevent timer\n", __func__);
+ add_clockevent(timer);
break;
}
--
2.25.1
^ permalink raw reply related
* [PATCH v4 7/7] clocksource: mips-gic-timer: Mark GIC timer as unstable if ref clock changes
From: Serge Semin @ 2020-05-21 0:53 UTC (permalink / raw)
To: Thomas Gleixner, Thomas Bogendoerfer, Daniel Lezcano
Cc: Serge Semin, Serge Semin, Alexey Malahov, Paul Burton,
Ralf Baechle, Alessandro Zummo, Alexandre Belloni, Arnd Bergmann,
Rob Herring, linux-mips, linux-rtc, devicetree, Paul Cercueil,
Krzysztof Kozlowski, Geert Uytterhoeven, Randy Dunlap,
Claudiu Beznea, Maarten ter Huurne, Vincenzo Frascino,
linux-kernel
In-Reply-To: <20200521005321.12129-1-Sergey.Semin@baikalelectronics.ru>
Currently clocksource framework doesn't support the clocks with variable
frequency. Since MIPS GIC timer ticks rate might be unstable on some
platforms, we must make sure that it justifies the clocksource
requirements. MIPS GIC timer is incremented with the CPU cluster reference
clocks rate. So in case if CPU frequency changes, the MIPS GIC tick rate
changes synchronously. Due to this the clocksource subsystem can't rely on
the timer to measure system clocks anymore. This commit marks the MIPS GIC
based clocksource as unstable if reference clock (normally it's a CPU
reference clocks) rate changes. The clocksource will execute a watchdog
thread, which lowers the MIPS GIC timer rating to zero and fallbacks to a
new stable one.
Note we don't need to set the CLOCK_SOURCE_MUST_VERIFY flag to the MIPS
GIC clocksource since normally the timer is stable. The only reason why
it gets unstable is due to the ref clock rate change, which event we
detect here in the driver by means of the clocks event notifier.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: linux-rtc@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
Changelog v3:
- Mark clocksource as unstable instead of lowering its rating.
---
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/mips-gic-timer.c | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index f2142e6bbea3..37a745f3ca91 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -572,6 +572,7 @@ config CLKSRC_VERSATILE
config CLKSRC_MIPS_GIC
bool
depends on MIPS_GIC
+ select CLOCKSOURCE_WATCHDOG
select TIMER_OF
config CLKSRC_TANGO_XTAL
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c
index ef12c12c2432..d78ad7b60cdc 100644
--- a/drivers/clocksource/mips-gic-timer.c
+++ b/drivers/clocksource/mips-gic-timer.c
@@ -24,6 +24,9 @@
static DEFINE_PER_CPU(struct clock_event_device, gic_clockevent_device);
static int gic_timer_irq;
static unsigned int gic_frequency;
+static bool __read_mostly gic_clock_unstable;
+
+static void git_clocksource_unstable(char *reason);
static u64 notrace gic_read_count_2x32(void)
{
@@ -125,8 +128,10 @@ static int gic_clk_notifier(struct notifier_block *nb, unsigned long action,
{
struct clk_notifier_data *cnd = data;
- if (action == POST_RATE_CHANGE)
+ if (action == POST_RATE_CHANGE) {
+ git_clocksource_unstable("ref clock rate change");
on_each_cpu(gic_update_frequency, (void *)cnd->new_rate, 1);
+ }
return NOTIFY_OK;
}
@@ -172,6 +177,18 @@ static struct clocksource gic_clocksource = {
.vdso_clock_mode = VDSO_CLOCKMODE_GIC,
};
+static void git_clocksource_unstable(char *reason)
+{
+ if (gic_clock_unstable)
+ return;
+
+ gic_clock_unstable = true;
+
+ pr_info("GIC timer is unstable due to %s\n", reason);
+
+ clocksource_mark_unstable(&gic_clocksource);
+}
+
static int __init __gic_clocksource_init(void)
{
unsigned int count_width;
--
2.25.1
^ permalink raw reply related
* [PATCH v4 4/7] clocksource: dw_apb_timer: Set clockevent any-possible-CPU mask
From: Serge Semin @ 2020-05-21 0:53 UTC (permalink / raw)
To: Thomas Gleixner, Thomas Bogendoerfer, Daniel Lezcano
Cc: Serge Semin, Serge Semin, Alexey Malahov, Paul Burton,
Ralf Baechle, Alessandro Zummo, Alexandre Belloni, Arnd Bergmann,
Rob Herring, linux-mips, linux-rtc, devicetree, Allison Randal,
afzal mohammed, Kate Stewart, Greg Kroah-Hartman, Enrico Weigelt,
Alexios Zavras, linux-kernel
In-Reply-To: <20200521005321.12129-1-Sergey.Semin@baikalelectronics.ru>
Currently the DW APB Timer driver binds all clockevent timers to
CPU #0. This isn't good for multiple reasons. First of all seeing
the device is placed on APB bus (which makes it accessible from any
CPU core), accessible over MMIO and having the DYNIRQ flag set we
can be sure that manually binding the timer to any CPU just isn't
correct. By doing so we just set an extra limitation on device usage.
This also doesn't reflect the device actual capability, since by
setting the IRQ affinity we can make it virtually local to any CPU.
Secondly imagine if you had a real CPU-local timer with the same
rating and the same CPU-affinity. In this case if DW APB timer was
registered first, then due to the clockevent framework tick-timer
selection procedure we'll end up with the real CPU-local timer being
left unselected for clock-events tracking. But on most of the platforms
(MIPS/ARM/etc) such timers are normally embedded into the CPU core and
are accessible with much better performance then devices placed on APB.
For instance in MIPS architectures there is r4k-timer, which is
CPU-local, assigned with the same rating, and normally its
clockevent device is registered after the platform-specific one.
So in order to fix all of these issues lets set the DW APB clockevent
timer cpumask to be 'cpu_possible_mask'. By doing so the clockevent
framework would prefer to select the real CPU-local timer instead
of DW APB one. Otherwise if there is no other than DW APB device for
clockevents tracking then it will be selected.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: linux-rtc@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
drivers/clocksource/dw_apb_timer.c | 18 +++++++-----------
drivers/clocksource/dw_apb_timer_of.c | 3 +--
include/linux/dw_apb_timer.h | 2 +-
3 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
index b207a77b0831..8ebb43916423 100644
--- a/drivers/clocksource/dw_apb_timer.c
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -106,6 +106,7 @@ static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
dw_ced->eoi(&dw_ced->timer);
evt->event_handler(evt);
+
return IRQ_HANDLED;
}
@@ -123,8 +124,7 @@ static int apbt_shutdown(struct clock_event_device *evt)
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
u32 ctrl;
- pr_debug("%s CPU %d state=shutdown\n", __func__,
- cpumask_first(evt->cpumask));
+ pr_debug("%s state=shutdown\n", __func__);
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
ctrl &= ~APBTMR_CONTROL_ENABLE;
@@ -137,8 +137,7 @@ static int apbt_set_oneshot(struct clock_event_device *evt)
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
u32 ctrl;
- pr_debug("%s CPU %d state=oneshot\n", __func__,
- cpumask_first(evt->cpumask));
+ pr_debug("%s state=oneshot\n", __func__);
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
/*
@@ -170,8 +169,7 @@ static int apbt_set_periodic(struct clock_event_device *evt)
unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ);
u32 ctrl;
- pr_debug("%s CPU %d state=periodic\n", __func__,
- cpumask_first(evt->cpumask));
+ pr_debug("%s state=periodic\n", __func__);
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
@@ -194,8 +192,7 @@ static int apbt_resume(struct clock_event_device *evt)
{
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
- pr_debug("%s CPU %d state=resume\n", __func__,
- cpumask_first(evt->cpumask));
+ pr_debug("%s state=resume\n", __func__);
apbt_enable_int(&dw_ced->timer);
return 0;
@@ -222,7 +219,6 @@ static int apbt_next_event(unsigned long delta,
/**
* dw_apb_clockevent_init() - use an APB timer as a clock_event_device
*
- * @cpu: The CPU the events will be targeted at.
* @name: The name used for the timer and the IRQ for it.
* @rating: The rating to give the timer.
* @base: I/O base for the timer registers.
@@ -237,7 +233,7 @@ static int apbt_next_event(unsigned long delta,
* releasing the IRQ.
*/
struct dw_apb_clock_event_device *
-dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
+dw_apb_clockevent_init(const char *name, unsigned int rating,
void __iomem *base, int irq, unsigned long freq)
{
struct dw_apb_clock_event_device *dw_ced =
@@ -257,7 +253,7 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
dw_ced->ced.max_delta_ticks = 0x7fffffff;
dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced);
dw_ced->ced.min_delta_ticks = 5000;
- dw_ced->ced.cpumask = cpumask_of(cpu);
+ dw_ced->ced.cpumask = cpu_possible_mask;
dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ;
dw_ced->ced.set_state_shutdown = apbt_shutdown;
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index 8c28b127759f..0a2505b323d7 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -73,8 +73,7 @@ static void __init add_clockevent(struct device_node *event_timer)
timer_get_base_and_rate(event_timer, &iobase, &rate);
- ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq,
- rate);
+ ced = dw_apb_clockevent_init(event_timer->name, 300, iobase, irq, rate);
if (!ced)
panic("Unable to initialise clockevent device");
diff --git a/include/linux/dw_apb_timer.h b/include/linux/dw_apb_timer.h
index 82ebf9223948..689022bc8d17 100644
--- a/include/linux/dw_apb_timer.h
+++ b/include/linux/dw_apb_timer.h
@@ -39,7 +39,7 @@ void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced);
void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced);
struct dw_apb_clock_event_device *
-dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
+dw_apb_clockevent_init(const char *name, unsigned int rating,
void __iomem *base, int irq, unsigned long freq);
struct dw_apb_clocksource *
dw_apb_clocksource_init(unsigned rating, const char *name, void __iomem *base,
--
2.25.1
^ permalink raw reply related
* [PATCH v4 3/7] dt-bindings: interrupt-controller: Convert mti,gic to DT schema
From: Serge Semin @ 2020-05-21 0:53 UTC (permalink / raw)
To: Thomas Gleixner, Thomas Bogendoerfer, Daniel Lezcano,
Jason Cooper, Marc Zyngier, Rob Herring
Cc: Serge Semin, Serge Semin, Rob Herring, Alexey Malahov,
Paul Burton, Ralf Baechle, Alessandro Zummo, Alexandre Belloni,
Arnd Bergmann, linux-mips, linux-rtc, linux-kernel, devicetree
In-Reply-To: <20200521005321.12129-1-Sergey.Semin@baikalelectronics.ru>
Modern device tree bindings are supposed to be created as YAML-files
in accordance with DT schema. This commit replaces MIPS GIC legacy bare
text binding with YAML file. As before the binding file states that the
corresponding dts node is supposed to be compatible with MIPS Global
Interrupt Controller indicated by the "mti,gic" compatible string and
to provide a mandatory interrupt-controller and '#interrupt-cells'
properties. There might be optional registers memory range,
"mti,reserved-cpu-vectors" and "mti,reserved-ipi-vectors" properties
specified.
MIPS GIC also includes a free-running global timer, per-CPU count/compare
timers, and a watchdog. Since currently the GIC Timer is only supported the
DT schema expects an IRQ and clock-phandler charged timer sub-node with
"mti,mips-gic-timer" compatible string.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Rob Herring <robh@kernel.org>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-mips@vger.kernel.org
Cc: linux-rtc@vger.kernel.org
---
I don't really know who is the corresponding driver maintainer, so I
added Paul to the maintainers property since he used to be looking for the
MIPS arch and Thomas looking after it now. Any idea what email should be
specified there instead?
Changelog v3:
- Since timer sub-node has no unit-address, the node shouldn't be named
with one. So alter the MIPS GIC bindings to have a pure "timer"
sub-node.
- Discard allOf: [ $ref: /schemas/interrupt-controller.yaml# ].
- Since it's a conversion patch use GPL-2.0-only SPDX header.
---
.../interrupt-controller/mips-gic.txt | 67 --------
.../interrupt-controller/mti,gic.yaml | 148 ++++++++++++++++++
2 files changed, 148 insertions(+), 67 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/interrupt-controller/mips-gic.txt
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/mti,gic.yaml
diff --git a/Documentation/devicetree/bindings/interrupt-controller/mips-gic.txt b/Documentation/devicetree/bindings/interrupt-controller/mips-gic.txt
deleted file mode 100644
index 173595305e26..000000000000
--- a/Documentation/devicetree/bindings/interrupt-controller/mips-gic.txt
+++ /dev/null
@@ -1,67 +0,0 @@
-MIPS Global Interrupt Controller (GIC)
-
-The MIPS GIC routes external interrupts to individual VPEs and IRQ pins.
-It also supports local (per-processor) interrupts and software-generated
-interrupts which can be used as IPIs. The GIC also includes a free-running
-global timer, per-CPU count/compare timers, and a watchdog.
-
-Required properties:
-- compatible : Should be "mti,gic".
-- interrupt-controller : Identifies the node as an interrupt controller
-- #interrupt-cells : Specifies the number of cells needed to encode an
- interrupt specifier. Should be 3.
- - The first cell is the type of interrupt, local or shared.
- See <include/dt-bindings/interrupt-controller/mips-gic.h>.
- - The second cell is the GIC interrupt number.
- - The third cell encodes the interrupt flags.
- See <include/dt-bindings/interrupt-controller/irq.h> for a list of valid
- flags.
-
-Optional properties:
-- reg : Base address and length of the GIC registers. If not present,
- the base address reported by the hardware GCR_GIC_BASE will be used.
-- mti,reserved-cpu-vectors : Specifies the list of CPU interrupt vectors
- to which the GIC may not route interrupts. Valid values are 2 - 7.
- This property is ignored if the CPU is started in EIC mode.
-- mti,reserved-ipi-vectors : Specifies the range of GIC interrupts that are
- reserved for IPIs.
- It accepts 2 values, the 1st is the starting interrupt and the 2nd is the size
- of the reserved range.
- If not specified, the driver will allocate the last 2 * number of VPEs in the
- system.
-
-Required properties for timer sub-node:
-- compatible : Should be "mti,gic-timer".
-- interrupts : Interrupt for the GIC local timer.
-
-Optional properties for timer sub-node:
-- clocks : GIC timer operating clock.
-- clock-frequency : Clock frequency at which the GIC timers operate.
-
-Note that one of clocks or clock-frequency must be specified.
-
-Example:
-
- gic: interrupt-controller@1bdc0000 {
- compatible = "mti,gic";
- reg = <0x1bdc0000 0x20000>;
-
- interrupt-controller;
- #interrupt-cells = <3>;
-
- mti,reserved-cpu-vectors = <7>;
- mti,reserved-ipi-vectors = <40 8>;
-
- timer {
- compatible = "mti,gic-timer";
- interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
- clock-frequency = <50000000>;
- };
- };
-
- uart@18101400 {
- ...
- interrupt-parent = <&gic>;
- interrupts = <GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH>;
- ...
- };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/mti,gic.yaml b/Documentation/devicetree/bindings/interrupt-controller/mti,gic.yaml
new file mode 100644
index 000000000000..9f0eb3addac4
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/mti,gic.yaml
@@ -0,0 +1,148 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/mti,gic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MIPS Global Interrupt Controller
+
+maintainers:
+ - Paul Burton <paulburton@kernel.org>
+ - Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+
+description: |
+ The MIPS GIC routes external interrupts to individual VPEs and IRQ pins.
+ It also supports local (per-processor) interrupts and software-generated
+ interrupts which can be used as IPIs. The GIC also includes a free-running
+ global timer, per-CPU count/compare timers, and a watchdog.
+
+properties:
+ compatible:
+ const: mti,gic
+
+ "#interrupt-cells":
+ const: 3
+ description: |
+ The 1st cell is the type of interrupt: local or shared defined in the
+ file 'dt-bindings/interrupt-controller/mips-gic.h'. The 2nd cell is the
+ GIC interrupt number. The 3d cell encodes the interrupt flags setting up
+ the IRQ trigger modes, which are defined in the file
+ 'dt-bindings/interrupt-controller/irq.h'.
+
+ reg:
+ description: |
+ Base address and length of the GIC registers space. If not present,
+ the base address reported by the hardware GCR_GIC_BASE will be used.
+ maxItems: 1
+
+ interrupt-controller: true
+
+ mti,reserved-cpu-vectors:
+ description: |
+ Specifies the list of CPU interrupt vectors to which the GIC may not
+ route interrupts. This property is ignored if the CPU is started in EIC
+ mode.
+ allOf:
+ - $ref: /schemas/types.yaml#definitions/uint32-array
+ - minItems: 1
+ maxItems: 6
+ uniqueItems: true
+ items:
+ minimum: 2
+ maximum: 7
+
+ mti,reserved-ipi-vectors:
+ description: |
+ Specifies the range of GIC interrupts that are reserved for IPIs.
+ It accepts two values: the 1st is the starting interrupt and the 2nd is
+ the size of the reserved range. If not specified, the driver will
+ allocate the last (2 * number of VPEs in the system).
+ allOf:
+ - $ref: /schemas/types.yaml#definitions/uint32-array
+ - items:
+ - minimum: 0
+ maximum: 254
+ - minimum: 2
+ maximum: 254
+
+ timer:
+ type: object
+ description: |
+ MIPS GIC includes a free-running global timer, per-CPU count/compare
+ timers, and a watchdog. Currently only the GIC Timer is supported.
+ properties:
+ compatible:
+ const: mti,gic-timer
+
+ interrupts:
+ description: |
+ Interrupt for the GIC local timer, so normally it's suppose to be of
+ <GIC_LOCAL X IRQ_TYPE_NONE> format.
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-frequency: true
+
+ required:
+ - compatible
+ - interrupts
+
+ oneOf:
+ - required:
+ - clocks
+ - required:
+ - clock-frequency
+
+ additionalProperties: false
+
+unevaluatedProperties: false
+
+required:
+ - compatible
+ - "#interrupt-cells"
+ - interrupt-controller
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/mips-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ interrupt-controller@1bdc0000 {
+ compatible = "mti,gic";
+ reg = <0x1bdc0000 0x20000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ mti,reserved-cpu-vectors = <7>;
+ mti,reserved-ipi-vectors = <40 8>;
+
+ timer {
+ compatible = "mti,gic-timer";
+ interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
+ clock-frequency = <50000000>;
+ };
+ };
+ - |
+ #include <dt-bindings/interrupt-controller/mips-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ interrupt-controller@1bdc0000 {
+ compatible = "mti,gic";
+ reg = <0x1bdc0000 0x20000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ timer {
+ compatible = "mti,gic-timer";
+ interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
+ clocks = <&cpu_pll>;
+ };
+ };
+ - |
+ interrupt-controller {
+ compatible = "mti,gic";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+...
--
2.25.1
^ permalink raw reply related
* [PATCH v4 2/7] dt-bindings: timer: Move snps,dw-apb-timer DT schema from rtc
From: Serge Semin @ 2020-05-21 0:53 UTC (permalink / raw)
To: Thomas Gleixner, Thomas Bogendoerfer, Daniel Lezcano,
Alessandro Zummo, Alexandre Belloni, Rob Herring
Cc: Serge Semin, Serge Semin, Rob Herring, Alexey Malahov,
Paul Burton, Ralf Baechle, Arnd Bergmann, linux-mips, linux-rtc,
devicetree, linux-kernel
In-Reply-To: <20200521005321.12129-1-Sergey.Semin@baikalelectronics.ru>
This binding file doesn't belong to the rtc seeing it's a pure timer
with no rtc facilities like days/months/years counting and alarms.
So move the YAML-file to the Documentation/devicetree/bindings/timer/
directory.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Acked-by: Rob Herring <robh@kernel.org>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-mips@vger.kernel.org
---
.../devicetree/bindings/{rtc => timer}/snps,dw-apb-timer.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename Documentation/devicetree/bindings/{rtc => timer}/snps,dw-apb-timer.yaml (96%)
diff --git a/Documentation/devicetree/bindings/rtc/snps,dw-apb-timer.yaml b/Documentation/devicetree/bindings/timer/snps,dw-apb-timer.yaml
similarity index 96%
rename from Documentation/devicetree/bindings/rtc/snps,dw-apb-timer.yaml
rename to Documentation/devicetree/bindings/timer/snps,dw-apb-timer.yaml
index 002fe1ee709b..5d300efdf0ca 100644
--- a/Documentation/devicetree/bindings/rtc/snps,dw-apb-timer.yaml
+++ b/Documentation/devicetree/bindings/timer/snps,dw-apb-timer.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
-$id: http://devicetree.org/schemas/rtc/snps,dw-apb-timer.yaml#
+$id: http://devicetree.org/schemas/timer/snps,dw-apb-timer.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Synopsys DesignWare APB Timer
--
2.25.1
^ permalink raw reply related
* [PATCH v4 1/7] dt-bindings: rtc: Convert snps,dw-apb-timer to DT schema
From: Serge Semin @ 2020-05-21 0:53 UTC (permalink / raw)
To: Thomas Gleixner, Thomas Bogendoerfer, Daniel Lezcano,
Alessandro Zummo, Alexandre Belloni, Rob Herring
Cc: Serge Semin, Serge Semin, Rob Herring, Alexey Malahov,
Paul Burton, Ralf Baechle, Arnd Bergmann, linux-mips, linux-rtc,
devicetree, linux-kernel
In-Reply-To: <20200521005321.12129-1-Sergey.Semin@baikalelectronics.ru>
Modern device tree bindings are supposed to be created as YAML-files
in accordance with DT schema. This commit replaces Synopsys DW Timer
legacy bare text binding with YAML file. As before the binding file
states that the corresponding dts node is supposed to be compatible
with generic DW APB Timer indicated by the "snps,dw-apb-timer"
compatible string and to provide a mandatory registers memory range,
one timer interrupt, either reference clock source or a fixed clock
rate value. It may also have an optional APB bus reference clock
phandle specified.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Rob Herring <robh@kernel.org>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-mips@vger.kernel.org
---
This binding file doesn't belong to the bindings/rtc seeing it's a pure
timer with no rtc facilities like days/months/years counting and alarms.
The binding file will be moved to the
"Documentation/devicetree/bindings/timer/" directory in the next patch.
I also don't know who is the corresponding driver maintainer, so I added
Daniel Lezcano to the maintainers schema. Any idea what email should be
specified there instead?
Changelog v3:
- Since it's a conversion patch use GPL-2.0-only SPDX header.
- Replace "additionalProperties: false" property with
"unevaluatedProperties: false".
---
.../devicetree/bindings/rtc/dw-apb.txt | 32 -------
.../bindings/rtc/snps,dw-apb-timer.yaml | 88 +++++++++++++++++++
2 files changed, 88 insertions(+), 32 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/rtc/dw-apb.txt
create mode 100644 Documentation/devicetree/bindings/rtc/snps,dw-apb-timer.yaml
diff --git a/Documentation/devicetree/bindings/rtc/dw-apb.txt b/Documentation/devicetree/bindings/rtc/dw-apb.txt
deleted file mode 100644
index c703d51abb6c..000000000000
--- a/Documentation/devicetree/bindings/rtc/dw-apb.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-* Designware APB timer
-
-Required properties:
-- compatible: One of:
- "snps,dw-apb-timer"
- "snps,dw-apb-timer-sp" <DEPRECATED>
- "snps,dw-apb-timer-osc" <DEPRECATED>
-- reg: physical base address of the controller and length of memory mapped
- region.
-- interrupts: IRQ line for the timer.
-- either clocks+clock-names or clock-frequency properties
-
-Optional properties:
-- clocks : list of clock specifiers, corresponding to entries in
- the clock-names property;
-- clock-names : should contain "timer" and "pclk" entries, matching entries
- in the clocks property.
-- clock-frequency: The frequency in HZ of the timer.
-- clock-freq: For backwards compatibility with picoxcell
-
-If using the clock specifiers, the pclk clock is optional, as not all
-systems may use one.
-
-
-Example:
- timer@ffe00000 {
- compatible = "snps,dw-apb-timer";
- interrupts = <0 170 4>;
- reg = <0xffe00000 0x1000>;
- clocks = <&timer_clk>, <&timer_pclk>;
- clock-names = "timer", "pclk";
- };
diff --git a/Documentation/devicetree/bindings/rtc/snps,dw-apb-timer.yaml b/Documentation/devicetree/bindings/rtc/snps,dw-apb-timer.yaml
new file mode 100644
index 000000000000..002fe1ee709b
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/snps,dw-apb-timer.yaml
@@ -0,0 +1,88 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/snps,dw-apb-timer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare APB Timer
+
+maintainers:
+ - Daniel Lezcano <daniel.lezcano@linaro.org>
+
+properties:
+ compatible:
+ oneOf:
+ - const: snps,dw-apb-timer
+ - enum:
+ - snps,dw-apb-timer-sp
+ - snps,dw-apb-timer-osc
+ deprecated: true
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ minItems: 1
+ items:
+ - description: Timer ticks reference clock source
+ - description: APB interface clock source
+
+ clock-names:
+ minItems: 1
+ items:
+ - const: timer
+ - const: pclk
+
+ clock-frequency: true
+
+ clock-freq:
+ $ref: "/schemas/types.yaml#/definitions/uint32"
+ description: |
+ Has the same meaning as the 'clock-frequency' property - timer clock
+ frequency in HZ, but is defined only for the backwards compatibility
+ with the picoxcell platform.
+
+unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+oneOf:
+ - required:
+ - clocks
+ - clock-names
+ - required:
+ - clock-frequency
+ - required:
+ - clock-freq
+
+examples:
+ - |
+ timer@ffe00000 {
+ compatible = "snps,dw-apb-timer";
+ interrupts = <0 170 4>;
+ reg = <0xffe00000 0x1000>;
+ clocks = <&timer_clk>, <&timer_pclk>;
+ clock-names = "timer", "pclk";
+ };
+ - |
+ timer@ffe00000 {
+ compatible = "snps,dw-apb-timer";
+ interrupts = <0 170 4>;
+ reg = <0xffe00000 0x1000>;
+ clocks = <&timer_clk>;
+ clock-names = "timer";
+ };
+ - |
+ timer@ffe00000 {
+ compatible = "snps,dw-apb-timer";
+ interrupts = <0 170 4>;
+ reg = <0xffe00000 0x1000>;
+ clock-frequency = <25000000>;
+ };
+...
--
2.25.1
^ permalink raw reply related
* [PATCH v4 0/7] clocksource: Fix MIPS GIC and DW APB Timer for Baikal-T1 SoC support
From: Serge Semin @ 2020-05-21 0:53 UTC (permalink / raw)
To: Thomas Gleixner, Thomas Bogendoerfer, Daniel Lezcano
Cc: Serge Semin, Serge Semin, Alexey Malahov, Maxim Kaurkin,
Pavel Parkhomenko, Ramil Zaripov, Ekaterina Skachko, Vadim Vlasov,
Alexey Kolotnikov, Paul Burton, Ralf Baechle, Arnd Bergmann,
Alessandro Zummo, Alexandre Belloni, Rob Herring, linux-mips,
linux-rtc, devicetree, linux-kernel
As for all Baikal-T1 SoC related patchsets, which need this, we replaced
the DW APB Timer legacy plain text-based dt-binding file with DT schema.
Similarly the MIPS GIC bindings file is also converted to DT schema seeing
it also defines the MIPS GIC Timer binding.
Aside from MIPS-specific r4k timer Baikal-T1 chip also provides a
functionality of two another timers: embedded into the MIPS GIC timer and
three external DW timers available over APB bus. But we can't use them
before the corresponding drivers are properly fixed. First of all DW APB
Timer shouldn't be bound to a single CPU, since as being accessible over
APB they are external with respect to all possible CPUs. Secondly there
might be more than just two DW APB Timers in the system (Baikal-T1 has
three of them), so permit the driver to use one of them as a clocksource
and the rest - for clockevents. Thirdly it's possible to use MIPS GIC
timer as a clocksource so register it in the corresponding subsystem
(the patch has been found in the Paul Burton MIPS repo so I left the
original Signed-off-by attribute). Finally in the same way as r4k timer
the MIPS GIC timer should be used with care when CPUFREQ config is enabled
since in case of CM2 the timer counting depends on the CPU reference clock
frequency while the clocksource subsystem currently doesn't support the
timers with non-stable clock.
This patchset is rebased and tested on the mainline Linux kernel 5.7-rc4:
base-commit: 0e698dfa2822 ("Linux 5.7-rc4")
tag: v5.7-rc4
Changelog v2:
- Fix the SoB tags.
- Our corporate email server doesn't change Message-Id anymore, so the
patchset is resubmitted being in the cover-letter-threaded format.
- Convert the "snps,dw-apb-timer" binding to DT schema in a dedicated
patch.
- Convert the "mti,gic" binding to DT schema in a dedicated patch.
Link: https://lore.kernel.org/linux-rtc/20200324174325.14213-1-Sergey.Semin@baikalelectronics.ru
Changelog v3:
- Make the MIPS GIC timer sub-node name not having a unit-address number.
- Discard allOf: [ $ref: /schemas/interrupt-controller.yaml# ] from MIPS
GIC bindings.
- Add patch moving the "snps,dw-apb-timer" binding file to the directory
with timers binding files.
Link: https://lore.kernel.org/linux-rtc/20200506214107.25956-1-Sergey.Semin@baikalelectronics.ru
Changelog v4:
- Mark clocksource as unstable instead of lowering its rating.
- Move conditional sched clocks registration to the Paul' patch.
- Add Thomas Gleixner to the patchset To-list to draw his attention to the
patch "dt-bindings: interrupt-controller: Convert mti,gic to DT schema".
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Maxim Kaurkin <Maxim.Kaurkin@baikalelectronics.ru>
Cc: Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>
Cc: Ramil Zaripov <Ramil.Zaripov@baikalelectronics.ru>
Cc: Ekaterina Skachko <Ekaterina.Skachko@baikalelectronics.ru>
Cc: Vadim Vlasov <V.Vlasov@baikalelectronics.ru>
Cc: Alexey Kolotnikov <Alexey.Kolotnikov@baikalelectronics.ru>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: linux-rtc@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Paul Burton (1):
clocksource: mips-gic-timer: Register as sched_clock
Serge Semin (6):
dt-bindings: rtc: Convert snps,dw-apb-timer to DT schema
dt-bindings: timer: Move snps,dw-apb-timer DT schema from rtc
dt-bindings: interrupt-controller: Convert mti,gic to DT schema
clocksource: dw_apb_timer: Set clockevent any-possible-CPU mask
clocksource: dw_apb_timer_of: Fix missing clockevent timers
clocksource: mips-gic-timer: Mark GIC timer as unstable if ref clock
changes
.../interrupt-controller/mips-gic.txt | 67 --------
.../interrupt-controller/mti,gic.yaml | 148 ++++++++++++++++++
.../devicetree/bindings/rtc/dw-apb.txt | 32 ----
.../bindings/timer/snps,dw-apb-timer.yaml | 88 +++++++++++
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/dw_apb_timer.c | 18 +--
drivers/clocksource/dw_apb_timer_of.c | 9 +-
drivers/clocksource/mips-gic-timer.c | 50 +++++-
include/linux/dw_apb_timer.h | 2 +-
9 files changed, 293 insertions(+), 122 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/interrupt-controller/mips-gic.txt
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/mti,gic.yaml
delete mode 100644 Documentation/devicetree/bindings/rtc/dw-apb.txt
create mode 100644 Documentation/devicetree/bindings/timer/snps,dw-apb-timer.yaml
--
2.25.1
^ permalink raw reply
* [PATCH 2/2] phy: qcom-usb-hs: Add qcom,enable-vbus-pullup support
From: Bryan O'Donoghue @ 2020-05-21 0:50 UTC (permalink / raw)
To: agross, bjorn.andersson, kishon, vkoul, robh+dt
Cc: linux-arm-msm, linux-kernel, devicetree, bryan.odonoghue,
Philipp Zabel, Stephen Boyd
In-Reply-To: <20200521005031.747162-1-bryan.odonoghue@linaro.org>
Downstream has a flag called qcom,dp-manual-pullup which informs the
downstream driver if it should toggle ULPI_MISC_A_VBUSVLDEXTSEL and
ULPI_MISC_A_VBUSVLDEXT.
Downstream states:
"qcom,dp-manual-pullup: If present, vbus is not routed to USB
controller/phy and controller driver therefore enables pull-up
explicitly before starting controller using usbcmd run/stop bit."
Working with a type-c controller which handles VBUS entirely means there's
a need to replicate similar logic in upstream.
The current PHY code waggles these bits if an extcon associated with VBUS
exists but, that is not the case when using a full-fat type-c controller
i.e. there's no VBUS line routed to a SoC pad to sense.
This patch enables and disables the VBUS pullup bits on PHY power_on and
power_off respectively if the DT has declared the bool
"qcom,enable-vbus-pullup".
Cc: Andy Gross <agross@kernel.org>
Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: linux-arm-msm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
drivers/phy/qualcomm/phy-qcom-usb-hs.c | 36 ++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c
index 61054272a7c8..578a4e1fc539 100644
--- a/drivers/phy/qualcomm/phy-qcom-usb-hs.c
+++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c
@@ -37,6 +37,7 @@ struct qcom_usb_hs_phy {
struct ulpi_seq *init_seq;
struct extcon_dev *vbus_edev;
struct notifier_block vbus_notify;
+ u8 enable_vbus_pullup:1;
};
static int qcom_usb_hs_phy_set_mode(struct phy *phy,
@@ -104,6 +105,23 @@ qcom_usb_hs_phy_vbus_notifier(struct notifier_block *nb, unsigned long event,
return ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXT);
}
+static int qcom_usb_hs_phy_enable_vbus_pullup(struct ulpi *ulpi, bool enable)
+{
+ u8 addr;
+ int ret;
+
+ if (enable)
+ addr = ULPI_SET(ULPI_MISC_A);
+ else
+ addr = ULPI_CLR(ULPI_MISC_A);
+
+ ret = ulpi_write(ulpi, addr, ULPI_MISC_A_VBUSVLDEXTSEL);
+ if (ret)
+ return ret;
+
+ return ulpi_write(ulpi, addr, ULPI_MISC_A_VBUSVLDEXT);
+}
+
static int qcom_usb_hs_phy_power_on(struct phy *phy)
{
struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
@@ -153,6 +171,12 @@ static int qcom_usb_hs_phy_power_on(struct phy *phy)
goto err_ulpi;
}
+ if (uphy->enable_vbus_pullup) {
+ ret = qcom_usb_hs_phy_enable_vbus_pullup(ulpi, true);
+ if (ret)
+ goto err_ulpi;
+ }
+
if (uphy->vbus_edev) {
state = extcon_get_state(uphy->vbus_edev, EXTCON_USB);
/* setup initial state */
@@ -179,10 +203,19 @@ static int qcom_usb_hs_phy_power_on(struct phy *phy)
static int qcom_usb_hs_phy_power_off(struct phy *phy)
{
struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
+ struct ulpi *ulpi = uphy->ulpi;
+ int ret;
if (uphy->vbus_edev)
extcon_unregister_notifier(uphy->vbus_edev, EXTCON_USB,
&uphy->vbus_notify);
+
+ if (uphy->enable_vbus_pullup) {
+ ret = qcom_usb_hs_phy_enable_vbus_pullup(ulpi, false);
+ if (ret)
+ return ret;
+ }
+
regulator_disable(uphy->v3p3);
regulator_disable(uphy->v1p8);
clk_disable_unprepare(uphy->sleep_clk);
@@ -228,6 +261,9 @@ static int qcom_usb_hs_phy_probe(struct ulpi *ulpi)
/* NUL terminate */
uphy->init_seq[size / 2].addr = uphy->init_seq[size / 2].val = 0;
+ if (of_property_read_bool(ulpi->dev.of_node, "qcom,enable-vbus-pullup"))
+ uphy->enable_vbus_pullup = 1;
+
uphy->ref_clk = clk = devm_clk_get(&ulpi->dev, "ref");
if (IS_ERR(clk))
return PTR_ERR(clk);
--
2.25.1
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: phy-qcom-usb-hs-phy: Add qcom,enable-vbus-pullup
From: Bryan O'Donoghue @ 2020-05-21 0:50 UTC (permalink / raw)
To: agross, bjorn.andersson, kishon, vkoul, robh+dt
Cc: linux-arm-msm, linux-kernel, devicetree, bryan.odonoghue,
Stephen Boyd
In-Reply-To: <20200521005031.747162-1-bryan.odonoghue@linaro.org>
This patch adds a dt-binding for qcom,enable-vbus-pullup. The binding
qcom,enable-vbus-pullup tells the HS USB PHY driver whether it should set
and unset the internal VBUS pullup bits when starting/stopping the USB PHY.
Setting the pullup bits is something you want to do if you have not routed
VBUS to a GPIO on the SoC and thus cannot use extcon with the current
switching logic in the PHY.
Cc: Andy Gross <agross@kernel.org>
Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-arm-msm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: devicetree@vger.kernel.org
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt b/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt
index b3b75c1e6285..77e9bf1f8ba2 100644
--- a/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt
+++ b/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt
@@ -64,6 +64,12 @@ PROPERTIES
from the ULPI_EXT_VENDOR_SPECIFIC address, for example,
<0x1 0x53> would mean "write the value 0x53 to address 0x81".
+- qcom,enable-vbus-pullup:
+ Usage: optional
+ Value type: <bool>
+ Definition: Flag to indicate if the USB PHY driver should toggle internal
+ VBUS line pullup bits when powering the PHY on or off.
+
EXAMPLE
otg: usb-controller {
--
2.25.1
^ permalink raw reply related
* [PATCH 0/2] phy: qcom-usb-hs: Add DT controlled VBUS pullup waggle
From: Bryan O'Donoghue @ 2020-05-21 0:50 UTC (permalink / raw)
To: agross, bjorn.andersson, kishon, vkoul, robh+dt
Cc: linux-arm-msm, linux-kernel, devicetree, bryan.odonoghue
On an MSM8939 we have a system behind both a type-c controller and a USB
Hub. VBUS is not connected to the PHY and no GPIO is available to signal
VBUS state to the USB controller and PHY.
In this case we've used USB role-switching to transition between
host and device mode.
The current code in qcom-usb-hs only touches the VBUS pullup control bits
if we have an extcon but, setting those bits is still required on the
example I gave of the MSM8939.
This series takes the downstream concept of a DT driven flag for the VBUS
pullup bits and applies it to upstream in the poweron/poweroff path of the
PHY.
I've opted to unset the bits on PHY poweroff though in downstream the bits
are only ever switched on if the flag is present, downstream never switches
the bits off again. I think though, setting the bits off on PHY power-off
is the right thing to do, so I've done it.
Bryan O'Donoghue (2):
dt-bindings: phy-qcom-usb-hs-phy: Add qcom,enable-vbus-pullup
phy: qcom-usb-hs: Add qcom,enable-vbus-pullup support
.../bindings/phy/qcom,usb-hs-phy.txt | 8 +++++
drivers/phy/qualcomm/phy-qcom-usb-hs.c | 36 +++++++++++++++++++
2 files changed, 44 insertions(+)
--
2.25.1
^ permalink raw reply
* Re: [PATCH v3 00/14] mips: Prepare MIPS-arch code for Baikal-T1 SoC support
From: Serge Semin @ 2020-05-21 0:42 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: Serge Semin, Alexey Malahov, Maxim Kaurkin, Pavel Parkhomenko,
Ramil Zaripov, Ekaterina Skachko, Vadim Vlasov, Alexey Kolotnikov,
Paul Burton, Ralf Baechle, Rob Herring, Frank Rowand,
Tony Lindgren, Arnd Bergmann, Olof Johansson, Greg Kroah-Hartman,
Jiri Slaby, linux-mips, devicetree, linux-kernel
In-Reply-To: <20200521003443.11385-1-Sergey.Semin@baikalelectronics.ru>
On Thu, May 21, 2020 at 03:34:29AM +0300, Serge Semin wrote:
>
[nip]
>
> This patchset is rebased and tested on the mainline Linux kernel 5.7-rc4:
> base-commit: 0e698dfa2822 ("Linux 5.7-rc4")
> tag: v5.7-rc4
Thomas,
Please note that this patchset is based on the Linux 5.7-rc4 tree (it most likely
will get cleanly applied on rc6 as well), while mips-next is still at rc1. Due
to that the patchset fails to be applied on mips-next. I think it would be
better first to merge the last Linux tree into the mips-next, then try to merge
this patchset in. Should you have any problem after that, please let me know.
I'll resend the patchset being rebased on top of the new mips-next tree.
-Sergey
^ 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