summaryrefslogblamecommitdiffstats
path: root/bsps/arm/atsam/include/bsp/power.h
blob: bf8259ee2b44e0bb4201dbe3c59b1a6a9c58e941 (plain) (tree)
1
2
3
4
5

                                           


                                                                 



















                                                                              








































































































































































                                                                                  







                                      











                                                         






















                                                         


                                             







                                                                              

                                        
     
                    



















                                                   
/* SPDX-License-Identifier: BSD-2-Clause */

/*
 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef LIBBSP_ARM_ATSAM_POWER_H
#define LIBBSP_ARM_ATSAM_POWER_H

#include <sys/types.h>

#include <stdint.h>

#ifdef __cplusplus
extern "C"{
#endif /* __cplusplus */

/**
 * @brief Status of the Low Power Support
 */
typedef enum {
  /**
   * @brief Used for Initialization of Handlers
   */
  ATSAM_POWER_INIT,
  /**
   * @brief Used for Switching On of Handlers
   */
  ATSAM_POWER_ON,
  /**
   * @brief Used for Switching Off of Handlers
   */
  ATSAM_POWER_OFF
} atsam_power_state;

/**
 * @brief Control structure for power control handling
 */
typedef struct atsam_power_control {
  /**
   * @brief Data pointer to the handler with its desired state
   */
  void (*handler)(
      const struct atsam_power_control *control,
      atsam_power_state state
  );
  /**
   * @brief Data chunk that is used by the handler
   */
  union {
    void *arg;
    struct {
      uint8_t first;
      uint8_t last;
    } peripherals;
  } data;
} atsam_power_control;

/**
 * @brief Performs a power state change according to the state parameter.
 *
 * The handlers of the control table are invoked in forward order (invocation
 * starts with table index zero) for the ATSAM_POWER_INIT and ATSAM_POWER_OFF
 * states, otherwise the handlers are invoked in reverse order (invocation
 * starts with the last table index).
 *
 * @param controls Table with power controls.
 * @param n Count of power control table entries.
 * @param state The desired power state.
 *
 * @code
 * #include <rtems.h>
 * #include <pthread.h>
 *
 * #include <bsp/power.h>
 *
 * static atsam_power_data_rtc_driver rtc_data = { .interval = 5 };
 *
 * static const atsam_power_control power_controls[] = {
 *   ATSAM_POWER_CLOCK_DRIVER,
 *   ATSAM_POWER_RTC_DRIVER(&rtc_data),
 *   ATSAM_POWER_SLEEP_MODE
 * };
 *
 * static pthread_once_t once = PTHREAD_ONCE_INIT;
 *
 * static void init(void)
 * {
 *   atsam_power_change_state(
 *     &power_controls[0],
 *     RTEMS_ARRAY_SIZE(power_controls),
 *     ATSAM_POWER_INIT
 *   );
 * }
 *
 * void power_init(void)
 * {
 *   pthread_once(&once, init);
 * }
 *
 * void low_power(void)
 * {
 *   atsam_power_change_state(
 *     &power_controls[0],
 *     RTEMS_ARRAY_SIZE(power_controls),
 *     ATSAM_POWER_OFF
 *   );
 *   atsam_power_change_state(
 *     &power_controls[0],
 *     RTEMS_ARRAY_SIZE(power_controls),
 *     ATSAM_POWER_ON
 *   );
 * }
 * @end
 */
void atsam_power_change_state(
  const atsam_power_control *controls,
  size_t n,
  atsam_power_state state
);

/**
 * @brief Power handler for a set of peripherals according to the specified
 * peripheral indices.
 *
 * For the power off state, the peripherals are enabled in the PMC.
 *
 * For the power on state, the peripherals are disabled in the Power Management
 * Controller (PMC).
 *
 * @see ATSAM_POWER_PERIPHERAL().
 */
void atsam_power_handler_peripheral(
  const atsam_power_control *controls,
  atsam_power_state state
);

/**
 * @brief Power handler for the clock driver.
 *
 * For the power off state, the system tick is disabled.
 *
 * For the power on state, the system tick is enabled.  In case no clock driver
 * is used by the application, then this may lead to a spurious interrupt
 * resulting in a fatal error.
 *
 * @see ATSAM_POWER_CLOCK_DRIVER().
 */
void atsam_power_handler_clock_driver(
  const atsam_power_control *controls,
  atsam_power_state state
);

/**
 * @brief Power handler for the RTC driver.
 *
 * This handler installs an interrupt handler during power support initialization.
 *
 * For the power off state, the RTC alarm interrupt is set up according to the
 * interval of the corresponding handler data.
 *
 * For the power on state, the RTC alarm interrupt is disabled.
 *
 * @see ATSAM_POWER_RTC_DRIVER().
 */
void atsam_power_handler_rtc_driver(
  const atsam_power_control *controls,
  atsam_power_state state
);

/**
 * @brief Power handler to enter the processor sleep mode.
 *
 * @see ATSAM_POWER_SLEEP_MODE().
 */
void atsam_power_handler_sleep_mode(
  const atsam_power_control *controls,
  atsam_power_state state
);

/**
 * @brief Power handler to enter the processor wait mode.
 *
 * The internal flash is put into deep sleep mode.
 *
 * @see ATSAM_POWER_WAIT_MODE().
 */
void atsam_power_handler_wait_mode(
  const atsam_power_control *controls,
  atsam_power_state state
);

/**
 * @brief Initializer for a peripheral power support.
 *
 * @param f The first peripheral index.
 * @param l The last peripheral index.
 */
#define ATSAM_POWER_PERIPHERAL(f, l) \
 { \
   .handler = atsam_power_handler_peripheral, \
   .data = { .peripherals = { .first = f, .last = l } } \
 }

#define ATSAM_POWER_HANDLER(h, a) \
 { \
   .handler = h, \
   .data = { .arg = a } \
 }

#define ATSAM_POWER_CLOCK_DRIVER \
 { .handler = atsam_power_handler_clock_driver }

#define ATSAM_POWER_SLEEP_MODE \
 { .handler = atsam_power_handler_sleep_mode }

#define ATSAM_POWER_WAIT_MODE \
 { .handler = atsam_power_handler_wait_mode }

/**
 * @brief Data for RTC driver power support.
 *
 * @see ATSAM_POWER_RTC_DRIVER().
 */
typedef struct {
  /**
   * @brief Interval in seconds for which the power off mode should be active.
   *
   * An interval up to 24h is supported.
   */
  uint32_t interval;
} atsam_power_data_rtc_driver;

/**
 * @brief Initializer for RTC driver power support.
 *
 * @param a Pointer to RTC driver power data.
 *
 * @see atsam_power_data_rtc_driver.
 */
#define ATSAM_POWER_RTC_DRIVER(a) \
 { \
    .handler = atsam_power_handler_rtc_driver, \
    .data = { .arg = a } \
 }

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* LIBBSP_ARM_ATSAM_POWER_H */