1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Creative ZEN X-Fi3 board 4 * 5 * Copyright (C) 2013 Marek Vasut <marex@denx.de> 6 * 7 * Hardware investigation done by: 8 * 9 * Amaury Pouly <amaury.pouly@gmail.com> 10 */ 11 12 #include <common.h> 13 #include <errno.h> 14 #include <asm/gpio.h> 15 #include <asm/io.h> 16 #include <asm/arch/iomux-mx23.h> 17 #include <asm/arch/imx-regs.h> 18 #include <asm/arch/clock.h> 19 #include <asm/arch/sys_proto.h> 20 21 DECLARE_GLOBAL_DATA_PTR; 22 23 /* 24 * Functions 25 */ 26 int board_early_init_f(void) 27 { 28 /* IO0 clock at 480MHz */ 29 mxs_set_ioclk(MXC_IOCLK0, 480000); 30 31 /* SSP0 clock at 96MHz */ 32 mxs_set_sspclk(MXC_SSPCLK0, 96000, 0); 33 34 return 0; 35 } 36 37 int dram_init(void) 38 { 39 return mxs_dram_init(); 40 } 41 42 #ifdef CONFIG_CMD_MMC 43 static int xfi3_mmc_cd(int id) 44 { 45 switch (id) { 46 case 0: 47 /* The SSP_DETECT is inverted on this board. */ 48 return gpio_get_value(MX23_PAD_SSP1_DETECT__GPIO_2_1); 49 case 1: 50 /* Phison bridge always present */ 51 return 1; 52 default: 53 return 0; 54 } 55 } 56 57 int board_mmc_init(bd_t *bis) 58 { 59 int ret; 60 61 /* MicroSD slot */ 62 gpio_direction_input(MX23_PAD_SSP1_DETECT__GPIO_2_1); 63 gpio_direction_output(MX23_PAD_GPMI_D07__GPIO_0_7, 0); 64 ret = mxsmmc_initialize(bis, 0, NULL, xfi3_mmc_cd); 65 if (ret) 66 return ret; 67 68 /* Phison SD-NAND bridge */ 69 ret = mxsmmc_initialize(bis, 1, NULL, xfi3_mmc_cd); 70 71 return ret; 72 } 73 #endif 74 75 #ifdef CONFIG_VIDEO_MXS 76 static int mxsfb_write_byte(uint32_t payload, const unsigned int data) 77 { 78 struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE; 79 const unsigned int timeout = 0x10000; 80 81 if (mxs_wait_mask_clr(®s->hw_lcdif_ctrl_reg, LCDIF_CTRL_RUN, 82 timeout)) 83 return -ETIMEDOUT; 84 85 writel((1 << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) | 86 (1 << LCDIF_TRANSFER_COUNT_H_COUNT_OFFSET), 87 ®s->hw_lcdif_transfer_count); 88 89 writel(LCDIF_CTRL_DATA_SELECT | LCDIF_CTRL_RUN, 90 ®s->hw_lcdif_ctrl_clr); 91 92 if (data) 93 writel(LCDIF_CTRL_DATA_SELECT, ®s->hw_lcdif_ctrl_set); 94 95 writel(LCDIF_CTRL_RUN, ®s->hw_lcdif_ctrl_set); 96 97 if (mxs_wait_mask_clr(®s->hw_lcdif_lcdif_stat_reg, 1 << 29, 98 timeout)) 99 return -ETIMEDOUT; 100 101 writel(payload, ®s->hw_lcdif_data); 102 return mxs_wait_mask_clr(®s->hw_lcdif_ctrl_reg, LCDIF_CTRL_RUN, 103 timeout); 104 } 105 106 static void mxsfb_write_register(uint32_t reg, uint32_t data) 107 { 108 mxsfb_write_byte(reg, 0); 109 mxsfb_write_byte(data, 1); 110 } 111 112 static const struct { 113 uint8_t reg; 114 uint8_t delay; 115 uint16_t val; 116 } lcd_regs[] = { 117 { 0x01, 0, 0x001c }, 118 { 0x02, 0, 0x0100 }, 119 /* Writing 0x30 to reg. 0x03 flips the LCD */ 120 { 0x03, 0, 0x1038 }, 121 { 0x08, 0, 0x0808 }, 122 /* This can contain 0x111 to rotate the LCD. */ 123 { 0x0c, 0, 0x0000 }, 124 { 0x0f, 0, 0x0c01 }, 125 { 0x20, 0, 0x0000 }, 126 { 0x21, 30, 0x0000 }, 127 /* Wait 30 mS here */ 128 { 0x10, 0, 0x0a00 }, 129 { 0x11, 30, 0x1038 }, 130 /* Wait 30 mS here */ 131 { 0x12, 0, 0x1010 }, 132 { 0x13, 0, 0x0050 }, 133 { 0x14, 0, 0x4f58 }, 134 { 0x30, 0, 0x0000 }, 135 { 0x31, 0, 0x00db }, 136 { 0x32, 0, 0x0000 }, 137 { 0x33, 0, 0x0000 }, 138 { 0x34, 0, 0x00db }, 139 { 0x35, 0, 0x0000 }, 140 { 0x36, 0, 0x00af }, 141 { 0x37, 0, 0x0000 }, 142 { 0x38, 0, 0x00db }, 143 { 0x39, 0, 0x0000 }, 144 { 0x50, 0, 0x0000 }, 145 { 0x51, 0, 0x0705 }, 146 { 0x52, 0, 0x0e0a }, 147 { 0x53, 0, 0x0300 }, 148 { 0x54, 0, 0x0a0e }, 149 { 0x55, 0, 0x0507 }, 150 { 0x56, 0, 0x0000 }, 151 { 0x57, 0, 0x0003 }, 152 { 0x58, 0, 0x090a }, 153 { 0x59, 30, 0x0a09 }, 154 /* Wait 30 mS here */ 155 { 0x07, 30, 0x1017 }, 156 /* Wait 40 mS here */ 157 { 0x36, 0, 0x00af }, 158 { 0x37, 0, 0x0000 }, 159 { 0x38, 0, 0x00db }, 160 { 0x39, 0, 0x0000 }, 161 { 0x20, 0, 0x0000 }, 162 { 0x21, 0, 0x0000 }, 163 }; 164 165 void mxsfb_system_setup(void) 166 { 167 struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE; 168 int i; 169 170 /* Switch the LCDIF into System-Mode */ 171 writel(LCDIF_CTRL_LCDIF_MASTER | LCDIF_CTRL_DOTCLK_MODE | 172 LCDIF_CTRL_BYPASS_COUNT, ®s->hw_lcdif_ctrl_clr); 173 174 /* Restart the SmartLCD controller */ 175 mdelay(50); 176 writel(1, ®s->hw_lcdif_ctrl1_set); 177 mdelay(50); 178 writel(1, ®s->hw_lcdif_ctrl1_clr); 179 mdelay(50); 180 writel(1, ®s->hw_lcdif_ctrl1_set); 181 mdelay(50); 182 183 /* Program the SmartLCD controller */ 184 writel(LCDIF_CTRL1_RECOVER_ON_UNDERFLOW, ®s->hw_lcdif_ctrl1_set); 185 186 writel((0x03 << LCDIF_TIMING_CMD_HOLD_OFFSET) | 187 (0x03 << LCDIF_TIMING_CMD_SETUP_OFFSET) | 188 (0x03 << LCDIF_TIMING_DATA_HOLD_OFFSET) | 189 (0x02 << LCDIF_TIMING_DATA_SETUP_OFFSET), 190 ®s->hw_lcdif_timing); 191 192 /* 193 * OTM2201A init and configuration sequence. 194 */ 195 for (i = 0; i < ARRAY_SIZE(lcd_regs); i++) { 196 mxsfb_write_register(lcd_regs[i].reg, lcd_regs[i].val); 197 if (lcd_regs[i].delay) 198 mdelay(lcd_regs[i].delay); 199 } 200 /* Turn on Framebuffer Upload Mode */ 201 mxsfb_write_byte(0x22, 0); 202 203 writel(LCDIF_CTRL_LCDIF_MASTER | LCDIF_CTRL_DATA_SELECT, 204 ®s->hw_lcdif_ctrl_set); 205 } 206 #endif 207 208 int board_init(void) 209 { 210 /* Adress of boot parameters */ 211 gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; 212 213 /* Turn on PWM backlight */ 214 gpio_direction_output(MX23_PAD_PWM2__GPIO_1_28, 1); 215 216 return 0; 217 } 218 219 int board_eth_init(bd_t *bis) 220 { 221 usb_eth_initialize(bis); 222 return 0; 223 } 224