1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/reboot.h>
9 #include <openthread/instance.h>
10 #include <openthread/platform/misc.h>
11 
12 #if defined(CONFIG_OPENTHREAD_PLATFORM_BOOTLOADER_MODE_RETENTION)
13 
14 #include <zephyr/retention/bootmode.h>
15 
16 #elif defined(CONFIG_OPENTHREAD_PLATFORM_BOOTLOADER_MODE_GPIO)
17 
18 BUILD_ASSERT(DT_HAS_COMPAT_STATUS_OKAY(openthread_config),
19 	"`openthread,config` compatible node not found");
20 BUILD_ASSERT(DT_NODE_HAS_PROP(DT_COMPAT_GET_ANY_STATUS_OKAY(openthread_config), bootloader_gpios),
21 	"`bootloader-gpios` property missing from `openthread,config` compatible node");
22 
23 #include <zephyr/drivers/gpio.h>
24 
25 static const struct gpio_dt_spec bootloader_gpio =
26 	GPIO_DT_SPEC_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(openthread_config),
27 			 bootloader_gpios);
28 #endif
29 
30 #include "platform-zephyr.h"
31 
otPlatReset(otInstance * aInstance)32 void otPlatReset(otInstance *aInstance)
33 {
34 	ARG_UNUSED(aInstance);
35 
36 	/* This function does nothing on the Posix platform. */
37 	sys_reboot(SYS_REBOOT_WARM);
38 }
39 
40 #if defined(CONFIG_OPENTHREAD_PLATFORM_BOOTLOADER_MODE)
otPlatResetToBootloader(otInstance * aInstance)41 otError otPlatResetToBootloader(otInstance *aInstance)
42 {
43 	OT_UNUSED_VARIABLE(aInstance);
44 
45 #if defined(CONFIG_OPENTHREAD_PLATFORM_BOOTLOADER_MODE_RETENTION)
46 	if (bootmode_set(BOOT_MODE_TYPE_BOOTLOADER)) {
47 		return OT_ERROR_NOT_CAPABLE;
48 	}
49 	sys_reboot(SYS_REBOOT_WARM);
50 
51 #elif defined(CONFIG_OPENTHREAD_PLATFORM_BOOTLOADER_MODE_GPIO)
52 	/*
53 	 * To enable resetting to bootloader by triggering gpio pin,
54 	 * select `CONFIG_OPENTHREAD_PLATFORM_BOOTLOADER_MODE_GPIO=y`,
55 	 * and in Devicetree create `openthread` node in `/options/` path with
56 	 * `compatible = "openthread,config"` property and `bootloader-gpios` property,
57 	 * which should represent GPIO pin's configuration,
58 	 * containing controller phandle, pin number and pin flags. e.g:
59 	 *
60 	 * options {
61 	 *	openthread {
62 	 *		compatible = "openthread,config";
63 	 *		bootloader-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
64 	 *	};
65 	 * };
66 	 *
67 	 * Note: in below implementation, chosen GPIO pin is configured as output
68 	 * and initialized to active state (logical value ‘1’).
69 	 * Configuring pin flags in `bootloader-gpios` allows to choose
70 	 * if pin should be active in high or in low state.
71 	 */
72 
73 	if (!gpio_is_ready_dt(&bootloader_gpio)) {
74 		return OT_ERROR_NOT_CAPABLE;
75 	}
76 	gpio_pin_configure_dt(&bootloader_gpio, GPIO_OUTPUT_ACTIVE);
77 
78 #endif
79 
80 	/*
81 	 * Return OT_ERROR_NOT_CAPABLE if resetting has been unsuccessful (invalid configuration or
82 	 * triggering reset had no effect)
83 	 */
84 	return OT_ERROR_NOT_CAPABLE;
85 }
86 #endif /* defined(CONFIG_OPENTHREAD_PLATFORM_BOOTLOADER_MODE) */
87 
otPlatGetResetReason(otInstance * aInstance)88 otPlatResetReason otPlatGetResetReason(otInstance *aInstance)
89 {
90 	ARG_UNUSED(aInstance);
91 
92 	return OT_PLAT_RESET_REASON_POWER_ON;
93 }
94 
otPlatWakeHost(void)95 void otPlatWakeHost(void)
96 {
97 	/* TODO */
98 }
99 
otPlatAssertFail(const char * aFilename,int aLineNumber)100 void otPlatAssertFail(const char *aFilename, int aLineNumber)
101 {
102 	/*
103 	 * The code below is used instead of __ASSERT(false) to print the actual assert
104 	 * location instead of __FILE__:__LINE__, which would point to this function.
105 	 */
106 	__ASSERT_PRINT("OpenThread ASSERT @ %s:%d\n", aFilename, aLineNumber);
107 	__ASSERT_POST_ACTION();
108 }
109