summaryrefslogtreecommitdiff
path: root/documentation/6.components/device-driver/phye/phye_consumer.md
blob: 1bba169ca8f617c93636c256bf82a90f585edfe2 (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
@page page_device_phye_consumer Phye consumer integration

# Host / MAC consumer pattern

How link-layer drivers acquire and sequence PHY bring-up **before** training or DMA.

---

## Recommended sequence

```c
struct rt_phye *phy;

phy = rt_phye_get_by_name(dev, "sata-phy");
if (rt_is_err_or_null(phy))
    return rt_ptr_err(phy) ? rt_ptr_err(phy) : -RT_ERROR;

err = rt_phye_init(phy);
if (err)
    goto put;

err = rt_phye_power_on(phy);
if (err)
    goto exit;

err = rt_phye_set_mode_simple(phy, RT_PHYE_MODE_SATA);
if (err)
    goto power_off;

/* optional: rt_phye_reset(phy) */

err = host_enable_and_train();   /* MAC-specific */
if (err)
    goto power_off;

/* store phy in driver private */

power_off:
    rt_phye_power_off(phy);
exit:
    rt_phye_exit(phy);
put:
    rt_phye_put(phy);
return err;
```

On success, keep PHY powered until **`remove`** — do not **`put`** until teardown.

---

## DesignWare AHCI example (`ata/ahci-dw.c`)

| Step | Call |
| --- | --- |
| Get | **`rt_phye_get_by_name(dev, "sata-phy")`** |
| Clocks | **`rt_clk_array_prepare_enable`** (before PHY) |
| PHY | **`rt_phye_init`** → **`rt_phye_power_on`** |
| Host | **`rt_ahci_host_register`** |
| Fail path | **`power_off`** → **`exit`** → disable clocks → **`rt_phye_put`** |
| Remove | **`exit`** + **`power_off`** (note order in source) |

DTS: host node needs **`phys`** / **`phy-names = "sata-phy"`** pointing at SATA PHY provider.

---

## PCIe host (typical)

Before **`rt_pci_host_bridge_probe`** or link training:

```c
phy = rt_phye_get_by_index(dev, 0);
rt_phye_init(phy);
rt_phye_power_on(phy);
rt_phye_set_mode(phy, RT_PHYE_MODE_PCIE, RT_PHYE_MODE_PCIE_RC);
/* then DWC / generic PCIe host probe */
```

Exact ordering vs **`clk`/`reset`** is SoC-specific — @ref page_device_pci_host.

---

## USB

Often uses **`usb-nop-xceiv`** (@ref page_device_phye_generic_usb) or SoC USB PHY:

```c
phy = rt_phye_get_by_index(dev, 0);
rt_phye_power_on(phy);
rt_phye_set_mode_simple(phy, RT_PHYE_MODE_USB_HOST_SS);
```

Generic USB driver may only implement **`power_on`/`power_off`/`reset`** — mode set optional.

---

## Error handling

| Return | Meaning |
| --- | --- |
| **`rt_err_ptr(-RT_EINVAL)`** | Bad args |
| **`rt_err_ptr` from `ofw_parse`** | DT cells wrong |
| **`NULL`** | No **`phys`** / provider missing |

Always **`rt_phye_put`** for every successful **`get`**.

---

## Pitfalls

| Issue | Mitigation |
| --- | --- |
| Train before **`power_on`** | Link fails — follow TRM order |
| **`set_mode` while link up** | Down link first |
| Leak **`put`** | Pair with **`get`** on all paths |
| Double **`power_off`** in remove | Match **`probe`** success path |

## See also

- @ref page_device_phye
- @ref page_device_phye_ofw
- @ref page_device_pci_probe
- @ref page_device_ata