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 * 6287e3f3fSJohn Crispin * Copyright (C) 2010 John Crispin <blogic@openwrt.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)) 91287e3f3fSJohn Crispin return sys; 92287e3f3fSJohn Crispin return sys >> 1; 93287e3f3fSJohn Crispin } 94287e3f3fSJohn Crispin 95287e3f3fSJohn Crispin unsigned long ltq_ar9_cpu_hz(void) 96287e3f3fSJohn Crispin { 97287e3f3fSJohn Crispin if (ltq_cgu_r32(CGU_SYS) & BIT(2)) 98287e3f3fSJohn Crispin return ltq_ar9_fpi_hz(); 99287e3f3fSJohn Crispin else 100287e3f3fSJohn Crispin return ltq_ar9_sys_hz(); 101287e3f3fSJohn Crispin } 102287e3f3fSJohn Crispin 103287e3f3fSJohn Crispin unsigned long ltq_vr9_cpu_hz(void) 104287e3f3fSJohn Crispin { 105287e3f3fSJohn Crispin unsigned int cpu_sel; 106287e3f3fSJohn Crispin unsigned long clk; 107287e3f3fSJohn Crispin 108b5a03d0cSHauke Mehrtens cpu_sel = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0xf; 109287e3f3fSJohn Crispin 110287e3f3fSJohn Crispin switch (cpu_sel) { 111287e3f3fSJohn Crispin case 0: 112287e3f3fSJohn Crispin clk = CLOCK_600M; 113287e3f3fSJohn Crispin break; 114287e3f3fSJohn Crispin case 1: 115287e3f3fSJohn Crispin clk = CLOCK_500M; 116287e3f3fSJohn Crispin break; 117287e3f3fSJohn Crispin case 2: 118287e3f3fSJohn Crispin clk = CLOCK_393M; 119287e3f3fSJohn Crispin break; 120287e3f3fSJohn Crispin case 3: 121287e3f3fSJohn Crispin clk = CLOCK_333M; 122287e3f3fSJohn Crispin break; 123287e3f3fSJohn Crispin case 5: 124287e3f3fSJohn Crispin case 6: 125287e3f3fSJohn Crispin clk = CLOCK_196_608M; 126287e3f3fSJohn Crispin break; 127287e3f3fSJohn Crispin case 7: 128287e3f3fSJohn Crispin clk = CLOCK_167M; 129287e3f3fSJohn Crispin break; 130287e3f3fSJohn Crispin case 4: 131287e3f3fSJohn Crispin case 8: 132287e3f3fSJohn Crispin case 9: 133287e3f3fSJohn Crispin clk = CLOCK_125M; 134287e3f3fSJohn Crispin break; 135287e3f3fSJohn Crispin default: 136287e3f3fSJohn Crispin clk = 0; 137287e3f3fSJohn Crispin break; 138287e3f3fSJohn Crispin } 139287e3f3fSJohn Crispin 140287e3f3fSJohn Crispin return clk; 141287e3f3fSJohn Crispin } 142287e3f3fSJohn Crispin 143287e3f3fSJohn Crispin unsigned long ltq_vr9_fpi_hz(void) 144287e3f3fSJohn Crispin { 145287e3f3fSJohn Crispin unsigned int ocp_sel, cpu_clk; 146287e3f3fSJohn Crispin unsigned long clk; 147287e3f3fSJohn Crispin 148287e3f3fSJohn Crispin cpu_clk = ltq_vr9_cpu_hz(); 149b5a03d0cSHauke Mehrtens ocp_sel = ltq_cgu_r32(CGU_SYS_XRX) & 0x3; 150287e3f3fSJohn Crispin 151287e3f3fSJohn Crispin switch (ocp_sel) { 152287e3f3fSJohn Crispin case 0: 153287e3f3fSJohn Crispin /* OCP ratio 1 */ 154287e3f3fSJohn Crispin clk = cpu_clk; 155287e3f3fSJohn Crispin break; 156287e3f3fSJohn Crispin case 2: 157287e3f3fSJohn Crispin /* OCP ratio 2 */ 158287e3f3fSJohn Crispin clk = cpu_clk / 2; 159287e3f3fSJohn Crispin break; 160287e3f3fSJohn Crispin case 3: 161287e3f3fSJohn Crispin /* OCP ratio 2.5 */ 162287e3f3fSJohn Crispin clk = (cpu_clk * 2) / 5; 163287e3f3fSJohn Crispin break; 164287e3f3fSJohn Crispin case 4: 165287e3f3fSJohn Crispin /* OCP ratio 3 */ 166287e3f3fSJohn Crispin clk = cpu_clk / 3; 167287e3f3fSJohn Crispin break; 168287e3f3fSJohn Crispin default: 169287e3f3fSJohn Crispin clk = 0; 170287e3f3fSJohn Crispin break; 171287e3f3fSJohn Crispin } 172287e3f3fSJohn Crispin 173287e3f3fSJohn Crispin return clk; 174287e3f3fSJohn Crispin } 175740c606eSJohn Crispin 176740c606eSJohn Crispin unsigned long ltq_vr9_pp32_hz(void) 177740c606eSJohn Crispin { 17818a3af60SHauke Mehrtens unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7; 179740c606eSJohn Crispin unsigned long clk; 180740c606eSJohn Crispin 181740c606eSJohn Crispin switch (clksys) { 18218a3af60SHauke Mehrtens case 0: 18318a3af60SHauke Mehrtens clk = CLOCK_500M; 18418a3af60SHauke Mehrtens break; 185740c606eSJohn Crispin case 1: 18618a3af60SHauke Mehrtens clk = CLOCK_432M; 187740c606eSJohn Crispin break; 188740c606eSJohn Crispin case 2: 18918a3af60SHauke Mehrtens clk = CLOCK_288M; 190740c606eSJohn Crispin break; 191740c606eSJohn Crispin default: 192740c606eSJohn Crispin clk = CLOCK_500M; 193740c606eSJohn Crispin break; 194740c606eSJohn Crispin } 195740c606eSJohn Crispin 196740c606eSJohn Crispin return clk; 197740c606eSJohn Crispin } 19861e371d8SHauke Mehrtens 19961e371d8SHauke Mehrtens unsigned long ltq_ar10_cpu_hz(void) 20061e371d8SHauke Mehrtens { 20161e371d8SHauke Mehrtens unsigned int clksys; 20261e371d8SHauke Mehrtens int cpu_fs = (ltq_cgu_r32(CGU_SYS_XRX) >> 8) & 0x1; 20361e371d8SHauke Mehrtens int freq_div = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7; 20461e371d8SHauke Mehrtens 20561e371d8SHauke Mehrtens switch (cpu_fs) { 20661e371d8SHauke Mehrtens case 0: 20761e371d8SHauke Mehrtens clksys = CLOCK_500M; 20861e371d8SHauke Mehrtens break; 20961e371d8SHauke Mehrtens case 1: 21061e371d8SHauke Mehrtens clksys = CLOCK_600M; 21161e371d8SHauke Mehrtens break; 21261e371d8SHauke Mehrtens default: 21361e371d8SHauke Mehrtens clksys = CLOCK_500M; 21461e371d8SHauke Mehrtens break; 21561e371d8SHauke Mehrtens } 21661e371d8SHauke Mehrtens 21761e371d8SHauke Mehrtens switch (freq_div) { 21861e371d8SHauke Mehrtens case 0: 21961e371d8SHauke Mehrtens return clksys; 22061e371d8SHauke Mehrtens case 1: 22161e371d8SHauke Mehrtens return clksys >> 1; 22261e371d8SHauke Mehrtens case 2: 22361e371d8SHauke Mehrtens return clksys >> 2; 22461e371d8SHauke Mehrtens default: 22561e371d8SHauke Mehrtens return clksys; 22661e371d8SHauke Mehrtens } 22761e371d8SHauke Mehrtens } 22861e371d8SHauke Mehrtens 22961e371d8SHauke Mehrtens unsigned long ltq_ar10_fpi_hz(void) 23061e371d8SHauke Mehrtens { 23161e371d8SHauke Mehrtens int freq_fpi = (ltq_cgu_r32(CGU_IF_CLK_AR10) >> 25) & 0xf; 23261e371d8SHauke Mehrtens 23361e371d8SHauke Mehrtens switch (freq_fpi) { 23461e371d8SHauke Mehrtens case 1: 23561e371d8SHauke Mehrtens return CLOCK_300M; 23661e371d8SHauke Mehrtens case 5: 23761e371d8SHauke Mehrtens return CLOCK_250M; 23861e371d8SHauke Mehrtens case 2: 23961e371d8SHauke Mehrtens return CLOCK_150M; 24061e371d8SHauke Mehrtens case 6: 24161e371d8SHauke Mehrtens return CLOCK_125M; 24261e371d8SHauke Mehrtens 24361e371d8SHauke Mehrtens default: 24461e371d8SHauke Mehrtens return CLOCK_125M; 24561e371d8SHauke Mehrtens } 24661e371d8SHauke Mehrtens } 24761e371d8SHauke Mehrtens 24861e371d8SHauke Mehrtens unsigned long ltq_ar10_pp32_hz(void) 24961e371d8SHauke Mehrtens { 25061e371d8SHauke Mehrtens unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7; 25161e371d8SHauke Mehrtens unsigned long clk; 25261e371d8SHauke Mehrtens 25361e371d8SHauke Mehrtens switch (clksys) { 25461e371d8SHauke Mehrtens case 1: 25561e371d8SHauke Mehrtens clk = CLOCK_250M; 25661e371d8SHauke Mehrtens break; 25761e371d8SHauke Mehrtens case 4: 25861e371d8SHauke Mehrtens clk = CLOCK_400M; 25961e371d8SHauke Mehrtens break; 26061e371d8SHauke Mehrtens default: 26161e371d8SHauke Mehrtens clk = CLOCK_250M; 26261e371d8SHauke Mehrtens break; 26361e371d8SHauke Mehrtens } 26461e371d8SHauke Mehrtens 26561e371d8SHauke Mehrtens return clk; 26661e371d8SHauke Mehrtens } 26761e371d8SHauke Mehrtens 26861e371d8SHauke Mehrtens unsigned long ltq_grx390_cpu_hz(void) 26961e371d8SHauke Mehrtens { 27061e371d8SHauke Mehrtens unsigned int clksys; 27161e371d8SHauke Mehrtens int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3); 27261e371d8SHauke Mehrtens int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7); 27361e371d8SHauke Mehrtens 27461e371d8SHauke Mehrtens switch (cpu_fs) { 27561e371d8SHauke Mehrtens case 0: 27661e371d8SHauke Mehrtens clksys = CLOCK_600M; 27761e371d8SHauke Mehrtens break; 27861e371d8SHauke Mehrtens case 1: 27961e371d8SHauke Mehrtens clksys = CLOCK_666M; 28061e371d8SHauke Mehrtens break; 28161e371d8SHauke Mehrtens case 2: 28261e371d8SHauke Mehrtens clksys = CLOCK_720M; 28361e371d8SHauke Mehrtens break; 28461e371d8SHauke Mehrtens default: 28561e371d8SHauke Mehrtens clksys = CLOCK_600M; 28661e371d8SHauke Mehrtens break; 28761e371d8SHauke Mehrtens } 28861e371d8SHauke Mehrtens 28961e371d8SHauke Mehrtens switch (freq_div) { 29061e371d8SHauke Mehrtens case 0: 29161e371d8SHauke Mehrtens return clksys; 29261e371d8SHauke Mehrtens case 1: 29361e371d8SHauke Mehrtens return clksys >> 1; 29461e371d8SHauke Mehrtens case 2: 29561e371d8SHauke Mehrtens return clksys >> 2; 29661e371d8SHauke Mehrtens default: 29761e371d8SHauke Mehrtens return clksys; 29861e371d8SHauke Mehrtens } 29961e371d8SHauke Mehrtens } 30061e371d8SHauke Mehrtens 30161e371d8SHauke Mehrtens unsigned long ltq_grx390_fpi_hz(void) 30261e371d8SHauke Mehrtens { 30361e371d8SHauke Mehrtens /* fpi clock is derived from ddr_clk */ 30461e371d8SHauke Mehrtens unsigned int clksys; 30561e371d8SHauke Mehrtens int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3); 30661e371d8SHauke Mehrtens int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX)) & 0x7); 30761e371d8SHauke Mehrtens switch (cpu_fs) { 30861e371d8SHauke Mehrtens case 0: 30961e371d8SHauke Mehrtens clksys = CLOCK_600M; 31061e371d8SHauke Mehrtens break; 31161e371d8SHauke Mehrtens case 1: 31261e371d8SHauke Mehrtens clksys = CLOCK_666M; 31361e371d8SHauke Mehrtens break; 31461e371d8SHauke Mehrtens case 2: 31561e371d8SHauke Mehrtens clksys = CLOCK_720M; 31661e371d8SHauke Mehrtens break; 31761e371d8SHauke Mehrtens default: 31861e371d8SHauke Mehrtens clksys = CLOCK_600M; 31961e371d8SHauke Mehrtens break; 32061e371d8SHauke Mehrtens } 32161e371d8SHauke Mehrtens 32261e371d8SHauke Mehrtens switch (freq_div) { 32361e371d8SHauke Mehrtens case 1: 32461e371d8SHauke Mehrtens return clksys >> 1; 32561e371d8SHauke Mehrtens case 2: 32661e371d8SHauke Mehrtens return clksys >> 2; 32761e371d8SHauke Mehrtens default: 32861e371d8SHauke Mehrtens return clksys >> 1; 32961e371d8SHauke Mehrtens } 33061e371d8SHauke Mehrtens } 33161e371d8SHauke Mehrtens 33261e371d8SHauke Mehrtens unsigned long ltq_grx390_pp32_hz(void) 33361e371d8SHauke Mehrtens { 33461e371d8SHauke Mehrtens unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7; 33561e371d8SHauke Mehrtens unsigned long clk; 33661e371d8SHauke Mehrtens 33761e371d8SHauke Mehrtens switch (clksys) { 33861e371d8SHauke Mehrtens case 1: 33961e371d8SHauke Mehrtens clk = CLOCK_250M; 34061e371d8SHauke Mehrtens break; 34161e371d8SHauke Mehrtens case 2: 34261e371d8SHauke Mehrtens clk = CLOCK_432M; 34361e371d8SHauke Mehrtens break; 34461e371d8SHauke Mehrtens case 4: 34561e371d8SHauke Mehrtens clk = CLOCK_400M; 34661e371d8SHauke Mehrtens break; 34761e371d8SHauke Mehrtens default: 34861e371d8SHauke Mehrtens clk = CLOCK_250M; 34961e371d8SHauke Mehrtens break; 35061e371d8SHauke Mehrtens } 35161e371d8SHauke Mehrtens return clk; 35261e371d8SHauke Mehrtens } 353