2020-09-22 10:17:45

by Piyush Mehta

[permalink] [raw]
Subject: [PATCH V2 0/2] ata: ahci: ceva: Update the driver to support xilinx GT phy

This patch series updates the ceva driver to add support for Xilinx GT phy.
This also updates the documentation with the device tree binding required
for working with Xilinx GT phy.

---
Changes in V2:
- Added backward compatibility with the older sequence of the CEVA controller.
- Update dt-bindings document: To make phy and reset properties optional.
- Remove rst_names property.
---
Piyush Mehta (2):
dt-bindings: ata: ahci: ceva: Update documentation for CEVA Controller
ata: ahci: ceva: Update the driver to support xilinx GT phy

.../devicetree/bindings/ata/ahci-ceva.txt | 6 ++++
drivers/ata/ahci_ceva.c | 39 ++++++++++++++++++++--
2 files changed, 43 insertions(+), 2 deletions(-)

--
2.7.4


2020-09-22 10:19:18

by Piyush Mehta

[permalink] [raw]
Subject: [PATCH V2 2/2] ata: ahci: ceva: Update the driver to support xilinx GT phy

SATA controller used in Xilinx ZynqMP platform uses xilinx GT phy
which has 4 GT lanes and can used by 4 peripherals at a time.
SATA controller uses 1 GT phy lane among the 4 GT lanes. To configure
the GT lane for SATA controller, the below sequence is expected.

1. Assert the SATA controller reset.
2. Configure the xilinx GT phy lane for SATA controller (phy_init).
3. De-assert the SATA controller reset.
4. Wait for PLL of the GT lane used by SATA to be locked (phy_power_on).

The ahci_platform_enable_resources() by default does the phy_init()
and phy_power_on() but the default sequence doesn't work with Xilinx
platforms. Because of this reason, updated the driver to support the
new sequence.

Added is_rst_ctrl flag, for backward compatibility with the older
sequence. If the reset controller is not available, then the SATA
controller will configure with the older sequences.

Signed-off-by: Piyush Mehta <[email protected]>
---
drivers/ata/ahci_ceva.c | 39 +++++++++++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c
index b10fd4c..c704906 100644
--- a/drivers/ata/ahci_ceva.c
+++ b/drivers/ata/ahci_ceva.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/reset.h>
#include "ahci.h"

/* Vendor Specific Register Offsets */
@@ -87,6 +88,7 @@ struct ceva_ahci_priv {
u32 axicc;
bool is_cci_enabled;
int flags;
+ struct reset_control *rst;
};

static unsigned int ceva_ahci_read_id(struct ata_device *dev,
@@ -194,7 +196,7 @@ static int ceva_ahci_probe(struct platform_device *pdev)
struct ahci_host_priv *hpriv;
struct ceva_ahci_priv *cevapriv;
enum dev_dma_attr attr;
- int rc;
+ int rc, i, is_rst_ctrl = 1;

cevapriv = devm_kzalloc(dev, sizeof(*cevapriv), GFP_KERNEL);
if (!cevapriv)
@@ -202,14 +204,47 @@ static int ceva_ahci_probe(struct platform_device *pdev)

cevapriv->ahci_pdev = pdev;

+ cevapriv->rst = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(cevapriv->rst)) {
+ if (PTR_ERR(cevapriv->rst) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "failed to get reset: %ld\n",
+ PTR_ERR(cevapriv->rst));
+ is_rst_ctrl = 0;
+ }
+
hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
+ if (is_rst_ctrl)
+ rc = ahci_platform_enable_clks(hpriv);
+ else
+ rc = ahci_platform_enable_resources(hpriv);

- rc = ahci_platform_enable_resources(hpriv);
if (rc)
return rc;

+ if (is_rst_ctrl) {
+ /* Assert the controller reset */
+ reset_control_assert(cevapriv->rst);
+
+ for (i = 0; i < hpriv->nports; i++) {
+ rc = phy_init(hpriv->phys[i]);
+ if (rc)
+ return rc;
+ }
+
+ /* De-assert the controller reset */
+ reset_control_deassert(cevapriv->rst);
+
+ for (i = 0; i < hpriv->nports; i++) {
+ rc = phy_power_on(hpriv->phys[i]);
+ if (rc) {
+ phy_exit(hpriv->phys[i]);
+ return rc;
+ }
+ }
+ }
+
if (of_property_read_bool(np, "ceva,broken-gen2"))
cevapriv->flags = CEVA_FLAG_BROKEN_GEN2;

--
2.7.4

2020-09-22 12:07:51

by Philipp Zabel

[permalink] [raw]
Subject: Re: [PATCH V2 2/2] ata: ahci: ceva: Update the driver to support xilinx GT phy

