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> 7287e3f3fSJohn Crispin */ 8287e3f3fSJohn Crispin 9287e3f3fSJohn Crispin #include <linux/io.h> 10287e3f3fSJohn Crispin #include <linux/export.h> 11287e3f3fSJohn Crispin #include <linux/init.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 29287e3f3fSJohn Crispin /* vr9 clock */ 30287e3f3fSJohn Crispin #define CGU_SYS_VR9 0x0c 31287e3f3fSJohn Crispin #define CGU_IF_CLK_VR9 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 56287e3f3fSJohn Crispin unsigned long ltq_ar9_sys_hz(void) 57287e3f3fSJohn Crispin { 58287e3f3fSJohn Crispin if (((ltq_cgu_r32(CGU_SYS) >> 3) & 0x3) == 0x2) 59287e3f3fSJohn Crispin return CLOCK_393M; 60287e3f3fSJohn Crispin return CLOCK_333M; 61287e3f3fSJohn Crispin } 62287e3f3fSJohn Crispin 63287e3f3fSJohn Crispin unsigned long ltq_ar9_fpi_hz(void) 64287e3f3fSJohn Crispin { 65287e3f3fSJohn Crispin unsigned long sys = ltq_ar9_sys_hz(); 66287e3f3fSJohn Crispin 67287e3f3fSJohn Crispin if (ltq_cgu_r32(CGU_SYS) & BIT(0)) 68287e3f3fSJohn Crispin return sys; 69287e3f3fSJohn Crispin return sys >> 1; 70287e3f3fSJohn Crispin } 71287e3f3fSJohn Crispin 72287e3f3fSJohn Crispin unsigned long ltq_ar9_cpu_hz(void) 73287e3f3fSJohn Crispin { 74287e3f3fSJohn Crispin if (ltq_cgu_r32(CGU_SYS) & BIT(2)) 75287e3f3fSJohn Crispin return ltq_ar9_fpi_hz(); 76287e3f3fSJohn Crispin else 77287e3f3fSJohn Crispin return ltq_ar9_sys_hz(); 78287e3f3fSJohn Crispin } 79287e3f3fSJohn Crispin 80287e3f3fSJohn Crispin unsigned long ltq_vr9_cpu_hz(void) 81287e3f3fSJohn Crispin { 82287e3f3fSJohn Crispin unsigned int cpu_sel; 83287e3f3fSJohn Crispin unsigned long clk; 84287e3f3fSJohn Crispin 85287e3f3fSJohn Crispin cpu_sel = (ltq_cgu_r32(CGU_SYS_VR9) >> 4) & 0xf; 86287e3f3fSJohn Crispin 87287e3f3fSJohn Crispin switch (cpu_sel) { 88287e3f3fSJohn Crispin case 0: 89287e3f3fSJohn Crispin clk = CLOCK_600M; 90287e3f3fSJohn Crispin break; 91287e3f3fSJohn Crispin case 1: 92287e3f3fSJohn Crispin clk = CLOCK_500M; 93287e3f3fSJohn Crispin break; 94287e3f3fSJohn Crispin case 2: 95287e3f3fSJohn Crispin clk = CLOCK_393M; 96287e3f3fSJohn Crispin break; 97287e3f3fSJohn Crispin case 3: 98287e3f3fSJohn Crispin clk = CLOCK_333M; 99287e3f3fSJohn Crispin break; 100287e3f3fSJohn Crispin case 5: 101287e3f3fSJohn Crispin case 6: 102287e3f3fSJohn Crispin clk = CLOCK_196_608M; 103287e3f3fSJohn Crispin break; 104287e3f3fSJohn Crispin case 7: 105287e3f3fSJohn Crispin clk = CLOCK_167M; 106287e3f3fSJohn Crispin break; 107287e3f3fSJohn Crispin case 4: 108287e3f3fSJohn Crispin case 8: 109287e3f3fSJohn Crispin case 9: 110287e3f3fSJohn Crispin clk = CLOCK_125M; 111287e3f3fSJohn Crispin break; 112287e3f3fSJohn Crispin default: 113287e3f3fSJohn Crispin clk = 0; 114287e3f3fSJohn Crispin break; 115287e3f3fSJohn Crispin } 116287e3f3fSJohn Crispin 117287e3f3fSJohn Crispin return clk; 118287e3f3fSJohn Crispin } 119287e3f3fSJohn Crispin 120287e3f3fSJohn Crispin unsigned long ltq_vr9_fpi_hz(void) 121287e3f3fSJohn Crispin { 122287e3f3fSJohn Crispin unsigned int ocp_sel, cpu_clk; 123287e3f3fSJohn Crispin unsigned long clk; 124287e3f3fSJohn Crispin 125287e3f3fSJohn Crispin cpu_clk = ltq_vr9_cpu_hz(); 126287e3f3fSJohn Crispin ocp_sel = ltq_cgu_r32(CGU_SYS_VR9) & 0x3; 127287e3f3fSJohn Crispin 128287e3f3fSJohn Crispin switch (ocp_sel) { 129287e3f3fSJohn Crispin case 0: 130287e3f3fSJohn Crispin /* OCP ratio 1 */ 131287e3f3fSJohn Crispin clk = cpu_clk; 132287e3f3fSJohn Crispin break; 133287e3f3fSJohn Crispin case 2: 134287e3f3fSJohn Crispin /* OCP ratio 2 */ 135287e3f3fSJohn Crispin clk = cpu_clk / 2; 136287e3f3fSJohn Crispin break; 137287e3f3fSJohn Crispin case 3: 138287e3f3fSJohn Crispin /* OCP ratio 2.5 */ 139287e3f3fSJohn Crispin clk = (cpu_clk * 2) / 5; 140287e3f3fSJohn Crispin break; 141287e3f3fSJohn Crispin case 4: 142287e3f3fSJohn Crispin /* OCP ratio 3 */ 143287e3f3fSJohn Crispin clk = cpu_clk / 3; 144287e3f3fSJohn Crispin break; 145287e3f3fSJohn Crispin default: 146287e3f3fSJohn Crispin clk = 0; 147287e3f3fSJohn Crispin break; 148287e3f3fSJohn Crispin } 149287e3f3fSJohn Crispin 150287e3f3fSJohn Crispin return clk; 151287e3f3fSJohn Crispin } 152