1/* 2 * This program is free software; you can redistribute it and/or modify it 3 * under the terms of the GNU General Public License version 2 as published 4 * by the Free Software Foundation. 5 * 6 * Copyright (C) 2011 John Crispin <blogic@openwrt.org> 7 */ 8 9#include <linux/ioport.h> 10#include <linux/export.h> 11#include <linux/clkdev.h> 12 13#include <lantiq_soc.h> 14 15#include "../clk.h" 16#include "../devices.h" 17 18/* clock control register */ 19#define CGU_IFCCR 0x0018 20/* system clock register */ 21#define CGU_SYS 0x0010 22/* pci control register */ 23#define CGU_PCICR 0x0034 24/* ephy configuration register */ 25#define CGU_EPHY 0x10 26/* power control register */ 27#define PMU_PWDCR 0x1C 28/* power status register */ 29#define PMU_PWDSR 0x20 30/* power control register */ 31#define PMU_PWDCR1 0x24 32/* power status register */ 33#define PMU_PWDSR1 0x28 34/* power control register */ 35#define PWDCR(x) ((x) ? (PMU_PWDCR1) : (PMU_PWDCR)) 36/* power status register */ 37#define PWDSR(x) ((x) ? (PMU_PWDSR1) : (PMU_PWDSR)) 38 39/* PMU - power management unit */ 40#define PMU_USB0_P BIT(0) 41#define PMU_PCI BIT(4) 42#define PMU_DMA BIT(5) 43#define PMU_USB0 BIT(6) 44#define PMU_EPHY BIT(7) /* ase */ 45#define PMU_SPI BIT(8) 46#define PMU_DFE BIT(9) 47#define PMU_EBU BIT(10) 48#define PMU_STP BIT(11) 49#define PMU_GPT BIT(12) 50#define PMU_PPE BIT(13) 51#define PMU_AHBS BIT(13) /* vr9 */ 52#define PMU_FPI BIT(14) 53#define PMU_AHBM BIT(15) 54#define PMU_PPE_QSB BIT(18) 55#define PMU_PPE_SLL01 BIT(19) 56#define PMU_PPE_TC BIT(21) 57#define PMU_PPE_EMA BIT(22) 58#define PMU_PPE_DPLUM BIT(23) 59#define PMU_PPE_DPLUS BIT(24) 60#define PMU_USB1_P BIT(26) 61#define PMU_USB1 BIT(27) 62#define PMU_SWITCH BIT(28) 63#define PMU_PPE_TOP BIT(29) 64#define PMU_GPHY BIT(30) 65#define PMU_PCIE_CLK BIT(31) 66 67#define PMU1_PCIE_PHY BIT(0) 68#define PMU1_PCIE_CTL BIT(1) 69#define PMU1_PCIE_PDI BIT(4) 70#define PMU1_PCIE_MSI BIT(5) 71 72#define ltq_pmu_w32(x, y) ltq_w32((x), ltq_pmu_membase + (y)) 73#define ltq_pmu_r32(x) ltq_r32(ltq_pmu_membase + (x)) 74 75static struct resource ltq_cgu_resource = 76 MEM_RES("cgu", LTQ_CGU_BASE_ADDR, LTQ_CGU_SIZE); 77 78static struct resource ltq_pmu_resource = 79 MEM_RES("pmu", LTQ_PMU_BASE_ADDR, LTQ_PMU_SIZE); 80 81static struct resource ltq_ebu_resource = 82 MEM_RES("ebu", LTQ_EBU_BASE_ADDR, LTQ_EBU_SIZE); 83 84void __iomem *ltq_cgu_membase; 85void __iomem *ltq_ebu_membase; 86static void __iomem *ltq_pmu_membase; 87 88static int ltq_cgu_enable(struct clk *clk) 89{ 90 ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | clk->bits, CGU_IFCCR); 91 return 0; 92} 93 94static void ltq_cgu_disable(struct clk *clk) 95{ 96 ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~clk->bits, CGU_IFCCR); 97} 98 99static int ltq_pmu_enable(struct clk *clk) 100{ 101 int err = 1000000; 102 103 ltq_pmu_w32(ltq_pmu_r32(PWDCR(clk->module)) & ~clk->bits, 104 PWDCR(clk->module)); 105 do {} while (--err && (ltq_pmu_r32(PWDSR(clk->module)) & clk->bits)); 106 107 if (!err) 108 panic("activating PMU module failed!\n"); 109 110 return 0; 111} 112 113static void ltq_pmu_disable(struct clk *clk) 114{ 115 ltq_pmu_w32(ltq_pmu_r32(PWDCR(clk->module)) | clk->bits, 116 PWDCR(clk->module)); 117} 118 119static int ltq_pci_enable(struct clk *clk) 120{ 121 unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR); 122 /* set clock bus speed */ 123 if (ltq_is_ar9()) { 124 ifccr &= ~0x1f00000; 125 if (clk->rate == CLOCK_33M) 126 ifccr |= 0xe00000; 127 else 128 ifccr |= 0x700000; /* 62.5M */ 129 } else { 130 ifccr &= ~0xf00000; 131 if (clk->rate == CLOCK_33M) 132 ifccr |= 0x800000; 133 else 134 ifccr |= 0x400000; /* 62.5M */ 135 } 136 ltq_cgu_w32(ifccr, CGU_IFCCR); 137 return 0; 138} 139 140static int ltq_pci_ext_enable(struct clk *clk) 141{ 142 /* enable external pci clock */ 143 ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~(1 << 16), 144 CGU_IFCCR); 145 ltq_cgu_w32((1 << 30), CGU_PCICR); 146 return 0; 147} 148 149static void ltq_pci_ext_disable(struct clk *clk) 150{ 151 /* disable external pci clock (internal) */ 152 ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | (1 << 16), 153 CGU_IFCCR); 154 ltq_cgu_w32((1 << 31) | (1 << 30), CGU_PCICR); 155} 156 157/* manage the clock gates via PMU */ 158static inline void clkdev_add_pmu(const char *dev, const char *con, 159 unsigned int module, unsigned int bits) 160{ 161 struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); 162 163 clk->cl.dev_id = dev; 164 clk->cl.con_id = con; 165 clk->cl.clk = clk; 166 clk->enable = ltq_pmu_enable; 167 clk->disable = ltq_pmu_disable; 168 clk->module = module; 169 clk->bits = bits; 170 clkdev_add(&clk->cl); 171} 172 173/* manage the clock generator */ 174static inline void clkdev_add_cgu(const char *dev, const char *con, 175 unsigned int bits) 176{ 177 struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); 178 179 clk->cl.dev_id = dev; 180 clk->cl.con_id = con; 181 clk->cl.clk = clk; 182 clk->enable = ltq_cgu_enable; 183 clk->disable = ltq_cgu_disable; 184 clk->bits = bits; 185 clkdev_add(&clk->cl); 186} 187 188/* pci needs its own enable function */ 189static inline void clkdev_add_pci(void) 190{ 191 struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL); 192 struct clk *clk_ext = kzalloc(sizeof(struct clk), GFP_KERNEL); 193 194 /* main pci clock */ 195 clk->cl.dev_id = "ltq_pci"; 196 clk->cl.con_id = NULL; 197 clk->cl.clk = clk; 198 clk->rate = CLOCK_33M; 199 clk->enable = ltq_pci_enable; 200 clk->disable = ltq_pmu_disable; 201 clk->module = 0; 202 clk->bits = PMU_PCI; 203 clkdev_add(&clk->cl); 204 205 /* use internal/external bus clock */ 206 clk_ext->cl.dev_id = "ltq_pci"; 207 clk_ext->cl.con_id = "external"; 208 clk_ext->cl.clk = clk_ext; 209 clk_ext->enable = ltq_pci_ext_enable; 210 clk_ext->disable = ltq_pci_ext_disable; 211 clkdev_add(&clk_ext->cl); 212 213} 214 215void __init ltq_soc_init(void) 216{ 217 ltq_pmu_membase = ltq_remap_resource(<q_pmu_resource); 218 if (!ltq_pmu_membase) 219 panic("Failed to remap pmu memory\n"); 220 221 ltq_cgu_membase = ltq_remap_resource(<q_cgu_resource); 222 if (!ltq_cgu_membase) 223 panic("Failed to remap cgu memory\n"); 224 225 ltq_ebu_membase = ltq_remap_resource(<q_ebu_resource); 226 if (!ltq_ebu_membase) 227 panic("Failed to remap ebu memory\n"); 228 229 /* make sure to unprotect the memory region where flash is located */ 230 ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0); 231 232 /* add our clocks */ 233 clkdev_add_pmu("ltq_fpi", NULL, 0, PMU_FPI); 234 clkdev_add_pmu("ltq_dma", NULL, 0, PMU_DMA); 235 clkdev_add_pmu("ltq_stp", NULL, 0, PMU_STP); 236 clkdev_add_pmu("ltq_spi.0", NULL, 0, PMU_SPI); 237 clkdev_add_pmu("ltq_gptu", NULL, 0, PMU_GPT); 238 clkdev_add_pmu("ltq_ebu", NULL, 0, PMU_EBU); 239 if (!ltq_is_vr9()) 240 clkdev_add_pmu("ltq_etop", NULL, 0, PMU_PPE); 241 if (!ltq_is_ase()) 242 clkdev_add_pci(); 243 if (ltq_is_ase()) { 244 if (ltq_cgu_r32(CGU_SYS) & (1 << 5)) 245 clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M); 246 else 247 clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M); 248 clkdev_add_cgu("ltq_etop", "ephycgu", CGU_EPHY), 249 clkdev_add_pmu("ltq_etop", "ephy", 0, PMU_EPHY); 250 clkdev_add_pmu("ltq_dsl", NULL, 0, 251 PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 | 252 PMU_AHBS | PMU_DFE); 253 } else if (ltq_is_vr9()) { 254 clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(), 255 ltq_vr9_fpi_hz()); 256 clkdev_add_pmu("ltq_pcie", "phy", 1, PMU1_PCIE_PHY); 257 clkdev_add_pmu("ltq_pcie", "bus", 0, PMU_PCIE_CLK); 258 clkdev_add_pmu("ltq_pcie", "msi", 1, PMU1_PCIE_MSI); 259 clkdev_add_pmu("ltq_pcie", "pdi", 1, PMU1_PCIE_PDI); 260 clkdev_add_pmu("ltq_pcie", "ctl", 1, PMU1_PCIE_CTL); 261 clkdev_add_pmu("ltq_pcie", "ahb", 0, PMU_AHBM | PMU_AHBS); 262 clkdev_add_pmu("usb0", NULL, 0, PMU_USB0 | PMU_USB0_P); 263 clkdev_add_pmu("usb1", NULL, 0, PMU_USB1 | PMU_USB1_P); 264 clkdev_add_pmu("ltq_vrx200", NULL, 0, 265 PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM | 266 PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 | 267 PMU_PPE_QSB); 268 clkdev_add_pmu("ltq_dsl", NULL, 0, PMU_DFE | PMU_AHBS); 269 } else if (ltq_is_ar9()) { 270 clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(), 271 ltq_ar9_fpi_hz()); 272 clkdev_add_pmu("ltq_etop", "switch", 0, PMU_SWITCH); 273 clkdev_add_pmu("ltq_dsl", NULL, 0, 274 PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 | 275 PMU_PPE_QSB | PMU_AHBS | PMU_DFE); 276 } else { 277 clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(), 278 ltq_danube_io_region_clock()); 279 clkdev_add_pmu("ltq_dsl", NULL, 0, 280 PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 | 281 PMU_PPE_QSB | PMU_AHBS | PMU_DFE); 282 } 283} 284