1287e3f3fSJohn Crispin /* 2287e3f3fSJohn Crispin * This program is free software; you can redistribute it and/or modify it 3287e3f3fSJohn Crispin * under the terms of the GNU General Public License version 2 as published 4287e3f3fSJohn Crispin * by the Free Software Foundation. 5287e3f3fSJohn Crispin * 697b92108SJohn Crispin * Copyright (C) 2010 John Crispin <john@phrozen.org> 7b5a03d0cSHauke Mehrtens * Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG 8287e3f3fSJohn Crispin */ 9287e3f3fSJohn Crispin 10287e3f3fSJohn Crispin #include <linux/io.h> 11287e3f3fSJohn Crispin #include <linux/export.h> 12287e3f3fSJohn Crispin #include <linux/clk.h> 13287e3f3fSJohn Crispin 14287e3f3fSJohn Crispin #include <asm/time.h> 15287e3f3fSJohn Crispin #include <asm/irq.h> 16287e3f3fSJohn Crispin #include <asm/div64.h> 17287e3f3fSJohn Crispin 18287e3f3fSJohn Crispin #include <lantiq_soc.h> 19287e3f3fSJohn Crispin 20287e3f3fSJohn Crispin #include "../clk.h" 21287e3f3fSJohn Crispin 22287e3f3fSJohn Crispin static unsigned int ram_clocks[] = { 23287e3f3fSJohn Crispin CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M }; 24287e3f3fSJohn Crispin #define DDR_HZ ram_clocks[ltq_cgu_r32(CGU_SYS) & 0x3] 25287e3f3fSJohn Crispin 26287e3f3fSJohn Crispin /* legacy xway clock */ 27287e3f3fSJohn Crispin #define CGU_SYS 0x10 28287e3f3fSJohn Crispin 29b5a03d0cSHauke Mehrtens /* vr9, ar10/grx390 clock */ 30b5a03d0cSHauke Mehrtens #define CGU_SYS_XRX 0x0c 3161e371d8SHauke Mehrtens #define CGU_IF_CLK_AR10 0x24 32287e3f3fSJohn Crispin 33287e3f3fSJohn Crispin unsigned long ltq_danube_fpi_hz(void) 34287e3f3fSJohn Crispin { 35287e3f3fSJohn Crispin unsigned long ddr_clock = DDR_HZ; 36287e3f3fSJohn Crispin 37287e3f3fSJohn Crispin if (ltq_cgu_r32(CGU_SYS) & 0x40) 38287e3f3fSJohn Crispin return ddr_clock >> 1; 39287e3f3fSJohn Crispin return ddr_clock; 40287e3f3fSJohn Crispin } 41287e3f3fSJohn Crispin 42287e3f3fSJohn Crispin unsigned long ltq_danube_cpu_hz(void) 43287e3f3fSJohn Crispin { 44287e3f3fSJohn Crispin switch (ltq_cgu_r32(CGU_SYS) & 0xc) { 45287e3f3fSJohn Crispin case 0: 46287e3f3fSJohn Crispin return CLOCK_333M; 47287e3f3fSJohn Crispin case 4: 48287e3f3fSJohn Crispin return DDR_HZ; 49287e3f3fSJohn Crispin case 8: 50287e3f3fSJohn Crispin return DDR_HZ << 1; 51287e3f3fSJohn Crispin default: 52287e3f3fSJohn Crispin return DDR_HZ >> 1; 53287e3f3fSJohn Crispin } 54287e3f3fSJohn Crispin } 55287e3f3fSJohn Crispin 56740c606eSJohn Crispin unsigned long ltq_danube_pp32_hz(void) 57740c606eSJohn Crispin { 58740c606eSJohn Crispin unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 7) & 3; 59740c606eSJohn Crispin unsigned long clk; 60740c606eSJohn Crispin 61740c606eSJohn Crispin switch (clksys) { 62740c606eSJohn Crispin case 1: 63740c606eSJohn Crispin clk = CLOCK_240M; 64740c606eSJohn Crispin break; 65740c606eSJohn Crispin case 2: 66740c606eSJohn Crispin clk = CLOCK_222M; 67740c606eSJohn Crispin break; 68740c606eSJohn Crispin case 3: 69740c606eSJohn Crispin clk = CLOCK_133M; 70740c606eSJohn Crispin break; 71740c606eSJohn Crispin default: 72740c606eSJohn Crispin clk = CLOCK_266M; 73740c606eSJohn Crispin break; 74740c606eSJohn Crispin } 75740c606eSJohn Crispin 76740c606eSJohn Crispin return clk; 77740c606eSJohn Crispin } 78740c606eSJohn Crispin 79287e3f3fSJohn Crispin unsigned long ltq_ar9_sys_hz(void) 80287e3f3fSJohn Crispin { 81287e3f3fSJohn Crispin if (((ltq_cgu_r32(CGU_SYS) >> 3) & 0x3) == 0x2) 82287e3f3fSJohn Crispin return CLOCK_393M; 83287e3f3fSJohn Crispin return CLOCK_333M; 84287e3f3fSJohn Crispin } 85287e3f3fSJohn Crispin 86287e3f3fSJohn Crispin unsigned long ltq_ar9_fpi_hz(void) 87287e3f3fSJohn Crispin { 88287e3f3fSJohn Crispin unsigned long sys = ltq_ar9_sys_hz(); 89287e3f3fSJohn Crispin 90287e3f3fSJohn Crispin if (ltq_cgu_r32(CGU_SYS) & BIT(0)) 911601078dSJohn Crispin return sys / 3; 921601078dSJohn Crispin else 931601078dSJohn Crispin return sys / 2; 94287e3f3fSJohn Crispin } 95287e3f3fSJohn Crispin 96287e3f3fSJohn Crispin unsigned long ltq_ar9_cpu_hz(void) 97287e3f3fSJohn Crispin { 98287e3f3fSJohn Crispin if (ltq_cgu_r32(CGU_SYS) & BIT(2)) 99287e3f3fSJohn Crispin return ltq_ar9_fpi_hz(); 100287e3f3fSJohn Crispin else 101287e3f3fSJohn Crispin return ltq_ar9_sys_hz(); 102287e3f3fSJohn Crispin } 103287e3f3fSJohn Crispin 104287e3f3fSJohn Crispin unsigned long ltq_vr9_cpu_hz(void) 105287e3f3fSJohn Crispin { 106287e3f3fSJohn Crispin unsigned int cpu_sel; 107287e3f3fSJohn Crispin unsigned long clk; 108287e3f3fSJohn Crispin 109b5a03d0cSHauke Mehrtens cpu_sel = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0xf; 110287e3f3fSJohn Crispin 111287e3f3fSJohn Crispin switch (cpu_sel) { 112287e3f3fSJohn Crispin case 0: 113287e3f3fSJohn Crispin clk = CLOCK_600M; 114287e3f3fSJohn Crispin break; 115287e3f3fSJohn Crispin case 1: 116287e3f3fSJohn Crispin clk = CLOCK_500M; 117287e3f3fSJohn Crispin break; 118287e3f3fSJohn Crispin case 2: 119287e3f3fSJohn Crispin clk = CLOCK_393M; 120287e3f3fSJohn Crispin break; 121287e3f3fSJohn Crispin case 3: 122287e3f3fSJohn Crispin clk = CLOCK_333M; 123287e3f3fSJohn Crispin break; 124287e3f3fSJohn Crispin case 5: 125287e3f3fSJohn Crispin case 6: 126287e3f3fSJohn Crispin clk = CLOCK_196_608M; 127287e3f3fSJohn Crispin break; 128287e3f3fSJohn Crispin case 7: 129287e3f3fSJohn Crispin clk = CLOCK_167M; 130287e3f3fSJohn Crispin break; 131287e3f3fSJohn Crispin case 4: 132287e3f3fSJohn Crispin case 8: 133287e3f3fSJohn Crispin case 9: 134287e3f3fSJohn Crispin clk = CLOCK_125M; 135287e3f3fSJohn Crispin break; 136287e3f3fSJohn Crispin default: 137287e3f3fSJohn Crispin clk = 0; 138287e3f3fSJohn Crispin break; 139287e3f3fSJohn Crispin } 140287e3f3fSJohn Crispin 141287e3f3fSJohn Crispin return clk; 142287e3f3fSJohn Crispin } 143287e3f3fSJohn Crispin 144287e3f3fSJohn Crispin unsigned long ltq_vr9_fpi_hz(void) 145287e3f3fSJohn Crispin { 146287e3f3fSJohn Crispin unsigned int ocp_sel, cpu_clk; 147287e3f3fSJohn Crispin unsigned long clk; 148287e3f3fSJohn Crispin 149287e3f3fSJohn Crispin cpu_clk = ltq_vr9_cpu_hz(); 150b5a03d0cSHauke Mehrtens ocp_sel = ltq_cgu_r32(CGU_SYS_XRX) & 0x3; 151287e3f3fSJohn Crispin 152287e3f3fSJohn Crispin switch (ocp_sel) { 153287e3f3fSJohn Crispin case 0: 154287e3f3fSJohn Crispin /* OCP ratio 1 */ 155287e3f3fSJohn Crispin clk = cpu_clk; 156287e3f3fSJohn Crispin break; 157287e3f3fSJohn Crispin case 2: 158287e3f3fSJohn Crispin /* OCP ratio 2 */ 159287e3f3fSJohn Crispin clk = cpu_clk / 2; 160287e3f3fSJohn Crispin break; 161287e3f3fSJohn Crispin case 3: 162287e3f3fSJohn Crispin /* OCP ratio 2.5 */ 163287e3f3fSJohn Crispin clk = (cpu_clk * 2) / 5; 164287e3f3fSJohn Crispin break; 165287e3f3fSJohn Crispin case 4: 166287e3f3fSJohn Crispin /* OCP ratio 3 */ 167287e3f3fSJohn Crispin clk = cpu_clk / 3; 168287e3f3fSJohn Crispin break; 169287e3f3fSJohn Crispin default: 170287e3f3fSJohn Crispin clk = 0; 171287e3f3fSJohn Crispin break; 172287e3f3fSJohn Crispin } 173287e3f3fSJohn Crispin 174287e3f3fSJohn Crispin return clk; 175287e3f3fSJohn Crispin } 176740c606eSJohn Crispin 177740c606eSJohn Crispin unsigned long ltq_vr9_pp32_hz(void) 178740c606eSJohn Crispin { 17918a3af60SHauke Mehrtens unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7; 180740c606eSJohn Crispin unsigned long clk; 181740c606eSJohn Crispin 182740c606eSJohn Crispin switch (clksys) { 18318a3af60SHauke Mehrtens case 0: 18418a3af60SHauke Mehrtens clk = CLOCK_500M; 18518a3af60SHauke Mehrtens break; 186740c606eSJohn Crispin case 1: 18718a3af60SHauke Mehrtens clk = CLOCK_432M; 188740c606eSJohn Crispin break; 189740c606eSJohn Crispin case 2: 19018a3af60SHauke Mehrtens clk = CLOCK_288M; 191740c606eSJohn Crispin break; 192740c606eSJohn Crispin default: 193740c606eSJohn Crispin clk = CLOCK_500M; 194740c606eSJohn Crispin break; 195740c606eSJohn Crispin } 196740c606eSJohn Crispin 197740c606eSJohn Crispin return clk; 198740c606eSJohn Crispin } 19961e371d8SHauke Mehrtens 20061e371d8SHauke Mehrtens unsigned long ltq_ar10_cpu_hz(void) 20161e371d8SHauke Mehrtens { 20261e371d8SHauke Mehrtens unsigned int clksys; 20361e371d8SHauke Mehrtens int cpu_fs = (ltq_cgu_r32(CGU_SYS_XRX) >> 8) & 0x1; 20461e371d8SHauke Mehrtens int freq_div = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7; 20561e371d8SHauke Mehrtens 20661e371d8SHauke Mehrtens switch (cpu_fs) { 20761e371d8SHauke Mehrtens case 0: 20861e371d8SHauke Mehrtens clksys = CLOCK_500M; 20961e371d8SHauke Mehrtens break; 21061e371d8SHauke Mehrtens case 1: 21161e371d8SHauke Mehrtens clksys = CLOCK_600M; 21261e371d8SHauke Mehrtens break; 21361e371d8SHauke Mehrtens default: 21461e371d8SHauke Mehrtens clksys = CLOCK_500M; 21561e371d8SHauke Mehrtens break; 21661e371d8SHauke Mehrtens } 21761e371d8SHauke Mehrtens 21861e371d8SHauke Mehrtens switch (freq_div) { 21961e371d8SHauke Mehrtens case 0: 22061e371d8SHauke Mehrtens return clksys; 22161e371d8SHauke Mehrtens case 1: 22261e371d8SHauke Mehrtens return clksys >> 1; 22361e371d8SHauke Mehrtens case 2: 22461e371d8SHauke Mehrtens return clksys >> 2; 22561e371d8SHauke Mehrtens default: 22661e371d8SHauke Mehrtens return clksys; 22761e371d8SHauke Mehrtens } 22861e371d8SHauke Mehrtens } 22961e371d8SHauke Mehrtens 23061e371d8SHauke Mehrtens unsigned long ltq_ar10_fpi_hz(void) 23161e371d8SHauke Mehrtens { 23261e371d8SHauke Mehrtens int freq_fpi = (ltq_cgu_r32(CGU_IF_CLK_AR10) >> 25) & 0xf; 23361e371d8SHauke Mehrtens 23461e371d8SHauke Mehrtens switch (freq_fpi) { 23561e371d8SHauke Mehrtens case 1: 23661e371d8SHauke Mehrtens return CLOCK_300M; 23761e371d8SHauke Mehrtens case 5: 23861e371d8SHauke Mehrtens return CLOCK_250M; 23961e371d8SHauke Mehrtens case 2: 24061e371d8SHauke Mehrtens return CLOCK_150M; 24161e371d8SHauke Mehrtens case 6: 24261e371d8SHauke Mehrtens return CLOCK_125M; 24361e371d8SHauke Mehrtens 24461e371d8SHauke Mehrtens default: 24561e371d8SHauke Mehrtens return CLOCK_125M; 24661e371d8SHauke Mehrtens } 24761e371d8SHauke Mehrtens } 24861e371d8SHauke Mehrtens 24961e371d8SHauke Mehrtens unsigned long ltq_ar10_pp32_hz(void) 25061e371d8SHauke Mehrtens { 25161e371d8SHauke Mehrtens unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7; 25261e371d8SHauke Mehrtens unsigned long clk; 25361e371d8SHauke Mehrtens 25461e371d8SHauke Mehrtens switch (clksys) { 25561e371d8SHauke Mehrtens case 1: 25661e371d8SHauke Mehrtens clk = CLOCK_250M; 25761e371d8SHauke Mehrtens break; 25861e371d8SHauke Mehrtens case 4: 25961e371d8SHauke Mehrtens clk = CLOCK_400M; 26061e371d8SHauke Mehrtens break; 26161e371d8SHauke Mehrtens default: 26261e371d8SHauke Mehrtens clk = CLOCK_250M; 26361e371d8SHauke Mehrtens break; 26461e371d8SHauke Mehrtens } 26561e371d8SHauke Mehrtens 26661e371d8SHauke Mehrtens return clk; 26761e371d8SHauke Mehrtens } 26861e371d8SHauke Mehrtens 26961e371d8SHauke Mehrtens unsigned long ltq_grx390_cpu_hz(void) 27061e371d8SHauke Mehrtens { 27161e371d8SHauke Mehrtens unsigned int clksys; 27261e371d8SHauke Mehrtens int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3); 27361e371d8SHauke Mehrtens int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7); 27461e371d8SHauke Mehrtens 27561e371d8SHauke Mehrtens switch (cpu_fs) { 27661e371d8SHauke Mehrtens case 0: 27761e371d8SHauke Mehrtens clksys = CLOCK_600M; 27861e371d8SHauke Mehrtens break; 27961e371d8SHauke Mehrtens case 1: 28061e371d8SHauke Mehrtens clksys = CLOCK_666M; 28161e371d8SHauke Mehrtens break; 28261e371d8SHauke Mehrtens case 2: 28361e371d8SHauke Mehrtens clksys = CLOCK_720M; 28461e371d8SHauke Mehrtens break; 28561e371d8SHauke Mehrtens default: 28661e371d8SHauke Mehrtens clksys = CLOCK_600M; 28761e371d8SHauke Mehrtens break; 28861e371d8SHauke Mehrtens } 28961e371d8SHauke Mehrtens 29061e371d8SHauke Mehrtens switch (freq_div) { 29161e371d8SHauke Mehrtens case 0: 29261e371d8SHauke Mehrtens return clksys; 29361e371d8SHauke Mehrtens case 1: 29461e371d8SHauke Mehrtens return clksys >> 1; 29561e371d8SHauke Mehrtens case 2: 29661e371d8SHauke Mehrtens return clksys >> 2; 29761e371d8SHauke Mehrtens default: 29861e371d8SHauke Mehrtens return clksys; 29961e371d8SHauke Mehrtens } 30061e371d8SHauke Mehrtens } 30161e371d8SHauke Mehrtens 30261e371d8SHauke Mehrtens unsigned long ltq_grx390_fpi_hz(void) 30361e371d8SHauke Mehrtens { 30461e371d8SHauke Mehrtens /* fpi clock is derived from ddr_clk */ 30561e371d8SHauke Mehrtens unsigned int clksys; 30661e371d8SHauke Mehrtens int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3); 30761e371d8SHauke Mehrtens int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX)) & 0x7); 30861e371d8SHauke Mehrtens switch (cpu_fs) { 30961e371d8SHauke Mehrtens case 0: 31061e371d8SHauke Mehrtens clksys = CLOCK_600M; 31161e371d8SHauke Mehrtens break; 31261e371d8SHauke Mehrtens case 1: 31361e371d8SHauke Mehrtens clksys = CLOCK_666M; 31461e371d8SHauke Mehrtens break; 31561e371d8SHauke Mehrtens case 2: 31661e371d8SHauke Mehrtens clksys = CLOCK_720M; 31761e371d8SHauke Mehrtens break; 31861e371d8SHauke Mehrtens default: 31961e371d8SHauke Mehrtens clksys = CLOCK_600M; 32061e371d8SHauke Mehrtens break; 32161e371d8SHauke Mehrtens } 32261e371d8SHauke Mehrtens 32361e371d8SHauke Mehrtens switch (freq_div) { 32461e371d8SHauke Mehrtens case 1: 32561e371d8SHauke Mehrtens return clksys >> 1; 32661e371d8SHauke Mehrtens case 2: 32761e371d8SHauke Mehrtens return clksys >> 2; 32861e371d8SHauke Mehrtens default: 32961e371d8SHauke Mehrtens return clksys >> 1; 33061e371d8SHauke Mehrtens } 33161e371d8SHauke Mehrtens } 33261e371d8SHauke Mehrtens 33361e371d8SHauke Mehrtens unsigned long ltq_grx390_pp32_hz(void) 33461e371d8SHauke Mehrtens { 33561e371d8SHauke Mehrtens unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7; 33661e371d8SHauke Mehrtens unsigned long clk; 33761e371d8SHauke Mehrtens 33861e371d8SHauke Mehrtens switch (clksys) { 33961e371d8SHauke Mehrtens case 1: 34061e371d8SHauke Mehrtens clk = CLOCK_250M; 34161e371d8SHauke Mehrtens break; 34261e371d8SHauke Mehrtens case 2: 34361e371d8SHauke Mehrtens clk = CLOCK_432M; 34461e371d8SHauke Mehrtens break; 34561e371d8SHauke Mehrtens case 4: 34661e371d8SHauke Mehrtens clk = CLOCK_400M; 34761e371d8SHauke Mehrtens break; 34861e371d8SHauke Mehrtens default: 34961e371d8SHauke Mehrtens clk = CLOCK_250M; 35061e371d8SHauke Mehrtens break; 35161e371d8SHauke Mehrtens } 35261e371d8SHauke Mehrtens return clk; 35361e371d8SHauke Mehrtens } 354