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