1 /* 2 * Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org> 3 * Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <div64.h> 10 #include <netdev.h> 11 #include <asm/io.h> 12 #include <asm/arch/imx-regs.h> 13 #include <asm/arch/clock.h> 14 #include <asm/arch/gpio.h> 15 #include <asm/mach-imx/sys_proto.h> 16 #ifdef CONFIG_MMC_MXC 17 #include <asm/arch/mxcmmc.h> 18 #endif 19 20 /* 21 * get the system pll clock in Hz 22 * 23 * mfi + mfn / (mfd +1) 24 * f = 2 * f_ref * -------------------- 25 * pd + 1 26 */ 27 static unsigned int imx_decode_pll(unsigned int pll, unsigned int f_ref) 28 { 29 unsigned int mfi = (pll >> 10) & 0xf; 30 unsigned int mfn = pll & 0x3ff; 31 unsigned int mfd = (pll >> 16) & 0x3ff; 32 unsigned int pd = (pll >> 26) & 0xf; 33 34 mfi = mfi <= 5 ? 5 : mfi; 35 36 return lldiv(2 * (u64)f_ref * (mfi * (mfd + 1) + mfn), 37 (mfd + 1) * (pd + 1)); 38 } 39 40 static ulong clk_in_32k(void) 41 { 42 return 1024 * CONFIG_MX27_CLK32; 43 } 44 45 static ulong clk_in_26m(void) 46 { 47 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 48 49 if (readl(&pll->cscr) & CSCR_OSC26M_DIV1P5) { 50 /* divide by 1.5 */ 51 return 26000000 * 2 / 3; 52 } else { 53 return 26000000; 54 } 55 } 56 57 static ulong imx_get_mpllclk(void) 58 { 59 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 60 ulong cscr = readl(&pll->cscr); 61 ulong fref; 62 63 if (cscr & CSCR_MCU_SEL) 64 fref = clk_in_26m(); 65 else 66 fref = clk_in_32k(); 67 68 return imx_decode_pll(readl(&pll->mpctl0), fref); 69 } 70 71 static ulong imx_get_armclk(void) 72 { 73 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 74 ulong cscr = readl(&pll->cscr); 75 ulong fref = imx_get_mpllclk(); 76 ulong div; 77 78 if (!(cscr & CSCR_ARM_SRC_MPLL)) 79 fref = lldiv((fref * 2), 3); 80 81 div = ((cscr >> 12) & 0x3) + 1; 82 83 return lldiv(fref, div); 84 } 85 86 static ulong imx_get_ahbclk(void) 87 { 88 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 89 ulong cscr = readl(&pll->cscr); 90 ulong fref = imx_get_mpllclk(); 91 ulong div; 92 93 div = ((cscr >> 8) & 0x3) + 1; 94 95 return lldiv(fref * 2, 3 * div); 96 } 97 98 static __attribute__((unused)) ulong imx_get_spllclk(void) 99 { 100 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 101 ulong cscr = readl(&pll->cscr); 102 ulong fref; 103 104 if (cscr & CSCR_SP_SEL) 105 fref = clk_in_26m(); 106 else 107 fref = clk_in_32k(); 108 109 return imx_decode_pll(readl(&pll->spctl0), fref); 110 } 111 112 static ulong imx_decode_perclk(ulong div) 113 { 114 return lldiv((imx_get_mpllclk() * 2), (div * 3)); 115 } 116 117 static ulong imx_get_perclk1(void) 118 { 119 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 120 121 return imx_decode_perclk((readl(&pll->pcdr1) & 0x3f) + 1); 122 } 123 124 static ulong imx_get_perclk2(void) 125 { 126 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 127 128 return imx_decode_perclk(((readl(&pll->pcdr1) >> 8) & 0x3f) + 1); 129 } 130 131 static __attribute__((unused)) ulong imx_get_perclk3(void) 132 { 133 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 134 135 return imx_decode_perclk(((readl(&pll->pcdr1) >> 16) & 0x3f) + 1); 136 } 137 138 static __attribute__((unused)) ulong imx_get_perclk4(void) 139 { 140 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 141 142 return imx_decode_perclk(((readl(&pll->pcdr1) >> 24) & 0x3f) + 1); 143 } 144 145 unsigned int mxc_get_clock(enum mxc_clock clk) 146 { 147 switch (clk) { 148 case MXC_ARM_CLK: 149 return imx_get_armclk(); 150 case MXC_I2C_CLK: 151 return imx_get_ahbclk()/2; 152 case MXC_UART_CLK: 153 return imx_get_perclk1(); 154 case MXC_FEC_CLK: 155 return imx_get_ahbclk(); 156 case MXC_ESDHC_CLK: 157 return imx_get_perclk2(); 158 } 159 return -1; 160 } 161 162 163 u32 get_cpu_rev(void) 164 { 165 return MXC_CPU_MX27 << 12; 166 } 167 168 #if defined(CONFIG_DISPLAY_CPUINFO) 169 int print_cpuinfo (void) 170 { 171 char buf[32]; 172 173 printf("CPU: Freescale i.MX27 at %s MHz\n\n", 174 strmhz(buf, imx_get_mpllclk())); 175 return 0; 176 } 177 #endif 178 179 int cpu_eth_init(bd_t *bis) 180 { 181 #if defined(CONFIG_FEC_MXC) 182 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 183 184 /* enable FEC clock */ 185 writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); 186 writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0); 187 return fecmxc_initialize(bis); 188 #else 189 return 0; 190 #endif 191 } 192 193 /* 194 * Initializes on-chip MMC controllers. 195 * to override, implement board_mmc_init() 196 */ 197 int cpu_mmc_init(bd_t *bis) 198 { 199 #ifdef CONFIG_MMC_MXC 200 return mxc_mmc_init(bis); 201 #else 202 return 0; 203 #endif 204 } 205 206 void imx_gpio_mode(int gpio_mode) 207 { 208 struct gpio_port_regs *regs = (struct gpio_port_regs *)IMX_GPIO_BASE; 209 unsigned int pin = gpio_mode & GPIO_PIN_MASK; 210 unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; 211 unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT; 212 unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT; 213 unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT; 214 unsigned int tmp; 215 216 /* Pullup enable */ 217 if (gpio_mode & GPIO_PUEN) { 218 writel(readl(®s->port[port].puen) | (1 << pin), 219 ®s->port[port].puen); 220 } else { 221 writel(readl(®s->port[port].puen) & ~(1 << pin), 222 ®s->port[port].puen); 223 } 224 225 /* Data direction */ 226 if (gpio_mode & GPIO_OUT) { 227 writel(readl(®s->port[port].gpio_dir) | 1 << pin, 228 ®s->port[port].gpio_dir); 229 } else { 230 writel(readl(®s->port[port].gpio_dir) & ~(1 << pin), 231 ®s->port[port].gpio_dir); 232 } 233 234 /* Primary / alternate function */ 235 if (gpio_mode & GPIO_AF) { 236 writel(readl(®s->port[port].gpr) | (1 << pin), 237 ®s->port[port].gpr); 238 } else { 239 writel(readl(®s->port[port].gpr) & ~(1 << pin), 240 ®s->port[port].gpr); 241 } 242 243 /* use as gpio? */ 244 if (!(gpio_mode & (GPIO_PF | GPIO_AF))) { 245 writel(readl(®s->port[port].gius) | (1 << pin), 246 ®s->port[port].gius); 247 } else { 248 writel(readl(®s->port[port].gius) & ~(1 << pin), 249 ®s->port[port].gius); 250 } 251 252 /* Output / input configuration */ 253 if (pin < 16) { 254 tmp = readl(®s->port[port].ocr1); 255 tmp &= ~(3 << (pin * 2)); 256 tmp |= (ocr << (pin * 2)); 257 writel(tmp, ®s->port[port].ocr1); 258 259 writel(readl(®s->port[port].iconfa1) & ~(3 << (pin * 2)), 260 ®s->port[port].iconfa1); 261 writel(readl(®s->port[port].iconfa1) | aout << (pin * 2), 262 ®s->port[port].iconfa1); 263 writel(readl(®s->port[port].iconfb1) & ~(3 << (pin * 2)), 264 ®s->port[port].iconfb1); 265 writel(readl(®s->port[port].iconfb1) | bout << (pin * 2), 266 ®s->port[port].iconfb1); 267 } else { 268 pin -= 16; 269 270 tmp = readl(®s->port[port].ocr2); 271 tmp &= ~(3 << (pin * 2)); 272 tmp |= (ocr << (pin * 2)); 273 writel(tmp, ®s->port[port].ocr2); 274 275 writel(readl(®s->port[port].iconfa2) & ~(3 << (pin * 2)), 276 ®s->port[port].iconfa2); 277 writel(readl(®s->port[port].iconfa2) | aout << (pin * 2), 278 ®s->port[port].iconfa2); 279 writel(readl(®s->port[port].iconfb2) & ~(3 << (pin * 2)), 280 ®s->port[port].iconfb2); 281 writel(readl(®s->port[port].iconfb2) | bout << (pin * 2), 282 ®s->port[port].iconfb2); 283 } 284 } 285 286 #ifdef CONFIG_MXC_UART 287 void mx27_uart1_init_pins(void) 288 { 289 int i; 290 unsigned int mode[] = { 291 PE12_PF_UART1_TXD, 292 PE13_PF_UART1_RXD, 293 }; 294 295 for (i = 0; i < ARRAY_SIZE(mode); i++) 296 imx_gpio_mode(mode[i]); 297 298 } 299 #endif /* CONFIG_MXC_UART */ 300 301 #ifdef CONFIG_FEC_MXC 302 void mx27_fec_init_pins(void) 303 { 304 int i; 305 unsigned int mode[] = { 306 PD0_AIN_FEC_TXD0, 307 PD1_AIN_FEC_TXD1, 308 PD2_AIN_FEC_TXD2, 309 PD3_AIN_FEC_TXD3, 310 PD4_AOUT_FEC_RX_ER, 311 PD5_AOUT_FEC_RXD1, 312 PD6_AOUT_FEC_RXD2, 313 PD7_AOUT_FEC_RXD3, 314 PD8_AF_FEC_MDIO, 315 PD9_AIN_FEC_MDC | GPIO_PUEN, 316 PD10_AOUT_FEC_CRS, 317 PD11_AOUT_FEC_TX_CLK, 318 PD12_AOUT_FEC_RXD0, 319 PD13_AOUT_FEC_RX_DV, 320 PD14_AOUT_FEC_CLR, 321 PD15_AOUT_FEC_COL, 322 PD16_AIN_FEC_TX_ER, 323 PF23_AIN_FEC_TX_EN, 324 }; 325 326 for (i = 0; i < ARRAY_SIZE(mode); i++) 327 imx_gpio_mode(mode[i]); 328 } 329 330 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) 331 { 332 int i; 333 struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; 334 struct fuse_bank *bank = &iim->bank[0]; 335 struct fuse_bank0_regs *fuse = 336 (struct fuse_bank0_regs *)bank->fuse_regs; 337 338 for (i = 0; i < 6; i++) 339 mac[6 - 1 - i] = readl(&fuse->mac_addr[i]) & 0xff; 340 } 341 #endif /* CONFIG_FEC_MXC */ 342 343 #ifdef CONFIG_MMC_MXC 344 void mx27_sd1_init_pins(void) 345 { 346 int i; 347 unsigned int mode[] = { 348 PE18_PF_SD1_D0, 349 PE19_PF_SD1_D1, 350 PE20_PF_SD1_D2, 351 PE21_PF_SD1_D3, 352 PE22_PF_SD1_CMD, 353 PE23_PF_SD1_CLK, 354 }; 355 356 for (i = 0; i < ARRAY_SIZE(mode); i++) 357 imx_gpio_mode(mode[i]); 358 359 } 360 361 void mx27_sd2_init_pins(void) 362 { 363 int i; 364 unsigned int mode[] = { 365 PB4_PF_SD2_D0, 366 PB5_PF_SD2_D1, 367 PB6_PF_SD2_D2, 368 PB7_PF_SD2_D3, 369 PB8_PF_SD2_CMD, 370 PB9_PF_SD2_CLK, 371 }; 372 373 for (i = 0; i < ARRAY_SIZE(mode); i++) 374 imx_gpio_mode(mode[i]); 375 376 } 377 #endif /* CONFIG_MMC_MXC */ 378 379 #ifndef CONFIG_SYS_DCACHE_OFF 380 void enable_caches(void) 381 { 382 /* Enable D-cache. I-cache is already enabled in start.S */ 383 dcache_enable(); 384 } 385 #endif /* CONFIG_SYS_DCACHE_OFF */ 386