summaryrefslogtreecommitdiff
path: root/chip/stm32/bkpdata.c
blob: bde026facddb11309aa842fe7ae940f988d95dba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/* Copyright 2020 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <assert.h>

#include "bkpdata.h"
#include "registers.h"
#include "system.h" /* enum system_bbram_idx */
#include "task.h"

uint16_t bkpdata_read(enum bkpdata_index index)
{
	if (index < 0 || index >= STM32_BKP_ENTRIES)
		return 0;

	if (index & 1)
		return STM32_BKP_DATA(index >> 1) >> 16;
	else
		return STM32_BKP_DATA(index >> 1) & 0xFFFF;
}

int bkpdata_write(enum bkpdata_index index, uint16_t value)
{
	static struct mutex bkpdata_write_mutex;
	int use_mutex = !in_interrupt_context();

	if (index < 0 || index >= STM32_BKP_ENTRIES)
		return EC_ERROR_INVAL;

	/*
	 * Two entries share a single 32-bit register, lock mutex to prevent
	 * read/mask/write races.
	 */
	if (use_mutex)
		mutex_lock(&bkpdata_write_mutex);
	if (index & 1) {
		uint32_t val = STM32_BKP_DATA(index >> 1);
		val = (val & 0x0000FFFF) | (value << 16);
		STM32_BKP_DATA(index >> 1) = val;
	} else {
		uint32_t val = STM32_BKP_DATA(index >> 1);
		val = (val & 0xFFFF0000) | value;
		STM32_BKP_DATA(index >> 1) = val;
	}
	if (use_mutex)
		mutex_unlock(&bkpdata_write_mutex);

	return EC_SUCCESS;
}

int bkpdata_index_lookup(enum system_bbram_idx idx, int *msb)
{
	*msb = 0;

#ifdef CONFIG_USB_PD_DUAL_ROLE
	if (idx == SYSTEM_BBRAM_IDX_PD0)
		return BKPDATA_INDEX_PD0;
	if (idx == SYSTEM_BBRAM_IDX_PD1)
		return BKPDATA_INDEX_PD1;
	if (idx == SYSTEM_BBRAM_IDX_PD2)
		return BKPDATA_INDEX_PD2;
#endif
	return -1;
}

uint32_t bkpdata_read_reset_flags(void)
{
	uint32_t flags = bkpdata_read(BKPDATA_INDEX_SAVED_RESET_FLAGS);

#ifdef CONFIG_STM32_EXTENDED_RESET_FLAGS
	flags |= bkpdata_read(BKPDATA_INDEX_SAVED_RESET_FLAGS_2) << 16;
#endif

	return flags;
}

__overridable void bkpdata_write_reset_flags(uint32_t save_flags)
{
	bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS, save_flags & 0xffff);
#ifdef CONFIG_STM32_EXTENDED_RESET_FLAGS
	bkpdata_write(BKPDATA_INDEX_SAVED_RESET_FLAGS_2, save_flags >> 16);
#endif
}