All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support
@ 2022-06-10  8:17 Serge Semin
  2022-06-10  8:17 ` [PATCH v4 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml Serge Semin
                   ` (22 more replies)
  0 siblings, 23 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

The main goal of this patchset was to add Baikal-T1 AHCI SATA specifics
support into the kernel AHCI subsystem. On the way of doing that we
figured out that mainly these specifics are actually DWC AHCI SATA
controller features, but still there were some Baikal-T1 SoC platform
peculiarities which we had to take into account. So the patchset
introduces two AHCI SATA controllers support and one AHCI SATA driver
with a series of preparation, optimization and cleanup patches.

The series starts used to start with converting the legacy AHCI SATA
controllers text-based DT-bindings to the DT-schema. But turned out that
has already been done in kernel v5.17. So instead we suggest to improve
the bindings usability by splitting up the AHCI DT bindings into two
schemas: one common AHCI SATA controller yaml-file, which can be reused by
any AHCI-compatible controller utilizing the kernel AHCI library
functions, and DT-bindings for the generic AHCI SATA devices indicated by
the "generic-ahci" compatible string and implemented in the
ahci_platform.c driver. Note after doing that we had to fix the
sata-common.yaml file SATA port IDs constraint.

Then a series of generic preparations-cleanups goes. First of all it
concerns the device-managed methods usage in the framework of the CSR
space remapping and the clocks requesting and enabling. Note since the
clocks handlers are requested and kept in the generic AHCI library it
seemed a good idea to add an AHCI-platform generic method to find and get
a particular clock handler from the pool of the requested ones. It was
used later in the series in the DWC/Baikal-T1-specific code. Secondly we
suggested to at least sanity check the number of SATA ports DT-sub-nodes
before using it further.  Thirdly the ports-implemented DT-property
parsing was moved from the AHCI platform-driver to the AHCI-library so to
be used by the non-generic AHCI drivers if required (DT-schema is
accordingly fixed too). Finally due to having the shared-reset control
support we had to add a new AHCI-resource getter flag -
AHCI_PLATFORM_RST_TRIGGER, which indicated using a trigger-like reset
control. For such platforms the controller reset will be performed by
means of the reset_control_reset() and reset_control_rearm() methods.
AHCI-library reset functions encapsulating the way the reset procedure is
performed have been also added.

After that goes a patches series with the platform-specific
AHCI-capabilities initialization. The suggested functionality will be
useful for the platforms with no BIOS, comprehensive bootloader/firmware
installed. In that case the AHCI-related platform-specifics like drive
staggered spin-up, mechanical presence switch attached or FIS-based
switching capability usage, etc will be left uninitialized with no generic
way to be indicated as available if required. We suggested to use the AHCI
device tree node and its ports sub-nodes for that. AHCI-platform library
will be responsible fo the corresponding DT-properties parsing and
pre-initialization of the internal capability registers cache, which will
be then flashed back to the corresponding CSR after HBA reset. Thus a
supposed to be firmware-work will be done by means of the AHCI-library and
the DT-data. A set of the preparations/cleanups required to be done before
introducing the feature.  First the DT-properties indicating the
corresponding capability availability were described in the common AHCI
DT-binding schema. Second we needed to add the enum items with the AHCI
Port CMD fields, which hadn't been added so far. Thirdly we suggested to
discard one of the port-map internal storage (force_port_map) in favor of
re-using another one (save_port_map) in order to simplify the port-map
initialization interface a bit by getting rid from a redundant variable.
Finally after discarding the double AHCI-version read procedure and
changing the __ahci_port_base() method prototype the platform
firmware-specific caps initialization functionality was introduced.

The main part of the series goes afterwards. A dedicated DWC AHCI SATA
controller driver was introduced together with the corresponding
DT-binding schema pre-patch. Note the driver built mode is activated
synchronously with the generic AHCI-platform driver by default so
automatically to be integrated into the kernel for the DWC AHCI-based
platforms which relied on activating the generic AHCI SATA controller
driver. Aside with the generic resources getting and AHCI-host
initialization, the driver implements the DWC-specific setups. In
particular it checks whether the platform capabilities activated by the
firmware (see the functionality described above) are actually supported by
the controller. It's done by means of the vendor-specific registers. Then
it makes sure that the embedded 1ms timer interval, which is used for the
DevSleep and CCC features, is correctly initialized based on the
application clock rate.  The last but not least the driver provides a way
to tune the DMA-interface performance up by setting the Tx/Rx transactions
maximum size up. The required values are specified by means of the
"snps,tx-ts-max" and snps,rx-ts-max" DT-properties.

Finally we suggest to extend the DWC AHCI SATA controller driver
functionality with a way to add the DWC-AHCI-based platform-specific
quirks. Indeed there are many DWC AHCI-based controllers and just a few of
them are diverged too much to be handled by a dedicated AHCI-driver. The
rest of them most likely can work well either with a generic version of
the driver or require a simple normally platform-specific quirk to get up
and running. Such platforms can define a platform-data in the DWC AHCI
driver with a set of the controller-specific flags and initialization
functions. Those functions will be called at the corresponding stages of
the device probe/resume/remove procedures so to be performing the platform
setups/cleanups.

After the denoted above functionality is added we can finally introduce
the Baikal-T1 AHCI SATA controller support into the DWC AHCI SATA driver.
The controller is based on the DWC AHCI SATA IP-core v4.10a and can work
well with the generic DWC AHCI driver. The only peculiarity of it is
connected with the SATA Ports reference clock source. It can be supplied
either from the internal SoC PLL or from the chip pads. Currently we have
to prefer selecting the signal coming from the pads if the corresponding
clock source is specified because the link doesn't get stably established
when the internal clock signal is activated. In addition the platform has
trigger-based reset signals so the corresponding flag must be passed to
the generic AHCI-resource getter.

Link: https://lore.kernel.org/linux-ide/20220324001628.13028-1-Sergey.Semin@baikalelectronics.ru/
Changelog v2:
- Rebase from kernel v5.17 to v5.18-rc3. (@Rob)
- Rebase onto the already available AHCI DT schema. As a result two more
  patches have been added. (@Rob)
- Rename 'syscon' property to 'baikal,bt1-syscon'. (@Rob)
- Replace min/max constraints of the snps,{tx,rx}-ts-max property with
  enum [ 1, 2, 4, ..., 1024 ]. (@Rob)
- Use dlemoal/libata.git git tree for the LIBATA SATA AHCI SYNOPSYS
  DWC driver (@Damien).
- Change the local objects prefix from 'dwc_ahci_' to 'ahci_dwc_',
  from 'bt1_ahci_' to 'ahci_bt1_'. (@Damien)
- Use LLDD term in place of 'glue-driver'. (@Damien)
- Convert the ahci_platform_assert_rsts() method to returning int status
  (@Damien).
- Drop the else word from the DT child_nodes value checking if-else-if
  statement (@Damien) and convert the after-else part into the ternary
  operator-based statement.
- Convert to checking the error-case first in the devm_clk_bulk_get_all()
  method invocation. (@Damien)
- Drop the rc variable initialization in the ahci_platform_get_resources()
  method. (@Damien)
- Add comma and replace "channel" with "SATA port" in the reg property
  description of the sata-common.yaml schema. (@Damien)

Link: https://lore.kernel.org/lkml/20220503200938.18027-1-Sergey.Semin@baikalelectronics.ru/
Changelog v3:
- Replace Jens's email address with Damien's one in the list of the
  common DT schema maintainers. (@Damien)

Link: https://lore.kernel.org/linux-ide/20220511231810.4928-1-Sergey.Semin@baikalelectronics.ru/
Changelog v4:
- Drop clocks, clock-names, resets, reset-names and power-domains
  properties from the AHCI common schema. (@Rob)
- Make sure the interrupts DT-property can have from 1 to 32 items
  specified. (@Rob)
- Decrease the "additionalProperties" property identation in the DW AHCI
  SATA DT-schema otherwise it's percieved as the node property instead of
  the key one. (@Rob)
- Convert the HBA-capabilities boolean properties to the bitfield
  DT-properties. (@Rob)
- Create SATA/AHCI-port properties definition hierarchy so the sub-schemas
  could inherit and extend the ports properties of the super-schema. (@Rob)
- Drop Baikal-T1 syscon reference and implement the clock signal
  source in the framework of the clock controller. (@Rob)
- Refactor the patch
  [PATCH v3 01/23] dt-bindings: ata: ahci-platform: Drop dma-coherent property declaration
  to
  [PATCH v3 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml
  (@Rob)
- Add a new patch:
  [PATCH v4 05/24] dt-bindings: ata: sata-brcm: Apply common AHCI schema
- Drop the patch:
  [PATCH v3 05/23] ata: libahci_platform: Explicitly set rc on devres_alloc failure
  (@Hannes, @Damien)
- Convert ahci_dwc_plat and ahci_bt1_plat to being statically defined.
  (@kbot)
- Rebase onto the kernel v5.18.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-ide@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: devicetree@vger.kernel.org

Serge Semin (23):
  dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml
  dt-bindings: ata: ahci-platform: Detach common AHCI bindings
  dt-bindings: ata: ahci-platform: Clarify common AHCI props constraints
  dt-bindings: ata: sata: Extend number of SATA ports
  dt-bindings: ata: sata-brcm: Apply common AHCI schema
  ata: libahci_platform: Convert to using platform devm-ioremap methods
  ata: libahci_platform: Convert to using devm bulk clocks API
  ata: libahci_platform: Sanity check the DT child nodes number
  ata: libahci_platform: Parse ports-implemented property in resources
    getter
  ata: libahci_platform: Introduce reset assertion/deassertion methods
  dt-bindings: ata: ahci: Add platform capability properties
  ata: libahci: Extend port-cmd flags set with port capabilities
  ata: libahci: Discard redundant force_port_map parameter
  ata: libahci: Don't read AHCI version twice in the save-config method
  ata: ahci: Convert __ahci_port_base to accepting hpriv as arguments
  ata: ahci: Introduce firmware-specific caps initialization
  dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema
  ata: libahci_platform: Add function returning a clock-handle by id
  ata: ahci: Add DWC AHCI SATA controller support
  dt-bindings: ata: ahci: Add Baikal-T1 AHCI SATA controller DT schema
  ata: ahci-dwc: Add platform-specific quirks support
  ata: ahci-dwc: Add Baikal-T1 AHCI SATA interface support
  MAINTAINERS: Add maintainers for DWC AHCI SATA driver

 .../devicetree/bindings/ata/ahci-common.yaml  | 123 +++++
 .../bindings/ata/ahci-platform.yaml           |  92 +---
 .../bindings/ata/baikal,bt1-ahci.yaml         | 116 ++++
 .../bindings/ata/brcm,sata-brcm.yaml          |   4 +-
 .../devicetree/bindings/ata/sata-common.yaml  |  17 +-
 .../bindings/ata/snps,dwc-ahci.yaml           | 129 +++++
 MAINTAINERS                                   |   9 +
 drivers/ata/Kconfig                           |  11 +
 drivers/ata/Makefile                          |   1 +
 drivers/ata/ahci.c                            |   4 +-
 drivers/ata/ahci.h                            |  21 +-
 drivers/ata/ahci_dwc.c                        | 494 ++++++++++++++++++
 drivers/ata/ahci_mtk.c                        |   2 -
 drivers/ata/ahci_platform.c                   |   5 -
 drivers/ata/ahci_st.c                         |   3 -
 drivers/ata/libahci.c                         |  63 ++-
 drivers/ata/libahci_platform.c                | 222 ++++++--
 include/dt-bindings/ata/ahci.h                |  20 +
 include/linux/ahci_platform.h                 |   8 +-
 19 files changed, 1174 insertions(+), 170 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/ata/ahci-common.yaml
 create mode 100644 Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
 create mode 100644 Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
 create mode 100644 drivers/ata/ahci_dwc.c
 create mode 100644 include/dt-bindings/ata/ahci.h

-- 
2.35.1


^ permalink raw reply	[flat|nested] 80+ messages in thread

* [PATCH v4 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14 22:02   ` Rob Herring
  2022-06-14 22:15   ` Florian Fainelli
  2022-06-10  8:17 ` [PATCH v4 02/23] dt-bindings: ata: ahci-platform: Detach common AHCI bindings Serge Semin
                   ` (21 subsequent siblings)
  22 siblings, 2 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Rob Herring, Krzysztof Kozlowski, Florian Fainelli,
	Linus Walleij
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	linux-ide, linux-kernel, devicetree

Seeing doubtfully any SATA device working without embedded DMA engine
let's permit the device nodes being equipped with the dma-coherent
property in case if the platform is capable of cache-coherent DMAs.

As a side-effect we can drop the explicit dma-coherent property definition
from the particular device schemas. Currently it concerns the Broadcom
SATA AHCI controller only.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

---

Changelog v2:
- This is a new patch created after rebasing v1 onto the 5.18-rc3 kernel.

Changelog v4:
- Move the dma-coherent property to the sata-common.yaml schema instead
  of removing it.
- Remove the Hannes' rb tag.
---
 Documentation/devicetree/bindings/ata/ahci-platform.yaml  | 2 --
 Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml | 2 --
 Documentation/devicetree/bindings/ata/sata-common.yaml    | 2 ++
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
index c146ab8e14e5..9304e4731965 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
@@ -87,8 +87,6 @@ properties:
     description:
       regulator for AHCI controller
 
-  dma-coherent: true
-
   phy-supply:
     description:
       regulator for PHY power
diff --git a/Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml b/Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml
index 235a93ac86b0..4ee74df8e58a 100644
--- a/Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml
+++ b/Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml
@@ -41,8 +41,6 @@ properties:
   interrupts:
     maxItems: 1
 
-  dma-coherent: true
-
 if:
   properties:
     compatible:
diff --git a/Documentation/devicetree/bindings/ata/sata-common.yaml b/Documentation/devicetree/bindings/ata/sata-common.yaml
index 7ac77b1c5850..cb88d3e25e73 100644
--- a/Documentation/devicetree/bindings/ata/sata-common.yaml
+++ b/Documentation/devicetree/bindings/ata/sata-common.yaml
@@ -31,6 +31,8 @@ properties:
   "#size-cells":
     const: 0
 
+  dma-coherent: true
+
 patternProperties:
   "^sata-port@[0-9a-e]$":
     description: |
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 02/23] dt-bindings: ata: ahci-platform: Detach common AHCI bindings
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
  2022-06-10  8:17 ` [PATCH v4 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14 22:16   ` Rob Herring
  2022-06-10  8:17 ` [PATCH v4 03/23] dt-bindings: ata: ahci-platform: Clarify common AHCI props constraints Serge Semin
                   ` (20 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Rob Herring, Krzysztof Kozlowski, Linus Walleij
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	linux-ide, linux-kernel, devicetree

In order to create a more sophisticated AHCI controller DT bindings let's
divide the already available generic AHCI platform YAML schema into the
platform part and a set of the common AHCI properties. The former part
will be used to evaluate the AHCI DT nodes mainly compatible with the
generic AHCI controller while the later schema will be used for more
thorough AHCI DT nodes description. For instance such YAML schemas design
will be useful for our DW AHCI SATA controller derivative with four clock
sources, two reset lines, one system controller reference and specific
max Rx/Tx DMA xfers size constraints.

Note the phys and target-supply property requirement is preserved in the
generic AHCI platform bindings because some platforms can lack of the
explicitly specified PHYs or target device power regulators.

Also note the SATA/AHCI ports properties have been moved to the
$defs-paragraph of the schemas. It's done in order to create the
extendable properties hierarchy such that particular AHCI-controller
could add vendor-specific port properties.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

---

Folks, I don't really see why the phys/target-supply requirement has been
added to the generic AHCI DT schema in the first place. Probably just to
imply some meaning for the sub-nodes definition. Anyway in one of the
further patches I am adding the DW AHCI SATA controller DT bindings which
won't require having these properties specified in the sub-nodes, but will
describe additional port-specific properties. That's why I get to keep the
constraints in the ahci-platform.yaml schema instead of moving them to the
common schema.

Changelog v2:
- This is a new patch created after rebasing v1 onto the 5.18-rc3 kernel.

Changelog v3:
- Replace Jens's email address with Damien's one in the list of the
  schema maintainers. (@Damien)

Changelog v4:
- Drop clocks, clock-names, resets, reset-names and power-domains
  properties from the common schema. (@Rob)
- Create sata/ahci-port properties definition hierarchy so the sub-schemas
  would inherit and extend the ports properties of the super-schema. (@Rob)
---
 .../devicetree/bindings/ata/ahci-common.yaml  | 100 ++++++++++++++++++
 .../bindings/ata/ahci-platform.yaml           |  72 ++-----------
 .../devicetree/bindings/ata/sata-common.yaml  |   8 +-
 3 files changed, 115 insertions(+), 65 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/ata/ahci-common.yaml

diff --git a/Documentation/devicetree/bindings/ata/ahci-common.yaml b/Documentation/devicetree/bindings/ata/ahci-common.yaml
new file mode 100644
index 000000000000..e89bda3b62cc
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/ahci-common.yaml
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ata/ahci-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Common Properties for Serial ATA AHCI controllers
+
+maintainers:
+  - Hans de Goede <hdegoede@redhat.com>
+  - Damien Le Moal <damien.lemoal@opensource.wdc.com>
+
+description:
+  This document defines device tree properties for a common AHCI SATA
+  controller implementation. It's hardware interface is supposed to
+  conform to the technical standard defined by Intel (see Serial ATA
+  Advanced Host Controller Interface specification for details). The
+  document doesn't constitute a DT-node binding by itself but merely
+  defines a set of common properties for the AHCI-compatible devices.
+
+select: false
+
+allOf:
+  - $ref: sata-common.yaml#
+
+properties:
+  reg:
+    description:
+      Generic AHCI registers space conforming to the Serial ATA AHCI
+      specification.
+
+  reg-names:
+    description: CSR space IDs
+
+  interrupts:
+    description:
+      Generic AHCI state change interrupt. Can be implemented either as a
+      single line attached to the controller or as a set of the signals
+      indicating the particular port events.
+
+  ahci-supply:
+    description: Power regulator for AHCI controller
+
+  target-supply:
+    description: Power regulator for SATA target device
+
+  phy-supply:
+    description: Power regulator for SATA PHY
+
+  phys:
+    description: Reference to the SATA PHY node
+    maxItems: 1
+
+  phy-names:
+    maxItems: 1
+
+  ports-implemented:
+    $ref: '/schemas/types.yaml#/definitions/uint32'
+    description:
+      Mask that indicates which ports the HBA supports. Useful if PI is not
+      programmed by the BIOS, which is true for some embedded SoC's.
+    maximum: 0x1f
+
+patternProperties:
+  "^sata-port@[0-9a-f]+$":
+    $ref: '#/$defs/ahci-port'
+    description:
+      It is optionally possible to describe the ports as sub-nodes so
+      to enable each port independently when dealing with multiple PHYs.
+
+required:
+  - reg
+  - interrupts
+
+additionalProperties: true
+
+$defs:
+  ahci-port:
+    $ref: /schemas/ata/sata-common.yaml#/$defs/sata-port
+
+    properties:
+      reg:
+        description: AHCI SATA port identifier
+        maxItems: 1
+
+      phys:
+        description: Individual AHCI SATA port PHY
+        maxItems: 1
+
+      phy-names:
+        description: AHCI SATA port PHY ID
+        maxItems: 1
+
+      target-supply:
+        description: Power regulator for SATA port target device
+
+    required:
+      - reg
+
+...
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
index 9304e4731965..15be98e0385b 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
@@ -36,8 +36,7 @@ select:
     - compatible
 
 allOf:
-  - $ref: "sata-common.yaml#"
-
+  - $ref: "ahci-common.yaml#"
 
 properties:
   compatible:
@@ -69,90 +68,37 @@ properties:
     maxItems: 1
 
   clocks:
-    description:
-      Clock IDs array as required by the controller.
     minItems: 1
     maxItems: 3
 
   clock-names:
-    description:
-      Names of clocks corresponding to IDs in the clock property.
     minItems: 1
     maxItems: 3
 
   interrupts:
     maxItems: 1
 
-  ahci-supply:
-    description:
-      regulator for AHCI controller
-
-  phy-supply:
-    description:
-      regulator for PHY power
-
-  phys:
-    description:
-      List of all PHYs on this controller
-    maxItems: 1
-
-  phy-names:
-    description:
-      Name specifier for the PHYs
-    maxItems: 1
-
-  ports-implemented:
-    $ref: '/schemas/types.yaml#/definitions/uint32'
-    description: |
-      Mask that indicates which ports that the HBA supports
-      are available for software to use. Useful if PORTS_IMPL
-      is not programmed by the BIOS, which is true with
-      some embedded SoCs.
-    maximum: 0x1f
-
   power-domains:
     maxItems: 1
 
   resets:
     maxItems: 1
 
-  target-supply:
-    description:
-      regulator for SATA target power
-
-required:
-  - compatible
-  - reg
-  - interrupts
-
 patternProperties:
   "^sata-port@[0-9a-f]+$":
-    type: object
-    additionalProperties: false
-    description:
-      Subnode with configuration of the Ports.
-
-    properties:
-      reg:
-        maxItems: 1
-
-      phys:
-        maxItems: 1
-
-      phy-names:
-        maxItems: 1
-
-      target-supply:
-        description:
-          regulator for SATA target power
-
-    required:
-      - reg
+    $ref: /schemas/ata/ahci-common.yaml#/$defs/ahci-port
 
     anyOf:
       - required: [ phys ]
       - required: [ target-supply ]
 
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
 unevaluatedProperties: false
 
 examples:
diff --git a/Documentation/devicetree/bindings/ata/sata-common.yaml b/Documentation/devicetree/bindings/ata/sata-common.yaml
index cb88d3e25e73..5a31a902618d 100644
--- a/Documentation/devicetree/bindings/ata/sata-common.yaml
+++ b/Documentation/devicetree/bindings/ata/sata-common.yaml
@@ -35,9 +35,15 @@ properties:
 
 patternProperties:
   "^sata-port@[0-9a-e]$":
+    $ref: '#/$defs/sata-port'
     description: |
       DT nodes for ports connected on the SATA host. The SATA port
       nodes will be named "sata-port".
+
+additionalProperties: true
+
+$defs:
+  sata-port:
     type: object
 
     properties:
@@ -49,6 +55,4 @@ patternProperties:
           multiplier making it possible to connect up to 15 disks to a single
           SATA port.
 
-additionalProperties: true
-
 ...
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 03/23] dt-bindings: ata: ahci-platform: Clarify common AHCI props constraints
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
  2022-06-10  8:17 ` [PATCH v4 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml Serge Semin
  2022-06-10  8:17 ` [PATCH v4 02/23] dt-bindings: ata: ahci-platform: Detach common AHCI bindings Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14 22:17   ` Rob Herring
  2022-06-10  8:17 ` [PATCH v4 04/23] dt-bindings: ata: sata: Extend number of SATA ports Serge Semin
                   ` (19 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Rob Herring, Krzysztof Kozlowski
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	linux-ide, linux-kernel, devicetree

Indeed in accordance with what is implemented in the AHCI platform driver
and the way the AHCI DT nodes are defined in the DT files we can add the
next AHCI DT properties constraints: AHCI CSR ID is fixed to 'ahci', PHY
name is fixed to 'sata-phy', AHCI controller can't have more than 32 ports
by design, AHCI controller can have up to 32 IRQ lines.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>

---

Changelog v2:
- This is a new patch created after rebasing v1 onto the 5.18-rc3 kernel.

Changelog v4:
- Fix spelling: 'imeplemtned' and 'paltform' in the patch log. (@Hannes)
- Add the interrupts property constraints. (@Rob)
- Add forgotten '---' patchlog-changelog separator. (@Sergei)
---
 .../devicetree/bindings/ata/ahci-common.yaml    | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/ata/ahci-common.yaml b/Documentation/devicetree/bindings/ata/ahci-common.yaml
index e89bda3b62cc..12a97b56226f 100644
--- a/Documentation/devicetree/bindings/ata/ahci-common.yaml
+++ b/Documentation/devicetree/bindings/ata/ahci-common.yaml
@@ -31,12 +31,16 @@ properties:
 
   reg-names:
     description: CSR space IDs
+    contains:
+      const: ahci
 
   interrupts:
     description:
       Generic AHCI state change interrupt. Can be implemented either as a
       single line attached to the controller or as a set of the signals
       indicating the particular port events.
+    minItems: 1
+    maxItems: 32
 
   ahci-supply:
     description: Power regulator for AHCI controller
@@ -52,14 +56,13 @@ properties:
     maxItems: 1
 
   phy-names:
-    maxItems: 1
+    const: sata-phy
 
   ports-implemented:
     $ref: '/schemas/types.yaml#/definitions/uint32'
     description:
       Mask that indicates which ports the HBA supports. Useful if PI is not
       programmed by the BIOS, which is true for some embedded SoC's.
-    maximum: 0x1f
 
 patternProperties:
   "^sata-port@[0-9a-f]+$":
@@ -80,8 +83,12 @@ $defs:
 
     properties:
       reg:
-        description: AHCI SATA port identifier
-        maxItems: 1
+        description:
+          AHCI SATA port identifier. By design AHCI controller can't have
+          more than 32 ports due to the CAP.NP fields and PI register size
+          constraints.
+        minimum: 0
+        maximum: 31
 
       phys:
         description: Individual AHCI SATA port PHY
@@ -89,7 +96,7 @@ $defs:
 
       phy-names:
         description: AHCI SATA port PHY ID
-        maxItems: 1
+        const: sata-phy
 
       target-supply:
         description: Power regulator for SATA port target device
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 04/23] dt-bindings: ata: sata: Extend number of SATA ports
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (2 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 03/23] dt-bindings: ata: ahci-platform: Clarify common AHCI props constraints Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-10  8:17 ` [PATCH v4 05/23] dt-bindings: ata: sata-brcm: Apply common AHCI schema Serge Semin
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Rob Herring, Krzysztof Kozlowski, Linus Walleij
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	linux-ide, linux-kernel, devicetree, Rob Herring

The denoted in the description upper limit only concerns the Port
Multipliers, but not the actual SATA ports. It's an external device
attached to a SATA port in order to access more than one SATA-drive. So
when it's attached to a SATA port it just extends the port capability
while the number of actual SATA ports stays the same. For instance on AHCI
controllers the number of actual ports is determined by the CAP.NP field
and the PI (Ports Implemented) register. AFAICS in general the maximum
number of SATA ports depends on the particular controller implementation.
Generic AHCI controller can't have more than 32 ports (since CAP.NP is of
5 bits wide and PI register is 32-bits size), while DWC AHCI SATA
controller can't be configured with more than 8 ports activated. So let's
discard the SATA ports reg-property restrictions and just make sure that
it consists of a single reg-item.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Rob Herring <robh@kernel.org>

---

Changelog v2:
- Add comma and replace "channel" with "SATA port" in the reg property
  description (@Damien).
---
 Documentation/devicetree/bindings/ata/sata-common.yaml | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/ata/sata-common.yaml b/Documentation/devicetree/bindings/ata/sata-common.yaml
index 5a31a902618d..58c9342b9925 100644
--- a/Documentation/devicetree/bindings/ata/sata-common.yaml
+++ b/Documentation/devicetree/bindings/ata/sata-common.yaml
@@ -49,10 +49,9 @@ $defs:
     properties:
       reg:
         minimum: 0
-        maximum: 14
         description:
-          The ID number of the drive port SATA can potentially use a port
-          multiplier making it possible to connect up to 15 disks to a single
-          SATA port.
+          The ID number of the SATA port. Aside with being directly used,
+          each port can have a Port Multiplier attached thus allowing to
+          access more than one drive by means of a single SATA port.
 
 ...
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 05/23] dt-bindings: ata: sata-brcm: Apply common AHCI schema
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (3 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 04/23] dt-bindings: ata: sata: Extend number of SATA ports Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14 22:15   ` Florian Fainelli
  2022-06-14 22:17   ` Rob Herring
  2022-06-10  8:17 ` [PATCH v4 06/23] ata: libahci_platform: Convert to using platform devm-ioremap methods Serge Semin
                   ` (17 subsequent siblings)
  22 siblings, 2 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Rob Herring, Krzysztof Kozlowski, Florian Fainelli
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	linux-ide, linux-kernel, devicetree

The Broadcom SATA controller is obviously based on the AHCI standard. The
device driver uses the kernel AHCI library to work with it. Therefore we
can be have a more thorough DT-bindings evaluation by referring to the
AHCI-common schema instead of using the more relaxed SATA-common one.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

---

Changelog v4:
- This is a new patch added on v4 lap of the review procedure.
---
 Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml b/Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml
index 4ee74df8e58a..fa8ebc8f243f 100644
--- a/Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml
+++ b/Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml
@@ -14,7 +14,7 @@ maintainers:
   - Florian Fainelli <f.fainelli@gmail.com>
 
 allOf:
-  - $ref: sata-common.yaml#
+  - $ref: ahci-common.yaml#
 
 properties:
   compatible:
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 06/23] ata: libahci_platform: Convert to using platform devm-ioremap methods
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (4 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 05/23] dt-bindings: ata: sata-brcm: Apply common AHCI schema Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-10  8:17 ` [PATCH v4 07/23] ata: libahci_platform: Convert to using devm bulk clocks API Serge Semin
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

Currently the IOMEM AHCI registers space is mapped by means of the
two functions invocation: platform_get_resource() is used to get the very
first memory resource and devm_ioremap_resource() is called to remap that
resource. Device-managed kernel API provides a handy wrapper to perform
the same in single function call: devm_platform_ioremap_resource().

While at it seeing many AHCI platform drivers rely on having the AHCI CSR
space marked with "ahci" name let's first try to find and remap the CSR
IO-mem with that name and only if it fails fallback to getting the very
first registers space platform resource.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>

---

Changelog v2:
- Check whether there is "ahci" reg resource before using the
  devm_platform_ioremap_resource_byname() method in order to prevent a
  false error message printed in the log (@Damien)
- Slightly update the patch title due to the change above and to be more
  specific about what the platform device managed methods are utilized
  for.
---
 drivers/ata/libahci_platform.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 32495ae96567..1e9e825d6cc5 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -402,8 +402,14 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 
 	devres_add(dev, hpriv);
 
-	hpriv->mmio = devm_ioremap_resource(dev,
-			      platform_get_resource(pdev, IORESOURCE_MEM, 0));
+	/*
+	 * If the DT provided an "ahci" named resource, use it. Otherwise,
+	 * fallback to using the default first resource for the device node.
+	 */
+	if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci"))
+		hpriv->mmio = devm_platform_ioremap_resource_byname(pdev, "ahci");
+	else
+		hpriv->mmio = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(hpriv->mmio)) {
 		rc = PTR_ERR(hpriv->mmio);
 		goto err_out;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 07/23] ata: libahci_platform: Convert to using devm bulk clocks API
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (5 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 06/23] ata: libahci_platform: Convert to using platform devm-ioremap methods Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14  8:22   ` Damien Le Moal
  2022-06-10  8:17 ` [PATCH v4 08/23] ata: libahci_platform: Sanity check the DT child nodes number Serge Semin
                   ` (15 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

In order to simplify the clock-related code there is a way to convert the
current fixed clocks array into using the common bulk clocks kernel API
with dynamic set of the clock handlers and device-managed clock-resource
tracking. It's a bit tricky due to the complication coming from the
requirement to support the platforms (da850, spear13xx) with the
non-OF-based clock source, but still doable.

Before this modification there are two methods have been used to get the
clocks connected to an AHCI device: clk_get() - to get the very first
clock in the list and of_clk_get() - to get the rest of them. Basically
the platforms with non-OF-based clocks definition could specify only a
single reference clock source. The platforms with OF-hw clocks have been
luckier and could setup up to AHCI_MAX_CLKS clocks. Such semantic can be
retained with using devm_clk_bulk_get_all() to retrieve the clocks defined
via the DT firmware and devm_clk_get_optional() otherwise. In both cases
using the device-managed version of the methods will cause the automatic
resources deallocation on the AHCI device removal event. The only
complicated part in the suggested approach is the explicit allocation and
initialization of the clk_bulk_data structure instance for the non-OF
reference clocks. It's required in order to use the Bulk Clocks API for
the both denoted cases of the clocks definition.

Note aside with the clock-related code reduction and natural
simplification, there are several bonuses the suggested modification
provides. First of all the limitation of having no greater than
AHCI_MAX_CLKS clocks is now removed, since the devm_clk_bulk_get_all()
method will allocate as many reference clocks data descriptors as there
are clocks specified for the device. Secondly the clock names are
auto-detected. So the LLDD (glue) drivers can make sure that the required
clocks are specified just by checking the clock IDs in the clk_bulk_data
array.  Thirdly using the handy Bulk Clocks kernel API improves the
clocks-handling code readability. And the last but not least this
modification implements a true optional clocks support to the
ahci_platform_get_resources() method. Indeed the previous clocks getting
procedure just stopped getting the clocks on any errors (aside from
non-critical -EPROBE_DEFER) in a way so the callee wasn't even informed
about abnormal loop termination. The new implementation lacks of such
problem. The ahci_platform_get_resources() will return an error code if
the corresponding clocks getting method ends execution abnormally.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>

---

Changelog v2:
- Convert to checking the error-case first in the devm_clk_bulk_get_all()
  method invocation. (@Damien)
- Fix some grammar mistakes in the comments.
---
 drivers/ata/ahci.h             |  4 +-
 drivers/ata/libahci_platform.c | 84 ++++++++++++++++------------------
 2 files changed, 41 insertions(+), 47 deletions(-)

diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index ad11a4c52fbe..c3770a19781b 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -38,7 +38,6 @@
 
 enum {
 	AHCI_MAX_PORTS		= 32,
-	AHCI_MAX_CLKS		= 5,
 	AHCI_MAX_SG		= 168, /* hardware max is 64K */
 	AHCI_DMA_BOUNDARY	= 0xffffffff,
 	AHCI_MAX_CMDS		= 32,
@@ -339,7 +338,8 @@ struct ahci_host_priv {
 	u32			em_msg_type;	/* EM message type */
 	u32			remapped_nvme;	/* NVMe remapped device count */
 	bool			got_runtime_pm; /* Did we do pm_runtime_get? */
-	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
+	unsigned int		n_clks;
+	struct clk_bulk_data	*clks;		/* Optional */
 	struct reset_control	*rsts;		/* Optional */
 	struct regulator	**target_pwrs;	/* Optional */
 	struct regulator	*ahci_regulator;/* Optional */
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 1e9e825d6cc5..814804582d1d 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -8,6 +8,7 @@
  *   Anton Vorontsov <avorontsov@ru.mvista.com>
  */
 
+#include <linux/clk-provider.h>
 #include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/gfp.h>
@@ -97,28 +98,14 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
  * ahci_platform_enable_clks - Enable platform clocks
  * @hpriv: host private area to store config values
  *
- * This function enables all the clks found in hpriv->clks, starting at
- * index 0. If any clk fails to enable it disables all the clks already
- * enabled in reverse order, and then returns an error.
+ * This function enables all the clks found for the AHCI device.
  *
  * RETURNS:
  * 0 on success otherwise a negative error code
  */
 int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
 {
-	int c, rc;
-
-	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
-		rc = clk_prepare_enable(hpriv->clks[c]);
-		if (rc)
-			goto disable_unprepare_clk;
-	}
-	return 0;
-
-disable_unprepare_clk:
-	while (--c >= 0)
-		clk_disable_unprepare(hpriv->clks[c]);
-	return rc;
+	return clk_bulk_prepare_enable(hpriv->n_clks, hpriv->clks);
 }
 EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
 
@@ -126,16 +113,13 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
  * ahci_platform_disable_clks - Disable platform clocks
  * @hpriv: host private area to store config values
  *
- * This function disables all the clks found in hpriv->clks, in reverse
- * order of ahci_platform_enable_clks (starting at the end of the array).
+ * This function disables all the clocks enabled before
+ * (bulk-clocks-disable function is supposed to do that in reverse
+ * from the enabling procedure order).
  */
 void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
 {
-	int c;
-
-	for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
-		if (hpriv->clks[c])
-			clk_disable_unprepare(hpriv->clks[c]);
+	clk_bulk_disable_unprepare(hpriv->n_clks, hpriv->clks);
 }
 EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
 
@@ -292,8 +276,6 @@ static void ahci_platform_put_resources(struct device *dev, void *res)
 		pm_runtime_disable(dev);
 	}
 
-	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
-		clk_put(hpriv->clks[c]);
 	/*
 	 * The regulators are tied to child node device and not to the
 	 * SATA device itself. So we can't use devm for automatically
@@ -374,8 +356,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
  * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
  * 2) regulator for controlling the targets power (optional)
  *    regulator for controlling the AHCI controller (optional)
- * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
- *    or for non devicetree enabled platforms a single clock
+ * 3) all clocks specified in the devicetree node, or a single
+ *    clock for non-OF platforms (optional)
  * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional)
  * 5) phys (optional)
  *
@@ -385,11 +367,10 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
 struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 						   unsigned int flags)
 {
+	int child_nodes, rc = -ENOMEM, enabled_ports = 0;
 	struct device *dev = &pdev->dev;
 	struct ahci_host_priv *hpriv;
-	struct clk *clk;
 	struct device_node *child;
-	int i, enabled_ports = 0, rc = -ENOMEM, child_nodes;
 	u32 mask_port_map = 0;
 
 	if (!devres_open_group(dev, NULL, GFP_KERNEL))
@@ -415,25 +396,38 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 		goto err_out;
 	}
 
-	for (i = 0; i < AHCI_MAX_CLKS; i++) {
+	/*
+	 * Bulk clocks getting procedure can fail to find any clock due to
+	 * running on a non-OF platform or due to the clocks being defined in
+	 * bypass of the DT firmware (like da850, spear13xx). In that case we
+	 * fallback to getting a single clock source right from the dev clocks
+	 * list.
+	 */
+	rc = devm_clk_bulk_get_all(dev, &hpriv->clks);
+	if (rc < 0)
+		goto err_out;
+
+	if (rc > 0) {
+		/* Got clocks in bulk */
+		hpriv->n_clks = rc;
+	} else {
 		/*
-		 * For now we must use clk_get(dev, NULL) for the first clock,
-		 * because some platforms (da850, spear13xx) are not yet
-		 * converted to use devicetree for clocks.  For new platforms
-		 * this is equivalent to of_clk_get(dev->of_node, 0).
+		 * No clock bulk found: fallback to manually getting
+		 * the optional clock.
 		 */
-		if (i == 0)
-			clk = clk_get(dev, NULL);
-		else
-			clk = of_clk_get(dev->of_node, i);
-
-		if (IS_ERR(clk)) {
-			rc = PTR_ERR(clk);
-			if (rc == -EPROBE_DEFER)
-				goto err_out;
-			break;
+		hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL);
+		if (!hpriv->clks) {
+			rc = -ENOMEM;
+			goto err_out;
+		}
+		hpriv->clks->clk = devm_clk_get_optional(dev, NULL);
+		if (IS_ERR(hpriv->clks->clk)) {
+			rc = PTR_ERR(hpriv->clks->clk);
+			goto err_out;
+		} else if (hpriv->clks->clk) {
+			hpriv->clks->id = __clk_get_name(hpriv->clks->clk);
+			hpriv->n_clks = 1;
 		}
-		hpriv->clks[i] = clk;
 	}
 
 	hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 08/23] ata: libahci_platform: Sanity check the DT child nodes number
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (6 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 07/23] ata: libahci_platform: Convert to using devm bulk clocks API Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14  8:23   ` Damien Le Moal
  2022-06-10  8:17   ` Serge Semin
                   ` (14 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

Having greater than AHCI_MAX_PORTS (32) ports detected isn't that critical
from the further AHCI-platform initialization point of view since
exceeding the ports upper limit will cause allocating more resources than
will be used afterwards. But detecting too many child DT-nodes doesn't
seem right since it's very unlikely to have it on an ordinary platform. In
accordance with the AHCI specification there can't be more than 32 ports
implemented at least due to having the CAP.NP field of 5 bits wide and the
PI register of dword size. Thus if such situation is found the DTB must
have been corrupted and the data read from it shouldn't be reliable. Let's
consider that as an erroneous situation and halt further resources
allocation.

Note it's logically more correct to have the nports set only after the
initialization value is checked for being sane. So while at it let's make
sure nports is assigned with a correct value.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>

---

Changelog v2:
- Drop the else word from the child_nodes value checking if-else-if
  statement (@Damien) and convert the after-else part into the ternary
  operator-based statement.

Changelog v4:
- Fix some logical mistakes in the patch log. (@Sergei Shtylyov)
---
 drivers/ata/libahci_platform.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 814804582d1d..8aed7b29c7ab 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -451,15 +451,22 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 		}
 	}
 
-	hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
+	/*
+	 * Too many sub-nodes most likely means having something wrong with
+	 * the firmware.
+	 */
+	child_nodes = of_get_child_count(dev->of_node);
+	if (child_nodes > AHCI_MAX_PORTS) {
+		rc = -EINVAL;
+		goto err_out;
+	}
 
 	/*
 	 * If no sub-node was found, we still need to set nports to
 	 * one in order to be able to use the
 	 * ahci_platform_[en|dis]able_[phys|regulators] functions.
 	 */
-	if (!child_nodes)
-		hpriv->nports = 1;
+	hpriv->nports = child_nodes ?: 1;
 
 	hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
 	if (!hpriv->phys) {
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 09/23] ata: libahci_platform: Parse ports-implemented property in resources getter
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
  2022-06-10  8:17 ` [PATCH v4 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml Serge Semin
@ 2022-06-10  8:17   ` Serge Semin
  2022-06-10  8:17 ` [PATCH v4 03/23] dt-bindings: ata: ahci-platform: Clarify common AHCI props constraints Serge Semin
                     ` (20 subsequent siblings)
  22 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Matthias Brugger, Patrice Chotard
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree,
	linux-arm-kernel, linux-mediatek

The ports-implemented property is mainly used on the OF-based platforms
with no ports mapping initialized by a bootloader/BIOS firmware. Seeing
the same of_property_read_u32()-based pattern has already been implemented
in the generic AHCI LLDD (glue) driver and in the Mediatek, St AHCI
drivers let's move the property read procedure to the generic
ahci_platform_get_resources() method. Thus we'll have the forced ports
mapping feature supported for each OF-based platform which requires that,
and stop re-implementing the same pattern in there a bit simplifying the
code.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
---
 drivers/ata/ahci_mtk.c         | 2 --
 drivers/ata/ahci_platform.c    | 3 ---
 drivers/ata/ahci_st.c          | 3 ---
 drivers/ata/libahci_platform.c | 3 +++
 4 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c
index 1f6c85fde983..c056378e3e72 100644
--- a/drivers/ata/ahci_mtk.c
+++ b/drivers/ata/ahci_mtk.c
@@ -118,8 +118,6 @@ static int mtk_ahci_parse_property(struct ahci_host_priv *hpriv,
 				   SYS_CFG_SATA_EN);
 	}
 
-	of_property_read_u32(np, "ports-implemented", &hpriv->force_port_map);
-
 	return 0;
 }
 
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 28a8de5b48b9..9b56490ecbc3 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -56,9 +56,6 @@ static int ahci_probe(struct platform_device *pdev)
 	if (rc)
 		return rc;
 
-	of_property_read_u32(dev->of_node,
-			     "ports-implemented", &hpriv->force_port_map);
-
 	if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci"))
 		hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
 
diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c
index 7526653c843b..068621099c00 100644
--- a/drivers/ata/ahci_st.c
+++ b/drivers/ata/ahci_st.c
@@ -168,9 +168,6 @@ static int st_ahci_probe(struct platform_device *pdev)
 
 	st_ahci_configure_oob(hpriv->mmio);
 
-	of_property_read_u32(dev->of_node,
-			     "ports-implemented", &hpriv->force_port_map);
-
 	err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info,
 				      &ahci_platform_sht);
 	if (err) {
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 8aed7b29c7ab..1a7060646009 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -483,6 +483,9 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 		goto err_out;
 	}
 
+	of_property_read_u32(dev->of_node,
+			     "ports-implemented", &hpriv->force_port_map);
+
 	if (child_nodes) {
 		for_each_child_of_node(dev->of_node, child) {
 			u32 port;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 09/23] ata: libahci_platform: Parse ports-implemented property in resources getter
@ 2022-06-10  8:17   ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Matthias Brugger, Patrice Chotard
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree,
	linux-arm-kernel, linux-mediatek

The ports-implemented property is mainly used on the OF-based platforms
with no ports mapping initialized by a bootloader/BIOS firmware. Seeing
the same of_property_read_u32()-based pattern has already been implemented
in the generic AHCI LLDD (glue) driver and in the Mediatek, St AHCI
drivers let's move the property read procedure to the generic
ahci_platform_get_resources() method. Thus we'll have the forced ports
mapping feature supported for each OF-based platform which requires that,
and stop re-implementing the same pattern in there a bit simplifying the
code.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
---
 drivers/ata/ahci_mtk.c         | 2 --
 drivers/ata/ahci_platform.c    | 3 ---
 drivers/ata/ahci_st.c          | 3 ---
 drivers/ata/libahci_platform.c | 3 +++
 4 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c
index 1f6c85fde983..c056378e3e72 100644
--- a/drivers/ata/ahci_mtk.c
+++ b/drivers/ata/ahci_mtk.c
@@ -118,8 +118,6 @@ static int mtk_ahci_parse_property(struct ahci_host_priv *hpriv,
 				   SYS_CFG_SATA_EN);
 	}
 
-	of_property_read_u32(np, "ports-implemented", &hpriv->force_port_map);
-
 	return 0;
 }
 
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 28a8de5b48b9..9b56490ecbc3 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -56,9 +56,6 @@ static int ahci_probe(struct platform_device *pdev)
 	if (rc)
 		return rc;
 
-	of_property_read_u32(dev->of_node,
-			     "ports-implemented", &hpriv->force_port_map);
-
 	if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci"))
 		hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
 
diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c
index 7526653c843b..068621099c00 100644
--- a/drivers/ata/ahci_st.c
+++ b/drivers/ata/ahci_st.c
@@ -168,9 +168,6 @@ static int st_ahci_probe(struct platform_device *pdev)
 
 	st_ahci_configure_oob(hpriv->mmio);
 
-	of_property_read_u32(dev->of_node,
-			     "ports-implemented", &hpriv->force_port_map);
-
 	err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info,
 				      &ahci_platform_sht);
 	if (err) {
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 8aed7b29c7ab..1a7060646009 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -483,6 +483,9 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 		goto err_out;
 	}
 
+	of_property_read_u32(dev->of_node,
+			     "ports-implemented", &hpriv->force_port_map);
+
 	if (child_nodes) {
 		for_each_child_of_node(dev->of_node, child) {
 			u32 port;
-- 
2.35.1


_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 09/23] ata: libahci_platform: Parse ports-implemented property in resources getter
@ 2022-06-10  8:17   ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Matthias Brugger, Patrice Chotard
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree,
	linux-arm-kernel, linux-mediatek

The ports-implemented property is mainly used on the OF-based platforms
with no ports mapping initialized by a bootloader/BIOS firmware. Seeing
the same of_property_read_u32()-based pattern has already been implemented
in the generic AHCI LLDD (glue) driver and in the Mediatek, St AHCI
drivers let's move the property read procedure to the generic
ahci_platform_get_resources() method. Thus we'll have the forced ports
mapping feature supported for each OF-based platform which requires that,
and stop re-implementing the same pattern in there a bit simplifying the
code.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
---
 drivers/ata/ahci_mtk.c         | 2 --
 drivers/ata/ahci_platform.c    | 3 ---
 drivers/ata/ahci_st.c          | 3 ---
 drivers/ata/libahci_platform.c | 3 +++
 4 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c
index 1f6c85fde983..c056378e3e72 100644
--- a/drivers/ata/ahci_mtk.c
+++ b/drivers/ata/ahci_mtk.c
@@ -118,8 +118,6 @@ static int mtk_ahci_parse_property(struct ahci_host_priv *hpriv,
 				   SYS_CFG_SATA_EN);
 	}
 
-	of_property_read_u32(np, "ports-implemented", &hpriv->force_port_map);
-
 	return 0;
 }
 
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 28a8de5b48b9..9b56490ecbc3 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -56,9 +56,6 @@ static int ahci_probe(struct platform_device *pdev)
 	if (rc)
 		return rc;
 
-	of_property_read_u32(dev->of_node,
-			     "ports-implemented", &hpriv->force_port_map);
-
 	if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci"))
 		hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
 
diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c
index 7526653c843b..068621099c00 100644
--- a/drivers/ata/ahci_st.c
+++ b/drivers/ata/ahci_st.c
@@ -168,9 +168,6 @@ static int st_ahci_probe(struct platform_device *pdev)
 
 	st_ahci_configure_oob(hpriv->mmio);
 
-	of_property_read_u32(dev->of_node,
-			     "ports-implemented", &hpriv->force_port_map);
-
 	err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info,
 				      &ahci_platform_sht);
 	if (err) {
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 8aed7b29c7ab..1a7060646009 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -483,6 +483,9 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 		goto err_out;
 	}
 
+	of_property_read_u32(dev->of_node,
+			     "ports-implemented", &hpriv->force_port_map);
+
 	if (child_nodes) {
 		for_each_child_of_node(dev->of_node, child) {
 			u32 port;
-- 
2.35.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 10/23] ata: libahci_platform: Introduce reset assertion/deassertion methods
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (8 preceding siblings ...)
  2022-06-10  8:17   ` Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-10  8:17 ` [PATCH v4 11/23] dt-bindings: ata: ahci: Add platform capability properties Serge Semin
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

Currently the ACHI-platform library supports only the assert and deassert
reset signals and ignores the platforms with self-deasserting reset lines.
That prone to having the platforms with self-deasserting reset method
misbehaviour when it comes to resuming from sleep state after the clocks
have been fully disabled. For such cases the controller needs to be fully
reset all over after the reference clocks are enabled and stable,
otherwise the controller state machine might be in an undetermined state.

The best solution would be to auto-detect which reset method is supported
by the particular platform and use it implicitly in the framework of the
ahci_platform_enable_resources()/ahci_platform_disable_resources()
methods. Alas it can't be implemented due to the AHCI-platform library
already supporting the shared reset control lines. As [1] says in such
case we have to use only one of the next methods:
+ reset_control_assert()/reset_control_deassert();
+ reset_control_reset()/reset_control_rearm().
If the driver had an exclusive control over the reset lines we could have
been able to manipulate the lines with no much limitation and just used
the combination of the methods above to cover all the possible
reset-control cases. Since the shared reset control has already been
advertised and couldn't be changed with no risk to breaking the platforms
relying on it, we have no choice but to make the platform drivers to
determine which reset methods the platform reset system supports.

In order to implement both types of reset control support we suggest to
introduce the new AHCI-platform flag: AHCI_PLATFORM_RST_TRIGGER, which
when passed to the ahci_platform_get_resources() method together with the
AHCI_PLATFORM_GET_RESETS flag will indicate that the reset lines are
self-deasserting thus the reset_control_reset()/reset_control_rearm() will
be used to control the reset state. Otherwise the
reset_control_deassert()/reset_control_assert() methods will be utilized.

[1] Documentation/driver-api/reset.rst

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>

---

Changelog v2:
- Convert the ahci_platform_assert_rsts() method to returning int status
  (@Damien).
- Fix some grammar mistakes in the ahci_platform_deassert_rsts() doc
  (@Damien).
---
 drivers/ata/ahci.h             |  1 +
 drivers/ata/libahci_platform.c | 50 ++++++++++++++++++++++++++++++----
 include/linux/ahci_platform.h  |  5 +++-
 3 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index c3770a19781b..7d834deefeb9 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -340,6 +340,7 @@ struct ahci_host_priv {
 	bool			got_runtime_pm; /* Did we do pm_runtime_get? */
 	unsigned int		n_clks;
 	struct clk_bulk_data	*clks;		/* Optional */
+	unsigned int		f_rsts;
 	struct reset_control	*rsts;		/* Optional */
 	struct regulator	**target_pwrs;	/* Optional */
 	struct regulator	*ahci_regulator;/* Optional */
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 1a7060646009..fcf00ffc7d12 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -123,6 +123,44 @@ void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
 }
 EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
 
+/**
+ * ahci_platform_deassert_rsts - Deassert/trigger platform resets
+ * @hpriv: host private area to store config values
+ *
+ * This function deasserts or triggers all the reset lines found for
+ * the AHCI device.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_deassert_rsts(struct ahci_host_priv *hpriv)
+{
+	if (hpriv->f_rsts & AHCI_PLATFORM_RST_TRIGGER)
+		return reset_control_reset(hpriv->rsts);
+
+	return reset_control_deassert(hpriv->rsts);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_deassert_rsts);
+
+/**
+ * ahci_platform_assert_rsts - Assert/rearm platform resets
+ * @hpriv: host private area to store config values
+ *
+ * This function asserts or rearms (for self-deasserting resets) all
+ * the reset controls found for the AHCI device.
+ *
+ * RETURNS:
+ * 0 on success otherwise a negative error code
+ */
+int ahci_platform_assert_rsts(struct ahci_host_priv *hpriv)
+{
+	if (hpriv->f_rsts & AHCI_PLATFORM_RST_TRIGGER)
+		return reset_control_rearm(hpriv->rsts);
+
+	return reset_control_assert(hpriv->rsts);
+}
+EXPORT_SYMBOL_GPL(ahci_platform_assert_rsts);
+
 /**
  * ahci_platform_enable_regulators - Enable regulators
  * @hpriv: host private area to store config values
@@ -220,18 +258,18 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
 	if (rc)
 		goto disable_regulator;
 
-	rc = reset_control_deassert(hpriv->rsts);
+	rc = ahci_platform_deassert_rsts(hpriv);
 	if (rc)
 		goto disable_clks;
 
 	rc = ahci_platform_enable_phys(hpriv);
 	if (rc)
-		goto disable_resets;
+		goto disable_rsts;
 
 	return 0;
 
-disable_resets:
-	reset_control_assert(hpriv->rsts);
+disable_rsts:
+	ahci_platform_assert_rsts(hpriv);
 
 disable_clks:
 	ahci_platform_disable_clks(hpriv);
@@ -258,7 +296,7 @@ void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
 {
 	ahci_platform_disable_phys(hpriv);
 
-	reset_control_assert(hpriv->rsts);
+	ahci_platform_assert_rsts(hpriv);
 
 	ahci_platform_disable_clks(hpriv);
 
@@ -449,6 +487,8 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 			rc = PTR_ERR(hpriv->rsts);
 			goto err_out;
 		}
+
+		hpriv->f_rsts = flags & AHCI_PLATFORM_RST_TRIGGER;
 	}
 
 	/*
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 49e5383d4222..6d7dd472d370 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -23,6 +23,8 @@ int ahci_platform_enable_phys(struct ahci_host_priv *hpriv);
 void ahci_platform_disable_phys(struct ahci_host_priv *hpriv);
 int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
 void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
+int ahci_platform_deassert_rsts(struct ahci_host_priv *hpriv);
+int ahci_platform_assert_rsts(struct ahci_host_priv *hpriv);
 int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv);
 void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv);
 int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
@@ -41,6 +43,7 @@ int ahci_platform_resume_host(struct device *dev);
 int ahci_platform_suspend(struct device *dev);
 int ahci_platform_resume(struct device *dev);
 
-#define AHCI_PLATFORM_GET_RESETS	0x01
+#define AHCI_PLATFORM_GET_RESETS	BIT(0)
+#define AHCI_PLATFORM_RST_TRIGGER	BIT(1)
 
 #endif /* _AHCI_PLATFORM_H */
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 11/23] dt-bindings: ata: ahci: Add platform capability properties
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (9 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 10/23] ata: libahci_platform: Introduce reset assertion/deassertion methods Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14 22:19   ` Rob Herring
  2022-06-10  8:17 ` [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities Serge Semin
                   ` (11 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Rob Herring, Krzysztof Kozlowski
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	linux-ide, linux-kernel, devicetree

In case if the platform doesn't have BIOS or a comprehensive firmware
installed then the HBA capability flags will be left uninitialized. As a
good alternative we suggest to define the DT-properties with the AHCI
platform capabilities describing all the HW-init flags of the
corresponding capability register. Luckily there aren't too many of them.
SSS - Staggered Spin-up support and MPS - Mechanical Presence Switch
support determine the corresponding feature availability for the whole HBA
by means of the "hba-cap" property. Each port can have the "hba-port-cap"
property initialized indicating that the port supports some of the next
functionalities: HPCP - HotPlug capable port, MPSP - Mechanical Presence
Switch attached to a port, CPD - Cold Plug detection, ESP - External SATA
Port (eSATA), FBSCP - FIS-based switching capable port.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

---

Changelog v4:
- Fix some misspelling in the patch log.
- Convert the boolean properties to the bitfield properties. (@Rob)
- Remove Hannes' rb tag due to the patch content change.
---
 .../devicetree/bindings/ata/ahci-common.yaml  | 16 +++++++++++++++
 .../bindings/ata/ahci-platform.yaml           | 10 ++++++++++
 include/dt-bindings/ata/ahci.h                | 20 +++++++++++++++++++
 3 files changed, 46 insertions(+)
 create mode 100644 include/dt-bindings/ata/ahci.h

diff --git a/Documentation/devicetree/bindings/ata/ahci-common.yaml b/Documentation/devicetree/bindings/ata/ahci-common.yaml
index 12a97b56226f..94d72aeaad0f 100644
--- a/Documentation/devicetree/bindings/ata/ahci-common.yaml
+++ b/Documentation/devicetree/bindings/ata/ahci-common.yaml
@@ -58,6 +58,14 @@ properties:
   phy-names:
     const: sata-phy
 
+  hba-cap:
+    $ref: '/schemas/types.yaml#/definitions/uint32'
+    description:
+      Bitfield of the HBA generic platform capabilities like Staggered
+      Spin-up or Mechanical Presence Switch support. It can be used to
+      appropriately initialize the HWinit fields of the HBA CAP register
+      in case if the system firmware hasn't done it.
+
   ports-implemented:
     $ref: '/schemas/types.yaml#/definitions/uint32'
     description:
@@ -101,6 +109,14 @@ $defs:
       target-supply:
         description: Power regulator for SATA port target device
 
+      hba-port-cap:
+        $ref: '/schemas/types.yaml#/definitions/uint32'
+        description:
+          Bitfield of the HBA port-specific platform capabilities like Hot
+          plugging, eSATA, FIS-based Switching, etc (see AHCI specification
+          for details). It can be used to initialize the HWinit fields of
+          the PxCMD register in case if the system firmware hasn't done it.
+
     required:
       - reg
 
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
index 15be98e0385b..e19cf9828e68 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
@@ -111,6 +111,8 @@ examples:
   - |
     #include <dt-bindings/interrupt-controller/arm-gic.h>
     #include <dt-bindings/clock/berlin2q.h>
+    #include <dt-bindings/ata/ahci.h>
+
     sata@f7e90000 {
         compatible = "marvell,berlin2q-ahci", "generic-ahci";
         reg = <0xf7e90000 0x1000>;
@@ -119,15 +121,23 @@ examples:
         #address-cells = <1>;
         #size-cells = <0>;
 
+        hba-cap = <HBA_SMPS>;
+
         sata0: sata-port@0 {
             reg = <0>;
+
             phys = <&sata_phy 0>;
             target-supply = <&reg_sata0>;
+
+            hba-port-cap = <(HBA_PORT_FBSCP | HBA_PORT_ESP)>;
         };
 
         sata1: sata-port@1 {
             reg = <1>;
+
             phys = <&sata_phy 1>;
             target-supply = <&reg_sata1>;
+
+            hba-port-cap = <(HBA_PORT_HPCP | HBA_PORT_MPSP | HBA_PORT_FBSCP)>;
         };
     };
diff --git a/include/dt-bindings/ata/ahci.h b/include/dt-bindings/ata/ahci.h
new file mode 100644
index 000000000000..6841caebcedf
--- /dev/null
+++ b/include/dt-bindings/ata/ahci.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides constants for most AHCI bindings.
+ */
+
+#ifndef _DT_BINDINGS_ATA_AHCI_H
+#define _DT_BINDINGS_ATA_AHCI_H
+
+/* Host Bus Adapter generic platform capabilities */
+#define HBA_SSS		(1 << 27)
+#define HBA_SMPS	(1 << 28)
+
+/* Host Bus Adapter port-specific platform capabilities */
+#define HBA_PORT_HPCP	(1 << 18)
+#define HBA_PORT_MPSP	(1 << 19)
+#define HBA_PORT_CPD	(1 << 20)
+#define HBA_PORT_ESP	(1 << 21)
+#define HBA_PORT_FBSCP	(1 << 22)
+
+#endif
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (10 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 11/23] dt-bindings: ata: ahci: Add platform capability properties Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14  8:32   ` Damien Le Moal
  2022-06-10  8:17 ` [PATCH v4 13/23] ata: libahci: Discard redundant force_port_map parameter Serge Semin
                   ` (10 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

Currently not all of the Port-specific capabilities listed in the
PORT_CMD-enumeration. Let's extend that set with the Cold Presence
Detection and Mechanical Presence Switch attached to the Port flags [1] so
to closeup the set of the platform-specific port-capabilities flags.  Note
these flags are supposed to be set by the platform firmware if there is
one. Alternatively as we are about to do they can be set by means of the
OF properties.

While at it replace PORT_IRQ_DEV_ILCK with PORT_IRQ_DMPS and fix the
comment there. In accordance with [2] that IRQ flag is supposed to
indicate the state of the signal coming from the Mechanical Presence
Switch.

[1] Serial ATA AHCI 1.3.1 Specification, p.27
[2] Serial ATA AHCI 1.3.1 Specification, p.24, p.88

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>

---

Changelog v4:
- Fix the DMPS macros name in the patch log. (@Sergei Shtylyov)
---
 drivers/ata/ahci.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 7d834deefeb9..f501531bd1b3 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -138,7 +138,7 @@ enum {
 	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
 
 	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
-	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
+	PORT_IRQ_DMPS		= (1 << 7), /* mechanical presence status */
 	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
 	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
 	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
@@ -166,6 +166,8 @@ enum {
 	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
 	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
 	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
+	PORT_CMD_CPD		= (1 << 20), /* Cold Presence Detection */
+	PORT_CMD_MPSP		= (1 << 19), /* Mechanical Presence Switch */
 	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
 	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
 	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
@@ -181,6 +183,9 @@ enum {
 	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
 	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
 
+	PORT_CMD_CAP		= PORT_CMD_HPCP | PORT_CMD_MPSP |
+				  PORT_CMD_CPD | PORT_CMD_ESP | PORT_CMD_FBSCP,
+
 	/* PORT_FBS bits */
 	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
 	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 13/23] ata: libahci: Discard redundant force_port_map parameter
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (11 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-10  8:17 ` [PATCH v4 14/23] ata: libahci: Don't read AHCI version twice in the save-config method Serge Semin
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

Currently there are four port-map-related fields declared in the
ahci_host_priv structure and used to setup the HBA ports mapping. First
the ports-mapping is read from the PI register and immediately stored in
the saved_port_map field. If forced_port_map is initialized with non-zero
value then its value will have greater priority over the value read from
PI, thus it will override the saved_port_map field. That value will be
then masked by a non-zero mask_port_map field and after some sanity checks
it will be stored in the ahci_host_priv.port_map field as a final port
mapping.

As you can see the logic is a bit too complicated for such a simple task.
We can freely get rid from at least one of the fields with no change to
the implemented semantic. The force_port_map field can be replaced with
taking non-zero saved_port_map value into account. So if saved_port_map is
pre-initialized by the low level drivers (platform drivers) then it will
have greater priority over the value read from PI register and will be
used as actual HBA ports mapping later on. Thus the ports map forcing task
will be just transferred from force_port_map to the saved_port_map field.

This modification will perfectly fit into the feature of having OF-based
initialization of the HW-init HBA CSR fields we are about to introduce in
the next commit.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/ahci.c             |  2 +-
 drivers/ata/ahci.h             |  1 -
 drivers/ata/libahci.c          | 10 ++++++----
 drivers/ata/libahci_platform.c |  2 +-
 4 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 397dfd27c90d..9bc8fa77e92f 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -656,7 +656,7 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
 {
 	if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
 		dev_info(&pdev->dev, "JMB361 has only one port\n");
-		hpriv->force_port_map = 1;
+		hpriv->saved_port_map = 1;
 	}
 
 	/*
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index f501531bd1b3..0e66446a5883 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -327,7 +327,6 @@ struct ahci_port_priv {
 struct ahci_host_priv {
 	/* Input fields */
 	unsigned int		flags;		/* AHCI_HFLAG_* */
-	u32			force_port_map;	/* force port map */
 	u32			mask_port_map;	/* mask out particular bits */
 
 	void __iomem *		mmio;		/* bus-independent mem map */
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index cf8c7fd59ada..000a7072614f 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -453,7 +453,6 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 	 * reset.  Values without are used for driver operation.
 	 */
 	hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
-	hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
 
 	/* CAP2 register is only defined for AHCI 1.2 and later */
 	vers = readl(mmio + HOST_VERSION);
@@ -517,10 +516,13 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 		cap &= ~HOST_CAP_SXS;
 	}
 
-	if (hpriv->force_port_map && port_map != hpriv->force_port_map) {
+	/* Override the HBA ports mapping if the platform needs it */
+	port_map = readl(mmio + HOST_PORTS_IMPL);
+	if (hpriv->saved_port_map && port_map != hpriv->saved_port_map) {
 		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
-			 port_map, hpriv->force_port_map);
-		port_map = hpriv->force_port_map;
+			 port_map, hpriv->saved_port_map);
+		port_map = hpriv->saved_port_map;
+	} else {
 		hpriv->saved_port_map = port_map;
 	}
 
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index fcf00ffc7d12..efe640603f3f 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -524,7 +524,7 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 	}
 
 	of_property_read_u32(dev->of_node,
-			     "ports-implemented", &hpriv->force_port_map);
+			     "ports-implemented", &hpriv->saved_port_map);
 
 	if (child_nodes) {
 		for_each_child_of_node(dev->of_node, child) {
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 14/23] ata: libahci: Don't read AHCI version twice in the save-config method
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (12 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 13/23] ata: libahci: Discard redundant force_port_map parameter Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-10  8:17 ` [PATCH v4 15/23] ata: ahci: Convert __ahci_port_base to accepting hpriv as arguments Serge Semin
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

There is no point in reading the AHCI version all over in the tail of the
ahci_save_initial_config() method. That register is RO and doesn't change
its value even after reset. So just reuse the data, which has already been
read from there earlier in the head of the function.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/libahci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 000a7072614f..1ffaa5f5f21a 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -564,7 +564,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 	/* record values to use during operation */
 	hpriv->cap = cap;
 	hpriv->cap2 = cap2;
-	hpriv->version = readl(mmio + HOST_VERSION);
+	hpriv->version = vers;
 	hpriv->port_map = port_map;
 
 	if (!hpriv->start_engine)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 15/23] ata: ahci: Convert __ahci_port_base to accepting hpriv as arguments
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (13 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 14/23] ata: libahci: Don't read AHCI version twice in the save-config method Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14  8:38   ` Damien Le Moal
  2022-06-10  8:17 ` [PATCH v4 16/23] ata: ahci: Introduce firmware-specific caps initialization Serge Semin
                   ` (7 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

It may get required to retrieve the port-base address even before the
ata_host instance is initialized and activated, for instance in the
ahci_save_initial_config() method which we about to update (consider this
modification as a preparation for that one). Seeing the __ahci_port_base()
function isn't used much it's the best candidate to provide the required
functionality. So let's convert it to accepting the ahci_host_priv
structure pointer.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
 drivers/ata/ahci.c | 2 +-
 drivers/ata/ahci.h | 7 ++++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 9bc8fa77e92f..d14d74649e0e 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -689,7 +689,7 @@ static void ahci_pci_init_controller(struct ata_host *host)
 			mv = 2;
 		else
 			mv = 4;
-		port_mmio = __ahci_port_base(host, mv);
+		port_mmio = __ahci_port_base(hpriv, mv);
 
 		writel(0, port_mmio + PORT_IRQ_MASK);
 
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 0e66446a5883..8b9826533ae5 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -431,10 +431,9 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht);
 void ahci_error_handler(struct ata_port *ap);
 u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked);
 
-static inline void __iomem *__ahci_port_base(struct ata_host *host,
+static inline void __iomem *__ahci_port_base(struct ahci_host_priv *hpriv,
 					     unsigned int port_no)
 {
-	struct ahci_host_priv *hpriv = host->private_data;
 	void __iomem *mmio = hpriv->mmio;
 
 	return mmio + 0x100 + (port_no * 0x80);
@@ -442,7 +441,9 @@ static inline void __iomem *__ahci_port_base(struct ata_host *host,
 
 static inline void __iomem *ahci_port_base(struct ata_port *ap)
 {
-	return __ahci_port_base(ap->host, ap->port_no);
+	struct ahci_host_priv *hpriv = ap->host->private_data;
+
+	return __ahci_port_base(hpriv, ap->port_no);
 }
 
 static inline int ahci_nr_ports(u32 cap)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 16/23] ata: ahci: Introduce firmware-specific caps initialization
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (14 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 15/23] ata: ahci: Convert __ahci_port_base to accepting hpriv as arguments Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14  8:42   ` Damien Le Moal
  2022-06-10  8:17 ` [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema Serge Semin
                   ` (6 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

There are systems with no BIOS or comprehensive embedded firmware which
could be able to properly initialize the SATA AHCI controller
platform-specific capabilities. In that case a good alternative to having
a clever bootloader is to create a device tree node with the properties
well describing all the AHCI-related platform specifics. All the settings
which are normally detected and marked as available in the HBA and its
ports capabilities fields [1] could be defined in the platform DTB by
means of a set of the dedicated properties. Such approach perfectly fits
to the DTB-philosophy - to provide hardware/platform description.

So here we suggest to extend the SATA AHCI device tree bindings with two
additional DT-properties:
1) "hba-cap" - HBA platform generic capabilities like:
   - SSS - Staggered Spin-up support.
   - SMPS - Mechanical Presence Switch support.
2) "hba-port-cap" - HBA platform port capabilities like:
   - HPCP - Hot Plug Capable Port.
   - MPSP - Mechanical Presence Switch Attached to Port.
   - CPD - Cold Presence Detection.
   - ESP - External SATA Port.
   - FBSCP - FIS-based Switching Capable Port.
All of these capabilities require to have a corresponding hardware
configuration. Thus it's ok to have them defined in DTB.

Even though the driver currently takes into account the state of the ESP
and FBSCP flags state only, there is nothing wrong with having all of them
supported by the generic AHCI library in order to have a complete OF-based
platform-capabilities initialization procedure. These properties will be
parsed in the ahci_platform_get_resources() method and their values will
be stored in the saved_* fields of the ahci_host_priv structure, which in
its turn then will be used to restore the H.CAP, H.PI and P#.CMD
capability fields on device init and after HBA reset.

Please note this modification concerns the HW-init HBA and its ports flags
only, which are by specification [1] are supposed to be initialized by the
BIOS/platform firmware/expansion ROM and which are normally declared in
the one-time-writable-after-reset register fields. Even though these flags
aren't supposed to be cleared after HBA reset some AHCI instances may
violate that rule so we still need to perform the fields resetting after
each reset. Luckily the corresponding functionality has already been
partly implemented in the framework of the ahci_save_initial_config() and
ahci_restore_initial_config() methods.

[1] Serial ATA AHCI 1.3.1 Specification, p. 103

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

---

Changelog v4:
- Convert the boolean properties to the bitfield DT-properties. (@Rob)
---
 drivers/ata/ahci.h             |  1 +
 drivers/ata/libahci.c          | 51 ++++++++++++++++++++++++++++------
 drivers/ata/libahci_platform.c | 41 +++++++++++++++++++++++++--
 3 files changed, 82 insertions(+), 11 deletions(-)

diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 8b9826533ae5..0de221055961 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -337,6 +337,7 @@ struct ahci_host_priv {
 	u32			saved_cap;	/* saved initial cap */
 	u32			saved_cap2;	/* saved initial cap2 */
 	u32			saved_port_map;	/* saved initial port_map */
+	u32			saved_port_cap[AHCI_MAX_PORTS]; /* saved port_cap */
 	u32 			em_loc; /* enclosure management location */
 	u32			em_buf_sz;	/* EM buffer size in byte */
 	u32			em_msg_type;	/* EM message type */
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 1ffaa5f5f21a..954386a2b500 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -16,6 +16,7 @@
  * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
  */
 
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
@@ -443,16 +444,28 @@ static ssize_t ahci_show_em_supported(struct device *dev,
 void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 {
 	void __iomem *mmio = hpriv->mmio;
-	u32 cap, cap2, vers, port_map;
+	void __iomem *port_mmio;
+	unsigned long port_map;
+	u32 cap, cap2, vers;
 	int i;
 
 	/* make sure AHCI mode is enabled before accessing CAP */
 	ahci_enable_ahci(mmio);
 
-	/* Values prefixed with saved_ are written back to host after
-	 * reset.  Values without are used for driver operation.
+	/*
+	 * Values prefixed with saved_ are written back to the HBA and ports
+	 * registers after reset. Values without are used for driver operation.
+	 */
+
+	/*
+	 * Override HW-init HBA capability fields with the platform-specific
+	 * values. The rest of the HBA capabilities are defined as Read-only
+	 * and can't be modified in CSR anyway.
 	 */
-	hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
+	cap = readl(mmio + HOST_CAP);
+	if (hpriv->saved_cap)
+		cap = (cap & ~(HOST_CAP_SSS | HOST_CAP_MPS)) | hpriv->saved_cap;
+	hpriv->saved_cap = cap;
 
 	/* CAP2 register is only defined for AHCI 1.2 and later */
 	vers = readl(mmio + HOST_VERSION);
@@ -519,7 +532,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 	/* Override the HBA ports mapping if the platform needs it */
 	port_map = readl(mmio + HOST_PORTS_IMPL);
 	if (hpriv->saved_port_map && port_map != hpriv->saved_port_map) {
-		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
+		dev_info(dev, "forcing port_map 0x%lx -> 0x%x\n",
 			 port_map, hpriv->saved_port_map);
 		port_map = hpriv->saved_port_map;
 	} else {
@@ -527,7 +540,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 	}
 
 	if (hpriv->mask_port_map) {
-		dev_warn(dev, "masking port_map 0x%x -> 0x%x\n",
+		dev_warn(dev, "masking port_map 0x%lx -> 0x%lx\n",
 			port_map,
 			port_map & hpriv->mask_port_map);
 		port_map &= hpriv->mask_port_map;
@@ -546,7 +559,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 		 */
 		if (map_ports > ahci_nr_ports(cap)) {
 			dev_warn(dev,
-				 "implemented port map (0x%x) contains more ports than nr_ports (%u), using nr_ports\n",
+				 "implemented port map (0x%lx) contains more ports than nr_ports (%u), using nr_ports\n",
 				 port_map, ahci_nr_ports(cap));
 			port_map = 0;
 		}
@@ -555,12 +568,26 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 	/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
 	if (!port_map && vers < 0x10300) {
 		port_map = (1 << ahci_nr_ports(cap)) - 1;
-		dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
+		dev_warn(dev, "forcing PORTS_IMPL to 0x%lx\n", port_map);
 
 		/* write the fixed up value to the PI register */
 		hpriv->saved_port_map = port_map;
 	}
 
+	/*
+	 * Preserve the ports capabilities defined by the platform. Note there
+	 * is no need in storing the rest of the P#.CMD fields since they are
+	 * volatile.
+	 */
+	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
+		if (hpriv->saved_port_cap[i])
+			continue;
+
+		port_mmio = __ahci_port_base(hpriv, i);
+		hpriv->saved_port_cap[i] =
+			readl(port_mmio + PORT_CMD) & PORT_CMD_CAP;
+	}
+
 	/* record values to use during operation */
 	hpriv->cap = cap;
 	hpriv->cap2 = cap2;
@@ -590,13 +617,21 @@ EXPORT_SYMBOL_GPL(ahci_save_initial_config);
 static void ahci_restore_initial_config(struct ata_host *host)
 {
 	struct ahci_host_priv *hpriv = host->private_data;
+	unsigned long port_map = hpriv->port_map;
 	void __iomem *mmio = hpriv->mmio;
+	void __iomem *port_mmio;
+	int i;
 
 	writel(hpriv->saved_cap, mmio + HOST_CAP);
 	if (hpriv->saved_cap2)
 		writel(hpriv->saved_cap2, mmio + HOST_CAP2);
 	writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
 	(void) readl(mmio + HOST_PORTS_IMPL);	/* flush */
+
+	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
+		port_mmio = __ahci_port_base(hpriv, i);
+		writel(hpriv->saved_port_cap[i], port_mmio + PORT_CMD);
+	}
 }
 
 static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index efe640603f3f..8b542a8bc487 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -23,6 +23,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/of_platform.h>
 #include <linux/reset.h>
+
 #include "ahci.h"
 
 static void ahci_host_stop(struct ata_host *host);
@@ -383,6 +384,34 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
 	return rc;
 }
 
+static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv,
+				      struct device *dev)
+{
+	struct device_node *child;
+	u32 port;
+
+	if (!of_property_read_u32(dev->of_node, "hba-cap", &hpriv->saved_cap))
+		hpriv->saved_cap &= (HOST_CAP_SSS | HOST_CAP_MPS);
+
+	of_property_read_u32(dev->of_node,
+			     "ports-implemented", &hpriv->saved_port_map);
+
+	for_each_child_of_node(dev->of_node, child) {
+		if (!of_device_is_available(child))
+			continue;
+
+		if (of_property_read_u32(child, "reg", &port)) {
+			of_node_put(child);
+			return -EINVAL;
+		}
+
+		if (!of_property_read_u32(child, "hba-port-cap", &hpriv->saved_port_cap[port]))
+			hpriv->saved_port_cap[port] &= PORT_CMD_CAP;
+	}
+
+	return 0;
+}
+
 /**
  * ahci_platform_get_resources - Get platform resources
  * @pdev: platform device to get resources for
@@ -523,9 +552,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 		goto err_out;
 	}
 
-	of_property_read_u32(dev->of_node,
-			     "ports-implemented", &hpriv->saved_port_map);
-
 	if (child_nodes) {
 		for_each_child_of_node(dev->of_node, child) {
 			u32 port;
@@ -590,6 +616,15 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
 		if (rc == -EPROBE_DEFER)
 			goto err_out;
 	}
+
+	/*
+	 * Retrieve firmware-specific flags which then will be used to set
+	 * the HW-init fields of HBA and its ports
+	 */
+	rc = ahci_platform_get_firmware(hpriv, dev);
+	if (rc)
+		goto err_out;
+
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 	hpriv->got_runtime_pm = true;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (15 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 16/23] ata: ahci: Introduce firmware-specific caps initialization Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14 22:27   ` Rob Herring
  2022-06-10  8:17 ` [PATCH v4 18/23] ata: libahci_platform: Add function returning a clock-handle by id Serge Semin
                   ` (5 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Rob Herring, Krzysztof Kozlowski, Serge Semin
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, linux-ide,
	linux-kernel, devicetree

Synopsys AHCI SATA controller is mainly compatible with the generic AHCI
SATA controller except a few peculiarities and the platform environment
requirements. In particular it can have one or two reference clocks to
feed up its AXI/AHB interface and SATA PHYs domain and at least one reset
control for the application clock domain. In addition to that the DMA
interface of each port can be tuned up to work with the predefined maximum
data chunk size. Note unlike generic AHCI controller DWC AHCI can't have
more than 8 ports. All of that is reflected in the new DWC AHCI SATA
device DT binding.

Note the DWC AHCI SATA controller DT-schema has been created in a way so
to be reused for the vendor-specific DT-schemas (see for example the
"snps,dwc-ahci" compatible string binding). One of which we are about to
introduce.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

---

Changelog v2:
- Replace min/max constraints of the snps,{tx,rx}-ts-max property with
  enum [ 1, 2, 4, ..., 1024 ]. (@Rob)

Changelog v4:
- Decrease the "additionalProperties" property identation otherwise it's
  percieved as the node property instead of the key one. (@Rob)
- Use the ahci-port properties definition from the AHCI common schema
  in order to extend it with DWC AHCI SATA port properties. (@Rob)
- Remove the Hannes' rb tag since the patch content has changed.
---
 .../bindings/ata/ahci-platform.yaml           |   8 --
 .../bindings/ata/snps,dwc-ahci.yaml           | 129 ++++++++++++++++++
 2 files changed, 129 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml

diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
index e19cf9828e68..7dc2a2e8f598 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
@@ -30,8 +30,6 @@ select:
           - marvell,armada-3700-ahci
           - marvell,armada-8k-ahci
           - marvell,berlin2q-ahci
-          - snps,dwc-ahci
-          - snps,spear-ahci
   required:
     - compatible
 
@@ -48,17 +46,11 @@ properties:
               - marvell,berlin2-ahci
               - marvell,berlin2q-ahci
           - const: generic-ahci
-      - items:
-          - enum:
-              - rockchip,rk3568-dwc-ahci
-          - const: snps,dwc-ahci
       - enum:
           - cavium,octeon-7130-ahci
           - hisilicon,hisi-ahci
           - ibm,476gtr-ahci
           - marvell,armada-3700-ahci
-          - snps,dwc-ahci
-          - snps,spear-ahci
 
   reg:
     minItems: 1
diff --git a/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
new file mode 100644
index 000000000000..af78f6c9b857
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
@@ -0,0 +1,129 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ata/snps,dwc-ahci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DWC AHCI SATA controller
+
+maintainers:
+  - Serge Semin <fancer.lancer@gmail.com>
+
+description:
+  This document defines device tree bindings for the Synopsys DWC
+  implementation of the AHCI SATA controller.
+
+allOf:
+  - $ref: ahci-common.yaml#
+
+properties:
+  compatible:
+    oneOf:
+      - description: Synopsys AHCI SATA-compatible devices
+        contains:
+          const: snps,dwc-ahci
+      - description: SPEAr1340 AHCI SATA device
+        const: snps,spear-ahci
+      - description: Rockhip RK3568 ahci controller
+        const: rockchip,rk3568-dwc-ahci
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    description:
+      Basic DWC AHCI SATA clock sources like application AXI/AHB BIU clock
+      and embedded PHYs reference clock together with vendor-specific set
+      of clocks.
+    minItems: 1
+    maxItems: 4
+
+  clock-names:
+    contains:
+      anyOf:
+        - description: Application AXI/AHB BIU clock source
+          enum:
+            - aclk
+            - sata
+        - description: SATA Ports reference clock
+          enum:
+            - ref
+            - sata_ref
+
+  resets:
+    description:
+      At least basic core and application clock domains reset is normally
+      supported by the DWC AHCI SATA controller. Some platform specific
+      clocks can be also specified though.
+
+  reset-names:
+    contains:
+      description: Core and application clock domains reset control
+      const: arst
+
+patternProperties:
+  "^sata-port@[0-9a-e]$":
+    $ref: '#/$defs/dwc-ahci-port'
+
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+unevaluatedProperties: false
+
+$defs:
+  dwc-ahci-port:
+    $ref: /schemas/ata/ahci-common.yaml#/$defs/ahci-port
+
+    properties:
+      reg:
+        minimum: 0
+        maximum: 7
+
+      snps,tx-ts-max:
+        $ref: /schemas/types.yaml#/definitions/uint32
+        description: Maximal size of Tx DMA transactions in FIFO words
+        enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
+
+      snps,rx-ts-max:
+        $ref: /schemas/types.yaml#/definitions/uint32
+        description: Maximal size of Rx DMA transactions in FIFO words
+        enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/ata/ahci.h>
+
+    sata@122f0000 {
+      compatible = "snps,dwc-ahci";
+      reg = <0x122F0000 0x1ff>;
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+
+      clocks = <&clock1>, <&clock2>;
+      clock-names = "aclk", "ref";
+
+      phys = <&sata_phy>;
+      phy-names = "sata-phy";
+
+      ports-implemented = <0x1>;
+
+      sata-port@0 {
+        reg = <0>;
+
+        hba-port-cap = <HBA_PORT_FBSCP>;
+
+        snps,tx-ts-max = <512>;
+        snps,rx-ts-max = <512>;
+      };
+    };
+...
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 18/23] ata: libahci_platform: Add function returning a clock-handle by id
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (16 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14  8:45   ` Damien Le Moal
  2022-06-10  8:17 ` [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support Serge Semin
                   ` (4 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

Since all the clocks are retrieved by the method
ahci_platform_get_resources() there is no need for the LLD (glue) drivers
to be looking for some particular of them in the kernel clocks table
again. Instead we suggest to add a simple method returning a
device-specific clock with passed connection ID if it is managed to be
found. Otherwise the function will return NULL. Thus the glue-drivers
won't need to either manually touching the hpriv->clks array or calling
clk_get()-friends. The AHCI platform drivers will be able to use the new
function right after the ahci_platform_get_resources() method invocation
and up to the device removal.

Note the method is left unused here, but will be utilized in the framework
of the DWC AHCI SATA driver being added in the next commit.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

---

Changelog v2:
- Fix some grammar mistakes in the method description.

Changelog v4:
- Add a note regarding the new method usage.
---
 drivers/ata/libahci_platform.c | 27 +++++++++++++++++++++++++++
 include/linux/ahci_platform.h  |  3 +++
 2 files changed, 30 insertions(+)

diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 8b542a8bc487..418961f954af 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -95,6 +95,33 @@ void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
 }
 EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
 
+/**
+ * ahci_platform_find_clk - Find platform clock
+ * @hpriv: host private area to store config values
+ * @con_id: clock connection ID
+ *
+ * This function returns a pointer to the clock descriptor of the clock with
+ * the passed ID.
+ *
+ * RETURNS:
+ * Pointer to the clock descriptor on success otherwise NULL
+ */
+struct clk *ahci_platform_find_clk(struct ahci_host_priv *hpriv, const char *con_id)
+{
+	struct clk *clk = NULL;
+	int i;
+
+	for (i = 0; i < hpriv->n_clks; i++) {
+		if (!strcmp(hpriv->clks[i].id, con_id)) {
+			clk = hpriv->clks[i].clk;
+			break;
+		}
+	}
+
+	return clk;
+}
+EXPORT_SYMBOL_GPL(ahci_platform_find_clk);
+
 /**
  * ahci_platform_enable_clks - Enable platform clocks
  * @hpriv: host private area to store config values
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 6d7dd472d370..3418980b0341 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -13,6 +13,7 @@
 
 #include <linux/compiler.h>
 
+struct clk;
 struct device;
 struct ata_port_info;
 struct ahci_host_priv;
@@ -21,6 +22,8 @@ struct scsi_host_template;
 
 int ahci_platform_enable_phys(struct ahci_host_priv *hpriv);
 void ahci_platform_disable_phys(struct ahci_host_priv *hpriv);
+struct clk *
+ahci_platform_find_clk(struct ahci_host_priv *hpriv, const char *con_id);
 int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
 void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
 int ahci_platform_deassert_rsts(struct ahci_host_priv *hpriv);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (17 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 18/23] ata: libahci_platform: Add function returning a clock-handle by id Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-10 16:34   ` Randy Dunlap
  2022-06-14  8:53   ` Damien Le Moal
  2022-06-10  8:17 ` [PATCH v4 20/23] dt-bindings: ata: ahci: Add Baikal-T1 AHCI SATA controller DT schema Serge Semin
                   ` (3 subsequent siblings)
  22 siblings, 2 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke, Serge Semin
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

Synopsys AHCI SATA controller can work pretty under with the generic
AHCI-platform driver control. But there are vendor-specific peculiarities
which can tune the device performance up and which may need to be fixed up
for proper device functioning. In addition some DWC AHCI-based controllers
may require small platform-specific fixups, so adding them in the generic
AHCI driver would have ruined the code simplicity. Shortly speaking in
order to keep the generic AHCI-platform code clean and have DWC AHCI
SATA-specific features supported we suggest to add a dedicated DWC AHCI
SATA device driver. Aside with the standard AHCI-platform resources
getting, enabling/disabling and the controller registration the new driver
performs the next actions.

First of all there is a way to verify whether the HBA/ports capabilities
activated in OF are correct. Almost all features availability is reflected
in the vendor-specific parameters registers. So the DWC AHCI driver does
the capabilities sanity check based on the corresponding fields state.

Secondly if either the Command Completion Coalescing or the Device Sleep
feature is enabled the DWC AHCI-specific internal 1ms timer must be fixed
in accordance with the application clock signal frequency. In particular
the timer value must be set to be Fapp * 1000. Normally the SoC designers
pre-configure the TIMER1MS register to contain a correct value by default.
But the platforms can support the application clock rate change. If that
happens the 1ms timer value must be accordingly updated otherwise the
dependent features won't work as expected. In the DWC AHCI driver we
suggest to rely on the "aclk" reference clock rate to set the timer
interval up. That clock source is supposed to be the AHCI SATA application
clock in accordance with the DT bindings.

Finally DWC AHCI SATA controller AXI/AHB bus DMA-engine can be tuned up to
transfer up to 1024 * FIFO words at a time by setting the Tx/Rx
transaction size in the DMA control register. The maximum value depends on
the DMA data bus and AXI/AHB bus maximum burst length. In most of the
cases it's better to set the maximum possible value to reach the best AHCI
SATA controller performance. But sometimes in order to improve the system
interconnect responsiveness, transferring in smaller data chunks may be
more preferable. For such cases and for the case when the default value
doesn't provide the best DMA bus performance we suggest to use the new
HBA-port specific DT-properties "snps,{tx,rx}-ts-max" to tune the DMA
transactions size up.

After all the settings denoted above are handled the DWC AHCI SATA driver
proceeds further with the standard AHCI-platform host initializations.

Note since DWC AHCI controller is now have a dedicated driver we can
discard the corresponding compatible string from the ahci-platform.c
module. The same concerns "snps,spear-ahci" compatible string, which is
also based on the DWC AHCI IP-core.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>

---

Note there are three more AHCI SATA drivers which have been created for
the devices based on the DWC AHCI SATA IP-core. It's AHCI SunXi, St and
iMX drivers. Mostly they don't support the features implemented in this
driver. So hopefully sometime in future they can be converted to be based
on the generic DWC AHCI SATA driver and just perform some
subvendor-specific setups in their own LLDD (glue) driver code. But for
now let's leave the generic DWC AHCI SATA code as is. Hopefully the new
DWC AHCI-based device drivers will try at least to re-use a part of the
DWC AHCI driver methods if not being able to be integrated in the generic
DWC driver code.

Changelog v2:
- Change the local objects prefix from 'dwc_ahci_' to 'ahci_dwc_'.
  (@Damien)

Changelog v4:
- Replace GPLv2 with just GPL license which are the same in the framework
  of the MODULE_LICENSE() macro.
---
 drivers/ata/Kconfig         |  10 +
 drivers/ata/Makefile        |   1 +
 drivers/ata/ahci_dwc.c      | 395 ++++++++++++++++++++++++++++++++++++
 drivers/ata/ahci_platform.c |   2 -
 4 files changed, 406 insertions(+), 2 deletions(-)
 create mode 100644 drivers/ata/ahci_dwc.c

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index bb45a9c00514..95e0e022b5bb 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -176,6 +176,16 @@ config AHCI_DM816
 
 	  If unsure, say N.
 
+config AHCI_DWC
+	tristate "Synopsys DWC AHCI SATA support"
+	select SATA_HOST
+	default SATA_AHCI_PLATFORM
+	help
+	  This option enables support for the Synopsys DWC AHCI SATA
+	  controller implementation.
+
+	  If unsure, say N.
+
 config AHCI_ST
 	tristate "ST AHCI SATA support"
 	depends on ARCH_STI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index b8aebfb14e82..34623365d9a6 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_AHCI_BRCM)		+= ahci_brcm.o libahci.o libahci_platform.o
 obj-$(CONFIG_AHCI_CEVA)		+= ahci_ceva.o libahci.o libahci_platform.o
 obj-$(CONFIG_AHCI_DA850)	+= ahci_da850.o libahci.o libahci_platform.o
 obj-$(CONFIG_AHCI_DM816)	+= ahci_dm816.o libahci.o libahci_platform.o
+obj-$(CONFIG_AHCI_DWC)		+= ahci_dwc.o libahci.o libahci_platform.o
 obj-$(CONFIG_AHCI_IMX)		+= ahci_imx.o libahci.o libahci_platform.o
 obj-$(CONFIG_AHCI_MTK)		+= ahci_mtk.o libahci.o libahci_platform.o
 obj-$(CONFIG_AHCI_MVEBU)	+= ahci_mvebu.o libahci.o libahci_platform.o
diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c
new file mode 100644
index 000000000000..8c2510933a31
--- /dev/null
+++ b/drivers/ata/ahci_dwc.c
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * DWC AHCI SATA Platform driver
+ *
+ * Copyright (C) 2021 BAIKAL ELECTRONICS, JSC
+ */
+
+#include <linux/ahci_platform.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/libata.h>
+#include <linux/log2.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+
+#include "ahci.h"
+
+#define DRV_NAME "ahci-dwc"
+
+#define AHCI_DWC_FBS_PMPN_MAX		15
+
+/* DWC AHCI SATA controller specific registers */
+#define AHCI_DWC_HOST_OOBR		0xbc
+#define AHCI_DWC_HOST_OOB_WE		BIT(31)
+#define AHCI_DWC_HOST_CWMIN_MASK	GENMASK(30, 24)
+#define AHCI_DWC_HOST_CWMAX_MASK	GENMASK(23, 16)
+#define AHCI_DWC_HOST_CIMIN_MASK	GENMASK(15, 8)
+#define AHCI_DWC_HOST_CIMAX_MASK	GENMASK(7, 0)
+
+#define AHCI_DWC_HOST_GPCR		0xd0
+#define AHCI_DWC_HOST_GPSR		0xd4
+
+#define AHCI_DWC_HOST_TIMER1MS		0xe0
+#define AHCI_DWC_HOST_TIMV_MASK		GENMASK(19, 0)
+
+#define AHCI_DWC_HOST_GPARAM1R		0xe8
+#define AHCI_DWC_HOST_ALIGN_M		BIT(31)
+#define AHCI_DWC_HOST_RX_BUFFER		BIT(30)
+#define AHCI_DWC_HOST_PHY_DATA_MASK	GENMASK(29, 28)
+#define AHCI_DWC_HOST_PHY_RST		BIT(27)
+#define AHCI_DWC_HOST_PHY_CTRL_MASK	GENMASK(26, 21)
+#define AHCI_DWC_HOST_PHY_STAT_MASK	GENMASK(20, 15)
+#define AHCI_DWC_HOST_LATCH_M		BIT(14)
+#define AHCI_DWC_HOST_PHY_TYPE_MASK	GENMASK(13, 11)
+#define AHCI_DWC_HOST_RET_ERR		BIT(10)
+#define AHCI_DWC_HOST_AHB_ENDIAN_MASK	GENMASK(9, 8)
+#define AHCI_DWC_HOST_S_HADDR		BIT(7)
+#define AHCI_DWC_HOST_M_HADDR		BIT(6)
+#define AHCI_DWC_HOST_S_HDATA_MASK	GENMASK(5, 3)
+#define AHCI_DWC_HOST_M_HDATA_MASK	GENMASK(2, 0)
+
+#define AHCI_DWC_HOST_GPARAM2R		0xec
+#define AHCI_DWC_HOST_FBS_MEM_S		BIT(19)
+#define AHCI_DWC_HOST_FBS_PMPN_MASK	GENMASK(17, 16)
+#define AHCI_DWC_HOST_FBS_SUP		BIT(15)
+#define AHCI_DWC_HOST_DEV_CP		BIT(14)
+#define AHCI_DWC_HOST_DEV_MP		BIT(13)
+#define AHCI_DWC_HOST_ENCODE_M		BIT(12)
+#define AHCI_DWC_HOST_RXOOB_CLK_M	BIT(11)
+#define AHCI_DWC_HOST_RXOOB_M		BIT(10)
+#define AHCI_DWC_HOST_TXOOB_M		BIT(9)
+#define AHCI_DWC_HOST_RXOOB_M		BIT(10)
+#define AHCI_DWC_HOST_RXOOB_CLK_MASK	GENMASK(8, 0)
+
+#define AHCI_DWC_HOST_PPARAMR		0xf0
+#define AHCI_DWC_HOST_TX_MEM_M		BIT(11)
+#define AHCI_DWC_HOST_TX_MEM_S		BIT(10)
+#define AHCI_DWC_HOST_RX_MEM_M		BIT(9)
+#define AHCI_DWC_HOST_RX_MEM_S		BIT(8)
+#define AHCI_DWC_HOST_TXFIFO_DEPTH	GENMASK(7, 4)
+#define AHCI_DWC_HOST_RXFIFO_DEPTH	GENMASK(3, 0)
+
+#define AHCI_DWC_HOST_TESTR		0xf4
+#define AHCI_DWC_HOST_PSEL_MASK		GENMASK(18, 16)
+#define AHCI_DWC_HOST_TEST_IF		BIT(0)
+
+#define AHCI_DWC_HOST_VERSIONR		0xf8
+#define AHCI_DWC_HOST_IDR		0xfc
+
+#define AHCI_DWC_PORT_DMACR		0x70
+#define AHCI_DWC_PORT_RXABL_MASK	GENMASK(15, 12)
+#define AHCI_DWC_PORT_TXABL_MASK	GENMASK(11, 8)
+#define AHCI_DWC_PORT_RXTS_MASK		GENMASK(7, 4)
+#define AHCI_DWC_PORT_TXTS_MASK		GENMASK(3, 0)
+#define AHCI_DWC_PORT_PHYCR		0x74
+#define AHCI_DWC_PORT_PHYSR		0x78
+
+struct ahci_dwc_host_priv {
+	struct platform_device *pdev;
+
+	u32 timv;
+	u32 dmacr[AHCI_MAX_PORTS];
+};
+
+static struct ahci_host_priv *ahci_dwc_get_resources(struct platform_device *pdev)
+{
+	struct ahci_dwc_host_priv *dpriv;
+	struct ahci_host_priv *hpriv;
+
+	dpriv = devm_kzalloc(&pdev->dev, sizeof(*dpriv), GFP_KERNEL);
+	if (!dpriv)
+		return ERR_PTR(-ENOMEM);
+
+	dpriv->pdev = pdev;
+
+	hpriv = ahci_platform_get_resources(pdev, AHCI_PLATFORM_GET_RESETS);
+	if (IS_ERR(hpriv))
+		return hpriv;
+
+	hpriv->plat_data = (void *)dpriv;
+
+	return hpriv;
+}
+
+static void ahci_dwc_check_cap(struct ahci_host_priv *hpriv)
+{
+	unsigned long port_map = hpriv->saved_port_map | hpriv->mask_port_map;
+	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
+	bool dev_mp, dev_cp, fbs_sup;
+	unsigned int fbs_pmp;
+	u32 param;
+	int i;
+
+	param = readl(hpriv->mmio + AHCI_DWC_HOST_GPARAM2R);
+	dev_mp = !!(param & AHCI_DWC_HOST_DEV_MP);
+	dev_cp = !!(param & AHCI_DWC_HOST_DEV_CP);
+	fbs_sup = !!(param & AHCI_DWC_HOST_FBS_SUP);
+	fbs_pmp = 5 * FIELD_GET(AHCI_DWC_HOST_FBS_PMPN_MASK, param);
+
+	if (!dev_mp && hpriv->saved_cap & HOST_CAP_MPS) {
+		dev_warn(&dpriv->pdev->dev, "MPS is unsupported\n");
+		hpriv->saved_cap &= ~HOST_CAP_MPS;
+	}
+
+
+	if (fbs_sup && fbs_pmp < AHCI_DWC_FBS_PMPN_MAX) {
+		dev_warn(&dpriv->pdev->dev, "PMPn is limited up to %u ports\n",
+			 fbs_pmp);
+	}
+
+	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
+		if (!dev_mp && hpriv->saved_port_cap[i] & PORT_CMD_MPSP) {
+			dev_warn(&dpriv->pdev->dev, "MPS incapable port %d\n", i);
+			hpriv->saved_port_cap[i] &= ~PORT_CMD_MPSP;
+		}
+
+		if (!dev_cp && hpriv->saved_port_cap[i] & PORT_CMD_CPD) {
+			dev_warn(&dpriv->pdev->dev, "CPD incapable port %d\n", i);
+			hpriv->saved_port_cap[i] &= ~PORT_CMD_CPD;
+		}
+
+		if (!fbs_sup && hpriv->saved_port_cap[i] & PORT_CMD_FBSCP) {
+			dev_warn(&dpriv->pdev->dev, "FBS incapable port %d\n", i);
+			hpriv->saved_port_cap[i] &= ~PORT_CMD_FBSCP;
+		}
+	}
+}
+
+static void ahci_dwc_init_timer(struct ahci_host_priv *hpriv)
+{
+	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
+	unsigned long rate;
+	struct clk *aclk;
+	u32 cap, cap2;
+
+	/* 1ms tick is generated only for the CCC or DevSleep features */
+	cap = readl(hpriv->mmio + HOST_CAP);
+	cap2 = readl(hpriv->mmio + HOST_CAP2);
+	if (!(cap & HOST_CAP_CCC) && !(cap2 & HOST_CAP2_SDS))
+		return;
+
+	/*
+	 * Tick is generated based on the AXI/AHB application clocks signal
+	 * so we need to be sure in the clock we are going to use.
+	 */
+	aclk = ahci_platform_find_clk(hpriv, "aclk");
+	if (!aclk)
+		return;
+
+	/* 1ms timer interval is set as TIMV = AMBA_FREQ[MHZ] * 1000 */
+	dpriv->timv = readl(hpriv->mmio + AHCI_DWC_HOST_TIMER1MS);
+	dpriv->timv = FIELD_GET(AHCI_DWC_HOST_TIMV_MASK, dpriv->timv);
+	rate = clk_get_rate(aclk) / 1000UL;
+	if (rate == dpriv->timv)
+		return;
+
+	dev_info(&dpriv->pdev->dev, "Update CCC/DevSlp timer for Fapp %lu MHz\n",
+		 rate / 1000UL);
+	dpriv->timv = FIELD_PREP(AHCI_DWC_HOST_TIMV_MASK, rate);
+	writel(dpriv->timv, hpriv->mmio + AHCI_DWC_HOST_TIMER1MS);
+}
+
+static int ahci_dwc_init_dmacr(struct ahci_host_priv *hpriv)
+{
+	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
+	struct device_node *child;
+	void __iomem *port_mmio;
+	u32 port, dmacr, ts;
+
+	/*
+	 * Update the DMA Tx/Rx transaction sizes in accordance with the
+	 * platform setup. Note values exceeding maximal or minimal limits will
+	 * be automatically clamped. Also note the register isn't affected by
+	 * the HBA global reset so we can freely initialize it once until the
+	 * next system reset.
+	 */
+	for_each_child_of_node(dpriv->pdev->dev.of_node, child) {
+		if (!of_device_is_available(child))
+			continue;
+
+		if (of_property_read_u32(child, "reg", &port)) {
+			of_node_put(child);
+			return -EINVAL;
+		}
+
+		port_mmio = __ahci_port_base(hpriv, port);
+		dmacr = readl(port_mmio + AHCI_DWC_PORT_DMACR);
+
+		if (!of_property_read_u32(child, "snps,tx-ts-max", &ts)) {
+			ts = ilog2(ts);
+			dmacr &= ~AHCI_DWC_PORT_TXTS_MASK;
+			dmacr |= FIELD_PREP(AHCI_DWC_PORT_TXTS_MASK, ts);
+		}
+
+		if (!of_property_read_u32(child, "snps,rx-ts-max", &ts)) {
+			ts = ilog2(ts);
+			dmacr &= ~AHCI_DWC_PORT_RXTS_MASK;
+			dmacr |= FIELD_PREP(AHCI_DWC_PORT_RXTS_MASK, ts);
+		}
+
+		writel(dmacr, port_mmio + AHCI_DWC_PORT_DMACR);
+		dpriv->dmacr[port] = dmacr;
+	}
+
+	return 0;
+}
+
+static int ahci_dwc_init_host(struct ahci_host_priv *hpriv)
+{
+	int rc;
+
+	rc = ahci_platform_enable_resources(hpriv);
+	if (rc)
+		return rc;
+
+	ahci_dwc_check_cap(hpriv);
+
+	ahci_dwc_init_timer(hpriv);
+
+	rc = ahci_dwc_init_dmacr(hpriv);
+	if (rc)
+		goto err_disable_resources;
+
+	return 0;
+
+err_disable_resources:
+	ahci_platform_disable_resources(hpriv);
+
+	return rc;
+}
+
+static int ahci_dwc_reinit_host(struct ahci_host_priv *hpriv)
+{
+	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
+	unsigned long port_map = hpriv->port_map;
+	void __iomem *port_mmio;
+	int i, rc;
+
+	rc = ahci_platform_enable_resources(hpriv);
+	if (rc)
+		return rc;
+
+	writel(dpriv->timv, hpriv->mmio + AHCI_DWC_HOST_TIMER1MS);
+
+	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
+		port_mmio = __ahci_port_base(hpriv, i);
+		writel(dpriv->dmacr[i], port_mmio + AHCI_DWC_PORT_DMACR);
+	}
+
+	return 0;
+}
+
+static void ahci_dwc_clear_host(struct ahci_host_priv *hpriv)
+{
+	ahci_platform_disable_resources(hpriv);
+}
+
+static void ahci_dwc_stop_host(struct ata_host *host)
+{
+	struct ahci_host_priv *hpriv = host->private_data;
+
+	ahci_dwc_clear_host(hpriv);
+}
+
+static struct ata_port_operations ahci_dwc_port_ops = {
+	.inherits	= &ahci_platform_ops,
+	.host_stop	= ahci_dwc_stop_host,
+};
+
+static const struct ata_port_info ahci_dwc_port_info = {
+	.flags		= AHCI_FLAG_COMMON,
+	.pio_mask	= ATA_PIO4,
+	.udma_mask	= ATA_UDMA6,
+	.port_ops	= &ahci_dwc_port_ops,
+};
+
+static struct scsi_host_template ahci_dwc_scsi_info = {
+	AHCI_SHT(DRV_NAME),
+};
+
+static int ahci_dwc_probe(struct platform_device *pdev)
+{
+	struct ahci_host_priv *hpriv;
+	int rc;
+
+	hpriv = ahci_dwc_get_resources(pdev);
+	if (IS_ERR(hpriv))
+		return PTR_ERR(hpriv);
+
+	rc = ahci_dwc_init_host(hpriv);
+	if (rc)
+		return rc;
+
+	rc = ahci_platform_init_host(pdev, hpriv, &ahci_dwc_port_info,
+				     &ahci_dwc_scsi_info);
+	if (rc)
+		goto err_clear_host;
+
+	return 0;
+
+err_clear_host:
+	ahci_dwc_clear_host(hpriv);
+
+	return rc;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int ahci_dwc_suspend(struct device *dev)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	int rc;
+
+	rc = ahci_platform_suspend_host(dev);
+	if (rc)
+		return rc;
+
+	ahci_dwc_clear_host(hpriv);
+
+	return 0;
+}
+
+static int ahci_dwc_resume(struct device *dev)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	int rc;
+
+	rc = ahci_dwc_reinit_host(hpriv);
+	if (rc)
+		return rc;
+
+	return ahci_platform_resume_host(dev);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(ahci_dwc_pm_ops, ahci_dwc_suspend, ahci_dwc_resume);
+
+static const struct of_device_id ahci_dwc_of_match[] = {
+	{ .compatible = "snps,dwc-ahci", },
+	{ .compatible = "snps,spear-ahci", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ahci_dwc_of_match);
+
+static struct platform_driver ahci_dwc_driver = {
+	.probe = ahci_dwc_probe,
+	.remove = ata_platform_remove_one,
+	.shutdown = ahci_platform_shutdown,
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = ahci_dwc_of_match,
+		.pm = &ahci_dwc_pm_ops,
+	},
+};
+module_platform_driver(ahci_dwc_driver);
+
+MODULE_DESCRIPTION("DWC AHCI SATA platform driver");
+MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 9b56490ecbc3..8f5572a9f8f1 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -80,9 +80,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
 static const struct of_device_id ahci_of_match[] = {
 	{ .compatible = "generic-ahci", },
 	/* Keep the following compatibles for device tree compatibility */
-	{ .compatible = "snps,spear-ahci", },
 	{ .compatible = "ibm,476gtr-ahci", },
-	{ .compatible = "snps,dwc-ahci", },
 	{ .compatible = "hisilicon,hisi-ahci", },
 	{ .compatible = "cavium,octeon-7130-ahci", },
 	{ /* sentinel */ }
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 20/23] dt-bindings: ata: ahci: Add Baikal-T1 AHCI SATA controller DT schema
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (18 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-14 22:29   ` Rob Herring
  2022-06-10  8:17 ` [PATCH v4 21/23] ata: ahci-dwc: Add platform-specific quirks support Serge Semin
                   ` (2 subsequent siblings)
  22 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Serge Semin, Rob Herring, Krzysztof Kozlowski
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, linux-ide,
	linux-kernel, devicetree

Baikal-T1 AHCI controller is based on the DWC AHCI SATA IP-core v4.10a
with the next specific settings: two SATA ports, cascaded CSR access based
on two clock domains (APB and AXI), selectable source of the reference
clock (though stable work is currently available from the external source
only), two reset lanes for the application and SATA ports domains. Other
than that the device is fully compatible with the generic DWC AHCI SATA
bindings.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>

---

Changelog v2:
- Rename 'syscon' property to 'baikal,bt1-syscon'.
- Drop macro usage from the example node.

Changelog v4:
- Use the DWC AHCI port properties definition from the DWC AHCI SATA
  common schema. (@Rob)
- Drop Baikal-T1 syscon reference and implement the clock signal
  source in the framework of the clock controller. (@Rob)
---
 .../bindings/ata/baikal,bt1-ahci.yaml         | 116 ++++++++++++++++++
 1 file changed, 116 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml

diff --git a/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml b/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
new file mode 100644
index 000000000000..d5fbd7d561d8
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
@@ -0,0 +1,116 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ata/baikal,bt1-ahci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Baikal-T1 SoC AHCI SATA controller
+
+maintainers:
+  - Serge Semin <fancer.lancer@gmail.com>
+
+description: |
+  AHCI SATA controller embedded into the Baikal-T1 SoC is based on the
+  DWC AHCI SATA v4.10a IP-core.
+
+allOf:
+  - $ref: snps,dwc-ahci.yaml#
+
+properties:
+  compatible:
+    contains:
+      const: baikal,bt1-ahci
+
+  clocks:
+    items:
+      - description: Peripheral APB bus clock source
+      - description: Application AXI BIU clock
+      - description: SATA Ports reference clock
+
+  clock-names:
+    items:
+      - const: pclk
+      - const: aclk
+      - const: ref
+
+  resets:
+    items:
+      - description: Application AXI BIU domain reset
+      - description: SATA Ports clock domain reset
+
+  reset-names:
+    items:
+      - const: arst
+      - const: ref
+
+  ports-implemented:
+    maximum: 0x3
+
+patternProperties:
+  "^sata-port@[0-9a-e]$":
+    $ref: /schemas/ata/snps,dwc-ahci.yaml#/$defs/dwc-ahci-port
+
+    properties:
+      reg:
+        minimum: 0
+        maximum: 1
+
+      snps,tx-ts-max:
+        $ref: /schemas/types.yaml#/definitions/uint32
+        description:
+          Due to having AXI3 bus interface utilized the maximum Tx DMA
+          transaction size can't exceed 16 beats (AxLEN[3:0]).
+        enum: [ 1, 2, 4, 8, 16 ]
+
+      snps,rx-ts-max:
+        $ref: /schemas/types.yaml#/definitions/uint32
+        description:
+          Due to having AXI3 bus interface utilized the maximum Rx DMA
+          transaction size can't exceed 16 beats (AxLEN[3:0]).
+        enum: [ 1, 2, 4, 8, 16 ]
+
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - resets
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    sata@1f050000 {
+      compatible = "baikal,bt1-ahci", "snps,dwc-ahci";
+      reg = <0x1f050000 0x2000>;
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      interrupts = <0 64 4>;
+
+      clocks = <&ccu_sys 1>, <&ccu_axi 2>, <&sata_ref_clk>;
+      clock-names = "pclk", "aclk", "ref";
+
+      resets = <&ccu_axi 2>, <&ccu_sys 0>;
+      reset-names = "arst", "ref";
+
+      ports-implemented = <0x3>;
+
+      sata-port@0 {
+        reg = <0>;
+
+        snps,tx-ts-max = <4>;
+        snps,rx-ts-max = <4>;
+      };
+
+      sata-port@1 {
+        reg = <1>;
+
+        snps,tx-ts-max = <4>;
+        snps,rx-ts-max = <4>;
+      };
+    };
+...
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 21/23] ata: ahci-dwc: Add platform-specific quirks support
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (19 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 20/23] dt-bindings: ata: ahci: Add Baikal-T1 AHCI SATA controller DT schema Serge Semin
@ 2022-06-10  8:17 ` Serge Semin
  2022-06-10  8:18 ` [PATCH v4 22/23] ata: ahci-dwc: Add Baikal-T1 AHCI SATA interface support Serge Semin
  2022-06-10  8:18 ` [PATCH v4 23/23] MAINTAINERS: Add maintainers for DWC AHCI SATA driver Serge Semin
  22 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:17 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke, Serge Semin
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

Some DWC AHCI SATA IP-core derivatives require to perform small platform
or IP-core specific setups. They are too small to be placed in a dedicated
driver. It's just much easier to have a set of quirks for them right in
the DWC AHCI driver code. Since we are about to add such platform support,
as a pre-requisite we introduce a platform-data based DWC AHCI quirks API.
The platform data can be used to define the flags passed to the
ahci_platform_get_resources() method, additional AHCI host-flags and a set
of callbacks to initialize, re-initialize and clear the platform settings.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

---

Changelog v2:
- Change the local objects prefix from 'dwc_ahci_' to 'ahci_dwc_'.
  (@Damien)

Changelog v4:
- Convert ahci_dwc_plat to being statically defined. (@kbot)
---
 drivers/ata/ahci_dwc.c | 52 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c
index 8c2510933a31..ab4180b7ed23 100644
--- a/drivers/ata/ahci_dwc.c
+++ b/drivers/ata/ahci_dwc.c
@@ -90,7 +90,16 @@
 #define AHCI_DWC_PORT_PHYCR		0x74
 #define AHCI_DWC_PORT_PHYSR		0x78
 
+struct ahci_dwc_plat_data {
+	unsigned int pflags;
+	unsigned int hflags;
+	int (*init)(struct ahci_host_priv *hpriv);
+	int (*reinit)(struct ahci_host_priv *hpriv);
+	void (*clear)(struct ahci_host_priv *hpriv);
+};
+
 struct ahci_dwc_host_priv {
+	const struct ahci_dwc_plat_data *pdata;
 	struct platform_device *pdev;
 
 	u32 timv;
@@ -107,11 +116,15 @@ static struct ahci_host_priv *ahci_dwc_get_resources(struct platform_device *pde
 		return ERR_PTR(-ENOMEM);
 
 	dpriv->pdev = pdev;
+	dpriv->pdata = device_get_match_data(&pdev->dev);
+	if (!dpriv->pdata)
+		return ERR_PTR(-EINVAL);
 
-	hpriv = ahci_platform_get_resources(pdev, AHCI_PLATFORM_GET_RESETS);
+	hpriv = ahci_platform_get_resources(pdev, dpriv->pdata->pflags);
 	if (IS_ERR(hpriv))
 		return hpriv;
 
+	hpriv->flags |= dpriv->pdata->hflags;
 	hpriv->plat_data = (void *)dpriv;
 
 	return hpriv;
@@ -242,22 +255,33 @@ static int ahci_dwc_init_dmacr(struct ahci_host_priv *hpriv)
 
 static int ahci_dwc_init_host(struct ahci_host_priv *hpriv)
 {
+	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
 	int rc;
 
 	rc = ahci_platform_enable_resources(hpriv);
 	if (rc)
 		return rc;
 
+	if (dpriv->pdata->init) {
+		rc = dpriv->pdata->init(hpriv);
+		if (rc)
+			goto err_disable_resources;
+	}
+
 	ahci_dwc_check_cap(hpriv);
 
 	ahci_dwc_init_timer(hpriv);
 
 	rc = ahci_dwc_init_dmacr(hpriv);
 	if (rc)
-		goto err_disable_resources;
+		goto err_clear_platform;
 
 	return 0;
 
+err_clear_platform:
+	if (dpriv->pdata->clear)
+		dpriv->pdata->clear(hpriv);
+
 err_disable_resources:
 	ahci_platform_disable_resources(hpriv);
 
@@ -275,6 +299,12 @@ static int ahci_dwc_reinit_host(struct ahci_host_priv *hpriv)
 	if (rc)
 		return rc;
 
+	if (dpriv->pdata->reinit) {
+		rc = dpriv->pdata->reinit(hpriv);
+		if (rc)
+			goto err_disable_resources;
+	}
+
 	writel(dpriv->timv, hpriv->mmio + AHCI_DWC_HOST_TIMER1MS);
 
 	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
@@ -283,10 +313,20 @@ static int ahci_dwc_reinit_host(struct ahci_host_priv *hpriv)
 	}
 
 	return 0;
+
+err_disable_resources:
+	ahci_platform_disable_resources(hpriv);
+
+	return rc;
 }
 
 static void ahci_dwc_clear_host(struct ahci_host_priv *hpriv)
 {
+	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
+
+	if (dpriv->pdata->clear)
+		dpriv->pdata->clear(hpriv);
+
 	ahci_platform_disable_resources(hpriv);
 }
 
@@ -371,9 +411,13 @@ static int ahci_dwc_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(ahci_dwc_pm_ops, ahci_dwc_suspend, ahci_dwc_resume);
 
+static struct ahci_dwc_plat_data ahci_dwc_plat = {
+	.pflags = AHCI_PLATFORM_GET_RESETS,
+};
+
 static const struct of_device_id ahci_dwc_of_match[] = {
-	{ .compatible = "snps,dwc-ahci", },
-	{ .compatible = "snps,spear-ahci", },
+	{ .compatible = "snps,dwc-ahci", &ahci_dwc_plat },
+	{ .compatible = "snps,spear-ahci", &ahci_dwc_plat },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ahci_dwc_of_match);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 22/23] ata: ahci-dwc: Add Baikal-T1 AHCI SATA interface support
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (20 preceding siblings ...)
  2022-06-10  8:17 ` [PATCH v4 21/23] ata: ahci-dwc: Add platform-specific quirks support Serge Semin
@ 2022-06-10  8:18 ` Serge Semin
  2022-06-10  8:18 ` [PATCH v4 23/23] MAINTAINERS: Add maintainers for DWC AHCI SATA driver Serge Semin
  22 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:18 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke, Serge Semin
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

It's almost fully compatible DWC AHCI SATA IP-core derivative except the
reference clocks source, which need to be very carefully selected. In
particular the DWC AHCI SATA PHY can be clocked either from the pads
ref_pad_clk_{m,p} or from the internal wires ref_alt_clk_{m,n}. In the
later case the clock signal is generated from the Baikal-T1 CCU SATA PLL.
The clocks source is selected by means of the ref_use_pad wire connected
to the CCU SATA reference clock CSR.

In normal situation it would be much more handy to use the internal
reference clock source, but alas we haven't managed to make the AHCI
controller working well with it so far. So it's preferable to have the
controller clocked from the external clock generator and fallback to the
internal clock source only as a last resort. Other than that the
controller is full compatible with the DWC AHCI SATA IP-core.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Hannes Reinecke <hare@suse.de>

---

Changelog v2:
- Rename 'syscon' property to 'baikal,bt1-syscon'.
- Change the local objects prefix from 'dwc_ahci_' to 'ahci_dwc_',
  from 'bt1_ahci_' to 'ahci_bt1_'. (@Damien)

Changelog v4:
- Convert ahci_bt1_plat to being statically defined. (@kbot)
- Drop Baikal-T1 syscon reference relying on the clock controller
  and the platform setup having the proper clock source selected. (@Rob)
---
 drivers/ata/Kconfig    |  1 +
 drivers/ata/ahci_dwc.c | 55 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 95e0e022b5bb..249717cdc74f 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -180,6 +180,7 @@ config AHCI_DWC
 	tristate "Synopsys DWC AHCI SATA support"
 	select SATA_HOST
 	default SATA_AHCI_PLATFORM
+	select MFD_SYSCON if (MIPS_BAIKAL_T1 || COMPILE_TEST)
 	help
 	  This option enables support for the Synopsys DWC AHCI SATA
 	  controller implementation.
diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c
index ab4180b7ed23..ed31c0f6782a 100644
--- a/drivers/ata/ahci_dwc.c
+++ b/drivers/ata/ahci_dwc.c
@@ -13,10 +13,12 @@
 #include <linux/kernel.h>
 #include <linux/libata.h>
 #include <linux/log2.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
+#include <linux/regmap.h>
 
 #include "ahci.h"
 
@@ -90,6 +92,20 @@
 #define AHCI_DWC_PORT_PHYCR		0x74
 #define AHCI_DWC_PORT_PHYSR		0x78
 
+/* Baikal-T1 AHCI SATA specific registers */
+#define AHCI_BT1_HOST_PHYCR		AHCI_DWC_HOST_GPCR
+#define AHCI_BT1_HOST_MPLM_MASK		GENMASK(29, 23)
+#define AHCI_BT1_HOST_LOSDT_MASK	GENMASK(22, 20)
+#define AHCI_BT1_HOST_CRR		BIT(19)
+#define AHCI_BT1_HOST_CRW		BIT(18)
+#define AHCI_BT1_HOST_CRCD		BIT(17)
+#define AHCI_BT1_HOST_CRCA		BIT(16)
+#define AHCI_BT1_HOST_CRDI_MASK		GENMASK(15, 0)
+
+#define AHCI_BT1_HOST_PHYSR		AHCI_DWC_HOST_GPSR
+#define AHCI_BT1_HOST_CRA		BIT(16)
+#define AHCI_BT1_HOST_CRDO_MASK		GENMASK(15, 0)
+
 struct ahci_dwc_plat_data {
 	unsigned int pflags;
 	unsigned int hflags;
@@ -106,6 +122,39 @@ struct ahci_dwc_host_priv {
 	u32 dmacr[AHCI_MAX_PORTS];
 };
 
+static int ahci_bt1_init(struct ahci_host_priv *hpriv)
+{
+	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
+	int ret;
+
+	/* APB, application and reference clocks are required */
+	if (!ahci_platform_find_clk(hpriv, "pclk") ||
+	    !ahci_platform_find_clk(hpriv, "aclk") ||
+	    !ahci_platform_find_clk(hpriv, "ref")) {
+		dev_err(&dpriv->pdev->dev, "No system clocks specified\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Fully reset the SATA AXI and ref clocks domain to ensure the state
+	 * machine is working from scratch especially if the reference clocks
+	 * source has been changed.
+	 */
+	ret = ahci_platform_assert_rsts(hpriv);
+	if (ret) {
+		dev_err(&dpriv->pdev->dev, "Couldn't assert the resets\n");
+		return ret;
+	}
+
+	ret = ahci_platform_deassert_rsts(hpriv);
+	if (ret) {
+		dev_err(&dpriv->pdev->dev, "Couldn't de-assert the resets\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static struct ahci_host_priv *ahci_dwc_get_resources(struct platform_device *pdev)
 {
 	struct ahci_dwc_host_priv *dpriv;
@@ -415,9 +464,15 @@ static struct ahci_dwc_plat_data ahci_dwc_plat = {
 	.pflags = AHCI_PLATFORM_GET_RESETS,
 };
 
+static struct ahci_dwc_plat_data ahci_bt1_plat = {
+	.pflags = AHCI_PLATFORM_GET_RESETS | AHCI_PLATFORM_RST_TRIGGER,
+	.init = ahci_bt1_init,
+};
+
 static const struct of_device_id ahci_dwc_of_match[] = {
 	{ .compatible = "snps,dwc-ahci", &ahci_dwc_plat },
 	{ .compatible = "snps,spear-ahci", &ahci_dwc_plat },
+	{ .compatible = "baikal,bt1-ahci", &ahci_bt1_plat },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ahci_dwc_of_match);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* [PATCH v4 23/23] MAINTAINERS: Add maintainers for DWC AHCI SATA driver
  2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
                   ` (21 preceding siblings ...)
  2022-06-10  8:18 ` [PATCH v4 22/23] ata: ahci-dwc: Add Baikal-T1 AHCI SATA interface support Serge Semin
@ 2022-06-10  8:18 ` Serge Semin
  22 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-10  8:18 UTC (permalink / raw)
  To: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
	Rob Herring, linux-ide, linux-kernel, devicetree

Add myself as a maintainer of the new DWC AHCI SATA driver and
its DT-bindings schema.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

---

Changelog v2:
- Use dlemoal/libata.git git tree for the LIBATA SATA AHCI SYNOPSYS
  DWC driver (@Damien).
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f468864fd268..fee2e1c8dde5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11137,6 +11137,15 @@ F:	drivers/ata/ahci_platform.c
 F:	drivers/ata/libahci_platform.c
 F:	include/linux/ahci_platform.h
 
+LIBATA SATA AHCI SYNOPSYS DWC CONTROLLER DRIVER
+M:	Serge Semin <fancer.lancer@gmail.com>
+L:	linux-ide@vger.kernel.org
+S:	Maintained
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata.git
+F:	Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
+F:	Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
+F:	drivers/ata/ahci_dwc.c
+
 LIBATA SATA PROMISE TX2/TX4 CONTROLLER DRIVER
 M:	Mikael Pettersson <mikpelinux@gmail.com>
 L:	linux-ide@vger.kernel.org
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-10  8:17 ` [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support Serge Semin
@ 2022-06-10 16:34   ` Randy Dunlap
  2022-06-10 21:58     ` Serge Semin
  2022-06-14  8:53   ` Damien Le Moal
  1 sibling, 1 reply; 80+ messages in thread
From: Randy Dunlap @ 2022-06-10 16:34 UTC (permalink / raw)
  To: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Serge Semin
  Cc: Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

Hi--

On 6/10/22 01:17, Serge Semin wrote:
> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> index bb45a9c00514..95e0e022b5bb 100644
> --- a/drivers/ata/Kconfig
> +++ b/drivers/ata/Kconfig
> @@ -176,6 +176,16 @@ config AHCI_DM816
>  
>  	  If unsure, say N.
>  
> +config AHCI_DWC
> +	tristate "Synopsys DWC AHCI SATA support"
> +	select SATA_HOST
> +	default SATA_AHCI_PLATFORM

I don't think this needs to default to SATA_AHCI_PLATFORM.
It might build a driver that isn't needed.
And it's incompatible with "If unsure, say N."

> +	help
> +	  This option enables support for the Synopsys DWC AHCI SATA
> +	  controller implementation.
> +
> +	  If unsure, say N.

-- 
~Randy

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-10 16:34   ` Randy Dunlap
@ 2022-06-10 21:58     ` Serge Semin
  2022-06-10 23:34       ` Randy Dunlap
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-10 21:58 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

On Fri, Jun 10, 2022 at 09:34:46AM -0700, Randy Dunlap wrote:
> Hi--

Hi Randy

> 
> On 6/10/22 01:17, Serge Semin wrote:
> > diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> > index bb45a9c00514..95e0e022b5bb 100644
> > --- a/drivers/ata/Kconfig
> > +++ b/drivers/ata/Kconfig
> > @@ -176,6 +176,16 @@ config AHCI_DM816
> >  
> >  	  If unsure, say N.
> >  
> > +config AHCI_DWC
> > +	tristate "Synopsys DWC AHCI SATA support"
> > +	select SATA_HOST
> > +	default SATA_AHCI_PLATFORM
> 

> I don't think this needs to default to SATA_AHCI_PLATFORM.
> It might build a driver that isn't needed.
> And it's incompatible with "If unsure, say N."

Basically you are right, but this particular setting is connected with
the modification I've done in the drivers/ata/ahci_platform.c driver
in the framework of this commit. I've moved the "snps,spear-ahci" and
"snps,dwc-ahci" compatible devices support to the new driver. Thus
should I omit the SATA_AHCI_PLATFORM dependency their default kernel
configs will lack the corresponding controllers support. If it's not a
problem and we can rely on the kernel build system ability to ask
whether the new config needs to be set/cleared, then I would be very
happy to drop the default setting. What do you think?

-Sergey

> 
> > +	help
> > +	  This option enables support for the Synopsys DWC AHCI SATA
> > +	  controller implementation.
> > +
> > +	  If unsure, say N.
> 
> -- 
> ~Randy

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-10 21:58     ` Serge Semin
@ 2022-06-10 23:34       ` Randy Dunlap
  2022-06-15 21:30         ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Randy Dunlap @ 2022-06-10 23:34 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

Hi Serge,

On 6/10/22 14:58, Serge Semin wrote:
> On Fri, Jun 10, 2022 at 09:34:46AM -0700, Randy Dunlap wrote:
>> Hi--
> 
> Hi Randy
> 
>>
>> On 6/10/22 01:17, Serge Semin wrote:
>>> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
>>> index bb45a9c00514..95e0e022b5bb 100644
>>> --- a/drivers/ata/Kconfig
>>> +++ b/drivers/ata/Kconfig
>>> @@ -176,6 +176,16 @@ config AHCI_DM816
>>>  
>>>  	  If unsure, say N.
>>>  
>>> +config AHCI_DWC
>>> +	tristate "Synopsys DWC AHCI SATA support"
>>> +	select SATA_HOST
>>> +	default SATA_AHCI_PLATFORM
>>
> 
>> I don't think this needs to default to SATA_AHCI_PLATFORM.
>> It might build a driver that isn't needed.
>> And it's incompatible with "If unsure, say N."
> 
> Basically you are right, but this particular setting is connected with
> the modification I've done in the drivers/ata/ahci_platform.c driver
> in the framework of this commit. I've moved the "snps,spear-ahci" and
> "snps,dwc-ahci" compatible devices support to the new driver. Thus
> should I omit the SATA_AHCI_PLATFORM dependency their default kernel
> configs will lack the corresponding controllers support. If it's not a
> problem and we can rely on the kernel build system ability to ask
> whether the new config needs to be set/cleared, then I would be very
> happy to drop the default setting. What do you think?

I'd prefer to try it like that.
If it becomes a problem, we can go back to this v4 patch.

>>> +	help
>>> +	  This option enables support for the Synopsys DWC AHCI SATA
>>> +	  controller implementation.
>>> +
>>> +	  If unsure, say N.
>>
>> -- 
>> ~Randy

Thanks.
-- 
~Randy

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 07/23] ata: libahci_platform: Convert to using devm bulk clocks API
  2022-06-10  8:17 ` [PATCH v4 07/23] ata: libahci_platform: Convert to using devm bulk clocks API Serge Semin
@ 2022-06-14  8:22   ` Damien Le Moal
  2022-06-15 20:45     ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-14  8:22 UTC (permalink / raw)
  To: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

On 6/10/22 17:17, Serge Semin wrote:
> In order to simplify the clock-related code there is a way to convert the
> current fixed clocks array into using the common bulk clocks kernel API
> with dynamic set of the clock handlers and device-managed clock-resource
> tracking. It's a bit tricky due to the complication coming from the
> requirement to support the platforms (da850, spear13xx) with the
> non-OF-based clock source, but still doable.
> 
> Before this modification there are two methods have been used to get the
> clocks connected to an AHCI device: clk_get() - to get the very first
> clock in the list and of_clk_get() - to get the rest of them. Basically
> the platforms with non-OF-based clocks definition could specify only a
> single reference clock source. The platforms with OF-hw clocks have been
> luckier and could setup up to AHCI_MAX_CLKS clocks. Such semantic can be
> retained with using devm_clk_bulk_get_all() to retrieve the clocks defined
> via the DT firmware and devm_clk_get_optional() otherwise. In both cases
> using the device-managed version of the methods will cause the automatic
> resources deallocation on the AHCI device removal event. The only
> complicated part in the suggested approach is the explicit allocation and
> initialization of the clk_bulk_data structure instance for the non-OF
> reference clocks. It's required in order to use the Bulk Clocks API for
> the both denoted cases of the clocks definition.
> 
> Note aside with the clock-related code reduction and natural
> simplification, there are several bonuses the suggested modification
> provides. First of all the limitation of having no greater than
> AHCI_MAX_CLKS clocks is now removed, since the devm_clk_bulk_get_all()
> method will allocate as many reference clocks data descriptors as there
> are clocks specified for the device. Secondly the clock names are
> auto-detected. So the LLDD (glue) drivers can make sure that the required
> clocks are specified just by checking the clock IDs in the clk_bulk_data
> array.  Thirdly using the handy Bulk Clocks kernel API improves the
> clocks-handling code readability. And the last but not least this
> modification implements a true optional clocks support to the
> ahci_platform_get_resources() method. Indeed the previous clocks getting
> procedure just stopped getting the clocks on any errors (aside from
> non-critical -EPROBE_DEFER) in a way so the callee wasn't even informed
> about abnormal loop termination. The new implementation lacks of such
> problem. The ahci_platform_get_resources() will return an error code if
> the corresponding clocks getting method ends execution abnormally.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> 
> ---
> 
> Changelog v2:
> - Convert to checking the error-case first in the devm_clk_bulk_get_all()
>   method invocation. (@Damien)
> - Fix some grammar mistakes in the comments.
> ---
>  drivers/ata/ahci.h             |  4 +-
>  drivers/ata/libahci_platform.c | 84 ++++++++++++++++------------------
>  2 files changed, 41 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> index ad11a4c52fbe..c3770a19781b 100644
> --- a/drivers/ata/ahci.h
> +++ b/drivers/ata/ahci.h
> @@ -38,7 +38,6 @@
>  
>  enum {
>  	AHCI_MAX_PORTS		= 32,
> -	AHCI_MAX_CLKS		= 5,
>  	AHCI_MAX_SG		= 168, /* hardware max is 64K */
>  	AHCI_DMA_BOUNDARY	= 0xffffffff,
>  	AHCI_MAX_CMDS		= 32,
> @@ -339,7 +338,8 @@ struct ahci_host_priv {
>  	u32			em_msg_type;	/* EM message type */
>  	u32			remapped_nvme;	/* NVMe remapped device count */
>  	bool			got_runtime_pm; /* Did we do pm_runtime_get? */
> -	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
> +	unsigned int		n_clks;
> +	struct clk_bulk_data	*clks;		/* Optional */
>  	struct reset_control	*rsts;		/* Optional */
>  	struct regulator	**target_pwrs;	/* Optional */
>  	struct regulator	*ahci_regulator;/* Optional */
> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> index 1e9e825d6cc5..814804582d1d 100644
> --- a/drivers/ata/libahci_platform.c
> +++ b/drivers/ata/libahci_platform.c
> @@ -8,6 +8,7 @@
>   *   Anton Vorontsov <avorontsov@ru.mvista.com>
>   */
>  
> +#include <linux/clk-provider.h>
>  #include <linux/clk.h>
>  #include <linux/kernel.h>
>  #include <linux/gfp.h>
> @@ -97,28 +98,14 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
>   * ahci_platform_enable_clks - Enable platform clocks
>   * @hpriv: host private area to store config values
>   *
> - * This function enables all the clks found in hpriv->clks, starting at
> - * index 0. If any clk fails to enable it disables all the clks already
> - * enabled in reverse order, and then returns an error.
> + * This function enables all the clks found for the AHCI device.
>   *
>   * RETURNS:
>   * 0 on success otherwise a negative error code
>   */
>  int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
>  {
> -	int c, rc;
> -
> -	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
> -		rc = clk_prepare_enable(hpriv->clks[c]);
> -		if (rc)
> -			goto disable_unprepare_clk;
> -	}
> -	return 0;
> -
> -disable_unprepare_clk:
> -	while (--c >= 0)
> -		clk_disable_unprepare(hpriv->clks[c]);
> -	return rc;
> +	return clk_bulk_prepare_enable(hpriv->n_clks, hpriv->clks);
>  }
>  EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
>  
> @@ -126,16 +113,13 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
>   * ahci_platform_disable_clks - Disable platform clocks
>   * @hpriv: host private area to store config values
>   *
> - * This function disables all the clks found in hpriv->clks, in reverse
> - * order of ahci_platform_enable_clks (starting at the end of the array).
> + * This function disables all the clocks enabled before
> + * (bulk-clocks-disable function is supposed to do that in reverse
> + * from the enabling procedure order).
>   */
>  void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
>  {
> -	int c;
> -
> -	for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
> -		if (hpriv->clks[c])
> -			clk_disable_unprepare(hpriv->clks[c]);
> +	clk_bulk_disable_unprepare(hpriv->n_clks, hpriv->clks);
>  }
>  EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
>  
> @@ -292,8 +276,6 @@ static void ahci_platform_put_resources(struct device *dev, void *res)
>  		pm_runtime_disable(dev);
>  	}
>  
> -	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
> -		clk_put(hpriv->clks[c]);
>  	/*
>  	 * The regulators are tied to child node device and not to the
>  	 * SATA device itself. So we can't use devm for automatically
> @@ -374,8 +356,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
>   * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
>   * 2) regulator for controlling the targets power (optional)
>   *    regulator for controlling the AHCI controller (optional)
> - * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
> - *    or for non devicetree enabled platforms a single clock
> + * 3) all clocks specified in the devicetree node, or a single
> + *    clock for non-OF platforms (optional)
>   * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional)
>   * 5) phys (optional)
>   *
> @@ -385,11 +367,10 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
>  struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
>  						   unsigned int flags)
>  {
> +	int child_nodes, rc = -ENOMEM, enabled_ports = 0;
>  	struct device *dev = &pdev->dev;
>  	struct ahci_host_priv *hpriv;
> -	struct clk *clk;
>  	struct device_node *child;
> -	int i, enabled_ports = 0, rc = -ENOMEM, child_nodes;
>  	u32 mask_port_map = 0;
>  
>  	if (!devres_open_group(dev, NULL, GFP_KERNEL))
> @@ -415,25 +396,38 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
>  		goto err_out;
>  	}
>  
> -	for (i = 0; i < AHCI_MAX_CLKS; i++) {
> +	/*
> +	 * Bulk clocks getting procedure can fail to find any clock due to
> +	 * running on a non-OF platform or due to the clocks being defined in
> +	 * bypass of the DT firmware (like da850, spear13xx). In that case we
> +	 * fallback to getting a single clock source right from the dev clocks
> +	 * list.
> +	 */
> +	rc = devm_clk_bulk_get_all(dev, &hpriv->clks);
> +	if (rc < 0)
> +		goto err_out;
> +
> +	if (rc > 0) {
> +		/* Got clocks in bulk */
> +		hpriv->n_clks = rc;
> +	} else {
>  		/*
> -		 * For now we must use clk_get(dev, NULL) for the first clock,
> -		 * because some platforms (da850, spear13xx) are not yet
> -		 * converted to use devicetree for clocks.  For new platforms
> -		 * this is equivalent to of_clk_get(dev->of_node, 0).
> +		 * No clock bulk found: fallback to manually getting
> +		 * the optional clock.
>  		 */
> -		if (i == 0)
> -			clk = clk_get(dev, NULL);
> -		else
> -			clk = of_clk_get(dev->of_node, i);
> -
> -		if (IS_ERR(clk)) {
> -			rc = PTR_ERR(clk);
> -			if (rc == -EPROBE_DEFER)
> -				goto err_out;
> -			break;
> +		hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL);
> +		if (!hpriv->clks) {
> +			rc = -ENOMEM;
> +			goto err_out;
> +		}
> +		hpriv->clks->clk = devm_clk_get_optional(dev, NULL);
> +		if (IS_ERR(hpriv->clks->clk)) {
> +			rc = PTR_ERR(hpriv->clks->clk);
> +			goto err_out;
> +		} else if (hpriv->clks->clk) {

Nit: the else is not needed here.

> +			hpriv->clks->id = __clk_get_name(hpriv->clks->clk);
> +			hpriv->n_clks = 1;
>  		}
> -		hpriv->clks[i] = clk;
>  	}
>  
>  	hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 08/23] ata: libahci_platform: Sanity check the DT child nodes number
  2022-06-10  8:17 ` [PATCH v4 08/23] ata: libahci_platform: Sanity check the DT child nodes number Serge Semin
@ 2022-06-14  8:23   ` Damien Le Moal
  2022-06-15 20:53     ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-14  8:23 UTC (permalink / raw)
  To: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

On 6/10/22 17:17, Serge Semin wrote:
> Having greater than AHCI_MAX_PORTS (32) ports detected isn't that critical
> from the further AHCI-platform initialization point of view since
> exceeding the ports upper limit will cause allocating more resources than
> will be used afterwards. But detecting too many child DT-nodes doesn't
> seem right since it's very unlikely to have it on an ordinary platform. In
> accordance with the AHCI specification there can't be more than 32 ports
> implemented at least due to having the CAP.NP field of 5 bits wide and the
> PI register of dword size. Thus if such situation is found the DTB must
> have been corrupted and the data read from it shouldn't be reliable. Let's
> consider that as an erroneous situation and halt further resources
> allocation.
> 
> Note it's logically more correct to have the nports set only after the
> initialization value is checked for being sane. So while at it let's make
> sure nports is assigned with a correct value.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> 
> ---
> 
> Changelog v2:
> - Drop the else word from the child_nodes value checking if-else-if
>   statement (@Damien) and convert the after-else part into the ternary
>   operator-based statement.
> 
> Changelog v4:
> - Fix some logical mistakes in the patch log. (@Sergei Shtylyov)
> ---
>  drivers/ata/libahci_platform.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> index 814804582d1d..8aed7b29c7ab 100644
> --- a/drivers/ata/libahci_platform.c
> +++ b/drivers/ata/libahci_platform.c
> @@ -451,15 +451,22 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
>  		}
>  	}
>  
> -	hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
> +	/*
> +	 * Too many sub-nodes most likely means having something wrong with
> +	 * the firmware.
> +	 */
> +	child_nodes = of_get_child_count(dev->of_node);
> +	if (child_nodes > AHCI_MAX_PORTS) {
> +		rc = -EINVAL;
> +		goto err_out;
> +	}
>  
>  	/*
>  	 * If no sub-node was found, we still need to set nports to
>  	 * one in order to be able to use the
>  	 * ahci_platform_[en|dis]able_[phys|regulators] functions.
>  	 */
> -	if (!child_nodes)
> -		hpriv->nports = 1;
> +	hpriv->nports = child_nodes ?: 1;

This change is not necessary and makes the code far less easy to read.

>  
>  	hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
>  	if (!hpriv->phys) {


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities
  2022-06-10  8:17 ` [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities Serge Semin
@ 2022-06-14  8:32   ` Damien Le Moal
  2022-06-15 20:58     ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-14  8:32 UTC (permalink / raw)
  To: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

On 6/10/22 17:17, Serge Semin wrote:
> Currently not all of the Port-specific capabilities listed in the

s/listed/are listed

> PORT_CMD-enumeration. Let's extend that set with the Cold Presence
> Detection and Mechanical Presence Switch attached to the Port flags [1] so
> to closeup the set of the platform-specific port-capabilities flags.  Note
> these flags are supposed to be set by the platform firmware if there is
> one. Alternatively as we are about to do they can be set by means of the
> OF properties.
> 
> While at it replace PORT_IRQ_DEV_ILCK with PORT_IRQ_DMPS and fix the
> comment there. In accordance with [2] that IRQ flag is supposed to
> indicate the state of the signal coming from the Mechanical Presence
> Switch.
> 
> [1] Serial ATA AHCI 1.3.1 Specification, p.27
> [2] Serial ATA AHCI 1.3.1 Specification, p.24, p.88
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> 
> ---
> 
> Changelog v4:
> - Fix the DMPS macros name in the patch log. (@Sergei Shtylyov)
> ---
>  drivers/ata/ahci.h | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> index 7d834deefeb9..f501531bd1b3 100644
> --- a/drivers/ata/ahci.h
> +++ b/drivers/ata/ahci.h
> @@ -138,7 +138,7 @@ enum {
>  	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
>  
>  	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
> -	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
> +	PORT_IRQ_DMPS		= (1 << 7), /* mechanical presence status */
>  	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
>  	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
>  	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
> @@ -166,6 +166,8 @@ enum {
>  	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
>  	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
>  	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
> +	PORT_CMD_CPD		= (1 << 20), /* Cold Presence Detection */
> +	PORT_CMD_MPSP		= (1 << 19), /* Mechanical Presence Switch */
>  	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
>  	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
>  	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
> @@ -181,6 +183,9 @@ enum {
>  	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
>  	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
>  
> +	PORT_CMD_CAP		= PORT_CMD_HPCP | PORT_CMD_MPSP |
> +				  PORT_CMD_CPD | PORT_CMD_ESP | PORT_CMD_FBSCP,

What is this one for ? A comment above it would be nice.

> +
>  	/* PORT_FBS bits */
>  	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
>  	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 15/23] ata: ahci: Convert __ahci_port_base to accepting hpriv as arguments
  2022-06-10  8:17 ` [PATCH v4 15/23] ata: ahci: Convert __ahci_port_base to accepting hpriv as arguments Serge Semin
@ 2022-06-14  8:38   ` Damien Le Moal
  2022-06-15 21:25     ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-14  8:38 UTC (permalink / raw)
  To: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

On 6/10/22 17:17, Serge Semin wrote:
> It may get required to retrieve the port-base address even before the

The port base address may be required even before the...

> ata_host instance is initialized and activated, for instance in the
> ahci_save_initial_config() method which we about to update (consider this

s/we/we are

> modification as a preparation for that one). Seeing the __ahci_port_base()
> function isn't used much it's the best candidate to provide the required
> functionality. So let's convert it to accepting the ahci_host_priv
> structure pointer.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> ---
>  drivers/ata/ahci.c | 2 +-
>  drivers/ata/ahci.h | 7 ++++---
>  2 files changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
> index 9bc8fa77e92f..d14d74649e0e 100644
> --- a/drivers/ata/ahci.c
> +++ b/drivers/ata/ahci.c
> @@ -689,7 +689,7 @@ static void ahci_pci_init_controller(struct ata_host *host)
>  			mv = 2;
>  		else
>  			mv = 4;
> -		port_mmio = __ahci_port_base(host, mv);
> +		port_mmio = __ahci_port_base(hpriv, mv);
>  
>  		writel(0, port_mmio + PORT_IRQ_MASK);
>  
> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> index 0e66446a5883..8b9826533ae5 100644
> --- a/drivers/ata/ahci.h
> +++ b/drivers/ata/ahci.h
> @@ -431,10 +431,9 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht);
>  void ahci_error_handler(struct ata_port *ap);
>  u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked);
>  
> -static inline void __iomem *__ahci_port_base(struct ata_host *host,
> +static inline void __iomem *__ahci_port_base(struct ahci_host_priv *hpriv,
>  					     unsigned int port_no)
>  {
> -	struct ahci_host_priv *hpriv = host->private_data;
>  	void __iomem *mmio = hpriv->mmio;
>  
>  	return mmio + 0x100 + (port_no * 0x80);
> @@ -442,7 +441,9 @@ static inline void __iomem *__ahci_port_base(struct ata_host *host,
>  
>  static inline void __iomem *ahci_port_base(struct ata_port *ap)
>  {
> -	return __ahci_port_base(ap->host, ap->port_no);
> +	struct ahci_host_priv *hpriv = ap->host->private_data;
> +
> +	return __ahci_port_base(hpriv, ap->port_no);
>  }
>  
>  static inline int ahci_nr_ports(u32 cap)


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 16/23] ata: ahci: Introduce firmware-specific caps initialization
  2022-06-10  8:17 ` [PATCH v4 16/23] ata: ahci: Introduce firmware-specific caps initialization Serge Semin
@ 2022-06-14  8:42   ` Damien Le Moal
  2022-06-15 21:11     ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-14  8:42 UTC (permalink / raw)
  To: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

On 6/10/22 17:17, Serge Semin wrote:
> There are systems with no BIOS or comprehensive embedded firmware which
> could be able to properly initialize the SATA AHCI controller
> platform-specific capabilities. In that case a good alternative to having
> a clever bootloader is to create a device tree node with the properties
> well describing all the AHCI-related platform specifics. All the settings
> which are normally detected and marked as available in the HBA and its
> ports capabilities fields [1] could be defined in the platform DTB by
> means of a set of the dedicated properties. Such approach perfectly fits
> to the DTB-philosophy - to provide hardware/platform description.
> 
> So here we suggest to extend the SATA AHCI device tree bindings with two
> additional DT-properties:
> 1) "hba-cap" - HBA platform generic capabilities like:
>    - SSS - Staggered Spin-up support.
>    - SMPS - Mechanical Presence Switch support.
> 2) "hba-port-cap" - HBA platform port capabilities like:
>    - HPCP - Hot Plug Capable Port.
>    - MPSP - Mechanical Presence Switch Attached to Port.
>    - CPD - Cold Presence Detection.
>    - ESP - External SATA Port.
>    - FBSCP - FIS-based Switching Capable Port.
> All of these capabilities require to have a corresponding hardware
> configuration. Thus it's ok to have them defined in DTB.
> 
> Even though the driver currently takes into account the state of the ESP
> and FBSCP flags state only, there is nothing wrong with having all of them
> supported by the generic AHCI library in order to have a complete OF-based
> platform-capabilities initialization procedure. These properties will be
> parsed in the ahci_platform_get_resources() method and their values will
> be stored in the saved_* fields of the ahci_host_priv structure, which in
> its turn then will be used to restore the H.CAP, H.PI and P#.CMD
> capability fields on device init and after HBA reset.
> 
> Please note this modification concerns the HW-init HBA and its ports flags
> only, which are by specification [1] are supposed to be initialized by the
> BIOS/platform firmware/expansion ROM and which are normally declared in
> the one-time-writable-after-reset register fields. Even though these flags
> aren't supposed to be cleared after HBA reset some AHCI instances may
> violate that rule so we still need to perform the fields resetting after
> each reset. Luckily the corresponding functionality has already been
> partly implemented in the framework of the ahci_save_initial_config() and
> ahci_restore_initial_config() methods.
> 
> [1] Serial ATA AHCI 1.3.1 Specification, p. 103
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> 
> ---
> 
> Changelog v4:
> - Convert the boolean properties to the bitfield DT-properties. (@Rob)
> ---
>  drivers/ata/ahci.h             |  1 +
>  drivers/ata/libahci.c          | 51 ++++++++++++++++++++++++++++------
>  drivers/ata/libahci_platform.c | 41 +++++++++++++++++++++++++--
>  3 files changed, 82 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> index 8b9826533ae5..0de221055961 100644
> --- a/drivers/ata/ahci.h
> +++ b/drivers/ata/ahci.h
> @@ -337,6 +337,7 @@ struct ahci_host_priv {
>  	u32			saved_cap;	/* saved initial cap */
>  	u32			saved_cap2;	/* saved initial cap2 */
>  	u32			saved_port_map;	/* saved initial port_map */
> +	u32			saved_port_cap[AHCI_MAX_PORTS]; /* saved port_cap */
>  	u32 			em_loc; /* enclosure management location */
>  	u32			em_buf_sz;	/* EM buffer size in byte */
>  	u32			em_msg_type;	/* EM message type */
> diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
> index 1ffaa5f5f21a..954386a2b500 100644
> --- a/drivers/ata/libahci.c
> +++ b/drivers/ata/libahci.c
> @@ -16,6 +16,7 @@
>   * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
>   */
>  
> +#include <linux/bitops.h>
>  #include <linux/kernel.h>
>  #include <linux/gfp.h>
>  #include <linux/module.h>
> @@ -443,16 +444,28 @@ static ssize_t ahci_show_em_supported(struct device *dev,
>  void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>  {
>  	void __iomem *mmio = hpriv->mmio;
> -	u32 cap, cap2, vers, port_map;
> +	void __iomem *port_mmio;
> +	unsigned long port_map;
> +	u32 cap, cap2, vers;
>  	int i;
>  
>  	/* make sure AHCI mode is enabled before accessing CAP */
>  	ahci_enable_ahci(mmio);
>  
> -	/* Values prefixed with saved_ are written back to host after
> -	 * reset.  Values without are used for driver operation.
> +	/*
> +	 * Values prefixed with saved_ are written back to the HBA and ports
> +	 * registers after reset. Values without are used for driver operation.
> +	 */
> +
> +	/*
> +	 * Override HW-init HBA capability fields with the platform-specific
> +	 * values. The rest of the HBA capabilities are defined as Read-only
> +	 * and can't be modified in CSR anyway.
>  	 */
> -	hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
> +	cap = readl(mmio + HOST_CAP);
> +	if (hpriv->saved_cap)
> +		cap = (cap & ~(HOST_CAP_SSS | HOST_CAP_MPS)) | hpriv->saved_cap;
> +	hpriv->saved_cap = cap;
>  
>  	/* CAP2 register is only defined for AHCI 1.2 and later */
>  	vers = readl(mmio + HOST_VERSION);
> @@ -519,7 +532,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>  	/* Override the HBA ports mapping if the platform needs it */
>  	port_map = readl(mmio + HOST_PORTS_IMPL);
>  	if (hpriv->saved_port_map && port_map != hpriv->saved_port_map) {
> -		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
> +		dev_info(dev, "forcing port_map 0x%lx -> 0x%x\n",

This change is not necessary.

>  			 port_map, hpriv->saved_port_map);
>  		port_map = hpriv->saved_port_map;
>  	} else {
> @@ -527,7 +540,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>  	}
>  
>  	if (hpriv->mask_port_map) {
> -		dev_warn(dev, "masking port_map 0x%x -> 0x%x\n",
> +		dev_warn(dev, "masking port_map 0x%lx -> 0x%lx\n",

Same.

>  			port_map,
>  			port_map & hpriv->mask_port_map);
>  		port_map &= hpriv->mask_port_map;
> @@ -546,7 +559,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>  		 */
>  		if (map_ports > ahci_nr_ports(cap)) {
>  			dev_warn(dev,
> -				 "implemented port map (0x%x) contains more ports than nr_ports (%u), using nr_ports\n",
> +				 "implemented port map (0x%lx) contains more ports than nr_ports (%u), using nr_ports\n",

Same.

>  				 port_map, ahci_nr_ports(cap));
>  			port_map = 0;
>  		}
> @@ -555,12 +568,26 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>  	/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
>  	if (!port_map && vers < 0x10300) {
>  		port_map = (1 << ahci_nr_ports(cap)) - 1;
> -		dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
> +		dev_warn(dev, "forcing PORTS_IMPL to 0x%lx\n", port_map);

And again not needed.

>  
>  		/* write the fixed up value to the PI register */
>  		hpriv->saved_port_map = port_map;
>  	}
>  
> +	/*
> +	 * Preserve the ports capabilities defined by the platform. Note there
> +	 * is no need in storing the rest of the P#.CMD fields since they are
> +	 * volatile.
> +	 */
> +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> +		if (hpriv->saved_port_cap[i])
> +			continue;
> +
> +		port_mmio = __ahci_port_base(hpriv, i);
> +		hpriv->saved_port_cap[i] =
> +			readl(port_mmio + PORT_CMD) & PORT_CMD_CAP;
> +	}
> +
>  	/* record values to use during operation */
>  	hpriv->cap = cap;
>  	hpriv->cap2 = cap2;
> @@ -590,13 +617,21 @@ EXPORT_SYMBOL_GPL(ahci_save_initial_config);
>  static void ahci_restore_initial_config(struct ata_host *host)
>  {
>  	struct ahci_host_priv *hpriv = host->private_data;
> +	unsigned long port_map = hpriv->port_map;
>  	void __iomem *mmio = hpriv->mmio;
> +	void __iomem *port_mmio;
> +	int i;
>  
>  	writel(hpriv->saved_cap, mmio + HOST_CAP);
>  	if (hpriv->saved_cap2)
>  		writel(hpriv->saved_cap2, mmio + HOST_CAP2);
>  	writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
>  	(void) readl(mmio + HOST_PORTS_IMPL);	/* flush */
> +
> +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> +		port_mmio = __ahci_port_base(hpriv, i);
> +		writel(hpriv->saved_port_cap[i], port_mmio + PORT_CMD);
> +	}
>  }
>  
>  static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> index efe640603f3f..8b542a8bc487 100644
> --- a/drivers/ata/libahci_platform.c
> +++ b/drivers/ata/libahci_platform.c
> @@ -23,6 +23,7 @@
>  #include <linux/pm_runtime.h>
>  #include <linux/of_platform.h>
>  #include <linux/reset.h>
> +

white line change.

>  #include "ahci.h"
>  
>  static void ahci_host_stop(struct ata_host *host);
> @@ -383,6 +384,34 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
>  	return rc;
>  }
>  
> +static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv,
> +				      struct device *dev)
> +{
> +	struct device_node *child;
> +	u32 port;
> +
> +	if (!of_property_read_u32(dev->of_node, "hba-cap", &hpriv->saved_cap))
> +		hpriv->saved_cap &= (HOST_CAP_SSS | HOST_CAP_MPS);
> +
> +	of_property_read_u32(dev->of_node,
> +			     "ports-implemented", &hpriv->saved_port_map);
> +
> +	for_each_child_of_node(dev->of_node, child) {
> +		if (!of_device_is_available(child))
> +			continue;
> +
> +		if (of_property_read_u32(child, "reg", &port)) {
> +			of_node_put(child);
> +			return -EINVAL;
> +		}
> +
> +		if (!of_property_read_u32(child, "hba-port-cap", &hpriv->saved_port_cap[port]))
> +			hpriv->saved_port_cap[port] &= PORT_CMD_CAP;
> +	}
> +
> +	return 0;
> +}
> +
>  /**
>   * ahci_platform_get_resources - Get platform resources
>   * @pdev: platform device to get resources for
> @@ -523,9 +552,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
>  		goto err_out;
>  	}
>  
> -	of_property_read_u32(dev->of_node,
> -			     "ports-implemented", &hpriv->saved_port_map);
> -
>  	if (child_nodes) {
>  		for_each_child_of_node(dev->of_node, child) {
>  			u32 port;
> @@ -590,6 +616,15 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
>  		if (rc == -EPROBE_DEFER)
>  			goto err_out;
>  	}
> +
> +	/*
> +	 * Retrieve firmware-specific flags which then will be used to set
> +	 * the HW-init fields of HBA and its ports
> +	 */
> +	rc = ahci_platform_get_firmware(hpriv, dev);
> +	if (rc)
> +		goto err_out;
> +
>  	pm_runtime_enable(dev);
>  	pm_runtime_get_sync(dev);
>  	hpriv->got_runtime_pm = true;


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 18/23] ata: libahci_platform: Add function returning a clock-handle by id
  2022-06-10  8:17 ` [PATCH v4 18/23] ata: libahci_platform: Add function returning a clock-handle by id Serge Semin
@ 2022-06-14  8:45   ` Damien Le Moal
  2022-06-15 21:24     ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-14  8:45 UTC (permalink / raw)
  To: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

On 6/10/22 17:17, Serge Semin wrote:
> Since all the clocks are retrieved by the method
> ahci_platform_get_resources() there is no need for the LLD (glue) drivers
> to be looking for some particular of them in the kernel clocks table
> again. Instead we suggest to add a simple method returning a
> device-specific clock with passed connection ID if it is managed to be
> found. Otherwise the function will return NULL. Thus the glue-drivers
> won't need to either manually touching the hpriv->clks array or calling
> clk_get()-friends. The AHCI platform drivers will be able to use the new
> function right after the ahci_platform_get_resources() method invocation
> and up to the device removal.
> 
> Note the method is left unused here, but will be utilized in the framework
> of the DWC AHCI SATA driver being added in the next commit.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> 
> ---
> 
> Changelog v2:
> - Fix some grammar mistakes in the method description.
> 
> Changelog v4:
> - Add a note regarding the new method usage.
> ---
>  drivers/ata/libahci_platform.c | 27 +++++++++++++++++++++++++++
>  include/linux/ahci_platform.h  |  3 +++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> index 8b542a8bc487..418961f954af 100644
> --- a/drivers/ata/libahci_platform.c
> +++ b/drivers/ata/libahci_platform.c
> @@ -95,6 +95,33 @@ void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
>  }
>  EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
>  
> +/**
> + * ahci_platform_find_clk - Find platform clock
> + * @hpriv: host private area to store config values
> + * @con_id: clock connection ID
> + *
> + * This function returns a pointer to the clock descriptor of the clock with
> + * the passed ID.
> + *
> + * RETURNS:
> + * Pointer to the clock descriptor on success otherwise NULL
> + */
> +struct clk *ahci_platform_find_clk(struct ahci_host_priv *hpriv, const char *con_id)
> +{
> +	struct clk *clk = NULL;
> +	int i;
> +
> +	for (i = 0; i < hpriv->n_clks; i++) {
> +		if (!strcmp(hpriv->clks[i].id, con_id)) {
> +			clk = hpriv->clks[i].clk;

			return hpriv->clks[i].clk;

> +			break;
> +		}
> +	}
> +
> +	return clk;

And then "return NULL;" here and you do not need the clk variable.

> +}
> +EXPORT_SYMBOL_GPL(ahci_platform_find_clk);
> +
>  /**
>   * ahci_platform_enable_clks - Enable platform clocks
>   * @hpriv: host private area to store config values
> diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
> index 6d7dd472d370..3418980b0341 100644
> --- a/include/linux/ahci_platform.h
> +++ b/include/linux/ahci_platform.h
> @@ -13,6 +13,7 @@
>  
>  #include <linux/compiler.h>
>  
> +struct clk;
>  struct device;
>  struct ata_port_info;
>  struct ahci_host_priv;
> @@ -21,6 +22,8 @@ struct scsi_host_template;
>  
>  int ahci_platform_enable_phys(struct ahci_host_priv *hpriv);
>  void ahci_platform_disable_phys(struct ahci_host_priv *hpriv);
> +struct clk *
> +ahci_platform_find_clk(struct ahci_host_priv *hpriv, const char *con_id);

Please make this:

struct clk *ahci_platform_find_clk(struct ahci_host_priv *hpriv,

                                   const char *con_id);

>  int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
>  void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
>  int ahci_platform_deassert_rsts(struct ahci_host_priv *hpriv);


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-10  8:17 ` [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support Serge Semin
  2022-06-10 16:34   ` Randy Dunlap
@ 2022-06-14  8:53   ` Damien Le Moal
  2022-06-15 21:48     ` Serge Semin
  1 sibling, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-14  8:53 UTC (permalink / raw)
  To: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke, Serge Semin
  Cc: Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On 6/10/22 17:17, Serge Semin wrote:
> Synopsys AHCI SATA controller can work pretty under with the generic
> AHCI-platform driver control. But there are vendor-specific peculiarities
> which can tune the device performance up and which may need to be fixed up
> for proper device functioning. In addition some DWC AHCI-based controllers
> may require small platform-specific fixups, so adding them in the generic
> AHCI driver would have ruined the code simplicity. Shortly speaking in
> order to keep the generic AHCI-platform code clean and have DWC AHCI
> SATA-specific features supported we suggest to add a dedicated DWC AHCI
> SATA device driver. Aside with the standard AHCI-platform resources
> getting, enabling/disabling and the controller registration the new driver
> performs the next actions.
> 
> First of all there is a way to verify whether the HBA/ports capabilities
> activated in OF are correct. Almost all features availability is reflected
> in the vendor-specific parameters registers. So the DWC AHCI driver does
> the capabilities sanity check based on the corresponding fields state.
> 
> Secondly if either the Command Completion Coalescing or the Device Sleep
> feature is enabled the DWC AHCI-specific internal 1ms timer must be fixed
> in accordance with the application clock signal frequency. In particular
> the timer value must be set to be Fapp * 1000. Normally the SoC designers
> pre-configure the TIMER1MS register to contain a correct value by default.
> But the platforms can support the application clock rate change. If that
> happens the 1ms timer value must be accordingly updated otherwise the
> dependent features won't work as expected. In the DWC AHCI driver we
> suggest to rely on the "aclk" reference clock rate to set the timer
> interval up. That clock source is supposed to be the AHCI SATA application
> clock in accordance with the DT bindings.
> 
> Finally DWC AHCI SATA controller AXI/AHB bus DMA-engine can be tuned up to
> transfer up to 1024 * FIFO words at a time by setting the Tx/Rx
> transaction size in the DMA control register. The maximum value depends on
> the DMA data bus and AXI/AHB bus maximum burst length. In most of the
> cases it's better to set the maximum possible value to reach the best AHCI
> SATA controller performance. But sometimes in order to improve the system
> interconnect responsiveness, transferring in smaller data chunks may be
> more preferable. For such cases and for the case when the default value
> doesn't provide the best DMA bus performance we suggest to use the new
> HBA-port specific DT-properties "snps,{tx,rx}-ts-max" to tune the DMA
> transactions size up.
> 
> After all the settings denoted above are handled the DWC AHCI SATA driver
> proceeds further with the standard AHCI-platform host initializations.
> 
> Note since DWC AHCI controller is now have a dedicated driver we can
> discard the corresponding compatible string from the ahci-platform.c
> module. The same concerns "snps,spear-ahci" compatible string, which is
> also based on the DWC AHCI IP-core.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> 
> ---
> 
> Note there are three more AHCI SATA drivers which have been created for
> the devices based on the DWC AHCI SATA IP-core. It's AHCI SunXi, St and
> iMX drivers. Mostly they don't support the features implemented in this
> driver. So hopefully sometime in future they can be converted to be based
> on the generic DWC AHCI SATA driver and just perform some
> subvendor-specific setups in their own LLDD (glue) driver code. But for
> now let's leave the generic DWC AHCI SATA code as is. Hopefully the new
> DWC AHCI-based device drivers will try at least to re-use a part of the
> DWC AHCI driver methods if not being able to be integrated in the generic
> DWC driver code.
> 
> Changelog v2:
> - Change the local objects prefix from 'dwc_ahci_' to 'ahci_dwc_'.
>   (@Damien)
> 
> Changelog v4:
> - Replace GPLv2 with just GPL license which are the same in the framework
>   of the MODULE_LICENSE() macro.
> ---
>  drivers/ata/Kconfig         |  10 +
>  drivers/ata/Makefile        |   1 +
>  drivers/ata/ahci_dwc.c      | 395 ++++++++++++++++++++++++++++++++++++
>  drivers/ata/ahci_platform.c |   2 -
>  4 files changed, 406 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/ata/ahci_dwc.c
> 
> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> index bb45a9c00514..95e0e022b5bb 100644
> --- a/drivers/ata/Kconfig
> +++ b/drivers/ata/Kconfig
> @@ -176,6 +176,16 @@ config AHCI_DM816
>  
>  	  If unsure, say N.
>  
> +config AHCI_DWC
> +	tristate "Synopsys DWC AHCI SATA support"
> +	select SATA_HOST
> +	default SATA_AHCI_PLATFORM
> +	help
> +	  This option enables support for the Synopsys DWC AHCI SATA
> +	  controller implementation.
> +
> +	  If unsure, say N.
> +
>  config AHCI_ST
>  	tristate "ST AHCI SATA support"
>  	depends on ARCH_STI
> diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
> index b8aebfb14e82..34623365d9a6 100644
> --- a/drivers/ata/Makefile
> +++ b/drivers/ata/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_AHCI_BRCM)		+= ahci_brcm.o libahci.o libahci_platform.o
>  obj-$(CONFIG_AHCI_CEVA)		+= ahci_ceva.o libahci.o libahci_platform.o
>  obj-$(CONFIG_AHCI_DA850)	+= ahci_da850.o libahci.o libahci_platform.o
>  obj-$(CONFIG_AHCI_DM816)	+= ahci_dm816.o libahci.o libahci_platform.o
> +obj-$(CONFIG_AHCI_DWC)		+= ahci_dwc.o libahci.o libahci_platform.o
>  obj-$(CONFIG_AHCI_IMX)		+= ahci_imx.o libahci.o libahci_platform.o
>  obj-$(CONFIG_AHCI_MTK)		+= ahci_mtk.o libahci.o libahci_platform.o
>  obj-$(CONFIG_AHCI_MVEBU)	+= ahci_mvebu.o libahci.o libahci_platform.o
> diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c
> new file mode 100644
> index 000000000000..8c2510933a31
> --- /dev/null
> +++ b/drivers/ata/ahci_dwc.c
> @@ -0,0 +1,395 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * DWC AHCI SATA Platform driver
> + *
> + * Copyright (C) 2021 BAIKAL ELECTRONICS, JSC
> + */
> +
> +#include <linux/ahci_platform.h>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/libata.h>
> +#include <linux/log2.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm.h>
> +
> +#include "ahci.h"
> +
> +#define DRV_NAME "ahci-dwc"
> +
> +#define AHCI_DWC_FBS_PMPN_MAX		15
> +
> +/* DWC AHCI SATA controller specific registers */
> +#define AHCI_DWC_HOST_OOBR		0xbc
> +#define AHCI_DWC_HOST_OOB_WE		BIT(31)
> +#define AHCI_DWC_HOST_CWMIN_MASK	GENMASK(30, 24)
> +#define AHCI_DWC_HOST_CWMAX_MASK	GENMASK(23, 16)
> +#define AHCI_DWC_HOST_CIMIN_MASK	GENMASK(15, 8)
> +#define AHCI_DWC_HOST_CIMAX_MASK	GENMASK(7, 0)
> +
> +#define AHCI_DWC_HOST_GPCR		0xd0
> +#define AHCI_DWC_HOST_GPSR		0xd4
> +
> +#define AHCI_DWC_HOST_TIMER1MS		0xe0
> +#define AHCI_DWC_HOST_TIMV_MASK		GENMASK(19, 0)
> +
> +#define AHCI_DWC_HOST_GPARAM1R		0xe8
> +#define AHCI_DWC_HOST_ALIGN_M		BIT(31)
> +#define AHCI_DWC_HOST_RX_BUFFER		BIT(30)
> +#define AHCI_DWC_HOST_PHY_DATA_MASK	GENMASK(29, 28)
> +#define AHCI_DWC_HOST_PHY_RST		BIT(27)
> +#define AHCI_DWC_HOST_PHY_CTRL_MASK	GENMASK(26, 21)
> +#define AHCI_DWC_HOST_PHY_STAT_MASK	GENMASK(20, 15)
> +#define AHCI_DWC_HOST_LATCH_M		BIT(14)
> +#define AHCI_DWC_HOST_PHY_TYPE_MASK	GENMASK(13, 11)
> +#define AHCI_DWC_HOST_RET_ERR		BIT(10)
> +#define AHCI_DWC_HOST_AHB_ENDIAN_MASK	GENMASK(9, 8)
> +#define AHCI_DWC_HOST_S_HADDR		BIT(7)
> +#define AHCI_DWC_HOST_M_HADDR		BIT(6)
> +#define AHCI_DWC_HOST_S_HDATA_MASK	GENMASK(5, 3)
> +#define AHCI_DWC_HOST_M_HDATA_MASK	GENMASK(2, 0)
> +
> +#define AHCI_DWC_HOST_GPARAM2R		0xec
> +#define AHCI_DWC_HOST_FBS_MEM_S		BIT(19)
> +#define AHCI_DWC_HOST_FBS_PMPN_MASK	GENMASK(17, 16)
> +#define AHCI_DWC_HOST_FBS_SUP		BIT(15)
> +#define AHCI_DWC_HOST_DEV_CP		BIT(14)
> +#define AHCI_DWC_HOST_DEV_MP		BIT(13)
> +#define AHCI_DWC_HOST_ENCODE_M		BIT(12)
> +#define AHCI_DWC_HOST_RXOOB_CLK_M	BIT(11)
> +#define AHCI_DWC_HOST_RXOOB_M		BIT(10)
> +#define AHCI_DWC_HOST_TXOOB_M		BIT(9)
> +#define AHCI_DWC_HOST_RXOOB_M		BIT(10)
> +#define AHCI_DWC_HOST_RXOOB_CLK_MASK	GENMASK(8, 0)
> +
> +#define AHCI_DWC_HOST_PPARAMR		0xf0
> +#define AHCI_DWC_HOST_TX_MEM_M		BIT(11)
> +#define AHCI_DWC_HOST_TX_MEM_S		BIT(10)
> +#define AHCI_DWC_HOST_RX_MEM_M		BIT(9)
> +#define AHCI_DWC_HOST_RX_MEM_S		BIT(8)
> +#define AHCI_DWC_HOST_TXFIFO_DEPTH	GENMASK(7, 4)
> +#define AHCI_DWC_HOST_RXFIFO_DEPTH	GENMASK(3, 0)
> +
> +#define AHCI_DWC_HOST_TESTR		0xf4
> +#define AHCI_DWC_HOST_PSEL_MASK		GENMASK(18, 16)
> +#define AHCI_DWC_HOST_TEST_IF		BIT(0)
> +
> +#define AHCI_DWC_HOST_VERSIONR		0xf8
> +#define AHCI_DWC_HOST_IDR		0xfc
> +
> +#define AHCI_DWC_PORT_DMACR		0x70
> +#define AHCI_DWC_PORT_RXABL_MASK	GENMASK(15, 12)
> +#define AHCI_DWC_PORT_TXABL_MASK	GENMASK(11, 8)
> +#define AHCI_DWC_PORT_RXTS_MASK		GENMASK(7, 4)
> +#define AHCI_DWC_PORT_TXTS_MASK		GENMASK(3, 0)
> +#define AHCI_DWC_PORT_PHYCR		0x74
> +#define AHCI_DWC_PORT_PHYSR		0x78
> +
> +struct ahci_dwc_host_priv {
> +	struct platform_device *pdev;
> +
> +	u32 timv;
> +	u32 dmacr[AHCI_MAX_PORTS];
> +};
> +
> +static struct ahci_host_priv *ahci_dwc_get_resources(struct platform_device *pdev)
> +{
> +	struct ahci_dwc_host_priv *dpriv;
> +	struct ahci_host_priv *hpriv;
> +
> +	dpriv = devm_kzalloc(&pdev->dev, sizeof(*dpriv), GFP_KERNEL);
> +	if (!dpriv)
> +		return ERR_PTR(-ENOMEM);
> +
> +	dpriv->pdev = pdev;
> +
> +	hpriv = ahci_platform_get_resources(pdev, AHCI_PLATFORM_GET_RESETS);
> +	if (IS_ERR(hpriv))
> +		return hpriv;
> +
> +	hpriv->plat_data = (void *)dpriv;
> +
> +	return hpriv;
> +}
> +
> +static void ahci_dwc_check_cap(struct ahci_host_priv *hpriv)
> +{
> +	unsigned long port_map = hpriv->saved_port_map | hpriv->mask_port_map;
> +	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
> +	bool dev_mp, dev_cp, fbs_sup;
> +	unsigned int fbs_pmp;
> +	u32 param;
> +	int i;
> +
> +	param = readl(hpriv->mmio + AHCI_DWC_HOST_GPARAM2R);
> +	dev_mp = !!(param & AHCI_DWC_HOST_DEV_MP);
> +	dev_cp = !!(param & AHCI_DWC_HOST_DEV_CP);
> +	fbs_sup = !!(param & AHCI_DWC_HOST_FBS_SUP);
> +	fbs_pmp = 5 * FIELD_GET(AHCI_DWC_HOST_FBS_PMPN_MASK, param);
> +
> +	if (!dev_mp && hpriv->saved_cap & HOST_CAP_MPS) {
> +		dev_warn(&dpriv->pdev->dev, "MPS is unsupported\n");
> +		hpriv->saved_cap &= ~HOST_CAP_MPS;
> +	}
> +
> +
> +	if (fbs_sup && fbs_pmp < AHCI_DWC_FBS_PMPN_MAX) {
> +		dev_warn(&dpriv->pdev->dev, "PMPn is limited up to %u ports\n",
> +			 fbs_pmp);
> +	}
> +
> +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> +		if (!dev_mp && hpriv->saved_port_cap[i] & PORT_CMD_MPSP) {
> +			dev_warn(&dpriv->pdev->dev, "MPS incapable port %d\n", i);
> +			hpriv->saved_port_cap[i] &= ~PORT_CMD_MPSP;
> +		}
> +
> +		if (!dev_cp && hpriv->saved_port_cap[i] & PORT_CMD_CPD) {
> +			dev_warn(&dpriv->pdev->dev, "CPD incapable port %d\n", i);
> +			hpriv->saved_port_cap[i] &= ~PORT_CMD_CPD;
> +		}
> +
> +		if (!fbs_sup && hpriv->saved_port_cap[i] & PORT_CMD_FBSCP) {
> +			dev_warn(&dpriv->pdev->dev, "FBS incapable port %d\n", i);
> +			hpriv->saved_port_cap[i] &= ~PORT_CMD_FBSCP;
> +		}
> +	}
> +}
> +
> +static void ahci_dwc_init_timer(struct ahci_host_priv *hpriv)
> +{
> +	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
> +	unsigned long rate;
> +	struct clk *aclk;
> +	u32 cap, cap2;
> +
> +	/* 1ms tick is generated only for the CCC or DevSleep features */
> +	cap = readl(hpriv->mmio + HOST_CAP);
> +	cap2 = readl(hpriv->mmio + HOST_CAP2);
> +	if (!(cap & HOST_CAP_CCC) && !(cap2 & HOST_CAP2_SDS))
> +		return;
> +
> +	/*
> +	 * Tick is generated based on the AXI/AHB application clocks signal
> +	 * so we need to be sure in the clock we are going to use.
> +	 */
> +	aclk = ahci_platform_find_clk(hpriv, "aclk");
> +	if (!aclk)
> +		return;
> +
> +	/* 1ms timer interval is set as TIMV = AMBA_FREQ[MHZ] * 1000 */
> +	dpriv->timv = readl(hpriv->mmio + AHCI_DWC_HOST_TIMER1MS);
> +	dpriv->timv = FIELD_GET(AHCI_DWC_HOST_TIMV_MASK, dpriv->timv);
> +	rate = clk_get_rate(aclk) / 1000UL;
> +	if (rate == dpriv->timv)
> +		return;
> +
> +	dev_info(&dpriv->pdev->dev, "Update CCC/DevSlp timer for Fapp %lu MHz\n",
> +		 rate / 1000UL);
> +	dpriv->timv = FIELD_PREP(AHCI_DWC_HOST_TIMV_MASK, rate);
> +	writel(dpriv->timv, hpriv->mmio + AHCI_DWC_HOST_TIMER1MS);
> +}
> +
> +static int ahci_dwc_init_dmacr(struct ahci_host_priv *hpriv)
> +{
> +	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
> +	struct device_node *child;
> +	void __iomem *port_mmio;
> +	u32 port, dmacr, ts;
> +
> +	/*
> +	 * Update the DMA Tx/Rx transaction sizes in accordance with the
> +	 * platform setup. Note values exceeding maximal or minimal limits will
> +	 * be automatically clamped. Also note the register isn't affected by
> +	 * the HBA global reset so we can freely initialize it once until the
> +	 * next system reset.
> +	 */
> +	for_each_child_of_node(dpriv->pdev->dev.of_node, child) {
> +		if (!of_device_is_available(child))
> +			continue;
> +
> +		if (of_property_read_u32(child, "reg", &port)) {
> +			of_node_put(child);
> +			return -EINVAL;
> +		}
> +
> +		port_mmio = __ahci_port_base(hpriv, port);
> +		dmacr = readl(port_mmio + AHCI_DWC_PORT_DMACR);
> +
> +		if (!of_property_read_u32(child, "snps,tx-ts-max", &ts)) {
> +			ts = ilog2(ts);
> +			dmacr &= ~AHCI_DWC_PORT_TXTS_MASK;
> +			dmacr |= FIELD_PREP(AHCI_DWC_PORT_TXTS_MASK, ts);
> +		}
> +
> +		if (!of_property_read_u32(child, "snps,rx-ts-max", &ts)) {
> +			ts = ilog2(ts);
> +			dmacr &= ~AHCI_DWC_PORT_RXTS_MASK;
> +			dmacr |= FIELD_PREP(AHCI_DWC_PORT_RXTS_MASK, ts);
> +		}
> +
> +		writel(dmacr, port_mmio + AHCI_DWC_PORT_DMACR);
> +		dpriv->dmacr[port] = dmacr;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ahci_dwc_init_host(struct ahci_host_priv *hpriv)
> +{
> +	int rc;
> +
> +	rc = ahci_platform_enable_resources(hpriv);
> +	if (rc)
> +		return rc;
> +
> +	ahci_dwc_check_cap(hpriv);
> +
> +	ahci_dwc_init_timer(hpriv);
> +
> +	rc = ahci_dwc_init_dmacr(hpriv);
> +	if (rc)
> +		goto err_disable_resources;
> +
> +	return 0;
> +
> +err_disable_resources:
> +	ahci_platform_disable_resources(hpriv);
> +
> +	return rc;
> +}
> +
> +static int ahci_dwc_reinit_host(struct ahci_host_priv *hpriv)
> +{
> +	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
> +	unsigned long port_map = hpriv->port_map;
> +	void __iomem *port_mmio;
> +	int i, rc;
> +
> +	rc = ahci_platform_enable_resources(hpriv);
> +	if (rc)
> +		return rc;
> +
> +	writel(dpriv->timv, hpriv->mmio + AHCI_DWC_HOST_TIMER1MS);
> +
> +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> +		port_mmio = __ahci_port_base(hpriv, i);
> +		writel(dpriv->dmacr[i], port_mmio + AHCI_DWC_PORT_DMACR);
> +	}
> +
> +	return 0;
> +}
> +
> +static void ahci_dwc_clear_host(struct ahci_host_priv *hpriv)
> +{
> +	ahci_platform_disable_resources(hpriv);
> +}
> +
> +static void ahci_dwc_stop_host(struct ata_host *host)
> +{
> +	struct ahci_host_priv *hpriv = host->private_data;
> +
> +	ahci_dwc_clear_host(hpriv);
> +}
> +
> +static struct ata_port_operations ahci_dwc_port_ops = {
> +	.inherits	= &ahci_platform_ops,
> +	.host_stop	= ahci_dwc_stop_host,
> +};
> +
> +static const struct ata_port_info ahci_dwc_port_info = {
> +	.flags		= AHCI_FLAG_COMMON,
> +	.pio_mask	= ATA_PIO4,
> +	.udma_mask	= ATA_UDMA6,
> +	.port_ops	= &ahci_dwc_port_ops,
> +};
> +
> +static struct scsi_host_template ahci_dwc_scsi_info = {
> +	AHCI_SHT(DRV_NAME),
> +};
> +
> +static int ahci_dwc_probe(struct platform_device *pdev)
> +{
> +	struct ahci_host_priv *hpriv;
> +	int rc;
> +
> +	hpriv = ahci_dwc_get_resources(pdev);
> +	if (IS_ERR(hpriv))
> +		return PTR_ERR(hpriv);
> +
> +	rc = ahci_dwc_init_host(hpriv);
> +	if (rc)
> +		return rc;
> +
> +	rc = ahci_platform_init_host(pdev, hpriv, &ahci_dwc_port_info,
> +				     &ahci_dwc_scsi_info);
> +	if (rc)
> +		goto err_clear_host;
> +
> +	return 0;
> +
> +err_clear_host:
> +	ahci_dwc_clear_host(hpriv);
> +
> +	return rc;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int ahci_dwc_suspend(struct device *dev)
> +{
> +	struct ata_host *host = dev_get_drvdata(dev);
> +	struct ahci_host_priv *hpriv = host->private_data;
> +	int rc;
> +
> +	rc = ahci_platform_suspend_host(dev);
> +	if (rc)
> +		return rc;
> +
> +	ahci_dwc_clear_host(hpriv);
> +
> +	return 0;
> +}
> +
> +static int ahci_dwc_resume(struct device *dev)
> +{
> +	struct ata_host *host = dev_get_drvdata(dev);
> +	struct ahci_host_priv *hpriv = host->private_data;
> +	int rc;
> +
> +	rc = ahci_dwc_reinit_host(hpriv);
> +	if (rc)
> +		return rc;
> +
> +	return ahci_platform_resume_host(dev);
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(ahci_dwc_pm_ops, ahci_dwc_suspend, ahci_dwc_resume);

include/linux/pm.h says:
/* Deprecated. Use DEFINE_SIMPLE_DEV_PM_OPS() instead. */

> +
> +static const struct of_device_id ahci_dwc_of_match[] = {
> +	{ .compatible = "snps,dwc-ahci", },
> +	{ .compatible = "snps,spear-ahci", },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, ahci_dwc_of_match);
> +
> +static struct platform_driver ahci_dwc_driver = {
> +	.probe = ahci_dwc_probe,
> +	.remove = ata_platform_remove_one,
> +	.shutdown = ahci_platform_shutdown,
> +	.driver = {
> +		.name = DRV_NAME,
> +		.of_match_table = ahci_dwc_of_match,
> +		.pm = &ahci_dwc_pm_ops,
> +	},
> +};
> +module_platform_driver(ahci_dwc_driver);
> +
> +MODULE_DESCRIPTION("DWC AHCI SATA platform driver");
> +MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
> +MODULE_LICENSE("GPL");

MODULE_LICENSE("GPL v2");

To match the file header SPDX.

> diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
> index 9b56490ecbc3..8f5572a9f8f1 100644
> --- a/drivers/ata/ahci_platform.c
> +++ b/drivers/ata/ahci_platform.c
> @@ -80,9 +80,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
>  static const struct of_device_id ahci_of_match[] = {
>  	{ .compatible = "generic-ahci", },
>  	/* Keep the following compatibles for device tree compatibility */
> -	{ .compatible = "snps,spear-ahci", },
>  	{ .compatible = "ibm,476gtr-ahci", },
> -	{ .compatible = "snps,dwc-ahci", },
>  	{ .compatible = "hisilicon,hisi-ahci", },
>  	{ .compatible = "cavium,octeon-7130-ahci", },
>  	{ /* sentinel */ }


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml
  2022-06-10  8:17 ` [PATCH v4 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml Serge Semin
@ 2022-06-14 22:02   ` Rob Herring
  2022-06-14 22:15   ` Florian Fainelli
  1 sibling, 0 replies; 80+ messages in thread
From: Rob Herring @ 2022-06-14 22:02 UTC (permalink / raw)
  To: Serge Semin
  Cc: Jens Axboe, Serge Semin, Hannes Reinecke, Damien Le Moal,
	Pavel Parkhomenko, Alexey Malahov, linux-kernel, linux-ide,
	Krzysztof Kozlowski, Rob Herring, Florian Fainelli, devicetree,
	Hans de Goede, Linus Walleij

On Fri, 10 Jun 2022 11:17:39 +0300, Serge Semin wrote:
> Seeing doubtfully any SATA device working without embedded DMA engine
> let's permit the device nodes being equipped with the dma-coherent
> property in case if the platform is capable of cache-coherent DMAs.
> 
> As a side-effect we can drop the explicit dma-coherent property definition
> from the particular device schemas. Currently it concerns the Broadcom
> SATA AHCI controller only.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> 
> ---
> 
> Changelog v2:
> - This is a new patch created after rebasing v1 onto the 5.18-rc3 kernel.
> 
> Changelog v4:
> - Move the dma-coherent property to the sata-common.yaml schema instead
>   of removing it.
> - Remove the Hannes' rb tag.
> ---
>  Documentation/devicetree/bindings/ata/ahci-platform.yaml  | 2 --
>  Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml | 2 --
>  Documentation/devicetree/bindings/ata/sata-common.yaml    | 2 ++
>  3 files changed, 2 insertions(+), 4 deletions(-)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml
  2022-06-10  8:17 ` [PATCH v4 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml Serge Semin
  2022-06-14 22:02   ` Rob Herring
@ 2022-06-14 22:15   ` Florian Fainelli
  1 sibling, 0 replies; 80+ messages in thread
From: Florian Fainelli @ 2022-06-14 22:15 UTC (permalink / raw)
  To: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Rob Herring, Krzysztof Kozlowski, Linus Walleij
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, linux-ide,
	linux-kernel, devicetree

On 6/10/22 01:17, Serge Semin wrote:
> Seeing doubtfully any SATA device working without embedded DMA engine
> let's permit the device nodes being equipped with the dma-coherent
> property in case if the platform is capable of cache-coherent DMAs.
> 
> As a side-effect we can drop the explicit dma-coherent property definition
> from the particular device schemas. Currently it concerns the Broadcom
> SATA AHCI controller only.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 05/23] dt-bindings: ata: sata-brcm: Apply common AHCI schema
  2022-06-10  8:17 ` [PATCH v4 05/23] dt-bindings: ata: sata-brcm: Apply common AHCI schema Serge Semin
@ 2022-06-14 22:15   ` Florian Fainelli
  2022-06-14 22:17   ` Rob Herring
  1 sibling, 0 replies; 80+ messages in thread
From: Florian Fainelli @ 2022-06-14 22:15 UTC (permalink / raw)
  To: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Rob Herring, Krzysztof Kozlowski
  Cc: Serge Semin, Alexey Malahov, Pavel Parkhomenko, linux-ide,
	linux-kernel, devicetree

On 6/10/22 01:17, Serge Semin wrote:
> The Broadcom SATA controller is obviously based on the AHCI standard. The
> device driver uses the kernel AHCI library to work with it. Therefore we
> can be have a more thorough DT-bindings evaluation by referring to the
> AHCI-common schema instead of using the more relaxed SATA-common one.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 02/23] dt-bindings: ata: ahci-platform: Detach common AHCI bindings
  2022-06-10  8:17 ` [PATCH v4 02/23] dt-bindings: ata: ahci-platform: Detach common AHCI bindings Serge Semin
@ 2022-06-14 22:16   ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2022-06-14 22:16 UTC (permalink / raw)
  To: Serge Semin
  Cc: Alexey Malahov, Serge Semin, Linus Walleij, linux-ide,
	linux-kernel, Hannes Reinecke, Pavel Parkhomenko, Jens Axboe,
	Damien Le Moal, devicetree, Krzysztof Kozlowski, Rob Herring,
	Hans de Goede

On Fri, 10 Jun 2022 11:17:40 +0300, Serge Semin wrote:
> In order to create a more sophisticated AHCI controller DT bindings let's
> divide the already available generic AHCI platform YAML schema into the
> platform part and a set of the common AHCI properties. The former part
> will be used to evaluate the AHCI DT nodes mainly compatible with the
> generic AHCI controller while the later schema will be used for more
> thorough AHCI DT nodes description. For instance such YAML schemas design
> will be useful for our DW AHCI SATA controller derivative with four clock
> sources, two reset lines, one system controller reference and specific
> max Rx/Tx DMA xfers size constraints.
> 
> Note the phys and target-supply property requirement is preserved in the
> generic AHCI platform bindings because some platforms can lack of the
> explicitly specified PHYs or target device power regulators.
> 
> Also note the SATA/AHCI ports properties have been moved to the
> $defs-paragraph of the schemas. It's done in order to create the
> extendable properties hierarchy such that particular AHCI-controller
> could add vendor-specific port properties.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> 
> ---
> 
> Folks, I don't really see why the phys/target-supply requirement has been
> added to the generic AHCI DT schema in the first place. Probably just to
> imply some meaning for the sub-nodes definition. Anyway in one of the
> further patches I am adding the DW AHCI SATA controller DT bindings which
> won't require having these properties specified in the sub-nodes, but will
> describe additional port-specific properties. That's why I get to keep the
> constraints in the ahci-platform.yaml schema instead of moving them to the
> common schema.
> 
> Changelog v2:
> - This is a new patch created after rebasing v1 onto the 5.18-rc3 kernel.
> 
> Changelog v3:
> - Replace Jens's email address with Damien's one in the list of the
>   schema maintainers. (@Damien)
> 
> Changelog v4:
> - Drop clocks, clock-names, resets, reset-names and power-domains
>   properties from the common schema. (@Rob)
> - Create sata/ahci-port properties definition hierarchy so the sub-schemas
>   would inherit and extend the ports properties of the super-schema. (@Rob)
> ---
>  .../devicetree/bindings/ata/ahci-common.yaml  | 100 ++++++++++++++++++
>  .../bindings/ata/ahci-platform.yaml           |  72 ++-----------
>  .../devicetree/bindings/ata/sata-common.yaml  |   8 +-
>  3 files changed, 115 insertions(+), 65 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/ata/ahci-common.yaml
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 03/23] dt-bindings: ata: ahci-platform: Clarify common AHCI props constraints
  2022-06-10  8:17 ` [PATCH v4 03/23] dt-bindings: ata: ahci-platform: Clarify common AHCI props constraints Serge Semin
@ 2022-06-14 22:17   ` Rob Herring
  0 siblings, 0 replies; 80+ messages in thread
From: Rob Herring @ 2022-06-14 22:17 UTC (permalink / raw)
  To: Serge Semin
  Cc: Rob Herring, Pavel Parkhomenko, devicetree, Krzysztof Kozlowski,
	Damien Le Moal, linux-ide, Jens Axboe, Alexey Malahov,
	Hannes Reinecke, linux-kernel, Hans de Goede, Serge Semin

On Fri, 10 Jun 2022 11:17:41 +0300, Serge Semin wrote:
> Indeed in accordance with what is implemented in the AHCI platform driver
> and the way the AHCI DT nodes are defined in the DT files we can add the
> next AHCI DT properties constraints: AHCI CSR ID is fixed to 'ahci', PHY
> name is fixed to 'sata-phy', AHCI controller can't have more than 32 ports
> by design, AHCI controller can have up to 32 IRQ lines.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> 
> ---
> 
> Changelog v2:
> - This is a new patch created after rebasing v1 onto the 5.18-rc3 kernel.
> 
> Changelog v4:
> - Fix spelling: 'imeplemtned' and 'paltform' in the patch log. (@Hannes)
> - Add the interrupts property constraints. (@Rob)
> - Add forgotten '---' patchlog-changelog separator. (@Sergei)
> ---
>  .../devicetree/bindings/ata/ahci-common.yaml    | 17 ++++++++++++-----
>  1 file changed, 12 insertions(+), 5 deletions(-)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 05/23] dt-bindings: ata: sata-brcm: Apply common AHCI schema
  2022-06-10  8:17 ` [PATCH v4 05/23] dt-bindings: ata: sata-brcm: Apply common AHCI schema Serge Semin
  2022-06-14 22:15   ` Florian Fainelli
@ 2022-06-14 22:17   ` Rob Herring
  1 sibling, 0 replies; 80+ messages in thread
From: Rob Herring @ 2022-06-14 22:17 UTC (permalink / raw)
  To: Serge Semin
  Cc: Alexey Malahov, Hannes Reinecke, Hans de Goede, linux-ide,
	Jens Axboe, Serge Semin, Rob Herring, linux-kernel,
	Damien Le Moal, devicetree, Florian Fainelli, Pavel Parkhomenko,
	Krzysztof Kozlowski

On Fri, 10 Jun 2022 11:17:43 +0300, Serge Semin wrote:
> The Broadcom SATA controller is obviously based on the AHCI standard. The
> device driver uses the kernel AHCI library to work with it. Therefore we
> can be have a more thorough DT-bindings evaluation by referring to the
> AHCI-common schema instead of using the more relaxed SATA-common one.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> 
> ---
> 
> Changelog v4:
> - This is a new patch added on v4 lap of the review procedure.
> ---
>  Documentation/devicetree/bindings/ata/brcm,sata-brcm.yaml | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 11/23] dt-bindings: ata: ahci: Add platform capability properties
  2022-06-10  8:17 ` [PATCH v4 11/23] dt-bindings: ata: ahci: Add platform capability properties Serge Semin
@ 2022-06-14 22:19   ` Rob Herring
  2022-06-15 21:56     ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Rob Herring @ 2022-06-14 22:19 UTC (permalink / raw)
  To: Serge Semin
  Cc: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Krzysztof Kozlowski, Serge Semin, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

On Fri, Jun 10, 2022 at 11:17:49AM +0300, Serge Semin wrote:
> In case if the platform doesn't have BIOS or a comprehensive firmware
> installed then the HBA capability flags will be left uninitialized. As a
> good alternative we suggest to define the DT-properties with the AHCI
> platform capabilities describing all the HW-init flags of the
> corresponding capability register. Luckily there aren't too many of them.
> SSS - Staggered Spin-up support and MPS - Mechanical Presence Switch
> support determine the corresponding feature availability for the whole HBA
> by means of the "hba-cap" property. Each port can have the "hba-port-cap"
> property initialized indicating that the port supports some of the next
> functionalities: HPCP - HotPlug capable port, MPSP - Mechanical Presence
> Switch attached to a port, CPD - Cold Plug detection, ESP - External SATA
> Port (eSATA), FBSCP - FIS-based switching capable port.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> 
> ---
> 
> Changelog v4:
> - Fix some misspelling in the patch log.
> - Convert the boolean properties to the bitfield properties. (@Rob)
> - Remove Hannes' rb tag due to the patch content change.
> ---
>  .../devicetree/bindings/ata/ahci-common.yaml  | 16 +++++++++++++++
>  .../bindings/ata/ahci-platform.yaml           | 10 ++++++++++
>  include/dt-bindings/ata/ahci.h                | 20 +++++++++++++++++++
>  3 files changed, 46 insertions(+)
>  create mode 100644 include/dt-bindings/ata/ahci.h
> 
> diff --git a/Documentation/devicetree/bindings/ata/ahci-common.yaml b/Documentation/devicetree/bindings/ata/ahci-common.yaml
> index 12a97b56226f..94d72aeaad0f 100644
> --- a/Documentation/devicetree/bindings/ata/ahci-common.yaml
> +++ b/Documentation/devicetree/bindings/ata/ahci-common.yaml
> @@ -58,6 +58,14 @@ properties:
>    phy-names:
>      const: sata-phy
>  
> +  hba-cap:
> +    $ref: '/schemas/types.yaml#/definitions/uint32'
> +    description:
> +      Bitfield of the HBA generic platform capabilities like Staggered
> +      Spin-up or Mechanical Presence Switch support. It can be used to
> +      appropriately initialize the HWinit fields of the HBA CAP register
> +      in case if the system firmware hasn't done it.
> +
>    ports-implemented:
>      $ref: '/schemas/types.yaml#/definitions/uint32'
>      description:
> @@ -101,6 +109,14 @@ $defs:
>        target-supply:
>          description: Power regulator for SATA port target device
>  
> +      hba-port-cap:
> +        $ref: '/schemas/types.yaml#/definitions/uint32'
> +        description:
> +          Bitfield of the HBA port-specific platform capabilities like Hot
> +          plugging, eSATA, FIS-based Switching, etc (see AHCI specification
> +          for details). It can be used to initialize the HWinit fields of
> +          the PxCMD register in case if the system firmware hasn't done it.
> +
>      required:
>        - reg
>  
> diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> index 15be98e0385b..e19cf9828e68 100644
> --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> @@ -111,6 +111,8 @@ examples:
>    - |
>      #include <dt-bindings/interrupt-controller/arm-gic.h>
>      #include <dt-bindings/clock/berlin2q.h>
> +    #include <dt-bindings/ata/ahci.h>
> +
>      sata@f7e90000 {
>          compatible = "marvell,berlin2q-ahci", "generic-ahci";
>          reg = <0xf7e90000 0x1000>;
> @@ -119,15 +121,23 @@ examples:
>          #address-cells = <1>;
>          #size-cells = <0>;
>  
> +        hba-cap = <HBA_SMPS>;
> +
>          sata0: sata-port@0 {
>              reg = <0>;
> +
>              phys = <&sata_phy 0>;
>              target-supply = <&reg_sata0>;
> +
> +            hba-port-cap = <(HBA_PORT_FBSCP | HBA_PORT_ESP)>;
>          };
>  
>          sata1: sata-port@1 {
>              reg = <1>;
> +
>              phys = <&sata_phy 1>;
>              target-supply = <&reg_sata1>;
> +
> +            hba-port-cap = <(HBA_PORT_HPCP | HBA_PORT_MPSP | HBA_PORT_FBSCP)>;
>          };
>      };
> diff --git a/include/dt-bindings/ata/ahci.h b/include/dt-bindings/ata/ahci.h
> new file mode 100644
> index 000000000000..6841caebcedf
> --- /dev/null
> +++ b/include/dt-bindings/ata/ahci.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0 */

Dual license.

With that,

Reviewed-by: Rob Herring <robh@kernel.org>

> +/*
> + * This header provides constants for most AHCI bindings.
> + */
> +
> +#ifndef _DT_BINDINGS_ATA_AHCI_H
> +#define _DT_BINDINGS_ATA_AHCI_H
> +
> +/* Host Bus Adapter generic platform capabilities */
> +#define HBA_SSS		(1 << 27)
> +#define HBA_SMPS	(1 << 28)
> +
> +/* Host Bus Adapter port-specific platform capabilities */
> +#define HBA_PORT_HPCP	(1 << 18)
> +#define HBA_PORT_MPSP	(1 << 19)
> +#define HBA_PORT_CPD	(1 << 20)
> +#define HBA_PORT_ESP	(1 << 21)
> +#define HBA_PORT_FBSCP	(1 << 22)
> +
> +#endif
> -- 
> 2.35.1
> 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema
  2022-06-10  8:17 ` [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema Serge Semin
@ 2022-06-14 22:27   ` Rob Herring
  2022-06-17 19:37     ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Rob Herring @ 2022-06-14 22:27 UTC (permalink / raw)
  To: Serge Semin
  Cc: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Krzysztof Kozlowski, Serge Semin, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

On Fri, Jun 10, 2022 at 11:17:55AM +0300, Serge Semin wrote:
> Synopsys AHCI SATA controller is mainly compatible with the generic AHCI
> SATA controller except a few peculiarities and the platform environment
> requirements. In particular it can have one or two reference clocks to
> feed up its AXI/AHB interface and SATA PHYs domain and at least one reset
> control for the application clock domain. In addition to that the DMA
> interface of each port can be tuned up to work with the predefined maximum
> data chunk size. Note unlike generic AHCI controller DWC AHCI can't have
> more than 8 ports. All of that is reflected in the new DWC AHCI SATA
> device DT binding.
> 
> Note the DWC AHCI SATA controller DT-schema has been created in a way so
> to be reused for the vendor-specific DT-schemas (see for example the
> "snps,dwc-ahci" compatible string binding). One of which we are about to
> introduce.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> 
> ---
> 
> Changelog v2:
> - Replace min/max constraints of the snps,{tx,rx}-ts-max property with
>   enum [ 1, 2, 4, ..., 1024 ]. (@Rob)
> 
> Changelog v4:
> - Decrease the "additionalProperties" property identation otherwise it's
>   percieved as the node property instead of the key one. (@Rob)
> - Use the ahci-port properties definition from the AHCI common schema
>   in order to extend it with DWC AHCI SATA port properties. (@Rob)
> - Remove the Hannes' rb tag since the patch content has changed.
> ---
>  .../bindings/ata/ahci-platform.yaml           |   8 --
>  .../bindings/ata/snps,dwc-ahci.yaml           | 129 ++++++++++++++++++
>  2 files changed, 129 insertions(+), 8 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> 
> diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> index e19cf9828e68..7dc2a2e8f598 100644
> --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> @@ -30,8 +30,6 @@ select:
>            - marvell,armada-3700-ahci
>            - marvell,armada-8k-ahci
>            - marvell,berlin2q-ahci
> -          - snps,dwc-ahci
> -          - snps,spear-ahci
>    required:
>      - compatible
>  
> @@ -48,17 +46,11 @@ properties:
>                - marvell,berlin2-ahci
>                - marvell,berlin2q-ahci
>            - const: generic-ahci
> -      - items:
> -          - enum:
> -              - rockchip,rk3568-dwc-ahci
> -          - const: snps,dwc-ahci
>        - enum:
>            - cavium,octeon-7130-ahci
>            - hisilicon,hisi-ahci
>            - ibm,476gtr-ahci
>            - marvell,armada-3700-ahci
> -          - snps,dwc-ahci
> -          - snps,spear-ahci
>  
>    reg:
>      minItems: 1
> diff --git a/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> new file mode 100644
> index 000000000000..af78f6c9b857
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> @@ -0,0 +1,129 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/ata/snps,dwc-ahci.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Synopsys DWC AHCI SATA controller
> +
> +maintainers:
> +  - Serge Semin <fancer.lancer@gmail.com>
> +
> +description:
> +  This document defines device tree bindings for the Synopsys DWC
> +  implementation of the AHCI SATA controller.
> +
> +allOf:
> +  - $ref: ahci-common.yaml#
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - description: Synopsys AHCI SATA-compatible devices
> +        contains:
> +          const: snps,dwc-ahci
> +      - description: SPEAr1340 AHCI SATA device
> +        const: snps,spear-ahci
> +      - description: Rockhip RK3568 ahci controller
> +        const: rockchip,rk3568-dwc-ahci

This is never true because there is a fallback. We should keep what we 
had before.


> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  clocks:
> +    description:
> +      Basic DWC AHCI SATA clock sources like application AXI/AHB BIU clock
> +      and embedded PHYs reference clock together with vendor-specific set
> +      of clocks.
> +    minItems: 1
> +    maxItems: 4
> +
> +  clock-names:
> +    contains:
> +      anyOf:
> +        - description: Application AXI/AHB BIU clock source
> +          enum:
> +            - aclk
> +            - sata
> +        - description: SATA Ports reference clock
> +          enum:
> +            - ref
> +            - sata_ref
> +
> +  resets:
> +    description:
> +      At least basic core and application clock domains reset is normally
> +      supported by the DWC AHCI SATA controller. Some platform specific
> +      clocks can be also specified though.

s/clocks/resets/ ?

This allows any number of resets which isn't great. I think this schema 
should just be the 'simple' cases where there's only 1 reset and 1 
clock (or how many the DWC block actually has if you have that info). 
More complicated cases get there own schema.

> +
> +  reset-names:
> +    contains:
> +      description: Core and application clock domains reset control
> +      const: arst
> +
> +patternProperties:
> +  "^sata-port@[0-9a-e]$":
> +    $ref: '#/$defs/dwc-ahci-port'
> +
> +    unevaluatedProperties: false
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +
> +unevaluatedProperties: false
> +
> +$defs:
> +  dwc-ahci-port:
> +    $ref: /schemas/ata/ahci-common.yaml#/$defs/ahci-port
> +
> +    properties:
> +      reg:
> +        minimum: 0
> +        maximum: 7
> +
> +      snps,tx-ts-max:
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        description: Maximal size of Tx DMA transactions in FIFO words
> +        enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
> +
> +      snps,rx-ts-max:
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        description: Maximal size of Rx DMA transactions in FIFO words
> +        enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/ata/ahci.h>
> +
> +    sata@122f0000 {
> +      compatible = "snps,dwc-ahci";
> +      reg = <0x122F0000 0x1ff>;
> +      #address-cells = <1>;
> +      #size-cells = <0>;
> +
> +      interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
> +
> +      clocks = <&clock1>, <&clock2>;
> +      clock-names = "aclk", "ref";
> +
> +      phys = <&sata_phy>;
> +      phy-names = "sata-phy";
> +
> +      ports-implemented = <0x1>;
> +
> +      sata-port@0 {
> +        reg = <0>;
> +
> +        hba-port-cap = <HBA_PORT_FBSCP>;
> +
> +        snps,tx-ts-max = <512>;
> +        snps,rx-ts-max = <512>;
> +      };
> +    };
> +...
> -- 
> 2.35.1
> 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 20/23] dt-bindings: ata: ahci: Add Baikal-T1 AHCI SATA controller DT schema
  2022-06-10  8:17 ` [PATCH v4 20/23] dt-bindings: ata: ahci: Add Baikal-T1 AHCI SATA controller DT schema Serge Semin
@ 2022-06-14 22:29   ` Rob Herring
  2022-06-17 19:49     ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Rob Herring @ 2022-06-14 22:29 UTC (permalink / raw)
  To: Serge Semin
  Cc: Damien Le Moal, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Serge Semin, Krzysztof Kozlowski, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

On Fri, Jun 10, 2022 at 11:17:58AM +0300, Serge Semin wrote:
> Baikal-T1 AHCI controller is based on the DWC AHCI SATA IP-core v4.10a
> with the next specific settings: two SATA ports, cascaded CSR access based
> on two clock domains (APB and AXI), selectable source of the reference
> clock (though stable work is currently available from the external source
> only), two reset lanes for the application and SATA ports domains. Other
> than that the device is fully compatible with the generic DWC AHCI SATA
> bindings.
> 
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Reviewed-by: Hannes Reinecke <hare@suse.de>
> 
> ---
> 
> Changelog v2:
> - Rename 'syscon' property to 'baikal,bt1-syscon'.
> - Drop macro usage from the example node.
> 
> Changelog v4:
> - Use the DWC AHCI port properties definition from the DWC AHCI SATA
>   common schema. (@Rob)
> - Drop Baikal-T1 syscon reference and implement the clock signal
>   source in the framework of the clock controller. (@Rob)
> ---
>  .../bindings/ata/baikal,bt1-ahci.yaml         | 116 ++++++++++++++++++
>  1 file changed, 116 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
> 
> diff --git a/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml b/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
> new file mode 100644
> index 000000000000..d5fbd7d561d8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
> @@ -0,0 +1,116 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/ata/baikal,bt1-ahci.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Baikal-T1 SoC AHCI SATA controller
> +
> +maintainers:
> +  - Serge Semin <fancer.lancer@gmail.com>
> +
> +description: |
> +  AHCI SATA controller embedded into the Baikal-T1 SoC is based on the
> +  DWC AHCI SATA v4.10a IP-core.
> +
> +allOf:
> +  - $ref: snps,dwc-ahci.yaml#
> +
> +properties:
> +  compatible:
> +    contains:
> +      const: baikal,bt1-ahci
> +
> +  clocks:
> +    items:
> +      - description: Peripheral APB bus clock source
> +      - description: Application AXI BIU clock
> +      - description: SATA Ports reference clock
> +
> +  clock-names:
> +    items:
> +      - const: pclk
> +      - const: aclk
> +      - const: ref
> +
> +  resets:
> +    items:
> +      - description: Application AXI BIU domain reset
> +      - description: SATA Ports clock domain reset
> +
> +  reset-names:
> +    items:
> +      - const: arst
> +      - const: ref
> +
> +  ports-implemented:
> +    maximum: 0x3
> +
> +patternProperties:
> +  "^sata-port@[0-9a-e]$":
> +    $ref: /schemas/ata/snps,dwc-ahci.yaml#/$defs/dwc-ahci-port
> +
> +    properties:
> +      reg:
> +        minimum: 0
> +        maximum: 1
> +
> +      snps,tx-ts-max:
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        description:
> +          Due to having AXI3 bus interface utilized the maximum Tx DMA
> +          transaction size can't exceed 16 beats (AxLEN[3:0]).
> +        enum: [ 1, 2, 4, 8, 16 ]
> +
> +      snps,rx-ts-max:
> +        $ref: /schemas/types.yaml#/definitions/uint32
> +        description:
> +          Due to having AXI3 bus interface utilized the maximum Rx DMA
> +          transaction size can't exceed 16 beats (AxLEN[3:0]).
> +        enum: [ 1, 2, 4, 8, 16 ]
> +
> +    unevaluatedProperties: false
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - clocks
> +  - clock-names
> +  - resets
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    sata@1f050000 {
> +      compatible = "baikal,bt1-ahci", "snps,dwc-ahci";

Just drop 'snps,dwc-ahci'. The generic IP block fallbacks have proven to 
be useless.

> +      reg = <0x1f050000 0x2000>;
> +      #address-cells = <1>;
> +      #size-cells = <0>;
> +
> +      interrupts = <0 64 4>;
> +
> +      clocks = <&ccu_sys 1>, <&ccu_axi 2>, <&sata_ref_clk>;
> +      clock-names = "pclk", "aclk", "ref";
> +
> +      resets = <&ccu_axi 2>, <&ccu_sys 0>;
> +      reset-names = "arst", "ref";
> +
> +      ports-implemented = <0x3>;
> +
> +      sata-port@0 {
> +        reg = <0>;
> +
> +        snps,tx-ts-max = <4>;
> +        snps,rx-ts-max = <4>;
> +      };
> +
> +      sata-port@1 {
> +        reg = <1>;
> +
> +        snps,tx-ts-max = <4>;
> +        snps,rx-ts-max = <4>;
> +      };
> +    };
> +...
> -- 
> 2.35.1
> 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 07/23] ata: libahci_platform: Convert to using devm bulk clocks API
  2022-06-14  8:22   ` Damien Le Moal
@ 2022-06-15 20:45     ` Serge Semin
  2022-06-16  0:23       ` Damien Le Moal
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-15 20:45 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Tue, Jun 14, 2022 at 05:22:02PM +0900, Damien Le Moal wrote:
> On 6/10/22 17:17, Serge Semin wrote:
> > In order to simplify the clock-related code there is a way to convert the
> > current fixed clocks array into using the common bulk clocks kernel API
> > with dynamic set of the clock handlers and device-managed clock-resource
> > tracking. It's a bit tricky due to the complication coming from the
> > requirement to support the platforms (da850, spear13xx) with the
> > non-OF-based clock source, but still doable.
> > 
> > Before this modification there are two methods have been used to get the
> > clocks connected to an AHCI device: clk_get() - to get the very first
> > clock in the list and of_clk_get() - to get the rest of them. Basically
> > the platforms with non-OF-based clocks definition could specify only a
> > single reference clock source. The platforms with OF-hw clocks have been
> > luckier and could setup up to AHCI_MAX_CLKS clocks. Such semantic can be
> > retained with using devm_clk_bulk_get_all() to retrieve the clocks defined
> > via the DT firmware and devm_clk_get_optional() otherwise. In both cases
> > using the device-managed version of the methods will cause the automatic
> > resources deallocation on the AHCI device removal event. The only
> > complicated part in the suggested approach is the explicit allocation and
> > initialization of the clk_bulk_data structure instance for the non-OF
> > reference clocks. It's required in order to use the Bulk Clocks API for
> > the both denoted cases of the clocks definition.
> > 
> > Note aside with the clock-related code reduction and natural
> > simplification, there are several bonuses the suggested modification
> > provides. First of all the limitation of having no greater than
> > AHCI_MAX_CLKS clocks is now removed, since the devm_clk_bulk_get_all()
> > method will allocate as many reference clocks data descriptors as there
> > are clocks specified for the device. Secondly the clock names are
> > auto-detected. So the LLDD (glue) drivers can make sure that the required
> > clocks are specified just by checking the clock IDs in the clk_bulk_data
> > array.  Thirdly using the handy Bulk Clocks kernel API improves the
> > clocks-handling code readability. And the last but not least this
> > modification implements a true optional clocks support to the
> > ahci_platform_get_resources() method. Indeed the previous clocks getting
> > procedure just stopped getting the clocks on any errors (aside from
> > non-critical -EPROBE_DEFER) in a way so the callee wasn't even informed
> > about abnormal loop termination. The new implementation lacks of such
> > problem. The ahci_platform_get_resources() will return an error code if
> > the corresponding clocks getting method ends execution abnormally.
> > 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > Reviewed-by: Hannes Reinecke <hare@suse.de>
> > 
> > ---
> > 
> > Changelog v2:
> > - Convert to checking the error-case first in the devm_clk_bulk_get_all()
> >   method invocation. (@Damien)
> > - Fix some grammar mistakes in the comments.
> > ---
> >  drivers/ata/ahci.h             |  4 +-
> >  drivers/ata/libahci_platform.c | 84 ++++++++++++++++------------------
> >  2 files changed, 41 insertions(+), 47 deletions(-)
> > 
> > diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> > index ad11a4c52fbe..c3770a19781b 100644
> > --- a/drivers/ata/ahci.h
> > +++ b/drivers/ata/ahci.h
> > @@ -38,7 +38,6 @@
> >  
> >  enum {
> >  	AHCI_MAX_PORTS		= 32,
> > -	AHCI_MAX_CLKS		= 5,
> >  	AHCI_MAX_SG		= 168, /* hardware max is 64K */
> >  	AHCI_DMA_BOUNDARY	= 0xffffffff,
> >  	AHCI_MAX_CMDS		= 32,
> > @@ -339,7 +338,8 @@ struct ahci_host_priv {
> >  	u32			em_msg_type;	/* EM message type */
> >  	u32			remapped_nvme;	/* NVMe remapped device count */
> >  	bool			got_runtime_pm; /* Did we do pm_runtime_get? */
> > -	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
> > +	unsigned int		n_clks;
> > +	struct clk_bulk_data	*clks;		/* Optional */
> >  	struct reset_control	*rsts;		/* Optional */
> >  	struct regulator	**target_pwrs;	/* Optional */
> >  	struct regulator	*ahci_regulator;/* Optional */
> > diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> > index 1e9e825d6cc5..814804582d1d 100644
> > --- a/drivers/ata/libahci_platform.c
> > +++ b/drivers/ata/libahci_platform.c
> > @@ -8,6 +8,7 @@
> >   *   Anton Vorontsov <avorontsov@ru.mvista.com>
> >   */
> >  
> > +#include <linux/clk-provider.h>
> >  #include <linux/clk.h>
> >  #include <linux/kernel.h>
> >  #include <linux/gfp.h>
> > @@ -97,28 +98,14 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
> >   * ahci_platform_enable_clks - Enable platform clocks
> >   * @hpriv: host private area to store config values
> >   *
> > - * This function enables all the clks found in hpriv->clks, starting at
> > - * index 0. If any clk fails to enable it disables all the clks already
> > - * enabled in reverse order, and then returns an error.
> > + * This function enables all the clks found for the AHCI device.
> >   *
> >   * RETURNS:
> >   * 0 on success otherwise a negative error code
> >   */
> >  int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
> >  {
> > -	int c, rc;
> > -
> > -	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
> > -		rc = clk_prepare_enable(hpriv->clks[c]);
> > -		if (rc)
> > -			goto disable_unprepare_clk;
> > -	}
> > -	return 0;
> > -
> > -disable_unprepare_clk:
> > -	while (--c >= 0)
> > -		clk_disable_unprepare(hpriv->clks[c]);
> > -	return rc;
> > +	return clk_bulk_prepare_enable(hpriv->n_clks, hpriv->clks);
> >  }
> >  EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
> >  
> > @@ -126,16 +113,13 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
> >   * ahci_platform_disable_clks - Disable platform clocks
> >   * @hpriv: host private area to store config values
> >   *
> > - * This function disables all the clks found in hpriv->clks, in reverse
> > - * order of ahci_platform_enable_clks (starting at the end of the array).
> > + * This function disables all the clocks enabled before
> > + * (bulk-clocks-disable function is supposed to do that in reverse
> > + * from the enabling procedure order).
> >   */
> >  void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
> >  {
> > -	int c;
> > -
> > -	for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
> > -		if (hpriv->clks[c])
> > -			clk_disable_unprepare(hpriv->clks[c]);
> > +	clk_bulk_disable_unprepare(hpriv->n_clks, hpriv->clks);
> >  }
> >  EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
> >  
> > @@ -292,8 +276,6 @@ static void ahci_platform_put_resources(struct device *dev, void *res)
> >  		pm_runtime_disable(dev);
> >  	}
> >  
> > -	for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
> > -		clk_put(hpriv->clks[c]);
> >  	/*
> >  	 * The regulators are tied to child node device and not to the
> >  	 * SATA device itself. So we can't use devm for automatically
> > @@ -374,8 +356,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
> >   * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
> >   * 2) regulator for controlling the targets power (optional)
> >   *    regulator for controlling the AHCI controller (optional)
> > - * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
> > - *    or for non devicetree enabled platforms a single clock
> > + * 3) all clocks specified in the devicetree node, or a single
> > + *    clock for non-OF platforms (optional)
> >   * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional)
> >   * 5) phys (optional)
> >   *
> > @@ -385,11 +367,10 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
> >  struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
> >  						   unsigned int flags)
> >  {
> > +	int child_nodes, rc = -ENOMEM, enabled_ports = 0;
> >  	struct device *dev = &pdev->dev;
> >  	struct ahci_host_priv *hpriv;
> > -	struct clk *clk;
> >  	struct device_node *child;
> > -	int i, enabled_ports = 0, rc = -ENOMEM, child_nodes;
> >  	u32 mask_port_map = 0;
> >  
> >  	if (!devres_open_group(dev, NULL, GFP_KERNEL))
> > @@ -415,25 +396,38 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
> >  		goto err_out;
> >  	}
> >  
> > -	for (i = 0; i < AHCI_MAX_CLKS; i++) {
> > +	/*
> > +	 * Bulk clocks getting procedure can fail to find any clock due to
> > +	 * running on a non-OF platform or due to the clocks being defined in
> > +	 * bypass of the DT firmware (like da850, spear13xx). In that case we
> > +	 * fallback to getting a single clock source right from the dev clocks
> > +	 * list.
> > +	 */
> > +	rc = devm_clk_bulk_get_all(dev, &hpriv->clks);
> > +	if (rc < 0)
> > +		goto err_out;
> > +
> > +	if (rc > 0) {
> > +		/* Got clocks in bulk */
> > +		hpriv->n_clks = rc;
> > +	} else {
> >  		/*
> > -		 * For now we must use clk_get(dev, NULL) for the first clock,
> > -		 * because some platforms (da850, spear13xx) are not yet
> > -		 * converted to use devicetree for clocks.  For new platforms
> > -		 * this is equivalent to of_clk_get(dev->of_node, 0).
> > +		 * No clock bulk found: fallback to manually getting
> > +		 * the optional clock.
> >  		 */
> > -		if (i == 0)
> > -			clk = clk_get(dev, NULL);
> > -		else
> > -			clk = of_clk_get(dev->of_node, i);
> > -
> > -		if (IS_ERR(clk)) {
> > -			rc = PTR_ERR(clk);
> > -			if (rc == -EPROBE_DEFER)
> > -				goto err_out;
> > -			break;
> > +		hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL);
> > +		if (!hpriv->clks) {
> > +			rc = -ENOMEM;
> > +			goto err_out;
> > +		}
> > +		hpriv->clks->clk = devm_clk_get_optional(dev, NULL);

> > +		if (IS_ERR(hpriv->clks->clk)) {
> > +			rc = PTR_ERR(hpriv->clks->clk);
> > +			goto err_out;
> > +		} else if (hpriv->clks->clk) {
> 
> Nit: the else is not needed here.

Well, it depends on what you see behind it. I see many reasons to keep
it and only one tiny reason to drop it. Keeping it will improve the
code readability and maintainability like having a more natural
execution flow representation, thus clearer read-flow (else part as
exception to the if part), less modifications should the goto part is
changed/removed, a more exact program flow representation can be used
by the compiler for some internal optimizations, it's one line shorter
than the case we no 'else' here. On the other hand indeed we can drop
it since if the conditional statement is true, the code afterwards
won't be executed due to the goto operator. But as I see it dropping
the else operator won't improve anything, but vise-versa will worsen
the code instead. So if I get to miss something please justify why you
want it being dropped, otherwise I would rather preserve it.

-Sergey

> 
> > +			hpriv->clks->id = __clk_get_name(hpriv->clks->clk);
> > +			hpriv->n_clks = 1;
> >  		}
> > -		hpriv->clks[i] = clk;
> >  	}
> >  
> >  	hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 08/23] ata: libahci_platform: Sanity check the DT child nodes number
  2022-06-14  8:23   ` Damien Le Moal
@ 2022-06-15 20:53     ` Serge Semin
  2022-06-16  0:25       ` Damien Le Moal
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-15 20:53 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Tue, Jun 14, 2022 at 05:23:33PM +0900, Damien Le Moal wrote:
> On 6/10/22 17:17, Serge Semin wrote:
> > Having greater than AHCI_MAX_PORTS (32) ports detected isn't that critical
> > from the further AHCI-platform initialization point of view since
> > exceeding the ports upper limit will cause allocating more resources than
> > will be used afterwards. But detecting too many child DT-nodes doesn't
> > seem right since it's very unlikely to have it on an ordinary platform. In
> > accordance with the AHCI specification there can't be more than 32 ports
> > implemented at least due to having the CAP.NP field of 5 bits wide and the
> > PI register of dword size. Thus if such situation is found the DTB must
> > have been corrupted and the data read from it shouldn't be reliable. Let's
> > consider that as an erroneous situation and halt further resources
> > allocation.
> > 
> > Note it's logically more correct to have the nports set only after the
> > initialization value is checked for being sane. So while at it let's make
> > sure nports is assigned with a correct value.
> > 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > Reviewed-by: Hannes Reinecke <hare@suse.de>
> > 
> > ---
> > 
> > Changelog v2:
> > - Drop the else word from the child_nodes value checking if-else-if
> >   statement (@Damien) and convert the after-else part into the ternary
> >   operator-based statement.
> > 
> > Changelog v4:
> > - Fix some logical mistakes in the patch log. (@Sergei Shtylyov)
> > ---
> >  drivers/ata/libahci_platform.c | 13 ++++++++++---
> >  1 file changed, 10 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> > index 814804582d1d..8aed7b29c7ab 100644
> > --- a/drivers/ata/libahci_platform.c
> > +++ b/drivers/ata/libahci_platform.c
> > @@ -451,15 +451,22 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
> >  		}
> >  	}
> >  
> > -	hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
> > +	/*
> > +	 * Too many sub-nodes most likely means having something wrong with
> > +	 * the firmware.
> > +	 */
> > +	child_nodes = of_get_child_count(dev->of_node);
> > +	if (child_nodes > AHCI_MAX_PORTS) {
> > +		rc = -EINVAL;
> > +		goto err_out;
> > +	}
> >  
> >  	/*
> >  	 * If no sub-node was found, we still need to set nports to
> >  	 * one in order to be able to use the
> >  	 * ahci_platform_[en|dis]able_[phys|regulators] functions.
> >  	 */
> > -	if (!child_nodes)
> > -		hpriv->nports = 1;
> > +	hpriv->nports = child_nodes ?: 1;
> 

> This change is not necessary and makes the code far less easy to read.

elaborate please. What change? What part of this change makes the code
less easy to read?

-Sergey

> 
> >  
> >  	hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
> >  	if (!hpriv->phys) {
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities
  2022-06-14  8:32   ` Damien Le Moal
@ 2022-06-15 20:58     ` Serge Semin
  2022-06-16  0:28       ` Damien Le Moal
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-15 20:58 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Tue, Jun 14, 2022 at 05:32:41PM +0900, Damien Le Moal wrote:
> On 6/10/22 17:17, Serge Semin wrote:
> > Currently not all of the Port-specific capabilities listed in the
> 
> s/listed/are listed
> 
> > PORT_CMD-enumeration. Let's extend that set with the Cold Presence
> > Detection and Mechanical Presence Switch attached to the Port flags [1] so
> > to closeup the set of the platform-specific port-capabilities flags.  Note
> > these flags are supposed to be set by the platform firmware if there is
> > one. Alternatively as we are about to do they can be set by means of the
> > OF properties.
> > 
> > While at it replace PORT_IRQ_DEV_ILCK with PORT_IRQ_DMPS and fix the
> > comment there. In accordance with [2] that IRQ flag is supposed to
> > indicate the state of the signal coming from the Mechanical Presence
> > Switch.
> > 
> > [1] Serial ATA AHCI 1.3.1 Specification, p.27
> > [2] Serial ATA AHCI 1.3.1 Specification, p.24, p.88
> > 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > Reviewed-by: Hannes Reinecke <hare@suse.de>
> > 
> > ---
> > 
> > Changelog v4:
> > - Fix the DMPS macros name in the patch log. (@Sergei Shtylyov)
> > ---
> >  drivers/ata/ahci.h | 7 ++++++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> > index 7d834deefeb9..f501531bd1b3 100644
> > --- a/drivers/ata/ahci.h
> > +++ b/drivers/ata/ahci.h
> > @@ -138,7 +138,7 @@ enum {
> >  	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
> >  
> >  	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
> > -	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
> > +	PORT_IRQ_DMPS		= (1 << 7), /* mechanical presence status */
> >  	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
> >  	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
> >  	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
> > @@ -166,6 +166,8 @@ enum {
> >  	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
> >  	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
> >  	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
> > +	PORT_CMD_CPD		= (1 << 20), /* Cold Presence Detection */
> > +	PORT_CMD_MPSP		= (1 << 19), /* Mechanical Presence Switch */
> >  	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
> >  	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
> >  	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
> > @@ -181,6 +183,9 @@ enum {
> >  	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
> >  	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
> >  
> > +	PORT_CMD_CAP		= PORT_CMD_HPCP | PORT_CMD_MPSP |
> > +				  PORT_CMD_CPD | PORT_CMD_ESP | PORT_CMD_FBSCP,
> 

> What is this one for ? A comment above it would be nice.

Isn't it obviously inferrable from the definition and the item name?

-Sergey

> 
> > +
> >  	/* PORT_FBS bits */
> >  	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
> >  	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 16/23] ata: ahci: Introduce firmware-specific caps initialization
  2022-06-14  8:42   ` Damien Le Moal
@ 2022-06-15 21:11     ` Serge Semin
  2022-06-16  0:29       ` Damien Le Moal
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-15 21:11 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Tue, Jun 14, 2022 at 05:42:35PM +0900, Damien Le Moal wrote:
> On 6/10/22 17:17, Serge Semin wrote:
> > There are systems with no BIOS or comprehensive embedded firmware which
> > could be able to properly initialize the SATA AHCI controller
> > platform-specific capabilities. In that case a good alternative to having
> > a clever bootloader is to create a device tree node with the properties
> > well describing all the AHCI-related platform specifics. All the settings
> > which are normally detected and marked as available in the HBA and its
> > ports capabilities fields [1] could be defined in the platform DTB by
> > means of a set of the dedicated properties. Such approach perfectly fits
> > to the DTB-philosophy - to provide hardware/platform description.
> > 
> > So here we suggest to extend the SATA AHCI device tree bindings with two
> > additional DT-properties:
> > 1) "hba-cap" - HBA platform generic capabilities like:
> >    - SSS - Staggered Spin-up support.
> >    - SMPS - Mechanical Presence Switch support.
> > 2) "hba-port-cap" - HBA platform port capabilities like:
> >    - HPCP - Hot Plug Capable Port.
> >    - MPSP - Mechanical Presence Switch Attached to Port.
> >    - CPD - Cold Presence Detection.
> >    - ESP - External SATA Port.
> >    - FBSCP - FIS-based Switching Capable Port.
> > All of these capabilities require to have a corresponding hardware
> > configuration. Thus it's ok to have them defined in DTB.
> > 
> > Even though the driver currently takes into account the state of the ESP
> > and FBSCP flags state only, there is nothing wrong with having all of them
> > supported by the generic AHCI library in order to have a complete OF-based
> > platform-capabilities initialization procedure. These properties will be
> > parsed in the ahci_platform_get_resources() method and their values will
> > be stored in the saved_* fields of the ahci_host_priv structure, which in
> > its turn then will be used to restore the H.CAP, H.PI and P#.CMD
> > capability fields on device init and after HBA reset.
> > 
> > Please note this modification concerns the HW-init HBA and its ports flags
> > only, which are by specification [1] are supposed to be initialized by the
> > BIOS/platform firmware/expansion ROM and which are normally declared in
> > the one-time-writable-after-reset register fields. Even though these flags
> > aren't supposed to be cleared after HBA reset some AHCI instances may
> > violate that rule so we still need to perform the fields resetting after
> > each reset. Luckily the corresponding functionality has already been
> > partly implemented in the framework of the ahci_save_initial_config() and
> > ahci_restore_initial_config() methods.
> > 
> > [1] Serial ATA AHCI 1.3.1 Specification, p. 103
> > 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > 
> > ---
> > 
> > Changelog v4:
> > - Convert the boolean properties to the bitfield DT-properties. (@Rob)
> > ---
> >  drivers/ata/ahci.h             |  1 +
> >  drivers/ata/libahci.c          | 51 ++++++++++++++++++++++++++++------
> >  drivers/ata/libahci_platform.c | 41 +++++++++++++++++++++++++--
> >  3 files changed, 82 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> > index 8b9826533ae5..0de221055961 100644
> > --- a/drivers/ata/ahci.h
> > +++ b/drivers/ata/ahci.h
> > @@ -337,6 +337,7 @@ struct ahci_host_priv {
> >  	u32			saved_cap;	/* saved initial cap */
> >  	u32			saved_cap2;	/* saved initial cap2 */
> >  	u32			saved_port_map;	/* saved initial port_map */
> > +	u32			saved_port_cap[AHCI_MAX_PORTS]; /* saved port_cap */
> >  	u32 			em_loc; /* enclosure management location */
> >  	u32			em_buf_sz;	/* EM buffer size in byte */
> >  	u32			em_msg_type;	/* EM message type */
> > diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
> > index 1ffaa5f5f21a..954386a2b500 100644
> > --- a/drivers/ata/libahci.c
> > +++ b/drivers/ata/libahci.c
> > @@ -16,6 +16,7 @@
> >   * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
> >   */
> >  
> > +#include <linux/bitops.h>
> >  #include <linux/kernel.h>
> >  #include <linux/gfp.h>
> >  #include <linux/module.h>
> > @@ -443,16 +444,28 @@ static ssize_t ahci_show_em_supported(struct device *dev,
> >  void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
> >  {
> >  	void __iomem *mmio = hpriv->mmio;
> > -	u32 cap, cap2, vers, port_map;
> > +	void __iomem *port_mmio;
> > +	unsigned long port_map;
> > +	u32 cap, cap2, vers;
> >  	int i;
> >  
> >  	/* make sure AHCI mode is enabled before accessing CAP */
> >  	ahci_enable_ahci(mmio);
> >  
> > -	/* Values prefixed with saved_ are written back to host after
> > -	 * reset.  Values without are used for driver operation.
> > +	/*
> > +	 * Values prefixed with saved_ are written back to the HBA and ports
> > +	 * registers after reset. Values without are used for driver operation.
> > +	 */
> > +
> > +	/*
> > +	 * Override HW-init HBA capability fields with the platform-specific
> > +	 * values. The rest of the HBA capabilities are defined as Read-only
> > +	 * and can't be modified in CSR anyway.
> >  	 */
> > -	hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
> > +	cap = readl(mmio + HOST_CAP);
> > +	if (hpriv->saved_cap)
> > +		cap = (cap & ~(HOST_CAP_SSS | HOST_CAP_MPS)) | hpriv->saved_cap;
> > +	hpriv->saved_cap = cap;
> >  
> >  	/* CAP2 register is only defined for AHCI 1.2 and later */
> >  	vers = readl(mmio + HOST_VERSION);
> > @@ -519,7 +532,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
> >  	/* Override the HBA ports mapping if the platform needs it */
> >  	port_map = readl(mmio + HOST_PORTS_IMPL);
> >  	if (hpriv->saved_port_map && port_map != hpriv->saved_port_map) {
> > -		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
> > +		dev_info(dev, "forcing port_map 0x%lx -> 0x%x\n",
> 

> This change is not necessary.

It is. The port_map type has been changed.

> 
> >  			 port_map, hpriv->saved_port_map);
> >  		port_map = hpriv->saved_port_map;
> >  	} else {
> > @@ -527,7 +540,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
> >  	}
> >  
> >  	if (hpriv->mask_port_map) {
> > -		dev_warn(dev, "masking port_map 0x%x -> 0x%x\n",
> > +		dev_warn(dev, "masking port_map 0x%lx -> 0x%lx\n",
> 
> Same.

ditto

> 
> >  			port_map,
> >  			port_map & hpriv->mask_port_map);
> >  		port_map &= hpriv->mask_port_map;
> > @@ -546,7 +559,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
> >  		 */
> >  		if (map_ports > ahci_nr_ports(cap)) {
> >  			dev_warn(dev,
> > -				 "implemented port map (0x%x) contains more ports than nr_ports (%u), using nr_ports\n",
> > +				 "implemented port map (0x%lx) contains more ports than nr_ports (%u), using nr_ports\n",
> 
> Same.

ditto.

> 
> >  				 port_map, ahci_nr_ports(cap));
> >  			port_map = 0;
> >  		}
> > @@ -555,12 +568,26 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
> >  	/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
> >  	if (!port_map && vers < 0x10300) {
> >  		port_map = (1 << ahci_nr_ports(cap)) - 1;
> > -		dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
> > +		dev_warn(dev, "forcing PORTS_IMPL to 0x%lx\n", port_map);
> 
> And again not needed.

and ditto.

> 
> >  
> >  		/* write the fixed up value to the PI register */
> >  		hpriv->saved_port_map = port_map;
> >  	}
> >  
> > +	/*
> > +	 * Preserve the ports capabilities defined by the platform. Note there
> > +	 * is no need in storing the rest of the P#.CMD fields since they are
> > +	 * volatile.
> > +	 */
> > +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> > +		if (hpriv->saved_port_cap[i])
> > +			continue;
> > +
> > +		port_mmio = __ahci_port_base(hpriv, i);
> > +		hpriv->saved_port_cap[i] =
> > +			readl(port_mmio + PORT_CMD) & PORT_CMD_CAP;
> > +	}
> > +
> >  	/* record values to use during operation */
> >  	hpriv->cap = cap;
> >  	hpriv->cap2 = cap2;
> > @@ -590,13 +617,21 @@ EXPORT_SYMBOL_GPL(ahci_save_initial_config);
> >  static void ahci_restore_initial_config(struct ata_host *host)
> >  {
> >  	struct ahci_host_priv *hpriv = host->private_data;
> > +	unsigned long port_map = hpriv->port_map;
> >  	void __iomem *mmio = hpriv->mmio;
> > +	void __iomem *port_mmio;
> > +	int i;
> >  
> >  	writel(hpriv->saved_cap, mmio + HOST_CAP);
> >  	if (hpriv->saved_cap2)
> >  		writel(hpriv->saved_cap2, mmio + HOST_CAP2);
> >  	writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
> >  	(void) readl(mmio + HOST_PORTS_IMPL);	/* flush */
> > +
> > +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> > +		port_mmio = __ahci_port_base(hpriv, i);
> > +		writel(hpriv->saved_port_cap[i], port_mmio + PORT_CMD);
> > +	}
> >  }
> >  
> >  static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
> > diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> > index efe640603f3f..8b542a8bc487 100644
> > --- a/drivers/ata/libahci_platform.c
> > +++ b/drivers/ata/libahci_platform.c
> > @@ -23,6 +23,7 @@
> >  #include <linux/pm_runtime.h>
> >  #include <linux/of_platform.h>
> >  #include <linux/reset.h>
> > +
> 
> white line change.

Ok. I'll drop it.

-Sergey

> 
> >  #include "ahci.h"
> >  
> >  static void ahci_host_stop(struct ata_host *host);
> > @@ -383,6 +384,34 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
> >  	return rc;
> >  }
> >  
> > +static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv,
> > +				      struct device *dev)
> > +{
> > +	struct device_node *child;
> > +	u32 port;
> > +
> > +	if (!of_property_read_u32(dev->of_node, "hba-cap", &hpriv->saved_cap))
> > +		hpriv->saved_cap &= (HOST_CAP_SSS | HOST_CAP_MPS);
> > +
> > +	of_property_read_u32(dev->of_node,
> > +			     "ports-implemented", &hpriv->saved_port_map);
> > +
> > +	for_each_child_of_node(dev->of_node, child) {
> > +		if (!of_device_is_available(child))
> > +			continue;
> > +
> > +		if (of_property_read_u32(child, "reg", &port)) {
> > +			of_node_put(child);
> > +			return -EINVAL;
> > +		}
> > +
> > +		if (!of_property_read_u32(child, "hba-port-cap", &hpriv->saved_port_cap[port]))
> > +			hpriv->saved_port_cap[port] &= PORT_CMD_CAP;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> >  /**
> >   * ahci_platform_get_resources - Get platform resources
> >   * @pdev: platform device to get resources for
> > @@ -523,9 +552,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
> >  		goto err_out;
> >  	}
> >  
> > -	of_property_read_u32(dev->of_node,
> > -			     "ports-implemented", &hpriv->saved_port_map);
> > -
> >  	if (child_nodes) {
> >  		for_each_child_of_node(dev->of_node, child) {
> >  			u32 port;
> > @@ -590,6 +616,15 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
> >  		if (rc == -EPROBE_DEFER)
> >  			goto err_out;
> >  	}
> > +
> > +	/*
> > +	 * Retrieve firmware-specific flags which then will be used to set
> > +	 * the HW-init fields of HBA and its ports
> > +	 */
> > +	rc = ahci_platform_get_firmware(hpriv, dev);
> > +	if (rc)
> > +		goto err_out;
> > +
> >  	pm_runtime_enable(dev);
> >  	pm_runtime_get_sync(dev);
> >  	hpriv->got_runtime_pm = true;
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 18/23] ata: libahci_platform: Add function returning a clock-handle by id
  2022-06-14  8:45   ` Damien Le Moal
@ 2022-06-15 21:24     ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-15 21:24 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Tue, Jun 14, 2022 at 05:45:35PM +0900, Damien Le Moal wrote:
> On 6/10/22 17:17, Serge Semin wrote:
> > Since all the clocks are retrieved by the method
> > ahci_platform_get_resources() there is no need for the LLD (glue) drivers
> > to be looking for some particular of them in the kernel clocks table
> > again. Instead we suggest to add a simple method returning a
> > device-specific clock with passed connection ID if it is managed to be
> > found. Otherwise the function will return NULL. Thus the glue-drivers
> > won't need to either manually touching the hpriv->clks array or calling
> > clk_get()-friends. The AHCI platform drivers will be able to use the new
> > function right after the ahci_platform_get_resources() method invocation
> > and up to the device removal.
> > 
> > Note the method is left unused here, but will be utilized in the framework
> > of the DWC AHCI SATA driver being added in the next commit.
> > 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > 
> > ---
> > 
> > Changelog v2:
> > - Fix some grammar mistakes in the method description.
> > 
> > Changelog v4:
> > - Add a note regarding the new method usage.
> > ---
> >  drivers/ata/libahci_platform.c | 27 +++++++++++++++++++++++++++
> >  include/linux/ahci_platform.h  |  3 +++
> >  2 files changed, 30 insertions(+)
> > 
> > diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> > index 8b542a8bc487..418961f954af 100644
> > --- a/drivers/ata/libahci_platform.c
> > +++ b/drivers/ata/libahci_platform.c
> > @@ -95,6 +95,33 @@ void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
> >  }
> >  EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
> >  
> > +/**
> > + * ahci_platform_find_clk - Find platform clock
> > + * @hpriv: host private area to store config values
> > + * @con_id: clock connection ID
> > + *
> > + * This function returns a pointer to the clock descriptor of the clock with
> > + * the passed ID.
> > + *
> > + * RETURNS:
> > + * Pointer to the clock descriptor on success otherwise NULL
> > + */
> > +struct clk *ahci_platform_find_clk(struct ahci_host_priv *hpriv, const char *con_id)
> > +{
> > +	struct clk *clk = NULL;
> > +	int i;
> > +
> > +	for (i = 0; i < hpriv->n_clks; i++) {
> > +		if (!strcmp(hpriv->clks[i].id, con_id)) {
> > +			clk = hpriv->clks[i].clk;
> 
> 			return hpriv->clks[i].clk;
> 
> > +			break;
> > +		}
> > +	}
> > +
> > +	return clk;
> 

> And then "return NULL;" here and you do not need the clk variable.

Ok.

> 
> > +}
> > +EXPORT_SYMBOL_GPL(ahci_platform_find_clk);
> > +
> >  /**
> >   * ahci_platform_enable_clks - Enable platform clocks
> >   * @hpriv: host private area to store config values
> > diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
> > index 6d7dd472d370..3418980b0341 100644
> > --- a/include/linux/ahci_platform.h
> > +++ b/include/linux/ahci_platform.h
> > @@ -13,6 +13,7 @@
> >  
> >  #include <linux/compiler.h>
> >  
> > +struct clk;
> >  struct device;
> >  struct ata_port_info;
> >  struct ahci_host_priv;
> > @@ -21,6 +22,8 @@ struct scsi_host_template;
> >  
> >  int ahci_platform_enable_phys(struct ahci_host_priv *hpriv);
> >  void ahci_platform_disable_phys(struct ahci_host_priv *hpriv);
> > +struct clk *
> > +ahci_platform_find_clk(struct ahci_host_priv *hpriv, const char *con_id);
> 

> Please make this:
> 
> struct clk *ahci_platform_find_clk(struct ahci_host_priv *hpriv,
> 
>                                    const char *con_id);

Ok.

-Sergey

> 
> >  int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
> >  void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
> >  int ahci_platform_deassert_rsts(struct ahci_host_priv *hpriv);
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 15/23] ata: ahci: Convert __ahci_port_base to accepting hpriv as arguments
  2022-06-14  8:38   ` Damien Le Moal
@ 2022-06-15 21:25     ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-15 21:25 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Tue, Jun 14, 2022 at 05:38:14PM +0900, Damien Le Moal wrote:
> On 6/10/22 17:17, Serge Semin wrote:
> > It may get required to retrieve the port-base address even before the
> 
> The port base address may be required even before the...
> 
> > ata_host instance is initialized and activated, for instance in the
> > ahci_save_initial_config() method which we about to update (consider this
> 
> s/we/we are

Got it. will be fixed in v5.

-Sergey

> 
> > modification as a preparation for that one). Seeing the __ahci_port_base()
> > function isn't used much it's the best candidate to provide the required
> > functionality. So let's convert it to accepting the ahci_host_priv
> > structure pointer.
> > 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > Reviewed-by: Hannes Reinecke <hare@suse.de>
> > ---
> >  drivers/ata/ahci.c | 2 +-
> >  drivers/ata/ahci.h | 7 ++++---
> >  2 files changed, 5 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
> > index 9bc8fa77e92f..d14d74649e0e 100644
> > --- a/drivers/ata/ahci.c
> > +++ b/drivers/ata/ahci.c
> > @@ -689,7 +689,7 @@ static void ahci_pci_init_controller(struct ata_host *host)
> >  			mv = 2;
> >  		else
> >  			mv = 4;
> > -		port_mmio = __ahci_port_base(host, mv);
> > +		port_mmio = __ahci_port_base(hpriv, mv);
> >  
> >  		writel(0, port_mmio + PORT_IRQ_MASK);
> >  
> > diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> > index 0e66446a5883..8b9826533ae5 100644
> > --- a/drivers/ata/ahci.h
> > +++ b/drivers/ata/ahci.h
> > @@ -431,10 +431,9 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht);
> >  void ahci_error_handler(struct ata_port *ap);
> >  u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked);
> >  
> > -static inline void __iomem *__ahci_port_base(struct ata_host *host,
> > +static inline void __iomem *__ahci_port_base(struct ahci_host_priv *hpriv,
> >  					     unsigned int port_no)
> >  {
> > -	struct ahci_host_priv *hpriv = host->private_data;
> >  	void __iomem *mmio = hpriv->mmio;
> >  
> >  	return mmio + 0x100 + (port_no * 0x80);
> > @@ -442,7 +441,9 @@ static inline void __iomem *__ahci_port_base(struct ata_host *host,
> >  
> >  static inline void __iomem *ahci_port_base(struct ata_port *ap)
> >  {
> > -	return __ahci_port_base(ap->host, ap->port_no);
> > +	struct ahci_host_priv *hpriv = ap->host->private_data;
> > +
> > +	return __ahci_port_base(hpriv, ap->port_no);
> >  }
> >  
> >  static inline int ahci_nr_ports(u32 cap)
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-10 23:34       ` Randy Dunlap
@ 2022-06-15 21:30         ` Serge Semin
  2022-06-16  0:31           ` Damien Le Moal
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-15 21:30 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

On Fri, Jun 10, 2022 at 04:34:13PM -0700, Randy Dunlap wrote:
> Hi Serge,
> 
> On 6/10/22 14:58, Serge Semin wrote:
> > On Fri, Jun 10, 2022 at 09:34:46AM -0700, Randy Dunlap wrote:
> >> Hi--
> > 
> > Hi Randy
> > 
> >>
> >> On 6/10/22 01:17, Serge Semin wrote:
> >>> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> >>> index bb45a9c00514..95e0e022b5bb 100644
> >>> --- a/drivers/ata/Kconfig
> >>> +++ b/drivers/ata/Kconfig
> >>> @@ -176,6 +176,16 @@ config AHCI_DM816
> >>>  
> >>>  	  If unsure, say N.
> >>>  
> >>> +config AHCI_DWC
> >>> +	tristate "Synopsys DWC AHCI SATA support"
> >>> +	select SATA_HOST
> >>> +	default SATA_AHCI_PLATFORM
> >>
> > 
> >> I don't think this needs to default to SATA_AHCI_PLATFORM.
> >> It might build a driver that isn't needed.
> >> And it's incompatible with "If unsure, say N."
> > 
> > Basically you are right, but this particular setting is connected with
> > the modification I've done in the drivers/ata/ahci_platform.c driver
> > in the framework of this commit. I've moved the "snps,spear-ahci" and
> > "snps,dwc-ahci" compatible devices support to the new driver. Thus
> > should I omit the SATA_AHCI_PLATFORM dependency their default kernel
> > configs will lack the corresponding controllers support. If it's not a
> > problem and we can rely on the kernel build system ability to ask
> > whether the new config needs to be set/cleared, then I would be very
> > happy to drop the default setting. What do you think?
> 

> I'd prefer to try it like that.
> If it becomes a problem, we can go back to this v4 patch.

Agreed then (seeing Damien is silent about your comment).

-Sergey

> 
> >>> +	help
> >>> +	  This option enables support for the Synopsys DWC AHCI SATA
> >>> +	  controller implementation.
> >>> +
> >>> +	  If unsure, say N.
> >>
> >> -- 
> >> ~Randy
> 
> Thanks.
> -- 
> ~Randy

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-14  8:53   ` Damien Le Moal
@ 2022-06-15 21:48     ` Serge Semin
  2022-06-16  0:33       ` Damien Le Moal
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-15 21:48 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Tue, Jun 14, 2022 at 05:53:39PM +0900, Damien Le Moal wrote:
> On 6/10/22 17:17, Serge Semin wrote:
> > Synopsys AHCI SATA controller can work pretty under with the generic
> > AHCI-platform driver control. But there are vendor-specific peculiarities
> > which can tune the device performance up and which may need to be fixed up
> > for proper device functioning. In addition some DWC AHCI-based controllers
> > may require small platform-specific fixups, so adding them in the generic
> > AHCI driver would have ruined the code simplicity. Shortly speaking in
> > order to keep the generic AHCI-platform code clean and have DWC AHCI
> > SATA-specific features supported we suggest to add a dedicated DWC AHCI
> > SATA device driver. Aside with the standard AHCI-platform resources
> > getting, enabling/disabling and the controller registration the new driver
> > performs the next actions.
> > 
> > First of all there is a way to verify whether the HBA/ports capabilities
> > activated in OF are correct. Almost all features availability is reflected
> > in the vendor-specific parameters registers. So the DWC AHCI driver does
> > the capabilities sanity check based on the corresponding fields state.
> > 
> > Secondly if either the Command Completion Coalescing or the Device Sleep
> > feature is enabled the DWC AHCI-specific internal 1ms timer must be fixed
> > in accordance with the application clock signal frequency. In particular
> > the timer value must be set to be Fapp * 1000. Normally the SoC designers
> > pre-configure the TIMER1MS register to contain a correct value by default.
> > But the platforms can support the application clock rate change. If that
> > happens the 1ms timer value must be accordingly updated otherwise the
> > dependent features won't work as expected. In the DWC AHCI driver we
> > suggest to rely on the "aclk" reference clock rate to set the timer
> > interval up. That clock source is supposed to be the AHCI SATA application
> > clock in accordance with the DT bindings.
> > 
> > Finally DWC AHCI SATA controller AXI/AHB bus DMA-engine can be tuned up to
> > transfer up to 1024 * FIFO words at a time by setting the Tx/Rx
> > transaction size in the DMA control register. The maximum value depends on
> > the DMA data bus and AXI/AHB bus maximum burst length. In most of the
> > cases it's better to set the maximum possible value to reach the best AHCI
> > SATA controller performance. But sometimes in order to improve the system
> > interconnect responsiveness, transferring in smaller data chunks may be
> > more preferable. For such cases and for the case when the default value
> > doesn't provide the best DMA bus performance we suggest to use the new
> > HBA-port specific DT-properties "snps,{tx,rx}-ts-max" to tune the DMA
> > transactions size up.
> > 
> > After all the settings denoted above are handled the DWC AHCI SATA driver
> > proceeds further with the standard AHCI-platform host initializations.
> > 
> > Note since DWC AHCI controller is now have a dedicated driver we can
> > discard the corresponding compatible string from the ahci-platform.c
> > module. The same concerns "snps,spear-ahci" compatible string, which is
> > also based on the DWC AHCI IP-core.
> > 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > Reviewed-by: Hannes Reinecke <hare@suse.de>
> > 
> > ---
> > 
> > Note there are three more AHCI SATA drivers which have been created for
> > the devices based on the DWC AHCI SATA IP-core. It's AHCI SunXi, St and
> > iMX drivers. Mostly they don't support the features implemented in this
> > driver. So hopefully sometime in future they can be converted to be based
> > on the generic DWC AHCI SATA driver and just perform some
> > subvendor-specific setups in their own LLDD (glue) driver code. But for
> > now let's leave the generic DWC AHCI SATA code as is. Hopefully the new
> > DWC AHCI-based device drivers will try at least to re-use a part of the
> > DWC AHCI driver methods if not being able to be integrated in the generic
> > DWC driver code.
> > 
> > Changelog v2:
> > - Change the local objects prefix from 'dwc_ahci_' to 'ahci_dwc_'.
> >   (@Damien)
> > 
> > Changelog v4:
> > - Replace GPLv2 with just GPL license which are the same in the framework
> >   of the MODULE_LICENSE() macro.
> > ---
> >  drivers/ata/Kconfig         |  10 +
> >  drivers/ata/Makefile        |   1 +
> >  drivers/ata/ahci_dwc.c      | 395 ++++++++++++++++++++++++++++++++++++
> >  drivers/ata/ahci_platform.c |   2 -
> >  4 files changed, 406 insertions(+), 2 deletions(-)
> >  create mode 100644 drivers/ata/ahci_dwc.c
> > 
> > diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> > index bb45a9c00514..95e0e022b5bb 100644
> > --- a/drivers/ata/Kconfig
> > +++ b/drivers/ata/Kconfig
> > @@ -176,6 +176,16 @@ config AHCI_DM816
> >  
> >  	  If unsure, say N.
> >  
> > +config AHCI_DWC
> > +	tristate "Synopsys DWC AHCI SATA support"
> > +	select SATA_HOST
> > +	default SATA_AHCI_PLATFORM
> > +	help
> > +	  This option enables support for the Synopsys DWC AHCI SATA
> > +	  controller implementation.
> > +
> > +	  If unsure, say N.
> > +
> >  config AHCI_ST
> >  	tristate "ST AHCI SATA support"
> >  	depends on ARCH_STI
> > diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
> > index b8aebfb14e82..34623365d9a6 100644
> > --- a/drivers/ata/Makefile
> > +++ b/drivers/ata/Makefile
> > @@ -17,6 +17,7 @@ obj-$(CONFIG_AHCI_BRCM)		+= ahci_brcm.o libahci.o libahci_platform.o
> >  obj-$(CONFIG_AHCI_CEVA)		+= ahci_ceva.o libahci.o libahci_platform.o
> >  obj-$(CONFIG_AHCI_DA850)	+= ahci_da850.o libahci.o libahci_platform.o
> >  obj-$(CONFIG_AHCI_DM816)	+= ahci_dm816.o libahci.o libahci_platform.o
> > +obj-$(CONFIG_AHCI_DWC)		+= ahci_dwc.o libahci.o libahci_platform.o
> >  obj-$(CONFIG_AHCI_IMX)		+= ahci_imx.o libahci.o libahci_platform.o
> >  obj-$(CONFIG_AHCI_MTK)		+= ahci_mtk.o libahci.o libahci_platform.o
> >  obj-$(CONFIG_AHCI_MVEBU)	+= ahci_mvebu.o libahci.o libahci_platform.o
> > diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c
> > new file mode 100644
> > index 000000000000..8c2510933a31
> > --- /dev/null
> > +++ b/drivers/ata/ahci_dwc.c
> > @@ -0,0 +1,395 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * DWC AHCI SATA Platform driver
> > + *
> > + * Copyright (C) 2021 BAIKAL ELECTRONICS, JSC
> > + */
> > +
> > +#include <linux/ahci_platform.h>
> > +#include <linux/bitfield.h>
> > +#include <linux/bits.h>
> > +#include <linux/clk.h>
> > +#include <linux/device.h>
> > +#include <linux/kernel.h>
> > +#include <linux/libata.h>
> > +#include <linux/log2.h>
> > +#include <linux/module.h>
> > +#include <linux/of_device.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pm.h>
> > +
> > +#include "ahci.h"
> > +
> > +#define DRV_NAME "ahci-dwc"
> > +
> > +#define AHCI_DWC_FBS_PMPN_MAX		15
> > +
> > +/* DWC AHCI SATA controller specific registers */
> > +#define AHCI_DWC_HOST_OOBR		0xbc
> > +#define AHCI_DWC_HOST_OOB_WE		BIT(31)
> > +#define AHCI_DWC_HOST_CWMIN_MASK	GENMASK(30, 24)
> > +#define AHCI_DWC_HOST_CWMAX_MASK	GENMASK(23, 16)
> > +#define AHCI_DWC_HOST_CIMIN_MASK	GENMASK(15, 8)
> > +#define AHCI_DWC_HOST_CIMAX_MASK	GENMASK(7, 0)
> > +
> > +#define AHCI_DWC_HOST_GPCR		0xd0
> > +#define AHCI_DWC_HOST_GPSR		0xd4
> > +
> > +#define AHCI_DWC_HOST_TIMER1MS		0xe0
> > +#define AHCI_DWC_HOST_TIMV_MASK		GENMASK(19, 0)
> > +
> > +#define AHCI_DWC_HOST_GPARAM1R		0xe8
> > +#define AHCI_DWC_HOST_ALIGN_M		BIT(31)
> > +#define AHCI_DWC_HOST_RX_BUFFER		BIT(30)
> > +#define AHCI_DWC_HOST_PHY_DATA_MASK	GENMASK(29, 28)
> > +#define AHCI_DWC_HOST_PHY_RST		BIT(27)
> > +#define AHCI_DWC_HOST_PHY_CTRL_MASK	GENMASK(26, 21)
> > +#define AHCI_DWC_HOST_PHY_STAT_MASK	GENMASK(20, 15)
> > +#define AHCI_DWC_HOST_LATCH_M		BIT(14)
> > +#define AHCI_DWC_HOST_PHY_TYPE_MASK	GENMASK(13, 11)
> > +#define AHCI_DWC_HOST_RET_ERR		BIT(10)
> > +#define AHCI_DWC_HOST_AHB_ENDIAN_MASK	GENMASK(9, 8)
> > +#define AHCI_DWC_HOST_S_HADDR		BIT(7)
> > +#define AHCI_DWC_HOST_M_HADDR		BIT(6)
> > +#define AHCI_DWC_HOST_S_HDATA_MASK	GENMASK(5, 3)
> > +#define AHCI_DWC_HOST_M_HDATA_MASK	GENMASK(2, 0)
> > +
> > +#define AHCI_DWC_HOST_GPARAM2R		0xec
> > +#define AHCI_DWC_HOST_FBS_MEM_S		BIT(19)
> > +#define AHCI_DWC_HOST_FBS_PMPN_MASK	GENMASK(17, 16)
> > +#define AHCI_DWC_HOST_FBS_SUP		BIT(15)
> > +#define AHCI_DWC_HOST_DEV_CP		BIT(14)
> > +#define AHCI_DWC_HOST_DEV_MP		BIT(13)
> > +#define AHCI_DWC_HOST_ENCODE_M		BIT(12)
> > +#define AHCI_DWC_HOST_RXOOB_CLK_M	BIT(11)
> > +#define AHCI_DWC_HOST_RXOOB_M		BIT(10)
> > +#define AHCI_DWC_HOST_TXOOB_M		BIT(9)
> > +#define AHCI_DWC_HOST_RXOOB_M		BIT(10)
> > +#define AHCI_DWC_HOST_RXOOB_CLK_MASK	GENMASK(8, 0)
> > +
> > +#define AHCI_DWC_HOST_PPARAMR		0xf0
> > +#define AHCI_DWC_HOST_TX_MEM_M		BIT(11)
> > +#define AHCI_DWC_HOST_TX_MEM_S		BIT(10)
> > +#define AHCI_DWC_HOST_RX_MEM_M		BIT(9)
> > +#define AHCI_DWC_HOST_RX_MEM_S		BIT(8)
> > +#define AHCI_DWC_HOST_TXFIFO_DEPTH	GENMASK(7, 4)
> > +#define AHCI_DWC_HOST_RXFIFO_DEPTH	GENMASK(3, 0)
> > +
> > +#define AHCI_DWC_HOST_TESTR		0xf4
> > +#define AHCI_DWC_HOST_PSEL_MASK		GENMASK(18, 16)
> > +#define AHCI_DWC_HOST_TEST_IF		BIT(0)
> > +
> > +#define AHCI_DWC_HOST_VERSIONR		0xf8
> > +#define AHCI_DWC_HOST_IDR		0xfc
> > +
> > +#define AHCI_DWC_PORT_DMACR		0x70
> > +#define AHCI_DWC_PORT_RXABL_MASK	GENMASK(15, 12)
> > +#define AHCI_DWC_PORT_TXABL_MASK	GENMASK(11, 8)
> > +#define AHCI_DWC_PORT_RXTS_MASK		GENMASK(7, 4)
> > +#define AHCI_DWC_PORT_TXTS_MASK		GENMASK(3, 0)
> > +#define AHCI_DWC_PORT_PHYCR		0x74
> > +#define AHCI_DWC_PORT_PHYSR		0x78
> > +
> > +struct ahci_dwc_host_priv {
> > +	struct platform_device *pdev;
> > +
> > +	u32 timv;
> > +	u32 dmacr[AHCI_MAX_PORTS];
> > +};
> > +
> > +static struct ahci_host_priv *ahci_dwc_get_resources(struct platform_device *pdev)
> > +{
> > +	struct ahci_dwc_host_priv *dpriv;
> > +	struct ahci_host_priv *hpriv;
> > +
> > +	dpriv = devm_kzalloc(&pdev->dev, sizeof(*dpriv), GFP_KERNEL);
> > +	if (!dpriv)
> > +		return ERR_PTR(-ENOMEM);
> > +
> > +	dpriv->pdev = pdev;
> > +
> > +	hpriv = ahci_platform_get_resources(pdev, AHCI_PLATFORM_GET_RESETS);
> > +	if (IS_ERR(hpriv))
> > +		return hpriv;
> > +
> > +	hpriv->plat_data = (void *)dpriv;
> > +
> > +	return hpriv;
> > +}
> > +
> > +static void ahci_dwc_check_cap(struct ahci_host_priv *hpriv)
> > +{
> > +	unsigned long port_map = hpriv->saved_port_map | hpriv->mask_port_map;
> > +	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
> > +	bool dev_mp, dev_cp, fbs_sup;
> > +	unsigned int fbs_pmp;
> > +	u32 param;
> > +	int i;
> > +
> > +	param = readl(hpriv->mmio + AHCI_DWC_HOST_GPARAM2R);
> > +	dev_mp = !!(param & AHCI_DWC_HOST_DEV_MP);
> > +	dev_cp = !!(param & AHCI_DWC_HOST_DEV_CP);
> > +	fbs_sup = !!(param & AHCI_DWC_HOST_FBS_SUP);
> > +	fbs_pmp = 5 * FIELD_GET(AHCI_DWC_HOST_FBS_PMPN_MASK, param);
> > +
> > +	if (!dev_mp && hpriv->saved_cap & HOST_CAP_MPS) {
> > +		dev_warn(&dpriv->pdev->dev, "MPS is unsupported\n");
> > +		hpriv->saved_cap &= ~HOST_CAP_MPS;
> > +	}
> > +
> > +
> > +	if (fbs_sup && fbs_pmp < AHCI_DWC_FBS_PMPN_MAX) {
> > +		dev_warn(&dpriv->pdev->dev, "PMPn is limited up to %u ports\n",
> > +			 fbs_pmp);
> > +	}
> > +
> > +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> > +		if (!dev_mp && hpriv->saved_port_cap[i] & PORT_CMD_MPSP) {
> > +			dev_warn(&dpriv->pdev->dev, "MPS incapable port %d\n", i);
> > +			hpriv->saved_port_cap[i] &= ~PORT_CMD_MPSP;
> > +		}
> > +
> > +		if (!dev_cp && hpriv->saved_port_cap[i] & PORT_CMD_CPD) {
> > +			dev_warn(&dpriv->pdev->dev, "CPD incapable port %d\n", i);
> > +			hpriv->saved_port_cap[i] &= ~PORT_CMD_CPD;
> > +		}
> > +
> > +		if (!fbs_sup && hpriv->saved_port_cap[i] & PORT_CMD_FBSCP) {
> > +			dev_warn(&dpriv->pdev->dev, "FBS incapable port %d\n", i);
> > +			hpriv->saved_port_cap[i] &= ~PORT_CMD_FBSCP;
> > +		}
> > +	}
> > +}
> > +
> > +static void ahci_dwc_init_timer(struct ahci_host_priv *hpriv)
> > +{
> > +	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
> > +	unsigned long rate;
> > +	struct clk *aclk;
> > +	u32 cap, cap2;
> > +
> > +	/* 1ms tick is generated only for the CCC or DevSleep features */
> > +	cap = readl(hpriv->mmio + HOST_CAP);
> > +	cap2 = readl(hpriv->mmio + HOST_CAP2);
> > +	if (!(cap & HOST_CAP_CCC) && !(cap2 & HOST_CAP2_SDS))
> > +		return;
> > +
> > +	/*
> > +	 * Tick is generated based on the AXI/AHB application clocks signal
> > +	 * so we need to be sure in the clock we are going to use.
> > +	 */
> > +	aclk = ahci_platform_find_clk(hpriv, "aclk");
> > +	if (!aclk)
> > +		return;
> > +
> > +	/* 1ms timer interval is set as TIMV = AMBA_FREQ[MHZ] * 1000 */
> > +	dpriv->timv = readl(hpriv->mmio + AHCI_DWC_HOST_TIMER1MS);
> > +	dpriv->timv = FIELD_GET(AHCI_DWC_HOST_TIMV_MASK, dpriv->timv);
> > +	rate = clk_get_rate(aclk) / 1000UL;
> > +	if (rate == dpriv->timv)
> > +		return;
> > +
> > +	dev_info(&dpriv->pdev->dev, "Update CCC/DevSlp timer for Fapp %lu MHz\n",
> > +		 rate / 1000UL);
> > +	dpriv->timv = FIELD_PREP(AHCI_DWC_HOST_TIMV_MASK, rate);
> > +	writel(dpriv->timv, hpriv->mmio + AHCI_DWC_HOST_TIMER1MS);
> > +}
> > +
> > +static int ahci_dwc_init_dmacr(struct ahci_host_priv *hpriv)
> > +{
> > +	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
> > +	struct device_node *child;
> > +	void __iomem *port_mmio;
> > +	u32 port, dmacr, ts;
> > +
> > +	/*
> > +	 * Update the DMA Tx/Rx transaction sizes in accordance with the
> > +	 * platform setup. Note values exceeding maximal or minimal limits will
> > +	 * be automatically clamped. Also note the register isn't affected by
> > +	 * the HBA global reset so we can freely initialize it once until the
> > +	 * next system reset.
> > +	 */
> > +	for_each_child_of_node(dpriv->pdev->dev.of_node, child) {
> > +		if (!of_device_is_available(child))
> > +			continue;
> > +
> > +		if (of_property_read_u32(child, "reg", &port)) {
> > +			of_node_put(child);
> > +			return -EINVAL;
> > +		}
> > +
> > +		port_mmio = __ahci_port_base(hpriv, port);
> > +		dmacr = readl(port_mmio + AHCI_DWC_PORT_DMACR);
> > +
> > +		if (!of_property_read_u32(child, "snps,tx-ts-max", &ts)) {
> > +			ts = ilog2(ts);
> > +			dmacr &= ~AHCI_DWC_PORT_TXTS_MASK;
> > +			dmacr |= FIELD_PREP(AHCI_DWC_PORT_TXTS_MASK, ts);
> > +		}
> > +
> > +		if (!of_property_read_u32(child, "snps,rx-ts-max", &ts)) {
> > +			ts = ilog2(ts);
> > +			dmacr &= ~AHCI_DWC_PORT_RXTS_MASK;
> > +			dmacr |= FIELD_PREP(AHCI_DWC_PORT_RXTS_MASK, ts);
> > +		}
> > +
> > +		writel(dmacr, port_mmio + AHCI_DWC_PORT_DMACR);
> > +		dpriv->dmacr[port] = dmacr;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int ahci_dwc_init_host(struct ahci_host_priv *hpriv)
> > +{
> > +	int rc;
> > +
> > +	rc = ahci_platform_enable_resources(hpriv);
> > +	if (rc)
> > +		return rc;
> > +
> > +	ahci_dwc_check_cap(hpriv);
> > +
> > +	ahci_dwc_init_timer(hpriv);
> > +
> > +	rc = ahci_dwc_init_dmacr(hpriv);
> > +	if (rc)
> > +		goto err_disable_resources;
> > +
> > +	return 0;
> > +
> > +err_disable_resources:
> > +	ahci_platform_disable_resources(hpriv);
> > +
> > +	return rc;
> > +}
> > +
> > +static int ahci_dwc_reinit_host(struct ahci_host_priv *hpriv)
> > +{
> > +	struct ahci_dwc_host_priv *dpriv = hpriv->plat_data;
> > +	unsigned long port_map = hpriv->port_map;
> > +	void __iomem *port_mmio;
> > +	int i, rc;
> > +
> > +	rc = ahci_platform_enable_resources(hpriv);
> > +	if (rc)
> > +		return rc;
> > +
> > +	writel(dpriv->timv, hpriv->mmio + AHCI_DWC_HOST_TIMER1MS);
> > +
> > +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> > +		port_mmio = __ahci_port_base(hpriv, i);
> > +		writel(dpriv->dmacr[i], port_mmio + AHCI_DWC_PORT_DMACR);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void ahci_dwc_clear_host(struct ahci_host_priv *hpriv)
> > +{
> > +	ahci_platform_disable_resources(hpriv);
> > +}
> > +
> > +static void ahci_dwc_stop_host(struct ata_host *host)
> > +{
> > +	struct ahci_host_priv *hpriv = host->private_data;
> > +
> > +	ahci_dwc_clear_host(hpriv);
> > +}
> > +
> > +static struct ata_port_operations ahci_dwc_port_ops = {
> > +	.inherits	= &ahci_platform_ops,
> > +	.host_stop	= ahci_dwc_stop_host,
> > +};
> > +
> > +static const struct ata_port_info ahci_dwc_port_info = {
> > +	.flags		= AHCI_FLAG_COMMON,
> > +	.pio_mask	= ATA_PIO4,
> > +	.udma_mask	= ATA_UDMA6,
> > +	.port_ops	= &ahci_dwc_port_ops,
> > +};
> > +
> > +static struct scsi_host_template ahci_dwc_scsi_info = {
> > +	AHCI_SHT(DRV_NAME),
> > +};
> > +
> > +static int ahci_dwc_probe(struct platform_device *pdev)
> > +{
> > +	struct ahci_host_priv *hpriv;
> > +	int rc;
> > +
> > +	hpriv = ahci_dwc_get_resources(pdev);
> > +	if (IS_ERR(hpriv))
> > +		return PTR_ERR(hpriv);
> > +
> > +	rc = ahci_dwc_init_host(hpriv);
> > +	if (rc)
> > +		return rc;
> > +
> > +	rc = ahci_platform_init_host(pdev, hpriv, &ahci_dwc_port_info,
> > +				     &ahci_dwc_scsi_info);
> > +	if (rc)
> > +		goto err_clear_host;
> > +
> > +	return 0;
> > +
> > +err_clear_host:
> > +	ahci_dwc_clear_host(hpriv);
> > +
> > +	return rc;
> > +}
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int ahci_dwc_suspend(struct device *dev)
> > +{
> > +	struct ata_host *host = dev_get_drvdata(dev);
> > +	struct ahci_host_priv *hpriv = host->private_data;
> > +	int rc;
> > +
> > +	rc = ahci_platform_suspend_host(dev);
> > +	if (rc)
> > +		return rc;
> > +
> > +	ahci_dwc_clear_host(hpriv);
> > +
> > +	return 0;
> > +}
> > +
> > +static int ahci_dwc_resume(struct device *dev)
> > +{
> > +	struct ata_host *host = dev_get_drvdata(dev);
> > +	struct ahci_host_priv *hpriv = host->private_data;
> > +	int rc;
> > +
> > +	rc = ahci_dwc_reinit_host(hpriv);
> > +	if (rc)
> > +		return rc;
> > +
> > +	return ahci_platform_resume_host(dev);
> > +}
> > +#endif
> > +
> > +static SIMPLE_DEV_PM_OPS(ahci_dwc_pm_ops, ahci_dwc_suspend, ahci_dwc_resume);
> 

> include/linux/pm.h says:
> /* Deprecated. Use DEFINE_SIMPLE_DEV_PM_OPS() instead. */

Ok.

> 
> > +
> > +static const struct of_device_id ahci_dwc_of_match[] = {
> > +	{ .compatible = "snps,dwc-ahci", },
> > +	{ .compatible = "snps,spear-ahci", },
> > +	{},
> > +};
> > +MODULE_DEVICE_TABLE(of, ahci_dwc_of_match);
> > +
> > +static struct platform_driver ahci_dwc_driver = {
> > +	.probe = ahci_dwc_probe,
> > +	.remove = ata_platform_remove_one,
> > +	.shutdown = ahci_platform_shutdown,
> > +	.driver = {
> > +		.name = DRV_NAME,
> > +		.of_match_table = ahci_dwc_of_match,
> > +		.pm = &ahci_dwc_pm_ops,
> > +	},
> > +};
> > +module_platform_driver(ahci_dwc_driver);
> > +
> > +MODULE_DESCRIPTION("DWC AHCI SATA platform driver");
> > +MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
> > +MODULE_LICENSE("GPL");
> 

> MODULE_LICENSE("GPL v2");
> 
> To match the file header SPDX.

No. Please see the commit bf7fbeeae6db ("module: Cure the
MODULE_LICENSE "GPL" vs. "GPL v2" bogosity") and what checkpatch.pl
says should the "GPL v2" string is used in the module license block.
More info regarding this macro and the possible license values are
described here:
Documentation/process/license-rules.rst

-Sergey

> 
> > diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
> > index 9b56490ecbc3..8f5572a9f8f1 100644
> > --- a/drivers/ata/ahci_platform.c
> > +++ b/drivers/ata/ahci_platform.c
> > @@ -80,9 +80,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
> >  static const struct of_device_id ahci_of_match[] = {
> >  	{ .compatible = "generic-ahci", },
> >  	/* Keep the following compatibles for device tree compatibility */
> > -	{ .compatible = "snps,spear-ahci", },
> >  	{ .compatible = "ibm,476gtr-ahci", },
> > -	{ .compatible = "snps,dwc-ahci", },
> >  	{ .compatible = "hisilicon,hisi-ahci", },
> >  	{ .compatible = "cavium,octeon-7130-ahci", },
> >  	{ /* sentinel */ }
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 11/23] dt-bindings: ata: ahci: Add platform capability properties
  2022-06-14 22:19   ` Rob Herring
@ 2022-06-15 21:56     ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-15 21:56 UTC (permalink / raw)
  To: Rob Herring
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Krzysztof Kozlowski, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

On Tue, Jun 14, 2022 at 04:19:17PM -0600, Rob Herring wrote:
> On Fri, Jun 10, 2022 at 11:17:49AM +0300, Serge Semin wrote:
> > In case if the platform doesn't have BIOS or a comprehensive firmware
> > installed then the HBA capability flags will be left uninitialized. As a
> > good alternative we suggest to define the DT-properties with the AHCI
> > platform capabilities describing all the HW-init flags of the
> > corresponding capability register. Luckily there aren't too many of them.
> > SSS - Staggered Spin-up support and MPS - Mechanical Presence Switch
> > support determine the corresponding feature availability for the whole HBA
> > by means of the "hba-cap" property. Each port can have the "hba-port-cap"
> > property initialized indicating that the port supports some of the next
> > functionalities: HPCP - HotPlug capable port, MPSP - Mechanical Presence
> > Switch attached to a port, CPD - Cold Plug detection, ESP - External SATA
> > Port (eSATA), FBSCP - FIS-based switching capable port.
> > 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > 
> > ---
> > 
> > Changelog v4:
> > - Fix some misspelling in the patch log.
> > - Convert the boolean properties to the bitfield properties. (@Rob)
> > - Remove Hannes' rb tag due to the patch content change.
> > ---
> >  .../devicetree/bindings/ata/ahci-common.yaml  | 16 +++++++++++++++
> >  .../bindings/ata/ahci-platform.yaml           | 10 ++++++++++
> >  include/dt-bindings/ata/ahci.h                | 20 +++++++++++++++++++
> >  3 files changed, 46 insertions(+)
> >  create mode 100644 include/dt-bindings/ata/ahci.h
> > 
> > diff --git a/Documentation/devicetree/bindings/ata/ahci-common.yaml b/Documentation/devicetree/bindings/ata/ahci-common.yaml
> > index 12a97b56226f..94d72aeaad0f 100644
> > --- a/Documentation/devicetree/bindings/ata/ahci-common.yaml
> > +++ b/Documentation/devicetree/bindings/ata/ahci-common.yaml
> > @@ -58,6 +58,14 @@ properties:
> >    phy-names:
> >      const: sata-phy
> >  
> > +  hba-cap:
> > +    $ref: '/schemas/types.yaml#/definitions/uint32'
> > +    description:
> > +      Bitfield of the HBA generic platform capabilities like Staggered
> > +      Spin-up or Mechanical Presence Switch support. It can be used to
> > +      appropriately initialize the HWinit fields of the HBA CAP register
> > +      in case if the system firmware hasn't done it.
> > +
> >    ports-implemented:
> >      $ref: '/schemas/types.yaml#/definitions/uint32'
> >      description:
> > @@ -101,6 +109,14 @@ $defs:
> >        target-supply:
> >          description: Power regulator for SATA port target device
> >  
> > +      hba-port-cap:
> > +        $ref: '/schemas/types.yaml#/definitions/uint32'
> > +        description:
> > +          Bitfield of the HBA port-specific platform capabilities like Hot
> > +          plugging, eSATA, FIS-based Switching, etc (see AHCI specification
> > +          for details). It can be used to initialize the HWinit fields of
> > +          the PxCMD register in case if the system firmware hasn't done it.
> > +
> >      required:
> >        - reg
> >  
> > diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > index 15be98e0385b..e19cf9828e68 100644
> > --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > @@ -111,6 +111,8 @@ examples:
> >    - |
> >      #include <dt-bindings/interrupt-controller/arm-gic.h>
> >      #include <dt-bindings/clock/berlin2q.h>
> > +    #include <dt-bindings/ata/ahci.h>
> > +
> >      sata@f7e90000 {
> >          compatible = "marvell,berlin2q-ahci", "generic-ahci";
> >          reg = <0xf7e90000 0x1000>;
> > @@ -119,15 +121,23 @@ examples:
> >          #address-cells = <1>;
> >          #size-cells = <0>;
> >  
> > +        hba-cap = <HBA_SMPS>;
> > +
> >          sata0: sata-port@0 {
> >              reg = <0>;
> > +
> >              phys = <&sata_phy 0>;
> >              target-supply = <&reg_sata0>;
> > +
> > +            hba-port-cap = <(HBA_PORT_FBSCP | HBA_PORT_ESP)>;
> >          };
> >  
> >          sata1: sata-port@1 {
> >              reg = <1>;
> > +
> >              phys = <&sata_phy 1>;
> >              target-supply = <&reg_sata1>;
> > +
> > +            hba-port-cap = <(HBA_PORT_HPCP | HBA_PORT_MPSP | HBA_PORT_FBSCP)>;
> >          };
> >      };
> > diff --git a/include/dt-bindings/ata/ahci.h b/include/dt-bindings/ata/ahci.h
> > new file mode 100644
> > index 000000000000..6841caebcedf
> > --- /dev/null
> > +++ b/include/dt-bindings/ata/ahci.h
> > @@ -0,0 +1,20 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> 

> Dual license.

Ok.

> 
> With that,
> 
> Reviewed-by: Rob Herring <robh@kernel.org>

Thanks.

-Sergey

> 
> > +/*
> > + * This header provides constants for most AHCI bindings.
> > + */
> > +
> > +#ifndef _DT_BINDINGS_ATA_AHCI_H
> > +#define _DT_BINDINGS_ATA_AHCI_H
> > +
> > +/* Host Bus Adapter generic platform capabilities */
> > +#define HBA_SSS		(1 << 27)
> > +#define HBA_SMPS	(1 << 28)
> > +
> > +/* Host Bus Adapter port-specific platform capabilities */
> > +#define HBA_PORT_HPCP	(1 << 18)
> > +#define HBA_PORT_MPSP	(1 << 19)
> > +#define HBA_PORT_CPD	(1 << 20)
> > +#define HBA_PORT_ESP	(1 << 21)
> > +#define HBA_PORT_FBSCP	(1 << 22)
> > +
> > +#endif
> > -- 
> > 2.35.1
> > 
> > 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 07/23] ata: libahci_platform: Convert to using devm bulk clocks API
  2022-06-15 20:45     ` Serge Semin
@ 2022-06-16  0:23       ` Damien Le Moal
  2022-06-17 19:54         ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-16  0:23 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On 2022/06/16 5:45, Serge Semin wrote:
[...]
>>> +		hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL);
>>> +		if (!hpriv->clks) {
>>> +			rc = -ENOMEM;
>>> +			goto err_out;
>>> +		}
>>> +		hpriv->clks->clk = devm_clk_get_optional(dev, NULL);
> 
>>> +		if (IS_ERR(hpriv->clks->clk)) {
>>> +			rc = PTR_ERR(hpriv->clks->clk);
>>> +			goto err_out;
>>> +		} else if (hpriv->clks->clk) {
>>
>> Nit: the else is not needed here.
> 
> Well, it depends on what you see behind it. I see many reasons to keep
> it and only one tiny reason to drop it. Keeping it will improve the
> code readability and maintainability like having a more natural
> execution flow representation, thus clearer read-flow (else part as
> exception to the if part), less modifications should the goto part is
> changed/removed, a more exact program flow representation can be used
> by the compiler for some internal optimizations, it's one line shorter
> than the case we no 'else' here. On the other hand indeed we can drop
> it since if the conditional statement is true, the code afterwards
> won't be executed due to the goto operator. But as I see it dropping
> the else operator won't improve anything, but vise-versa will worsen
> the code instead. So if I get to miss something please justify why you
> want it being dropped, otherwise I would rather preserve it.

An else after a goto or return is never necessary and in my opinion makes the
code harder to read. I am not interested in debating this in general anyway. For
this particular case, the code would be:

		hpriv->clks->clk = devm_clk_get_optional(dev, NULL);
		if (IS_ERR(hpriv->clks->clk)) {
			/* Error path */
			rc = PTR_ERR(hpriv->clks->clk);
			goto err_out;
		}

		/* Normal path */
		if (hpriv->clks->clk) {
			...
		}

Which in my opinion is a lot easier to understand compared to having to parse
the if/else if and figure out which case in that sequence is normal vs error.

As noted, this is a nit. If you really insist, keep that else if.

> 
> -Sergey
> 
>>
>>> +			hpriv->clks->id = __clk_get_name(hpriv->clks->clk);
>>> +			hpriv->n_clks = 1;
>>>  		}
>>> -		hpriv->clks[i] = clk;
>>>  	}
>>>  
>>>  	hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");
>>
>>
>> -- 
>> Damien Le Moal
>> Western Digital Research


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 08/23] ata: libahci_platform: Sanity check the DT child nodes number
  2022-06-15 20:53     ` Serge Semin
@ 2022-06-16  0:25       ` Damien Le Moal
  2022-06-17 20:18         ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-16  0:25 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On 2022/06/16 5:53, Serge Semin wrote:
> On Tue, Jun 14, 2022 at 05:23:33PM +0900, Damien Le Moal wrote:
>> On 6/10/22 17:17, Serge Semin wrote:
>>> Having greater than AHCI_MAX_PORTS (32) ports detected isn't that critical
>>> from the further AHCI-platform initialization point of view since
>>> exceeding the ports upper limit will cause allocating more resources than
>>> will be used afterwards. But detecting too many child DT-nodes doesn't
>>> seem right since it's very unlikely to have it on an ordinary platform. In
>>> accordance with the AHCI specification there can't be more than 32 ports
>>> implemented at least due to having the CAP.NP field of 5 bits wide and the
>>> PI register of dword size. Thus if such situation is found the DTB must
>>> have been corrupted and the data read from it shouldn't be reliable. Let's
>>> consider that as an erroneous situation and halt further resources
>>> allocation.
>>>
>>> Note it's logically more correct to have the nports set only after the
>>> initialization value is checked for being sane. So while at it let's make
>>> sure nports is assigned with a correct value.
>>>
>>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
>>> Reviewed-by: Hannes Reinecke <hare@suse.de>
>>>
>>> ---
>>>
>>> Changelog v2:
>>> - Drop the else word from the child_nodes value checking if-else-if
>>>   statement (@Damien) and convert the after-else part into the ternary
>>>   operator-based statement.
>>>
>>> Changelog v4:
>>> - Fix some logical mistakes in the patch log. (@Sergei Shtylyov)
>>> ---
>>>  drivers/ata/libahci_platform.c | 13 ++++++++++---
>>>  1 file changed, 10 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
>>> index 814804582d1d..8aed7b29c7ab 100644
>>> --- a/drivers/ata/libahci_platform.c
>>> +++ b/drivers/ata/libahci_platform.c
>>> @@ -451,15 +451,22 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
>>>  		}
>>>  	}
>>>  
>>> -	hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
>>> +	/*
>>> +	 * Too many sub-nodes most likely means having something wrong with
>>> +	 * the firmware.
>>> +	 */
>>> +	child_nodes = of_get_child_count(dev->of_node);
>>> +	if (child_nodes > AHCI_MAX_PORTS) {
>>> +		rc = -EINVAL;
>>> +		goto err_out;
>>> +	}
>>>  
>>>  	/*
>>>  	 * If no sub-node was found, we still need to set nports to
>>>  	 * one in order to be able to use the
>>>  	 * ahci_platform_[en|dis]able_[phys|regulators] functions.
>>>  	 */
>>> -	if (!child_nodes)
>>> -		hpriv->nports = 1;
>>> +	hpriv->nports = child_nodes ?: 1;
>>
> 
>> This change is not necessary and makes the code far less easy to read.
> 
> elaborate please. What change? What part of this change makes the code
> less easy to read?

You changed:

	if (!child_nodes)
		hpriv->nports = 1;

to:

	hpriv->nports = child_nodes ?: 1;

That is the same. So the change is not needed in the first place, and worse,
makes the code way harder to read for no good reason.

> 
> -Sergey
> 
>>
>>>  
>>>  	hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
>>>  	if (!hpriv->phys) {
>>
>>
>> -- 
>> Damien Le Moal
>> Western Digital Research


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities
  2022-06-15 20:58     ` Serge Semin
@ 2022-06-16  0:28       ` Damien Le Moal
  2022-06-17 20:31         ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-16  0:28 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On 2022/06/16 5:58, Serge Semin wrote:
> On Tue, Jun 14, 2022 at 05:32:41PM +0900, Damien Le Moal wrote:
>> On 6/10/22 17:17, Serge Semin wrote:
>>> Currently not all of the Port-specific capabilities listed in the
>>
>> s/listed/are listed
>>
>>> PORT_CMD-enumeration. Let's extend that set with the Cold Presence
>>> Detection and Mechanical Presence Switch attached to the Port flags [1] so
>>> to closeup the set of the platform-specific port-capabilities flags.  Note
>>> these flags are supposed to be set by the platform firmware if there is
>>> one. Alternatively as we are about to do they can be set by means of the
>>> OF properties.
>>>
>>> While at it replace PORT_IRQ_DEV_ILCK with PORT_IRQ_DMPS and fix the
>>> comment there. In accordance with [2] that IRQ flag is supposed to
>>> indicate the state of the signal coming from the Mechanical Presence
>>> Switch.
>>>
>>> [1] Serial ATA AHCI 1.3.1 Specification, p.27
>>> [2] Serial ATA AHCI 1.3.1 Specification, p.24, p.88
>>>
>>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
>>> Reviewed-by: Hannes Reinecke <hare@suse.de>
>>>
>>> ---
>>>
>>> Changelog v4:
>>> - Fix the DMPS macros name in the patch log. (@Sergei Shtylyov)
>>> ---
>>>  drivers/ata/ahci.h | 7 ++++++-
>>>  1 file changed, 6 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
>>> index 7d834deefeb9..f501531bd1b3 100644
>>> --- a/drivers/ata/ahci.h
>>> +++ b/drivers/ata/ahci.h
>>> @@ -138,7 +138,7 @@ enum {
>>>  	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
>>>  
>>>  	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
>>> -	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
>>> +	PORT_IRQ_DMPS		= (1 << 7), /* mechanical presence status */
>>>  	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
>>>  	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
>>>  	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
>>> @@ -166,6 +166,8 @@ enum {
>>>  	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
>>>  	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
>>>  	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
>>> +	PORT_CMD_CPD		= (1 << 20), /* Cold Presence Detection */
>>> +	PORT_CMD_MPSP		= (1 << 19), /* Mechanical Presence Switch */
>>>  	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
>>>  	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
>>>  	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
>>> @@ -181,6 +183,9 @@ enum {
>>>  	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
>>>  	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
>>>  
>>> +	PORT_CMD_CAP		= PORT_CMD_HPCP | PORT_CMD_MPSP |
>>> +				  PORT_CMD_CPD | PORT_CMD_ESP | PORT_CMD_FBSCP,
>>
> 
>> What is this one for ? A comment above it would be nice.
> 
> Isn't it obviously inferrable from the definition and the item name?

I am guessing from the name. Am I guessing OK ? A comment would still be nice.
Why just these bits ? There are more cap/support indicator bits in that port cmd
bitfield. So why this particular set of bits ? What do they mean all together ?

Sure I can go and read the specs to figure it out. But again, a comment would
avoid readers of the code to have to decrypt all that.

> 
> -Sergey
> 
>>
>>> +
>>>  	/* PORT_FBS bits */
>>>  	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
>>>  	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
>>
>>
>> -- 
>> Damien Le Moal
>> Western Digital Research


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 16/23] ata: ahci: Introduce firmware-specific caps initialization
  2022-06-15 21:11     ` Serge Semin
@ 2022-06-16  0:29       ` Damien Le Moal
  2022-06-17 20:32         ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-16  0:29 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On 2022/06/16 6:11, Serge Semin wrote:
> On Tue, Jun 14, 2022 at 05:42:35PM +0900, Damien Le Moal wrote:
>> On 6/10/22 17:17, Serge Semin wrote:
>>> There are systems with no BIOS or comprehensive embedded firmware which
>>> could be able to properly initialize the SATA AHCI controller
>>> platform-specific capabilities. In that case a good alternative to having
>>> a clever bootloader is to create a device tree node with the properties
>>> well describing all the AHCI-related platform specifics. All the settings
>>> which are normally detected and marked as available in the HBA and its
>>> ports capabilities fields [1] could be defined in the platform DTB by
>>> means of a set of the dedicated properties. Such approach perfectly fits
>>> to the DTB-philosophy - to provide hardware/platform description.
>>>
>>> So here we suggest to extend the SATA AHCI device tree bindings with two
>>> additional DT-properties:
>>> 1) "hba-cap" - HBA platform generic capabilities like:
>>>    - SSS - Staggered Spin-up support.
>>>    - SMPS - Mechanical Presence Switch support.
>>> 2) "hba-port-cap" - HBA platform port capabilities like:
>>>    - HPCP - Hot Plug Capable Port.
>>>    - MPSP - Mechanical Presence Switch Attached to Port.
>>>    - CPD - Cold Presence Detection.
>>>    - ESP - External SATA Port.
>>>    - FBSCP - FIS-based Switching Capable Port.
>>> All of these capabilities require to have a corresponding hardware
>>> configuration. Thus it's ok to have them defined in DTB.
>>>
>>> Even though the driver currently takes into account the state of the ESP
>>> and FBSCP flags state only, there is nothing wrong with having all of them
>>> supported by the generic AHCI library in order to have a complete OF-based
>>> platform-capabilities initialization procedure. These properties will be
>>> parsed in the ahci_platform_get_resources() method and their values will
>>> be stored in the saved_* fields of the ahci_host_priv structure, which in
>>> its turn then will be used to restore the H.CAP, H.PI and P#.CMD
>>> capability fields on device init and after HBA reset.
>>>
>>> Please note this modification concerns the HW-init HBA and its ports flags
>>> only, which are by specification [1] are supposed to be initialized by the
>>> BIOS/platform firmware/expansion ROM and which are normally declared in
>>> the one-time-writable-after-reset register fields. Even though these flags
>>> aren't supposed to be cleared after HBA reset some AHCI instances may
>>> violate that rule so we still need to perform the fields resetting after
>>> each reset. Luckily the corresponding functionality has already been
>>> partly implemented in the framework of the ahci_save_initial_config() and
>>> ahci_restore_initial_config() methods.
>>>
>>> [1] Serial ATA AHCI 1.3.1 Specification, p. 103
>>>
>>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
>>>
>>> ---
>>>
>>> Changelog v4:
>>> - Convert the boolean properties to the bitfield DT-properties. (@Rob)
>>> ---
>>>  drivers/ata/ahci.h             |  1 +
>>>  drivers/ata/libahci.c          | 51 ++++++++++++++++++++++++++++------
>>>  drivers/ata/libahci_platform.c | 41 +++++++++++++++++++++++++--
>>>  3 files changed, 82 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
>>> index 8b9826533ae5..0de221055961 100644
>>> --- a/drivers/ata/ahci.h
>>> +++ b/drivers/ata/ahci.h
>>> @@ -337,6 +337,7 @@ struct ahci_host_priv {
>>>  	u32			saved_cap;	/* saved initial cap */
>>>  	u32			saved_cap2;	/* saved initial cap2 */
>>>  	u32			saved_port_map;	/* saved initial port_map */
>>> +	u32			saved_port_cap[AHCI_MAX_PORTS]; /* saved port_cap */
>>>  	u32 			em_loc; /* enclosure management location */
>>>  	u32			em_buf_sz;	/* EM buffer size in byte */
>>>  	u32			em_msg_type;	/* EM message type */
>>> diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
>>> index 1ffaa5f5f21a..954386a2b500 100644
>>> --- a/drivers/ata/libahci.c
>>> +++ b/drivers/ata/libahci.c
>>> @@ -16,6 +16,7 @@
>>>   * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
>>>   */
>>>  
>>> +#include <linux/bitops.h>
>>>  #include <linux/kernel.h>
>>>  #include <linux/gfp.h>
>>>  #include <linux/module.h>
>>> @@ -443,16 +444,28 @@ static ssize_t ahci_show_em_supported(struct device *dev,
>>>  void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>>>  {
>>>  	void __iomem *mmio = hpriv->mmio;
>>> -	u32 cap, cap2, vers, port_map;
>>> +	void __iomem *port_mmio;
>>> +	unsigned long port_map;
>>> +	u32 cap, cap2, vers;
>>>  	int i;
>>>  
>>>  	/* make sure AHCI mode is enabled before accessing CAP */
>>>  	ahci_enable_ahci(mmio);
>>>  
>>> -	/* Values prefixed with saved_ are written back to host after
>>> -	 * reset.  Values without are used for driver operation.
>>> +	/*
>>> +	 * Values prefixed with saved_ are written back to the HBA and ports
>>> +	 * registers after reset. Values without are used for driver operation.
>>> +	 */
>>> +
>>> +	/*
>>> +	 * Override HW-init HBA capability fields with the platform-specific
>>> +	 * values. The rest of the HBA capabilities are defined as Read-only
>>> +	 * and can't be modified in CSR anyway.
>>>  	 */
>>> -	hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
>>> +	cap = readl(mmio + HOST_CAP);
>>> +	if (hpriv->saved_cap)
>>> +		cap = (cap & ~(HOST_CAP_SSS | HOST_CAP_MPS)) | hpriv->saved_cap;
>>> +	hpriv->saved_cap = cap;
>>>  
>>>  	/* CAP2 register is only defined for AHCI 1.2 and later */
>>>  	vers = readl(mmio + HOST_VERSION);
>>> @@ -519,7 +532,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>>>  	/* Override the HBA ports mapping if the platform needs it */
>>>  	port_map = readl(mmio + HOST_PORTS_IMPL);
>>>  	if (hpriv->saved_port_map && port_map != hpriv->saved_port_map) {
>>> -		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
>>> +		dev_info(dev, "forcing port_map 0x%lx -> 0x%x\n",
>>
> 
>> This change is not necessary.
> 
> It is. The port_map type has been changed.

Ignore. When I read the patches the other day, the mailer font had that "l" look
like a "1" :) My mistake.

> 
>>
>>>  			 port_map, hpriv->saved_port_map);
>>>  		port_map = hpriv->saved_port_map;
>>>  	} else {
>>> @@ -527,7 +540,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>>>  	}
>>>  
>>>  	if (hpriv->mask_port_map) {
>>> -		dev_warn(dev, "masking port_map 0x%x -> 0x%x\n",
>>> +		dev_warn(dev, "masking port_map 0x%lx -> 0x%lx\n",
>>
>> Same.
> 
> ditto
> 
>>
>>>  			port_map,
>>>  			port_map & hpriv->mask_port_map);
>>>  		port_map &= hpriv->mask_port_map;
>>> @@ -546,7 +559,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>>>  		 */
>>>  		if (map_ports > ahci_nr_ports(cap)) {
>>>  			dev_warn(dev,
>>> -				 "implemented port map (0x%x) contains more ports than nr_ports (%u), using nr_ports\n",
>>> +				 "implemented port map (0x%lx) contains more ports than nr_ports (%u), using nr_ports\n",
>>
>> Same.
> 
> ditto.
> 
>>
>>>  				 port_map, ahci_nr_ports(cap));
>>>  			port_map = 0;
>>>  		}
>>> @@ -555,12 +568,26 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
>>>  	/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
>>>  	if (!port_map && vers < 0x10300) {
>>>  		port_map = (1 << ahci_nr_ports(cap)) - 1;
>>> -		dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
>>> +		dev_warn(dev, "forcing PORTS_IMPL to 0x%lx\n", port_map);
>>
>> And again not needed.
> 
> and ditto.
> 
>>
>>>  
>>>  		/* write the fixed up value to the PI register */
>>>  		hpriv->saved_port_map = port_map;
>>>  	}
>>>  
>>> +	/*
>>> +	 * Preserve the ports capabilities defined by the platform. Note there
>>> +	 * is no need in storing the rest of the P#.CMD fields since they are
>>> +	 * volatile.
>>> +	 */
>>> +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
>>> +		if (hpriv->saved_port_cap[i])
>>> +			continue;
>>> +
>>> +		port_mmio = __ahci_port_base(hpriv, i);
>>> +		hpriv->saved_port_cap[i] =
>>> +			readl(port_mmio + PORT_CMD) & PORT_CMD_CAP;
>>> +	}
>>> +
>>>  	/* record values to use during operation */
>>>  	hpriv->cap = cap;
>>>  	hpriv->cap2 = cap2;
>>> @@ -590,13 +617,21 @@ EXPORT_SYMBOL_GPL(ahci_save_initial_config);
>>>  static void ahci_restore_initial_config(struct ata_host *host)
>>>  {
>>>  	struct ahci_host_priv *hpriv = host->private_data;
>>> +	unsigned long port_map = hpriv->port_map;
>>>  	void __iomem *mmio = hpriv->mmio;
>>> +	void __iomem *port_mmio;
>>> +	int i;
>>>  
>>>  	writel(hpriv->saved_cap, mmio + HOST_CAP);
>>>  	if (hpriv->saved_cap2)
>>>  		writel(hpriv->saved_cap2, mmio + HOST_CAP2);
>>>  	writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
>>>  	(void) readl(mmio + HOST_PORTS_IMPL);	/* flush */
>>> +
>>> +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
>>> +		port_mmio = __ahci_port_base(hpriv, i);
>>> +		writel(hpriv->saved_port_cap[i], port_mmio + PORT_CMD);
>>> +	}
>>>  }
>>>  
>>>  static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
>>> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
>>> index efe640603f3f..8b542a8bc487 100644
>>> --- a/drivers/ata/libahci_platform.c
>>> +++ b/drivers/ata/libahci_platform.c
>>> @@ -23,6 +23,7 @@
>>>  #include <linux/pm_runtime.h>
>>>  #include <linux/of_platform.h>
>>>  #include <linux/reset.h>
>>> +
>>
>> white line change.
> 
> Ok. I'll drop it.
> 
> -Sergey
> 
>>
>>>  #include "ahci.h"
>>>  
>>>  static void ahci_host_stop(struct ata_host *host);
>>> @@ -383,6 +384,34 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
>>>  	return rc;
>>>  }
>>>  
>>> +static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv,
>>> +				      struct device *dev)
>>> +{
>>> +	struct device_node *child;
>>> +	u32 port;
>>> +
>>> +	if (!of_property_read_u32(dev->of_node, "hba-cap", &hpriv->saved_cap))
>>> +		hpriv->saved_cap &= (HOST_CAP_SSS | HOST_CAP_MPS);
>>> +
>>> +	of_property_read_u32(dev->of_node,
>>> +			     "ports-implemented", &hpriv->saved_port_map);
>>> +
>>> +	for_each_child_of_node(dev->of_node, child) {
>>> +		if (!of_device_is_available(child))
>>> +			continue;
>>> +
>>> +		if (of_property_read_u32(child, "reg", &port)) {
>>> +			of_node_put(child);
>>> +			return -EINVAL;
>>> +		}
>>> +
>>> +		if (!of_property_read_u32(child, "hba-port-cap", &hpriv->saved_port_cap[port]))
>>> +			hpriv->saved_port_cap[port] &= PORT_CMD_CAP;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  /**
>>>   * ahci_platform_get_resources - Get platform resources
>>>   * @pdev: platform device to get resources for
>>> @@ -523,9 +552,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
>>>  		goto err_out;
>>>  	}
>>>  
>>> -	of_property_read_u32(dev->of_node,
>>> -			     "ports-implemented", &hpriv->saved_port_map);
>>> -
>>>  	if (child_nodes) {
>>>  		for_each_child_of_node(dev->of_node, child) {
>>>  			u32 port;
>>> @@ -590,6 +616,15 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
>>>  		if (rc == -EPROBE_DEFER)
>>>  			goto err_out;
>>>  	}
>>> +
>>> +	/*
>>> +	 * Retrieve firmware-specific flags which then will be used to set
>>> +	 * the HW-init fields of HBA and its ports
>>> +	 */
>>> +	rc = ahci_platform_get_firmware(hpriv, dev);
>>> +	if (rc)
>>> +		goto err_out;
>>> +
>>>  	pm_runtime_enable(dev);
>>>  	pm_runtime_get_sync(dev);
>>>  	hpriv->got_runtime_pm = true;
>>
>>
>> -- 
>> Damien Le Moal
>> Western Digital Research


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-15 21:30         ` Serge Semin
@ 2022-06-16  0:31           ` Damien Le Moal
  2022-06-17 20:36             ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-16  0:31 UTC (permalink / raw)
  To: Serge Semin, Randy Dunlap
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On 2022/06/16 6:30, Serge Semin wrote:
> On Fri, Jun 10, 2022 at 04:34:13PM -0700, Randy Dunlap wrote:
>> Hi Serge,
>>
>> On 6/10/22 14:58, Serge Semin wrote:
>>> On Fri, Jun 10, 2022 at 09:34:46AM -0700, Randy Dunlap wrote:
>>>> Hi--
>>>
>>> Hi Randy
>>>
>>>>
>>>> On 6/10/22 01:17, Serge Semin wrote:
>>>>> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
>>>>> index bb45a9c00514..95e0e022b5bb 100644
>>>>> --- a/drivers/ata/Kconfig
>>>>> +++ b/drivers/ata/Kconfig
>>>>> @@ -176,6 +176,16 @@ config AHCI_DM816
>>>>>  
>>>>>  	  If unsure, say N.
>>>>>  
>>>>> +config AHCI_DWC
>>>>> +	tristate "Synopsys DWC AHCI SATA support"
>>>>> +	select SATA_HOST
>>>>> +	default SATA_AHCI_PLATFORM
>>>>
>>>
>>>> I don't think this needs to default to SATA_AHCI_PLATFORM.
>>>> It might build a driver that isn't needed.
>>>> And it's incompatible with "If unsure, say N."
>>>
>>> Basically you are right, but this particular setting is connected with
>>> the modification I've done in the drivers/ata/ahci_platform.c driver
>>> in the framework of this commit. I've moved the "snps,spear-ahci" and
>>> "snps,dwc-ahci" compatible devices support to the new driver. Thus
>>> should I omit the SATA_AHCI_PLATFORM dependency their default kernel
>>> configs will lack the corresponding controllers support. If it's not a
>>> problem and we can rely on the kernel build system ability to ask
>>> whether the new config needs to be set/cleared, then I would be very
>>> happy to drop the default setting. What do you think?
>>
> 
>> I'd prefer to try it like that.
>> If it becomes a problem, we can go back to this v4 patch.
> 
> Agreed then (seeing Damien is silent about your comment).

I have not thought about it :)
I do not use SATA PLATFORM at all, so I am not familiar with its dependencies.
Will have a look and do my usual build tests anyway.

> 
> -Sergey
> 
>>
>>>>> +	help
>>>>> +	  This option enables support for the Synopsys DWC AHCI SATA
>>>>> +	  controller implementation.
>>>>> +
>>>>> +	  If unsure, say N.
>>>>
>>>> -- 
>>>> ~Randy
>>
>> Thanks.
>> -- 
>> ~Randy


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-15 21:48     ` Serge Semin
@ 2022-06-16  0:33       ` Damien Le Moal
  2022-06-17 20:34         ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-16  0:33 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On 2022/06/16 6:48, Serge Semin wrote:
[...]
>> MODULE_LICENSE("GPL v2");
>>
>> To match the file header SPDX.
> 
> No. Please see the commit bf7fbeeae6db ("module: Cure the
> MODULE_LICENSE "GPL" vs. "GPL v2" bogosity") and what checkpatch.pl
> says should the "GPL v2" string is used in the module license block.
> More info regarding this macro and the possible license values are
> described here:
> Documentation/process/license-rules.rst

ah ! OK. I was not 100% sure. Doing a quick grep, there is still a lot of (half
?) of "GPL v2" vs "GPL".

Ignore this then.

> 
> -Sergey
> 
>>
>>> diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
>>> index 9b56490ecbc3..8f5572a9f8f1 100644
>>> --- a/drivers/ata/ahci_platform.c
>>> +++ b/drivers/ata/ahci_platform.c
>>> @@ -80,9 +80,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
>>>  static const struct of_device_id ahci_of_match[] = {
>>>  	{ .compatible = "generic-ahci", },
>>>  	/* Keep the following compatibles for device tree compatibility */
>>> -	{ .compatible = "snps,spear-ahci", },
>>>  	{ .compatible = "ibm,476gtr-ahci", },
>>> -	{ .compatible = "snps,dwc-ahci", },
>>>  	{ .compatible = "hisilicon,hisi-ahci", },
>>>  	{ .compatible = "cavium,octeon-7130-ahci", },
>>>  	{ /* sentinel */ }
>>
>>
>> -- 
>> Damien Le Moal
>> Western Digital Research
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema
  2022-06-14 22:27   ` Rob Herring
@ 2022-06-17 19:37     ` Serge Semin
  2022-06-28 12:10       ` Serge Semin
  2022-07-06 22:36       ` Rob Herring
  0 siblings, 2 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-17 19:37 UTC (permalink / raw)
  To: Rob Herring
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Krzysztof Kozlowski, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

On Tue, Jun 14, 2022 at 04:27:54PM -0600, Rob Herring wrote:
> On Fri, Jun 10, 2022 at 11:17:55AM +0300, Serge Semin wrote:
> > Synopsys AHCI SATA controller is mainly compatible with the generic AHCI
> > SATA controller except a few peculiarities and the platform environment
> > requirements. In particular it can have one or two reference clocks to
> > feed up its AXI/AHB interface and SATA PHYs domain and at least one reset
> > control for the application clock domain. In addition to that the DMA
> > interface of each port can be tuned up to work with the predefined maximum
> > data chunk size. Note unlike generic AHCI controller DWC AHCI can't have
> > more than 8 ports. All of that is reflected in the new DWC AHCI SATA
> > device DT binding.
> > 
> > Note the DWC AHCI SATA controller DT-schema has been created in a way so
> > to be reused for the vendor-specific DT-schemas (see for example the
> > "snps,dwc-ahci" compatible string binding). One of which we are about to
> > introduce.
> > 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > 
> > ---
> > 
> > Changelog v2:
> > - Replace min/max constraints of the snps,{tx,rx}-ts-max property with
> >   enum [ 1, 2, 4, ..., 1024 ]. (@Rob)
> > 
> > Changelog v4:
> > - Decrease the "additionalProperties" property identation otherwise it's
> >   percieved as the node property instead of the key one. (@Rob)
> > - Use the ahci-port properties definition from the AHCI common schema
> >   in order to extend it with DWC AHCI SATA port properties. (@Rob)
> > - Remove the Hannes' rb tag since the patch content has changed.
> > ---
> >  .../bindings/ata/ahci-platform.yaml           |   8 --
> >  .../bindings/ata/snps,dwc-ahci.yaml           | 129 ++++++++++++++++++
> >  2 files changed, 129 insertions(+), 8 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > index e19cf9828e68..7dc2a2e8f598 100644
> > --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > @@ -30,8 +30,6 @@ select:
> >            - marvell,armada-3700-ahci
> >            - marvell,armada-8k-ahci
> >            - marvell,berlin2q-ahci
> > -          - snps,dwc-ahci
> > -          - snps,spear-ahci
> >    required:
> >      - compatible
> >  
> > @@ -48,17 +46,11 @@ properties:
> >                - marvell,berlin2-ahci
> >                - marvell,berlin2q-ahci
> >            - const: generic-ahci
> > -      - items:
> > -          - enum:
> > -              - rockchip,rk3568-dwc-ahci
> > -          - const: snps,dwc-ahci
> >        - enum:
> >            - cavium,octeon-7130-ahci
> >            - hisilicon,hisi-ahci
> >            - ibm,476gtr-ahci
> >            - marvell,armada-3700-ahci
> > -          - snps,dwc-ahci
> > -          - snps,spear-ahci
> >  
> >    reg:
> >      minItems: 1
> > diff --git a/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > new file mode 100644
> > index 000000000000..af78f6c9b857
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > @@ -0,0 +1,129 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/ata/snps,dwc-ahci.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Synopsys DWC AHCI SATA controller
> > +
> > +maintainers:
> > +  - Serge Semin <fancer.lancer@gmail.com>
> > +
> > +description:
> > +  This document defines device tree bindings for the Synopsys DWC
> > +  implementation of the AHCI SATA controller.
> > +
> > +allOf:
> > +  - $ref: ahci-common.yaml#
> > +
> > +properties:
> > +  compatible:
> > +    oneOf:
> > +      - description: Synopsys AHCI SATA-compatible devices
> > +        contains:
> > +          const: snps,dwc-ahci
> > +      - description: SPEAr1340 AHCI SATA device
> > +        const: snps,spear-ahci
> > +      - description: Rockhip RK3568 ahci controller
> > +        const: rockchip,rk3568-dwc-ahci
> 

> This is never true because there is a fallback. We should keep what we 
> had before.

Could you be more specific what you meant? I don't see
"snps,spear-ahci" and "rockchip,rk3568-dwc-ahci" used with the fallback
string so modification is correct in that case.

My idea was to have the compatible strings with the required generic
fallback "snps,dwc-ahci" for all new devices thus identifying the
controller IP-core origin. But later you said "The generic IP block
fallbacks have proven to be useless." I do agree that functionally it
isn't that often used, but in some cases it can be handy for instance
to implement quirks in the generic code or use the fallback as an
additional info regarding the IP-core origin/version. So if I were you
I wouldn't be that strict about dropping the generic IP-core fallback
identifier. It's much easier to have it specified from the very
beginning than adding it after it has been declared as not required.

> 
> 
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  interrupts:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    description:
> > +      Basic DWC AHCI SATA clock sources like application AXI/AHB BIU clock
> > +      and embedded PHYs reference clock together with vendor-specific set
> > +      of clocks.
> > +    minItems: 1
> > +    maxItems: 4
> > +
> > +  clock-names:
> > +    contains:
> > +      anyOf:
> > +        - description: Application AXI/AHB BIU clock source
> > +          enum:
> > +            - aclk
> > +            - sata
> > +        - description: SATA Ports reference clock
> > +          enum:
> > +            - ref
> > +            - sata_ref
> > +
> > +  resets:
> > +    description:
> > +      At least basic core and application clock domains reset is normally
> > +      supported by the DWC AHCI SATA controller. Some platform specific
> > +      clocks can be also specified though.
> 

> s/clocks/resets/ ?

Right, but only in the reference to "platform specific clocks" -> "... resets".

> 
> This allows any number of resets which isn't great. I think this schema 
> should just be the 'simple' cases where there's only 1 reset and 1 
> clock (or how many the DWC block actually has if you have that info). 
> More complicated cases get there own schema.

DWC SATA reference manual claims there can be resets implemented to
each clock domain.
1) PM-clk <- PM-rst - PM keep-alive clock/reset.
2) aclk/hclk <- aresetn/hresetn - AXI/AHB clock domain/reset.
3) rbc*_clk <- rbc*_rst - PHY Receive Clock domain/reset. (Up to
number of ports <= 8.)
4) asic*_clk <- asic*_rst - PHY Transmit Clock domain/reset. (Up to
number of ports <= 8.)
5) rxoob*_clk <- rxoob*_rst - RxOOB Detection Clock domain/reset. (Up
to number of ports <= 8.)

So to speak the IP-core can be equipped with up to 26 clocks and
resets. Should we be more strict we would have needed to define the
properties with all the names above and permit up to 26 clocks/resets
items. (Do you want it to be done?). In our case for instance there
is "aclk" and a single common "ref" clock for all 3, 4 and 5 domain
(clock 1 is missing).

-Sergey

> 
> > +
> > +  reset-names:
> > +    contains:
> > +      description: Core and application clock domains reset control
> > +      const: arst
> > +
> > +patternProperties:
> > +  "^sata-port@[0-9a-e]$":
> > +    $ref: '#/$defs/dwc-ahci-port'
> > +
> > +    unevaluatedProperties: false
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - interrupts
> > +
> > +unevaluatedProperties: false
> > +
> > +$defs:
> > +  dwc-ahci-port:
> > +    $ref: /schemas/ata/ahci-common.yaml#/$defs/ahci-port
> > +
> > +    properties:
> > +      reg:
> > +        minimum: 0
> > +        maximum: 7
> > +
> > +      snps,tx-ts-max:
> > +        $ref: /schemas/types.yaml#/definitions/uint32
> > +        description: Maximal size of Tx DMA transactions in FIFO words
> > +        enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
> > +
> > +      snps,rx-ts-max:
> > +        $ref: /schemas/types.yaml#/definitions/uint32
> > +        description: Maximal size of Rx DMA transactions in FIFO words
> > +        enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> > +    #include <dt-bindings/ata/ahci.h>
> > +
> > +    sata@122f0000 {
> > +      compatible = "snps,dwc-ahci";
> > +      reg = <0x122F0000 0x1ff>;
> > +      #address-cells = <1>;
> > +      #size-cells = <0>;
> > +
> > +      interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
> > +
> > +      clocks = <&clock1>, <&clock2>;
> > +      clock-names = "aclk", "ref";
> > +
> > +      phys = <&sata_phy>;
> > +      phy-names = "sata-phy";
> > +
> > +      ports-implemented = <0x1>;
> > +
> > +      sata-port@0 {
> > +        reg = <0>;
> > +
> > +        hba-port-cap = <HBA_PORT_FBSCP>;
> > +
> > +        snps,tx-ts-max = <512>;
> > +        snps,rx-ts-max = <512>;
> > +      };
> > +    };
> > +...
> > -- 
> > 2.35.1
> > 
> > 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 20/23] dt-bindings: ata: ahci: Add Baikal-T1 AHCI SATA controller DT schema
  2022-06-14 22:29   ` Rob Herring
@ 2022-06-17 19:49     ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-17 19:49 UTC (permalink / raw)
  To: Rob Herring
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Krzysztof Kozlowski, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

On Tue, Jun 14, 2022 at 04:29:22PM -0600, Rob Herring wrote:
> On Fri, Jun 10, 2022 at 11:17:58AM +0300, Serge Semin wrote:
> > Baikal-T1 AHCI controller is based on the DWC AHCI SATA IP-core v4.10a
> > with the next specific settings: two SATA ports, cascaded CSR access based
> > on two clock domains (APB and AXI), selectable source of the reference
> > clock (though stable work is currently available from the external source
> > only), two reset lanes for the application and SATA ports domains. Other
> > than that the device is fully compatible with the generic DWC AHCI SATA
> > bindings.
> > 
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > Reviewed-by: Hannes Reinecke <hare@suse.de>
> > 
> > ---
> > 
> > Changelog v2:
> > - Rename 'syscon' property to 'baikal,bt1-syscon'.
> > - Drop macro usage from the example node.
> > 
> > Changelog v4:
> > - Use the DWC AHCI port properties definition from the DWC AHCI SATA
> >   common schema. (@Rob)
> > - Drop Baikal-T1 syscon reference and implement the clock signal
> >   source in the framework of the clock controller. (@Rob)
> > ---
> >  .../bindings/ata/baikal,bt1-ahci.yaml         | 116 ++++++++++++++++++
> >  1 file changed, 116 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml b/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
> > new file mode 100644
> > index 000000000000..d5fbd7d561d8
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml
> > @@ -0,0 +1,116 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/ata/baikal,bt1-ahci.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Baikal-T1 SoC AHCI SATA controller
> > +
> > +maintainers:
> > +  - Serge Semin <fancer.lancer@gmail.com>
> > +
> > +description: |
> > +  AHCI SATA controller embedded into the Baikal-T1 SoC is based on the
> > +  DWC AHCI SATA v4.10a IP-core.
> > +
> > +allOf:
> > +  - $ref: snps,dwc-ahci.yaml#
> > +
> > +properties:
> > +  compatible:
> > +    contains:
> > +      const: baikal,bt1-ahci
> > +
> > +  clocks:
> > +    items:
> > +      - description: Peripheral APB bus clock source
> > +      - description: Application AXI BIU clock
> > +      - description: SATA Ports reference clock
> > +
> > +  clock-names:
> > +    items:
> > +      - const: pclk
> > +      - const: aclk
> > +      - const: ref
> > +
> > +  resets:
> > +    items:
> > +      - description: Application AXI BIU domain reset
> > +      - description: SATA Ports clock domain reset
> > +
> > +  reset-names:
> > +    items:
> > +      - const: arst
> > +      - const: ref
> > +
> > +  ports-implemented:
> > +    maximum: 0x3
> > +
> > +patternProperties:
> > +  "^sata-port@[0-9a-e]$":
> > +    $ref: /schemas/ata/snps,dwc-ahci.yaml#/$defs/dwc-ahci-port
> > +
> > +    properties:
> > +      reg:
> > +        minimum: 0
> > +        maximum: 1
> > +
> > +      snps,tx-ts-max:
> > +        $ref: /schemas/types.yaml#/definitions/uint32
> > +        description:
> > +          Due to having AXI3 bus interface utilized the maximum Tx DMA
> > +          transaction size can't exceed 16 beats (AxLEN[3:0]).
> > +        enum: [ 1, 2, 4, 8, 16 ]
> > +
> > +      snps,rx-ts-max:
> > +        $ref: /schemas/types.yaml#/definitions/uint32
> > +        description:
> > +          Due to having AXI3 bus interface utilized the maximum Rx DMA
> > +          transaction size can't exceed 16 beats (AxLEN[3:0]).
> > +        enum: [ 1, 2, 4, 8, 16 ]
> > +
> > +    unevaluatedProperties: false
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - interrupts
> > +  - clocks
> > +  - clock-names
> > +  - resets
> > +
> > +unevaluatedProperties: false
> > +
> > +examples:
> > +  - |
> > +    sata@1f050000 {
> > +      compatible = "baikal,bt1-ahci", "snps,dwc-ahci";
> 

> Just drop 'snps,dwc-ahci'. The generic IP block fallbacks have proven to 
> be useless.

Please see my answer to your comment to the patch
[PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema
in this series here:
https://lore.kernel.org/linux-ide/20220617193744.av27axznbogademt@mobilestation/
Let's settle the fallback usage in general otherwise I'll keep
submitting patches with such functionality and will always be getting
your notes in that regard.)

-Sergey


> 
> > +      reg = <0x1f050000 0x2000>;
> > +      #address-cells = <1>;
> > +      #size-cells = <0>;
> > +
> > +      interrupts = <0 64 4>;
> > +
> > +      clocks = <&ccu_sys 1>, <&ccu_axi 2>, <&sata_ref_clk>;
> > +      clock-names = "pclk", "aclk", "ref";
> > +
> > +      resets = <&ccu_axi 2>, <&ccu_sys 0>;
> > +      reset-names = "arst", "ref";
> > +
> > +      ports-implemented = <0x3>;
> > +
> > +      sata-port@0 {
> > +        reg = <0>;
> > +
> > +        snps,tx-ts-max = <4>;
> > +        snps,rx-ts-max = <4>;
> > +      };
> > +
> > +      sata-port@1 {
> > +        reg = <1>;
> > +
> > +        snps,tx-ts-max = <4>;
> > +        snps,rx-ts-max = <4>;
> > +      };
> > +    };
> > +...
> > -- 
> > 2.35.1
> > 
> > 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 07/23] ata: libahci_platform: Convert to using devm bulk clocks API
  2022-06-16  0:23       ` Damien Le Moal
@ 2022-06-17 19:54         ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-17 19:54 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Thu, Jun 16, 2022 at 09:23:28AM +0900, Damien Le Moal wrote:
> On 2022/06/16 5:45, Serge Semin wrote:
> [...]
> >>> +		hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL);
> >>> +		if (!hpriv->clks) {
> >>> +			rc = -ENOMEM;
> >>> +			goto err_out;
> >>> +		}
> >>> +		hpriv->clks->clk = devm_clk_get_optional(dev, NULL);
> > 
> >>> +		if (IS_ERR(hpriv->clks->clk)) {
> >>> +			rc = PTR_ERR(hpriv->clks->clk);
> >>> +			goto err_out;
> >>> +		} else if (hpriv->clks->clk) {
> >>
> >> Nit: the else is not needed here.
> > 
> > Well, it depends on what you see behind it. I see many reasons to keep
> > it and only one tiny reason to drop it. Keeping it will improve the
> > code readability and maintainability like having a more natural
> > execution flow representation, thus clearer read-flow (else part as
> > exception to the if part), less modifications should the goto part is
> > changed/removed, a more exact program flow representation can be used
> > by the compiler for some internal optimizations, it's one line shorter
> > than the case we no 'else' here. On the other hand indeed we can drop
> > it since if the conditional statement is true, the code afterwards
> > won't be executed due to the goto operator. But as I see it dropping
> > the else operator won't improve anything, but vise-versa will worsen
> > the code instead. So if I get to miss something please justify why you
> > want it being dropped, otherwise I would rather preserve it.
> 
> An else after a goto or return is never necessary and in my opinion makes the
> code harder to read. I am not interested in debating this in general anyway. For
> this particular case, the code would be:
> 
> 		hpriv->clks->clk = devm_clk_get_optional(dev, NULL);
> 		if (IS_ERR(hpriv->clks->clk)) {
> 			/* Error path */
> 			rc = PTR_ERR(hpriv->clks->clk);
> 			goto err_out;
> 		}
> 
> 		/* Normal path */
> 		if (hpriv->clks->clk) {
> 			...
> 		}
> 
> Which in my opinion is a lot easier to understand compared to having to parse
> the if/else if and figure out which case in that sequence is normal vs error.
> 

> As noted, this is a nit. If you really insist, keep that else if.

Ok. I'll leave it as is then.

Thanks
-Sergey

> 
> > 
> > -Sergey
> > 
> >>
> >>> +			hpriv->clks->id = __clk_get_name(hpriv->clks->clk);
> >>> +			hpriv->n_clks = 1;
> >>>  		}
> >>> -		hpriv->clks[i] = clk;
> >>>  	}
> >>>  
> >>>  	hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");
> >>
> >>
> >> -- 
> >> Damien Le Moal
> >> Western Digital Research
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 08/23] ata: libahci_platform: Sanity check the DT child nodes number
  2022-06-16  0:25       ` Damien Le Moal
@ 2022-06-17 20:18         ` Serge Semin
  2022-06-18  6:49           ` Damien Le Moal
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-17 20:18 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Thu, Jun 16, 2022 at 09:25:48AM +0900, Damien Le Moal wrote:
> On 2022/06/16 5:53, Serge Semin wrote:
> > On Tue, Jun 14, 2022 at 05:23:33PM +0900, Damien Le Moal wrote:
> >> On 6/10/22 17:17, Serge Semin wrote:
> >>> Having greater than AHCI_MAX_PORTS (32) ports detected isn't that critical
> >>> from the further AHCI-platform initialization point of view since
> >>> exceeding the ports upper limit will cause allocating more resources than
> >>> will be used afterwards. But detecting too many child DT-nodes doesn't
> >>> seem right since it's very unlikely to have it on an ordinary platform. In
> >>> accordance with the AHCI specification there can't be more than 32 ports
> >>> implemented at least due to having the CAP.NP field of 5 bits wide and the
> >>> PI register of dword size. Thus if such situation is found the DTB must
> >>> have been corrupted and the data read from it shouldn't be reliable. Let's
> >>> consider that as an erroneous situation and halt further resources
> >>> allocation.
> >>>
> >>> Note it's logically more correct to have the nports set only after the
> >>> initialization value is checked for being sane. So while at it let's make
> >>> sure nports is assigned with a correct value.
> >>>
> >>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> >>> Reviewed-by: Hannes Reinecke <hare@suse.de>
> >>>
> >>> ---
> >>>
> >>> Changelog v2:
> >>> - Drop the else word from the child_nodes value checking if-else-if
> >>>   statement (@Damien) and convert the after-else part into the ternary
> >>>   operator-based statement.
> >>>
> >>> Changelog v4:
> >>> - Fix some logical mistakes in the patch log. (@Sergei Shtylyov)
> >>> ---
> >>>  drivers/ata/libahci_platform.c | 13 ++++++++++---
> >>>  1 file changed, 10 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> >>> index 814804582d1d..8aed7b29c7ab 100644
> >>> --- a/drivers/ata/libahci_platform.c
> >>> +++ b/drivers/ata/libahci_platform.c
> >>> @@ -451,15 +451,22 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
> >>>  		}
> >>>  	}
> >>>  
> >>> -	hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
> >>> +	/*
> >>> +	 * Too many sub-nodes most likely means having something wrong with
> >>> +	 * the firmware.
> >>> +	 */
> >>> +	child_nodes = of_get_child_count(dev->of_node);
> >>> +	if (child_nodes > AHCI_MAX_PORTS) {
> >>> +		rc = -EINVAL;
> >>> +		goto err_out;
> >>> +	}
> >>>  
> >>>  	/*
> >>>  	 * If no sub-node was found, we still need to set nports to
> >>>  	 * one in order to be able to use the
> >>>  	 * ahci_platform_[en|dis]able_[phys|regulators] functions.
> >>>  	 */
> >>> -	if (!child_nodes)
> >>> -		hpriv->nports = 1;
> >>> +	hpriv->nports = child_nodes ?: 1;
> >>
> > 
> >> This change is not necessary and makes the code far less easy to read.
> > 
> > elaborate please. What change? What part of this change makes the code
> > less easy to read?
> 

> You changed:
> 
> 	if (!child_nodes)
> 		hpriv->nports = 1;
> 
> to:
> 
> 	hpriv->nports = child_nodes ?: 1;
> 
> That is the same. So the change is not needed in the first place, and worse,
> makes the code way harder to read for no good reason.

No, they aren't the same:
+	if (!child_nodes)
+		hpriv->nports = 1;
and
+	hpriv->nports = child_nodes ?: 1;
aren't equivalent. The equivalent implementation would be:
+	if (child_nodes)
+		hpriv->nports = child_nodes;
+	else
+		hpriv->nports = 1;

As I said in the patchlog, hpriv->nports is updated now only if
of_get_child_count() returns a valid number of the child nodes,
ports, which semantically is more correct. In the previous
implementation it was always set to the number of child nodes
no matter whether that value was correct or not.

Regarding the ternary operator with omitted operand. Well, it's not
that rare beast in the kernel:
$ grep -r "?:" kernel/ drivers/ mm/ fs/ block/ | wc -l
699
But if you insist in it being not that readable, I can replace it with
more bulky if-else statement. Do you?

-Sergey

> 
> > 
> > -Sergey
> > 
> >>
> >>>  
> >>>  	hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
> >>>  	if (!hpriv->phys) {
> >>
> >>
> >> -- 
> >> Damien Le Moal
> >> Western Digital Research
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities
  2022-06-16  0:28       ` Damien Le Moal
@ 2022-06-17 20:31         ` Serge Semin
  2022-06-18  6:52           ` Damien Le Moal
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-17 20:31 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Thu, Jun 16, 2022 at 09:28:18AM +0900, Damien Le Moal wrote:
> On 2022/06/16 5:58, Serge Semin wrote:
> > On Tue, Jun 14, 2022 at 05:32:41PM +0900, Damien Le Moal wrote:
> >> On 6/10/22 17:17, Serge Semin wrote:
> >>> Currently not all of the Port-specific capabilities listed in the
> >>
> >> s/listed/are listed
> >>
> >>> PORT_CMD-enumeration. Let's extend that set with the Cold Presence
> >>> Detection and Mechanical Presence Switch attached to the Port flags [1] so
> >>> to closeup the set of the platform-specific port-capabilities flags.  Note
> >>> these flags are supposed to be set by the platform firmware if there is
> >>> one. Alternatively as we are about to do they can be set by means of the
> >>> OF properties.
> >>>
> >>> While at it replace PORT_IRQ_DEV_ILCK with PORT_IRQ_DMPS and fix the
> >>> comment there. In accordance with [2] that IRQ flag is supposed to
> >>> indicate the state of the signal coming from the Mechanical Presence
> >>> Switch.
> >>>
> >>> [1] Serial ATA AHCI 1.3.1 Specification, p.27
> >>> [2] Serial ATA AHCI 1.3.1 Specification, p.24, p.88
> >>>
> >>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> >>> Reviewed-by: Hannes Reinecke <hare@suse.de>
> >>>
> >>> ---
> >>>
> >>> Changelog v4:
> >>> - Fix the DMPS macros name in the patch log. (@Sergei Shtylyov)
> >>> ---
> >>>  drivers/ata/ahci.h | 7 ++++++-
> >>>  1 file changed, 6 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> >>> index 7d834deefeb9..f501531bd1b3 100644
> >>> --- a/drivers/ata/ahci.h
> >>> +++ b/drivers/ata/ahci.h
> >>> @@ -138,7 +138,7 @@ enum {
> >>>  	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
> >>>  
> >>>  	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
> >>> -	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
> >>> +	PORT_IRQ_DMPS		= (1 << 7), /* mechanical presence status */
> >>>  	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
> >>>  	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
> >>>  	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
> >>> @@ -166,6 +166,8 @@ enum {
> >>>  	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
> >>>  	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
> >>>  	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
> >>> +	PORT_CMD_CPD		= (1 << 20), /* Cold Presence Detection */
> >>> +	PORT_CMD_MPSP		= (1 << 19), /* Mechanical Presence Switch */
> >>>  	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
> >>>  	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
> >>>  	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
> >>> @@ -181,6 +183,9 @@ enum {
> >>>  	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
> >>>  	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
> >>>  
> >>> +	PORT_CMD_CAP		= PORT_CMD_HPCP | PORT_CMD_MPSP |
> >>> +				  PORT_CMD_CPD | PORT_CMD_ESP | PORT_CMD_FBSCP,
> >>
> > 
> >> What is this one for ? A comment above it would be nice.
> > 
> > Isn't it obviously inferrable from the definition and the item name?
> 

> I am guessing from the name. Am I guessing OK ? A comment would still be nice.
> Why just these bits ? There are more cap/support indicator bits in that port cmd
> bitfield. So why this particular set of bits ? What do they mean all together ?

Normally the variable/constant name should be self-content (as the
kernel coding style doc states and what the common sense suggests). So
the reader could correctly guess its purpose/content/value. In this
case PORT_CMD_CAP - means PORT CMD capabilities mask. All of the
possible flags have been set in that mask. There are no more
capabilities in the PORT CMD register left undeclared. That's why the
name is selected the way it is and why I haven't added any comment in
here (what the kernel coding style says about the over-commenting the
code).

> 
> Sure I can go and read the specs to figure it out. But again, a comment would
> avoid readers of the code to have to decrypt all that.

If you still insist on having an additional comment. I can add
something like "/* PORT_CMD capabilities mask */". Are you ok with it?

-Sergey

> 
> > 
> > -Sergey
> > 
> >>
> >>> +
> >>>  	/* PORT_FBS bits */
> >>>  	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
> >>>  	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
> >>
> >>
> >> -- 
> >> Damien Le Moal
> >> Western Digital Research
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 16/23] ata: ahci: Introduce firmware-specific caps initialization
  2022-06-16  0:29       ` Damien Le Moal
@ 2022-06-17 20:32         ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-17 20:32 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Thu, Jun 16, 2022 at 09:29:50AM +0900, Damien Le Moal wrote:
> On 2022/06/16 6:11, Serge Semin wrote:
> > On Tue, Jun 14, 2022 at 05:42:35PM +0900, Damien Le Moal wrote:
> >> On 6/10/22 17:17, Serge Semin wrote:
> >>> There are systems with no BIOS or comprehensive embedded firmware which
> >>> could be able to properly initialize the SATA AHCI controller
> >>> platform-specific capabilities. In that case a good alternative to having
> >>> a clever bootloader is to create a device tree node with the properties
> >>> well describing all the AHCI-related platform specifics. All the settings
> >>> which are normally detected and marked as available in the HBA and its
> >>> ports capabilities fields [1] could be defined in the platform DTB by
> >>> means of a set of the dedicated properties. Such approach perfectly fits
> >>> to the DTB-philosophy - to provide hardware/platform description.
> >>>
> >>> So here we suggest to extend the SATA AHCI device tree bindings with two
> >>> additional DT-properties:
> >>> 1) "hba-cap" - HBA platform generic capabilities like:
> >>>    - SSS - Staggered Spin-up support.
> >>>    - SMPS - Mechanical Presence Switch support.
> >>> 2) "hba-port-cap" - HBA platform port capabilities like:
> >>>    - HPCP - Hot Plug Capable Port.
> >>>    - MPSP - Mechanical Presence Switch Attached to Port.
> >>>    - CPD - Cold Presence Detection.
> >>>    - ESP - External SATA Port.
> >>>    - FBSCP - FIS-based Switching Capable Port.
> >>> All of these capabilities require to have a corresponding hardware
> >>> configuration. Thus it's ok to have them defined in DTB.
> >>>
> >>> Even though the driver currently takes into account the state of the ESP
> >>> and FBSCP flags state only, there is nothing wrong with having all of them
> >>> supported by the generic AHCI library in order to have a complete OF-based
> >>> platform-capabilities initialization procedure. These properties will be
> >>> parsed in the ahci_platform_get_resources() method and their values will
> >>> be stored in the saved_* fields of the ahci_host_priv structure, which in
> >>> its turn then will be used to restore the H.CAP, H.PI and P#.CMD
> >>> capability fields on device init and after HBA reset.
> >>>
> >>> Please note this modification concerns the HW-init HBA and its ports flags
> >>> only, which are by specification [1] are supposed to be initialized by the
> >>> BIOS/platform firmware/expansion ROM and which are normally declared in
> >>> the one-time-writable-after-reset register fields. Even though these flags
> >>> aren't supposed to be cleared after HBA reset some AHCI instances may
> >>> violate that rule so we still need to perform the fields resetting after
> >>> each reset. Luckily the corresponding functionality has already been
> >>> partly implemented in the framework of the ahci_save_initial_config() and
> >>> ahci_restore_initial_config() methods.
> >>>
> >>> [1] Serial ATA AHCI 1.3.1 Specification, p. 103
> >>>
> >>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> >>>
> >>> ---
> >>>
> >>> Changelog v4:
> >>> - Convert the boolean properties to the bitfield DT-properties. (@Rob)
> >>> ---
> >>>  drivers/ata/ahci.h             |  1 +
> >>>  drivers/ata/libahci.c          | 51 ++++++++++++++++++++++++++++------
> >>>  drivers/ata/libahci_platform.c | 41 +++++++++++++++++++++++++--
> >>>  3 files changed, 82 insertions(+), 11 deletions(-)
> >>>
> >>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> >>> index 8b9826533ae5..0de221055961 100644
> >>> --- a/drivers/ata/ahci.h
> >>> +++ b/drivers/ata/ahci.h
> >>> @@ -337,6 +337,7 @@ struct ahci_host_priv {
> >>>  	u32			saved_cap;	/* saved initial cap */
> >>>  	u32			saved_cap2;	/* saved initial cap2 */
> >>>  	u32			saved_port_map;	/* saved initial port_map */
> >>> +	u32			saved_port_cap[AHCI_MAX_PORTS]; /* saved port_cap */
> >>>  	u32 			em_loc; /* enclosure management location */
> >>>  	u32			em_buf_sz;	/* EM buffer size in byte */
> >>>  	u32			em_msg_type;	/* EM message type */
> >>> diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
> >>> index 1ffaa5f5f21a..954386a2b500 100644
> >>> --- a/drivers/ata/libahci.c
> >>> +++ b/drivers/ata/libahci.c
> >>> @@ -16,6 +16,7 @@
> >>>   * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
> >>>   */
> >>>  
> >>> +#include <linux/bitops.h>
> >>>  #include <linux/kernel.h>
> >>>  #include <linux/gfp.h>
> >>>  #include <linux/module.h>
> >>> @@ -443,16 +444,28 @@ static ssize_t ahci_show_em_supported(struct device *dev,
> >>>  void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
> >>>  {
> >>>  	void __iomem *mmio = hpriv->mmio;
> >>> -	u32 cap, cap2, vers, port_map;
> >>> +	void __iomem *port_mmio;
> >>> +	unsigned long port_map;
> >>> +	u32 cap, cap2, vers;
> >>>  	int i;
> >>>  
> >>>  	/* make sure AHCI mode is enabled before accessing CAP */
> >>>  	ahci_enable_ahci(mmio);
> >>>  
> >>> -	/* Values prefixed with saved_ are written back to host after
> >>> -	 * reset.  Values without are used for driver operation.
> >>> +	/*
> >>> +	 * Values prefixed with saved_ are written back to the HBA and ports
> >>> +	 * registers after reset. Values without are used for driver operation.
> >>> +	 */
> >>> +
> >>> +	/*
> >>> +	 * Override HW-init HBA capability fields with the platform-specific
> >>> +	 * values. The rest of the HBA capabilities are defined as Read-only
> >>> +	 * and can't be modified in CSR anyway.
> >>>  	 */
> >>> -	hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
> >>> +	cap = readl(mmio + HOST_CAP);
> >>> +	if (hpriv->saved_cap)
> >>> +		cap = (cap & ~(HOST_CAP_SSS | HOST_CAP_MPS)) | hpriv->saved_cap;
> >>> +	hpriv->saved_cap = cap;
> >>>  
> >>>  	/* CAP2 register is only defined for AHCI 1.2 and later */
> >>>  	vers = readl(mmio + HOST_VERSION);
> >>> @@ -519,7 +532,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
> >>>  	/* Override the HBA ports mapping if the platform needs it */
> >>>  	port_map = readl(mmio + HOST_PORTS_IMPL);
> >>>  	if (hpriv->saved_port_map && port_map != hpriv->saved_port_map) {
> >>> -		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
> >>> +		dev_info(dev, "forcing port_map 0x%lx -> 0x%x\n",
> >>
> > 
> >> This change is not necessary.
> > 
> > It is. The port_map type has been changed.
> 
> Ignore. When I read the patches the other day, the mailer font had that "l" look
> like a "1" :) My mistake.

Ok.)

-Sergey

> 
> > 
> >>
> >>>  			 port_map, hpriv->saved_port_map);
> >>>  		port_map = hpriv->saved_port_map;
> >>>  	} else {
> >>> @@ -527,7 +540,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
> >>>  	}
> >>>  
> >>>  	if (hpriv->mask_port_map) {
> >>> -		dev_warn(dev, "masking port_map 0x%x -> 0x%x\n",
> >>> +		dev_warn(dev, "masking port_map 0x%lx -> 0x%lx\n",
> >>
> >> Same.
> > 
> > ditto
> > 
> >>
> >>>  			port_map,
> >>>  			port_map & hpriv->mask_port_map);
> >>>  		port_map &= hpriv->mask_port_map;
> >>> @@ -546,7 +559,7 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
> >>>  		 */
> >>>  		if (map_ports > ahci_nr_ports(cap)) {
> >>>  			dev_warn(dev,
> >>> -				 "implemented port map (0x%x) contains more ports than nr_ports (%u), using nr_ports\n",
> >>> +				 "implemented port map (0x%lx) contains more ports than nr_ports (%u), using nr_ports\n",
> >>
> >> Same.
> > 
> > ditto.
> > 
> >>
> >>>  				 port_map, ahci_nr_ports(cap));
> >>>  			port_map = 0;
> >>>  		}
> >>> @@ -555,12 +568,26 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
> >>>  	/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
> >>>  	if (!port_map && vers < 0x10300) {
> >>>  		port_map = (1 << ahci_nr_ports(cap)) - 1;
> >>> -		dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
> >>> +		dev_warn(dev, "forcing PORTS_IMPL to 0x%lx\n", port_map);
> >>
> >> And again not needed.
> > 
> > and ditto.
> > 
> >>
> >>>  
> >>>  		/* write the fixed up value to the PI register */
> >>>  		hpriv->saved_port_map = port_map;
> >>>  	}
> >>>  
> >>> +	/*
> >>> +	 * Preserve the ports capabilities defined by the platform. Note there
> >>> +	 * is no need in storing the rest of the P#.CMD fields since they are
> >>> +	 * volatile.
> >>> +	 */
> >>> +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> >>> +		if (hpriv->saved_port_cap[i])
> >>> +			continue;
> >>> +
> >>> +		port_mmio = __ahci_port_base(hpriv, i);
> >>> +		hpriv->saved_port_cap[i] =
> >>> +			readl(port_mmio + PORT_CMD) & PORT_CMD_CAP;
> >>> +	}
> >>> +
> >>>  	/* record values to use during operation */
> >>>  	hpriv->cap = cap;
> >>>  	hpriv->cap2 = cap2;
> >>> @@ -590,13 +617,21 @@ EXPORT_SYMBOL_GPL(ahci_save_initial_config);
> >>>  static void ahci_restore_initial_config(struct ata_host *host)
> >>>  {
> >>>  	struct ahci_host_priv *hpriv = host->private_data;
> >>> +	unsigned long port_map = hpriv->port_map;
> >>>  	void __iomem *mmio = hpriv->mmio;
> >>> +	void __iomem *port_mmio;
> >>> +	int i;
> >>>  
> >>>  	writel(hpriv->saved_cap, mmio + HOST_CAP);
> >>>  	if (hpriv->saved_cap2)
> >>>  		writel(hpriv->saved_cap2, mmio + HOST_CAP2);
> >>>  	writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
> >>>  	(void) readl(mmio + HOST_PORTS_IMPL);	/* flush */
> >>> +
> >>> +	for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
> >>> +		port_mmio = __ahci_port_base(hpriv, i);
> >>> +		writel(hpriv->saved_port_cap[i], port_mmio + PORT_CMD);
> >>> +	}
> >>>  }
> >>>  
> >>>  static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
> >>> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
> >>> index efe640603f3f..8b542a8bc487 100644
> >>> --- a/drivers/ata/libahci_platform.c
> >>> +++ b/drivers/ata/libahci_platform.c
> >>> @@ -23,6 +23,7 @@
> >>>  #include <linux/pm_runtime.h>
> >>>  #include <linux/of_platform.h>
> >>>  #include <linux/reset.h>
> >>> +
> >>
> >> white line change.
> > 
> > Ok. I'll drop it.
> > 
> > -Sergey
> > 
> >>
> >>>  #include "ahci.h"
> >>>  
> >>>  static void ahci_host_stop(struct ata_host *host);
> >>> @@ -383,6 +384,34 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
> >>>  	return rc;
> >>>  }
> >>>  
> >>> +static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv,
> >>> +				      struct device *dev)
> >>> +{
> >>> +	struct device_node *child;
> >>> +	u32 port;
> >>> +
> >>> +	if (!of_property_read_u32(dev->of_node, "hba-cap", &hpriv->saved_cap))
> >>> +		hpriv->saved_cap &= (HOST_CAP_SSS | HOST_CAP_MPS);
> >>> +
> >>> +	of_property_read_u32(dev->of_node,
> >>> +			     "ports-implemented", &hpriv->saved_port_map);
> >>> +
> >>> +	for_each_child_of_node(dev->of_node, child) {
> >>> +		if (!of_device_is_available(child))
> >>> +			continue;
> >>> +
> >>> +		if (of_property_read_u32(child, "reg", &port)) {
> >>> +			of_node_put(child);
> >>> +			return -EINVAL;
> >>> +		}
> >>> +
> >>> +		if (!of_property_read_u32(child, "hba-port-cap", &hpriv->saved_port_cap[port]))
> >>> +			hpriv->saved_port_cap[port] &= PORT_CMD_CAP;
> >>> +	}
> >>> +
> >>> +	return 0;
> >>> +}
> >>> +
> >>>  /**
> >>>   * ahci_platform_get_resources - Get platform resources
> >>>   * @pdev: platform device to get resources for
> >>> @@ -523,9 +552,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
> >>>  		goto err_out;
> >>>  	}
> >>>  
> >>> -	of_property_read_u32(dev->of_node,
> >>> -			     "ports-implemented", &hpriv->saved_port_map);
> >>> -
> >>>  	if (child_nodes) {
> >>>  		for_each_child_of_node(dev->of_node, child) {
> >>>  			u32 port;
> >>> @@ -590,6 +616,15 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
> >>>  		if (rc == -EPROBE_DEFER)
> >>>  			goto err_out;
> >>>  	}
> >>> +
> >>> +	/*
> >>> +	 * Retrieve firmware-specific flags which then will be used to set
> >>> +	 * the HW-init fields of HBA and its ports
> >>> +	 */
> >>> +	rc = ahci_platform_get_firmware(hpriv, dev);
> >>> +	if (rc)
> >>> +		goto err_out;
> >>> +
> >>>  	pm_runtime_enable(dev);
> >>>  	pm_runtime_get_sync(dev);
> >>>  	hpriv->got_runtime_pm = true;
> >>
> >>
> >> -- 
> >> Damien Le Moal
> >> Western Digital Research
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-16  0:33       ` Damien Le Moal
@ 2022-06-17 20:34         ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-17 20:34 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Thu, Jun 16, 2022 at 09:33:22AM +0900, Damien Le Moal wrote:
> On 2022/06/16 6:48, Serge Semin wrote:
> [...]
> >> MODULE_LICENSE("GPL v2");
> >>
> >> To match the file header SPDX.
> > 
> > No. Please see the commit bf7fbeeae6db ("module: Cure the
> > MODULE_LICENSE "GPL" vs. "GPL v2" bogosity") and what checkpatch.pl
> > says should the "GPL v2" string is used in the module license block.
> > More info regarding this macro and the possible license values are
> > described here:
> > Documentation/process/license-rules.rst
> 

> ah ! OK. I was not 100% sure. Doing a quick grep, there is still a lot of (half
> ?) of "GPL v2" vs "GPL".
> 
> Ignore this then.

Ok.

-Sergey

> 
> > 
> > -Sergey
> > 
> >>
> >>> diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
> >>> index 9b56490ecbc3..8f5572a9f8f1 100644
> >>> --- a/drivers/ata/ahci_platform.c
> >>> +++ b/drivers/ata/ahci_platform.c
> >>> @@ -80,9 +80,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
> >>>  static const struct of_device_id ahci_of_match[] = {
> >>>  	{ .compatible = "generic-ahci", },
> >>>  	/* Keep the following compatibles for device tree compatibility */
> >>> -	{ .compatible = "snps,spear-ahci", },
> >>>  	{ .compatible = "ibm,476gtr-ahci", },
> >>> -	{ .compatible = "snps,dwc-ahci", },
> >>>  	{ .compatible = "hisilicon,hisi-ahci", },
> >>>  	{ .compatible = "cavium,octeon-7130-ahci", },
> >>>  	{ /* sentinel */ }
> >>
> >>
> >> -- 
> >> Damien Le Moal
> >> Western Digital Research
> > 
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-16  0:31           ` Damien Le Moal
@ 2022-06-17 20:36             ` Serge Semin
  2022-06-18  6:54               ` Damien Le Moal
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-17 20:36 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Randy Dunlap, Serge Semin, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

On Thu, Jun 16, 2022 at 09:31:30AM +0900, Damien Le Moal wrote:
> On 2022/06/16 6:30, Serge Semin wrote:
> > On Fri, Jun 10, 2022 at 04:34:13PM -0700, Randy Dunlap wrote:
> >> Hi Serge,
> >>
> >> On 6/10/22 14:58, Serge Semin wrote:
> >>> On Fri, Jun 10, 2022 at 09:34:46AM -0700, Randy Dunlap wrote:
> >>>> Hi--
> >>>
> >>> Hi Randy
> >>>
> >>>>
> >>>> On 6/10/22 01:17, Serge Semin wrote:
> >>>>> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> >>>>> index bb45a9c00514..95e0e022b5bb 100644
> >>>>> --- a/drivers/ata/Kconfig
> >>>>> +++ b/drivers/ata/Kconfig
> >>>>> @@ -176,6 +176,16 @@ config AHCI_DM816
> >>>>>  
> >>>>>  	  If unsure, say N.
> >>>>>  
> >>>>> +config AHCI_DWC
> >>>>> +	tristate "Synopsys DWC AHCI SATA support"
> >>>>> +	select SATA_HOST
> >>>>> +	default SATA_AHCI_PLATFORM
> >>>>
> >>>
> >>>> I don't think this needs to default to SATA_AHCI_PLATFORM.
> >>>> It might build a driver that isn't needed.
> >>>> And it's incompatible with "If unsure, say N."
> >>>
> >>> Basically you are right, but this particular setting is connected with
> >>> the modification I've done in the drivers/ata/ahci_platform.c driver
> >>> in the framework of this commit. I've moved the "snps,spear-ahci" and
> >>> "snps,dwc-ahci" compatible devices support to the new driver. Thus
> >>> should I omit the SATA_AHCI_PLATFORM dependency their default kernel
> >>> configs will lack the corresponding controllers support. If it's not a
> >>> problem and we can rely on the kernel build system ability to ask
> >>> whether the new config needs to be set/cleared, then I would be very
> >>> happy to drop the default setting. What do you think?
> >>
> > 
> >> I'd prefer to try it like that.
> >> If it becomes a problem, we can go back to this v4 patch.
> > 
> > Agreed then (seeing Damien is silent about your comment).
> 

> I have not thought about it :)
> I do not use SATA PLATFORM at all, so I am not familiar with its dependencies.
> Will have a look and do my usual build tests anyway.

Ok. I'll be waiting for you reply in this regard the before
re-submitting the next series version.

-Sergey

> 
> > 
> > -Sergey
> > 
> >>
> >>>>> +	help
> >>>>> +	  This option enables support for the Synopsys DWC AHCI SATA
> >>>>> +	  controller implementation.
> >>>>> +
> >>>>> +	  If unsure, say N.
> >>>>
> >>>> -- 
> >>>> ~Randy
> >>
> >> Thanks.
> >> -- 
> >> ~Randy
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 08/23] ata: libahci_platform: Sanity check the DT child nodes number
  2022-06-17 20:18         ` Serge Semin
@ 2022-06-18  6:49           ` Damien Le Moal
  0 siblings, 0 replies; 80+ messages in thread
From: Damien Le Moal @ 2022-06-18  6:49 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On 6/18/22 05:18, Serge Semin wrote:
> On Thu, Jun 16, 2022 at 09:25:48AM +0900, Damien Le Moal wrote:
>> On 2022/06/16 5:53, Serge Semin wrote:
>>> On Tue, Jun 14, 2022 at 05:23:33PM +0900, Damien Le Moal wrote:
>>>> On 6/10/22 17:17, Serge Semin wrote:
>>>>> Having greater than AHCI_MAX_PORTS (32) ports detected isn't that critical
>>>>> from the further AHCI-platform initialization point of view since
>>>>> exceeding the ports upper limit will cause allocating more resources than
>>>>> will be used afterwards. But detecting too many child DT-nodes doesn't
>>>>> seem right since it's very unlikely to have it on an ordinary platform. In
>>>>> accordance with the AHCI specification there can't be more than 32 ports
>>>>> implemented at least due to having the CAP.NP field of 5 bits wide and the
>>>>> PI register of dword size. Thus if such situation is found the DTB must
>>>>> have been corrupted and the data read from it shouldn't be reliable. Let's
>>>>> consider that as an erroneous situation and halt further resources
>>>>> allocation.
>>>>>
>>>>> Note it's logically more correct to have the nports set only after the
>>>>> initialization value is checked for being sane. So while at it let's make
>>>>> sure nports is assigned with a correct value.
>>>>>
>>>>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
>>>>> Reviewed-by: Hannes Reinecke <hare@suse.de>
>>>>>
>>>>> ---
>>>>>
>>>>> Changelog v2:
>>>>> - Drop the else word from the child_nodes value checking if-else-if
>>>>>   statement (@Damien) and convert the after-else part into the ternary
>>>>>   operator-based statement.
>>>>>
>>>>> Changelog v4:
>>>>> - Fix some logical mistakes in the patch log. (@Sergei Shtylyov)
>>>>> ---
>>>>>  drivers/ata/libahci_platform.c | 13 ++++++++++---
>>>>>  1 file changed, 10 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
>>>>> index 814804582d1d..8aed7b29c7ab 100644
>>>>> --- a/drivers/ata/libahci_platform.c
>>>>> +++ b/drivers/ata/libahci_platform.c
>>>>> @@ -451,15 +451,22 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
>>>>>  		}
>>>>>  	}
>>>>>  
>>>>> -	hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
>>>>> +	/*
>>>>> +	 * Too many sub-nodes most likely means having something wrong with
>>>>> +	 * the firmware.
>>>>> +	 */
>>>>> +	child_nodes = of_get_child_count(dev->of_node);
>>>>> +	if (child_nodes > AHCI_MAX_PORTS) {
>>>>> +		rc = -EINVAL;
>>>>> +		goto err_out;
>>>>> +	}
>>>>>  
>>>>>  	/*
>>>>>  	 * If no sub-node was found, we still need to set nports to
>>>>>  	 * one in order to be able to use the
>>>>>  	 * ahci_platform_[en|dis]able_[phys|regulators] functions.
>>>>>  	 */
>>>>> -	if (!child_nodes)
>>>>> -		hpriv->nports = 1;
>>>>> +	hpriv->nports = child_nodes ?: 1;
>>>>
>>>
>>>> This change is not necessary and makes the code far less easy to read.
>>>
>>> elaborate please. What change? What part of this change makes the code
>>> less easy to read?
>>
> 
>> You changed:
>>
>> 	if (!child_nodes)
>> 		hpriv->nports = 1;
>>
>> to:
>>
>> 	hpriv->nports = child_nodes ?: 1;
>>
>> That is the same. So the change is not needed in the first place, and worse,
>> makes the code way harder to read for no good reason.
> 
> No, they aren't the same:
> +	if (!child_nodes)
> +		hpriv->nports = 1;
> and
> +	hpriv->nports = child_nodes ?: 1;
> aren't equivalent. The equivalent implementation would be:
> +	if (child_nodes)
> +		hpriv->nports = child_nodes;
> +	else
> +		hpriv->nports = 1;

Then use this code. That cryptic C code is hard to read.

> 
> As I said in the patchlog, hpriv->nports is updated now only if
> of_get_child_count() returns a valid number of the child nodes,
> ports, which semantically is more correct. In the previous
> implementation it was always set to the number of child nodes
> no matter whether that value was correct or not.
> 
> Regarding the ternary operator with omitted operand. Well, it's not
> that rare beast in the kernel:
> $ grep -r "?:" kernel/ drivers/ mm/ fs/ block/ | wc -l
> 699
> But if you insist in it being not that readable, I can replace it with
> more bulky if-else statement. Do you?

Yes please, use the spelled out if/else. I prefer easy to read code rather
than loosing time trying to understand that cryptic C syntax, which  I
actually did not know about.

> 
> -Sergey
> 
>>
>>>
>>> -Sergey
>>>
>>>>
>>>>>  
>>>>>  	hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
>>>>>  	if (!hpriv->phys) {
>>>>
>>>>
>>>> -- 
>>>> Damien Le Moal
>>>> Western Digital Research
>>
>>
>> -- 
>> Damien Le Moal
>> Western Digital Research


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities
  2022-06-17 20:31         ` Serge Semin
@ 2022-06-18  6:52           ` Damien Le Moal
  2022-06-18  8:10             ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-18  6:52 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On 6/18/22 05:31, Serge Semin wrote:
> On Thu, Jun 16, 2022 at 09:28:18AM +0900, Damien Le Moal wrote:
>> On 2022/06/16 5:58, Serge Semin wrote:
>>> On Tue, Jun 14, 2022 at 05:32:41PM +0900, Damien Le Moal wrote:
>>>> On 6/10/22 17:17, Serge Semin wrote:
>>>>> Currently not all of the Port-specific capabilities listed in the
>>>>
>>>> s/listed/are listed
>>>>
>>>>> PORT_CMD-enumeration. Let's extend that set with the Cold Presence
>>>>> Detection and Mechanical Presence Switch attached to the Port flags [1] so
>>>>> to closeup the set of the platform-specific port-capabilities flags.  Note
>>>>> these flags are supposed to be set by the platform firmware if there is
>>>>> one. Alternatively as we are about to do they can be set by means of the
>>>>> OF properties.
>>>>>
>>>>> While at it replace PORT_IRQ_DEV_ILCK with PORT_IRQ_DMPS and fix the
>>>>> comment there. In accordance with [2] that IRQ flag is supposed to
>>>>> indicate the state of the signal coming from the Mechanical Presence
>>>>> Switch.
>>>>>
>>>>> [1] Serial ATA AHCI 1.3.1 Specification, p.27
>>>>> [2] Serial ATA AHCI 1.3.1 Specification, p.24, p.88
>>>>>
>>>>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
>>>>> Reviewed-by: Hannes Reinecke <hare@suse.de>
>>>>>
>>>>> ---
>>>>>
>>>>> Changelog v4:
>>>>> - Fix the DMPS macros name in the patch log. (@Sergei Shtylyov)
>>>>> ---
>>>>>  drivers/ata/ahci.h | 7 ++++++-
>>>>>  1 file changed, 6 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
>>>>> index 7d834deefeb9..f501531bd1b3 100644
>>>>> --- a/drivers/ata/ahci.h
>>>>> +++ b/drivers/ata/ahci.h
>>>>> @@ -138,7 +138,7 @@ enum {
>>>>>  	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
>>>>>  
>>>>>  	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
>>>>> -	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
>>>>> +	PORT_IRQ_DMPS		= (1 << 7), /* mechanical presence status */
>>>>>  	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
>>>>>  	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
>>>>>  	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
>>>>> @@ -166,6 +166,8 @@ enum {
>>>>>  	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
>>>>>  	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
>>>>>  	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
>>>>> +	PORT_CMD_CPD		= (1 << 20), /* Cold Presence Detection */
>>>>> +	PORT_CMD_MPSP		= (1 << 19), /* Mechanical Presence Switch */
>>>>>  	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
>>>>>  	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
>>>>>  	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
>>>>> @@ -181,6 +183,9 @@ enum {
>>>>>  	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
>>>>>  	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
>>>>>  
>>>>> +	PORT_CMD_CAP		= PORT_CMD_HPCP | PORT_CMD_MPSP |
>>>>> +				  PORT_CMD_CPD | PORT_CMD_ESP | PORT_CMD_FBSCP,
>>>>
>>>
>>>> What is this one for ? A comment above it would be nice.
>>>
>>> Isn't it obviously inferrable from the definition and the item name?
>>
> 
>> I am guessing from the name. Am I guessing OK ? A comment would still be nice.
>> Why just these bits ? There are more cap/support indicator bits in that port cmd
>> bitfield. So why this particular set of bits ? What do they mean all together ?
> 
> Normally the variable/constant name should be self-content (as the
> kernel coding style doc states and what the common sense suggests). So
> the reader could correctly guess its purpose/content/value. In this
> case PORT_CMD_CAP - means PORT CMD capabilities mask. All of the
> possible flags have been set in that mask. There are no more
> capabilities in the PORT CMD register left undeclared. That's why the
> name is selected the way it is and why I haven't added any comment in
> here (what the kernel coding style says about the over-commenting the
> code).

Yes, I understood from the name what it is. What I do NOT understand is
why all the feature bits are not there. Why this subset only ? A comment
about that would be nice so that the reason for it is not lost.

> 
>>
>> Sure I can go and read the specs to figure it out. But again, a comment would
>> avoid readers of the code to have to decrypt all that.
> 
> If you still insist on having an additional comment. I can add
> something like "/* PORT_CMD capabilities mask */". Are you ok with it?

That does not help on its own. The macro name says that already. I would
like a note about why only these features are selected.

> 
> -Sergey
> 
>>
>>>
>>> -Sergey
>>>
>>>>
>>>>> +
>>>>>  	/* PORT_FBS bits */
>>>>>  	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
>>>>>  	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
>>>>
>>>>
>>>> -- 
>>>> Damien Le Moal
>>>> Western Digital Research
>>
>>
>> -- 
>> Damien Le Moal
>> Western Digital Research


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support
  2022-06-17 20:36             ` Serge Semin
@ 2022-06-18  6:54               ` Damien Le Moal
  0 siblings, 0 replies; 80+ messages in thread
From: Damien Le Moal @ 2022-06-18  6:54 UTC (permalink / raw)
  To: Serge Semin
  Cc: Randy Dunlap, Serge Semin, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Alexey Malahov, Pavel Parkhomenko, Rob Herring,
	linux-ide, linux-kernel, devicetree

On 6/18/22 05:36, Serge Semin wrote:
> On Thu, Jun 16, 2022 at 09:31:30AM +0900, Damien Le Moal wrote:
>> On 2022/06/16 6:30, Serge Semin wrote:
>>> On Fri, Jun 10, 2022 at 04:34:13PM -0700, Randy Dunlap wrote:
>>>> Hi Serge,
>>>>
>>>> On 6/10/22 14:58, Serge Semin wrote:
>>>>> On Fri, Jun 10, 2022 at 09:34:46AM -0700, Randy Dunlap wrote:
>>>>>> Hi--
>>>>>
>>>>> Hi Randy
>>>>>
>>>>>>
>>>>>> On 6/10/22 01:17, Serge Semin wrote:
>>>>>>> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
>>>>>>> index bb45a9c00514..95e0e022b5bb 100644
>>>>>>> --- a/drivers/ata/Kconfig
>>>>>>> +++ b/drivers/ata/Kconfig
>>>>>>> @@ -176,6 +176,16 @@ config AHCI_DM816
>>>>>>>  
>>>>>>>  	  If unsure, say N.
>>>>>>>  
>>>>>>> +config AHCI_DWC
>>>>>>> +	tristate "Synopsys DWC AHCI SATA support"
>>>>>>> +	select SATA_HOST
>>>>>>> +	default SATA_AHCI_PLATFORM
>>>>>>
>>>>>
>>>>>> I don't think this needs to default to SATA_AHCI_PLATFORM.
>>>>>> It might build a driver that isn't needed.
>>>>>> And it's incompatible with "If unsure, say N."
>>>>>
>>>>> Basically you are right, but this particular setting is connected with
>>>>> the modification I've done in the drivers/ata/ahci_platform.c driver
>>>>> in the framework of this commit. I've moved the "snps,spear-ahci" and
>>>>> "snps,dwc-ahci" compatible devices support to the new driver. Thus
>>>>> should I omit the SATA_AHCI_PLATFORM dependency their default kernel
>>>>> configs will lack the corresponding controllers support. If it's not a
>>>>> problem and we can rely on the kernel build system ability to ask
>>>>> whether the new config needs to be set/cleared, then I would be very
>>>>> happy to drop the default setting. What do you think?
>>>>
>>>
>>>> I'd prefer to try it like that.
>>>> If it becomes a problem, we can go back to this v4 patch.
>>>
>>> Agreed then (seeing Damien is silent about your comment).
>>
> 
>> I have not thought about it :)
>> I do not use SATA PLATFORM at all, so I am not familiar with its dependencies.
>> Will have a look and do my usual build tests anyway.
> 
> Ok. I'll be waiting for you reply in this regard the before
> re-submitting the next series version.

Please send a fixed-up new version. I will use that to look at builds and
config dependencies.


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities
  2022-06-18  6:52           ` Damien Le Moal
@ 2022-06-18  8:10             ` Serge Semin
  2022-06-28 12:08               ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-18  8:10 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Sat, Jun 18, 2022 at 03:52:28PM +0900, Damien Le Moal wrote:
> On 6/18/22 05:31, Serge Semin wrote:
> > On Thu, Jun 16, 2022 at 09:28:18AM +0900, Damien Le Moal wrote:
> >> On 2022/06/16 5:58, Serge Semin wrote:
> >>> On Tue, Jun 14, 2022 at 05:32:41PM +0900, Damien Le Moal wrote:
> >>>> On 6/10/22 17:17, Serge Semin wrote:
> >>>>> Currently not all of the Port-specific capabilities listed in the
> >>>>
> >>>> s/listed/are listed
> >>>>
> >>>>> PORT_CMD-enumeration. Let's extend that set with the Cold Presence
> >>>>> Detection and Mechanical Presence Switch attached to the Port flags [1] so
> >>>>> to closeup the set of the platform-specific port-capabilities flags.  Note
> >>>>> these flags are supposed to be set by the platform firmware if there is
> >>>>> one. Alternatively as we are about to do they can be set by means of the
> >>>>> OF properties.
> >>>>>
> >>>>> While at it replace PORT_IRQ_DEV_ILCK with PORT_IRQ_DMPS and fix the
> >>>>> comment there. In accordance with [2] that IRQ flag is supposed to
> >>>>> indicate the state of the signal coming from the Mechanical Presence
> >>>>> Switch.
> >>>>>
> >>>>> [1] Serial ATA AHCI 1.3.1 Specification, p.27
> >>>>> [2] Serial ATA AHCI 1.3.1 Specification, p.24, p.88
> >>>>>
> >>>>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> >>>>> Reviewed-by: Hannes Reinecke <hare@suse.de>
> >>>>>
> >>>>> ---
> >>>>>
> >>>>> Changelog v4:
> >>>>> - Fix the DMPS macros name in the patch log. (@Sergei Shtylyov)
> >>>>> ---
> >>>>>  drivers/ata/ahci.h | 7 ++++++-
> >>>>>  1 file changed, 6 insertions(+), 1 deletion(-)
> >>>>>
> >>>>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> >>>>> index 7d834deefeb9..f501531bd1b3 100644
> >>>>> --- a/drivers/ata/ahci.h
> >>>>> +++ b/drivers/ata/ahci.h
> >>>>> @@ -138,7 +138,7 @@ enum {
> >>>>>  	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
> >>>>>  
> >>>>>  	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
> >>>>> -	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
> >>>>> +	PORT_IRQ_DMPS		= (1 << 7), /* mechanical presence status */
> >>>>>  	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
> >>>>>  	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
> >>>>>  	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
> >>>>> @@ -166,6 +166,8 @@ enum {
> >>>>>  	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
> >>>>>  	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
> >>>>>  	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
> >>>>> +	PORT_CMD_CPD		= (1 << 20), /* Cold Presence Detection */
> >>>>> +	PORT_CMD_MPSP		= (1 << 19), /* Mechanical Presence Switch */
> >>>>>  	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
> >>>>>  	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
> >>>>>  	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
> >>>>> @@ -181,6 +183,9 @@ enum {
> >>>>>  	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
> >>>>>  	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
> >>>>>  
> >>>>> +	PORT_CMD_CAP		= PORT_CMD_HPCP | PORT_CMD_MPSP |
> >>>>> +				  PORT_CMD_CPD | PORT_CMD_ESP | PORT_CMD_FBSCP,
> >>>>
> >>>
> >>>> What is this one for ? A comment above it would be nice.
> >>>
> >>> Isn't it obviously inferrable from the definition and the item name?
> >>
> > 
> >> I am guessing from the name. Am I guessing OK ? A comment would still be nice.
> >> Why just these bits ? There are more cap/support indicator bits in that port cmd
> >> bitfield. So why this particular set of bits ? What do they mean all together ?
> > 
> > Normally the variable/constant name should be self-content (as the
> > kernel coding style doc states and what the common sense suggests). So
> > the reader could correctly guess its purpose/content/value. In this
> > case PORT_CMD_CAP - means PORT CMD capabilities mask. All of the
> > possible flags have been set in that mask. There are no more
> > capabilities in the PORT CMD register left undeclared. That's why the
> > name is selected the way it is and why I haven't added any comment in
> > here (what the kernel coding style says about the over-commenting the
> > code).
> 

> Yes, I understood from the name what it is. What I do NOT understand is
> why all the feature bits are not there. Why this subset only ? A comment
> about that would be nice so that the reason for it is not lost.

Well, because it's indeed "PORT_CMD capabilities mask", and not features,
not setups, not settings, not status flags, etc. As I said all the port
Capabilities have been listed in that mask:
PORT_CMD_FBSCP	BIT(22) - FIS-based Switching Capable Port
PORT_CMD_ESP	BIT(21) - External SATA Port
PORT_CMD_CPD	BIT(20) - Cold Presence Detect
PORT_CMD_MPSP	BIT(19) - Mechanical Presence Switch Attached to Port
PORT_CMD_HPCP	BIT(18) - Hot Plug Capable Port
I've or'ed-them-up in a single mask => PORT_CMD_CAP in order to work
with them independently from the rest of the PORT_CMD CSR fields.

Unlike the generic controller CAP/CAP2 registers, which consists of the
device capabilities only, PORT_CMD contains various R/W settings (PM, LED
driver, etc), RO status flags (CMD-list running, FIS recv running, etc)
and amongst other the RO/Wo !port-specific capabilities!. The later ones
indicate the platform-specific device features. Since the register
contains flags with the intermixed nature, I need to have a mask to at
least get the capabilities and preserve them between the device
resets. That's why the PORT_CMD_CAP has been introduced in the
framework of this patch. Its name was chosen with a reference to the
CAP registers, see:
HOST_CAP, HOST_CAP2, and finally my PORT_CMD_CAP.

> 
> > 
> >>
> >> Sure I can go and read the specs to figure it out. But again, a comment would
> >> avoid readers of the code to have to decrypt all that.
> > 
> > If you still insist on having an additional comment. I can add
> > something like "/* PORT_CMD capabilities mask */". Are you ok with it?
> 

> That does not help on its own. The macro name says that already. I would
> like a note about why only these features are selected.

Please see the explanation above. I don't see what else to say about
that mask, because in short what I said above really means "PORT_CMD
capabilities mask". So should you have some more clever text, which
would be more suitable here, please tell me and I'll add it to the
patch.

Regarding what you said earlier. In order to fully understand the
AHCI driver a hacker would always need to read the specs. There is
just no way to do that effectively enough without the controller
manual at hands. And the PORT_CMD capabilities isn't the most
complicated part of the device.

-Sergey

> 
> > 
> > -Sergey
> > 
> >>
> >>>
> >>> -Sergey
> >>>
> >>>>
> >>>>> +
> >>>>>  	/* PORT_FBS bits */
> >>>>>  	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
> >>>>>  	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
> >>>>
> >>>>
> >>>> -- 
> >>>> Damien Le Moal
> >>>> Western Digital Research
> >>
> >>
> >> -- 
> >> Damien Le Moal
> >> Western Digital Research
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities
  2022-06-18  8:10             ` Serge Semin
@ 2022-06-28 12:08               ` Serge Semin
  2022-06-29  1:35                 ` Damien Le Moal
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-06-28 12:08 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

Damien,
Any notes to the comments below?

-Sergey

On Sat, Jun 18, 2022 at 11:10:55AM +0300, Serge Semin wrote:
> On Sat, Jun 18, 2022 at 03:52:28PM +0900, Damien Le Moal wrote:
> > On 6/18/22 05:31, Serge Semin wrote:
> > > On Thu, Jun 16, 2022 at 09:28:18AM +0900, Damien Le Moal wrote:
> > >> On 2022/06/16 5:58, Serge Semin wrote:
> > >>> On Tue, Jun 14, 2022 at 05:32:41PM +0900, Damien Le Moal wrote:
> > >>>> On 6/10/22 17:17, Serge Semin wrote:
> > >>>>> Currently not all of the Port-specific capabilities listed in the
> > >>>>
> > >>>> s/listed/are listed
> > >>>>
> > >>>>> PORT_CMD-enumeration. Let's extend that set with the Cold Presence
> > >>>>> Detection and Mechanical Presence Switch attached to the Port flags [1] so
> > >>>>> to closeup the set of the platform-specific port-capabilities flags.  Note
> > >>>>> these flags are supposed to be set by the platform firmware if there is
> > >>>>> one. Alternatively as we are about to do they can be set by means of the
> > >>>>> OF properties.
> > >>>>>
> > >>>>> While at it replace PORT_IRQ_DEV_ILCK with PORT_IRQ_DMPS and fix the
> > >>>>> comment there. In accordance with [2] that IRQ flag is supposed to
> > >>>>> indicate the state of the signal coming from the Mechanical Presence
> > >>>>> Switch.
> > >>>>>
> > >>>>> [1] Serial ATA AHCI 1.3.1 Specification, p.27
> > >>>>> [2] Serial ATA AHCI 1.3.1 Specification, p.24, p.88
> > >>>>>
> > >>>>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > >>>>> Reviewed-by: Hannes Reinecke <hare@suse.de>
> > >>>>>
> > >>>>> ---
> > >>>>>
> > >>>>> Changelog v4:
> > >>>>> - Fix the DMPS macros name in the patch log. (@Sergei Shtylyov)
> > >>>>> ---
> > >>>>>  drivers/ata/ahci.h | 7 ++++++-
> > >>>>>  1 file changed, 6 insertions(+), 1 deletion(-)
> > >>>>>
> > >>>>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> > >>>>> index 7d834deefeb9..f501531bd1b3 100644
> > >>>>> --- a/drivers/ata/ahci.h
> > >>>>> +++ b/drivers/ata/ahci.h
> > >>>>> @@ -138,7 +138,7 @@ enum {
> > >>>>>  	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
> > >>>>>  
> > >>>>>  	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
> > >>>>> -	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
> > >>>>> +	PORT_IRQ_DMPS		= (1 << 7), /* mechanical presence status */
> > >>>>>  	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
> > >>>>>  	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
> > >>>>>  	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
> > >>>>> @@ -166,6 +166,8 @@ enum {
> > >>>>>  	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
> > >>>>>  	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
> > >>>>>  	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
> > >>>>> +	PORT_CMD_CPD		= (1 << 20), /* Cold Presence Detection */
> > >>>>> +	PORT_CMD_MPSP		= (1 << 19), /* Mechanical Presence Switch */
> > >>>>>  	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
> > >>>>>  	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
> > >>>>>  	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
> > >>>>> @@ -181,6 +183,9 @@ enum {
> > >>>>>  	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
> > >>>>>  	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
> > >>>>>  
> > >>>>> +	PORT_CMD_CAP		= PORT_CMD_HPCP | PORT_CMD_MPSP |
> > >>>>> +				  PORT_CMD_CPD | PORT_CMD_ESP | PORT_CMD_FBSCP,
> > >>>>
> > >>>
> > >>>> What is this one for ? A comment above it would be nice.
> > >>>
> > >>> Isn't it obviously inferrable from the definition and the item name?
> > >>
> > > 
> > >> I am guessing from the name. Am I guessing OK ? A comment would still be nice.
> > >> Why just these bits ? There are more cap/support indicator bits in that port cmd
> > >> bitfield. So why this particular set of bits ? What do they mean all together ?
> > > 
> > > Normally the variable/constant name should be self-content (as the
> > > kernel coding style doc states and what the common sense suggests). So
> > > the reader could correctly guess its purpose/content/value. In this
> > > case PORT_CMD_CAP - means PORT CMD capabilities mask. All of the
> > > possible flags have been set in that mask. There are no more
> > > capabilities in the PORT CMD register left undeclared. That's why the
> > > name is selected the way it is and why I haven't added any comment in
> > > here (what the kernel coding style says about the over-commenting the
> > > code).
> > 
> 
> > Yes, I understood from the name what it is. What I do NOT understand is
> > why all the feature bits are not there. Why this subset only ? A comment
> > about that would be nice so that the reason for it is not lost.
> 
> Well, because it's indeed "PORT_CMD capabilities mask", and not features,
> not setups, not settings, not status flags, etc. As I said all the port
> Capabilities have been listed in that mask:
> PORT_CMD_FBSCP	BIT(22) - FIS-based Switching Capable Port
> PORT_CMD_ESP	BIT(21) - External SATA Port
> PORT_CMD_CPD	BIT(20) - Cold Presence Detect
> PORT_CMD_MPSP	BIT(19) - Mechanical Presence Switch Attached to Port
> PORT_CMD_HPCP	BIT(18) - Hot Plug Capable Port
> I've or'ed-them-up in a single mask => PORT_CMD_CAP in order to work
> with them independently from the rest of the PORT_CMD CSR fields.
> 
> Unlike the generic controller CAP/CAP2 registers, which consists of the
> device capabilities only, PORT_CMD contains various R/W settings (PM, LED
> driver, etc), RO status flags (CMD-list running, FIS recv running, etc)
> and amongst other the RO/Wo !port-specific capabilities!. The later ones
> indicate the platform-specific device features. Since the register
> contains flags with the intermixed nature, I need to have a mask to at
> least get the capabilities and preserve them between the device
> resets. That's why the PORT_CMD_CAP has been introduced in the
> framework of this patch. Its name was chosen with a reference to the
> CAP registers, see:
> HOST_CAP, HOST_CAP2, and finally my PORT_CMD_CAP.
> 
> > 
> > > 
> > >>
> > >> Sure I can go and read the specs to figure it out. But again, a comment would
> > >> avoid readers of the code to have to decrypt all that.
> > > 
> > > If you still insist on having an additional comment. I can add
> > > something like "/* PORT_CMD capabilities mask */". Are you ok with it?
> > 
> 
> > That does not help on its own. The macro name says that already. I would
> > like a note about why only these features are selected.
> 
> Please see the explanation above. I don't see what else to say about
> that mask, because in short what I said above really means "PORT_CMD
> capabilities mask". So should you have some more clever text, which
> would be more suitable here, please tell me and I'll add it to the
> patch.
> 
> Regarding what you said earlier. In order to fully understand the
> AHCI driver a hacker would always need to read the specs. There is
> just no way to do that effectively enough without the controller
> manual at hands. And the PORT_CMD capabilities isn't the most
> complicated part of the device.
> 
> -Sergey
> 
> > 
> > > 
> > > -Sergey
> > > 
> > >>
> > >>>
> > >>> -Sergey
> > >>>
> > >>>>
> > >>>>> +
> > >>>>>  	/* PORT_FBS bits */
> > >>>>>  	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
> > >>>>>  	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
> > >>>>
> > >>>>
> > >>>> -- 
> > >>>> Damien Le Moal
> > >>>> Western Digital Research
> > >>
> > >>
> > >> -- 
> > >> Damien Le Moal
> > >> Western Digital Research
> > 
> > 
> > -- 
> > Damien Le Moal
> > Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema
  2022-06-17 19:37     ` Serge Semin
@ 2022-06-28 12:10       ` Serge Semin
  2022-07-06 22:36       ` Rob Herring
  1 sibling, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-28 12:10 UTC (permalink / raw)
  To: Rob Herring
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Krzysztof Kozlowski, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

Rob,
I am very much waiting for your response to the notes below.

-Sergey

On Fri, Jun 17, 2022 at 10:37:44PM +0300, Serge Semin wrote:
> On Tue, Jun 14, 2022 at 04:27:54PM -0600, Rob Herring wrote:
> > On Fri, Jun 10, 2022 at 11:17:55AM +0300, Serge Semin wrote:
> > > Synopsys AHCI SATA controller is mainly compatible with the generic AHCI
> > > SATA controller except a few peculiarities and the platform environment
> > > requirements. In particular it can have one or two reference clocks to
> > > feed up its AXI/AHB interface and SATA PHYs domain and at least one reset
> > > control for the application clock domain. In addition to that the DMA
> > > interface of each port can be tuned up to work with the predefined maximum
> > > data chunk size. Note unlike generic AHCI controller DWC AHCI can't have
> > > more than 8 ports. All of that is reflected in the new DWC AHCI SATA
> > > device DT binding.
> > > 
> > > Note the DWC AHCI SATA controller DT-schema has been created in a way so
> > > to be reused for the vendor-specific DT-schemas (see for example the
> > > "snps,dwc-ahci" compatible string binding). One of which we are about to
> > > introduce.
> > > 
> > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > > 
> > > ---
> > > 
> > > Changelog v2:
> > > - Replace min/max constraints of the snps,{tx,rx}-ts-max property with
> > >   enum [ 1, 2, 4, ..., 1024 ]. (@Rob)
> > > 
> > > Changelog v4:
> > > - Decrease the "additionalProperties" property identation otherwise it's
> > >   percieved as the node property instead of the key one. (@Rob)
> > > - Use the ahci-port properties definition from the AHCI common schema
> > >   in order to extend it with DWC AHCI SATA port properties. (@Rob)
> > > - Remove the Hannes' rb tag since the patch content has changed.
> > > ---
> > >  .../bindings/ata/ahci-platform.yaml           |   8 --
> > >  .../bindings/ata/snps,dwc-ahci.yaml           | 129 ++++++++++++++++++
> > >  2 files changed, 129 insertions(+), 8 deletions(-)
> > >  create mode 100644 Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > 
> > > diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > index e19cf9828e68..7dc2a2e8f598 100644
> > > --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > @@ -30,8 +30,6 @@ select:
> > >            - marvell,armada-3700-ahci
> > >            - marvell,armada-8k-ahci
> > >            - marvell,berlin2q-ahci
> > > -          - snps,dwc-ahci
> > > -          - snps,spear-ahci
> > >    required:
> > >      - compatible
> > >  
> > > @@ -48,17 +46,11 @@ properties:
> > >                - marvell,berlin2-ahci
> > >                - marvell,berlin2q-ahci
> > >            - const: generic-ahci
> > > -      - items:
> > > -          - enum:
> > > -              - rockchip,rk3568-dwc-ahci
> > > -          - const: snps,dwc-ahci
> > >        - enum:
> > >            - cavium,octeon-7130-ahci
> > >            - hisilicon,hisi-ahci
> > >            - ibm,476gtr-ahci
> > >            - marvell,armada-3700-ahci
> > > -          - snps,dwc-ahci
> > > -          - snps,spear-ahci
> > >  
> > >    reg:
> > >      minItems: 1
> > > diff --git a/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > new file mode 100644
> > > index 000000000000..af78f6c9b857
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > @@ -0,0 +1,129 @@
> > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > +%YAML 1.2
> > > +---
> > > +$id: http://devicetree.org/schemas/ata/snps,dwc-ahci.yaml#
> > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > +
> > > +title: Synopsys DWC AHCI SATA controller
> > > +
> > > +maintainers:
> > > +  - Serge Semin <fancer.lancer@gmail.com>
> > > +
> > > +description:
> > > +  This document defines device tree bindings for the Synopsys DWC
> > > +  implementation of the AHCI SATA controller.
> > > +
> > > +allOf:
> > > +  - $ref: ahci-common.yaml#
> > > +
> > > +properties:
> > > +  compatible:
> > > +    oneOf:
> > > +      - description: Synopsys AHCI SATA-compatible devices
> > > +        contains:
> > > +          const: snps,dwc-ahci
> > > +      - description: SPEAr1340 AHCI SATA device
> > > +        const: snps,spear-ahci
> > > +      - description: Rockhip RK3568 ahci controller
> > > +        const: rockchip,rk3568-dwc-ahci
> > 
> 
> > This is never true because there is a fallback. We should keep what we 
> > had before.
> 
> Could you be more specific what you meant? I don't see
> "snps,spear-ahci" and "rockchip,rk3568-dwc-ahci" used with the fallback
> string so modification is correct in that case.
> 
> My idea was to have the compatible strings with the required generic
> fallback "snps,dwc-ahci" for all new devices thus identifying the
> controller IP-core origin. But later you said "The generic IP block
> fallbacks have proven to be useless." I do agree that functionally it
> isn't that often used, but in some cases it can be handy for instance
> to implement quirks in the generic code or use the fallback as an
> additional info regarding the IP-core origin/version. So if I were you
> I wouldn't be that strict about dropping the generic IP-core fallback
> identifier. It's much easier to have it specified from the very
> beginning than adding it after it has been declared as not required.
> 
> > 
> > 
> > > +
> > > +  reg:
> > > +    maxItems: 1
> > > +
> > > +  interrupts:
> > > +    maxItems: 1
> > > +
> > > +  clocks:
> > > +    description:
> > > +      Basic DWC AHCI SATA clock sources like application AXI/AHB BIU clock
> > > +      and embedded PHYs reference clock together with vendor-specific set
> > > +      of clocks.
> > > +    minItems: 1
> > > +    maxItems: 4
> > > +
> > > +  clock-names:
> > > +    contains:
> > > +      anyOf:
> > > +        - description: Application AXI/AHB BIU clock source
> > > +          enum:
> > > +            - aclk
> > > +            - sata
> > > +        - description: SATA Ports reference clock
> > > +          enum:
> > > +            - ref
> > > +            - sata_ref
> > > +
> > > +  resets:
> > > +    description:
> > > +      At least basic core and application clock domains reset is normally
> > > +      supported by the DWC AHCI SATA controller. Some platform specific
> > > +      clocks can be also specified though.
> > 
> 
> > s/clocks/resets/ ?
> 
> Right, but only in the reference to "platform specific clocks" -> "... resets".
> 
> > 
> > This allows any number of resets which isn't great. I think this schema 
> > should just be the 'simple' cases where there's only 1 reset and 1 
> > clock (or how many the DWC block actually has if you have that info). 
> > More complicated cases get there own schema.
> 
> DWC SATA reference manual claims there can be resets implemented to
> each clock domain.
> 1) PM-clk <- PM-rst - PM keep-alive clock/reset.
> 2) aclk/hclk <- aresetn/hresetn - AXI/AHB clock domain/reset.
> 3) rbc*_clk <- rbc*_rst - PHY Receive Clock domain/reset. (Up to
> number of ports <= 8.)
> 4) asic*_clk <- asic*_rst - PHY Transmit Clock domain/reset. (Up to
> number of ports <= 8.)
> 5) rxoob*_clk <- rxoob*_rst - RxOOB Detection Clock domain/reset. (Up
> to number of ports <= 8.)
> 
> So to speak the IP-core can be equipped with up to 26 clocks and
> resets. Should we be more strict we would have needed to define the
> properties with all the names above and permit up to 26 clocks/resets
> items. (Do you want it to be done?). In our case for instance there
> is "aclk" and a single common "ref" clock for all 3, 4 and 5 domain
> (clock 1 is missing).
> 
> -Sergey
> 
> > 
> > > +
> > > +  reset-names:
> > > +    contains:
> > > +      description: Core and application clock domains reset control
> > > +      const: arst
> > > +
> > > +patternProperties:
> > > +  "^sata-port@[0-9a-e]$":
> > > +    $ref: '#/$defs/dwc-ahci-port'
> > > +
> > > +    unevaluatedProperties: false
> > > +
> > > +required:
> > > +  - compatible
> > > +  - reg
> > > +  - interrupts
> > > +
> > > +unevaluatedProperties: false
> > > +
> > > +$defs:
> > > +  dwc-ahci-port:
> > > +    $ref: /schemas/ata/ahci-common.yaml#/$defs/ahci-port
> > > +
> > > +    properties:
> > > +      reg:
> > > +        minimum: 0
> > > +        maximum: 7
> > > +
> > > +      snps,tx-ts-max:
> > > +        $ref: /schemas/types.yaml#/definitions/uint32
> > > +        description: Maximal size of Tx DMA transactions in FIFO words
> > > +        enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
> > > +
> > > +      snps,rx-ts-max:
> > > +        $ref: /schemas/types.yaml#/definitions/uint32
> > > +        description: Maximal size of Rx DMA transactions in FIFO words
> > > +        enum: [ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 ]
> > > +
> > > +examples:
> > > +  - |
> > > +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> > > +    #include <dt-bindings/ata/ahci.h>
> > > +
> > > +    sata@122f0000 {
> > > +      compatible = "snps,dwc-ahci";
> > > +      reg = <0x122F0000 0x1ff>;
> > > +      #address-cells = <1>;
> > > +      #size-cells = <0>;
> > > +
> > > +      interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
> > > +
> > > +      clocks = <&clock1>, <&clock2>;
> > > +      clock-names = "aclk", "ref";
> > > +
> > > +      phys = <&sata_phy>;
> > > +      phy-names = "sata-phy";
> > > +
> > > +      ports-implemented = <0x1>;
> > > +
> > > +      sata-port@0 {
> > > +        reg = <0>;
> > > +
> > > +        hba-port-cap = <HBA_PORT_FBSCP>;
> > > +
> > > +        snps,tx-ts-max = <512>;
> > > +        snps,rx-ts-max = <512>;
> > > +      };
> > > +    };
> > > +...
> > > -- 
> > > 2.35.1
> > > 
> > > 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities
  2022-06-28 12:08               ` Serge Semin
@ 2022-06-29  1:35                 ` Damien Le Moal
  2022-06-29  1:47                   ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Damien Le Moal @ 2022-06-29  1:35 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On 6/28/22 21:08, Serge Semin wrote:
> Damien,
> Any notes to the comments below?

Been very busy and had no time to look at this. Please post your latest
version of the series and we'll go from there.

> 
> -Sergey
> 
> On Sat, Jun 18, 2022 at 11:10:55AM +0300, Serge Semin wrote:
>> On Sat, Jun 18, 2022 at 03:52:28PM +0900, Damien Le Moal wrote:
>>> On 6/18/22 05:31, Serge Semin wrote:
>>>> On Thu, Jun 16, 2022 at 09:28:18AM +0900, Damien Le Moal wrote:
>>>>> On 2022/06/16 5:58, Serge Semin wrote:
>>>>>> On Tue, Jun 14, 2022 at 05:32:41PM +0900, Damien Le Moal wrote:
>>>>>>> On 6/10/22 17:17, Serge Semin wrote:
>>>>>>>> Currently not all of the Port-specific capabilities listed in the
>>>>>>>
>>>>>>> s/listed/are listed
>>>>>>>
>>>>>>>> PORT_CMD-enumeration. Let's extend that set with the Cold Presence
>>>>>>>> Detection and Mechanical Presence Switch attached to the Port flags [1] so
>>>>>>>> to closeup the set of the platform-specific port-capabilities flags.  Note
>>>>>>>> these flags are supposed to be set by the platform firmware if there is
>>>>>>>> one. Alternatively as we are about to do they can be set by means of the
>>>>>>>> OF properties.
>>>>>>>>
>>>>>>>> While at it replace PORT_IRQ_DEV_ILCK with PORT_IRQ_DMPS and fix the
>>>>>>>> comment there. In accordance with [2] that IRQ flag is supposed to
>>>>>>>> indicate the state of the signal coming from the Mechanical Presence
>>>>>>>> Switch.
>>>>>>>>
>>>>>>>> [1] Serial ATA AHCI 1.3.1 Specification, p.27
>>>>>>>> [2] Serial ATA AHCI 1.3.1 Specification, p.24, p.88
>>>>>>>>
>>>>>>>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
>>>>>>>> Reviewed-by: Hannes Reinecke <hare@suse.de>
>>>>>>>>
>>>>>>>> ---
>>>>>>>>
>>>>>>>> Changelog v4:
>>>>>>>> - Fix the DMPS macros name in the patch log. (@Sergei Shtylyov)
>>>>>>>> ---
>>>>>>>>  drivers/ata/ahci.h | 7 ++++++-
>>>>>>>>  1 file changed, 6 insertions(+), 1 deletion(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
>>>>>>>> index 7d834deefeb9..f501531bd1b3 100644
>>>>>>>> --- a/drivers/ata/ahci.h
>>>>>>>> +++ b/drivers/ata/ahci.h
>>>>>>>> @@ -138,7 +138,7 @@ enum {
>>>>>>>>  	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
>>>>>>>>  
>>>>>>>>  	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
>>>>>>>> -	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
>>>>>>>> +	PORT_IRQ_DMPS		= (1 << 7), /* mechanical presence status */
>>>>>>>>  	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
>>>>>>>>  	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
>>>>>>>>  	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
>>>>>>>> @@ -166,6 +166,8 @@ enum {
>>>>>>>>  	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
>>>>>>>>  	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
>>>>>>>>  	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
>>>>>>>> +	PORT_CMD_CPD		= (1 << 20), /* Cold Presence Detection */
>>>>>>>> +	PORT_CMD_MPSP		= (1 << 19), /* Mechanical Presence Switch */
>>>>>>>>  	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
>>>>>>>>  	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
>>>>>>>>  	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
>>>>>>>> @@ -181,6 +183,9 @@ enum {
>>>>>>>>  	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
>>>>>>>>  	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
>>>>>>>>  
>>>>>>>> +	PORT_CMD_CAP		= PORT_CMD_HPCP | PORT_CMD_MPSP |
>>>>>>>> +				  PORT_CMD_CPD | PORT_CMD_ESP | PORT_CMD_FBSCP,
>>>>>>>
>>>>>>
>>>>>>> What is this one for ? A comment above it would be nice.
>>>>>>
>>>>>> Isn't it obviously inferrable from the definition and the item name?
>>>>>
>>>>
>>>>> I am guessing from the name. Am I guessing OK ? A comment would still be nice.
>>>>> Why just these bits ? There are more cap/support indicator bits in that port cmd
>>>>> bitfield. So why this particular set of bits ? What do they mean all together ?
>>>>
>>>> Normally the variable/constant name should be self-content (as the
>>>> kernel coding style doc states and what the common sense suggests). So
>>>> the reader could correctly guess its purpose/content/value. In this
>>>> case PORT_CMD_CAP - means PORT CMD capabilities mask. All of the
>>>> possible flags have been set in that mask. There are no more
>>>> capabilities in the PORT CMD register left undeclared. That's why the
>>>> name is selected the way it is and why I haven't added any comment in
>>>> here (what the kernel coding style says about the over-commenting the
>>>> code).
>>>
>>
>>> Yes, I understood from the name what it is. What I do NOT understand is
>>> why all the feature bits are not there. Why this subset only ? A comment
>>> about that would be nice so that the reason for it is not lost.
>>
>> Well, because it's indeed "PORT_CMD capabilities mask", and not features,
>> not setups, not settings, not status flags, etc. As I said all the port
>> Capabilities have been listed in that mask:
>> PORT_CMD_FBSCP	BIT(22) - FIS-based Switching Capable Port
>> PORT_CMD_ESP	BIT(21) - External SATA Port
>> PORT_CMD_CPD	BIT(20) - Cold Presence Detect
>> PORT_CMD_MPSP	BIT(19) - Mechanical Presence Switch Attached to Port
>> PORT_CMD_HPCP	BIT(18) - Hot Plug Capable Port
>> I've or'ed-them-up in a single mask => PORT_CMD_CAP in order to work
>> with them independently from the rest of the PORT_CMD CSR fields.
>>
>> Unlike the generic controller CAP/CAP2 registers, which consists of the
>> device capabilities only, PORT_CMD contains various R/W settings (PM, LED
>> driver, etc), RO status flags (CMD-list running, FIS recv running, etc)
>> and amongst other the RO/Wo !port-specific capabilities!. The later ones
>> indicate the platform-specific device features. Since the register
>> contains flags with the intermixed nature, I need to have a mask to at
>> least get the capabilities and preserve them between the device
>> resets. That's why the PORT_CMD_CAP has been introduced in the
>> framework of this patch. Its name was chosen with a reference to the
>> CAP registers, see:
>> HOST_CAP, HOST_CAP2, and finally my PORT_CMD_CAP.
>>
>>>
>>>>
>>>>>
>>>>> Sure I can go and read the specs to figure it out. But again, a comment would
>>>>> avoid readers of the code to have to decrypt all that.
>>>>
>>>> If you still insist on having an additional comment. I can add
>>>> something like "/* PORT_CMD capabilities mask */". Are you ok with it?
>>>
>>
>>> That does not help on its own. The macro name says that already. I would
>>> like a note about why only these features are selected.
>>
>> Please see the explanation above. I don't see what else to say about
>> that mask, because in short what I said above really means "PORT_CMD
>> capabilities mask". So should you have some more clever text, which
>> would be more suitable here, please tell me and I'll add it to the
>> patch.
>>
>> Regarding what you said earlier. In order to fully understand the
>> AHCI driver a hacker would always need to read the specs. There is
>> just no way to do that effectively enough without the controller
>> manual at hands. And the PORT_CMD capabilities isn't the most
>> complicated part of the device.
>>
>> -Sergey
>>
>>>
>>>>
>>>> -Sergey
>>>>
>>>>>
>>>>>>
>>>>>> -Sergey
>>>>>>
>>>>>>>
>>>>>>>> +
>>>>>>>>  	/* PORT_FBS bits */
>>>>>>>>  	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
>>>>>>>>  	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
>>>>>>>
>>>>>>>
>>>>>>> -- 
>>>>>>> Damien Le Moal
>>>>>>> Western Digital Research
>>>>>
>>>>>
>>>>> -- 
>>>>> Damien Le Moal
>>>>> Western Digital Research
>>>
>>>
>>> -- 
>>> Damien Le Moal
>>> Western Digital Research


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities
  2022-06-29  1:35                 ` Damien Le Moal
@ 2022-06-29  1:47                   ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-06-29  1:47 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Hans de Goede, Jens Axboe, Hannes Reinecke,
	Alexey Malahov, Pavel Parkhomenko, Rob Herring, linux-ide,
	linux-kernel, devicetree

On Wed, Jun 29, 2022 at 10:35:13AM +0900, Damien Le Moal wrote:
> On 6/28/22 21:08, Serge Semin wrote:
> > Damien,
> > Any notes to the comments below?
> 

> Been very busy and had no time to look at this. Please post your latest
> version of the series and we'll go from there.

Ok. As soon as I get the responses from Rob.

-Sergey

> 
> > 
> > -Sergey
> > 
> > On Sat, Jun 18, 2022 at 11:10:55AM +0300, Serge Semin wrote:
> >> On Sat, Jun 18, 2022 at 03:52:28PM +0900, Damien Le Moal wrote:
> >>> On 6/18/22 05:31, Serge Semin wrote:
> >>>> On Thu, Jun 16, 2022 at 09:28:18AM +0900, Damien Le Moal wrote:
> >>>>> On 2022/06/16 5:58, Serge Semin wrote:
> >>>>>> On Tue, Jun 14, 2022 at 05:32:41PM +0900, Damien Le Moal wrote:
> >>>>>>> On 6/10/22 17:17, Serge Semin wrote:
> >>>>>>>> Currently not all of the Port-specific capabilities listed in the
> >>>>>>>
> >>>>>>> s/listed/are listed
> >>>>>>>
> >>>>>>>> PORT_CMD-enumeration. Let's extend that set with the Cold Presence
> >>>>>>>> Detection and Mechanical Presence Switch attached to the Port flags [1] so
> >>>>>>>> to closeup the set of the platform-specific port-capabilities flags.  Note
> >>>>>>>> these flags are supposed to be set by the platform firmware if there is
> >>>>>>>> one. Alternatively as we are about to do they can be set by means of the
> >>>>>>>> OF properties.
> >>>>>>>>
> >>>>>>>> While at it replace PORT_IRQ_DEV_ILCK with PORT_IRQ_DMPS and fix the
> >>>>>>>> comment there. In accordance with [2] that IRQ flag is supposed to
> >>>>>>>> indicate the state of the signal coming from the Mechanical Presence
> >>>>>>>> Switch.
> >>>>>>>>
> >>>>>>>> [1] Serial ATA AHCI 1.3.1 Specification, p.27
> >>>>>>>> [2] Serial ATA AHCI 1.3.1 Specification, p.24, p.88
> >>>>>>>>
> >>>>>>>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> >>>>>>>> Reviewed-by: Hannes Reinecke <hare@suse.de>
> >>>>>>>>
> >>>>>>>> ---
> >>>>>>>>
> >>>>>>>> Changelog v4:
> >>>>>>>> - Fix the DMPS macros name in the patch log. (@Sergei Shtylyov)
> >>>>>>>> ---
> >>>>>>>>  drivers/ata/ahci.h | 7 ++++++-
> >>>>>>>>  1 file changed, 6 insertions(+), 1 deletion(-)
> >>>>>>>>
> >>>>>>>> diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
> >>>>>>>> index 7d834deefeb9..f501531bd1b3 100644
> >>>>>>>> --- a/drivers/ata/ahci.h
> >>>>>>>> +++ b/drivers/ata/ahci.h
> >>>>>>>> @@ -138,7 +138,7 @@ enum {
> >>>>>>>>  	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
> >>>>>>>>  
> >>>>>>>>  	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
> >>>>>>>> -	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
> >>>>>>>> +	PORT_IRQ_DMPS		= (1 << 7), /* mechanical presence status */
> >>>>>>>>  	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
> >>>>>>>>  	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
> >>>>>>>>  	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
> >>>>>>>> @@ -166,6 +166,8 @@ enum {
> >>>>>>>>  	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
> >>>>>>>>  	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
> >>>>>>>>  	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
> >>>>>>>> +	PORT_CMD_CPD		= (1 << 20), /* Cold Presence Detection */
> >>>>>>>> +	PORT_CMD_MPSP		= (1 << 19), /* Mechanical Presence Switch */
> >>>>>>>>  	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
> >>>>>>>>  	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
> >>>>>>>>  	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
> >>>>>>>> @@ -181,6 +183,9 @@ enum {
> >>>>>>>>  	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
> >>>>>>>>  	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
> >>>>>>>>  
> >>>>>>>> +	PORT_CMD_CAP		= PORT_CMD_HPCP | PORT_CMD_MPSP |
> >>>>>>>> +				  PORT_CMD_CPD | PORT_CMD_ESP | PORT_CMD_FBSCP,
> >>>>>>>
> >>>>>>
> >>>>>>> What is this one for ? A comment above it would be nice.
> >>>>>>
> >>>>>> Isn't it obviously inferrable from the definition and the item name?
> >>>>>
> >>>>
> >>>>> I am guessing from the name. Am I guessing OK ? A comment would still be nice.
> >>>>> Why just these bits ? There are more cap/support indicator bits in that port cmd
> >>>>> bitfield. So why this particular set of bits ? What do they mean all together ?
> >>>>
> >>>> Normally the variable/constant name should be self-content (as the
> >>>> kernel coding style doc states and what the common sense suggests). So
> >>>> the reader could correctly guess its purpose/content/value. In this
> >>>> case PORT_CMD_CAP - means PORT CMD capabilities mask. All of the
> >>>> possible flags have been set in that mask. There are no more
> >>>> capabilities in the PORT CMD register left undeclared. That's why the
> >>>> name is selected the way it is and why I haven't added any comment in
> >>>> here (what the kernel coding style says about the over-commenting the
> >>>> code).
> >>>
> >>
> >>> Yes, I understood from the name what it is. What I do NOT understand is
> >>> why all the feature bits are not there. Why this subset only ? A comment
> >>> about that would be nice so that the reason for it is not lost.
> >>
> >> Well, because it's indeed "PORT_CMD capabilities mask", and not features,
> >> not setups, not settings, not status flags, etc. As I said all the port
> >> Capabilities have been listed in that mask:
> >> PORT_CMD_FBSCP	BIT(22) - FIS-based Switching Capable Port
> >> PORT_CMD_ESP	BIT(21) - External SATA Port
> >> PORT_CMD_CPD	BIT(20) - Cold Presence Detect
> >> PORT_CMD_MPSP	BIT(19) - Mechanical Presence Switch Attached to Port
> >> PORT_CMD_HPCP	BIT(18) - Hot Plug Capable Port
> >> I've or'ed-them-up in a single mask => PORT_CMD_CAP in order to work
> >> with them independently from the rest of the PORT_CMD CSR fields.
> >>
> >> Unlike the generic controller CAP/CAP2 registers, which consists of the
> >> device capabilities only, PORT_CMD contains various R/W settings (PM, LED
> >> driver, etc), RO status flags (CMD-list running, FIS recv running, etc)
> >> and amongst other the RO/Wo !port-specific capabilities!. The later ones
> >> indicate the platform-specific device features. Since the register
> >> contains flags with the intermixed nature, I need to have a mask to at
> >> least get the capabilities and preserve them between the device
> >> resets. That's why the PORT_CMD_CAP has been introduced in the
> >> framework of this patch. Its name was chosen with a reference to the
> >> CAP registers, see:
> >> HOST_CAP, HOST_CAP2, and finally my PORT_CMD_CAP.
> >>
> >>>
> >>>>
> >>>>>
> >>>>> Sure I can go and read the specs to figure it out. But again, a comment would
> >>>>> avoid readers of the code to have to decrypt all that.
> >>>>
> >>>> If you still insist on having an additional comment. I can add
> >>>> something like "/* PORT_CMD capabilities mask */". Are you ok with it?
> >>>
> >>
> >>> That does not help on its own. The macro name says that already. I would
> >>> like a note about why only these features are selected.
> >>
> >> Please see the explanation above. I don't see what else to say about
> >> that mask, because in short what I said above really means "PORT_CMD
> >> capabilities mask". So should you have some more clever text, which
> >> would be more suitable here, please tell me and I'll add it to the
> >> patch.
> >>
> >> Regarding what you said earlier. In order to fully understand the
> >> AHCI driver a hacker would always need to read the specs. There is
> >> just no way to do that effectively enough without the controller
> >> manual at hands. And the PORT_CMD capabilities isn't the most
> >> complicated part of the device.
> >>
> >> -Sergey
> >>
> >>>
> >>>>
> >>>> -Sergey
> >>>>
> >>>>>
> >>>>>>
> >>>>>> -Sergey
> >>>>>>
> >>>>>>>
> >>>>>>>> +
> >>>>>>>>  	/* PORT_FBS bits */
> >>>>>>>>  	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
> >>>>>>>>  	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
> >>>>>>>
> >>>>>>>
> >>>>>>> -- 
> >>>>>>> Damien Le Moal
> >>>>>>> Western Digital Research
> >>>>>
> >>>>>
> >>>>> -- 
> >>>>> Damien Le Moal
> >>>>> Western Digital Research
> >>>
> >>>
> >>> -- 
> >>> Damien Le Moal
> >>> Western Digital Research
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema
  2022-06-17 19:37     ` Serge Semin
  2022-06-28 12:10       ` Serge Semin
@ 2022-07-06 22:36       ` Rob Herring
  2022-07-07 15:25         ` Serge Semin
  1 sibling, 1 reply; 80+ messages in thread
From: Rob Herring @ 2022-07-06 22:36 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Krzysztof Kozlowski, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

On Fri, Jun 17, 2022 at 10:37:44PM +0300, Serge Semin wrote:
> On Tue, Jun 14, 2022 at 04:27:54PM -0600, Rob Herring wrote:
> > On Fri, Jun 10, 2022 at 11:17:55AM +0300, Serge Semin wrote:
> > > Synopsys AHCI SATA controller is mainly compatible with the generic AHCI
> > > SATA controller except a few peculiarities and the platform environment
> > > requirements. In particular it can have one or two reference clocks to
> > > feed up its AXI/AHB interface and SATA PHYs domain and at least one reset
> > > control for the application clock domain. In addition to that the DMA
> > > interface of each port can be tuned up to work with the predefined maximum
> > > data chunk size. Note unlike generic AHCI controller DWC AHCI can't have
> > > more than 8 ports. All of that is reflected in the new DWC AHCI SATA
> > > device DT binding.
> > > 
> > > Note the DWC AHCI SATA controller DT-schema has been created in a way so
> > > to be reused for the vendor-specific DT-schemas (see for example the
> > > "snps,dwc-ahci" compatible string binding). One of which we are about to
> > > introduce.
> > > 
> > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > > 
> > > ---
> > > 
> > > Changelog v2:
> > > - Replace min/max constraints of the snps,{tx,rx}-ts-max property with
> > >   enum [ 1, 2, 4, ..., 1024 ]. (@Rob)
> > > 
> > > Changelog v4:
> > > - Decrease the "additionalProperties" property identation otherwise it's
> > >   percieved as the node property instead of the key one. (@Rob)
> > > - Use the ahci-port properties definition from the AHCI common schema
> > >   in order to extend it with DWC AHCI SATA port properties. (@Rob)
> > > - Remove the Hannes' rb tag since the patch content has changed.
> > > ---
> > >  .../bindings/ata/ahci-platform.yaml           |   8 --
> > >  .../bindings/ata/snps,dwc-ahci.yaml           | 129 ++++++++++++++++++
> > >  2 files changed, 129 insertions(+), 8 deletions(-)
> > >  create mode 100644 Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > 
> > > diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > index e19cf9828e68..7dc2a2e8f598 100644
> > > --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > @@ -30,8 +30,6 @@ select:
> > >            - marvell,armada-3700-ahci
> > >            - marvell,armada-8k-ahci
> > >            - marvell,berlin2q-ahci
> > > -          - snps,dwc-ahci
> > > -          - snps,spear-ahci
> > >    required:
> > >      - compatible
> > >  
> > > @@ -48,17 +46,11 @@ properties:
> > >                - marvell,berlin2-ahci
> > >                - marvell,berlin2q-ahci
> > >            - const: generic-ahci
> > > -      - items:
> > > -          - enum:
> > > -              - rockchip,rk3568-dwc-ahci
> > > -          - const: snps,dwc-ahci
> > >        - enum:
> > >            - cavium,octeon-7130-ahci
> > >            - hisilicon,hisi-ahci
> > >            - ibm,476gtr-ahci
> > >            - marvell,armada-3700-ahci
> > > -          - snps,dwc-ahci
> > > -          - snps,spear-ahci
> > >  
> > >    reg:
> > >      minItems: 1
> > > diff --git a/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > new file mode 100644
> > > index 000000000000..af78f6c9b857
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > @@ -0,0 +1,129 @@
> > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > +%YAML 1.2
> > > +---
> > > +$id: http://devicetree.org/schemas/ata/snps,dwc-ahci.yaml#
> > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > +
> > > +title: Synopsys DWC AHCI SATA controller
> > > +
> > > +maintainers:
> > > +  - Serge Semin <fancer.lancer@gmail.com>
> > > +
> > > +description:
> > > +  This document defines device tree bindings for the Synopsys DWC
> > > +  implementation of the AHCI SATA controller.
> > > +
> > > +allOf:
> > > +  - $ref: ahci-common.yaml#
> > > +
> > > +properties:
> > > +  compatible:
> > > +    oneOf:
> > > +      - description: Synopsys AHCI SATA-compatible devices
> > > +        contains:
> > > +          const: snps,dwc-ahci
> > > +      - description: SPEAr1340 AHCI SATA device
> > > +        const: snps,spear-ahci
> > > +      - description: Rockhip RK3568 ahci controller
> > > +        const: rockchip,rk3568-dwc-ahci
> > 
> 
> > This is never true because there is a fallback. We should keep what we 
> > had before.
> 
> Could you be more specific what you meant? I don't see
> "snps,spear-ahci" and "rockchip,rk3568-dwc-ahci" used with the fallback
> string so modification is correct in that case.

Spear does not, just rockchip:

arch/arm64/boot/dts/rockchip/rk3568.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
arch/arm64/boot/dts/rockchip/rk356x.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
arch/arm64/boot/dts/rockchip/rk356x.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";

So the 3rd entry is never true.

> My idea was to have the compatible strings with the required generic
> fallback "snps,dwc-ahci" for all new devices thus identifying the
> controller IP-core origin. But later you said "The generic IP block
> fallbacks have proven to be useless." I do agree that functionally it
> isn't that often used, but in some cases it can be handy for instance
> to implement quirks in the generic code or use the fallback as an
> additional info regarding the IP-core origin/version. So if I were you
> I wouldn't be that strict about dropping the generic IP-core fallback
> identifier. It's much easier to have it specified from the very
> beginning than adding it after it has been declared as not required.

I wish they were useful, but experience has shown they are not.

> > > +  reg:
> > > +    maxItems: 1
> > > +
> > > +  interrupts:
> > > +    maxItems: 1
> > > +
> > > +  clocks:
> > > +    description:
> > > +      Basic DWC AHCI SATA clock sources like application AXI/AHB BIU clock
> > > +      and embedded PHYs reference clock together with vendor-specific set
> > > +      of clocks.
> > > +    minItems: 1
> > > +    maxItems: 4
> > > +
> > > +  clock-names:
> > > +    contains:
> > > +      anyOf:
> > > +        - description: Application AXI/AHB BIU clock source
> > > +          enum:
> > > +            - aclk
> > > +            - sata
> > > +        - description: SATA Ports reference clock
> > > +          enum:
> > > +            - ref
> > > +            - sata_ref
> > > +
> > > +  resets:
> > > +    description:
> > > +      At least basic core and application clock domains reset is normally
> > > +      supported by the DWC AHCI SATA controller. Some platform specific
> > > +      clocks can be also specified though.
> > 
> 
> > s/clocks/resets/ ?
> 
> Right, but only in the reference to "platform specific clocks" -> "... resets".
> 
> > 
> > This allows any number of resets which isn't great. I think this schema 
> > should just be the 'simple' cases where there's only 1 reset and 1 
> > clock (or how many the DWC block actually has if you have that info). 
> > More complicated cases get there own schema.
> 
> DWC SATA reference manual claims there can be resets implemented to
> each clock domain.
> 1) PM-clk <- PM-rst - PM keep-alive clock/reset.
> 2) aclk/hclk <- aresetn/hresetn - AXI/AHB clock domain/reset.
> 3) rbc*_clk <- rbc*_rst - PHY Receive Clock domain/reset. (Up to
> number of ports <= 8.)
> 4) asic*_clk <- asic*_rst - PHY Transmit Clock domain/reset. (Up to
> number of ports <= 8.)
> 5) rxoob*_clk <- rxoob*_rst - RxOOB Detection Clock domain/reset. (Up
> to number of ports <= 8.)
> 
> So to speak the IP-core can be equipped with up to 26 clocks and
> resets. Should we be more strict we would have needed to define the
> properties with all the names above and permit up to 26 clocks/resets
> items. (Do you want it to be done?). In our case for instance there
> is "aclk" and a single common "ref" clock for all 3, 4 and 5 domain
> (clock 1 is missing).

I imagine most implementations just tie most clocks together.

I guess there's not going to be much new SATA h/w, so perhaps fine 
as-is.

Rob

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema
  2022-07-06 22:36       ` Rob Herring
@ 2022-07-07 15:25         ` Serge Semin
  2022-07-12 20:13           ` Rob Herring
  0 siblings, 1 reply; 80+ messages in thread
From: Serge Semin @ 2022-07-07 15:25 UTC (permalink / raw)
  To: Rob Herring
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Krzysztof Kozlowski, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

On Wed, Jul 06, 2022 at 04:36:42PM -0600, Rob Herring wrote:
> On Fri, Jun 17, 2022 at 10:37:44PM +0300, Serge Semin wrote:
> > On Tue, Jun 14, 2022 at 04:27:54PM -0600, Rob Herring wrote:
> > > On Fri, Jun 10, 2022 at 11:17:55AM +0300, Serge Semin wrote:
> > > > Synopsys AHCI SATA controller is mainly compatible with the generic AHCI
> > > > SATA controller except a few peculiarities and the platform environment
> > > > requirements. In particular it can have one or two reference clocks to
> > > > feed up its AXI/AHB interface and SATA PHYs domain and at least one reset
> > > > control for the application clock domain. In addition to that the DMA
> > > > interface of each port can be tuned up to work with the predefined maximum
> > > > data chunk size. Note unlike generic AHCI controller DWC AHCI can't have
> > > > more than 8 ports. All of that is reflected in the new DWC AHCI SATA
> > > > device DT binding.
> > > > 
> > > > Note the DWC AHCI SATA controller DT-schema has been created in a way so
> > > > to be reused for the vendor-specific DT-schemas (see for example the
> > > > "snps,dwc-ahci" compatible string binding). One of which we are about to
> > > > introduce.
> > > > 
> > > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > > > 
> > > > ---
> > > > 
> > > > Changelog v2:
> > > > - Replace min/max constraints of the snps,{tx,rx}-ts-max property with
> > > >   enum [ 1, 2, 4, ..., 1024 ]. (@Rob)
> > > > 
> > > > Changelog v4:
> > > > - Decrease the "additionalProperties" property identation otherwise it's
> > > >   percieved as the node property instead of the key one. (@Rob)
> > > > - Use the ahci-port properties definition from the AHCI common schema
> > > >   in order to extend it with DWC AHCI SATA port properties. (@Rob)
> > > > - Remove the Hannes' rb tag since the patch content has changed.
> > > > ---
> > > >  .../bindings/ata/ahci-platform.yaml           |   8 --
> > > >  .../bindings/ata/snps,dwc-ahci.yaml           | 129 ++++++++++++++++++
> > > >  2 files changed, 129 insertions(+), 8 deletions(-)
> > > >  create mode 100644 Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > > index e19cf9828e68..7dc2a2e8f598 100644
> > > > --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > > +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > > @@ -30,8 +30,6 @@ select:
> > > >            - marvell,armada-3700-ahci
> > > >            - marvell,armada-8k-ahci
> > > >            - marvell,berlin2q-ahci
> > > > -          - snps,dwc-ahci
> > > > -          - snps,spear-ahci
> > > >    required:
> > > >      - compatible
> > > >  
> > > > @@ -48,17 +46,11 @@ properties:
> > > >                - marvell,berlin2-ahci
> > > >                - marvell,berlin2q-ahci
> > > >            - const: generic-ahci
> > > > -      - items:
> > > > -          - enum:
> > > > -              - rockchip,rk3568-dwc-ahci
> > > > -          - const: snps,dwc-ahci
> > > >        - enum:
> > > >            - cavium,octeon-7130-ahci
> > > >            - hisilicon,hisi-ahci
> > > >            - ibm,476gtr-ahci
> > > >            - marvell,armada-3700-ahci
> > > > -          - snps,dwc-ahci
> > > > -          - snps,spear-ahci
> > > >  
> > > >    reg:
> > > >      minItems: 1
> > > > diff --git a/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > > new file mode 100644
> > > > index 000000000000..af78f6c9b857
> > > > --- /dev/null
> > > > +++ b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > > @@ -0,0 +1,129 @@
> > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > +%YAML 1.2
> > > > +---
> > > > +$id: http://devicetree.org/schemas/ata/snps,dwc-ahci.yaml#
> > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > +
> > > > +title: Synopsys DWC AHCI SATA controller
> > > > +
> > > > +maintainers:
> > > > +  - Serge Semin <fancer.lancer@gmail.com>
> > > > +
> > > > +description:
> > > > +  This document defines device tree bindings for the Synopsys DWC
> > > > +  implementation of the AHCI SATA controller.
> > > > +
> > > > +allOf:
> > > > +  - $ref: ahci-common.yaml#
> > > > +
> > > > +properties:
> > > > +  compatible:
> > > > +    oneOf:
> > > > +      - description: Synopsys AHCI SATA-compatible devices
> > > > +        contains:
> > > > +          const: snps,dwc-ahci
> > > > +      - description: SPEAr1340 AHCI SATA device
> > > > +        const: snps,spear-ahci
> > > > +      - description: Rockhip RK3568 ahci controller
> > > > +        const: rockchip,rk3568-dwc-ahci
> > > 
> > 
> > > This is never true because there is a fallback. We should keep what we 
> > > had before.
> > 
> > Could you be more specific what you meant? I don't see
> > "snps,spear-ahci" and "rockchip,rk3568-dwc-ahci" used with the fallback
> > string so modification is correct in that case.
> 

> Spear does not, just rockchip:
> 
> arch/arm64/boot/dts/rockchip/rk3568.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
> arch/arm64/boot/dts/rockchip/rk356x.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
> arch/arm64/boot/dts/rockchip/rk356x.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
> 
> So the 3rd entry is never true.

Then I'll have to split the schema up into two bindings:
1. snps,dwc-ahci-common.yaml: generic DW SATA AHCI properties and no "compatible"
property constraint since you said fallback was useless.
2. snps,dwc-ahci.yaml: generic DW SATA AHCI DT-schema with
competibles: ("snps,dwc-ahci"), ("snps,spear-ahci"),
("rockchip,rk3568-dwc-ahci","snps,dwc-ahci").

Are you ok with this?

BTW if we had the fallback required the splitting up couldn't have
been needed.

> 
> > My idea was to have the compatible strings with the required generic
> > fallback "snps,dwc-ahci" for all new devices thus identifying the
> > controller IP-core origin. But later you said "The generic IP block
> > fallbacks have proven to be useless." I do agree that functionally it
> > isn't that often used, but in some cases it can be handy for instance
> > to implement quirks in the generic code or use the fallback as an
> > additional info regarding the IP-core origin/version. So if I were you
> > I wouldn't be that strict about dropping the generic IP-core fallback
> > identifier. It's much easier to have it specified from the very
> > beginning than adding it after it has been declared as not required.
> 
> I wish they were useful, but experience has shown they are not.

So what to do with the generic fallback compatibles then? Please
answer to the next questions so I would correct all my currently
stashed patches in accordance with it.

1) Do you want all the new DT-binding schemas refusing to have the
fallback compatibles except for the nodes which bindings have already
been defined that way?

2) What if a device IP-core has some versioning, but it's either
not auto-detectable at runtime or can be auto-detected but starting
from some IP-core version? Do we need it being specified in addition
to the vendor-specific compatible string?

3) The same as 2), but shall it have a generic version-less fallback
compatible string too?

4) The same as 2), but what if it concerns a device which driver
relies on the versioning?

5) The same as 2), but what if it concerns the device which currently
doesn't have a driver relying on the IP-core version?

6) What if we don't have the generic fallback compatible string
required, but at some point a kernel would need it to
implement a version/IP-core-specific quirk? If we had the generic
fallback specified in dts the older systems would have been supported
out-of-box, otherwise the firmware update would also needed.

IMO having the IP-core version + generic compatibles give many
benefits and it's much easier to have them required from the very
beginning instead of adding afterwards when then a need arises.

-Sergey

> 
> > > > +  reg:
> > > > +    maxItems: 1
> > > > +
> > > > +  interrupts:
> > > > +    maxItems: 1
> > > > +
> > > > +  clocks:
> > > > +    description:
> > > > +      Basic DWC AHCI SATA clock sources like application AXI/AHB BIU clock
> > > > +      and embedded PHYs reference clock together with vendor-specific set
> > > > +      of clocks.
> > > > +    minItems: 1
> > > > +    maxItems: 4
> > > > +
> > > > +  clock-names:
> > > > +    contains:
> > > > +      anyOf:
> > > > +        - description: Application AXI/AHB BIU clock source
> > > > +          enum:
> > > > +            - aclk
> > > > +            - sata
> > > > +        - description: SATA Ports reference clock
> > > > +          enum:
> > > > +            - ref
> > > > +            - sata_ref
> > > > +
> > > > +  resets:
> > > > +    description:
> > > > +      At least basic core and application clock domains reset is normally
> > > > +      supported by the DWC AHCI SATA controller. Some platform specific
> > > > +      clocks can be also specified though.
> > > 
> > 
> > > s/clocks/resets/ ?
> > 
> > Right, but only in the reference to "platform specific clocks" -> "... resets".
> > 
> > > 
> > > This allows any number of resets which isn't great. I think this schema 
> > > should just be the 'simple' cases where there's only 1 reset and 1 
> > > clock (or how many the DWC block actually has if you have that info). 
> > > More complicated cases get there own schema.
> > 
> > DWC SATA reference manual claims there can be resets implemented to
> > each clock domain.
> > 1) PM-clk <- PM-rst - PM keep-alive clock/reset.
> > 2) aclk/hclk <- aresetn/hresetn - AXI/AHB clock domain/reset.
> > 3) rbc*_clk <- rbc*_rst - PHY Receive Clock domain/reset. (Up to
> > number of ports <= 8.)
> > 4) asic*_clk <- asic*_rst - PHY Transmit Clock domain/reset. (Up to
> > number of ports <= 8.)
> > 5) rxoob*_clk <- rxoob*_rst - RxOOB Detection Clock domain/reset. (Up
> > to number of ports <= 8.)
> > 
> > So to speak the IP-core can be equipped with up to 26 clocks and
> > resets. Should we be more strict we would have needed to define the
> > properties with all the names above and permit up to 26 clocks/resets
> > items. (Do you want it to be done?). In our case for instance there
> > is "aclk" and a single common "ref" clock for all 3, 4 and 5 domain
> > (clock 1 is missing).
> 

> I imagine most implementations just tie most clocks together.
> 
> I guess there's not going to be much new SATA h/w, so perhaps fine 
> as-is.

Do you mean to keep the "resets" property with no num-of-items constraints
then?

-Sergey

> 
> Rob

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema
  2022-07-07 15:25         ` Serge Semin
@ 2022-07-12 20:13           ` Rob Herring
  2022-07-12 20:43             ` Serge Semin
  0 siblings, 1 reply; 80+ messages in thread
From: Rob Herring @ 2022-07-12 20:13 UTC (permalink / raw)
  To: Serge Semin
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Krzysztof Kozlowski, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

On Thu, Jul 07, 2022 at 06:25:39PM +0300, Serge Semin wrote:
> On Wed, Jul 06, 2022 at 04:36:42PM -0600, Rob Herring wrote:
> > On Fri, Jun 17, 2022 at 10:37:44PM +0300, Serge Semin wrote:
> > > On Tue, Jun 14, 2022 at 04:27:54PM -0600, Rob Herring wrote:
> > > > On Fri, Jun 10, 2022 at 11:17:55AM +0300, Serge Semin wrote:
> > > > > Synopsys AHCI SATA controller is mainly compatible with the generic AHCI
> > > > > SATA controller except a few peculiarities and the platform environment
> > > > > requirements. In particular it can have one or two reference clocks to
> > > > > feed up its AXI/AHB interface and SATA PHYs domain and at least one reset
> > > > > control for the application clock domain. In addition to that the DMA
> > > > > interface of each port can be tuned up to work with the predefined maximum
> > > > > data chunk size. Note unlike generic AHCI controller DWC AHCI can't have
> > > > > more than 8 ports. All of that is reflected in the new DWC AHCI SATA
> > > > > device DT binding.
> > > > > 
> > > > > Note the DWC AHCI SATA controller DT-schema has been created in a way so
> > > > > to be reused for the vendor-specific DT-schemas (see for example the
> > > > > "snps,dwc-ahci" compatible string binding). One of which we are about to
> > > > > introduce.
> > > > > 
> > > > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > > > > 
> > > > > ---
> > > > > 
> > > > > Changelog v2:
> > > > > - Replace min/max constraints of the snps,{tx,rx}-ts-max property with
> > > > >   enum [ 1, 2, 4, ..., 1024 ]. (@Rob)
> > > > > 
> > > > > Changelog v4:
> > > > > - Decrease the "additionalProperties" property identation otherwise it's
> > > > >   percieved as the node property instead of the key one. (@Rob)
> > > > > - Use the ahci-port properties definition from the AHCI common schema
> > > > >   in order to extend it with DWC AHCI SATA port properties. (@Rob)
> > > > > - Remove the Hannes' rb tag since the patch content has changed.
> > > > > ---
> > > > >  .../bindings/ata/ahci-platform.yaml           |   8 --
> > > > >  .../bindings/ata/snps,dwc-ahci.yaml           | 129 ++++++++++++++++++
> > > > >  2 files changed, 129 insertions(+), 8 deletions(-)
> > > > >  create mode 100644 Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > > > 
> > > > > diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > > > index e19cf9828e68..7dc2a2e8f598 100644
> > > > > --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > > > +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > > > @@ -30,8 +30,6 @@ select:
> > > > >            - marvell,armada-3700-ahci
> > > > >            - marvell,armada-8k-ahci
> > > > >            - marvell,berlin2q-ahci
> > > > > -          - snps,dwc-ahci
> > > > > -          - snps,spear-ahci
> > > > >    required:
> > > > >      - compatible
> > > > >  
> > > > > @@ -48,17 +46,11 @@ properties:
> > > > >                - marvell,berlin2-ahci
> > > > >                - marvell,berlin2q-ahci
> > > > >            - const: generic-ahci
> > > > > -      - items:
> > > > > -          - enum:
> > > > > -              - rockchip,rk3568-dwc-ahci
> > > > > -          - const: snps,dwc-ahci
> > > > >        - enum:
> > > > >            - cavium,octeon-7130-ahci
> > > > >            - hisilicon,hisi-ahci
> > > > >            - ibm,476gtr-ahci
> > > > >            - marvell,armada-3700-ahci
> > > > > -          - snps,dwc-ahci
> > > > > -          - snps,spear-ahci
> > > > >  
> > > > >    reg:
> > > > >      minItems: 1
> > > > > diff --git a/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > > > new file mode 100644
> > > > > index 000000000000..af78f6c9b857
> > > > > --- /dev/null
> > > > > +++ b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > > > @@ -0,0 +1,129 @@
> > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > > +%YAML 1.2
> > > > > +---
> > > > > +$id: http://devicetree.org/schemas/ata/snps,dwc-ahci.yaml#
> > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > > +
> > > > > +title: Synopsys DWC AHCI SATA controller
> > > > > +
> > > > > +maintainers:
> > > > > +  - Serge Semin <fancer.lancer@gmail.com>
> > > > > +
> > > > > +description:
> > > > > +  This document defines device tree bindings for the Synopsys DWC
> > > > > +  implementation of the AHCI SATA controller.
> > > > > +
> > > > > +allOf:
> > > > > +  - $ref: ahci-common.yaml#
> > > > > +
> > > > > +properties:
> > > > > +  compatible:
> > > > > +    oneOf:
> > > > > +      - description: Synopsys AHCI SATA-compatible devices
> > > > > +        contains:
> > > > > +          const: snps,dwc-ahci
> > > > > +      - description: SPEAr1340 AHCI SATA device
> > > > > +        const: snps,spear-ahci
> > > > > +      - description: Rockhip RK3568 ahci controller
> > > > > +        const: rockchip,rk3568-dwc-ahci
> > > > 
> > > 
> > > > This is never true because there is a fallback. We should keep what we 
> > > > had before.
> > > 
> > > Could you be more specific what you meant? I don't see
> > > "snps,spear-ahci" and "rockchip,rk3568-dwc-ahci" used with the fallback
> > > string so modification is correct in that case.
> > 
> 
> > Spear does not, just rockchip:
> > 
> > arch/arm64/boot/dts/rockchip/rk3568.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
> > arch/arm64/boot/dts/rockchip/rk356x.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
> > arch/arm64/boot/dts/rockchip/rk356x.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
> > 
> > So the 3rd entry is never true.
> 
> Then I'll have to split the schema up into two bindings:
> 1. snps,dwc-ahci-common.yaml: generic DW SATA AHCI properties and no "compatible"
> property constraint since you said fallback was useless.
> 2. snps,dwc-ahci.yaml: generic DW SATA AHCI DT-schema with
> competibles: ("snps,dwc-ahci"), ("snps,spear-ahci"),
> ("rockchip,rk3568-dwc-ahci","snps,dwc-ahci").
> 
> Are you ok with this?

Yes.

> BTW if we had the fallback required the splitting up couldn't have
> been needed.

We generally end up needing a split like this anyways.


> > > My idea was to have the compatible strings with the required generic
> > > fallback "snps,dwc-ahci" for all new devices thus identifying the
> > > controller IP-core origin. But later you said "The generic IP block
> > > fallbacks have proven to be useless." I do agree that functionally it
> > > isn't that often used, but in some cases it can be handy for instance
> > > to implement quirks in the generic code or use the fallback as an
> > > additional info regarding the IP-core origin/version. So if I were you
> > > I wouldn't be that strict about dropping the generic IP-core fallback
> > > identifier. It's much easier to have it specified from the very
> > > beginning than adding it after it has been declared as not required.
> > 
> > I wish they were useful, but experience has shown they are not.
> 
> So what to do with the generic fallback compatibles then? Please
> answer to the next questions so I would correct all my currently
> stashed patches in accordance with it.
> 
> 1) Do you want all the new DT-binding schemas refusing to have the
> fallback compatibles except for the nodes which bindings have already
> been defined that way?

Yes. I wouldn't go quite as far as 'refusing'. I'm okay with a fallback 
in cases that are simple enough to actually work without platform 
specific code. As soon as the clocks, resets, phys, etc. aren't 
standard, that goes out the window. Based on experience, that pretty 
much never happens except on the IP vendor's FPGA.


> 2) What if a device IP-core has some versioning, but it's either
> not auto-detectable at runtime or can be auto-detected but starting
> from some IP-core version? Do we need it being specified in addition
> to the vendor-specific compatible string?

By the time you are probing the device, you know the specific SoC and 
can just set a version variable easily. Why have a string to parse that 
doesn't work for version comparisons (e.g GT/GE/LT).

Also, what if you don't know the exact IP version? Maybe you can guess 
that it is at least at certain version based on knowing the features, so 
you set that version. Would you really want to put that guess in DT when 
later on you might need to change it?

> 3) The same as 2), but shall it have a generic version-less fallback
> compatible string too?

If the device can function without the version specific compatible.

> 4) The same as 2), but what if it concerns a device which driver
> relies on the versioning?
> 
> 5) The same as 2), but what if it concerns the device which currently
> doesn't have a driver relying on the IP-core version?

Again, let the driver set the version based on the platform specific 
compatible.

> 6) What if we don't have the generic fallback compatible string
> required, but at some point a kernel would need it to
> implement a version/IP-core-specific quirk? If we had the generic
> fallback specified in dts the older systems would have been supported
> out-of-box, otherwise the firmware update would also needed.

Again, when you start probing the device, you already know the specific 
platform implementation. From that, you can easily imply the IP vendor 
and version. No DT change needed.

> IMO having the IP-core version + generic compatibles give many
> benefits and it's much easier to have them required from the very
> beginning instead of adding afterwards when then a need arises.

Certainly adding afterwards is broken. That's why we insist on SoC 
specific compatibles. Adding them when we have some platform specific 
quirk doesn't work.

Rob

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema
  2022-07-12 20:13           ` Rob Herring
@ 2022-07-12 20:43             ` Serge Semin
  0 siblings, 0 replies; 80+ messages in thread
From: Serge Semin @ 2022-07-12 20:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: Serge Semin, Damien Le Moal, Hans de Goede, Jens Axboe,
	Hannes Reinecke, Krzysztof Kozlowski, Alexey Malahov,
	Pavel Parkhomenko, linux-ide, linux-kernel, devicetree

On Tue, Jul 12, 2022 at 02:13:42PM -0600, Rob Herring wrote:
> On Thu, Jul 07, 2022 at 06:25:39PM +0300, Serge Semin wrote:
> > On Wed, Jul 06, 2022 at 04:36:42PM -0600, Rob Herring wrote:
> > > On Fri, Jun 17, 2022 at 10:37:44PM +0300, Serge Semin wrote:
> > > > On Tue, Jun 14, 2022 at 04:27:54PM -0600, Rob Herring wrote:
> > > > > On Fri, Jun 10, 2022 at 11:17:55AM +0300, Serge Semin wrote:
> > > > > > Synopsys AHCI SATA controller is mainly compatible with the generic AHCI
> > > > > > SATA controller except a few peculiarities and the platform environment
> > > > > > requirements. In particular it can have one or two reference clocks to
> > > > > > feed up its AXI/AHB interface and SATA PHYs domain and at least one reset
> > > > > > control for the application clock domain. In addition to that the DMA
> > > > > > interface of each port can be tuned up to work with the predefined maximum
> > > > > > data chunk size. Note unlike generic AHCI controller DWC AHCI can't have
> > > > > > more than 8 ports. All of that is reflected in the new DWC AHCI SATA
> > > > > > device DT binding.
> > > > > > 
> > > > > > Note the DWC AHCI SATA controller DT-schema has been created in a way so
> > > > > > to be reused for the vendor-specific DT-schemas (see for example the
> > > > > > "snps,dwc-ahci" compatible string binding). One of which we are about to
> > > > > > introduce.
> > > > > > 
> > > > > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > > > > > 
> > > > > > ---
> > > > > > 
> > > > > > Changelog v2:
> > > > > > - Replace min/max constraints of the snps,{tx,rx}-ts-max property with
> > > > > >   enum [ 1, 2, 4, ..., 1024 ]. (@Rob)
> > > > > > 
> > > > > > Changelog v4:
> > > > > > - Decrease the "additionalProperties" property identation otherwise it's
> > > > > >   percieved as the node property instead of the key one. (@Rob)
> > > > > > - Use the ahci-port properties definition from the AHCI common schema
> > > > > >   in order to extend it with DWC AHCI SATA port properties. (@Rob)
> > > > > > - Remove the Hannes' rb tag since the patch content has changed.
> > > > > > ---
> > > > > >  .../bindings/ata/ahci-platform.yaml           |   8 --
> > > > > >  .../bindings/ata/snps,dwc-ahci.yaml           | 129 ++++++++++++++++++
> > > > > >  2 files changed, 129 insertions(+), 8 deletions(-)
> > > > > >  create mode 100644 Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > > > > 
> > > > > > diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.yaml b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > > > > index e19cf9828e68..7dc2a2e8f598 100644
> > > > > > --- a/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > > > > +++ b/Documentation/devicetree/bindings/ata/ahci-platform.yaml
> > > > > > @@ -30,8 +30,6 @@ select:
> > > > > >            - marvell,armada-3700-ahci
> > > > > >            - marvell,armada-8k-ahci
> > > > > >            - marvell,berlin2q-ahci
> > > > > > -          - snps,dwc-ahci
> > > > > > -          - snps,spear-ahci
> > > > > >    required:
> > > > > >      - compatible
> > > > > >  
> > > > > > @@ -48,17 +46,11 @@ properties:
> > > > > >                - marvell,berlin2-ahci
> > > > > >                - marvell,berlin2q-ahci
> > > > > >            - const: generic-ahci
> > > > > > -      - items:
> > > > > > -          - enum:
> > > > > > -              - rockchip,rk3568-dwc-ahci
> > > > > > -          - const: snps,dwc-ahci
> > > > > >        - enum:
> > > > > >            - cavium,octeon-7130-ahci
> > > > > >            - hisilicon,hisi-ahci
> > > > > >            - ibm,476gtr-ahci
> > > > > >            - marvell,armada-3700-ahci
> > > > > > -          - snps,dwc-ahci
> > > > > > -          - snps,spear-ahci
> > > > > >  
> > > > > >    reg:
> > > > > >      minItems: 1
> > > > > > diff --git a/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > > > > new file mode 100644
> > > > > > index 000000000000..af78f6c9b857
> > > > > > --- /dev/null
> > > > > > +++ b/Documentation/devicetree/bindings/ata/snps,dwc-ahci.yaml
> > > > > > @@ -0,0 +1,129 @@
> > > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > > > +%YAML 1.2
> > > > > > +---
> > > > > > +$id: http://devicetree.org/schemas/ata/snps,dwc-ahci.yaml#
> > > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > > > +
> > > > > > +title: Synopsys DWC AHCI SATA controller
> > > > > > +
> > > > > > +maintainers:
> > > > > > +  - Serge Semin <fancer.lancer@gmail.com>
> > > > > > +
> > > > > > +description:
> > > > > > +  This document defines device tree bindings for the Synopsys DWC
> > > > > > +  implementation of the AHCI SATA controller.
> > > > > > +
> > > > > > +allOf:
> > > > > > +  - $ref: ahci-common.yaml#
> > > > > > +
> > > > > > +properties:
> > > > > > +  compatible:
> > > > > > +    oneOf:
> > > > > > +      - description: Synopsys AHCI SATA-compatible devices
> > > > > > +        contains:
> > > > > > +          const: snps,dwc-ahci
> > > > > > +      - description: SPEAr1340 AHCI SATA device
> > > > > > +        const: snps,spear-ahci
> > > > > > +      - description: Rockhip RK3568 ahci controller
> > > > > > +        const: rockchip,rk3568-dwc-ahci
> > > > > 
> > > > 
> > > > > This is never true because there is a fallback. We should keep what we 
> > > > > had before.
> > > > 
> > > > Could you be more specific what you meant? I don't see
> > > > "snps,spear-ahci" and "rockchip,rk3568-dwc-ahci" used with the fallback
> > > > string so modification is correct in that case.
> > > 
> > 
> > > Spear does not, just rockchip:
> > > 
> > > arch/arm64/boot/dts/rockchip/rk3568.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
> > > arch/arm64/boot/dts/rockchip/rk356x.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
> > > arch/arm64/boot/dts/rockchip/rk356x.dtsi:               compatible = "rockchip,rk3568-dwc-ahci", "snps,dwc-ahci";
> > > 
> > > So the 3rd entry is never true.
> > 
> > Then I'll have to split the schema up into two bindings:
> > 1. snps,dwc-ahci-common.yaml: generic DW SATA AHCI properties and no "compatible"
> > property constraint since you said fallback was useless.
> > 2. snps,dwc-ahci.yaml: generic DW SATA AHCI DT-schema with
> > competibles: ("snps,dwc-ahci"), ("snps,spear-ahci"),
> > ("rockchip,rk3568-dwc-ahci","snps,dwc-ahci").
> > 
> > Are you ok with this?
> 

> Yes.
> 
> > BTW if we had the fallback required the splitting up couldn't have
> > been needed.
> 
> We generally end up needing a split like this anyways.

Ok. I'll split it up into two schemas then.

> 
> 
> > > > My idea was to have the compatible strings with the required generic
> > > > fallback "snps,dwc-ahci" for all new devices thus identifying the
> > > > controller IP-core origin. But later you said "The generic IP block
> > > > fallbacks have proven to be useless." I do agree that functionally it
> > > > isn't that often used, but in some cases it can be handy for instance
> > > > to implement quirks in the generic code or use the fallback as an
> > > > additional info regarding the IP-core origin/version. So if I were you
> > > > I wouldn't be that strict about dropping the generic IP-core fallback
> > > > identifier. It's much easier to have it specified from the very
> > > > beginning than adding it after it has been declared as not required.
> > > 
> > > I wish they were useful, but experience has shown they are not.
> > 
> > So what to do with the generic fallback compatibles then? Please
> > answer to the next questions so I would correct all my currently
> > stashed patches in accordance with it.
> > 
> > 1) Do you want all the new DT-binding schemas refusing to have the
> > fallback compatibles except for the nodes which bindings have already
> > been defined that way?
> 
> Yes. I wouldn't go quite as far as 'refusing'. I'm okay with a fallback 
> in cases that are simple enough to actually work without platform 
> specific code. As soon as the clocks, resets, phys, etc. aren't 
> standard, that goes out the window. Based on experience, that pretty 
> much never happens except on the IP vendor's FPGA.
> 
> 
> > 2) What if a device IP-core has some versioning, but it's either
> > not auto-detectable at runtime or can be auto-detected but starting
> > from some IP-core version? Do we need it being specified in addition
> > to the vendor-specific compatible string?
> 
> By the time you are probing the device, you know the specific SoC and 
> can just set a version variable easily. Why have a string to parse that 
> doesn't work for version comparisons (e.g GT/GE/LT).
> 
> Also, what if you don't know the exact IP version? Maybe you can guess 
> that it is at least at certain version based on knowing the features, so 
> you set that version. Would you really want to put that guess in DT when 
> later on you might need to change it?
> 
> > 3) The same as 2), but shall it have a generic version-less fallback
> > compatible string too?
> 
> If the device can function without the version specific compatible.
> 
> > 4) The same as 2), but what if it concerns a device which driver
> > relies on the versioning?
> > 
> > 5) The same as 2), but what if it concerns the device which currently
> > doesn't have a driver relying on the IP-core version?
> 
> Again, let the driver set the version based on the platform specific 
> compatible.
> 
> > 6) What if we don't have the generic fallback compatible string
> > required, but at some point a kernel would need it to
> > implement a version/IP-core-specific quirk? If we had the generic
> > fallback specified in dts the older systems would have been supported
> > out-of-box, otherwise the firmware update would also needed.
> 
> Again, when you start probing the device, you already know the specific 
> platform implementation. From that, you can easily imply the IP vendor 
> and version. No DT change needed.
> 
> > IMO having the IP-core version + generic compatibles give many
> > benefits and it's much easier to have them required from the very
> > beginning instead of adding afterwards when then a need arises.
> 
> Certainly adding afterwards is broken. That's why we insist on SoC 
> specific compatibles. Adding them when we have some platform specific 
> quirk doesn't work.

Got it. Thanks for the very thorough clarification. I'll fix my patches
in accordance with the described requirements.

-Serge(y)

> 
> Rob

^ permalink raw reply	[flat|nested] 80+ messages in thread

end of thread, other threads:[~2022-07-12 20:44 UTC | newest]

Thread overview: 80+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-10  8:17 [PATCH v4 00/23] ata: ahci: Add DWC/Baikal-T1 AHCI SATA support Serge Semin
2022-06-10  8:17 ` [PATCH v4 01/23] dt-bindings: ata: ahci-platform: Move dma-coherent to sata-common.yaml Serge Semin
2022-06-14 22:02   ` Rob Herring
2022-06-14 22:15   ` Florian Fainelli
2022-06-10  8:17 ` [PATCH v4 02/23] dt-bindings: ata: ahci-platform: Detach common AHCI bindings Serge Semin
2022-06-14 22:16   ` Rob Herring
2022-06-10  8:17 ` [PATCH v4 03/23] dt-bindings: ata: ahci-platform: Clarify common AHCI props constraints Serge Semin
2022-06-14 22:17   ` Rob Herring
2022-06-10  8:17 ` [PATCH v4 04/23] dt-bindings: ata: sata: Extend number of SATA ports Serge Semin
2022-06-10  8:17 ` [PATCH v4 05/23] dt-bindings: ata: sata-brcm: Apply common AHCI schema Serge Semin
2022-06-14 22:15   ` Florian Fainelli
2022-06-14 22:17   ` Rob Herring
2022-06-10  8:17 ` [PATCH v4 06/23] ata: libahci_platform: Convert to using platform devm-ioremap methods Serge Semin
2022-06-10  8:17 ` [PATCH v4 07/23] ata: libahci_platform: Convert to using devm bulk clocks API Serge Semin
2022-06-14  8:22   ` Damien Le Moal
2022-06-15 20:45     ` Serge Semin
2022-06-16  0:23       ` Damien Le Moal
2022-06-17 19:54         ` Serge Semin
2022-06-10  8:17 ` [PATCH v4 08/23] ata: libahci_platform: Sanity check the DT child nodes number Serge Semin
2022-06-14  8:23   ` Damien Le Moal
2022-06-15 20:53     ` Serge Semin
2022-06-16  0:25       ` Damien Le Moal
2022-06-17 20:18         ` Serge Semin
2022-06-18  6:49           ` Damien Le Moal
2022-06-10  8:17 ` [PATCH v4 09/23] ata: libahci_platform: Parse ports-implemented property in resources getter Serge Semin
2022-06-10  8:17   ` Serge Semin
2022-06-10  8:17   ` Serge Semin
2022-06-10  8:17 ` [PATCH v4 10/23] ata: libahci_platform: Introduce reset assertion/deassertion methods Serge Semin
2022-06-10  8:17 ` [PATCH v4 11/23] dt-bindings: ata: ahci: Add platform capability properties Serge Semin
2022-06-14 22:19   ` Rob Herring
2022-06-15 21:56     ` Serge Semin
2022-06-10  8:17 ` [PATCH v4 12/23] ata: libahci: Extend port-cmd flags set with port capabilities Serge Semin
2022-06-14  8:32   ` Damien Le Moal
2022-06-15 20:58     ` Serge Semin
2022-06-16  0:28       ` Damien Le Moal
2022-06-17 20:31         ` Serge Semin
2022-06-18  6:52           ` Damien Le Moal
2022-06-18  8:10             ` Serge Semin
2022-06-28 12:08               ` Serge Semin
2022-06-29  1:35                 ` Damien Le Moal
2022-06-29  1:47                   ` Serge Semin
2022-06-10  8:17 ` [PATCH v4 13/23] ata: libahci: Discard redundant force_port_map parameter Serge Semin
2022-06-10  8:17 ` [PATCH v4 14/23] ata: libahci: Don't read AHCI version twice in the save-config method Serge Semin
2022-06-10  8:17 ` [PATCH v4 15/23] ata: ahci: Convert __ahci_port_base to accepting hpriv as arguments Serge Semin
2022-06-14  8:38   ` Damien Le Moal
2022-06-15 21:25     ` Serge Semin
2022-06-10  8:17 ` [PATCH v4 16/23] ata: ahci: Introduce firmware-specific caps initialization Serge Semin
2022-06-14  8:42   ` Damien Le Moal
2022-06-15 21:11     ` Serge Semin
2022-06-16  0:29       ` Damien Le Moal
2022-06-17 20:32         ` Serge Semin
2022-06-10  8:17 ` [PATCH v4 17/23] dt-bindings: ata: ahci: Add DWC AHCI SATA controller DT schema Serge Semin
2022-06-14 22:27   ` Rob Herring
2022-06-17 19:37     ` Serge Semin
2022-06-28 12:10       ` Serge Semin
2022-07-06 22:36       ` Rob Herring
2022-07-07 15:25         ` Serge Semin
2022-07-12 20:13           ` Rob Herring
2022-07-12 20:43             ` Serge Semin
2022-06-10  8:17 ` [PATCH v4 18/23] ata: libahci_platform: Add function returning a clock-handle by id Serge Semin
2022-06-14  8:45   ` Damien Le Moal
2022-06-15 21:24     ` Serge Semin
2022-06-10  8:17 ` [PATCH v4 19/23] ata: ahci: Add DWC AHCI SATA controller support Serge Semin
2022-06-10 16:34   ` Randy Dunlap
2022-06-10 21:58     ` Serge Semin
2022-06-10 23:34       ` Randy Dunlap
2022-06-15 21:30         ` Serge Semin
2022-06-16  0:31           ` Damien Le Moal
2022-06-17 20:36             ` Serge Semin
2022-06-18  6:54               ` Damien Le Moal
2022-06-14  8:53   ` Damien Le Moal
2022-06-15 21:48     ` Serge Semin
2022-06-16  0:33       ` Damien Le Moal
2022-06-17 20:34         ` Serge Semin
2022-06-10  8:17 ` [PATCH v4 20/23] dt-bindings: ata: ahci: Add Baikal-T1 AHCI SATA controller DT schema Serge Semin
2022-06-14 22:29   ` Rob Herring
2022-06-17 19:49     ` Serge Semin
2022-06-10  8:17 ` [PATCH v4 21/23] ata: ahci-dwc: Add platform-specific quirks support Serge Semin
2022-06-10  8:18 ` [PATCH v4 22/23] ata: ahci-dwc: Add Baikal-T1 AHCI SATA interface support Serge Semin
2022-06-10  8:18 ` [PATCH v4 23/23] MAINTAINERS: Add maintainers for DWC AHCI SATA driver Serge Semin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.