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