summaryrefslogtreecommitdiff
path: root/documentation/6.components/device-driver/power/board_reset.md
blob: af3ea71894274381eeb9a8b6738983e4089967ea (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
135
136
137
138
139
140
141
142
143
@page page_device_power_board_reset Board poweroff and restart

# Board-level shutdown and restart

**`components/drivers/power/reset/`** — drivers that hook **system-wide** power off or CPU reset, not per-IP reset lines (@ref page_device_reset).

**Kconfig**: **`RT_USING_POWER_RESET`**, plus **`RT_POWER_RESET_GPIO_*`** or **`RT_POWER_RESET_SYSCON_*`**.

API header: **`components/drivers/include/drivers/core/power.h`** — details in @ref page_device_dm_power.

---

## Registration model

These drivers are **platform drivers** whose **`probe`** registers a **callback** with the DM power core. They do **not** register a char device for normal I/O.

```
RT_PLATFORM_DRIVER_EXPORT(gpio_poweroff_driver)
        |
        v
gpio_poweroff_probe(pdev)
        |
        +-- parse GPIO (rt_pin_get_named_pin) or syscon reg
        +-- rt_dm_power_off_handler(dev, MODE, PRIORITY, callback)
        |
        v
On rt_hw_cpu_shutdown() / rt_hw_cpu_reset():
        walk handlers by priority → callback → rt_dm_machine_shutdown/reset
```

### `rt_dm_power_off_handler`

```c
rt_err_t rt_dm_power_off_handler(struct rt_device *dev, int mode, int priority,
        rt_err_t (*callback)(struct rt_device *));
```

| `mode` | When invoked |
| --- | --- |
| **`RT_DM_POWER_OFF_MODE_SHUTDOWN`** | System power off (**`rt_hw_cpu_shutdown`**) |
| **`RT_DM_POWER_OFF_MODE_RESET`** | Warm reset path (**`rt_hw_cpu_reset`**) |

| `priority` (low → high) | Typical use |
| --- | --- |
| **`RT_DM_POWER_OFF_PRIO_PLATFORM`** | SoC flush |
| **`RT_DM_POWER_OFF_PRIO_LOW` / `DEFAULT` / `HIGH`** | Drivers, filesystem sync |
| **`RT_DM_POWER_OFF_PRIO_FIRMWARE`** | Last handoff |

Callbacks run in order; non-**`RT_EOK`** is logged but later handlers still run.

**`dev`**: passed to callback as **`dev->user_data`** context holder (GPIO drivers store private struct in **`user_data`**).

---

## In-tree drivers

| Driver | Compatible / binding | Registration |
| --- | --- | --- |
| **`gpio-poweroff`** | **`gpio-poweroff`** | **`RT_DM_POWER_OFF_MODE_SHUTDOWN`**, **`rt_pin_get_named_pin`** |
| **`gpio-restart`** | **`gpio-restart`** | **`RT_DM_POWER_OFF_MODE_RESET`** |
| **`syscon-poweroff`** | syscon reg | MMIO write in callback |
| **`syscon-reboot`** | syscon reg | reset trigger |
| **`syscon-reboot-mode`** | NVMEM + syscon | **`rt_dm_reboot_mode_register`** |

All use **`RT_PLATFORM_DRIVER_EXPORT`** except some syscon drivers use **`INIT_SUBSYS_EXPORT` + `rt_platform_driver_register`** (same binding, different init level — see @ref page_device_platform).

### GPIO poweroff example (flow)

```c
static rt_err_t gpio_poweroff_do_poweroff(struct rt_device *dev)
{
    struct gpio_poweroff *gp = dev->user_data;
    /* assert GPIO sequence, mdelay per DT timeout-ms */
    return RT_EOK;
}

static rt_err_t gpio_poweroff_probe(struct rt_platform_device *pdev)
{
    ...
    dev->user_data = gp;
    return rt_dm_power_off_handler(dev, RT_DM_POWER_OFF_MODE_SHUTDOWN,
            RT_DM_POWER_OFF_PRIO_DEFAULT, gpio_poweroff_do_poweroff);
}
RT_PLATFORM_DRIVER_EXPORT(gpio_poweroff_driver);
```

DT:

```dts
poweroff {
    compatible = "gpio-poweroff";
    gpios = <&gpio0 99 GPIO_ACTIVE_HIGH>;
    timeout-ms = <3000>;
    active-delay-ms = <100>;
    inactive-delay-ms = <100>;
};
```

---

## Reboot mode

```c
rt_dm_reboot_mode_register(dev, reboot_mode_callback);
rt_hw_cpu_reset_mode("recovery");  /* sets cmd + rt_hw_cpu_reset() */
```

**`syscon-reboot-mode`** persists mode to NVMEM/syscon so the next boot loader can read it. See **`reboot-mode.h`**, @ref page_device_dm_power.

---

## Machine hooks

BSP sets after handlers:

```c
rt_dm_machine_shutdown = board_shutdown;  /* PMIC off */
rt_dm_machine_reset = board_reset;        /* PSCI / watchdog */
```

Without these, callbacks may run but SoC never powers off.

---

## Pitfalls

| Issue | Mitigation |
| --- | --- |
| Wrong GPIO polarity | Match **`gpios`** flags and **`active_value`** from **`rt_pin_get_named_pin`** |
| **`RT_USING_PINCTRL` off** for gpio-poweroff | Kconfig depends on pinctrl for pad mux |
| Confuse with **`rt_reset_control`** | IP reset lines ≠ system poweroff |
| Handler sleeps in IRQ context | GPIO driver uses **`rt_thread_mdelay`** — ensure thread context |
| No **`rt_dm_machine_shutdown`** | Set BSP hook |

---

## See also

- @ref page_device_dm_power — handler lists, priorities
- @ref page_device_power — overview
- @ref page_device_platform
- @ref page_device_reset — reset **controller** API (different)
- `components/drivers/power/reset/`