<commit_before>/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* Clocks and power management settings */

#include "chipset.h"
#include "clock.h"
#include "common.h"
#include "console.h"
#include "cpu.h"
#include "hooks.h"
#include "hwtimer.h"
#include "registers.h"
#include "system.h"
#include "task.h"
#include "timer.h"
#include "util.h"

/* Console output macros */
#define CPUTS(outstr) cputs(CC_CLOCK, outstr)
#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args)

/* use 48Mhz USB-synchronized High-speed oscillator */
#define HSI48_CLOCK 48000000

/* use PLL at 38.4MHz as system clock. */
#define PLL_CLOCK 38400000

/* Low power idle statistics */
#ifdef CONFIG_LOW_POWER_IDLE
static int idle_sleep_cnt;
static int idle_dsleep_cnt;
static uint64_t idle_dsleep_time_us;
static int dsleep_recovery_margin_us = 1000000;

/*
 * minimum delay to enter stop mode
 * STOP_MODE_LATENCY: max time to wake up from STOP mode with regulator in low
 * power mode is 5 us + PLL locking time is 200us.
 * SET_RTC_MATCH_DELAY: max time to set RTC match alarm. if we set the alarm
 * in the past, it will never wake up and cause a watchdog.
 * For STM32F3, we are using HSE, which requires additional time to start up.
 * Therefore, the latency for STM32F3 is set longer.
 */
#ifdef CHIP_VARIANT_STM32F373
#define STOP_MODE_LATENCY 500  /* us */
#elif (CPU_CLOCK == PLL_CLOCK)
#define STOP_MODE_LATENCY 300   /* us */
#else
#define STOP_MODE_LATENCY 50    /* us */
#endif
#define SET_RTC_MATCH_DELAY 200 /* us */

#endif /* CONFIG_LOW_POWER_IDLE */

/*
 * RTC clock frequency (connected to LSI clock)
 *
 * TODO(crosbug.com/p/12281): Calibrate LSI frequency on a per-chip basis.  The
 * LSI on any given chip can be between 30 kHz to 60 kHz.  Without calibration,
 * LSI frequency may be off by as much as 50%.  Fortunately, we don't do any
 * high-precision delays based solely on LSI.
 */
/*
 * Set synchronous clock freq to LSI/2 (20kHz) to maximize subsecond
 * resolution. Set asynchronous clock to 1 Hz.
 */
#define RTC_FREQ (40000 / 2) /* Hz */
#define RTC_PREDIV_S (RTC_FREQ - 1)
#define RTC_PREDIV_A 1
#define US_PER_RTC_TICK (1000000 / RTC_FREQ)

/* Lock and unlock RTC write access */
static inline void rtc_lock_regs(void)
{
	STM32_RTC_WPR = 0xff;
}
static inline void rtc_unlock_regs(void)
{
	STM32_RTC_WPR = 0xca;
	STM32_RTC_WPR = 0x53;
}

/* Convert between RTC regs in BCD and seconds */
static inline uint32_t rtc_to_sec(uint32_t rtc)
{
	uint32_t sec;

	/* convert the hours field */
	sec = (((rtc & 0x300000) >> 20) * 10 + ((rtc & 0xf0000) >> 16)) * 3600;
	/* convert the minutes field */
	sec += (((rtc & 0x7000) >> 12) * 10 + ((rtc & 0xf00) >> 8)) * 60;
	/* convert the seconds field */
	sec += ((rtc & 0x70) >> 4) * 10 + (rtc & 0xf);

	return sec;
}
static inline uint32_t sec_to_rtc(uint32_t sec)
{
	uint32_t rtc;

	/* convert the hours field */
	rtc = ((sec / 36000) << 20) | (((sec / 3600) % 10) << 16);
	/* convert the minutes field */
	rtc |= (((sec % 3600) / 600) << 12) | (((sec % 600) / 60) << 8);
	/* convert the seconds field */
	rtc |= (((sec % 60) / 10) << 4) | (sec % 10);

	return rtc;
}

/* Return time diff between two rtc readings */
int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss,
		     uint32_t rtc1, uint32_t rtc1ss)
{
	int32_t diff;

	/* Note: this only looks at the diff mod 10 seconds */
	diff =  ((rtc1 & 0xf) * SECOND +
		 (RTC_PREDIV_S - rtc1ss) * US_PER_RTC_TICK) -
		((rtc0 & 0xf) * SECOND +
		 (RTC_PREDIV_S - rtc0ss) * US_PER_RTC_TICK);

	return (diff < 0) ? (diff + 10*SECOND) : diff;
}

static inline void rtc_read(uint32_t *rtc, uint32_t *rtcss)
{
	/* Read current time synchronously */
	do {
		*rtc = STM32_RTC_TR;
		*rtcss = STM32_RTC_SSR;
	} while (*rtc != STM32_RTC_TR);
}

