162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * MPC8xx 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 "mpc8xx.h" 1462306a36Sopenharmony_ci#include "stdio.h" 1562306a36Sopenharmony_ci#include "io.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define MPC8XX_PLPRCR (0x284/4) /* PLL and Reset Control Register */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* Return system clock from crystal frequency */ 2062306a36Sopenharmony_ciu32 mpc885_get_clock(u32 crystal) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci u32 *immr; 2362306a36Sopenharmony_ci u32 plprcr; 2462306a36Sopenharmony_ci int mfi, mfn, mfd, pdf; 2562306a36Sopenharmony_ci u32 ret; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci immr = fsl_get_immr(); 2862306a36Sopenharmony_ci if (!immr) { 2962306a36Sopenharmony_ci printf("mpc885_get_clock: Couldn't get IMMR base.\r\n"); 3062306a36Sopenharmony_ci return 0; 3162306a36Sopenharmony_ci } 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci plprcr = in_be32(&immr[MPC8XX_PLPRCR]); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci mfi = (plprcr >> 16) & 15; 3662306a36Sopenharmony_ci if (mfi < 5) { 3762306a36Sopenharmony_ci printf("Warning: PLPRCR[MFI] value of %d out-of-bounds\r\n", 3862306a36Sopenharmony_ci mfi); 3962306a36Sopenharmony_ci mfi = 5; 4062306a36Sopenharmony_ci } 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci pdf = (plprcr >> 1) & 0xf; 4362306a36Sopenharmony_ci mfd = (plprcr >> 22) & 0x1f; 4462306a36Sopenharmony_ci mfn = (plprcr >> 27) & 0x1f; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci ret = crystal * mfi; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci if (mfn != 0) 4962306a36Sopenharmony_ci ret += crystal * mfn / (mfd + 1); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci return ret / (pdf + 1); 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* Set common device tree fields based on the given clock frequencies. */ 5562306a36Sopenharmony_civoid mpc8xx_set_clocks(u32 sysclk) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci void *node; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci dt_fixup_cpu_clocks(sysclk, sysclk / 16, sysclk); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci node = finddevice("/soc/cpm"); 6262306a36Sopenharmony_ci if (node) 6362306a36Sopenharmony_ci setprop(node, "clock-frequency", &sysclk, 4); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci node = finddevice("/soc/cpm/brg"); 6662306a36Sopenharmony_ci if (node) 6762306a36Sopenharmony_ci setprop(node, "clock-frequency", &sysclk, 4); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ciint mpc885_fixup_clocks(u32 crystal) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci u32 sysclk = mpc885_get_clock(crystal); 7362306a36Sopenharmony_ci if (!sysclk) 7462306a36Sopenharmony_ci return 0; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci mpc8xx_set_clocks(sysclk); 7762306a36Sopenharmony_ci return 1; 7862306a36Sopenharmony_ci} 79