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