1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2015 Atmel Corporation 4 * Wenyou Yang <wenyou.yang@atmel.com> 5 */ 6 7 #include <common.h> 8 #include <asm/io.h> 9 #include <asm/arch/hardware.h> 10 #include <asm/arch/at91_pmc.h> 11 12 #define EN_UPLL_TIMEOUT 500 13 14 void at91_periph_clk_enable(int id) 15 { 16 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 17 18 #ifdef CPU_HAS_PCR 19 u32 regval; 20 u32 div_value; 21 22 if (id > AT91_PMC_PCR_PID_MASK) 23 return; 24 25 writel(id, &pmc->pcr); 26 27 div_value = readl(&pmc->pcr) & AT91_PMC_PCR_DIV; 28 29 regval = AT91_PMC_PCR_EN | AT91_PMC_PCR_CMD_WRITE | id | div_value; 30 31 writel(regval, &pmc->pcr); 32 #else 33 writel(0x01 << id, &pmc->pcer); 34 #endif 35 } 36 37 void at91_periph_clk_disable(int id) 38 { 39 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 40 41 #ifdef CPU_HAS_PCR 42 u32 regval; 43 44 if (id > AT91_PMC_PCR_PID_MASK) 45 return; 46 47 regval = AT91_PMC_PCR_CMD_WRITE | id; 48 49 writel(regval, &pmc->pcr); 50 #else 51 writel(0x01 << id, &pmc->pcdr); 52 #endif 53 } 54 55 void at91_system_clk_enable(int sys_clk) 56 { 57 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 58 59 writel(sys_clk, &pmc->scer); 60 } 61 62 void at91_system_clk_disable(int sys_clk) 63 { 64 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 65 66 writel(sys_clk, &pmc->scdr); 67 } 68 69 int at91_upll_clk_enable(void) 70 { 71 struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; 72 ulong start_time, tmp_time; 73 74 if ((readl(&pmc->uckr) & AT91_PMC_UPLLEN) == AT91_PMC_UPLLEN) 75 return 0; 76 77 start_time = get_timer(0); 78 writel(AT91_PMC_UPLLEN | AT91_PMC_BIASEN, &pmc->uckr); 79 while ((readl(&pmc->sr) & AT91_PMC_LOCKU) != AT91_PMC_LOCKU) { 80 tmp_time = get_timer(0); 81 if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) { 82 printf("ERROR: failed to enable UPLL\n"); 83 return -1; 84 } 85 } 86 87 return 0; 88 } 89 90 int at91_upll_clk_disable(void) 91 { 92 struct at91_pmc *pmc = (at91_pmc_t *)ATMEL_BASE_PMC; 93 ulong start_time, tmp_time; 94 95 start_time = get_timer(0); 96 writel(readl(&pmc->uckr) & ~AT91_PMC_UPLLEN, &pmc->uckr); 97 while ((readl(&pmc->sr) & AT91_PMC_LOCKU) == AT91_PMC_LOCKU) { 98 tmp_time = get_timer(0); 99 if ((tmp_time - start_time) > EN_UPLL_TIMEOUT) { 100 printf("ERROR: failed to stop UPLL\n"); 101 return -1; 102 } 103 } 104 105 return 0; 106 } 107 108 void at91_usb_clk_init(u32 value) 109 { 110 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 111 112 writel(value, &pmc->usb); 113 } 114 115 void at91_pllicpr_init(u32 icpr) 116 { 117 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 118 119 writel(icpr, &pmc->pllicpr); 120 } 121