1 /*
2  * sun9i specific clock code
3  *
4  * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
5  *
6  * SPDX-License-Identifier:	GPL-2.0+
7  */
8 
9 #include <common.h>
10 #include <asm/io.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/prcm.h>
13 #include <asm/arch/sys_proto.h>
14 
15 void clock_init_uart(void)
16 {
17 	struct sunxi_ccm_reg *const ccm =
18 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
19 
20 	/* open the clock for uart */
21 	setbits_le32(&ccm->apb1_gate,
22 		     CLK_GATE_OPEN << (APB1_GATE_UART_SHIFT +
23 				       CONFIG_CONS_INDEX - 1));
24 	/* deassert uart reset */
25 	setbits_le32(&ccm->apb1_reset_cfg,
26 		     1 << (APB1_RESET_UART_SHIFT +
27 			   CONFIG_CONS_INDEX - 1));
28 
29 	/* Dup with clock_init_safe(), drop once sun9i SPL support lands */
30 	writel(PLL4_CFG_DEFAULT, &ccm->pll4_periph0_cfg);
31 }
32 
33 int clock_twi_onoff(int port, int state)
34 {
35 	struct sunxi_ccm_reg *const ccm =
36 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
37 
38 	if (port > 4)
39 		return -1;
40 
41 	/* set the apb reset and clock gate for twi */
42 	if (state) {
43 		setbits_le32(&ccm->apb1_gate,
44 			     CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT + port));
45 		setbits_le32(&ccm->apb1_reset_cfg,
46 			     1 << (APB1_RESET_TWI_SHIFT + port));
47 	} else {
48 		clrbits_le32(&ccm->apb1_reset_cfg,
49 			     1 << (APB1_RESET_TWI_SHIFT + port));
50 		clrbits_le32(&ccm->apb1_gate,
51 			     CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT + port));
52 	}
53 
54 	return 0;
55 }
56 
57 unsigned int clock_get_pll4_periph0(void)
58 {
59 	struct sunxi_ccm_reg *const ccm =
60 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
61 	uint32_t rval = readl(&ccm->pll4_periph0_cfg);
62 	int n = ((rval & CCM_PLL4_CTRL_N_MASK) >> CCM_PLL4_CTRL_N_SHIFT);
63 	int p = ((rval & CCM_PLL4_CTRL_P_MASK) >> CCM_PLL4_CTRL_P_SHIFT);
64 	int m = ((rval & CCM_PLL4_CTRL_M_MASK) >> CCM_PLL4_CTRL_M_SHIFT) + 1;
65 	const int k = 1;
66 
67 	return ((24000000 * n * k) >> p) / m;
68 }
69