summaryrefslogtreecommitdiff
path: root/src/soc/mediatek/common/clkbuf.c
blob: 735457122fde5dcf64b09ec5860b6d4474ca5495 (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
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <delay.h>
#include <device/mmio.h>
#include <soc/clkbuf.h>
#include <soc/pmif.h>
#if CONFIG(SRCLKEN_RC_SUPPORT)
#include <soc/srclken_rc.h>
#endif

#define BUFTAG			"[CLKBUF]"
#define buf_info(fmt, arg ...)	printk(BIOS_INFO, BUFTAG "%s,%d: " fmt, \
					__func__, __LINE__, ## arg)

#define _buf_clrset32_impl(addr, clear, set) \
	buf_write(addr, (buf_read(addr) & ~((uint32_t)(clear))) | (set))

#define BUF_SET_FIELDS(addr, ...) \
	_BF_IMPL(_buf_clrset32_impl, addr, __VA_ARGS__)
#define BUF_READ_FIELD(addr, name) \
	EXTRACT_BITFIELD(buf_read(addr), name)

#define PMIC_CW00_INIT_VAL	0x4005 /* 0100 0000 0000 0101 */
#define PMIC_CW09_INIT_VAL	0x01F0 /* 0000 0001 1111 0000 */

static struct pmif *pmif_arb;

static u32 buf_read(u32 addr)
{
	u32 rdata;

	if (pmif_arb == NULL)
		pmif_arb = get_pmif_controller(PMIF_SPI, 0);
	pmif_arb->read(pmif_arb, 0, addr, &rdata);

	return rdata;
}

static void buf_write(u32 addr, u32 wdata)
{
	if (pmif_arb == NULL)
		pmif_arb = get_pmif_controller(PMIF_SPI, 0);
	pmif_arb->write(pmif_arb, 0, addr, wdata);
}

static void dump_clkbuf_log(void)
{
	u32 pmic_cw00, pmic_cw09, pmic_cw12, pmic_cw13, pmic_cw15, pmic_cw19,
	    top_spi_con1, ldo_vrfck_op_en, ldo_vbbck_op_en, ldo_vrfck_en,
	    ldo_vbbck_en, vrfck_hv_en;

	pmic_cw00 = BUF_READ_FIELD(PMIC_RG_DCXO_CW00, PMIC_REG_COMMON);
	pmic_cw09 = BUF_READ_FIELD(PMIC_RG_DCXO_CW09, PMIC_REG_COMMON);
	pmic_cw12 = BUF_READ_FIELD(PMIC_RG_DCXO_CW12, PMIC_REG_COMMON);
	pmic_cw13 = BUF_READ_FIELD(PMIC_RG_DCXO_CW13, PMIC_REG_COMMON);
	pmic_cw15 = BUF_READ_FIELD(PMIC_RG_DCXO_CW15, PMIC_REG_COMMON);
	pmic_cw19 = BUF_READ_FIELD(PMIC_RG_DCXO_CW19, PMIC_REG_COMMON);
	buf_info("DCXO_CW00/09/12/13/15/19=%#x %#x %#x %#x %#x %#x\n",
		pmic_cw00, pmic_cw09, pmic_cw12,
		pmic_cw13, pmic_cw15, pmic_cw19);

	top_spi_con1 = BUF_READ_FIELD(PMIC_RG_TOP_SPI_CON1, PMIC_RG_SRCLKEN_IN3_EN);
	ldo_vrfck_op_en = BUF_READ_FIELD(PMIC_RG_LDO_VRFCK_OP_EN,
					  PMIC_RG_LDO_VRFCK_HW14_OP_EN);
	ldo_vbbck_op_en = BUF_READ_FIELD(PMIC_RG_LDO_VBBCK_OP_EN,
					  PMIC_RG_LDO_VBBCK_HW14_OP_EN);
	ldo_vrfck_en = BUF_READ_FIELD(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN);
	ldo_vbbck_en = BUF_READ_FIELD(PMIC_RG_LDO_VBBCK_CON0, PMIC_RG_LDO_VBBCK_EN);
	buf_info("spi_con1/ldo_rf_op/ldo_bb_op/ldo_rf_en/ldo_bb_en=%#x %#x %#x %#x %#x\n",
		top_spi_con1, ldo_vrfck_op_en, ldo_vbbck_op_en,
		ldo_vrfck_en, ldo_vbbck_en);

	vrfck_hv_en = BUF_READ_FIELD(PMIC_RG_DCXO_ADLDO_BIAS_ELR_0, PMIC_RG_VRFCK_HV_EN);
	buf_info("clk buf vrfck_hv_en=%#x\n", vrfck_hv_en);
}

int clk_buf_init(void)
{
	/* Dump registers before setting */
	dump_clkbuf_log();

	/* Unlock pmic key */
	BUF_SET_FIELDS(PMIC_TOP_TMA_KEY, PMIC_REG_COMMON, PMIC_TOP_TMA_KEY_UNLOCK);

	/* 1.1 Set VRFCK input supply(11.ac mode) */
	BUF_SET_FIELDS(PMIC_RG_DCXO_ADLDO_BIAS_ELR_0, PMIC_RG_VRFCK_HV_EN, 0x0);

	/* 1.2.0 Set VRFCK En = 0 */
	BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN, 0x0);
	/* 1.2.1 Set VRFCK1 as power src */
	BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_ELR, PMIC_RG_LDO_VRFCK_ANA_SEL, 0x1);

	/* 1.2.2 Switch LDO-RFCK to LDO-RFCK1 */
	BUF_SET_FIELDS(PMIC_RG_DCXO_ADLDO_BIAS_ELR_0, PMIC_RG_VRFCK_NDIS_EN, 0x0);
	BUF_SET_FIELDS(PMIC_RG_DCXO_ADLDO_BIAS_ELR_1, PMIC_RG_VRFCK_1_NDIS_EN, 0x1);

	/* 1.2.0 Set VRFCK En = 1 */
	BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN, 0x1);

	/* 1.2.3 Lock pmic key */
	BUF_SET_FIELDS(PMIC_TOP_TMA_KEY, PMIC_REG_COMMON, 0x0);

	/* Enable XO LDO */
	BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_OP_EN_SET, PMIC_RG_LDO_VRFCK_HW14_OP_EN, 0x1);
	BUF_SET_FIELDS(PMIC_RG_LDO_VBBCK_OP_EN_SET, PMIC_RG_LDO_VBBCK_HW14_OP_EN, 0x1);
	BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN, 0x0);
	BUF_SET_FIELDS(PMIC_RG_LDO_VBBCK_CON0, PMIC_RG_LDO_VBBCK_EN, 0x0);

	/* Enable 26M control */
	if (!CONFIG(SRCLKEN_RC_SUPPORT)) {
		/* Legacy co-clock mode */
		BUF_SET_FIELDS(PMIC_RG_TOP_SPI_CON1, PMIC_RG_SRCLKEN_IN3_EN, 0x0);

		BUF_SET_FIELDS(PMIC_RG_DCXO_CW00, PMIC_REG_COMMON, PMIC_CW00_INIT_VAL);
		BUF_SET_FIELDS(PMIC_RG_DCXO_CW09, PMIC_REG_COMMON, PMIC_CW09_INIT_VAL);
	} else {
		/* New co-clock mode */
		/* All XO mode should set to 2'b01 */
		BUF_SET_FIELDS(PMIC_RG_DCXO_CW00, PMIC_REG_COMMON, PMIC_CW00_INIT_VAL);
		BUF_SET_FIELDS(PMIC_RG_DCXO_CW09, PMIC_REG_COMMON, PMIC_CW09_INIT_VAL);

		/* 1. Update control mapping table */
		BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL0, PMIC_RG_XO_VOTE, 0x005);
		BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL1, PMIC_RG_XO_VOTE, 0x0);
		BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL2, PMIC_RG_XO_VOTE, 0x0);
		BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL3, PMIC_RG_XO_VOTE, 0x0);
		BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL4, PMIC_RG_XO_VOTE, 0x0);
		/* Wait 100us */
		udelay(100);

		/* 2. Switch to new control mode */
		BUF_SET_FIELDS(PMIC_RG_DCXO_CW08, PMIC_RG_XO_PMIC_TOP_DIG_SW, 0x0);
	}

	/* Check if the setting is ok */
	dump_clkbuf_log();

	return 0;
}