xref: /rk3399_rockchip-uboot/arch/arm/mach-at91/clock.c (revision 20680b560a17fb29c862de77930cfbf76b24f83c)
141bf25c2SWenyou Yang /*
241bf25c2SWenyou Yang  * Copyright (C) 2015 Atmel Corporation
341bf25c2SWenyou Yang  *		      Wenyou Yang <wenyou.yang@atmel.com>
441bf25c2SWenyou Yang  *
541bf25c2SWenyou Yang  * SPDX-License-Identifier:	GPL-2.0+
641bf25c2SWenyou Yang  */
741bf25c2SWenyou Yang 
841bf25c2SWenyou Yang #include <common.h>
941bf25c2SWenyou Yang #include <asm/io.h>
1041bf25c2SWenyou Yang #include <asm/arch/hardware.h>
1141bf25c2SWenyou Yang #include <asm/arch/at91_pmc.h>
1241bf25c2SWenyou Yang 
131e70b373SWenyou Yang #define EN_UPLL_TIMEOUT		500
141e70b373SWenyou Yang 
at91_periph_clk_enable(int id)1541bf25c2SWenyou Yang void at91_periph_clk_enable(int id)
1641bf25c2SWenyou Yang {
1741bf25c2SWenyou Yang 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
1841bf25c2SWenyou Yang 
1941bf25c2SWenyou Yang #ifdef CPU_HAS_PCR
2041bf25c2SWenyou Yang 	u32 regval;
2141bf25c2SWenyou Yang 	u32 div_value;
2241bf25c2SWenyou Yang 
2341bf25c2SWenyou Yang 	if (id > AT91_PMC_PCR_PID_MASK)
2441bf25c2SWenyou Yang 		return;
2541bf25c2SWenyou Yang 
2641bf25c2SWenyou Yang 	writel(id, &pmc->pcr);
2741bf25c2SWenyou Yang 
2841bf25c2SWenyou Yang 	div_value = readl(&pmc->pcr) & AT91_PMC_PCR_DIV;
2941bf25c2SWenyou Yang 
3041bf25c2SWenyou Yang 	regval = AT91_PMC_PCR_EN | AT91_PMC_PCR_CMD_WRITE | id | div_value;
3141bf25c2SWenyou Yang 
3241bf25c2SWenyou Yang 	writel(regval, &pmc->pcr);
3341bf25c2SWenyou Yang #else
3441bf25c2SWenyou Yang 	writel(0x01 << id, &pmc->pcer);
3541bf25c2SWenyou Yang #endif
3641bf25c2SWenyou Yang }
3741bf25c2SWenyou Yang 
at91_periph_clk_disable(int id)3841bf25c2SWenyou Yang void at91_periph_clk_disable(int id)
3941bf25c2SWenyou Yang {
4041bf25c2SWenyou Yang 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
4141bf25c2SWenyou Yang 
4241bf25c2SWenyou Yang #ifdef CPU_HAS_PCR
4341bf25c2SWenyou Yang 	u32 regval;
4441bf25c2SWenyou Yang 
4541bf25c2SWenyou Yang 	if (id > AT91_PMC_PCR_PID_MASK)
4641bf25c2SWenyou Yang 		return;
4741bf25c2SWenyou Yang 
4841bf25c2SWenyou Yang 	regval = AT91_PMC_PCR_CMD_WRITE | id;
4941bf25c2SWenyou Yang 
5041bf25c2SWenyou Yang 	writel(regval, &pmc->pcr);
5141bf25c2SWenyou Yang #else
5241bf25c2SWenyou Yang 	writel(0x01 << id, &pmc->pcdr);
5341bf25c2SWenyou Yang #endif
5441bf25c2SWenyou Yang }
5541bf25c2SWenyou Yang 
at91_system_clk_enable(int sys_clk)5641bf25c2SWenyou Yang void at91_system_clk_enable(int sys_clk)
5741bf25c2SWenyou Yang {
5841bf25c2SWenyou Yang 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
5941bf25c2SWenyou Yang 
6041bf25c2SWenyou Yang 	writel(sys_clk, &pmc->scer);
6141bf25c2SWenyou Yang }
6241bf25c2SWenyou Yang 
at91_system_clk_disable(int sys_clk)6341bf25c2SWenyou Yang void at91_system_clk_disable(int sys_clk)
6441bf25c2SWenyou Yang {
6541bf25c2SWenyou Yang 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
6641bf25c2SWenyou Yang 
6741bf25c2SWenyou Yang 	writel(sys_clk, &pmc->scdr);
6841bf25c2SWenyou Yang }
691e70b373SWenyou Yang 
at91_upll_clk_enable(void)701e70b373SWenyou Yang int at91_upll_clk_enable(void)
711e70b373SWenyou Yang {
721e70b373SWenyou Yang 	struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
731e70b373SWenyou Yang 	ulong start_time, tmp_time;
741e70b373SWenyou Yang 
751e70b373SWenyou Yang 	if ((readl(&pmc->uckr) & AT91_PMC_UPLLEN) == AT91_PMC_UPLLEN)
761e70b373SWenyou Yang 		return 0;
771e70b373SWenyou Yang 
781e70b373SWenyou Yang 	start_time = get_timer(0);
791e70b373SWenyou Yang 	writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr);
801e70b373SWenyou Yang 	while ((readl(&pmc->sr) & AT91_PMC_LOCKU) != AT91_PMC_LOCKU) {
811e70b373SWenyou Yang 		tmp_time = get_timer(0);
821e70b373SWenyou Yang 		if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) {
831e70b373SWenyou Yang 			printf("ERROR: failed to enable UPLL\n");
841e70b373SWenyou Yang 			return -1;
851e70b373SWenyou Yang 		}
861e70b373SWenyou Yang 	}
871e70b373SWenyou Yang 
881e70b373SWenyou Yang 	return 0;
891e70b373SWenyou Yang }
901e70b373SWenyou Yang 
at91_upll_clk_disable(void)911e70b373SWenyou Yang int at91_upll_clk_disable(void)
921e70b373SWenyou Yang {
931e70b373SWenyou Yang 	struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC;
941e70b373SWenyou Yang 	ulong start_time, tmp_time;
951e70b373SWenyou Yang 
961e70b373SWenyou Yang 	start_time = get_timer(0);
971e70b373SWenyou Yang 	writel(readl(&pmc->uckr) & ~AT91_PMC_UPLLEN, &pmc->uckr);
981e70b373SWenyou Yang 	while ((readl(&pmc->sr) & AT91_PMC_LOCKU) == AT91_PMC_LOCKU) {
991e70b373SWenyou Yang 		tmp_time = get_timer(0);
1001e70b373SWenyou Yang 		if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) {
1011e70b373SWenyou Yang 			printf("ERROR: failed to stop UPLL\n");
1021e70b373SWenyou Yang 			return -1;
1031e70b373SWenyou Yang 		}
1041e70b373SWenyou Yang 	}
1051e70b373SWenyou Yang 
1061e70b373SWenyou Yang 	return 0;
1071e70b373SWenyou Yang }
1081e70b373SWenyou Yang 
at91_usb_clk_init(u32 value)1091e70b373SWenyou Yang void at91_usb_clk_init(u32 value)
1101e70b373SWenyou Yang {
1111e70b373SWenyou Yang 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
1121e70b373SWenyou Yang 
1131e70b373SWenyou Yang 	writel(value, &pmc->usb);
1141e70b373SWenyou Yang }
115*c0b868c0SWenyou Yang 
at91_pllicpr_init(u32 icpr)116*c0b868c0SWenyou Yang void at91_pllicpr_init(u32 icpr)
117*c0b868c0SWenyou Yang {
118*c0b868c0SWenyou Yang 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
119*c0b868c0SWenyou Yang 
120*c0b868c0SWenyou Yang 	writel(icpr, &pmc->pllicpr);
121*c0b868c0SWenyou Yang }
122