|
6 | 6 |
|
7 | 7 | #include <zephyr/drivers/sensor.h> |
8 | 8 | #include <zephyr/pm/device.h> |
| 9 | +#include <zephyr/pm/device_runtime.h> |
9 | 10 | #include <zephyr/drivers/pinctrl.h> |
10 | 11 | #include <soc.h> |
11 | 12 |
|
@@ -173,81 +174,78 @@ static const struct sensor_driver_api qdec_nrfx_driver_api = { |
173 | 174 | .trigger_set = qdec_nrfx_trigger_set, |
174 | 175 | }; |
175 | 176 |
|
176 | | -#ifdef CONFIG_PM_DEVICE |
177 | | -static int qdec_nrfx_pm_action(const struct device *dev, |
178 | | - enum pm_device_action action) |
| 177 | +static int qdec_pm_suspend(const struct device *dev) |
179 | 178 | { |
180 | 179 | const struct qdec_nrfx_config *config = dev->config; |
181 | | - int ret = 0; |
| 180 | + |
| 181 | + nrfx_qdec_disable(&config->qdec); |
| 182 | + qdec_nrfx_gpio_ctrl(dev, false); |
| 183 | + |
| 184 | + if (!IS_ENABLED(CONFIG_PM_DEVICE)) { |
| 185 | + return 0; |
| 186 | + } |
| 187 | + |
| 188 | + return pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); |
| 189 | +} |
| 190 | + |
| 191 | +static int qdec_pm_resume(const struct device *dev) |
| 192 | +{ |
| 193 | + const struct qdec_nrfx_config *config = dev->config; |
| 194 | + int ret; |
| 195 | + |
| 196 | + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); |
| 197 | + if (ret < 0) { |
| 198 | + return ret; |
| 199 | + } |
| 200 | + |
| 201 | + qdec_nrfx_gpio_ctrl(dev, true); |
| 202 | + nrfx_qdec_enable(&config->qdec); |
| 203 | + |
| 204 | + return 0; |
| 205 | +} |
| 206 | + |
| 207 | +static int qdec_nrfx_pm_action(const struct device *dev, enum pm_device_action action) |
| 208 | +{ |
| 209 | + int ret = -ENOTSUP; |
182 | 210 |
|
183 | 211 | switch (action) { |
184 | 212 | case PM_DEVICE_ACTION_RESUME: |
185 | | - ret = pinctrl_apply_state(config->pcfg, |
186 | | - PINCTRL_STATE_DEFAULT); |
187 | | - if (ret < 0) { |
188 | | - return ret; |
189 | | - } |
190 | | - qdec_nrfx_gpio_ctrl(dev, true); |
191 | | - nrfx_qdec_enable(&config->qdec); |
192 | | - break; |
193 | | - |
194 | | - case PM_DEVICE_ACTION_TURN_OFF: |
195 | | - /* device must be uninitialized */ |
196 | | - nrfx_qdec_uninit(&config->qdec); |
197 | | - ret = pinctrl_apply_state(config->pcfg, |
198 | | - PINCTRL_STATE_SLEEP); |
199 | | - if (ret < 0) { |
200 | | - return ret; |
201 | | - } |
| 213 | + ret = qdec_pm_resume(dev); |
202 | 214 | break; |
203 | 215 |
|
204 | 216 | case PM_DEVICE_ACTION_SUSPEND: |
205 | | - /* device must be suspended */ |
206 | | - nrfx_qdec_disable(&config->qdec); |
207 | | - qdec_nrfx_gpio_ctrl(dev, false); |
208 | | - ret = pinctrl_apply_state(config->pcfg, |
209 | | - PINCTRL_STATE_SLEEP); |
210 | | - if (ret < 0) { |
211 | | - return ret; |
| 217 | + if (IS_ENABLED(CONFIG_PM_DEVICE)) { |
| 218 | + ret = qdec_pm_suspend(dev); |
212 | 219 | } |
213 | 220 | break; |
214 | 221 | default: |
215 | | - return -ENOTSUP; |
| 222 | + break; |
216 | 223 | } |
217 | 224 |
|
218 | 225 | return ret; |
219 | 226 | } |
220 | | -#endif /* CONFIG_PM_DEVICE */ |
221 | 227 |
|
222 | 228 | static int qdec_nrfx_init(const struct device *dev) |
223 | 229 | { |
224 | | - const struct qdec_nrfx_config *dev_config = dev->config; |
225 | | - |
226 | | - dev_config->irq_connect(); |
| 230 | + const struct qdec_nrfx_config *config = dev->config; |
| 231 | + int ret; |
| 232 | + nrfx_err_t nerr; |
227 | 233 |
|
228 | | - int err = pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_DEFAULT); |
| 234 | + config->irq_connect(); |
229 | 235 |
|
230 | | - if (err < 0) { |
231 | | - return err; |
| 236 | + nerr = nrfx_qdec_init(&config->qdec, &config->config, qdec_nrfx_event_handler, (void *)dev); |
| 237 | + if (nerr != NRFX_SUCCESS) { |
| 238 | + return (nerr == NRFX_ERROR_INVALID_STATE) ? -EBUSY : -EFAULT; |
232 | 239 | } |
233 | 240 |
|
234 | | - nrfx_err_t nerr = nrfx_qdec_init(&dev_config->qdec, |
235 | | - &dev_config->config, |
236 | | - qdec_nrfx_event_handler, |
237 | | - (void *)dev); |
238 | | - |
239 | | - if (nerr == NRFX_ERROR_INVALID_STATE) { |
240 | | - LOG_ERR("qdec already in use"); |
241 | | - return -EBUSY; |
242 | | - } else if (nerr != NRFX_SUCCESS) { |
243 | | - LOG_ERR("failed to initialize qdec"); |
244 | | - return -EFAULT; |
| 241 | + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { |
| 242 | + ret = qdec_pm_suspend(dev); |
| 243 | + if (ret < 0) { |
| 244 | + return ret; |
| 245 | + } |
245 | 246 | } |
246 | 247 |
|
247 | | - qdec_nrfx_gpio_ctrl(dev, true); |
248 | | - nrfx_qdec_enable(&dev_config->qdec); |
249 | | - |
250 | | - return 0; |
| 248 | + return pm_device_driver_init(dev, qdec_nrfx_pm_action); |
251 | 249 | } |
252 | 250 |
|
253 | 251 | #define QDEC(idx) DT_NODELABEL(qdec##idx) |
@@ -282,7 +280,7 @@ static int qdec_nrfx_init(const struct device *dev) |
282 | 280 | .enable_pin = DT_PROP_OR(QDEC(idx), enable_pin, NRF_QDEC_PIN_NOT_CONNECTED), \ |
283 | 281 | .steps = QDEC_PROP(idx, steps), \ |
284 | 282 | }; \ |
285 | | - PM_DEVICE_DT_DEFINE(QDEC(idx), qdec_nrfx_pm_action); \ |
| 283 | + PM_DEVICE_DT_DEFINE(QDEC(idx), qdec_nrfx_pm_action, PM_DEVICE_ISR_SAFE); \ |
286 | 284 | SENSOR_DEVICE_DT_DEFINE(QDEC(idx), \ |
287 | 285 | qdec_nrfx_init, \ |
288 | 286 | PM_DEVICE_DT_GET(QDEC(idx)), \ |
|
0 commit comments