1/* 2 * Copyright (C) 2009 by Sascha Hauer, Pengutronix 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program; if not, write to the Free Software 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 16 * MA 02110-1301, USA. 17 */ 18 19#include <linux/kernel.h> 20#include <linux/init.h> 21#include <linux/list.h> 22#include <linux/clk.h> 23#include <linux/io.h> 24#include <linux/clkdev.h> 25 26#include <mach/clock.h> 27#include <mach/hardware.h> 28#include <mach/common.h> 29 30#include "crmregs-imx3.h" 31 32#ifdef HAVE_SET_RATE_SUPPORT 33static void calc_dividers(u32 div, u32 *pre, u32 *post, u32 maxpost) 34{ 35 u32 min_pre, temp_pre, old_err, err; 36 37 min_pre = (div - 1) / maxpost + 1; 38 old_err = 8; 39 40 for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) { 41 if (div > (temp_pre * maxpost)) 42 break; 43 44 if (div < (temp_pre * temp_pre)) 45 continue; 46 47 err = div % temp_pre; 48 49 if (err == 0) { 50 *pre = temp_pre; 51 break; 52 } 53 54 err = temp_pre - err; 55 56 if (err < old_err) { 57 old_err = err; 58 *pre = temp_pre; 59 } 60 } 61 62 *post = (div + *pre - 1) / *pre; 63} 64 65/* get the best values for a 3-bit divider combined with a 6-bit divider */ 66static void calc_dividers_3_6(u32 div, u32 *pre, u32 *post) 67{ 68 if (div >= 512) { 69 *pre = 8; 70 *post = 64; 71 } else if (div >= 64) { 72 calc_dividers(div, pre, post, 64); 73 } else if (div <= 8) { 74 *pre = div; 75 *post = 1; 76 } else { 77 *pre = 1; 78 *post = div; 79 } 80} 81 82/* get the best values for two cascaded 3-bit dividers */ 83static void calc_dividers_3_3(u32 div, u32 *pre, u32 *post) 84{ 85 if (div >= 64) { 86 *pre = *post = 8; 87 } else if (div > 8) { 88 calc_dividers(div, pre, post, 8); 89 } else { 90 *pre = 1; 91 *post = div; 92 } 93} 94#endif 95 96static unsigned long get_rate_mpll(void) 97{ 98 ulong mpctl = __raw_readl(MX35_CCM_MPCTL); 99 100 return mxc_decode_pll(mpctl, 24000000); 101} 102 103static unsigned long get_rate_ppll(void) 104{ 105 ulong ppctl = __raw_readl(MX35_CCM_PPCTL); 106 107 return mxc_decode_pll(ppctl, 24000000); 108} 109 110struct arm_ahb_div { 111 unsigned char arm, ahb, sel; 112}; 113 114static struct arm_ahb_div clk_consumer[] = { 115 { .arm = 1, .ahb = 4, .sel = 0}, 116 { .arm = 1, .ahb = 3, .sel = 1}, 117 { .arm = 2, .ahb = 2, .sel = 0}, 118 { .arm = 0, .ahb = 0, .sel = 0}, 119 { .arm = 0, .ahb = 0, .sel = 0}, 120 { .arm = 0, .ahb = 0, .sel = 0}, 121 { .arm = 4, .ahb = 1, .sel = 0}, 122 { .arm = 1, .ahb = 5, .sel = 0}, 123 { .arm = 1, .ahb = 8, .sel = 0}, 124 { .arm = 1, .ahb = 6, .sel = 1}, 125 { .arm = 2, .ahb = 4, .sel = 0}, 126 { .arm = 0, .ahb = 0, .sel = 0}, 127 { .arm = 0, .ahb = 0, .sel = 0}, 128 { .arm = 0, .ahb = 0, .sel = 0}, 129 { .arm = 4, .ahb = 2, .sel = 0}, 130 { .arm = 0, .ahb = 0, .sel = 0}, 131}; 132 133static unsigned long get_rate_arm(void) 134{ 135 unsigned long pdr0 = __raw_readl(MXC_CCM_PDR0); 136 struct arm_ahb_div *aad; 137 unsigned long fref = get_rate_mpll(); 138 139 aad = &clk_consumer[(pdr0 >> 16) & 0xf]; 140 if (aad->sel) 141 fref = fref * 3 / 4; 142 143 return fref / aad->arm; 144} 145 146static unsigned long get_rate_ahb(struct clk *clk) 147{ 148 unsigned long pdr0 = __raw_readl(MXC_CCM_PDR0); 149 struct arm_ahb_div *aad; 150 unsigned long fref = get_rate_arm(); 151 152 aad = &clk_consumer[(pdr0 >> 16) & 0xf]; 153 154 return fref / aad->ahb; 155} 156 157static unsigned long get_rate_ipg(struct clk *clk) 158{ 159 return get_rate_ahb(NULL) >> 1; 160} 161 162static unsigned long get_rate_uart(struct clk *clk) 163{ 164 unsigned long pdr3 = __raw_readl(MX35_CCM_PDR3); 165 unsigned long pdr4 = __raw_readl(MX35_CCM_PDR4); 166 unsigned long div = ((pdr4 >> 10) & 0x3f) + 1; 167 168 if (pdr3 & (1 << 14)) 169 return get_rate_arm() / div; 170 else 171 return get_rate_ppll() / div; 172} 173 174static unsigned long get_rate_sdhc(struct clk *clk) 175{ 176 unsigned long pdr3 = __raw_readl(MX35_CCM_PDR3); 177 unsigned long div, rate; 178 179 if (pdr3 & (1 << 6)) 180 rate = get_rate_arm(); 181 else 182 rate = get_rate_ppll(); 183 184 switch (clk->id) { 185 default: 186 case 0: 187 div = pdr3 & 0x3f; 188 break; 189 case 1: 190 div = (pdr3 >> 8) & 0x3f; 191 break; 192 case 2: 193 div = (pdr3 >> 16) & 0x3f; 194 break; 195 } 196 197 return rate / (div + 1); 198} 199 200static unsigned long get_rate_mshc(struct clk *clk) 201{ 202 unsigned long pdr1 = __raw_readl(MXC_CCM_PDR1); 203 unsigned long div1, div2, rate; 204 205 if (pdr1 & (1 << 7)) 206 rate = get_rate_arm(); 207 else 208 rate = get_rate_ppll(); 209 210 div1 = (pdr1 >> 29) & 0x7; 211 div2 = (pdr1 >> 22) & 0x3f; 212 213 return rate / ((div1 + 1) * (div2 + 1)); 214} 215 216static unsigned long get_rate_ssi(struct clk *clk) 217{ 218 unsigned long pdr2 = __raw_readl(MX35_CCM_PDR2); 219 unsigned long div1, div2, rate; 220 221 if (pdr2 & (1 << 6)) 222 rate = get_rate_arm(); 223 else 224 rate = get_rate_ppll(); 225 226 switch (clk->id) { 227 default: 228 case 0: 229 div1 = pdr2 & 0x3f; 230 div2 = (pdr2 >> 24) & 0x7; 231 break; 232 case 1: 233 div1 = (pdr2 >> 8) & 0x3f; 234 div2 = (pdr2 >> 27) & 0x7; 235 break; 236 } 237 238 return rate / ((div1 + 1) * (div2 + 1)); 239} 240 241static unsigned long get_rate_csi(struct clk *clk) 242{ 243 unsigned long pdr2 = __raw_readl(MX35_CCM_PDR2); 244 unsigned long rate; 245 246 if (pdr2 & (1 << 7)) 247 rate = get_rate_arm(); 248 else 249 rate = get_rate_ppll(); 250 251 return rate / (((pdr2 >> 16) & 0x3f) + 1); 252} 253 254static unsigned long get_rate_otg(struct clk *clk) 255{ 256 unsigned long pdr4 = __raw_readl(MX35_CCM_PDR4); 257 unsigned long rate; 258 259 if (pdr4 & (1 << 9)) 260 rate = get_rate_arm(); 261 else 262 rate = get_rate_ppll(); 263 264 return rate / (((pdr4 >> 22) & 0x3f) + 1); 265} 266 267static unsigned long get_rate_ipg_per(struct clk *clk) 268{ 269 unsigned long pdr0 = __raw_readl(MXC_CCM_PDR0); 270 unsigned long pdr4 = __raw_readl(MX35_CCM_PDR4); 271 unsigned long div; 272 273 if (pdr0 & (1 << 26)) { 274 div = (pdr4 >> 16) & 0x3f; 275 return get_rate_arm() / (div + 1); 276 } else { 277 div = (pdr0 >> 12) & 0x7; 278 return get_rate_ahb(NULL) / (div + 1); 279 } 280} 281 282static unsigned long get_rate_hsp(struct clk *clk) 283{ 284 unsigned long hsp_podf = (__raw_readl(MXC_CCM_PDR0) >> 20) & 0x03; 285 unsigned long fref = get_rate_mpll(); 286 287 if (fref > 400 * 1000 * 1000) { 288 switch (hsp_podf) { 289 case 0: 290 return fref >> 2; 291 case 1: 292 return fref >> 3; 293 case 2: 294 return fref / 3; 295 } 296 } else { 297 switch (hsp_podf) { 298 case 0: 299 case 2: 300 return fref / 3; 301 case 1: 302 return fref / 6; 303 } 304 } 305 306 return 0; 307} 308 309static int clk_cgr_enable(struct clk *clk) 310{ 311 u32 reg; 312 313 reg = __raw_readl(clk->enable_reg); 314 reg |= 3 << clk->enable_shift; 315 __raw_writel(reg, clk->enable_reg); 316 317 return 0; 318} 319 320static void clk_cgr_disable(struct clk *clk) 321{ 322 u32 reg; 323 324 reg = __raw_readl(clk->enable_reg); 325 reg &= ~(3 << clk->enable_shift); 326 __raw_writel(reg, clk->enable_reg); 327} 328 329#define DEFINE_CLOCK(name, i, er, es, gr, sr) \ 330 static struct clk name = { \ 331 .id = i, \ 332 .enable_reg = er, \ 333 .enable_shift = es, \ 334 .get_rate = gr, \ 335 .set_rate = sr, \ 336 .enable = clk_cgr_enable, \ 337 .disable = clk_cgr_disable, \ 338 } 339 340DEFINE_CLOCK(asrc_clk, 0, MX35_CCM_CGR0, 0, NULL, NULL); 341DEFINE_CLOCK(pata_clk, 0, MX35_CCM_CGR0, 2, get_rate_ipg, NULL); 342/* DEFINE_CLOCK(audmux_clk, 0, MX35_CCM_CGR0, 4, NULL, NULL); */ 343DEFINE_CLOCK(can1_clk, 0, MX35_CCM_CGR0, 6, get_rate_ipg, NULL); 344DEFINE_CLOCK(can2_clk, 1, MX35_CCM_CGR0, 8, get_rate_ipg, NULL); 345DEFINE_CLOCK(cspi1_clk, 0, MX35_CCM_CGR0, 10, get_rate_ipg, NULL); 346DEFINE_CLOCK(cspi2_clk, 1, MX35_CCM_CGR0, 12, get_rate_ipg, NULL); 347DEFINE_CLOCK(ect_clk, 0, MX35_CCM_CGR0, 14, get_rate_ipg, NULL); 348DEFINE_CLOCK(edio_clk, 0, MX35_CCM_CGR0, 16, NULL, NULL); 349DEFINE_CLOCK(emi_clk, 0, MX35_CCM_CGR0, 18, get_rate_ipg, NULL); 350DEFINE_CLOCK(epit1_clk, 0, MX35_CCM_CGR0, 20, get_rate_ipg, NULL); 351DEFINE_CLOCK(epit2_clk, 1, MX35_CCM_CGR0, 22, get_rate_ipg, NULL); 352DEFINE_CLOCK(esai_clk, 0, MX35_CCM_CGR0, 24, NULL, NULL); 353DEFINE_CLOCK(esdhc1_clk, 0, MX35_CCM_CGR0, 26, get_rate_sdhc, NULL); 354DEFINE_CLOCK(esdhc2_clk, 1, MX35_CCM_CGR0, 28, get_rate_sdhc, NULL); 355DEFINE_CLOCK(esdhc3_clk, 2, MX35_CCM_CGR0, 30, get_rate_sdhc, NULL); 356 357DEFINE_CLOCK(fec_clk, 0, MX35_CCM_CGR1, 0, get_rate_ipg, NULL); 358DEFINE_CLOCK(gpio1_clk, 0, MX35_CCM_CGR1, 2, NULL, NULL); 359DEFINE_CLOCK(gpio2_clk, 1, MX35_CCM_CGR1, 4, NULL, NULL); 360DEFINE_CLOCK(gpio3_clk, 2, MX35_CCM_CGR1, 6, NULL, NULL); 361DEFINE_CLOCK(gpt_clk, 0, MX35_CCM_CGR1, 8, get_rate_ipg, NULL); 362DEFINE_CLOCK(i2c1_clk, 0, MX35_CCM_CGR1, 10, get_rate_ipg_per, NULL); 363DEFINE_CLOCK(i2c2_clk, 1, MX35_CCM_CGR1, 12, get_rate_ipg_per, NULL); 364DEFINE_CLOCK(i2c3_clk, 2, MX35_CCM_CGR1, 14, get_rate_ipg_per, NULL); 365DEFINE_CLOCK(iomuxc_clk, 0, MX35_CCM_CGR1, 16, NULL, NULL); 366DEFINE_CLOCK(ipu_clk, 0, MX35_CCM_CGR1, 18, get_rate_hsp, NULL); 367DEFINE_CLOCK(kpp_clk, 0, MX35_CCM_CGR1, 20, get_rate_ipg, NULL); 368DEFINE_CLOCK(mlb_clk, 0, MX35_CCM_CGR1, 22, get_rate_ahb, NULL); 369DEFINE_CLOCK(mshc_clk, 0, MX35_CCM_CGR1, 24, get_rate_mshc, NULL); 370DEFINE_CLOCK(owire_clk, 0, MX35_CCM_CGR1, 26, get_rate_ipg_per, NULL); 371DEFINE_CLOCK(pwm_clk, 0, MX35_CCM_CGR1, 28, get_rate_ipg_per, NULL); 372DEFINE_CLOCK(rngc_clk, 0, MX35_CCM_CGR1, 30, get_rate_ipg, NULL); 373 374DEFINE_CLOCK(rtc_clk, 0, MX35_CCM_CGR2, 0, get_rate_ipg, NULL); 375DEFINE_CLOCK(rtic_clk, 0, MX35_CCM_CGR2, 2, get_rate_ahb, NULL); 376DEFINE_CLOCK(scc_clk, 0, MX35_CCM_CGR2, 4, get_rate_ipg, NULL); 377DEFINE_CLOCK(sdma_clk, 0, MX35_CCM_CGR2, 6, NULL, NULL); 378DEFINE_CLOCK(spba_clk, 0, MX35_CCM_CGR2, 8, get_rate_ipg, NULL); 379DEFINE_CLOCK(spdif_clk, 0, MX35_CCM_CGR2, 10, NULL, NULL); 380DEFINE_CLOCK(ssi1_clk, 0, MX35_CCM_CGR2, 12, get_rate_ssi, NULL); 381DEFINE_CLOCK(ssi2_clk, 1, MX35_CCM_CGR2, 14, get_rate_ssi, NULL); 382DEFINE_CLOCK(uart1_clk, 0, MX35_CCM_CGR2, 16, get_rate_uart, NULL); 383DEFINE_CLOCK(uart2_clk, 1, MX35_CCM_CGR2, 18, get_rate_uart, NULL); 384DEFINE_CLOCK(uart3_clk, 2, MX35_CCM_CGR2, 20, get_rate_uart, NULL); 385DEFINE_CLOCK(usbotg_clk, 0, MX35_CCM_CGR2, 22, get_rate_otg, NULL); 386DEFINE_CLOCK(wdog_clk, 0, MX35_CCM_CGR2, 24, NULL, NULL); 387DEFINE_CLOCK(max_clk, 0, MX35_CCM_CGR2, 26, NULL, NULL); 388DEFINE_CLOCK(audmux_clk, 0, MX35_CCM_CGR2, 30, NULL, NULL); 389 390DEFINE_CLOCK(csi_clk, 0, MX35_CCM_CGR3, 0, get_rate_csi, NULL); 391DEFINE_CLOCK(iim_clk, 0, MX35_CCM_CGR3, 2, NULL, NULL); 392DEFINE_CLOCK(gpu2d_clk, 0, MX35_CCM_CGR3, 4, NULL, NULL); 393 394DEFINE_CLOCK(usbahb_clk, 0, 0, 0, get_rate_ahb, NULL); 395 396static int clk_dummy_enable(struct clk *clk) 397{ 398 return 0; 399} 400 401static void clk_dummy_disable(struct clk *clk) 402{ 403} 404 405static unsigned long get_rate_nfc(struct clk *clk) 406{ 407 unsigned long div1; 408 409 div1 = (__raw_readl(MX35_CCM_PDR4) >> 28) + 1; 410 411 return get_rate_ahb(NULL) / div1; 412} 413 414/* NAND Controller: It seems it can't be disabled */ 415static struct clk nfc_clk = { 416 .id = 0, 417 .enable_reg = 0, 418 .enable_shift = 0, 419 .get_rate = get_rate_nfc, 420 .set_rate = NULL, /* set_rate_nfc, */ 421 .enable = clk_dummy_enable, 422 .disable = clk_dummy_disable 423}; 424 425#define _REGISTER_CLOCK(d, n, c) \ 426 { \ 427 .dev_id = d, \ 428 .con_id = n, \ 429 .clk = &c, \ 430 }, 431 432static struct clk_lookup lookups[] = { 433 _REGISTER_CLOCK(NULL, "asrc", asrc_clk) 434 _REGISTER_CLOCK("pata_imx", NULL, pata_clk) 435 _REGISTER_CLOCK("flexcan.0", NULL, can1_clk) 436 _REGISTER_CLOCK("flexcan.1", NULL, can2_clk) 437 _REGISTER_CLOCK("imx35-cspi.0", NULL, cspi1_clk) 438 _REGISTER_CLOCK("imx35-cspi.1", NULL, cspi2_clk) 439 _REGISTER_CLOCK(NULL, "ect", ect_clk) 440 _REGISTER_CLOCK(NULL, "edio", edio_clk) 441 _REGISTER_CLOCK(NULL, "emi", emi_clk) 442 _REGISTER_CLOCK("imx-epit.0", NULL, epit1_clk) 443 _REGISTER_CLOCK("imx-epit.1", NULL, epit2_clk) 444 _REGISTER_CLOCK(NULL, "esai", esai_clk) 445 _REGISTER_CLOCK("sdhci-esdhc-imx35.0", NULL, esdhc1_clk) 446 _REGISTER_CLOCK("sdhci-esdhc-imx35.1", NULL, esdhc2_clk) 447 _REGISTER_CLOCK("sdhci-esdhc-imx35.2", NULL, esdhc3_clk) 448 /* i.mx35 has the i.mx27 type fec */ 449 _REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk) 450 _REGISTER_CLOCK(NULL, "gpio", gpio1_clk) 451 _REGISTER_CLOCK(NULL, "gpio", gpio2_clk) 452 _REGISTER_CLOCK(NULL, "gpio", gpio3_clk) 453 _REGISTER_CLOCK("gpt.0", NULL, gpt_clk) 454 _REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk) 455 _REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk) 456 _REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk) 457 _REGISTER_CLOCK(NULL, "iomuxc", iomuxc_clk) 458 _REGISTER_CLOCK("ipu-core", NULL, ipu_clk) 459 _REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk) 460 _REGISTER_CLOCK(NULL, "kpp", kpp_clk) 461 _REGISTER_CLOCK(NULL, "mlb", mlb_clk) 462 _REGISTER_CLOCK(NULL, "mshc", mshc_clk) 463 _REGISTER_CLOCK("mxc_w1", NULL, owire_clk) 464 _REGISTER_CLOCK(NULL, "pwm", pwm_clk) 465 _REGISTER_CLOCK(NULL, "rngc", rngc_clk) 466 _REGISTER_CLOCK(NULL, "rtc", rtc_clk) 467 _REGISTER_CLOCK(NULL, "rtic", rtic_clk) 468 _REGISTER_CLOCK(NULL, "scc", scc_clk) 469 _REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk) 470 _REGISTER_CLOCK(NULL, "spba", spba_clk) 471 _REGISTER_CLOCK(NULL, "spdif", spdif_clk) 472 _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk) 473 _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk) 474 /* i.mx35 has the i.mx21 type uart */ 475 _REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk) 476 _REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk) 477 _REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk) 478 _REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk) 479 _REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk) 480 _REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk) 481 _REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk) 482 _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usbahb_clk) 483 _REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk) 484 _REGISTER_CLOCK(NULL, "max", max_clk) 485 _REGISTER_CLOCK(NULL, "audmux", audmux_clk) 486 _REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk) 487 _REGISTER_CLOCK(NULL, "iim", iim_clk) 488 _REGISTER_CLOCK(NULL, "gpu2d", gpu2d_clk) 489 _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) 490}; 491 492int __init mx35_clocks_init() 493{ 494 unsigned int cgr2 = 3 << 26; 495 496#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC) 497 cgr2 |= 3 << 16; 498#endif 499 500 clkdev_add_table(lookups, ARRAY_SIZE(lookups)); 501 502 /* Turn off all clocks except the ones we need to survive, namely: 503 * EMI, GPIO1/2/3, GPT, IOMUX, MAX and eventually uart 504 */ 505 __raw_writel((3 << 18), MX35_CCM_CGR0); 506 __raw_writel((3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 16), 507 MX35_CCM_CGR1); 508 __raw_writel(cgr2, MX35_CCM_CGR2); 509 __raw_writel(0, MX35_CCM_CGR3); 510 511 clk_enable(&iim_clk); 512 imx_print_silicon_rev("i.MX35", mx35_revision()); 513 clk_disable(&iim_clk); 514 515 /* 516 * Check if we came up in internal boot mode. If yes, we need some 517 * extra clocks turned on, otherwise the MX35 boot ROM code will 518 * hang after a watchdog reset. 519 */ 520 if (!(__raw_readl(MX35_CCM_RCSR) & (3 << 10))) { 521 /* Additionally turn on UART1, SCC, and IIM clocks */ 522 clk_enable(&iim_clk); 523 clk_enable(&uart1_clk); 524 clk_enable(&scc_clk); 525 } 526 527#ifdef CONFIG_MXC_USE_EPIT 528 epit_timer_init(&epit1_clk, 529 MX35_IO_ADDRESS(MX35_EPIT1_BASE_ADDR), MX35_INT_EPIT1); 530#else 531 mxc_timer_init(&gpt_clk, 532 MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT); 533#endif 534 535 return 0; 536} 537