Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:45

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (c) 2016 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifndef LIBBSP_ARM_ATSAM_POWER_H
0029 #define LIBBSP_ARM_ATSAM_POWER_H
0030 
0031 #include <sys/types.h>
0032 
0033 #include <stdint.h>
0034 
0035 #ifdef __cplusplus
0036 extern "C"{
0037 #endif /* __cplusplus */
0038 
0039 /**
0040  * @brief Status of the Low Power Support
0041  */
0042 typedef enum {
0043   /**
0044    * @brief Used for Initialization of Handlers
0045    */
0046   ATSAM_POWER_INIT,
0047   /**
0048    * @brief Used for Switching On of Handlers
0049    */
0050   ATSAM_POWER_ON,
0051   /**
0052    * @brief Used for Switching Off of Handlers
0053    */
0054   ATSAM_POWER_OFF
0055 } atsam_power_state;
0056 
0057 /**
0058  * @brief Control structure for power control handling
0059  */
0060 typedef struct atsam_power_control {
0061   /**
0062    * @brief Data pointer to the handler with its desired state
0063    */
0064   void (*handler)(
0065       const struct atsam_power_control *control,
0066       atsam_power_state state
0067   );
0068   /**
0069    * @brief Data chunk that is used by the handler
0070    */
0071   union {
0072     void *arg;
0073     struct {
0074       uint8_t first;
0075       uint8_t last;
0076     } peripherals;
0077   } data;
0078 } atsam_power_control;
0079 
0080 /**
0081  * @brief Performs a power state change according to the state parameter.
0082  *
0083  * The handlers of the control table are invoked in forward order (invocation
0084  * starts with table index zero) for the ATSAM_POWER_INIT and ATSAM_POWER_OFF
0085  * states, otherwise the handlers are invoked in reverse order (invocation
0086  * starts with the last table index).
0087  *
0088  * @param controls Table with power controls.
0089  * @param n Count of power control table entries.
0090  * @param state The desired power state.
0091  *
0092  * @code
0093  * #include <rtems.h>
0094  * #include <pthread.h>
0095  *
0096  * #include <bsp/power.h>
0097  *
0098  * static atsam_power_data_rtc_driver rtc_data = { .interval = 5 };
0099  *
0100  * static const atsam_power_control power_controls[] = {
0101  *   ATSAM_POWER_CLOCK_DRIVER,
0102  *   ATSAM_POWER_RTC_DRIVER(&rtc_data),
0103  *   ATSAM_POWER_SLEEP_MODE
0104  * };
0105  *
0106  * static pthread_once_t once = PTHREAD_ONCE_INIT;
0107  *
0108  * static void init(void)
0109  * {
0110  *   atsam_power_change_state(
0111  *     &power_controls[0],
0112  *     RTEMS_ARRAY_SIZE(power_controls),
0113  *     ATSAM_POWER_INIT
0114  *   );
0115  * }
0116  *
0117  * void power_init(void)
0118  * {
0119  *   pthread_once(&once, init);
0120  * }
0121  *
0122  * void low_power(void)
0123  * {
0124  *   atsam_power_change_state(
0125  *     &power_controls[0],
0126  *     RTEMS_ARRAY_SIZE(power_controls),
0127  *     ATSAM_POWER_OFF
0128  *   );
0129  *   atsam_power_change_state(
0130  *     &power_controls[0],
0131  *     RTEMS_ARRAY_SIZE(power_controls),
0132  *     ATSAM_POWER_ON
0133  *   );
0134  * }
0135  * @end
0136  */
0137 void atsam_power_change_state(
0138   const atsam_power_control *controls,
0139   size_t n,
0140   atsam_power_state state
0141 );
0142 
0143 /**
0144  * @brief Power handler for a set of peripherals according to the specified
0145  * peripheral indices.
0146  *
0147  * For the power off state, the peripherals are enabled in the PMC.
0148  *
0149  * For the power on state, the peripherals are disabled in the Power Management
0150  * Controller (PMC).
0151  *
0152  * @see ATSAM_POWER_PERIPHERAL().
0153  */
0154 void atsam_power_handler_peripheral(
0155   const atsam_power_control *controls,
0156   atsam_power_state state
0157 );
0158 
0159 /**
0160  * @brief Power handler for the clock driver.
0161  *
0162  * For the power off state, the system tick is disabled.
0163  *
0164  * For the power on state, the system tick is enabled.  In case no clock driver
0165  * is used by the application, then this may lead to a spurious interrupt
0166  * resulting in a fatal error.
0167  *
0168  * @see ATSAM_POWER_CLOCK_DRIVER().
0169  */
0170 void atsam_power_handler_clock_driver(
0171   const atsam_power_control *controls,
0172   atsam_power_state state
0173 );
0174 
0175 /**
0176  * @brief Power handler for the RTC driver.
0177  *
0178  * This handler installs an interrupt handler during power support initialization.
0179  *
0180  * For the power off state, the RTC alarm interrupt is set up according to the
0181  * interval of the corresponding handler data.
0182  *
0183  * For the power on state, the RTC alarm interrupt is disabled.
0184  *
0185  * @see ATSAM_POWER_RTC_DRIVER().
0186  */
0187 void atsam_power_handler_rtc_driver(
0188   const atsam_power_control *controls,
0189   atsam_power_state state
0190 );
0191 
0192 /**
0193  * @brief Power handler to enter the processor sleep mode.
0194  *
0195  * @see ATSAM_POWER_SLEEP_MODE().
0196  */
0197 void atsam_power_handler_sleep_mode(
0198   const atsam_power_control *controls,
0199   atsam_power_state state
0200 );
0201 
0202 /**
0203  * @brief Power handler to enter the processor wait mode.
0204  *
0205  * The internal flash is put into deep sleep mode.
0206  *
0207  * @see ATSAM_POWER_WAIT_MODE().
0208  */
0209 void atsam_power_handler_wait_mode(
0210   const atsam_power_control *controls,
0211   atsam_power_state state
0212 );
0213 
0214 /**
0215  * @brief Initializer for a peripheral power support.
0216  *
0217  * @param f The first peripheral index.
0218  * @param l The last peripheral index.
0219  */
0220 #define ATSAM_POWER_PERIPHERAL(f, l) \
0221  { \
0222    .handler = atsam_power_handler_peripheral, \
0223    .data = { .peripherals = { .first = f, .last = l } } \
0224  }
0225 
0226 #define ATSAM_POWER_HANDLER(h, a) \
0227  { \
0228    .handler = h, \
0229    .data = { .arg = a } \
0230  }
0231 
0232 #define ATSAM_POWER_CLOCK_DRIVER \
0233  { .handler = atsam_power_handler_clock_driver }
0234 
0235 #define ATSAM_POWER_SLEEP_MODE \
0236  { .handler = atsam_power_handler_sleep_mode }
0237 
0238 #define ATSAM_POWER_WAIT_MODE \
0239  { .handler = atsam_power_handler_wait_mode }
0240 
0241 /**
0242  * @brief Data for RTC driver power support.
0243  *
0244  * @see ATSAM_POWER_RTC_DRIVER().
0245  */
0246 typedef struct {
0247   /**
0248    * @brief Interval in seconds for which the power off mode should be active.
0249    *
0250    * An interval up to 24h is supported.
0251    */
0252   uint32_t interval;
0253 } atsam_power_data_rtc_driver;
0254 
0255 /**
0256  * @brief Initializer for RTC driver power support.
0257  *
0258  * @param a Pointer to RTC driver power data.
0259  *
0260  * @see atsam_power_data_rtc_driver.
0261  */
0262 #define ATSAM_POWER_RTC_DRIVER(a) \
0263  { \
0264     .handler = atsam_power_handler_rtc_driver, \
0265     .data = { .arg = a } \
0266  }
0267 
0268 #ifdef __cplusplus
0269 }
0270 #endif /* __cplusplus */
0271 
0272 #endif /* LIBBSP_ARM_ATSAM_POWER_H */