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