162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * PowerQUICC II support functions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Author: Scott Wood <scottwood@freescale.com> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2007 Freescale Semiconductor, Inc. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "ops.h" 1162306a36Sopenharmony_ci#include "types.h" 1262306a36Sopenharmony_ci#include "fsl-soc.h" 1362306a36Sopenharmony_ci#include "pq2.h" 1462306a36Sopenharmony_ci#include "stdio.h" 1562306a36Sopenharmony_ci#include "io.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define PQ2_SCCR (0x10c80/4) /* System Clock Configuration Register */ 1862306a36Sopenharmony_ci#define PQ2_SCMR (0x10c88/4) /* System Clock Mode Register */ 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic int pq2_corecnf_map[] = { 2162306a36Sopenharmony_ci 3, 2, 2, 2, 4, 4, 5, 9, 6, 11, 8, 10, 3, 12, 7, -1, 2262306a36Sopenharmony_ci 6, 5, 13, 2, 14, 4, 15, 9, 0, 11, 8, 10, 16, 12, 7, -1 2362306a36Sopenharmony_ci}; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* Get various clocks from crystal frequency. 2662306a36Sopenharmony_ci * Returns zero on failure and non-zero on success. 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ciint pq2_get_clocks(u32 crystal, u32 *sysfreq, u32 *corefreq, 2962306a36Sopenharmony_ci u32 *timebase, u32 *brgfreq) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci u32 *immr; 3262306a36Sopenharmony_ci u32 sccr, scmr, mainclk, busclk; 3362306a36Sopenharmony_ci int corecnf, busdf, plldf, pllmf, dfbrg; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci immr = fsl_get_immr(); 3662306a36Sopenharmony_ci if (!immr) { 3762306a36Sopenharmony_ci printf("pq2_get_clocks: Couldn't get IMMR base.\r\n"); 3862306a36Sopenharmony_ci return 0; 3962306a36Sopenharmony_ci } 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci sccr = in_be32(&immr[PQ2_SCCR]); 4262306a36Sopenharmony_ci scmr = in_be32(&immr[PQ2_SCMR]); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci dfbrg = sccr & 3; 4562306a36Sopenharmony_ci corecnf = (scmr >> 24) & 0x1f; 4662306a36Sopenharmony_ci busdf = (scmr >> 20) & 0xf; 4762306a36Sopenharmony_ci plldf = (scmr >> 12) & 1; 4862306a36Sopenharmony_ci pllmf = scmr & 0xfff; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci mainclk = crystal * (pllmf + 1) / (plldf + 1); 5162306a36Sopenharmony_ci busclk = mainclk / (busdf + 1); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci if (sysfreq) 5462306a36Sopenharmony_ci *sysfreq = mainclk / 2; 5562306a36Sopenharmony_ci if (timebase) 5662306a36Sopenharmony_ci *timebase = busclk / 4; 5762306a36Sopenharmony_ci if (brgfreq) 5862306a36Sopenharmony_ci *brgfreq = mainclk / (1 << ((dfbrg + 1) * 2)); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci if (corefreq) { 6162306a36Sopenharmony_ci int coremult = pq2_corecnf_map[corecnf]; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (coremult < 0) 6462306a36Sopenharmony_ci *corefreq = mainclk / 2; 6562306a36Sopenharmony_ci else if (coremult == 0) 6662306a36Sopenharmony_ci return 0; 6762306a36Sopenharmony_ci else 6862306a36Sopenharmony_ci *corefreq = busclk * coremult / 2; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci return 1; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* Set common device tree fields based on the given clock frequencies. */ 7562306a36Sopenharmony_civoid pq2_set_clocks(u32 sysfreq, u32 corefreq, u32 timebase, u32 brgfreq) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci void *node; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci dt_fixup_cpu_clocks(corefreq, timebase, sysfreq); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci node = finddevice("/soc/cpm"); 8262306a36Sopenharmony_ci if (node) 8362306a36Sopenharmony_ci setprop(node, "clock-frequency", &sysfreq, 4); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci node = finddevice("/soc/cpm/brg"); 8662306a36Sopenharmony_ci if (node) 8762306a36Sopenharmony_ci setprop(node, "clock-frequency", &brgfreq, 4); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciint pq2_fixup_clocks(u32 crystal) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci u32 sysfreq, corefreq, timebase, brgfreq; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci if (!pq2_get_clocks(crystal, &sysfreq, &corefreq, &timebase, &brgfreq)) 9562306a36Sopenharmony_ci return 0; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci pq2_set_clocks(sysfreq, corefreq, timebase, brgfreq); 9862306a36Sopenharmony_ci return 1; 9962306a36Sopenharmony_ci} 100