1/*- 2 * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights 3 * reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * NETLOGIC_BSD */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD$"); 32#include <sys/param.h> 33#include <sys/types.h> 34#include <sys/systm.h> 35 36#include <mips/nlm/hal/mips-extns.h> 37#include <mips/nlm/hal/haldefs.h> 38#include <mips/nlm/hal/iomap.h> 39#include <mips/nlm/hal/sys.h> 40#include <mips/nlm/xlp.h> 41 42uint32_t 43xlp_get_cpu_frequency(int node, int core) 44{ 45 uint64_t sysbase = nlm_get_sys_regbase(node); 46 unsigned int pll_divf, pll_divr, dfs_div, ext_div; 47 unsigned int rstval, dfsval; 48 49 rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); 50 dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE); 51 pll_divf = ((rstval >> 10) & 0x7f) + 1; 52 pll_divr = ((rstval >> 8) & 0x3) + 1; 53 if (!nlm_is_xlp8xx_ax()) 54 ext_div = ((rstval >> 30) & 0x3) + 1; 55 else 56 ext_div = 1; 57 dfs_div = ((dfsval >> (core << 2)) & 0xf) + 1; 58 59 return ((800000000ULL * pll_divf)/(3 * pll_divr * ext_div * dfs_div)); 60} 61 62static u_int 63nlm_get_device_frequency(uint64_t sysbase, int devtype) 64{ 65 uint32_t pllctrl, dfsdiv, spf, spr, div_val; 66 int extra_div; 67 68 pllctrl = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL); 69 if (devtype <= 7) 70 div_val = nlm_read_sys_reg(sysbase, SYS_DFS_DIV_VALUE0); 71 else { 72 devtype -= 8; 73 div_val = nlm_read_sys_reg(sysbase, SYS_DFS_DIV_VALUE1); 74 } 75 dfsdiv = ((div_val >> (devtype << 2)) & 0xf) + 1; 76 spf = (pllctrl >> 3 & 0x7f) + 1; 77 spr = (pllctrl >> 1 & 0x03) + 1; 78 if (devtype == DFS_DEVICE_NAE && !nlm_is_xlp8xx_ax()) 79 extra_div = 2; 80 else 81 extra_div = 1; 82 83 return ((400 * spf) / (3 * extra_div * spr * dfsdiv)); 84} 85 86int 87nlm_set_device_frequency(int node, int devtype, int frequency) 88{ 89 uint64_t sysbase; 90 u_int cur_freq; 91 int dec_div; 92 93 sysbase = nlm_get_sys_regbase(node); 94 cur_freq = nlm_get_device_frequency(sysbase, devtype); 95 if (cur_freq < (frequency - 5)) 96 dec_div = 1; 97 else 98 dec_div = 0; 99 100 for(;;) { 101 if ((cur_freq >= (frequency - 5)) && (cur_freq <= frequency)) 102 break; 103 if (dec_div) 104 nlm_write_sys_reg(sysbase, SYS_DFS_DIV_DEC_CTRL, 105 (1 << devtype)); 106 else 107 nlm_write_sys_reg(sysbase, SYS_DFS_DIV_INC_CTRL, 108 (1 << devtype)); 109 cur_freq = nlm_get_device_frequency(sysbase, devtype); 110 } 111 return (nlm_get_device_frequency(sysbase, devtype)); 112} 113