aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches/0117-ata-ahci_platform-Manage-SATA-PHY.patch
blob: 20211dcc1d62511b09d695df2e4c0484ed5efd9c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
From 05b9b8d1035944af25694d2ebe53077cf1ccb067 Mon Sep 17 00:00:00 2001
From: Roger Quadros <rogerq@ti.com>
Date: Sat, 22 Feb 2014 16:53:40 +0100
Subject: [PATCH 117/182] ata: ahci_platform: Manage SATA PHY

Some platforms have a PHY hooked up to the SATA controller. The PHY
needs to be initialized and powered up for SATA to work. We do that
using the PHY framework.

tj: Minor comment formatting updates.

CC: Balaji T K <balajitk@ti.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Tejun Heo<tj@kernel.org>
---
 drivers/ata/ahci.h          |    2 ++
 drivers/ata/ahci_platform.c |   47 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 47 insertions(+), 2 deletions(-)

--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -37,6 +37,7 @@
 
 #include <linux/clk.h>
 #include <linux/libata.h>
+#include <linux/phy/phy.h>
 #include <linux/regulator/consumer.h>
 
 /* Enclosure Management Control */
@@ -326,6 +327,7 @@ struct ahci_host_priv {
 	u32			em_msg_type;	/* EM message type */
 	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
 	struct regulator	*target_pwr;	/* Optional */
+	struct phy		*phy;		/* If platform uses phy */
 	void			*plat_data;	/* Other platform data */
 	/*
 	 * Optional ahci_start_engine override, if not set this gets set to the
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/libata.h>
 #include <linux/ahci_platform.h>
+#include <linux/phy/phy.h>
 #include "ahci.h"
 
 static void ahci_host_stop(struct ata_host *host);
@@ -140,6 +141,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_
  * following order:
  * 1) Regulator
  * 2) Clocks (through ahci_platform_enable_clks)
+ * 3) Phy
  *
  * If resource enabling fails at any point the previous enabled resources
  * are disabled in reverse order.
@@ -161,8 +163,23 @@ int ahci_platform_enable_resources(struc
 	if (rc)
 		goto disable_regulator;
 
+	if (hpriv->phy) {
+		rc = phy_init(hpriv->phy);
+		if (rc)
+			goto disable_clks;
+
+		rc = phy_power_on(hpriv->phy);
+		if (rc) {
+			phy_exit(hpriv->phy);
+			goto disable_clks;
+		}
+	}
+
 	return 0;
 
+disable_clks:
+	ahci_platform_disable_clks(hpriv);
+
 disable_regulator:
 	if (hpriv->target_pwr)
 		regulator_disable(hpriv->target_pwr);
@@ -176,11 +193,17 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_r
  *
  * This function disables all ahci_platform managed resources in the
  * following order:
- * 1) Clocks (through ahci_platform_disable_clks)
- * 2) Regulator
+ * 1) Phy
+ * 2) Clocks (through ahci_platform_disable_clks)
+ * 3) Regulator
  */
 void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
 {
+	if (hpriv->phy) {
+		phy_power_off(hpriv->phy);
+		phy_exit(hpriv->phy);
+	}
+
 	ahci_platform_disable_clks(hpriv);
 
 	if (hpriv->target_pwr)
@@ -208,6 +231,7 @@ static void ahci_platform_put_resources(
  * 2) regulator for controlling the targets power (optional)
  * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
  *    or for non devicetree enabled platforms a single clock
+ *	4) phy (optional)
  *
  * RETURNS:
  * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
@@ -266,6 +290,25 @@ struct ahci_host_priv *ahci_platform_get
 		hpriv->clks[i] = clk;
 	}
 
+	hpriv->phy = devm_phy_get(dev, "sata-phy");
+	if (IS_ERR(hpriv->phy)) {
+		rc = PTR_ERR(hpriv->phy);
+		switch (rc) {
+		case -ENODEV:
+		case -ENOSYS:
+			/* continue normally */
+			hpriv->phy = NULL;
+			break;
+
+		case -EPROBE_DEFER:
+			goto err_out;
+
+		default:
+			dev_err(dev, "couldn't get sata-phy\n");
+			goto err_out;
+		}
+	}
+
 	devres_remove_group(dev, NULL);
 	return hpriv;