summaryrefslogtreecommitdiffstats
path: root/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c
blob: ce8527263bdb62d4a5e0f245ca797154e7e9585c (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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
 * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <common/debug.h>
#include <lib/mmio.h>
#include <platform_def.h>
#include <spm.h>
#include <spm_pmic_wrap.h>
#include <lib/libc/string.h>

#define SLEEP_REG_MD_SPM_DVFS_CMD20	(SLEEP_REG_MD_BASE + 0x010)
#define SLEEP_REG_MD_SPM_DVFS_CMD21	(SLEEP_REG_MD_BASE + 0x014)
#define SLEEP_REG_MD_SPM_DVFS_CMD22	(SLEEP_REG_MD_BASE + 0x018)
#define SLEEP_REG_MD_SPM_DVFS_CMD23	(SLEEP_REG_MD_BASE + 0x01C)

/* PMIC_WRAP -> PMIC MT6358 */
#define VCORE_BASE_UV 50000
#define VOLT_TO_PMIC_VAL(volt)  (((volt) - VCORE_BASE_UV + 625 - 1) / 625)
#define PMIC_VAL_TO_VOLT(pmic)  (((pmic) * 625) + VCORE_BASE_UV)

#define DEFAULT_VOLT_VSRAM      (100000)
#define DEFAULT_VOLT_VCORE      (100000)
#define NR_PMIC_WRAP_CMD	(NR_IDX_ALL)
#define MAX_RETRY_COUNT		(100)
#define SPM_DATA_SHIFT		(16)

#define BUCK_VCORE_ELR0		0x14AA
#define BUCK_VPROC12_CON0	0x1408
#define BUCK_VPROC11_CON0	0x1388
#define TOP_SPI_CON0		0x044C
#define LDO_VSRAM_PROC12_CON0	0x1B88
#define LDO_VSRAM_PROC11_CON0	0x1B46
#define BUCK_VMODEM_ELR0	0x15A6

struct pmic_wrap_cmd {
	unsigned long cmd_addr;
	unsigned long cmd_wdata;
};

struct pmic_wrap_setting {
	enum pmic_wrap_phase_id phase;
	struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD];
	struct {
		struct {
			unsigned long cmd_addr;
			unsigned long cmd_wdata;
		} _[NR_PMIC_WRAP_CMD];
		const int nr_idx;
	} set[NR_PMIC_WRAP_PHASE];
};

static struct pmic_wrap_setting pw = {
	.phase = NR_PMIC_WRAP_PHASE,
	.addr = {{0, 0} },
	.set[PMIC_WRAP_PHASE_ALLINONE] = {
		._[CMD_0]    = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(70000),},
		._[CMD_1]    = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(80000),},
		._[CMD_2]    = {BUCK_VPROC12_CON0, 0x3,},
		._[CMD_3]    = {BUCK_VPROC12_CON0, 0x1,},
		._[CMD_4]    = {BUCK_VPROC11_CON0, 0x3,},
		._[CMD_5]    = {BUCK_VPROC11_CON0, 0x1,},
		._[CMD_6]    = {TOP_SPI_CON0, 0x1,},
		._[CMD_7]    = {TOP_SPI_CON0, 0x0,},
		._[CMD_8]    = {BUCK_VPROC12_CON0, 0x0,},
		._[CMD_9]    = {BUCK_VPROC12_CON0, 0x1,},
		._[CMD_10]   = {BUCK_VPROC11_CON0, 0x0,},
		._[CMD_11]   = {BUCK_VPROC11_CON0, 0x1,},
		._[CMD_12]   = {LDO_VSRAM_PROC12_CON0, 0x0,},
		._[CMD_13]   = {LDO_VSRAM_PROC12_CON0, 0x1,},
		._[CMD_14]   = {LDO_VSRAM_PROC11_CON0, 0x0,},
		._[CMD_15]   = {LDO_VSRAM_PROC11_CON0, 0x1,},
		._[CMD_20]   = {BUCK_VMODEM_ELR0, VOLT_TO_PMIC_VAL(55000),},
		._[CMD_21]   = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(60000),},
		._[CMD_22]   = {LDO_VSRAM_PROC11_CON0, 0x3,},
		._[CMD_23]   = {LDO_VSRAM_PROC11_CON0, 0x1,},
		.nr_idx = NR_IDX_ALL
	}
};

void _mt_spm_pmic_table_init(void)
{
	struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = {
		{(uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0,},
		{(uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1,},
		{(uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2,},
		{(uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3,},
		{(uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4,},
		{(uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5,},
		{(uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6,},
		{(uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7,},
		{(uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8,},
		{(uint32_t)SPM_DVFS_CMD9, (uint32_t)SPM_DVFS_CMD9,},
		{(uint32_t)SPM_DVFS_CMD10, (uint32_t)SPM_DVFS_CMD10,},
		{(uint32_t)SPM_DVFS_CMD11, (uint32_t)SPM_DVFS_CMD11,},
		{(uint32_t)SPM_DVFS_CMD12, (uint32_t)SPM_DVFS_CMD12,},
		{(uint32_t)SPM_DVFS_CMD13, (uint32_t)SPM_DVFS_CMD13,},
		{(uint32_t)SPM_DVFS_CMD14, (uint32_t)SPM_DVFS_CMD14,},
		{(uint32_t)SPM_DVFS_CMD15, (uint32_t)SPM_DVFS_CMD15,},
		{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD20,
		 (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD20,},
		{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD21,
		 (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD21,},
		{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD22,
		 (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD22,},
		{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD23,
		 (uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD23,}
	};

	memcpy(pw.addr, pwrap_cmd_default, sizeof(pwrap_cmd_default));
}

void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase)
{
	uint32_t idx, addr, data;

	if (phase >= NR_PMIC_WRAP_PHASE)
		return;

	if (pw.phase == phase)
		return;

	if (pw.addr[0].cmd_addr == 0)
		_mt_spm_pmic_table_init();

	pw.phase = phase;

	mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY |
		      BCLK_CG_EN_LSB | MD_BCLK_CG_EN_LSB);
	for (idx = 0; idx < pw.set[phase].nr_idx; idx++) {
		addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
		data = pw.set[phase]._[idx].cmd_wdata;
		mmio_write_32(pw.addr[idx].cmd_addr, addr | data);
	}
}

void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx,
			      uint32_t cmd_wdata)
{
	uint32_t addr;

	if (phase >= NR_PMIC_WRAP_PHASE)
		return;

	if (idx >= pw.set[phase].nr_idx)
		return;

	pw.set[phase]._[idx].cmd_wdata = cmd_wdata;

	mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY |
		      BCLK_CG_EN_LSB | MD_BCLK_CG_EN_LSB);
	if (pw.phase == phase) {
		addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
		mmio_write_32(pw.addr[idx].cmd_addr, addr | cmd_wdata);
	}
}

uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx)
{
	if (phase >= NR_PMIC_WRAP_PHASE)
		return 0;

	if (idx >= pw.set[phase].nr_idx)
		return 0;

	return pw.set[phase]._[idx].cmd_wdata;
}