1227783Sjchandra/*- 2227783Sjchandra * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights 3227783Sjchandra * reserved. 4227783Sjchandra * 5227783Sjchandra * Redistribution and use in source and binary forms, with or without 6227783Sjchandra * modification, are permitted provided that the following conditions are 7227783Sjchandra * met: 8227783Sjchandra * 9227783Sjchandra * 1. Redistributions of source code must retain the above copyright 10227783Sjchandra * notice, this list of conditions and the following disclaimer. 11227783Sjchandra * 2. Redistributions in binary form must reproduce the above copyright 12227783Sjchandra * notice, this list of conditions and the following disclaimer in 13227783Sjchandra * the documentation and/or other materials provided with the 14227783Sjchandra * distribution. 15227783Sjchandra * 16227783Sjchandra * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND 17227783Sjchandra * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18227783Sjchandra * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19227783Sjchandra * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE 20227783Sjchandra * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21227783Sjchandra * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22227783Sjchandra * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23227783Sjchandra * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24227783Sjchandra * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25227783Sjchandra * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26227783Sjchandra * THE POSSIBILITY OF SUCH DAMAGE. 27227783Sjchandra * 28227783Sjchandra * NETLOGIC_BSD */ 29227783Sjchandra 30227783Sjchandra#include <sys/cdefs.h> 31227783Sjchandra__FBSDID("$FreeBSD$"); 32227783Sjchandra#include <sys/param.h> 33227783Sjchandra#include <sys/types.h> 34227783Sjchandra#include <sys/systm.h> 35227783Sjchandra 36227783Sjchandra#include <mips/nlm/hal/mips-extns.h> 37227783Sjchandra#include <mips/nlm/hal/haldefs.h> 38227783Sjchandra#include <mips/nlm/hal/iomap.h> 39227783Sjchandra#include <mips/nlm/hal/sys.h> 40227783Sjchandra#include <mips/nlm/xlp.h> 41227783Sjchandra 42227783Sjchandrauint32_t 43233533Sjchandraxlp_get_cpu_frequency(int node, int core) 44227783Sjchandra{ 45233533Sjchandra uint64_t sysbase = nlm_get_sys_regbase(node); 46227783Sjchandra unsigned int pll_divf, pll_divr, dfs_div, ext_div; 47233533Sjchandra unsigned int rstval, dfsval; 48227783Sjchandra 49227783Sjchandra rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); 50227783Sjchandra dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE); 51227783Sjchandra pll_divf = ((rstval >> 10) & 0x7f) + 1; 52227783Sjchandra pll_divr = ((rstval >> 8) & 0x3) + 1; 53233533Sjchandra if (!nlm_is_xlp8xx_ax()) 54233563Sjchandra ext_div = ((rstval >> 30) & 0x3) + 1; 55233533Sjchandra else 56233563Sjchandra ext_div = 1; 57233533Sjchandra dfs_div = ((dfsval >> (core << 2)) & 0xf) + 1; 58227783Sjchandra 59233533Sjchandra return ((800000000ULL * pll_divf)/(3 * pll_divr * ext_div * dfs_div)); 60227783Sjchandra} 61227783Sjchandra 62233533Sjchandrastatic u_int 63233533Sjchandranlm_get_device_frequency(uint64_t sysbase, int devtype) 64233533Sjchandra{ 65233533Sjchandra uint32_t pllctrl, dfsdiv, spf, spr, div_val; 66233533Sjchandra int extra_div; 67233533Sjchandra 68233533Sjchandra pllctrl = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL); 69233533Sjchandra if (devtype <= 7) 70233533Sjchandra div_val = nlm_read_sys_reg(sysbase, SYS_DFS_DIV_VALUE0); 71233533Sjchandra else { 72233533Sjchandra devtype -= 8; 73233533Sjchandra div_val = nlm_read_sys_reg(sysbase, SYS_DFS_DIV_VALUE1); 74233533Sjchandra } 75233533Sjchandra dfsdiv = ((div_val >> (devtype << 2)) & 0xf) + 1; 76233533Sjchandra spf = (pllctrl >> 3 & 0x7f) + 1; 77233533Sjchandra spr = (pllctrl >> 1 & 0x03) + 1; 78255368Sjchandra if (devtype == DFS_DEVICE_NAE && !nlm_is_xlp8xx_ax()) 79255368Sjchandra extra_div = 2; 80255368Sjchandra else 81255368Sjchandra extra_div = 1; 82233533Sjchandra 83233533Sjchandra return ((400 * spf) / (3 * extra_div * spr * dfsdiv)); 84233533Sjchandra} 85233533Sjchandra 86233533Sjchandraint 87233533Sjchandranlm_set_device_frequency(int node, int devtype, int frequency) 88233533Sjchandra{ 89233533Sjchandra uint64_t sysbase; 90233533Sjchandra u_int cur_freq; 91233533Sjchandra int dec_div; 92233533Sjchandra 93233533Sjchandra sysbase = nlm_get_sys_regbase(node); 94233533Sjchandra cur_freq = nlm_get_device_frequency(sysbase, devtype); 95233533Sjchandra if (cur_freq < (frequency - 5)) 96233533Sjchandra dec_div = 1; 97233533Sjchandra else 98233533Sjchandra dec_div = 0; 99233533Sjchandra 100233533Sjchandra for(;;) { 101233533Sjchandra if ((cur_freq >= (frequency - 5)) && (cur_freq <= frequency)) 102233533Sjchandra break; 103233533Sjchandra if (dec_div) 104233533Sjchandra nlm_write_sys_reg(sysbase, SYS_DFS_DIV_DEC_CTRL, 105233533Sjchandra (1 << devtype)); 106233533Sjchandra else 107233533Sjchandra nlm_write_sys_reg(sysbase, SYS_DFS_DIV_INC_CTRL, 108233533Sjchandra (1 << devtype)); 109233533Sjchandra cur_freq = nlm_get_device_frequency(sysbase, devtype); 110233533Sjchandra } 111233533Sjchandra return (nlm_get_device_frequency(sysbase, devtype)); 112233533Sjchandra} 113