Michael Hennerich | 73feb5c | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 1 | /* |
| 2 | * arch/blackfin/mach-common/clocks-init.c - reprogram clocks / memory |
| 3 | * |
| 4 | * Copyright 2004-2008 Analog Devices Inc. |
| 5 | * |
| 6 | * Licensed under the GPL-2 or later. |
| 7 | */ |
| 8 | |
| 9 | #include <linux/linkage.h> |
| 10 | #include <linux/init.h> |
| 11 | #include <asm/blackfin.h> |
| 12 | |
| 13 | #include <asm/dma.h> |
| 14 | #include <asm/clocks.h> |
| 15 | #include <asm/mem_init.h> |
Mike Frysinger | 761ec44 | 2009-10-15 17:12:05 +0000 | [diff] [blame] | 16 | #include <asm/dpmc.h> |
Michael Hennerich | 73feb5c | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 17 | |
Bob Liu | 7c141c1 | 2012-05-17 17:15:40 +0800 | [diff] [blame^] | 18 | #ifdef CONFIG_BF60x |
| 19 | #define CSEL_P 0 |
| 20 | #define S0SEL_P 5 |
| 21 | #define SYSSEL_P 8 |
| 22 | #define S1SEL_P 13 |
| 23 | #define DSEL_P 16 |
| 24 | #define OSEL_P 22 |
| 25 | #define ALGN_P 29 |
| 26 | #define UPDT_P 30 |
| 27 | #define LOCK_P 31 |
| 28 | |
| 29 | #define CGU_CTL_VAL ((CONFIG_VCO_MULT << 8) | CLKIN_HALF) |
| 30 | #define CGU_DIV_VAL \ |
| 31 | ((CONFIG_CCLK_DIV << CSEL_P) | \ |
| 32 | (CONFIG_SCLK_DIV << SYSSEL_P) | \ |
| 33 | (CONFIG_SCLK0_DIV << S0SEL_P) | \ |
| 34 | (CONFIG_SCLK1_DIV << S1SEL_P) | \ |
| 35 | (CONFIG_DCLK_DIV << DSEL_P)) |
| 36 | |
| 37 | #define CONFIG_BFIN_DCLK (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_DCLK_DIV) / 1000000) |
| 38 | #if ((CONFIG_BFIN_DCLK != 125) && \ |
| 39 | (CONFIG_BFIN_DCLK != 133) && (CONFIG_BFIN_DCLK != 150) && \ |
| 40 | (CONFIG_BFIN_DCLK != 166) && (CONFIG_BFIN_DCLK != 200) && \ |
| 41 | (CONFIG_BFIN_DCLK != 225) && (CONFIG_BFIN_DCLK != 250)) |
| 42 | #error "DCLK must be in (125, 133, 150, 166, 200, 225, 250)MHz" |
| 43 | #endif |
| 44 | struct ddr_config { |
| 45 | u32 ddr_clk; |
| 46 | u32 dmc_ddrctl; |
| 47 | u32 dmc_ddrcfg; |
| 48 | u32 dmc_ddrtr0; |
| 49 | u32 dmc_ddrtr1; |
| 50 | u32 dmc_ddrtr2; |
| 51 | u32 dmc_ddrmr; |
| 52 | u32 dmc_ddrmr1; |
| 53 | }; |
| 54 | |
| 55 | struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) = { |
| 56 | [0] = { |
| 57 | .ddr_clk = 125, |
| 58 | .dmc_ddrctl = 0x00000904, |
| 59 | .dmc_ddrcfg = 0x00000422, |
| 60 | .dmc_ddrtr0 = 0x20705212, |
| 61 | .dmc_ddrtr1 = 0x201003CF, |
| 62 | .dmc_ddrtr2 = 0x00320107, |
| 63 | .dmc_ddrmr = 0x00000422, |
| 64 | .dmc_ddrmr1 = 0x4, |
| 65 | }, |
| 66 | [1] = { |
| 67 | .ddr_clk = 133, |
| 68 | .dmc_ddrctl = 0x00000904, |
| 69 | .dmc_ddrcfg = 0x00000422, |
| 70 | .dmc_ddrtr0 = 0x20806313, |
| 71 | .dmc_ddrtr1 = 0x2013040D, |
| 72 | .dmc_ddrtr2 = 0x00320108, |
| 73 | .dmc_ddrmr = 0x00000632, |
| 74 | .dmc_ddrmr1 = 0x4, |
| 75 | }, |
| 76 | [2] = { |
| 77 | .ddr_clk = 150, |
| 78 | .dmc_ddrctl = 0x00000904, |
| 79 | .dmc_ddrcfg = 0x00000422, |
| 80 | .dmc_ddrtr0 = 0x20A07323, |
| 81 | .dmc_ddrtr1 = 0x20160492, |
| 82 | .dmc_ddrtr2 = 0x00320209, |
| 83 | .dmc_ddrmr = 0x00000632, |
| 84 | .dmc_ddrmr1 = 0x4, |
| 85 | }, |
| 86 | [3] = { |
| 87 | .ddr_clk = 166, |
| 88 | .dmc_ddrctl = 0x00000904, |
| 89 | .dmc_ddrcfg = 0x00000422, |
| 90 | .dmc_ddrtr0 = 0x20A07323, |
| 91 | .dmc_ddrtr1 = 0x2016050E, |
| 92 | .dmc_ddrtr2 = 0x00320209, |
| 93 | .dmc_ddrmr = 0x00000632, |
| 94 | .dmc_ddrmr1 = 0x4, |
| 95 | }, |
| 96 | [4] = { |
| 97 | .ddr_clk = 200, |
| 98 | .dmc_ddrctl = 0x00000904, |
| 99 | .dmc_ddrcfg = 0x00000422, |
| 100 | .dmc_ddrtr0 = 0x20a07323, |
| 101 | .dmc_ddrtr1 = 0x2016050f, |
| 102 | .dmc_ddrtr2 = 0x00320509, |
| 103 | .dmc_ddrmr = 0x00000632, |
| 104 | .dmc_ddrmr1 = 0x4, |
| 105 | }, |
| 106 | [5] = { |
| 107 | .ddr_clk = 225, |
| 108 | .dmc_ddrctl = 0x00000904, |
| 109 | .dmc_ddrcfg = 0x00000422, |
| 110 | .dmc_ddrtr0 = 0x20E0A424, |
| 111 | .dmc_ddrtr1 = 0x302006DB, |
| 112 | .dmc_ddrtr2 = 0x0032020D, |
| 113 | .dmc_ddrmr = 0x00000842, |
| 114 | .dmc_ddrmr1 = 0x4, |
| 115 | }, |
| 116 | [6] = { |
| 117 | .ddr_clk = 250, |
| 118 | .dmc_ddrctl = 0x00000904, |
| 119 | .dmc_ddrcfg = 0x00000422, |
| 120 | .dmc_ddrtr0 = 0x20E0A424, |
| 121 | .dmc_ddrtr1 = 0x3020079E, |
| 122 | .dmc_ddrtr2 = 0x0032020D, |
| 123 | .dmc_ddrmr = 0x00000842, |
| 124 | .dmc_ddrmr1 = 0x4, |
| 125 | }, |
| 126 | }; |
| 127 | #else |
Michael Hennerich | 3316931 | 2009-02-04 16:49:45 +0800 | [diff] [blame] | 128 | #define SDGCTL_WIDTH (1 << 31) /* SDRAM external data path width */ |
Michael Hennerich | 73feb5c | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 129 | #define PLL_CTL_VAL \ |
| 130 | (((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \ |
Bob Liu | 7c141c1 | 2012-05-17 17:15:40 +0800 | [diff] [blame^] | 131 | (PLL_BYPASS << 8) | (ANOMALY_05000305 ? 0 : 0x8000)) |
| 132 | #endif |
Michael Hennerich | 73feb5c | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 133 | |
| 134 | __attribute__((l1_text)) |
| 135 | static void do_sync(void) |
| 136 | { |
| 137 | __builtin_bfin_ssync(); |
| 138 | } |
| 139 | |
| 140 | __attribute__((l1_text)) |
| 141 | void init_clocks(void) |
| 142 | { |
| 143 | /* Kill any active DMAs as they may trigger external memory accesses |
| 144 | * in the middle of reprogramming things, and that'll screw us up. |
| 145 | * For example, any automatic DMAs left by U-Boot for splash screens. |
| 146 | */ |
Steven Miao | 9690031 | 2012-05-16 17:49:52 +0800 | [diff] [blame] | 147 | |
Bob Liu | 7c141c1 | 2012-05-17 17:15:40 +0800 | [diff] [blame^] | 148 | #ifdef CONFIG_BF60x |
| 149 | int i, dlldatacycle, dll_ctl; |
| 150 | bfin_write32(CGU0_DIV, CGU_DIV_VAL); |
| 151 | bfin_write32(CGU0_CTL, CGU_CTL_VAL); |
| 152 | while ((bfin_read32(CGU0_STAT) & 0x8) || !(bfin_read32(CGU0_STAT) & 0x4)) |
| 153 | continue; |
| 154 | |
| 155 | bfin_write32(CGU0_DIV, CGU_DIV_VAL | (1 << UPDT_P)); |
| 156 | while (bfin_read32(CGU0_STAT) & (1 << 3)) |
| 157 | continue; |
| 158 | |
| 159 | for (i = 0; i < 7; i++) { |
| 160 | if (ddr_config_table[i].ddr_clk == CONFIG_BFIN_DCLK) { |
| 161 | bfin_write_DDR0_CFG(ddr_config_table[i].dmc_ddrcfg); |
| 162 | bfin_write_DDR0_TR0(ddr_config_table[i].dmc_ddrtr0); |
| 163 | bfin_write_DDR0_TR1(ddr_config_table[i].dmc_ddrtr1); |
| 164 | bfin_write_DDR0_TR2(ddr_config_table[i].dmc_ddrtr2); |
| 165 | bfin_write_DDR0_MR(ddr_config_table[i].dmc_ddrmr); |
| 166 | bfin_write_DDR0_EMR1(ddr_config_table[i].dmc_ddrmr1); |
| 167 | bfin_write_DDR0_CTL(ddr_config_table[i].dmc_ddrctl); |
| 168 | break; |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | do_sync(); |
| 173 | while (!(bfin_read_DDR0_STAT() & 0x4)) |
| 174 | continue; |
| 175 | |
| 176 | dlldatacycle = (bfin_read_DDR0_STAT() & 0x00f00000) >> 20; |
| 177 | dll_ctl = bfin_read_DDR0_DLLCTL(); |
| 178 | dll_ctl &= 0x0ff; |
| 179 | bfin_write_DDR0_DLLCTL(dll_ctl | (dlldatacycle << 8)); |
| 180 | |
| 181 | do_sync(); |
| 182 | while (!(bfin_read_DDR0_STAT() & 0x2000)) |
| 183 | continue; |
| 184 | #else |
Michael Hennerich | 73feb5c | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 185 | size_t i; |
Mike Frysinger | 211daf9 | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 186 | for (i = 0; i < MAX_DMA_CHANNELS; ++i) { |
Michael Hennerich | 73feb5c | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 187 | struct dma_register *dma = dma_io_base_addr[i]; |
| 188 | dma->cfg = 0; |
| 189 | } |
| 190 | |
| 191 | do_sync(); |
| 192 | |
| 193 | #ifdef SIC_IWR0 |
| 194 | bfin_write_SIC_IWR0(IWR_ENABLE(0)); |
| 195 | # ifdef SIC_IWR1 |
| 196 | /* BF52x system reset does not properly reset SIC_IWR1 which |
| 197 | * will screw up the bootrom as it relies on MDMA0/1 waking it |
| 198 | * up from IDLE instructions. See this report for more info: |
| 199 | * http://blackfin.uclinux.org/gf/tracker/4323 |
| 200 | */ |
| 201 | if (ANOMALY_05000435) |
| 202 | bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); |
| 203 | else |
| 204 | bfin_write_SIC_IWR1(IWR_DISABLE_ALL); |
| 205 | # endif |
| 206 | # ifdef SIC_IWR2 |
| 207 | bfin_write_SIC_IWR2(IWR_DISABLE_ALL); |
| 208 | # endif |
| 209 | #else |
| 210 | bfin_write_SIC_IWR(IWR_ENABLE(0)); |
| 211 | #endif |
| 212 | do_sync(); |
| 213 | #ifdef EBIU_SDGCTL |
| 214 | bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS); |
| 215 | do_sync(); |
| 216 | #endif |
| 217 | |
| 218 | #ifdef CLKBUFOE |
| 219 | bfin_write16(VR_CTL, bfin_read_VR_CTL() | CLKBUFOE); |
| 220 | do_sync(); |
| 221 | __asm__ __volatile__("IDLE;"); |
| 222 | #endif |
| 223 | bfin_write_PLL_LOCKCNT(0x300); |
| 224 | do_sync(); |
Mike Frysinger | 97b070c | 2009-04-24 03:17:07 +0000 | [diff] [blame] | 225 | /* We always write PLL_CTL thus avoiding Anomaly 05000242 */ |
Michael Hennerich | 73feb5c | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 226 | bfin_write16(PLL_CTL, PLL_CTL_VAL); |
| 227 | __asm__ __volatile__("IDLE;"); |
| 228 | bfin_write_PLL_DIV(CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV); |
| 229 | #ifdef EBIU_SDGCTL |
| 230 | bfin_write_EBIU_SDRRC(mem_SDRRC); |
Michael Hennerich | 3316931 | 2009-02-04 16:49:45 +0800 | [diff] [blame] | 231 | bfin_write_EBIU_SDGCTL((bfin_read_EBIU_SDGCTL() & SDGCTL_WIDTH) | mem_SDGCTL); |
Michael Hennerich | 73feb5c | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 232 | #else |
| 233 | bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ)); |
| 234 | do_sync(); |
| 235 | bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | 0x1); |
| 236 | bfin_write_EBIU_DDRCTL0(mem_DDRCTL0); |
| 237 | bfin_write_EBIU_DDRCTL1(mem_DDRCTL1); |
| 238 | bfin_write_EBIU_DDRCTL2(mem_DDRCTL2); |
| 239 | #ifdef CONFIG_MEM_EBIU_DDRQUE |
| 240 | bfin_write_EBIU_DDRQUE(CONFIG_MEM_EBIU_DDRQUE); |
| 241 | #endif |
| 242 | #endif |
Bob Liu | 7c141c1 | 2012-05-17 17:15:40 +0800 | [diff] [blame^] | 243 | #endif |
Michael Hennerich | 73feb5c | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 244 | do_sync(); |
| 245 | bfin_read16(0); |
Steven Miao | 9690031 | 2012-05-16 17:49:52 +0800 | [diff] [blame] | 246 | |
Michael Hennerich | 73feb5c | 2009-01-07 23:14:39 +0800 | [diff] [blame] | 247 | } |