1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2008 Eric Jarrige <eric.jarrige@armadeus.org> 4 * Copyright (c) 2009 Ilya Yanok <yanok@emcraft.com> 5 */ 6 7 #include <common.h> 8 #include <div64.h> 9 #include <netdev.h> 10 #include <asm/io.h> 11 #include <asm/arch/imx-regs.h> 12 #include <asm/arch/clock.h> 13 #include <asm/arch/gpio.h> 14 #include <asm/mach-imx/sys_proto.h> 15 #ifdef CONFIG_MMC_MXC 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 u32 get_cpu_rev(void) 163 { 164 return MXC_CPU_MX27 << 12; 165 } 166 167 #if defined(CONFIG_DISPLAY_CPUINFO) 168 int print_cpuinfo (void) 169 { 170 char buf[32]; 171 172 printf("CPU: Freescale i.MX27 at %s MHz\n\n", 173 strmhz(buf, imx_get_mpllclk())); 174 return 0; 175 } 176 #endif 177 178 int cpu_eth_init(bd_t *bis) 179 { 180 #if defined(CONFIG_FEC_MXC) 181 struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; 182 183 /* enable FEC clock */ 184 writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); 185 writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0); 186 return fecmxc_initialize(bis); 187 #else 188 return 0; 189 #endif 190 } 191 192 /* 193 * Initializes on-chip MMC controllers. 194 * to override, implement board_mmc_init() 195 */ 196 int cpu_mmc_init(bd_t *bis) 197 { 198 #ifdef CONFIG_MMC_MXC 199 return mxc_mmc_init(bis); 200 #else 201 return 0; 202 #endif 203 } 204 205 void imx_gpio_mode(int gpio_mode) 206 { 207 struct gpio_port_regs *regs = (struct gpio_port_regs *)IMX_GPIO_BASE; 208 unsigned int pin = gpio_mode & GPIO_PIN_MASK; 209 unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; 210 unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT; 211 unsigned int aout = (gpio_mode & GPIO_AOUT_MASK) >> GPIO_AOUT_SHIFT; 212 unsigned int bout = (gpio_mode & GPIO_BOUT_MASK) >> GPIO_BOUT_SHIFT; 213 unsigned int tmp; 214 215 /* Pullup enable */ 216 if (gpio_mode & GPIO_PUEN) { 217 writel(readl(®s->port[port].puen) | (1 << pin), 218 ®s->port[port].puen); 219 } else { 220 writel(readl(®s->port[port].puen) & ~(1 << pin), 221 ®s->port[port].puen); 222 } 223 224 /* Data direction */ 225 if (gpio_mode & GPIO_OUT) { 226 writel(readl(®s->port[port].gpio_dir) | 1 << pin, 227 ®s->port[port].gpio_dir); 228 } else { 229 writel(readl(®s->port[port].gpio_dir) & ~(1 << pin), 230 ®s->port[port].gpio_dir); 231 } 232 233 /* Primary / alternate function */ 234 if (gpio_mode & GPIO_AF) { 235 writel(readl(®s->port[port].gpr) | (1 << pin), 236 ®s->port[port].gpr); 237 } else { 238 writel(readl(®s->port[port].gpr) & ~(1 << pin), 239 ®s->port[port].gpr); 240 } 241 242 /* use as gpio? */ 243 if (!(gpio_mode & (GPIO_PF | GPIO_AF))) { 244 writel(readl(®s->port[port].gius) | (1 << pin), 245 ®s->port[port].gius); 246 } else { 247 writel(readl(®s->port[port].gius) & ~(1 << pin), 248 ®s->port[port].gius); 249 } 250 251 /* Output / input configuration */ 252 if (pin < 16) { 253 tmp = readl(®s->port[port].ocr1); 254 tmp &= ~(3 << (pin * 2)); 255 tmp |= (ocr << (pin * 2)); 256 writel(tmp, ®s->port[port].ocr1); 257 258 writel(readl(®s->port[port].iconfa1) & ~(3 << (pin * 2)), 259 ®s->port[port].iconfa1); 260 writel(readl(®s->port[port].iconfa1) | aout << (pin * 2), 261 ®s->port[port].iconfa1); 262 writel(readl(®s->port[port].iconfb1) & ~(3 << (pin * 2)), 263 ®s->port[port].iconfb1); 264 writel(readl(®s->port[port].iconfb1) | bout << (pin * 2), 265 ®s->port[port].iconfb1); 266 } else { 267 pin -= 16; 268 269 tmp = readl(®s->port[port].ocr2); 270 tmp &= ~(3 << (pin * 2)); 271 tmp |= (ocr << (pin * 2)); 272 writel(tmp, ®s->port[port].ocr2); 273 274 writel(readl(®s->port[port].iconfa2) & ~(3 << (pin * 2)), 275 ®s->port[port].iconfa2); 276 writel(readl(®s->port[port].iconfa2) | aout << (pin * 2), 277 ®s->port[port].iconfa2); 278 writel(readl(®s->port[port].iconfb2) & ~(3 << (pin * 2)), 279 ®s->port[port].iconfb2); 280 writel(readl(®s->port[port].iconfb2) | bout << (pin * 2), 281 ®s->port[port].iconfb2); 282 } 283 } 284 285 #ifdef CONFIG_MXC_UART 286 void mx27_uart1_init_pins(void) 287 { 288 int i; 289 unsigned int mode[] = { 290 PE12_PF_UART1_TXD, 291 PE13_PF_UART1_RXD, 292 }; 293 294 for (i = 0; i < ARRAY_SIZE(mode); i++) 295 imx_gpio_mode(mode[i]); 296 297 } 298 #endif /* CONFIG_MXC_UART */ 299 300 #ifdef CONFIG_FEC_MXC 301 void mx27_fec_init_pins(void) 302 { 303 int i; 304 unsigned int mode[] = { 305 PD0_AIN_FEC_TXD0, 306 PD1_AIN_FEC_TXD1, 307 PD2_AIN_FEC_TXD2, 308 PD3_AIN_FEC_TXD3, 309 PD4_AOUT_FEC_RX_ER, 310 PD5_AOUT_FEC_RXD1, 311 PD6_AOUT_FEC_RXD2, 312 PD7_AOUT_FEC_RXD3, 313 PD8_AF_FEC_MDIO, 314 PD9_AIN_FEC_MDC | GPIO_PUEN, 315 PD10_AOUT_FEC_CRS, 316 PD11_AOUT_FEC_TX_CLK, 317 PD12_AOUT_FEC_RXD0, 318 PD13_AOUT_FEC_RX_DV, 319 PD14_AOUT_FEC_CLR, 320 PD15_AOUT_FEC_COL, 321 PD16_AIN_FEC_TX_ER, 322 PF23_AIN_FEC_TX_EN, 323 }; 324 325 for (i = 0; i < ARRAY_SIZE(mode); i++) 326 imx_gpio_mode(mode[i]); 327 } 328 329 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) 330 { 331 int i; 332 struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; 333 struct fuse_bank *bank = &iim->bank[0]; 334 struct fuse_bank0_regs *fuse = 335 (struct fuse_bank0_regs *)bank->fuse_regs; 336 337 for (i = 0; i < 6; i++) 338 mac[6 - 1 - i] = readl(&fuse->mac_addr[i]) & 0xff; 339 } 340 #endif /* CONFIG_FEC_MXC */ 341 342 #ifdef CONFIG_MMC_MXC 343 void mx27_sd1_init_pins(void) 344 { 345 int i; 346 unsigned int mode[] = { 347 PE18_PF_SD1_D0, 348 PE19_PF_SD1_D1, 349 PE20_PF_SD1_D2, 350 PE21_PF_SD1_D3, 351 PE22_PF_SD1_CMD, 352 PE23_PF_SD1_CLK, 353 }; 354 355 for (i = 0; i < ARRAY_SIZE(mode); i++) 356 imx_gpio_mode(mode[i]); 357 358 } 359 360 void mx27_sd2_init_pins(void) 361 { 362 int i; 363 unsigned int mode[] = { 364 PB4_PF_SD2_D0, 365 PB5_PF_SD2_D1, 366 PB6_PF_SD2_D2, 367 PB7_PF_SD2_D3, 368 PB8_PF_SD2_CMD, 369 PB9_PF_SD2_CLK, 370 }; 371 372 for (i = 0; i < ARRAY_SIZE(mode); i++) 373 imx_gpio_mode(mode[i]); 374 375 } 376 #endif /* CONFIG_MMC_MXC */ 377