1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2016 Nelson Integration, LLC 4 * Author: Eric Nelson <eric@nelint.com> 5 */ 6 7 #include <common.h> 8 #include <asm/io.h> 9 #include <asm/arch/iomux.h> 10 #include <asm/arch/clock.h> 11 #include <asm/arch/crm_regs.h> 12 #include <asm/arch/mx6-ddr.h> 13 #include <asm/arch/mx6-pins.h> 14 #include <asm/arch/sys_proto.h> 15 #include <spl.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ 20 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ 21 PAD_CTL_SRE_FAST | PAD_CTL_HYS) 22 23 static iomux_v3_cfg_t const uart_pads[] = { 24 #ifdef CONFIG_UART2_EIM_D26_27 25 IOMUX_PADS(PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), 26 IOMUX_PADS(PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), 27 #elif defined(CONFIG_UART1_CSI0_DAT10_11) 28 IOMUX_PADS(PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), 29 IOMUX_PADS(PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), 30 #elif defined(CONFIG_UART1_SD3_DAT6_7) 31 IOMUX_PADS(PAD_SD3_DAT6__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), 32 IOMUX_PADS(PAD_SD3_DAT7__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)), 33 #elif defined(CONFIG_UART1_UART1) 34 MX6_PAD_UART1_TXD__UART1_TXD | MUX_PAD_CTRL(UART_PAD_CTRL), 35 MX6_PAD_UART1_RXD__UART1_RXD | MUX_PAD_CTRL(UART_PAD_CTRL), 36 #else 37 #error select UART console pads 38 #endif 39 }; 40 41 #ifdef CONFIG_DDR3 42 #define GRP_DDRTYPE 0x000C0000 43 #else 44 #define GRP_DDRTYPE 0x00080000 45 #endif 46 47 /* all existing designs have this disabled */ 48 #define DDR_PKE 0 49 50 /* use Kconfig for ODT and DRIVE_STRENGTH */ 51 #define DDR_ODT \ 52 (CONFIG_DDR_ODT << 8) 53 #define DRAM_DRIVE_STRENGTH \ 54 (CONFIG_DRAM_DRIVE_STRENGTH << 3) 55 56 /* configure MX6Q/DUAL mmdc DDR io registers */ 57 static struct mx6dq_iomux_ddr_regs const mx6dq_ddr_ioregs = { 58 /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */ 59 .dram_sdclk_0 = DDR_ODT + DRAM_DRIVE_STRENGTH, 60 .dram_sdclk_1 = DDR_ODT + DRAM_DRIVE_STRENGTH, 61 .dram_cas = DDR_ODT + DRAM_DRIVE_STRENGTH, 62 .dram_ras = DDR_ODT + DRAM_DRIVE_STRENGTH, 63 .dram_reset = DDR_ODT + DRAM_DRIVE_STRENGTH, 64 /* SDCKE[0:1]: 100k pull-up */ 65 .dram_sdcke0 = 0x00003000, 66 .dram_sdcke1 = 0x00003000, 67 /* SDBA2: pull-up disabled */ 68 .dram_sdba2 = 0x00000000, 69 /* SDODT[0:1]: 100k pull-up, 40 ohm */ 70 .dram_sdodt0 = 0x00003000 + DRAM_DRIVE_STRENGTH, 71 .dram_sdodt1 = 0x00003000 + DRAM_DRIVE_STRENGTH, 72 /* SDQS[0:7]: Differential input, 40 ohm */ 73 .dram_sdqs0 = DRAM_DRIVE_STRENGTH, 74 .dram_sdqs1 = DRAM_DRIVE_STRENGTH, 75 .dram_sdqs2 = DRAM_DRIVE_STRENGTH, 76 .dram_sdqs3 = DRAM_DRIVE_STRENGTH, 77 .dram_sdqs4 = DRAM_DRIVE_STRENGTH, 78 .dram_sdqs5 = DRAM_DRIVE_STRENGTH, 79 .dram_sdqs6 = DRAM_DRIVE_STRENGTH, 80 .dram_sdqs7 = DRAM_DRIVE_STRENGTH, 81 82 /* DQM[0:7]: Differential input, 40 ohm */ 83 .dram_dqm0 = DDR_ODT + DRAM_DRIVE_STRENGTH, 84 .dram_dqm1 = DDR_ODT + DRAM_DRIVE_STRENGTH, 85 .dram_dqm2 = DDR_ODT + DRAM_DRIVE_STRENGTH, 86 .dram_dqm3 = DDR_ODT + DRAM_DRIVE_STRENGTH, 87 .dram_dqm4 = DDR_ODT + DRAM_DRIVE_STRENGTH, 88 .dram_dqm5 = DDR_ODT + DRAM_DRIVE_STRENGTH, 89 .dram_dqm6 = DDR_ODT + DRAM_DRIVE_STRENGTH, 90 .dram_dqm7 = DDR_ODT + DRAM_DRIVE_STRENGTH, 91 }; 92 93 /* configure MX6Q/DUAL mmdc GRP io registers */ 94 static struct mx6dq_iomux_grp_regs const mx6dq_grp_ioregs = { 95 /* DDR3 */ 96 .grp_ddr_type = GRP_DDRTYPE, 97 .grp_ddrmode_ctl = DDR_ODT, 98 /* disable DDR pullups */ 99 .grp_ddrpke = DDR_PKE, 100 /* ADDR[00:16], SDBA[0:1]: 40 ohm */ 101 .grp_addds = DRAM_DRIVE_STRENGTH, 102 /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */ 103 .grp_ctlds = DRAM_DRIVE_STRENGTH, 104 /* DATA[00:63]: Differential input, 40 ohm */ 105 .grp_ddrmode = DDR_ODT, 106 .grp_b0ds = DRAM_DRIVE_STRENGTH, 107 .grp_b1ds = DRAM_DRIVE_STRENGTH, 108 .grp_b2ds = DRAM_DRIVE_STRENGTH, 109 .grp_b3ds = DRAM_DRIVE_STRENGTH, 110 .grp_b4ds = DRAM_DRIVE_STRENGTH, 111 .grp_b5ds = DRAM_DRIVE_STRENGTH, 112 .grp_b6ds = DRAM_DRIVE_STRENGTH, 113 .grp_b7ds = DRAM_DRIVE_STRENGTH, 114 }; 115 116 static struct mx6sdl_iomux_ddr_regs const mx6sdl_ddr_ioregs = { 117 /* SDCLK[0:1], CAS, RAS, Reset: Differential input, 40ohm */ 118 .dram_sdclk_0 = DDR_ODT + DRAM_DRIVE_STRENGTH, 119 .dram_sdclk_1 = DDR_ODT + DRAM_DRIVE_STRENGTH, 120 .dram_cas = DDR_ODT + DRAM_DRIVE_STRENGTH, 121 .dram_ras = DDR_ODT + DRAM_DRIVE_STRENGTH, 122 .dram_reset = DDR_ODT + DRAM_DRIVE_STRENGTH, 123 /* SDCKE[0:1]: 100k pull-up */ 124 .dram_sdcke0 = 0x00003000, 125 .dram_sdcke1 = 0x00003000, 126 /* SDBA2: pull-up disabled */ 127 .dram_sdba2 = 0x00000000, 128 /* SDODT[0:1]: 100k pull-up, 40 ohm */ 129 .dram_sdodt0 = 0x00003000 + DRAM_DRIVE_STRENGTH, 130 .dram_sdodt1 = 0x00003000 + DRAM_DRIVE_STRENGTH, 131 /* SDQS[0:7]: Differential input, 40 ohm */ 132 .dram_sdqs0 = DRAM_DRIVE_STRENGTH, 133 .dram_sdqs1 = DRAM_DRIVE_STRENGTH, 134 .dram_sdqs2 = DRAM_DRIVE_STRENGTH, 135 .dram_sdqs3 = DRAM_DRIVE_STRENGTH, 136 .dram_sdqs4 = DRAM_DRIVE_STRENGTH, 137 .dram_sdqs5 = DRAM_DRIVE_STRENGTH, 138 .dram_sdqs6 = DRAM_DRIVE_STRENGTH, 139 .dram_sdqs7 = DRAM_DRIVE_STRENGTH, 140 141 /* DQM[0:7]: Differential input, 40 ohm */ 142 .dram_dqm0 = DDR_ODT + DRAM_DRIVE_STRENGTH, 143 .dram_dqm1 = DDR_ODT + DRAM_DRIVE_STRENGTH, 144 .dram_dqm2 = DDR_ODT + DRAM_DRIVE_STRENGTH, 145 .dram_dqm3 = DDR_ODT + DRAM_DRIVE_STRENGTH, 146 .dram_dqm4 = DDR_ODT + DRAM_DRIVE_STRENGTH, 147 .dram_dqm5 = DDR_ODT + DRAM_DRIVE_STRENGTH, 148 .dram_dqm6 = DDR_ODT + DRAM_DRIVE_STRENGTH, 149 .dram_dqm7 = DDR_ODT + DRAM_DRIVE_STRENGTH, 150 }; 151 152 /* configure MX6SOLO/DUALLITE mmdc GRP io registers */ 153 static struct mx6sdl_iomux_grp_regs const mx6sdl_grp_ioregs = { 154 /* DDR3 */ 155 .grp_ddr_type = GRP_DDRTYPE, 156 /* SDQS[0:7]: Differential input, 40 ohm */ 157 .grp_ddrmode_ctl = DDR_ODT, 158 /* disable DDR pullups */ 159 .grp_ddrpke = DDR_PKE, 160 /* ADDR[00:16], SDBA[0:1]: 40 ohm */ 161 .grp_addds = DRAM_DRIVE_STRENGTH, 162 /* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm */ 163 .grp_ctlds = DRAM_DRIVE_STRENGTH, 164 /* DATA[00:63]: Differential input, 40 ohm */ 165 .grp_ddrmode = DDR_ODT, 166 .grp_b0ds = DRAM_DRIVE_STRENGTH, 167 .grp_b1ds = DRAM_DRIVE_STRENGTH, 168 .grp_b2ds = DRAM_DRIVE_STRENGTH, 169 .grp_b3ds = DRAM_DRIVE_STRENGTH, 170 .grp_b4ds = DRAM_DRIVE_STRENGTH, 171 .grp_b5ds = DRAM_DRIVE_STRENGTH, 172 .grp_b6ds = DRAM_DRIVE_STRENGTH, 173 .grp_b7ds = DRAM_DRIVE_STRENGTH, 174 }; 175 176 const struct mx6sl_iomux_ddr_regs mx6sl_ddr_ioregs = { 177 .dram_sdqs0 = DRAM_DRIVE_STRENGTH, 178 .dram_sdqs1 = DRAM_DRIVE_STRENGTH, 179 .dram_sdqs2 = DRAM_DRIVE_STRENGTH, 180 .dram_sdqs3 = DRAM_DRIVE_STRENGTH, 181 .dram_dqm0 = DRAM_DRIVE_STRENGTH, 182 .dram_dqm1 = DRAM_DRIVE_STRENGTH, 183 .dram_dqm2 = DRAM_DRIVE_STRENGTH, 184 .dram_dqm3 = DRAM_DRIVE_STRENGTH, 185 .dram_cas = DRAM_DRIVE_STRENGTH, 186 .dram_ras = DRAM_DRIVE_STRENGTH, 187 .dram_sdclk_0 = DRAM_DRIVE_STRENGTH, 188 .dram_reset = DRAM_DRIVE_STRENGTH, 189 .dram_sdba2 = 0x00020000, 190 .dram_odt0 = 0x00030000 + DRAM_DRIVE_STRENGTH, 191 .dram_odt1 = 0x00030000 + DRAM_DRIVE_STRENGTH, 192 }; 193 194 const struct mx6sl_iomux_grp_regs mx6sl_grp_ioregs = { 195 .grp_b0ds = DRAM_DRIVE_STRENGTH, 196 .grp_b1ds = DRAM_DRIVE_STRENGTH, 197 .grp_b2ds = DRAM_DRIVE_STRENGTH, 198 .grp_b3ds = DRAM_DRIVE_STRENGTH, 199 .grp_addds = DRAM_DRIVE_STRENGTH, 200 .grp_ctlds = DRAM_DRIVE_STRENGTH, 201 .grp_ddrmode_ctl = DDR_ODT, 202 .grp_ddrpke = DDR_PKE, 203 .grp_ddrmode = DDR_ODT, 204 .grp_ddr_type = GRP_DDRTYPE, 205 }; 206 207 static struct mx6_ddr_sysinfo const sysinfo = { 208 /* width of data bus:0=16,1=32,2=64 */ 209 #if CONFIG_DDRWIDTH == 32 210 .dsize = 1, 211 #elif CONFIG_DDRWIDTH == 64 212 .dsize = 2, 213 #else 214 #error missing CONFIG_DDRWIDTH 215 #endif 216 /* config for full 4GB range so that get_mem_size() works */ 217 .cs_density = 32, /* 32Gb per CS */ 218 219 /* # of chip selects */ 220 .ncs = CONFIG_DDRCS, 221 .cs1_mirror = 0, 222 .bi_on = 1, /* Bank interleaving enabled */ 223 .rtt_nom = CONFIG_RTT_NOM, 224 .rtt_wr = CONFIG_RTT_WR, 225 .ralat = CONFIG_RALAT, /* Read additional latency */ 226 .walat = CONFIG_WALAT, /* Write additional latency */ 227 .mif3_mode = 3, /* Command prediction working mode */ 228 #ifdef CONFIG_DDR3 229 .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */ 230 .sde_to_rst = 0x10, /* JEDEC value for LPDDR2 - 200us */ 231 .pd_fast_exit = 0, /* immaterial for calibration */ 232 .ddr_type = DDR_TYPE_DDR3, 233 #else 234 .rst_to_cke = 0x10, /* JEDEC value for LPDDR2: 200us */ 235 .sde_to_rst = 0, /* LPDDR2 does not need this field */ 236 .pd_fast_exit = 0, /* immaterial for calibration */ 237 .ddr_type = DDR_TYPE_LPDDR2, 238 #endif 239 .refsel = CONFIG_REFSEL, 240 .refr = CONFIG_REFR, 241 }; 242 243 #ifdef CONFIG_MT41K512M16TNA 244 /* Micron MT41K512M16TNA-125 */ 245 static struct mx6_ddr3_cfg const ddrtype = { 246 .mem_speed = 1600, 247 .density = 8, 248 .width = 16, 249 .banks = 8, 250 .rowaddr = 15, 251 .coladdr = 10, 252 .pagesz = 1, 253 .trcd = 1375, 254 .trcmin = 5062, 255 .trasmin = 3750, 256 }; 257 #elif defined(CONFIG_MT41K128M16JT) 258 /* Micron MT41K128M16JT-125 */ 259 static struct mx6_ddr3_cfg const ddrtype = { 260 .mem_speed = 1600, 261 .density = 2, 262 .width = 16, 263 .banks = 8, 264 .rowaddr = 14, 265 .coladdr = 10, 266 .pagesz = 2, 267 .trcd = 1375, 268 .trcmin = 4875, 269 .trasmin = 3500, 270 }; 271 #elif defined(CONFIG_H5TQ4G63AFR) 272 /* Hynix H5TQ4G63AFR */ 273 static struct mx6_ddr3_cfg const ddrtype = { 274 .mem_speed = 1600, 275 .density = 4, 276 .width = 16, 277 .banks = 8, 278 .rowaddr = 15, 279 .coladdr = 10, 280 .pagesz = 2, 281 .trcd = 1375, 282 .trcmin = 4875, 283 .trasmin = 3500, 284 }; 285 #elif defined CONFIG_H5TQ2G63DFR 286 /* Hynix H5TQ2G63DFR */ 287 static struct mx6_ddr3_cfg const ddrtype = { 288 .mem_speed = 1333, 289 .density = 2, 290 .width = 16, 291 .banks = 8, 292 .rowaddr = 14, 293 .coladdr = 10, 294 .pagesz = 2, 295 .trcd = 1350, 296 .trcmin = 4950, 297 .trasmin = 3600, 298 }; 299 #elif defined(CONFIG_MT42L256M32D2LG) 300 /* Micron MT42L256M32D2LG */ 301 static struct mx6_lpddr2_cfg ddrtype = { 302 .mem_speed = 800, 303 .density = 4, 304 .width = 32, 305 .banks = 8, 306 .rowaddr = 14, 307 .coladdr = 10, 308 .trcd_lp = 2000, 309 .trppb_lp = 2000, 310 .trpab_lp = 2250, 311 .trasmin = 4200, 312 }; 313 #elif defined(CONFIG_MT29PZZZ4D4BKESK) 314 /* Micron MT29PZZZ4D4BKESK */ 315 static struct mx6_lpddr2_cfg ddrtype = { 316 .mem_speed = 800, 317 .density = 4, 318 .width = 32, 319 .banks = 8, 320 .rowaddr = 14, 321 .coladdr = 10, 322 .trcd_lp = 2000, 323 .trppb_lp = 2000, 324 .trpab_lp = 2250, 325 .trasmin = 4200, 326 }; 327 #else 328 #error please select DDR type using menuconfig 329 #endif 330 331 static void ccgr_init(void) 332 { 333 struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; 334 335 /* FIXME: these should probably be checked, especially 336 * for i.MX6SL, UL, ULL 337 */ 338 writel(0x00C03F3F, &ccm->CCGR0); 339 writel(0x0030FC03, &ccm->CCGR1); 340 writel(0x0FFFC000, &ccm->CCGR2); 341 writel(0x3FF00000, &ccm->CCGR3); 342 writel(0x00FFF300, &ccm->CCGR4); 343 writel(0x0F0000C3, &ccm->CCGR5); 344 writel(0x000003FF, &ccm->CCGR6); 345 } 346 347 static void display_calibration(struct mx6_mmdc_calibration *calib) 348 { 349 printf(".p0_mpdgctrl0\t= 0x%08X\n", calib->p0_mpdgctrl0); 350 printf(".p0_mpdgctrl1\t= 0x%08X\n", calib->p0_mpdgctrl1); 351 printf(".p0_mprddlctl\t= 0x%08X\n", calib->p0_mprddlctl); 352 printf(".p0_mpwrdlctl\t= 0x%08X\n", calib->p0_mpwrdlctl); 353 printf(".p0_mpwldectrl0\t= 0x%08X\n", calib->p0_mpwldectrl0); 354 printf(".p0_mpwldectrl1\t= 0x%08X\n", calib->p0_mpwldectrl1); 355 if (sysinfo.dsize == 2) { 356 printf(".p1_mpdgctrl0\t= 0x%08X\n", calib->p1_mpdgctrl0); 357 printf(".p1_mpdgctrl1\t= 0x%08X\n", calib->p1_mpdgctrl1); 358 printf(".p1_mprddlctl\t= 0x%08X\n", calib->p1_mprddlctl); 359 printf(".p1_mpwrdlctl\t= 0x%08X\n", calib->p1_mpwrdlctl); 360 printf(".p1_mpwldectrl0\t= 0x%08X\n", calib->p1_mpwldectrl0); 361 printf(".p1_mpwldectrl1\t= 0x%08X\n", calib->p1_mpwldectrl1); 362 } 363 #ifdef CONFIG_IMXIMAGE_OUTPUT 364 printf("DATA 4 MX6_MMDC_P0_MPDGCTRL0\t= 0x%08X\n", calib->p0_mpdgctrl0); 365 printf("DATA 4 MX6_MMDC_P0_MPDGCTRL1\t= 0x%08X\n", calib->p0_mpdgctrl1); 366 printf("DATA 4 MX6_MMDC_P0_MPRDDLCTL\t= 0x%08X\n", calib->p0_mprddlctl); 367 printf("DATA 4 MX6_MMDC_P0_MPWRDLCTL\t= 0x%08X\n", calib->p0_mpwrdlctl); 368 printf("DATA 4 MX6_MMDC_P0_MPWLDECTRL0\t= 0x%08X\n", 369 calib->p0_mpwldectrl0); 370 printf("DATA 4 MX6_MMDC_P0_MPWLDECTRL1\t= 0x%08X\n", 371 calib->p0_mpwldectrl1); 372 if (sysinfo.dsize == 2) { 373 printf("DATA 4 MX6_MMDC_P1_MPDGCTRL0\t= 0x%08X\n", 374 calib->p1_mpdgctrl0); 375 printf("DATA 4 MX6_MMDC_P1_MPDGCTRL1\t= 0x%08X\n", 376 calib->p1_mpdgctrl1); 377 printf("DATA 4 MX6_MMDC_P1_MPRDDLCTL\t= 0x%08X\n", 378 calib->p1_mprddlctl); 379 printf("DATA 4 MX6_MMDC_P1_MPWRDLCTL\t= 0x%08X\n", 380 calib->p1_mpwrdlctl); 381 printf("DATA 4 MX6_MMDC_P1_MPWLDECTRL0\t= 0x%08X\n", 382 calib->p1_mpwldectrl0); 383 printf("DATA 4 MX6_MMDC_P1_MPWLDECTRL1\t= 0x%08X\n", 384 calib->p1_mpwldectrl1); 385 } 386 #endif 387 } 388 389 /* 390 * called from C runtime startup code (arch/arm/lib/crt0.S:_main) 391 * - we have a stack and a place to store GD, both in SRAM 392 * - no variable global data is available 393 */ 394 void board_init_f(ulong dummy) 395 { 396 int errs; 397 struct mx6_mmdc_calibration calibration = {0}; 398 399 memset((void *)gd, 0, sizeof(struct global_data)); 400 401 /* write leveling calibration defaults */ 402 calibration.p0_mpwrdlctl = 0x40404040; 403 calibration.p1_mpwrdlctl = 0x40404040; 404 405 /* setup AIPS and disable watchdog */ 406 arch_cpu_init(); 407 408 ccgr_init(); 409 410 SETUP_IOMUX_PADS(uart_pads); 411 412 /* setup GP timer */ 413 timer_init(); 414 415 /* UART clocks enabled and gd valid - init serial console */ 416 preloader_console_init(); 417 418 if (sysinfo.dsize != 1) { 419 if (is_cpu_type(MXC_CPU_MX6SX) || 420 is_cpu_type(MXC_CPU_MX6UL) || 421 is_cpu_type(MXC_CPU_MX6ULL) || 422 is_cpu_type(MXC_CPU_MX6SL)) { 423 printf("cpu type 0x%x doesn't support 64-bit bus\n", 424 get_cpu_type()); 425 reset_cpu(0); 426 } 427 } 428 #ifdef CONFIG_MX6SL 429 mx6sl_dram_iocfg(CONFIG_DDRWIDTH, &mx6sl_ddr_ioregs, 430 &mx6sl_grp_ioregs); 431 #else 432 if (is_cpu_type(MXC_CPU_MX6Q)) { 433 mx6dq_dram_iocfg(CONFIG_DDRWIDTH, &mx6dq_ddr_ioregs, 434 &mx6dq_grp_ioregs); 435 } else { 436 mx6sdl_dram_iocfg(CONFIG_DDRWIDTH, &mx6sdl_ddr_ioregs, 437 &mx6sdl_grp_ioregs); 438 } 439 #endif 440 mx6_dram_cfg(&sysinfo, &calibration, &ddrtype); 441 442 errs = mmdc_do_write_level_calibration(&sysinfo); 443 if (errs) { 444 printf("error %d from write level calibration\n", errs); 445 } else { 446 errs = mmdc_do_dqs_calibration(&sysinfo); 447 if (errs) { 448 printf("error %d from dqs calibration\n", errs); 449 } else { 450 printf("completed successfully\n"); 451 mmdc_read_calibration(&sysinfo, &calibration); 452 display_calibration(&calibration); 453 } 454 } 455 } 456