1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright (C) 2018 Marvell International Ltd.
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park * https://spdx.org/licenses
6*54fd6939SJiyong Park */
7*54fd6939SJiyong Park
8*54fd6939SJiyong Park #include <drivers/delay_timer.h>
9*54fd6939SJiyong Park #include <drivers/marvell/aro.h>
10*54fd6939SJiyong Park #include <lib/mmio.h>
11*54fd6939SJiyong Park
12*54fd6939SJiyong Park #include <a8k_plat_def.h>
13*54fd6939SJiyong Park
14*54fd6939SJiyong Park /* Notify bootloader on DRAM setup */
15*54fd6939SJiyong Park #define AP807_CPU_ARO_CTRL(cluster) \
16*54fd6939SJiyong Park (MVEBU_RFU_BASE + 0x82A8 + (0xA58 * (cluster)))
17*54fd6939SJiyong Park
18*54fd6939SJiyong Park /* 0 - ARO clock is enabled, 1 - ARO clock is disabled */
19*54fd6939SJiyong Park #define AP807_CPU_ARO_CLK_EN_OFFSET 0
20*54fd6939SJiyong Park #define AP807_CPU_ARO_CLK_EN_MASK (0x1 << AP807_CPU_ARO_CLK_EN_OFFSET)
21*54fd6939SJiyong Park
22*54fd6939SJiyong Park /* 0 - ARO is the clock source, 1 - PLL is the clock source */
23*54fd6939SJiyong Park #define AP807_CPU_ARO_SEL_PLL_OFFSET 5
24*54fd6939SJiyong Park #define AP807_CPU_ARO_SEL_PLL_MASK (0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET)
25*54fd6939SJiyong Park
26*54fd6939SJiyong Park /* AP807 clusters count */
27*54fd6939SJiyong Park #define AP807_CLUSTER_NUM 2
28*54fd6939SJiyong Park
29*54fd6939SJiyong Park /* PLL frequency values */
30*54fd6939SJiyong Park #define PLL_FREQ_1200 0x2AE5F002 /* 1200 */
31*54fd6939SJiyong Park #define PLL_FREQ_2000 0x2FC9F002 /* 2000 */
32*54fd6939SJiyong Park #define PLL_FREQ_2200 0x2AC57001 /* 2200 */
33*54fd6939SJiyong Park #define PLL_FREQ_2400 0x2AE5F001 /* 2400 */
34*54fd6939SJiyong Park
35*54fd6939SJiyong Park /* CPU PLL control registers */
36*54fd6939SJiyong Park #define AP807_CPU_PLL_CTRL(cluster) \
37*54fd6939SJiyong Park (MVEBU_RFU_BASE + 0x82E0 + (0x8 * (cluster)))
38*54fd6939SJiyong Park
39*54fd6939SJiyong Park #define AP807_CPU_PLL_PARAM(cluster) AP807_CPU_PLL_CTRL(cluster)
40*54fd6939SJiyong Park #define AP807_CPU_PLL_CFG(cluster) (AP807_CPU_PLL_CTRL(cluster) + 0x4)
41*54fd6939SJiyong Park #define AP807_CPU_PLL_CFG_BYPASS_MODE (0x1)
42*54fd6939SJiyong Park #define AP807_CPU_PLL_FRC_DSCHG (0x2)
43*54fd6939SJiyong Park #define AP807_CPU_PLL_CFG_USE_REG_FILE (0x1 << 9)
44*54fd6939SJiyong Park
pll_set_freq(unsigned int freq_val)45*54fd6939SJiyong Park static void pll_set_freq(unsigned int freq_val)
46*54fd6939SJiyong Park {
47*54fd6939SJiyong Park int i;
48*54fd6939SJiyong Park
49*54fd6939SJiyong Park if (freq_val != PLL_FREQ_2200)
50*54fd6939SJiyong Park return;
51*54fd6939SJiyong Park
52*54fd6939SJiyong Park for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
53*54fd6939SJiyong Park /* Set parameter of cluster i PLL to 2.2GHz */
54*54fd6939SJiyong Park mmio_write_32(AP807_CPU_PLL_PARAM(i), freq_val);
55*54fd6939SJiyong Park /* Set apll_lpf_frc_dschg - Control
56*54fd6939SJiyong Park * voltage of internal VCO is discharged
57*54fd6939SJiyong Park */
58*54fd6939SJiyong Park mmio_write_32(AP807_CPU_PLL_CFG(i),
59*54fd6939SJiyong Park AP807_CPU_PLL_FRC_DSCHG);
60*54fd6939SJiyong Park /* Set use_rf_conf load PLL parameter from register */
61*54fd6939SJiyong Park mmio_write_32(AP807_CPU_PLL_CFG(i),
62*54fd6939SJiyong Park AP807_CPU_PLL_FRC_DSCHG |
63*54fd6939SJiyong Park AP807_CPU_PLL_CFG_USE_REG_FILE);
64*54fd6939SJiyong Park /* Un-set apll_lpf_frc_dschg */
65*54fd6939SJiyong Park mmio_write_32(AP807_CPU_PLL_CFG(i),
66*54fd6939SJiyong Park AP807_CPU_PLL_CFG_USE_REG_FILE);
67*54fd6939SJiyong Park }
68*54fd6939SJiyong Park }
69*54fd6939SJiyong Park
70*54fd6939SJiyong Park /* Switch to ARO from PLL in ap807 */
aro_to_pll(void)71*54fd6939SJiyong Park static void aro_to_pll(void)
72*54fd6939SJiyong Park {
73*54fd6939SJiyong Park unsigned int reg;
74*54fd6939SJiyong Park int i;
75*54fd6939SJiyong Park
76*54fd6939SJiyong Park for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
77*54fd6939SJiyong Park /* switch from ARO to PLL */
78*54fd6939SJiyong Park reg = mmio_read_32(AP807_CPU_ARO_CTRL(i));
79*54fd6939SJiyong Park reg |= AP807_CPU_ARO_SEL_PLL_MASK;
80*54fd6939SJiyong Park mmio_write_32(AP807_CPU_ARO_CTRL(i), reg);
81*54fd6939SJiyong Park
82*54fd6939SJiyong Park mdelay(100);
83*54fd6939SJiyong Park
84*54fd6939SJiyong Park /* disable ARO clk driver */
85*54fd6939SJiyong Park reg = mmio_read_32(AP807_CPU_ARO_CTRL(i));
86*54fd6939SJiyong Park reg |= (AP807_CPU_ARO_CLK_EN_MASK);
87*54fd6939SJiyong Park mmio_write_32(AP807_CPU_ARO_CTRL(i), reg);
88*54fd6939SJiyong Park }
89*54fd6939SJiyong Park }
90*54fd6939SJiyong Park
91*54fd6939SJiyong Park /* switch from ARO to PLL
92*54fd6939SJiyong Park * in case of default frequency option, configure PLL registers
93*54fd6939SJiyong Park * to be aligned with new default frequency.
94*54fd6939SJiyong Park */
ap807_clocks_init(unsigned int freq_option)95*54fd6939SJiyong Park void ap807_clocks_init(unsigned int freq_option)
96*54fd6939SJiyong Park {
97*54fd6939SJiyong Park /* Modifications in frequency table:
98*54fd6939SJiyong Park * 0x0: 764x: change to 2000 MHz.
99*54fd6939SJiyong Park * 0x2: 744x change to 1800 MHz, 764x change to 2200/2400.
100*54fd6939SJiyong Park * 0x3: 3900/744x/764x change to 1200 MHz.
101*54fd6939SJiyong Park */
102*54fd6939SJiyong Park
103*54fd6939SJiyong Park if (freq_option == CPU_2200_DDR_1200_RCLK_1200)
104*54fd6939SJiyong Park pll_set_freq(PLL_FREQ_2200);
105*54fd6939SJiyong Park
106*54fd6939SJiyong Park /* Switch from ARO to PLL */
107*54fd6939SJiyong Park aro_to_pll();
108*54fd6939SJiyong Park
109*54fd6939SJiyong Park }
110