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