1 /*
2  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdint.h>
8 #include <stdbool.h>
9 
10 #include <arch.h>
11 #include <lib/mmio.h>
12 
13 #include <imx_regs.h>
14 #include <imx_clock.h>
15 
imx_clock_target_set(unsigned int id,uint32_t val)16 void imx_clock_target_set(unsigned int id, uint32_t val)
17 {
18 	struct ccm *ccm = ((struct ccm *)CCM_BASE);
19 	uintptr_t addr;
20 
21 	if (id > CCM_ROOT_CTRL_NUM)
22 		return;
23 
24 	addr = (uintptr_t)&ccm->ccm_root_ctrl[id].ccm_target_root;
25 	mmio_write_32(addr, val);
26 }
27 
imx_clock_target_clr(unsigned int id,uint32_t val)28 void imx_clock_target_clr(unsigned int id, uint32_t val)
29 {
30 	struct ccm *ccm = ((struct ccm *)CCM_BASE);
31 	uintptr_t addr;
32 
33 	if (id > CCM_ROOT_CTRL_NUM)
34 		return;
35 
36 	addr = (uintptr_t)&ccm->ccm_root_ctrl[id].ccm_target_root_clr;
37 	mmio_write_32(addr, val);
38 }
39 
imx_clock_gate_enable(unsigned int id,bool enable)40 void imx_clock_gate_enable(unsigned int id, bool enable)
41 {
42 	struct ccm *ccm = ((struct ccm *)CCM_BASE);
43 	uintptr_t addr;
44 
45 	if (id > CCM_CLK_GATE_CTRL_NUM)
46 		return;
47 
48 	/* TODO: add support for more than DOMAIN0 clocks */
49 	if (enable)
50 		addr = (uintptr_t)&ccm->ccm_clk_gate_ctrl[id].ccm_ccgr_set;
51 	else
52 		addr = (uintptr_t)&ccm->ccm_clk_gate_ctrl[id].ccm_ccgr_clr;
53 
54 	mmio_write_32(addr, CCM_CCGR_SETTING0_DOM_CLK_ALWAYS);
55 }
56 
imx_clock_enable_uart(unsigned int uart_id,uint32_t uart_clk_en_bits)57 void imx_clock_enable_uart(unsigned int uart_id, uint32_t uart_clk_en_bits)
58 {
59 	unsigned int ccm_trgt_id = CCM_TRT_ID_UART1_CLK_ROOT + uart_id;
60 	unsigned int ccm_ccgr_id = CCM_CCGR_ID_UART1 + uart_id;
61 
62 	/* Check for error */
63 	if (uart_id > MXC_MAX_UART_NUM)
64 		return;
65 
66 	/* Set target register values */
67 	imx_clock_target_set(ccm_trgt_id, uart_clk_en_bits);
68 
69 	/* Enable the clock gate */
70 	imx_clock_gate_enable(ccm_ccgr_id, true);
71 }
72 
imx_clock_disable_uart(unsigned int uart_id)73 void imx_clock_disable_uart(unsigned int uart_id)
74 {
75 	unsigned int ccm_trgt_id = CCM_TRT_ID_UART1_CLK_ROOT + uart_id;
76 	unsigned int ccm_ccgr_id = CCM_CCGR_ID_UART1 + uart_id;
77 
78 	/* Check for error */
79 	if (uart_id > MXC_MAX_UART_NUM)
80 		return;
81 
82 	/* Disable the clock gate */
83 	imx_clock_gate_enable(ccm_ccgr_id, false);
84 
85 	/* Clear the target */
86 	imx_clock_target_clr(ccm_trgt_id, 0xFFFFFFFF);
87 }
88 
imx_clock_enable_usdhc(unsigned int usdhc_id,uint32_t usdhc_clk_en_bits)89 void imx_clock_enable_usdhc(unsigned int usdhc_id, uint32_t usdhc_clk_en_bits)
90 {
91 	unsigned int ccm_trgt_id = CCM_TRT_ID_USDHC1_CLK_ROOT + usdhc_id;
92 	unsigned int ccm_ccgr_id = CCM_CCGR_ID_USBHDC1 + usdhc_id;
93 
94 	/* Check for error */
95 	if (usdhc_id > MXC_MAX_USDHC_NUM)
96 		return;
97 
98 	/* Set target register values */
99 	imx_clock_target_set(ccm_trgt_id, usdhc_clk_en_bits);
100 
101 	/* Enable the clock gate */
102 	imx_clock_gate_enable(ccm_ccgr_id, true);
103 }
104 
imx_clock_enable_wdog(unsigned int wdog_id)105 void imx_clock_enable_wdog(unsigned int wdog_id)
106 {
107 	unsigned int ccm_ccgr_id = CCM_CCGR_ID_WDOG1 + wdog_id;
108 
109 	/* Check for error */
110 	if (wdog_id > MXC_MAX_WDOG_NUM)
111 		return;
112 
113 	/* Enable the clock gate */
114 	imx_clock_gate_enable(ccm_ccgr_id, true);
115 }
116 
imx_clock_disable_wdog(unsigned int wdog_id)117 void imx_clock_disable_wdog(unsigned int wdog_id)
118 {
119 	unsigned int ccm_trgt_id = CCM_TRT_ID_WDOG_CLK_ROOT;
120 	unsigned int ccm_ccgr_id = CCM_CCGR_ID_WDOG1 + wdog_id;
121 
122 	/* Check for error */
123 	if (wdog_id > MXC_MAX_WDOG_NUM)
124 		return;
125 
126 	/* Disable the clock gate */
127 	imx_clock_gate_enable(ccm_ccgr_id, false);
128 
129 	/* Clear the target */
130 	imx_clock_target_clr(ccm_trgt_id, 0xFFFFFFFF);
131 }
132 
imx_clock_set_wdog_clk_root_bits(uint32_t wdog_clk_root_en_bits)133 void imx_clock_set_wdog_clk_root_bits(uint32_t wdog_clk_root_en_bits)
134 {
135 	/* Enable the common clock root just once */
136 	imx_clock_target_set(CCM_TRT_ID_WDOG_CLK_ROOT, wdog_clk_root_en_bits);
137 }
138 
imx_clock_enable_usb(unsigned int ccm_ccgr_usb_id)139 void imx_clock_enable_usb(unsigned int ccm_ccgr_usb_id)
140 {
141 	/* Enable the clock gate */
142 	imx_clock_gate_enable(ccm_ccgr_usb_id, true);
143 }
144 
imx_clock_disable_usb(unsigned int ccm_ccgr_usb_id)145 void imx_clock_disable_usb(unsigned int ccm_ccgr_usb_id)
146 {
147 	/* Disable the clock gate */
148 	imx_clock_gate_enable(ccm_ccgr_usb_id, false);
149 }
150 
imx_clock_set_usb_clk_root_bits(uint32_t usb_clk_root_en_bits)151 void imx_clock_set_usb_clk_root_bits(uint32_t usb_clk_root_en_bits)
152 {
153 	/* Enable the common clock root just once */
154 	imx_clock_target_set(CCM_TRT_ID_USB_HSIC_CLK_ROOT, usb_clk_root_en_bits);
155 }
156