• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 #include "sys_hal.h"
20 
21 #include "hi_osal.h"
22 #include "hi_type.h"
23 #include "hi_board.h"
24 
25 void *g_reg_crg_base_va = HI_NULL;
26 void *g_reg_sys_base_va = HI_NULL;
27 void *g_reg_ddr0_base_va = HI_NULL;
28 void *g_reg_misc_base_va = HI_NULL;
29 void *g_reg_otp_base_va = HI_NULL;
30 
31 #define io_crg_address(x) ((hi_uintptr_t)g_reg_crg_base_va + (x) - CRG_REGS_ADDR)
32 #define io_sys_address(x) ((hi_uintptr_t)g_reg_sys_base_va + (x) - SYS_REGS_ADDR)
33 #define io_ddr0_address(x) ((hi_uintptr_t)g_reg_ddr0_base_va + (x) - DDRC0_REG_ADDR)
34 #define io_misc_address(x) ((hi_uintptr_t)g_reg_misc_base_va + (x) - MISC_REGS_ADDR)
35 
36 static osal_spinlock_t g_crg_spin_lock = {0};
37 #define sys_crg_spin_lock(flags) osal_spin_lock_irqsave(&g_crg_spin_lock, &(flags))
38 #define sys_crg_spin_unlock(flags) osal_spin_unlock_irqrestore(&g_crg_spin_lock, &(flags))
39 
hi_reg_set_bit(unsigned long value,unsigned long offset,unsigned long addr)40 static void hi_reg_set_bit(unsigned long value, unsigned long offset, unsigned long addr)
41 {
42     unsigned long t, mask;
43     unsigned long flags;
44 
45     sys_crg_spin_lock(flags);
46     mask = 1 << offset;
47     t = osal_readl((const volatile void *)(hi_uintptr_t)addr);
48     t &= ~mask;
49     t |= (value << offset) & mask;
50     osal_writel(t, (volatile void *)(hi_uintptr_t)addr);
51     sys_crg_spin_unlock(flags);
52 }
53 
hi_reg_write32(unsigned long value,unsigned long mask,unsigned long addr)54 static void hi_reg_write32(unsigned long value, unsigned long mask, unsigned long addr)
55 {
56     unsigned long t;
57     unsigned long flags;
58 
59     sys_crg_spin_lock(flags);
60     t = osal_readl((const volatile void *)(hi_uintptr_t)addr);
61     t &= ~mask;
62     t |= value & mask;
63     osal_writel(t, (volatile void *)(hi_uintptr_t)addr);
64     sys_crg_spin_unlock(flags);
65 }
66 
hi_reg_read(unsigned int * pvalue,unsigned long addr)67 static inline void hi_reg_read(unsigned int *pvalue, unsigned long addr)
68 {
69     *pvalue = osal_readl((const volatile void *)(hi_uintptr_t)addr);
70 }
71 
72 /* VO control */
73 #define LCD_CRG_PERCTL_ADDR CRG_PERCTL65_ADDR
74 #define VOU_CRG_PERCTL_ADDR CRG_PERCTL66_ADDR
75 
sys_hal_vou_bus_reset_sel(hi_bool reset)76 hi_s32 sys_hal_vou_bus_reset_sel(hi_bool reset)
77 {
78     hi_u32 tmp = (reset == HI_TRUE) ? 1 : 0;
79 
80     hi_reg_set_bit(tmp, 0, io_crg_address(VOU_CRG_PERCTL_ADDR));
81 
82     return 0;
83 }
84 
sys_hal_vou_apb_clk_en(hi_s32 dev,hi_bool clk_en)85 hi_s32 sys_hal_vou_apb_clk_en(hi_s32 dev, hi_bool clk_en)
86 {
87     hi_u32 tmp = (clk_en == HI_TRUE) ? 1 : 0;
88     hi_unused(dev);
89 
90     hi_reg_set_bit(tmp, 1, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 1:vo software reset clock */
91 
92     return 0;
93 }
94 
95 /* VO AXI BUS CLK */
sys_hal_vou_bus_clk_en(hi_bool clk_en)96 hi_s32 sys_hal_vou_bus_clk_en(hi_bool clk_en)
97 {
98     hi_u32 tmp = (clk_en == HI_TRUE) ? 1 : 0;
99 
100     hi_reg_set_bit(tmp, 2, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 2:vo axi clock */
101 
102     return 0;
103 }
104 
sys_hal_vou_cfg_clk_en(hi_s32 dev,hi_bool clk_en)105 hi_s32 sys_hal_vou_cfg_clk_en(hi_s32 dev, hi_bool clk_en)
106 {
107     hi_u32 tmp = (clk_en == HI_TRUE) ? 1 : 0;
108     hi_unused(dev);
109 
110     hi_reg_set_bit(tmp, 3, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 3:vo cfg clock */
111 
112     return 0;
113 }
114 
sys_hal_vou_core_clk_en(hi_s32 dev,hi_bool clk_en)115 hi_s32 sys_hal_vou_core_clk_en(hi_s32 dev, hi_bool clk_en)
116 {
117     hi_u32 tmp = (clk_en == HI_TRUE) ? 1 : 0;
118     hi_unused(dev);
119 
120     hi_reg_set_bit(tmp, 5, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 5:vo core clock */
121 
122     return 0;
123 }
124 
sys_hal_vou_dev_clk_en(hi_s32 vo_dev,hi_bool clk_en)125 hi_s32 sys_hal_vou_dev_clk_en(hi_s32 vo_dev, hi_bool clk_en)
126 {
127     hi_u32 tmp = (clk_en == HI_TRUE) ? 1 : 0;
128     hi_unused(vo_dev);
129 
130     hi_reg_set_bit(tmp, 6, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 6:vo dev clock */
131 
132     return 0;
133 }
134 
sys_hal_vou_out_clk_en(hi_s32 dev,hi_bool clk_en)135 hi_s32 sys_hal_vou_out_clk_en(hi_s32 dev, hi_bool clk_en)
136 {
137     hi_u32 tmp = (clk_en == HI_TRUE) ? 1 : 0;
138     hi_unused(dev);
139 
140     hi_reg_set_bit(tmp, 8, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 8:VO_CLKOUT */
141 
142     return 0;
143 }
144 
sys_hal_vou_bt_clk_en(hi_s32 vo_dev,hi_bool bt_clk_en)145 hi_s32 sys_hal_vou_bt_clk_en(hi_s32 vo_dev, hi_bool bt_clk_en)
146 {
147     hi_u32 tmp = (bt_clk_en == HI_TRUE) ? 1 : 0;
148     hi_unused(vo_dev);
149 
150     hi_reg_set_bit(tmp, 8, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 8:vdp bt_bp clock en */
151     hi_reg_set_bit(tmp, 9, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 9:vdp BT1120/BT656 clock en */
152 
153     return 0;
154 }
155 
sys_hal_vou_hdmi_clk_en(hi_s32 vo_dev,hi_bool hdmi_clk_en)156 hi_s32 sys_hal_vou_hdmi_clk_en(hi_s32 vo_dev, hi_bool hdmi_clk_en)
157 {
158     hi_u32 tmp = (hdmi_clk_en == HI_TRUE) ? 1 : 0;
159     hi_unused(vo_dev);
160 
161     hi_reg_set_bit(tmp, 10, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 10:vdp hdmi clock en */
162 
163     return 0;
164 }
165 
sys_hal_vou_mipi_clk_en(hi_s32 vo_dev,hi_bool mipi_clk_en)166 hi_s32 sys_hal_vou_mipi_clk_en(hi_s32 vo_dev, hi_bool mipi_clk_en)
167 {
168     hi_u32 tmp = (mipi_clk_en == HI_TRUE) ? 1 : 0;
169     hi_unused(vo_dev);
170 
171     hi_reg_set_bit(tmp, 11, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 11:vdp mipi clock en */
172 
173     return 0;
174 }
175 
sys_hal_vou_hd0_div_mode(hi_s32 dev,hi_u32 hd0_div_mod)176 hi_s32 sys_hal_vou_hd0_div_mode(hi_s32 dev, hi_u32 hd0_div_mod)
177 {
178     hi_unused(dev);
179 
180     hi_reg_write32(hd0_div_mod << 12, 0x3 << 12, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 12:clock div; 0x3:mask */
181 
182     return 0;
183 }
184 
sys_hal_vou_hd_clk_sel(hi_s32 dev,hi_u32 clk_sel)185 hi_s32 sys_hal_vou_hd_clk_sel(hi_s32 dev, hi_u32 clk_sel)
186 {
187     hi_unused(dev);
188 
189     hi_reg_write32(clk_sel << 14, 0x1 << 14, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 14:vdp hd clock; 0x1:mask */
190 
191     return 0;
192 }
193 
sys_hal_vou_hdmi_tx_clk_en(hi_s32 dev,hi_bool hdmi_tx_clk_en)194 hi_s32 sys_hal_vou_hdmi_tx_clk_en(hi_s32 dev, hi_bool hdmi_tx_clk_en)
195 {
196     hi_u32 tmp = (hdmi_tx_clk_en == HI_TRUE) ? 1 : 0;
197     hi_unused(dev);
198 
199     hi_reg_write32(tmp << 18, 0x1 << 18, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 18:vdp hdmi clock; 0x1:mask */
200 
201     return 0;
202 }
203 
sys_hal_vou_mipi_tx_clk_en(hi_s32 dev,hi_bool mi_pi_tx_clk_en)204 hi_s32 sys_hal_vou_mipi_tx_clk_en(hi_s32 dev, hi_bool mi_pi_tx_clk_en)
205 {
206     hi_u32 tmp = (mi_pi_tx_clk_en == HI_TRUE) ? 1 : 0;
207     hi_unused(dev);
208 
209     hi_reg_write32(tmp << 19, 0x1 << 19, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 19:mipi_tx clock; 0x1:mask */
210 
211     return 0;
212 }
213 
sys_hal_vou_hd_out_pctrl(hi_s32 dev,hi_bool clk_reverse)214 hi_s32 sys_hal_vou_hd_out_pctrl(hi_s32 dev, hi_bool clk_reverse)
215 {
216     hi_u32 tmp = (clk_reverse == HI_TRUE) ? 1 : 0;
217     hi_unused(dev);
218 
219     hi_reg_set_bit(tmp, 20, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 20:VDP_MIPI phase */
220 
221     return 0;
222 }
223 
sys_hal_vou_out_clk_sel(hi_s32 dev,hi_u32 clk_sel)224 hi_s32 sys_hal_vou_out_clk_sel(hi_s32 dev, hi_u32 clk_sel)
225 {
226     hi_unused(dev);
227 
228     hi_reg_write32(clk_sel << 21, 0xf << 21, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 25:clock sel; 0xf:mask */
229 
230     return 0;
231 }
232 
sys_hal_vou_hd_hdmi_clk_div(hi_s32 dev,hi_u32 hdmi_clk_div)233 hi_s32 sys_hal_vou_hd_hdmi_clk_div(hi_s32 dev, hi_u32 hdmi_clk_div)
234 {
235     hi_unused(dev);
236 
237     hi_reg_write32(hdmi_clk_div << 25, 0x1f << 25, io_crg_address(VOU_CRG_PERCTL_ADDR)); /* 25:clock div; 0x1f:mask */
238 
239     return 0;
240 }
241 #ifdef HI_DEBUG
sys_hal_vou_bt_clk_sel(hi_s32 vo_dev,hi_u32 bt_clk_ch_sel)242 hi_s32 sys_hal_vou_bt_clk_sel(hi_s32 vo_dev, hi_u32 bt_clk_ch_sel)
243 {
244     if (vo_dev == 0) {
245     } else {
246         return -1;
247     }
248 
249     return 0;
250 }
251 #endif
252 
sys_hal_vou_lcd_clk_en(hi_s32 vo_dev,hi_bool clk_en)253 hi_s32 sys_hal_vou_lcd_clk_en(hi_s32 vo_dev, hi_bool clk_en)
254 {
255     hi_u32 tmp = (clk_en == HI_TRUE) ? 1 : 0;
256     hi_unused(vo_dev);
257 
258     hi_reg_set_bit(tmp, 27, io_crg_address(LCD_CRG_PERCTL_ADDR)); /* 27:lcd clock en */
259 
260     return 0;
261 }
262 
sys_hal_lcd_mclk_div(hi_u32 mclk_div)263 hi_s32 sys_hal_lcd_mclk_div(hi_u32 mclk_div)
264 {
265     hi_reg_write32(mclk_div, 0x7ffffff, io_crg_address(LCD_CRG_PERCTL_ADDR)); /* 0x7ffffff:clock div coef */
266 
267     return 0;
268 }
269 
sys_hal_lcd_data_mode(hi_u32 data_mode)270 hi_s32 sys_hal_lcd_data_mode(hi_u32 data_mode)
271 {
272     hi_reg_write32(data_mode << 8, 0x7 << 8, io_misc_address(MISC_CTL18_ADDR)); /* bit[8~10]:out mode; 0x7:mask */
273 
274     return 0;
275 }
276 
sys_hal_set_vo_pll_frac(hi_s32 pll,hi_u32 bits_set)277 hi_s32 sys_hal_set_vo_pll_frac(hi_s32 pll, hi_u32 bits_set)
278 {
279     if ((pll == 0) || (pll == 1)) {
280         hi_reg_write32(bits_set << 0, 0xffffff << 0, io_crg_address(CRG_PERCTL6_ADDR));
281     } else {
282         return -1;
283     }
284     return 0;
285 }
286 
sys_hal_set_vo_pll_postdiv1(hi_s32 pll,hi_u32 bits_set)287 hi_s32 sys_hal_set_vo_pll_postdiv1(hi_s32 pll, hi_u32 bits_set)
288 {
289     if ((pll == 0) || (pll == 1)) {
290         hi_reg_write32(bits_set << 24, 0x7 << 24, io_crg_address(CRG_PERCTL6_ADDR)); /* 24:vpll 1st;0x7:coef */
291     } else {
292         return -1;
293     }
294     return 0;
295 }
sys_hal_set_vo_pll_postdiv2(hi_s32 pll,hi_u32 bits_set)296 hi_s32 sys_hal_set_vo_pll_postdiv2(hi_s32 pll, hi_u32 bits_set)
297 {
298     if ((pll == 0) || (pll == 1)) {
299         hi_reg_write32(bits_set << 28, 0x7 << 28, io_crg_address(CRG_PERCTL6_ADDR)); /* 28:vpll 2nd;0x7:coef */
300     } else {
301         return -1;
302     }
303     return 0;
304 }
sys_hal_set_vo_pll_refdiv(hi_s32 pll,hi_u32 bits_set)305 hi_s32 sys_hal_set_vo_pll_refdiv(hi_s32 pll, hi_u32 bits_set)
306 {
307     if ((pll == 0) || (pll == 1)) {
308         hi_reg_write32(bits_set << 12, 0x3f << 12, io_crg_address(CRG_PERCTL7_ADDR)); /* 12:vpll div;0x3f:coef */
309     } else {
310         return -1;
311     }
312     return 0;
313 }
sys_hal_set_vo_pll_fbdiv(hi_s32 pll,hi_u32 bits_set)314 hi_s32 sys_hal_set_vo_pll_fbdiv(hi_s32 pll, hi_u32 bits_set)
315 {
316     if ((pll == 0) || (pll == 1)) {
317         hi_reg_write32(bits_set << 0, 0xfff << 0, io_crg_address(CRG_PERCTL7_ADDR)); /* 0xfff:coef */
318     } else {
319         return -1;
320     }
321     return 0;
322 }
323 
sys_hal_aio_reset_sel(hi_bool reset)324 hi_s32 sys_hal_aio_reset_sel(hi_bool reset)
325 {
326     hi_u32 tmp = (reset == HI_TRUE) ? 1 : 0;
327 
328     hi_reg_set_bit(tmp, 0, io_crg_address(CRG_PERCTL103_ADDR)); /* 0:software reset */
329     hi_reg_set_bit(tmp, 2, io_crg_address(CRG_PERCTL103_ADDR)); /* 2:pop reset */
330 
331     return 0;
332 }
333 
sys_hal_aio_clk_en(hi_bool clk_en)334 hi_s32 sys_hal_aio_clk_en(hi_bool clk_en)
335 {
336     hi_u32 tmp = (clk_en == HI_TRUE) ? 1 : 0;
337 
338     hi_reg_set_bit(tmp, 1, io_crg_address(CRG_PERCTL103_ADDR)); /* 1:clock */
339     hi_reg_set_bit(tmp, 3, io_crg_address(CRG_PERCTL103_ADDR)); /* 3:pll clock */
340 
341     return 0;
342 }
343 
344 
sys_hal_low_power(hi_void)345 static hi_void sys_hal_low_power(hi_void)
346 {
347     hi_reg_write32(0x00, 0x01, io_crg_address(CRG_PERCTL111_ADDR));
348 }
349 
sys_hal_init(hi_void)350 hi_s32 sys_hal_init(hi_void)
351 {
352     if (osal_spin_lock_init(&g_crg_spin_lock) < 0) {
353         osal_printk("spinlock init fail, line: %d. \n", __LINE__);
354         return -1;
355     }
356 
357     if (g_reg_crg_base_va == HI_NULL) {
358         g_reg_crg_base_va = (void *)osal_ioremap(CRG_REGS_ADDR, (hi_u32)CRG_REGS_SIZE);
359         if (g_reg_crg_base_va == HI_NULL) {
360             osal_printk("remap crg reg fail, line: %d. \n", __LINE__);
361             goto sys_hal_fail;
362         }
363     }
364 
365     if (g_reg_sys_base_va == HI_NULL) {
366         g_reg_sys_base_va = (void *)osal_ioremap(SYS_REGS_ADDR, (hi_u32)SYS_REGS_SIZE);
367         if (g_reg_sys_base_va == HI_NULL) {
368             osal_printk("remap sys reg fail, line: %d. \n", __LINE__);
369             goto sys_hal_fail;
370         }
371     }
372 
373     if (g_reg_ddr0_base_va == HI_NULL) {
374         g_reg_ddr0_base_va = (void *)osal_ioremap(DDRC0_REG_ADDR, (hi_u32)DDRC_REGS_SIZE);
375         if (g_reg_ddr0_base_va == HI_NULL) {
376             osal_printk("remap ddr0 reg fail, line: %d. \n", __LINE__);
377             goto sys_hal_fail;
378         }
379     }
380 
381     if (g_reg_misc_base_va == HI_NULL) {
382         g_reg_misc_base_va = (void *)osal_ioremap(MISC_REGS_ADDR, (hi_u32)MISC_REGS_SIZE);
383         if (g_reg_misc_base_va == HI_NULL) {
384             osal_printk("remap MISC reg fail, line: %d. \n", __LINE__);
385             goto sys_hal_fail;
386         }
387     }
388 
389     if (g_reg_otp_base_va == HI_NULL) {
390         g_reg_otp_base_va = (void *)osal_ioremap(OTP_REGS_ADDR, (hi_u32)OTP_REGS_SIZE);
391         if (g_reg_otp_base_va == HI_NULL) {
392             osal_printk("remap OTP reg fail, line: %d. \n", __LINE__);
393             goto sys_hal_fail;
394         }
395     }
396 
397     sys_hal_low_power();
398 
399     return 0;
400 
401 sys_hal_fail:
402     sys_hal_exit();
403     return -1;
404 }
405 
sys_hal_exit(hi_void)406 hi_void sys_hal_exit(hi_void)
407 {
408     if (g_reg_crg_base_va != HI_NULL) {
409         osal_iounmap(g_reg_crg_base_va, (hi_u32)CRG_REGS_SIZE);
410         g_reg_crg_base_va = HI_NULL;
411     }
412     if (g_reg_sys_base_va != HI_NULL) {
413         osal_iounmap(g_reg_sys_base_va, (hi_u32)SYS_REGS_SIZE);
414         g_reg_sys_base_va = HI_NULL;
415     }
416     if (g_reg_ddr0_base_va != HI_NULL) {
417         osal_iounmap(g_reg_ddr0_base_va, (hi_u32)DDRC_REGS_SIZE);
418         g_reg_ddr0_base_va = HI_NULL;
419     }
420 
421     if (g_reg_misc_base_va != HI_NULL) {
422         osal_iounmap(g_reg_misc_base_va, (hi_u32)MISC_REGS_SIZE);
423         g_reg_misc_base_va = HI_NULL;
424     }
425 
426     if (g_reg_otp_base_va != HI_NULL) {
427         osal_iounmap(g_reg_otp_base_va, (hi_u32)OTP_REGS_SIZE);
428         g_reg_otp_base_va = HI_NULL;
429     }
430 
431     osal_spin_lock_destroy(&g_crg_spin_lock);
432 
433     return;
434 }
435