sfp.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * SanDisk Sansa Fuze Plus 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. #include <common.h>
  12. #include <errno.h>
  13. #include <asm/gpio.h>
  14. #include <asm/io.h>
  15. #include <asm/arch/iomux-mx23.h>
  16. #include <asm/arch/imx-regs.h>
  17. #include <asm/arch/clock.h>
  18. #include <asm/arch/sys_proto.h>
  19. DECLARE_GLOBAL_DATA_PTR;
  20. /*
  21. * Functions
  22. */
  23. int board_early_init_f(void)
  24. {
  25. /* IO0 clock at 480MHz */
  26. mxs_set_ioclk(MXC_IOCLK0, 480000);
  27. /* SSP0 clock at 96MHz */
  28. mxs_set_sspclk(MXC_SSPCLK0, 96000, 0);
  29. return 0;
  30. }
  31. int dram_init(void)
  32. {
  33. return mxs_dram_init();
  34. }
  35. #ifdef CONFIG_CMD_MMC
  36. static int xfi3_mmc_cd(int id)
  37. {
  38. switch (id) {
  39. case 0:
  40. /* The SSP_DETECT is inverted on this board. */
  41. return gpio_get_value(MX23_PAD_SSP1_DETECT__GPIO_2_1);
  42. case 1:
  43. /* Internal eMMC always present */
  44. return 1;
  45. default:
  46. return 0;
  47. }
  48. }
  49. int board_mmc_init(bd_t *bis)
  50. {
  51. int ret;
  52. /* MicroSD slot */
  53. gpio_direction_input(MX23_PAD_SSP1_DETECT__GPIO_2_1);
  54. gpio_direction_output(MX23_PAD_GPMI_D08__GPIO_0_8, 0);
  55. ret = mxsmmc_initialize(bis, 0, NULL, xfi3_mmc_cd);
  56. if (ret)
  57. return ret;
  58. /* Internal eMMC */
  59. gpio_direction_output(MX23_PAD_PWM3__GPIO_1_29, 0);
  60. ret = mxsmmc_initialize(bis, 1, NULL, xfi3_mmc_cd);
  61. return ret;
  62. }
  63. #endif
  64. #ifdef CONFIG_VIDEO_MXS
  65. #define MUX_CONFIG_LCD (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
  66. const iomux_cfg_t iomux_lcd_gpio[] = {
  67. MX23_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_LCD,
  68. MX23_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_LCD,
  69. MX23_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_LCD,
  70. MX23_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_LCD,
  71. MX23_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_LCD,
  72. MX23_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_LCD,
  73. MX23_PAD_LCD_D06__GPIO_1_6 | MUX_CONFIG_LCD,
  74. MX23_PAD_LCD_D07__GPIO_1_7 | MUX_CONFIG_LCD,
  75. MX23_PAD_LCD_D08__GPIO_1_8 | MUX_CONFIG_LCD,
  76. MX23_PAD_LCD_D09__GPIO_1_9 | MUX_CONFIG_LCD,
  77. MX23_PAD_LCD_D10__GPIO_1_10 | MUX_CONFIG_LCD,
  78. MX23_PAD_LCD_D11__GPIO_1_11 | MUX_CONFIG_LCD,
  79. MX23_PAD_LCD_D12__GPIO_1_12 | MUX_CONFIG_LCD,
  80. MX23_PAD_LCD_D13__GPIO_1_13 | MUX_CONFIG_LCD,
  81. MX23_PAD_LCD_D14__GPIO_1_14 | MUX_CONFIG_LCD,
  82. MX23_PAD_LCD_D15__GPIO_1_15 | MUX_CONFIG_LCD,
  83. MX23_PAD_LCD_D16__GPIO_1_16 | MUX_CONFIG_LCD,
  84. MX23_PAD_LCD_D17__GPIO_1_17 | MUX_CONFIG_LCD,
  85. MX23_PAD_LCD_RESET__GPIO_1_18 | MUX_CONFIG_LCD,
  86. MX23_PAD_LCD_RS__GPIO_1_19 | MUX_CONFIG_LCD,
  87. MX23_PAD_LCD_WR__GPIO_1_20 | MUX_CONFIG_LCD,
  88. MX23_PAD_LCD_CS__GPIO_1_21 | MUX_CONFIG_LCD,
  89. MX23_PAD_LCD_ENABLE__GPIO_1_23 | MUX_CONFIG_LCD,
  90. };
  91. const iomux_cfg_t iomux_lcd_lcd[] = {
  92. MX23_PAD_LCD_D00__LCD_D00 | MUX_CONFIG_LCD,
  93. MX23_PAD_LCD_D01__LCD_D01 | MUX_CONFIG_LCD,
  94. MX23_PAD_LCD_D02__LCD_D02 | MUX_CONFIG_LCD,
  95. MX23_PAD_LCD_D03__LCD_D03 | MUX_CONFIG_LCD,
  96. MX23_PAD_LCD_D04__LCD_D04 | MUX_CONFIG_LCD,
  97. MX23_PAD_LCD_D05__LCD_D05 | MUX_CONFIG_LCD,
  98. MX23_PAD_LCD_D06__LCD_D06 | MUX_CONFIG_LCD,
  99. MX23_PAD_LCD_D07__LCD_D07 | MUX_CONFIG_LCD,
  100. MX23_PAD_LCD_D08__LCD_D08 | MUX_CONFIG_LCD,
  101. MX23_PAD_LCD_D09__LCD_D09 | MUX_CONFIG_LCD,
  102. MX23_PAD_LCD_D10__LCD_D10 | MUX_CONFIG_LCD,
  103. MX23_PAD_LCD_D11__LCD_D11 | MUX_CONFIG_LCD,
  104. MX23_PAD_LCD_D12__LCD_D12 | MUX_CONFIG_LCD,
  105. MX23_PAD_LCD_D13__LCD_D13 | MUX_CONFIG_LCD,
  106. MX23_PAD_LCD_D14__LCD_D14 | MUX_CONFIG_LCD,
  107. MX23_PAD_LCD_D15__LCD_D15 | MUX_CONFIG_LCD,
  108. MX23_PAD_LCD_D16__LCD_D16 | MUX_CONFIG_LCD,
  109. MX23_PAD_LCD_D17__LCD_D17 | MUX_CONFIG_LCD,
  110. MX23_PAD_LCD_RESET__LCD_RESET | MUX_CONFIG_LCD,
  111. MX23_PAD_LCD_RS__LCD_RS | MUX_CONFIG_LCD,
  112. MX23_PAD_LCD_WR__LCD_WR | MUX_CONFIG_LCD,
  113. MX23_PAD_LCD_CS__LCD_CS | MUX_CONFIG_LCD,
  114. MX23_PAD_LCD_ENABLE__LCD_ENABLE | MUX_CONFIG_LCD,
  115. MX23_PAD_LCD_VSYNC__LCD_VSYNC | MUX_CONFIG_LCD,
  116. };
  117. static int mxsfb_read_register(uint32_t reg, uint32_t *value)
  118. {
  119. iomux_cfg_t mux;
  120. uint32_t val = 0;
  121. int i;
  122. /* Mangle the register offset. */
  123. reg = ((reg & 0xff) << 1) | (((reg >> 8) & 0xff) << 10);
  124. /*
  125. * The SmartLCD interface on MX233 can only do WRITE operation
  126. * via the LCDIF controller. Implement the READ operation by
  127. * fiddling with bits.
  128. */
  129. mxs_iomux_setup_multiple_pads(iomux_lcd_gpio,
  130. ARRAY_SIZE(iomux_lcd_gpio));
  131. gpio_direction_output(MX23_PAD_LCD_RS__GPIO_1_19, 1);
  132. gpio_direction_output(MX23_PAD_LCD_CS__GPIO_1_21, 1);
  133. gpio_direction_output(MX23_PAD_LCD_WR__GPIO_1_20, 1);
  134. gpio_direction_output(MX23_PAD_LCD_ENABLE__GPIO_1_23, 1);
  135. for (i = 0; i < 18; i++) {
  136. mux = MXS_IOMUX_PAD_NAKED(1, i, PAD_MUXSEL_GPIO);
  137. gpio_direction_output(mux, 0);
  138. }
  139. udelay(2);
  140. gpio_direction_output(MX23_PAD_LCD_RS__GPIO_1_19, 0);
  141. udelay(1);
  142. gpio_direction_output(MX23_PAD_LCD_CS__GPIO_1_21, 0);
  143. udelay(1);
  144. gpio_direction_output(MX23_PAD_LCD_WR__GPIO_1_20, 0);
  145. udelay(1);
  146. for (i = 0; i < 18; i++) {
  147. mux = MXS_IOMUX_PAD_NAKED(1, i, PAD_MUXSEL_GPIO);
  148. gpio_direction_output(mux, (reg >> i) & 1);
  149. }
  150. udelay(1);
  151. gpio_direction_output(MX23_PAD_LCD_WR__GPIO_1_20, 1);
  152. udelay(3);
  153. for (i = 0; i < 18; i++) {
  154. mux = MXS_IOMUX_PAD_NAKED(1, i, PAD_MUXSEL_GPIO);
  155. gpio_direction_input(mux);
  156. }
  157. udelay(2);
  158. gpio_direction_output(MX23_PAD_LCD_ENABLE__GPIO_1_23, 0);
  159. udelay(1);
  160. gpio_direction_output(MX23_PAD_LCD_RS__GPIO_1_19, 1);
  161. udelay(1);
  162. gpio_direction_output(MX23_PAD_LCD_ENABLE__GPIO_1_23, 1);
  163. udelay(3);
  164. gpio_direction_output(MX23_PAD_LCD_ENABLE__GPIO_1_23, 0);
  165. udelay(2);
  166. for (i = 0; i < 18; i++) {
  167. mux = MXS_IOMUX_PAD_NAKED(1, i, PAD_MUXSEL_GPIO);
  168. val |= !!gpio_get_value(mux) << i;
  169. }
  170. udelay(1);
  171. gpio_direction_output(MX23_PAD_LCD_ENABLE__GPIO_1_23, 1);
  172. udelay(1);
  173. gpio_direction_output(MX23_PAD_LCD_CS__GPIO_1_21, 1);
  174. udelay(1);
  175. mxs_iomux_setup_multiple_pads(iomux_lcd_lcd,
  176. ARRAY_SIZE(iomux_lcd_lcd));
  177. /* Demangle the register value. */
  178. *value = ((val >> 1) & 0xff) | ((val >> 2) & 0xff00);
  179. writel(val, 0x2000);
  180. return 0;
  181. }
  182. static int mxsfb_write_byte(uint32_t payload, const unsigned int data)
  183. {
  184. struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
  185. const unsigned int timeout = 0x10000;
  186. /* What is going on here I do not know. FIXME */
  187. payload = ((payload & 0xff) << 1) | (((payload >> 8) & 0xff) << 10);
  188. if (mxs_wait_mask_clr(&regs->hw_lcdif_ctrl_reg, LCDIF_CTRL_RUN,
  189. timeout))
  190. return -ETIMEDOUT;
  191. writel((1 << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) |
  192. (1 << LCDIF_TRANSFER_COUNT_H_COUNT_OFFSET),
  193. &regs->hw_lcdif_transfer_count);
  194. writel(LCDIF_CTRL_DATA_SELECT | LCDIF_CTRL_RUN,
  195. &regs->hw_lcdif_ctrl_clr);
  196. if (data)
  197. writel(LCDIF_CTRL_DATA_SELECT, &regs->hw_lcdif_ctrl_set);
  198. writel(LCDIF_CTRL_RUN, &regs->hw_lcdif_ctrl_set);
  199. if (mxs_wait_mask_clr(&regs->hw_lcdif_lcdif_stat_reg, 1 << 29,
  200. timeout))
  201. return -ETIMEDOUT;
  202. writel(payload, &regs->hw_lcdif_data);
  203. return mxs_wait_mask_clr(&regs->hw_lcdif_ctrl_reg, LCDIF_CTRL_RUN,
  204. timeout);
  205. }
  206. static void mxsfb_write_register(uint32_t reg, uint32_t data)
  207. {
  208. mxsfb_write_byte(reg, 0);
  209. mxsfb_write_byte(data, 1);
  210. }
  211. static const struct {
  212. uint8_t reg;
  213. uint8_t delay;
  214. uint16_t val;
  215. } lcd_regs[] = {
  216. { 0xe5, 0 , 0x78f0 },
  217. { 0xe3, 0 , 0x3008 },
  218. { 0xe7, 0 , 0x0012 },
  219. { 0xef, 0 , 0x1231 },
  220. { 0x00, 0 , 0x0001 },
  221. { 0x01, 0 , 0x0100 },
  222. { 0x02, 0 , 0x0700 },
  223. { 0x03, 0 , 0x1030 },
  224. { 0x04, 0 , 0x0000 },
  225. { 0x08, 0 , 0x0207 },
  226. { 0x09, 0 , 0x0000 },
  227. { 0x0a, 0 , 0x0000 },
  228. { 0x0c, 0 , 0x0000 },
  229. { 0x0d, 0 , 0x0000 },
  230. { 0x0f, 0 , 0x0000 },
  231. { 0x10, 0 , 0x0000 },
  232. { 0x11, 0 , 0x0007 },
  233. { 0x12, 0 , 0x0000 },
  234. { 0x13, 20 , 0x0000 },
  235. /* Wait 20 mS here. */
  236. { 0x10, 0 , 0x1290 },
  237. { 0x11, 50 , 0x0007 },
  238. /* Wait 50 mS here. */
  239. { 0x12, 50 , 0x0019 },
  240. /* Wait 50 mS here. */
  241. { 0x13, 0 , 0x1700 },
  242. { 0x29, 50 , 0x0014 },
  243. /* Wait 50 mS here. */
  244. { 0x20, 0 , 0x0000 },
  245. { 0x21, 0 , 0x0000 },
  246. { 0x30, 0 , 0x0504 },
  247. { 0x31, 0 , 0x0007 },
  248. { 0x32, 0 , 0x0006 },
  249. { 0x35, 0 , 0x0106 },
  250. { 0x36, 0 , 0x0202 },
  251. { 0x37, 0 , 0x0504 },
  252. { 0x38, 0 , 0x0500 },
  253. { 0x39, 0 , 0x0706 },
  254. { 0x3c, 0 , 0x0204 },
  255. { 0x3d, 0 , 0x0202 },
  256. { 0x50, 0 , 0x0000 },
  257. { 0x51, 0 , 0x00ef },
  258. { 0x52, 0 , 0x0000 },
  259. { 0x53, 0 , 0x013f },
  260. { 0x60, 0 , 0xa700 },
  261. { 0x61, 0 , 0x0001 },
  262. { 0x6a, 0 , 0x0000 },
  263. { 0x2b, 50 , 0x000d },
  264. /* Wait 50 mS here. */
  265. { 0x90, 0 , 0x0011 },
  266. { 0x92, 0 , 0x0600 },
  267. { 0x93, 0 , 0x0003 },
  268. { 0x95, 0 , 0x0110 },
  269. { 0x97, 0 , 0x0000 },
  270. { 0x98, 0 , 0x0000 },
  271. { 0x07, 0 , 0x0173 },
  272. };
  273. void board_mxsfb_system_setup(void)
  274. {
  275. struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
  276. uint32_t id;
  277. int i;
  278. /* Switch the LCDIF into System-Mode */
  279. writel(LCDIF_CTRL_LCDIF_MASTER | LCDIF_CTRL_DOTCLK_MODE |
  280. LCDIF_CTRL_BYPASS_COUNT, &regs->hw_lcdif_ctrl_clr);
  281. /* To program the LCD, switch to 18bit bus + 18bit data. */
  282. clrsetbits_le32(&regs->hw_lcdif_ctrl,
  283. LCDIF_CTRL_WORD_LENGTH_MASK | LCDIF_CTRL_LCD_DATABUS_WIDTH_MASK,
  284. LCDIF_CTRL_WORD_LENGTH_18BIT |
  285. LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT);
  286. mxsfb_read_register(0, &id);
  287. writel(id, 0x2004);
  288. /* Restart the SmartLCD controller */
  289. mdelay(50);
  290. writel(1, &regs->hw_lcdif_ctrl1_set);
  291. mdelay(50);
  292. writel(1, &regs->hw_lcdif_ctrl1_clr);
  293. mdelay(50);
  294. writel(1, &regs->hw_lcdif_ctrl1_set);
  295. mdelay(50);
  296. /* Program the SmartLCD controller */
  297. writel(LCDIF_CTRL1_RECOVER_ON_UNDERFLOW, &regs->hw_lcdif_ctrl1_set);
  298. writel((0x02 << LCDIF_TIMING_CMD_HOLD_OFFSET) |
  299. (0x02 << LCDIF_TIMING_CMD_SETUP_OFFSET) |
  300. (0x02 << LCDIF_TIMING_DATA_HOLD_OFFSET) |
  301. (0x01 << LCDIF_TIMING_DATA_SETUP_OFFSET),
  302. &regs->hw_lcdif_timing);
  303. /*
  304. * ILI9325 init and configuration sequence.
  305. */
  306. for (i = 0; i < ARRAY_SIZE(lcd_regs); i++) {
  307. mxsfb_write_register(lcd_regs[i].reg, lcd_regs[i].val);
  308. if (lcd_regs[i].delay)
  309. mdelay(lcd_regs[i].delay);
  310. }
  311. /* Turn on Framebuffer Upload Mode */
  312. mxsfb_write_byte(0x22, 0);
  313. writel(LCDIF_CTRL_LCDIF_MASTER | LCDIF_CTRL_DATA_SELECT,
  314. &regs->hw_lcdif_ctrl_set);
  315. /* Operate the framebuffer in 16bit mode. */
  316. clrsetbits_le32(&regs->hw_lcdif_ctrl,
  317. LCDIF_CTRL_WORD_LENGTH_MASK | LCDIF_CTRL_LCD_DATABUS_WIDTH_MASK,
  318. LCDIF_CTRL_WORD_LENGTH_16BIT |
  319. LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT);
  320. }
  321. #endif
  322. int board_init(void)
  323. {
  324. /* Adress of boot parameters */
  325. gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
  326. /* Turn on PWM backlight */
  327. gpio_direction_output(MX23_PAD_PWM2__GPIO_1_28, 1);
  328. return 0;
  329. }
  330. int board_eth_init(bd_t *bis)
  331. {
  332. usb_eth_initialize(bis);
  333. return 0;
  334. }