| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * Copyright 2014 Broadcom Corporation.
- */
- #include <common.h>
- #include <asm/io.h>
- #include <asm/iproc-common/armpll.h>
- #include <asm/iproc-common/sysmap.h>
- #define NELEMS(x) (sizeof(x) / sizeof(x[0]))
- struct armpll_parameters {
- unsigned int mode;
- unsigned int ndiv_int;
- unsigned int ndiv_frac;
- unsigned int pdiv;
- unsigned int freqid;
- };
- struct armpll_parameters armpll_clk_tab[] = {
- { 25, 64, 1, 1, 0},
- { 100, 64, 1, 1, 2},
- { 400, 64, 1, 1, 6},
- { 448, 71, 713050, 1, 6},
- { 500, 80, 1, 1, 6},
- { 560, 89, 629145, 1, 6},
- { 600, 96, 1, 1, 6},
- { 800, 64, 1, 1, 7},
- { 896, 71, 713050, 1, 7},
- { 1000, 80, 1, 1, 7},
- { 1100, 88, 1, 1, 7},
- { 1120, 89, 629145, 1, 7},
- { 1200, 96, 1, 1, 7},
- };
- uint32_t armpll_config(uint32_t clkmhz)
- {
- uint32_t freqid;
- uint32_t ndiv_frac;
- uint32_t pll;
- uint32_t status = 1;
- uint32_t timeout_countdown;
- int i;
- for (i = 0; i < NELEMS(armpll_clk_tab); i++) {
- if (armpll_clk_tab[i].mode == clkmhz) {
- status = 0;
- break;
- }
- }
- if (status) {
- printf("Error: Clock configuration not supported\n");
- goto armpll_config_done;
- }
- /* Enable write access */
- writel(IPROC_REG_WRITE_ACCESS, IHOST_PROC_CLK_WR_ACCESS);
- if (clkmhz == 25)
- freqid = 0;
- else
- freqid = 2;
- /* Bypass ARM clock and run on sysclk */
- writel(1 << IHOST_PROC_CLK_POLICY_FREQ__PRIV_ACCESS_MODE |
- freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY3_FREQ_R |
- freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY2_FREQ_R |
- freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY1_FREQ_R |
- freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY0_FREQ_R,
- IHOST_PROC_CLK_POLICY_FREQ);
- writel(1 << IHOST_PROC_CLK_POLICY_CTL__GO |
- 1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC,
- IHOST_PROC_CLK_POLICY_CTL);
- /* Poll CCU until operation complete */
- timeout_countdown = 0x100000;
- while (readl(IHOST_PROC_CLK_POLICY_CTL) &
- (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) {
- timeout_countdown--;
- if (timeout_countdown == 0) {
- printf("CCU polling timedout\n");
- status = 1;
- goto armpll_config_done;
- }
- }
- if (clkmhz == 25 || clkmhz == 100) {
- status = 0;
- goto armpll_config_done;
- }
- /* Now it is safe to program the PLL */
- pll = readl(IHOST_PROC_CLK_PLLARMB);
- pll &= ~((1 << IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_WIDTH) - 1);
- ndiv_frac =
- ((1 << IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_WIDTH) - 1) &
- (armpll_clk_tab[i].ndiv_frac <<
- IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_R);
- pll |= ndiv_frac;
- writel(pll, IHOST_PROC_CLK_PLLARMB);
- writel(1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK |
- armpll_clk_tab[i].ndiv_int <<
- IHOST_PROC_CLK_PLLARMA__PLLARM_NDIV_INT_R |
- armpll_clk_tab[i].pdiv <<
- IHOST_PROC_CLK_PLLARMA__PLLARM_PDIV_R |
- 1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_RESETB,
- IHOST_PROC_CLK_PLLARMA);
- /* Poll ARM PLL Lock until operation complete */
- timeout_countdown = 0x100000;
- while (readl(IHOST_PROC_CLK_PLLARMA) &
- (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK)) {
- timeout_countdown--;
- if (timeout_countdown == 0) {
- printf("ARM PLL lock failed\n");
- status = 1;
- goto armpll_config_done;
- }
- }
- pll = readl(IHOST_PROC_CLK_PLLARMA);
- pll |= (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_POST_RESETB);
- writel(pll, IHOST_PROC_CLK_PLLARMA);
- /* Set the policy */
- writel(1 << IHOST_PROC_CLK_POLICY_FREQ__PRIV_ACCESS_MODE |
- armpll_clk_tab[i].freqid <<
- IHOST_PROC_CLK_POLICY_FREQ__POLICY3_FREQ_R |
- armpll_clk_tab[i].freqid <<
- IHOST_PROC_CLK_POLICY_FREQ__POLICY2_FREQ_R |
- armpll_clk_tab[i].freqid <<
- IHOST_PROC_CLK_POLICY_FREQ__POLICY1_FREQ_R |
- armpll_clk_tab[i+4].freqid <<
- IHOST_PROC_CLK_POLICY_FREQ__POLICY0_FREQ_R,
- IHOST_PROC_CLK_POLICY_FREQ);
- writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_CORE0_CLKGATE);
- writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_CORE1_CLKGATE);
- writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_ARM_SWITCH_CLKGATE);
- writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_ARM_PERIPH_CLKGATE);
- writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_APB0_CLKGATE);
- writel(1 << IHOST_PROC_CLK_POLICY_CTL__GO |
- 1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC,
- IHOST_PROC_CLK_POLICY_CTL);
- /* Poll CCU until operation complete */
- timeout_countdown = 0x100000;
- while (readl(IHOST_PROC_CLK_POLICY_CTL) &
- (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) {
- timeout_countdown--;
- if (timeout_countdown == 0) {
- printf("CCU polling failed\n");
- status = 1;
- goto armpll_config_done;
- }
- }
- status = 0;
- armpll_config_done:
- /* Disable access to PLL registers */
- writel(0, IHOST_PROC_CLK_WR_ACCESS);
- return status;
- }
|