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 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 108287e3f3fSJohn Crispin cpu_sel = (ltq_cgu_r32(CGU_SYS_VR9) >> 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(); 149287e3f3fSJohn Crispin ocp_sel = ltq_cgu_r32(CGU_SYS_VR9) & 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 { 178740c606eSJohn Crispin unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 3; 179740c606eSJohn Crispin unsigned long clk; 180740c606eSJohn Crispin 181740c606eSJohn Crispin switch (clksys) { 182740c606eSJohn Crispin case 1: 183740c606eSJohn Crispin clk = CLOCK_450M; 184740c606eSJohn Crispin break; 185740c606eSJohn Crispin case 2: 186740c606eSJohn Crispin clk = CLOCK_300M; 187740c606eSJohn Crispin break; 188740c606eSJohn Crispin default: 189740c606eSJohn Crispin clk = CLOCK_500M; 190740c606eSJohn Crispin break; 191740c606eSJohn Crispin } 192740c606eSJohn Crispin 193740c606eSJohn Crispin return clk; 194740c606eSJohn Crispin } 195