#include "core/lpc_regs.h"
#include "core/lpc_core.h"
#include "core/system.h"
+#include "core/pmu.h"
/* Private defines */
uint32_t main_clock;
uint8_t brown_out_detection_enabled;
uint8_t need_IRC;
+ uint8_t need_watchdog;
+ uint8_t need_self_wakeup_timer;
};
static struct lpc_desc_private lpc_private = {
.main_clock = LPC_IRC_OSC_CLK,
.brown_out_detection_enabled = 0,
.need_IRC = 1,
+ .need_watchdog = 0,
+ .need_self_wakeup_timer = 0,
};
/***************************************************************************** */
return lpc_private.brown_out_detection_enabled;
}
+/* Store the watchdog requirement info */
+void system_need_watchdog(uint8_t val)
+{
+ lpc_private.need_watchdog = val;
+}
+
+/* Return the status of watchdog config */
+uint8_t system_watchdog_enabled(void)
+{
+ return lpc_private.need_watchdog;
+}
+
+/* Store the Self Wakeup timer requirement info */
+void system_need_self_wakeup_timer(uint8_t val)
+{
+ lpc_private.need_self_wakeup_timer = val;
+}
+
+/* Return the status of Self Wakeup timer config */
+uint8_t system_self_wakeup_timer_enabled(void)
+{
+ return lpc_private.need_self_wakeup_timer;
+}
+
/***************************************************************************** */
/* Power */
subsystem_reset_release(reset_bit);
}
+
+/***************************************************************************** */
+/* Start logic */
+/***************************************************************************** */
+void enable_pin_intr_wake_source(uint32_t src)
+{
+ struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
+ sys_config->start_log_ctrl[0].wakeup_en |= src;
+}
+void enable_intr_wake_source(uint32_t src)
+{
+ struct lpc_sys_config* sys_config = LPC_SYS_CONFIG;
+ sys_config->start_log_ctrl[1].wakeup_en |= src;
+}
+
+
/***************************************************************************** */
/* System Clock */
/***************************************************************************** */
void msleep(uint32_t ms) __attribute__ ((weak, alias ("def_msleep")));
void usleep(uint32_t us) __attribute__ ((weak, alias ("def_usleep")));
+
+/***************************************************************************** */
+/* Self Wake-up timer functions */
+/***************************************************************************** */
+/* Turn ON the Self Wake-Up timer.
+ * - clk_src is one of LPC_WKT_USE_IRC, LPC_WKT_USE_10KHZ or LPC_WKT_USE_PIN_CLK
+ * Note that LPC_WKT_USE_IRC cannot be used for waking up from deep sleep or any
+ * power down mode.
+ */
+
+static void (*wkt_callback)(void) = NULL;
+void WKT_Handler(void)
+{
+ self_wakeup_timer_clear();
+ if (wkt_callback != NULL) {
+ wkt_callback();
+ }
+}
+
+void self_wakeup_timer_on(uint8_t clk_src, void (*callback)(void))
+{
+ struct lpc_pm_unit* pmu = LPC_PMU;
+ struct lpc_swt_wkt* swt = LPC_SWT_WKT;
+
+ wkt_callback = callback;
+ system_need_self_wakeup_timer(1);
+
+ subsystem_power(LPC_SYS_AHB_CLK_CTRL_WKT, 1);
+
+ subsystem_reset(LPC_WKT_RESET_N);
+
+ switch (clk_src) {
+ case LPC_WKT_USE_10KHZ:
+ pmu->deep_power_down_ctrl = LPC_WAKEUP_PIN_DISABLE | LPC_WAKEUP_CLK_10KHZ;
+ swt->control = LPC_WKT_CLK_SEL_10KHZ;
+ break;
+ case LPC_WKT_USE_IRC:
+ /* TODO */
+ break;
+ case LPC_WKT_USE_PIN_CLK:
+ /* TODO */
+ break;
+ default:
+ break;
+ }
+
+ /* Enable the wake-up timer interrupt as a wakeup source */
+ enable_intr_wake_source(LPC_WKT_INT_WAKEUP_EN);
+
+ /* Interrupt enable */
+ NVIC_EnableIRQ(WKT_IRQ);
+}
+
+/* Turn OFF the Self Wake-Up timer. */
+void self_wakeup_timer_off(void)
+{
+ NVIC_DisableIRQ(WKT_IRQ);
+ self_wakeup_timer_clear();
+ subsystem_reset_hold(LPC_WKT_RESET_N);
+ subsystem_power(LPC_SYS_AHB_CLK_CTRL_WKT, 0);
+}
+
+/* Clear both the alarm flag and the counter value, effectively stopping
+ * the Self Wake-Up timer
+ */
+void self_wakeup_timer_clear(void)
+{
+ struct lpc_swt_wkt* swt = LPC_SWT_WKT;
+ swt->control |= LPC_WKT_ALARM_FLAG | LPC_WKT_CLEAR_COUNTER;
+}
+
+
+/* Start the Self Wake-Up timer.
+ * - timer_val is the value loaded in the decrementer. Delay depends on the clock
+ * source selected by "clk_src" parameter given to self_wakeup_timer_on().
+ */
+void self_wakeup_timer_start(uint32_t timer_val)
+{
+ struct lpc_swt_wkt* swt = LPC_SWT_WKT;
+
+ /* Set value */
+ swt->count = timer_val;
+}
+
+
/* Power Management Unit (PMU) */
struct lpc_pm_unit
{
- volatile uint32_t power_ctrl; /* 0x000 : Power control Register (R/W) */
- volatile uint32_t gp_data[4]; /* 0x004 to 0x010 : General purpose Register 0 to 3 (R/W) */
- volatile uint32_t deep_power_down_ctrl; /* 0x014 : Deep power down control register (R/W) */
+ volatile uint32_t power_ctrl; /* 0x000 : PCON - Power control Register (R/W) */
+ volatile uint32_t gp_data[4]; /* 0x004 to 0x010 : GPREG - General purpose Register 0 to 3 (R/W) */
+ volatile uint32_t deep_power_down_ctrl; /* 0x014 : DPDCTRL - Deep power down control register (R/W) */
/* (WAKEUP pin control) */
};
#define LPC_PMU ((struct lpc_pm_unit *) LPC_PMU_BASE)
-/* System config register */
-#define LPC_WAKEUP_PIN_HYST_MASK (0x01 << 10)
-#define LPC_RTC_CLK_SRC_SHIFT 11
-#define LPC_RTC_CLK_SRC_MASK (0x0F << LPC_RTC_CLK_SRC_SHIFT)
-/* See RTC section above for RTC Clock source selection bits */
+/* Power control register fields (PCON) */
+#define LPC_PM_DEFAULT 0x00
+#define LPC_PM_DEEP_SLEEP 0x01
+#define LPC_PM_POWER_DOWN 0x02
+#define LPC_PM_DEEP_POWER_DOWN 0x03
+#define LPC_PM_NO_DPD (0x01 << 3)
+
+
+/* Deep power down control register fields */
+#define LPC_WAKEUP_PIN_HYST (0x01 << 0)
+#define LPC_WAKEUP_PIN_DISABLE (0x01 << 1)
+#define LPC_WAKEUP_CLK_10KHZ (0x01 << 2)
+#define LPC_WAKEUP_LPOSC_IN_DPD (0x01 << 3)
+#define LPC_WAKEUP_CLK_PIN_HYST (0x01 << 4)
+#define LPC_WAKEUP_CLK_PIN_EN (0x01 << 5)
#endif /* LPC_PMU_H */
/* Return the status of brown out detection config */
uint8_t system_brown_out_detection_enabled(void);
+/* Store the watchdog requirement info */
+void system_need_watchdog(uint8_t val);
+
+/* Return the status of watchdog config */
+uint8_t system_watchdog_enabled(void);
+
+/* Store the Self Wakeup timer requirement info */
+void system_need_self_wakeup_timer(uint8_t val);
+
+/* Return the status of Self Wakeup timer config */
+uint8_t system_self_wakeup_timer_enabled(void);
+
+
/***************************************************************************** */
/* System Clock */
/***************************************************************************** */
/* Pin interrupt wakeup enable */
#define LPC_PINT_WAKEUP_EN(x) (1 << (x))
+/* Interrupt sources wakeup enable */
+#define LPC_SPI0_INT_WAKEUP_EN (1 << 0)
+#define LPC_SPI1_INT_WAKEUP_EN (1 << 1)
+#define LPC_USART0_INT_WAKEUP_EN (1 << 3)
+#define LPC_USART1_INT_WAKEUP_EN (1 << 4)
+#define LPC_USART2_INT_WAKEUP_EN (1 << 5)
+#define LPC_I2C1_INT_WAKEUP_EN (1 << 7)
+#define LPC_I2C0_INT_WAKEUP_EN (1 << 8)
+#define LPC_WWDT_INT_WAKEUP_EN (1 << 12)
+#define LPC_BOD_INT_WAKEUP_EN (1 << 13)
+#define LPC_WKT_INT_WAKEUP_EN (1 << 15)
+#define LPC_I2C2_INT_WAKEUP_EN (1 << 21)
+#define LPC_I2C3_INT_WAKEUP_EN ((1 << 31) || (1 << 22))
+
+void enable_intr_wake_source(uint32_t src);
+void enable_pin_intr_wake_source(uint32_t src);
+
+
+#define LPC_RTC_CLK_SRC_SHIFT 11
+#define LPC_RTC_CLK_SRC_MASK (0x0F << LPC_RTC_CLK_SRC_SHIFT)
+/* See RTC section above for RTC Clock source selection bits */
+
+
+
+/***************************************************************************** */
+/* Self WakeUp Timer */
+/***************************************************************************** */
+
+/* Self Wake-Up Timer (SWT or WKT) */
+struct lpc_swt_wkt
+{
+ volatile uint32_t control; /* 0x000 : CTRL - Control Register (R/W) */
+ volatile uint32_t unused[2];
+ volatile uint32_t count; /* 0x00C : COUNT - Count register (-/W) */
+};
+#define LPC_SWT_WKT ((struct lpc_swt_wkt *) LPC_SWT_BASE)
+
+/* Wake-Up timer */
+#define LPC_WKT_CLK_SEL_IRC (0x00 << 0)
+#define LPC_WKT_CLK_SEL_10KHZ (0x01 << 0)
+#define LPC_WKT_ALARM_FLAG (0x01 << 1)
+#define LPC_WKT_CLEAR_COUNTER (0x01 << 2)
+#define LPC_WKT_EXT_CLK_SEL (0x01 << 3)
+
+/* Helpers, unrelated to registers */
+#define LPC_WKT_USE_IRC 1
+#define LPC_WKT_USE_10KHZ 2
+#define LPC_WKT_USE_PIN_CLK 3
+
+/* Turn ON the Self Wake-Up timer.
+ * - clk_src is one of LPC_WKT_USE_IRC, LPC_WKT_USE_10KHZ or LPC_WKT_USE_PIN_CLK
+ * Note that LPC_WKT_USE_IRC cannot be used for waking up from deep sleep or any
+ * power down mode.
+ */
+void self_wakeup_timer_on(uint8_t clk_src, void (*callback)(void));
+
+/* Turn OFF the Self Wake-Up timer. */
+void self_wakeup_timer_off(void);
+
+/* Clear both the alarm flag and the counter value, effectively stopping
+ * the Self Wake-Up timer
+ */
+void self_wakeup_timer_clear(void);
+
+/* Start the Self Wake-Up timer.
+ * - timer_val is the value loaded in the decrementer. Delay depends on the clock
+ * source selected by "clk_src" parameter given to self_wakeup_timer_on().
+ */
+void self_wakeup_timer_start(uint32_t timer_val);
+
+
/***************************************************************************** */
/* Flash Control */