On Tue, 2020-09-22 at 15:45 +0530, Piyush Mehta wrote:
> SATA controller used in Xilinx ZynqMP platform uses xilinx GT phy
> which has 4 GT lanes and can used by 4 peripherals at a time.
> SATA controller uses 1 GT phy lane among the 4 GT lanes. To configure
> the GT lane for SATA controller, the below sequence is expected.
>
> 1. Assert the SATA controller reset.
> 2. Configure the xilinx GT phy lane for SATA controller (phy_init).
> 3. De-assert the SATA controller reset.
> 4. Wait for PLL of the GT lane used by SATA to be locked (phy_power_on).
>
> The ahci_platform_enable_resources() by default does the phy_init()
> and phy_power_on() but the default sequence doesn't work with Xilinx
> platforms. Because of this reason, updated the driver to support the
> new sequence.
>
> Added is_rst_ctrl flag, for backward compatibility with the older
> sequence. If the reset controller is not available, then the SATA
> controller will configure with the older sequences.
>
> Signed-off-by: Piyush Mehta <[email protected]>
> ---
> drivers/ata/ahci_ceva.c | 39 +++++++++++++++++++++++++++++++++++++--
> 1 file changed, 37 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c
> index b10fd4c..c704906 100644
> --- a/drivers/ata/ahci_ceva.c
> +++ b/drivers/ata/ahci_ceva.c
> @@ -12,6 +12,7 @@
> #include <linux/module.h>
> #include <linux/of_device.h>
> #include <linux/platform_device.h>
> +#include <linux/reset.h>
> #include "ahci.h"
>
> /* Vendor Specific Register Offsets */
> @@ -87,6 +88,7 @@ struct ceva_ahci_priv {
> u32 axicc;
> bool is_cci_enabled;
> int flags;
> + struct reset_control *rst;
> };
>
> static unsigned int ceva_ahci_read_id(struct ata_device *dev,
> @@ -194,7 +196,7 @@ static int ceva_ahci_probe(struct platform_device *pdev)
> struct ahci_host_priv *hpriv;
> struct ceva_ahci_priv *cevapriv;
> enum dev_dma_attr attr;
> - int rc;
> + int rc, i, is_rst_ctrl = 1;
>
> cevapriv = devm_kzalloc(dev, sizeof(*cevapriv), GFP_KERNEL);
> if (!cevapriv)
> @@ -202,14 +204,47 @@ static int ceva_ahci_probe(struct platform_device *pdev)
>
> cevapriv->ahci_pdev = pdev;
>
> + cevapriv->rst = devm_reset_control_get(&pdev->dev, NULL);

Please use devm_reset_control_get_optional_exclusive()

> + if (IS_ERR(cevapriv->rst)) {
> + if (PTR_ERR(cevapriv->rst) != -EPROBE_DEFER)
> + dev_err(&pdev->dev, "failed to get reset: %ld\n",
> + PTR_ERR(cevapriv->rst));
> + is_rst_ctrl = 0;

is_rst_ctrl will not be required then.

> + }
> +
> hpriv = ahci_platform_get_resources(pdev, 0);
> if (IS_ERR(hpriv))
> return PTR_ERR(hpriv);
> + if (is_rst_ctrl)
> + rc = ahci_platform_enable_clks(hpriv);
> + else
> + rc = ahci_platform_enable_resources(hpriv);
>
> - rc = ahci_platform_enable_resources(hpriv);
> if (rc)
> return rc;
>
> + if (is_rst_ctrl) {

This can just be "if (cevapriv->rst)"

> + /* Assert the controller reset */
> + reset_control_assert(cevapriv->rst);
> +
> + for (i = 0; i < hpriv->nports; i++) {
> + rc = phy_init(hpriv->phys[i]);
> + if (rc)
> + return rc;
> + }
> +
> + /* De-assert the controller reset */
> + reset_control_deassert(cevapriv->rst);
> +
> + for (i = 0; i < hpriv->nports; i++) {
> + rc = phy_power_on(hpriv->phys[i]);
> + if (rc) {
> + phy_exit(hpriv->phys[i]);
> + return rc;
> + }
> + }
> + }
> +
> if (of_property_read_bool(np, "ceva,broken-gen2"))
> cevapriv->flags = CEVA_FLAG_BROKEN_GEN2;
>

regards
Philipp

2020-09-23 05:47:34

by Piyush Mehta

[permalink] [raw]
Subject: RE: [PATCH V2 2/2] ata: ahci: ceva: Update the driver to support xilinx GT phy

Hello Philipp,

Thanks for review.

Regards,
Piyush Mehta

-----Original Message-----
From: Philipp Zabel <[email protected]>
Sent: Tuesday, September 22, 2020 5:36 PM
To: Piyush Mehta <[email protected]>; [email protected]; [email protected]
Cc: [email protected]; [email protected]; [email protected]; git <[email protected]>; Srinivas Goud <[email protected]>; Michal Simek <[email protected]>
Subject: Re: [PATCH V2 2/2] ata: ahci: ceva: Update the driver to support xilinx GT phy

On Tue, 2020-09-22 at 15:45 +0530, Piyush Mehta wrote:
> SATA controller used in Xilinx ZynqMP platform uses xilinx GT phy
> which has 4 GT lanes and can used by 4 peripherals at a time.
> SATA controller uses 1 GT phy lane among the 4 GT lanes. To configure
> the GT lane for SATA controller, the below sequence is expected.
>
> 1. Assert the SATA controller reset.
> 2. Configure the xilinx GT phy lane for SATA controller (phy_init).
> 3. De-assert the SATA controller reset.
> 4. Wait for PLL of the GT lane used by SATA to be locked (phy_power_on).
>
> The ahci_platform_enable_resources() by default does the phy_init()
> and phy_power_on() but the default sequence doesn't work with Xilinx
> platforms. Because of this reason, updated the driver to support the
> new sequence.
>
> Added is_rst_ctrl flag, for backward compatibility with the older
> sequence. If the reset controller is not available, then the SATA
> controller will configure with the older sequences.
>
> Signed-off-by: Piyush Mehta <[email protected]>
> ---
> drivers/ata/ahci_ceva.c | 39 +++++++++++++++++++++++++++++++++++++--
> 1 file changed, 37 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c index
> b10fd4c..c704906 100644
> --- a/drivers/ata/ahci_ceva.c
> +++ b/drivers/ata/ahci_ceva.c
> @@ -12,6 +12,7 @@
> #include <linux/module.h>
> #include <linux/of_device.h>
> #include <linux/platform_device.h>
> +#include <linux/reset.h>
> #include "ahci.h"
>
> /* Vendor Specific Register Offsets */ @@ -87,6 +88,7 @@ struct
> ceva_ahci_priv {
> u32 axicc;
> bool is_cci_enabled;
> int flags;
> + struct reset_control *rst;
> };
>
> static unsigned int ceva_ahci_read_id(struct ata_device *dev, @@
> -194,7 +196,7 @@ static int ceva_ahci_probe(struct platform_device *pdev)
> struct ahci_host_priv *hpriv;
> struct ceva_ahci_priv *cevapriv;
> enum dev_dma_attr attr;
> - int rc;
> + int rc, i, is_rst_ctrl = 1;
>
> cevapriv = devm_kzalloc(dev, sizeof(*cevapriv), GFP_KERNEL);
> if (!cevapriv)
> @@ -202,14 +204,47 @@ static int ceva_ahci_probe(struct
> platform_device *pdev)
>
> cevapriv->ahci_pdev = pdev;
>
> + cevapriv->rst = devm_reset_control_get(&pdev->dev, NULL);

Please use devm_reset_control_get_optional_exclusive()

> + if (IS_ERR(cevapriv->rst)) {
> + if (PTR_ERR(cevapriv->rst) != -EPROBE_DEFER)
> + dev_err(&pdev->dev, "failed to get reset: %ld\n",
> + PTR_ERR(cevapriv->rst));
> + is_rst_ctrl = 0;

is_rst_ctrl will not be required then.

> + }
> +
> hpriv = ahci_platform_get_resources(pdev, 0);
> if (IS_ERR(hpriv))
> return PTR_ERR(hpriv);
> + if (is_rst_ctrl)
> + rc = ahci_platform_enable_clks(hpriv);
> + else
> + rc = ahci_platform_enable_resources(hpriv);
>
> - rc = ahci_platform_enable_resources(hpriv);
> if (rc)
> return rc;
>
> + if (is_rst_ctrl) {

This can just be "if (cevapriv->rst)"

> + /* Assert the controller reset */
> + reset_control_assert(cevapriv->rst);
> +
> + for (i = 0; i < hpriv->nports; i++) {
> + rc = phy_init(hpriv->phys[i]);
> + if (rc)
> + return rc;
> + }
> +
> + /* De-assert the controller reset */
> + reset_control_deassert(cevapriv->rst);
> +
> + for (i = 0; i < hpriv->nports; i++) {
> + rc = phy_power_on(hpriv->phys[i]);
> + if (rc) {
> + phy_exit(hpriv->phys[i]);
> + return rc;
> + }
> + }
> + }
> +
> if (of_property_read_bool(np, "ceva,broken-gen2"))
> cevapriv->flags = CEVA_FLAG_BROKEN_GEN2;
>

regards
Philipp