Skip to content

Commit 9d2ab99

Browse files
khayash1htejun
authored andcommitted
ata: libahci_platform: add reset control support
Add support to get and control a list of resets for the device as optional and shared. These resets must be kept de-asserted until the device is enabled. This is specified as shared because some SoCs like UniPhier series have common reset controls with all ahci controller instances. However, according to Thierry's view, https://www.spinics.net/lists/linux-ide/msg55357.html some hardware-specific drivers already use their own resets, and the common reset make a path to occur double controls of resets. The ahci_platform_get_resources() can get and control the reset only when the second argument includes AHCI_PLATFORM_GET_RESETS bit. Suggested-by: Hans de Goede <hdegoede@redhat.com> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Tejun Heo <tj@kernel.org>
1 parent 16af2d6 commit 9d2ab99

File tree

4 files changed

+30
-5
lines changed

4 files changed

+30
-5
lines changed

Documentation/devicetree/bindings/ata/ahci-platform.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ compatible:
3030
Optional properties:
3131
- dma-coherent : Present if dma operations are coherent
3232
- clocks : a list of phandle + clock specifier pairs
33+
- resets : a list of phandle + reset specifier pairs
3334
- target-supply : regulator for SATA target power
3435
- phys : reference to the SATA PHY node
3536
- phy-names : must be "sata-phy"

drivers/ata/ahci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ struct ahci_host_priv {
350350
u32 em_msg_type; /* EM message type */
351351
bool got_runtime_pm; /* Did we do pm_runtime_get? */
352352
struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
353+
struct reset_control *rsts; /* Optional */
353354
struct regulator **target_pwrs; /* Optional */
354355
/*
355356
* If platform uses PHYs. There is a 1:1 relation between the port number and

drivers/ata/libahci_platform.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/phy/phy.h>
2626
#include <linux/pm_runtime.h>
2727
#include <linux/of_platform.h>
28+
#include <linux/reset.h>
2829
#include "ahci.h"
2930

3031
static void ahci_host_stop(struct ata_host *host);
@@ -195,7 +196,8 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators);
195196
* following order:
196197
* 1) Regulator
197198
* 2) Clocks (through ahci_platform_enable_clks)
198-
* 3) Phys
199+
* 3) Resets
200+
* 4) Phys
199201
*
200202
* If resource enabling fails at any point the previous enabled resources
201203
* are disabled in reverse order.
@@ -215,12 +217,19 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
215217
if (rc)
216218
goto disable_regulator;
217219

218-
rc = ahci_platform_enable_phys(hpriv);
220+
rc = reset_control_deassert(hpriv->rsts);
219221
if (rc)
220222
goto disable_clks;
221223

224+
rc = ahci_platform_enable_phys(hpriv);
225+
if (rc)
226+
goto disable_resets;
227+
222228
return 0;
223229

230+
disable_resets:
231+
reset_control_assert(hpriv->rsts);
232+
224233
disable_clks:
225234
ahci_platform_disable_clks(hpriv);
226235

@@ -238,13 +247,16 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
238247
* This function disables all ahci_platform managed resources in the
239248
* following order:
240249
* 1) Phys
241-
* 2) Clocks (through ahci_platform_disable_clks)
242-
* 3) Regulator
250+
* 2) Resets
251+
* 3) Clocks (through ahci_platform_disable_clks)
252+
* 4) Regulator
243253
*/
244254
void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
245255
{
246256
ahci_platform_disable_phys(hpriv);
247257

258+
reset_control_assert(hpriv->rsts);
259+
248260
ahci_platform_disable_clks(hpriv);
249261

250262
ahci_platform_disable_regulators(hpriv);
@@ -341,7 +353,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
341353
* 2) regulator for controlling the targets power (optional)
342354
* 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
343355
* or for non devicetree enabled platforms a single clock
344-
* 4) phys (optional)
356+
* 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional)
357+
* 5) phys (optional)
345358
*
346359
* RETURNS:
347360
* The allocated ahci_host_priv on success, otherwise an ERR_PTR value
@@ -395,6 +408,14 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
395408
hpriv->clks[i] = clk;
396409
}
397410

411+
if (flags & AHCI_PLATFORM_GET_RESETS) {
412+
hpriv->rsts = devm_reset_control_array_get_optional_shared(dev);
413+
if (IS_ERR(hpriv->rsts)) {
414+
rc = PTR_ERR(hpriv->rsts);
415+
goto err_out;
416+
}
417+
}
418+
398419
hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
399420

400421
/*

include/linux/ahci_platform.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,6 @@ int ahci_platform_resume_host(struct device *dev);
4343
int ahci_platform_suspend(struct device *dev);
4444
int ahci_platform_resume(struct device *dev);
4545

46+
#define AHCI_PLATFORM_GET_RESETS 0x01
47+
4648
#endif /* _AHCI_PLATFORM_H */

0 commit comments

Comments
 (0)