1 /* 2 * Board functions for TI AM335X based rut board 3 * (C) Copyright 2013 Siemens Schweiz AG 4 * (C) Heiko Schocher, DENX Software Engineering, hs@denx.de. 5 * 6 * Based on: 7 * u-boot:/board/ti/am335x/board.c 8 * 9 * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ 10 * 11 * SPDX-License-Identifier: GPL-2.0+ 12 */ 13 14 #include <common.h> 15 #include <errno.h> 16 #include <spi.h> 17 #include <spl.h> 18 #include <asm/arch/cpu.h> 19 #include <asm/arch/hardware.h> 20 #include <asm/arch/omap.h> 21 #include <asm/arch/ddr_defs.h> 22 #include <asm/arch/clock.h> 23 #include <asm/arch/gpio.h> 24 #include <asm/arch/mmc_host_def.h> 25 #include <asm/arch/sys_proto.h> 26 #include <asm/io.h> 27 #include <asm/emif.h> 28 #include <asm/gpio.h> 29 #include <i2c.h> 30 #include <miiphy.h> 31 #include <cpsw.h> 32 #include <video.h> 33 #include <watchdog.h> 34 #include "board.h" 35 #include "../common/factoryset.h" 36 #include "../../../drivers/video/da8xx-fb.h" 37 38 DECLARE_GLOBAL_DATA_PTR; 39 40 /* 41 * Read header information from EEPROM into global structure. 42 */ 43 static int read_eeprom(void) 44 { 45 return 0; 46 } 47 48 #ifdef CONFIG_SPL_BUILD 49 static void board_init_ddr(void) 50 { 51 struct emif_regs rut_ddr3_emif_reg_data = { 52 .sdram_config = 0x61C04AB2, 53 .sdram_tim1 = 0x0888A39B, 54 .sdram_tim2 = 0x26337FDA, 55 .sdram_tim3 = 0x501F830F, 56 .emif_ddr_phy_ctlr_1 = 0x6, 57 .zq_config = 0x50074BE4, 58 .ref_ctrl = 0x93B, 59 }; 60 61 struct ddr_data rut_ddr3_data = { 62 .datardsratio0 = 0x3b, 63 .datawdsratio0 = 0x85, 64 .datafwsratio0 = 0x100, 65 .datawrsratio0 = 0xc1, 66 .datauserank0delay = 1, 67 .datadldiff0 = PHY_DLL_LOCK_DIFF, 68 }; 69 70 struct cmd_control rut_ddr3_cmd_ctrl_data = { 71 .cmd0csratio = 0x40, 72 .cmd0dldiff = 0, 73 .cmd0iclkout = 1, 74 .cmd1csratio = 0x40, 75 .cmd1dldiff = 0, 76 .cmd1iclkout = 1, 77 .cmd2csratio = 0x40, 78 .cmd2dldiff = 0, 79 .cmd2iclkout = 1, 80 }; 81 82 config_ddr(DDR_PLL_FREQ, RUT_IOCTRL_VAL, &rut_ddr3_data, 83 &rut_ddr3_cmd_ctrl_data, &rut_ddr3_emif_reg_data, 0); 84 } 85 86 static void spl_siemens_board_init(void) 87 { 88 return; 89 } 90 #endif /* if def CONFIG_SPL_BUILD */ 91 92 #if defined(CONFIG_DRIVER_TI_CPSW) 93 static void cpsw_control(int enabled) 94 { 95 /* VTP can be added here */ 96 97 return; 98 } 99 100 static struct cpsw_slave_data cpsw_slaves[] = { 101 { 102 .slave_reg_ofs = 0x208, 103 .sliver_reg_ofs = 0xd80, 104 .phy_id = 1, 105 .phy_if = PHY_INTERFACE_MODE_RMII, 106 }, 107 { 108 .slave_reg_ofs = 0x308, 109 .sliver_reg_ofs = 0xdc0, 110 .phy_id = 0, 111 .phy_if = PHY_INTERFACE_MODE_RMII, 112 }, 113 }; 114 115 static struct cpsw_platform_data cpsw_data = { 116 .mdio_base = CPSW_MDIO_BASE, 117 .cpsw_base = CPSW_BASE, 118 .mdio_div = 0xff, 119 .channels = 8, 120 .cpdma_reg_ofs = 0x800, 121 .slaves = 1, 122 .slave_data = cpsw_slaves, 123 .ale_reg_ofs = 0xd00, 124 .ale_entries = 1024, 125 .host_port_reg_ofs = 0x108, 126 .hw_stats_reg_ofs = 0x900, 127 .bd_ram_ofs = 0x2000, 128 .mac_control = (1 << 5), 129 .control = cpsw_control, 130 .host_port_num = 0, 131 .version = CPSW_CTRL_VERSION_2, 132 }; 133 134 #if defined(CONFIG_DRIVER_TI_CPSW) || \ 135 (defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET)) 136 int board_eth_init(bd_t *bis) 137 { 138 struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; 139 int n = 0; 140 int rv; 141 142 #ifndef CONFIG_SPL_BUILD 143 factoryset_setenv(); 144 #endif 145 146 /* Set rgmii mode and enable rmii clock to be sourced from chip */ 147 writel((RMII_MODE_ENABLE | RMII_CHIPCKL_ENABLE), &cdev->miisel); 148 149 rv = cpsw_register(&cpsw_data); 150 if (rv < 0) 151 printf("Error %d registering CPSW switch\n", rv); 152 else 153 n += rv; 154 return n; 155 } 156 #endif /* #if defined(CONFIG_DRIVER_TI_CPSW) */ 157 #endif /* #if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) */ 158 159 #if defined(CONFIG_HW_WATCHDOG) 160 static bool hw_watchdog_init_done; 161 static int hw_watchdog_trigger_level; 162 163 void hw_watchdog_reset(void) 164 { 165 if (!hw_watchdog_init_done) 166 return; 167 168 hw_watchdog_trigger_level = hw_watchdog_trigger_level ? 0 : 1; 169 gpio_set_value(WATCHDOG_TRIGGER_GPIO, hw_watchdog_trigger_level); 170 } 171 172 void hw_watchdog_init(void) 173 { 174 gpio_request(WATCHDOG_TRIGGER_GPIO, "watchdog_trigger"); 175 gpio_direction_output(WATCHDOG_TRIGGER_GPIO, hw_watchdog_trigger_level); 176 177 hw_watchdog_reset(); 178 179 hw_watchdog_init_done = 1; 180 } 181 #endif /* defined(CONFIG_HW_WATCHDOG) */ 182 183 #if defined(CONFIG_VIDEO) && !defined(CONFIG_SPL_BUILD) 184 static struct da8xx_panel lcd_panels[] = { 185 /* FORMIKE, 4.3", 480x800, KWH043MC17-F01 */ 186 [0] = { 187 .name = "KWH043MC17-F01", 188 .width = 480, 189 .height = 800, 190 .hfp = 50, /* no spec, "don't care" values */ 191 .hbp = 50, 192 .hsw = 50, 193 .vfp = 50, 194 .vbp = 50, 195 .vsw = 50, 196 .pxl_clk = 35910000, /* tCYCD=20ns, max 50MHz, 60fps */ 197 .invert_pxl_clk = 1, 198 }, 199 /* FORMIKE, 4.3", 480x800, KWH043ST20-F01 */ 200 [1] = { 201 .name = "KWH043ST20-F01", 202 .width = 480, 203 .height = 800, 204 .hfp = 50, /* no spec, "don't care" values */ 205 .hbp = 50, 206 .hsw = 50, 207 .vfp = 50, 208 .vbp = 50, 209 .vsw = 50, 210 .pxl_clk = 35910000, /* tCYCD=20ns, max 50MHz, 60fps */ 211 .invert_pxl_clk = 1, 212 }, 213 /* Multi-Inno, 4.3", 480x800, MI0430VT-1 */ 214 [2] = { 215 .name = "MI0430VT-1", 216 .width = 480, 217 .height = 800, 218 .hfp = 50, /* no spec, "don't care" values */ 219 .hbp = 50, 220 .hsw = 50, 221 .vfp = 50, 222 .vbp = 50, 223 .vsw = 50, 224 .pxl_clk = 35910000, /* tCYCD=20ns, max 50MHz, 60fps */ 225 .invert_pxl_clk = 1, 226 }, 227 }; 228 229 static const struct display_panel disp_panels[] = { 230 [0] = { 231 WVGA, 232 16, /* RGB 888 */ 233 16, 234 COLOR_ACTIVE, 235 }, 236 [1] = { 237 WVGA, 238 16, /* RGB 888 */ 239 16, 240 COLOR_ACTIVE, 241 }, 242 [2] = { 243 WVGA, 244 24, /* RGB 888 */ 245 16, 246 COLOR_ACTIVE, 247 }, 248 }; 249 250 static const struct lcd_ctrl_config lcd_cfgs[] = { 251 [0] = { 252 &disp_panels[0], 253 .ac_bias = 255, 254 .ac_bias_intrpt = 0, 255 .dma_burst_sz = 16, 256 .bpp = 16, 257 .fdd = 0x80, 258 .tft_alt_mode = 0, 259 .stn_565_mode = 0, 260 .mono_8bit_mode = 0, 261 .invert_line_clock = 1, 262 .invert_frm_clock = 1, 263 .sync_edge = 0, 264 .sync_ctrl = 1, 265 .raster_order = 0, 266 }, 267 [1] = { 268 &disp_panels[1], 269 .ac_bias = 255, 270 .ac_bias_intrpt = 0, 271 .dma_burst_sz = 16, 272 .bpp = 16, 273 .fdd = 0x80, 274 .tft_alt_mode = 0, 275 .stn_565_mode = 0, 276 .mono_8bit_mode = 0, 277 .invert_line_clock = 1, 278 .invert_frm_clock = 1, 279 .sync_edge = 0, 280 .sync_ctrl = 1, 281 .raster_order = 0, 282 }, 283 [2] = { 284 &disp_panels[2], 285 .ac_bias = 255, 286 .ac_bias_intrpt = 0, 287 .dma_burst_sz = 16, 288 .bpp = 24, 289 .fdd = 0x80, 290 .tft_alt_mode = 0, 291 .stn_565_mode = 0, 292 .mono_8bit_mode = 0, 293 .invert_line_clock = 1, 294 .invert_frm_clock = 1, 295 .sync_edge = 0, 296 .sync_ctrl = 1, 297 .raster_order = 0, 298 }, 299 300 }; 301 302 /* no console on this board */ 303 int board_cfb_skip(void) 304 { 305 return 1; 306 } 307 308 #define PLL_GET_M(v) ((v >> 8) & 0x7ff) 309 #define PLL_GET_N(v) (v & 0x7f) 310 311 static struct dpll_regs dpll_lcd_regs = { 312 .cm_clkmode_dpll = CM_WKUP + 0x98, 313 .cm_idlest_dpll = CM_WKUP + 0x48, 314 .cm_clksel_dpll = CM_WKUP + 0x54, 315 }; 316 317 static int get_clk(struct dpll_regs *dpll_regs) 318 { 319 unsigned int val; 320 unsigned int m, n; 321 int f = 0; 322 323 val = readl(dpll_regs->cm_clksel_dpll); 324 m = PLL_GET_M(val); 325 n = PLL_GET_N(val); 326 f = (m * V_OSCK) / n; 327 328 return f; 329 }; 330 331 int clk_get(int clk) 332 { 333 return get_clk(&dpll_lcd_regs); 334 }; 335 336 static int conf_disp_pll(int m, int n) 337 { 338 struct cm_perpll *cmper = (struct cm_perpll *)CM_PER; 339 struct cm_dpll *cmdpll = (struct cm_dpll *)CM_DPLL; 340 struct dpll_params dpll_lcd = {m, n, -1, -1, -1, -1, -1}; 341 #if defined(DISPL_PLL_SPREAD_SPECTRUM) 342 struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP; 343 #endif 344 345 u32 *const clk_domains[] = { 346 &cmper->lcdclkctrl, 347 0 348 }; 349 u32 *const clk_modules_explicit_en[] = { 350 &cmper->lcdclkctrl, 351 &cmper->lcdcclkstctrl, 352 &cmper->spi1clkctrl, 353 0 354 }; 355 do_enable_clocks(clk_domains, clk_modules_explicit_en, 1); 356 /* 0x44e0_0500 write lcdc pixel clock mux Linux hat hier 0 */ 357 writel(0x0, &cmdpll->clklcdcpixelclk); 358 359 do_setup_dpll(&dpll_lcd_regs, &dpll_lcd); 360 361 #if defined(DISPL_PLL_SPREAD_SPECTRUM) 362 writel(0x64, &cmwkup->resv6[3]); /* 0x50 */ 363 writel(0x800, &cmwkup->resv6[2]); /* 0x4c */ 364 writel(readl(&cmwkup->clkmoddplldisp) | (1 << 12), 365 &cmwkup->clkmoddplldisp); /* 0x98 */ 366 #endif 367 return 0; 368 } 369 370 static int set_gpio(int gpio, int state) 371 { 372 gpio_request(gpio, "temp"); 373 gpio_direction_output(gpio, state); 374 gpio_set_value(gpio, state); 375 gpio_free(gpio); 376 return 0; 377 } 378 379 static int enable_lcd(void) 380 { 381 unsigned char buf[1]; 382 383 set_gpio(BOARD_LCD_RESET, 1); 384 385 /* spi lcd init */ 386 kwh043st20_f01_spi_startup(1, 0, 5000000, SPI_MODE_3); 387 388 /* backlight on */ 389 buf[0] = 0xf; 390 i2c_write(0x24, 0x7, 1, buf, 1); 391 buf[0] = 0x3f; 392 i2c_write(0x24, 0x8, 1, buf, 1); 393 return 0; 394 } 395 396 int arch_early_init_r(void) 397 { 398 enable_lcd(); 399 return 0; 400 } 401 402 static int board_video_init(void) 403 { 404 int i; 405 int anzdisp = ARRAY_SIZE(lcd_panels); 406 int display = 1; 407 408 for (i = 0; i < anzdisp; i++) { 409 if (strncmp((const char *)factory_dat.disp_name, 410 lcd_panels[i].name, 411 strlen((const char *)factory_dat.disp_name)) == 0) { 412 printf("DISPLAY: %s\n", factory_dat.disp_name); 413 break; 414 } 415 } 416 if (i == anzdisp) { 417 i = 1; 418 printf("%s: %s not found, using default %s\n", __func__, 419 factory_dat.disp_name, lcd_panels[i].name); 420 } 421 conf_disp_pll(25, 2); 422 da8xx_video_init(&lcd_panels[display], &lcd_cfgs[display], 423 lcd_cfgs[display].bpp); 424 425 return 0; 426 } 427 #endif /* ifdef CONFIG_VIDEO */ 428 #include "../common/board.c" 429