void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us,
		      uint32_t *rtc, uint32_t *rtcss)
{<commit_msg>stm32f0: Fix RTC read glitch<commit_after>/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* Clocks and power management settings */

#include "chipset.h"
#include "clock.h"
#include "common.h"
#include "console.h"
#include "cpu.h"
#include "hooks.h"
#include "hwtimer.h"
#include "registers.h"
#include "system.h"
#include "task.h"
#include "timer.h"
#include "util.h"

/* Console output macros */
#define CPUTS(outstr) cputs(CC_CLOCK, outstr)
#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args)

/* use 48Mhz USB-synchronized High-speed oscillator */
#define HSI48_CLOCK 48000000

/* use PLL at 38.4MHz as system clock. */
#define PLL_CLOCK 38400000

/* Low power idle statistics */
#ifdef CONFIG_LOW_POWER_IDLE
static int idle_sleep_cnt;
static int idle_dsleep_cnt;
static uint64_t idle_dsleep_time_us;
static int dsleep_recovery_margin_us = 1000000;

/*
 * minimum delay to enter stop mode
 * STOP_MODE_LATENCY: max time to wake up from STOP mode with regulator in low
 * power mode is 5 us + PLL locking time is 200us.
 * SET_RTC_MATCH_DELAY: max time to set RTC match alarm. if we set the alarm
 * in the past, it will never wake up and cause a watchdog.
 * For STM32F3, we are using HSE, which requires additional time to start up.
 * Therefore, the latency for STM32F3 is set longer.
 */
#ifdef CHIP_VARIANT_STM32F373
#define STOP_MODE_LATENCY 500  /* us */
#elif (CPU_CLOCK == PLL_CLOCK)
#define STOP_MODE_LATENCY 300   /* us */
#else
#define STOP_MODE_LATENCY 50    /* us */
#endif
#define SET_RTC_MATCH_DELAY 200 /* us */

#endif /* CONFIG_LOW_POWER_IDLE */

/*
 * RTC clock frequency (connected to LSI clock)
 *
 * TODO(crosbug.com/p/12281): Calibrate LSI frequency on a per-chip basis.  The
 * LSI on any given chip can be between 30 kHz to 60 kHz.  Without calibration,
 * LSI frequency may be off by as much as 50%.  Fortunately, we don't do any
 * high-precision delays based solely on LSI.
 */
/*
 * Set synchronous clock freq to LSI/2 (20kHz) to maximize subsecond
 * resolution. Set asynchronous clock to 1 Hz.
 */
#define RTC_FREQ (40000 / 2) /* Hz */
#define RTC_PREDIV_S (RTC_FREQ - 1)
#define RTC_PREDIV_A 1
#define US_PER_RTC_TICK (1000000 / RTC_FREQ)

/* Lock and unlock RTC write access */
static inline void rtc_lock_regs(void)
{
	STM32_RTC_WPR = 0xff;
}
static inline void rtc_unlock_regs(void)
{
	STM32_RTC_WPR = 0xca;
	STM32_RTC_WPR = 0x53;
}

/* Convert between RTC regs in BCD and seconds */
static inline uint32_t rtc_to_sec(uint32_t rtc)
{
	uint32_t sec;

	/* convert the hours field */
	sec = (((rtc & 0x300000) >> 20) * 10 + ((rtc & 0xf0000) >> 16)) * 3600;
	/* convert the minutes field */
	sec += (((rtc & 0x7000) >> 12) * 10 + ((rtc & 0xf00) >> 8)) * 60;
	/* convert the seconds field */
	sec += ((rtc & 0x70) >> 4) * 10 + (rtc & 0xf);

	return sec;
}
static inline uint32_t sec_to_rtc(uint32_t sec)
{
	uint32_t rtc;

	/* convert the hours field */
	rtc = ((sec / 36000) << 20) | (((sec / 3600) % 10) << 16);
	/* convert the minutes field */
	rtc |= (((sec % 3600) / 600) << 12) | (((sec % 600) / 60) << 8);
	/* convert the seconds field */
	rtc |= (((sec % 60) / 10) << 4) | (sec % 10);

	return rtc;
}

/* Return time diff between two rtc readings */
int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss,
		     uint32_t rtc1, uint32_t rtc1ss)
{
	int32_t diff;

	/* Note: this only looks at the diff mod 10 seconds */
	diff =  ((rtc1 & 0xf) * SECOND +
		 (RTC_PREDIV_S - rtc1ss) * US_PER_RTC_TICK) -
		((rtc0 & 0xf) * SECOND +
		 (RTC_PREDIV_S - rtc0ss) * US_PER_RTC_TICK);

	return (diff < 0) ? (diff + 10*SECOND) : diff;
}

static inline void rtc_read(uint32_t *rtc, uint32_t *rtcss)
{
	/* Read current time synchronously */
	do {
		*rtc = STM32_RTC_TR;
		/*
		 * RTC_SSR must be read twice with identical values because
		 * glitches may occur for reads close to the RTCCLK edge.
		 */
		do {
			*rtcss = STM32_RTC_SSR;
		} while (*rtcss != STM32_RTC_SSR);
	} while (*rtc != STM32_RTC_TR);
}

void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us,
		      uint32_t *rtc, uint32_t *rtcss)
{
{'fraction_non_alphanumeric': 0.12152394952835967, 'fraction_numerical': 0.059659438931765285, 'mean_word_length': 3.6598173515981736, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1329590', 'n_tokens_mistral': 3544, 'n_tokens_neox': 3028, 'n_words': 1003}