gw_ventana.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2013 Gateworks Corporation
  4. *
  5. * Author: Tim Harvey <tharvey@gateworks.com>
  6. */
  7. #include <common.h>
  8. #include <init.h>
  9. #include <log.h>
  10. #include <net.h>
  11. #include <asm/arch/clock.h>
  12. #include <asm/arch/crm_regs.h>
  13. #include <asm/arch/iomux.h>
  14. #include <asm/arch/mx6-pins.h>
  15. #include <asm/arch/mxc_hdmi.h>
  16. #include <asm/arch/sys_proto.h>
  17. #include <asm/global_data.h>
  18. #include <asm/gpio.h>
  19. #include <asm/mach-imx/boot_mode.h>
  20. #include <asm/mach-imx/sata.h>
  21. #include <asm/mach-imx/video.h>
  22. #include <asm/io.h>
  23. #include <asm/setup.h>
  24. #include <dm.h>
  25. #include <env.h>
  26. #include <hwconfig.h>
  27. #include <i2c.h>
  28. #include <fdt_support.h>
  29. #include <jffs2/load_kernel.h>
  30. #include <linux/ctype.h>
  31. #include <miiphy.h>
  32. #include <mtd_node.h>
  33. #include <pci.h>
  34. #include <linux/delay.h>
  35. #include <linux/libfdt.h>
  36. #include <power/pmic.h>
  37. #include <power/ltc3676_pmic.h>
  38. #include <power/pfuze100_pmic.h>
  39. #include <fdt_support.h>
  40. #include <jffs2/load_kernel.h>
  41. #include "gsc.h"
  42. #include "common.h"
  43. DECLARE_GLOBAL_DATA_PTR;
  44. /*
  45. * EEPROM board info struct populated by read_eeprom so that we only have to
  46. * read it once.
  47. */
  48. struct ventana_board_info ventana_info;
  49. static int board_type;
  50. #ifdef CONFIG_USB_EHCI_MX6
  51. /* toggle USB_HUB_RST# for boards that have it; it is not defined in dt */
  52. int board_ehci_hcd_init(int port)
  53. {
  54. int gpio;
  55. /* USB HUB is always on P1 */
  56. if (port == 0)
  57. return 0;
  58. /* Reset USB HUB */
  59. switch (board_type) {
  60. case GW53xx:
  61. case GW552x:
  62. case GW5906:
  63. gpio = (IMX_GPIO_NR(1, 9));
  64. break;
  65. case GW54proto:
  66. case GW54xx:
  67. gpio = (IMX_GPIO_NR(1, 16));
  68. break;
  69. default:
  70. return 0;
  71. }
  72. /* request and toggle hub rst */
  73. gpio_request(gpio, "usb_hub_rst#");
  74. gpio_direction_output(gpio, 0);
  75. mdelay(2);
  76. gpio_set_value(gpio, 1);
  77. return 0;
  78. }
  79. #endif /* CONFIG_USB_EHCI_MX6 */
  80. /* configure eth0 PHY board-specific LED behavior */
  81. int board_phy_config(struct phy_device *phydev)
  82. {
  83. unsigned short val;
  84. /* Marvel 88E1510 */
  85. if (phydev->phy_id == 0x1410dd1) {
  86. /*
  87. * Page 3, Register 16: LED[2:0] Function Control Register
  88. * LED[0] (SPD:Amber) R16_3.3:0 to 0111: on-GbE link
  89. * LED[1] (LNK:Green) R16_3.7:4 to 0001: on-link, blink-activity
  90. */
  91. phy_write(phydev, MDIO_DEVAD_NONE, 22, 3);
  92. val = phy_read(phydev, MDIO_DEVAD_NONE, 16);
  93. val &= 0xff00;
  94. val |= 0x0017;
  95. phy_write(phydev, MDIO_DEVAD_NONE, 16, val);
  96. phy_write(phydev, MDIO_DEVAD_NONE, 22, 0);
  97. }
  98. /* TI DP83867 */
  99. else if (phydev->phy_id == 0x2000a231) {
  100. /* configure register 0x170 for ref CLKOUT */
  101. phy_write(phydev, MDIO_DEVAD_NONE, 13, 0x001f);
  102. phy_write(phydev, MDIO_DEVAD_NONE, 14, 0x0170);
  103. phy_write(phydev, MDIO_DEVAD_NONE, 13, 0x401f);
  104. val = phy_read(phydev, MDIO_DEVAD_NONE, 14);
  105. val &= ~0x1f00;
  106. val |= 0x0b00; /* chD tx clock*/
  107. phy_write(phydev, MDIO_DEVAD_NONE, 14, val);
  108. }
  109. if (phydev->drv->config)
  110. phydev->drv->config(phydev);
  111. return 0;
  112. }
  113. #ifdef CONFIG_MV88E61XX_SWITCH
  114. int mv88e61xx_hw_reset(struct phy_device *phydev)
  115. {
  116. struct mii_dev *bus = phydev->bus;
  117. /* GPIO[0] output, CLK125 */
  118. debug("enabling RGMII_REFCLK\n");
  119. bus->write(bus, 0x1c /*MV_GLOBAL2*/, 0,
  120. 0x1a /*MV_SCRATCH_MISC*/,
  121. (1 << 15) | (0x62 /*MV_GPIO_DIR*/ << 8) | 0xfe);
  122. bus->write(bus, 0x1c /*MV_GLOBAL2*/, 0,
  123. 0x1a /*MV_SCRATCH_MISC*/,
  124. (1 << 15) | (0x68 /*MV_GPIO01_CNTL*/ << 8) | 7);
  125. /* RGMII delay - Physical Control register bit[15:14] */
  126. debug("setting port%d RGMII rx/tx delay\n", CONFIG_MV88E61XX_CPU_PORT);
  127. /* forced 1000mbps full-duplex link */
  128. bus->write(bus, 0x10 + CONFIG_MV88E61XX_CPU_PORT, 0, 1, 0xc0fe);
  129. phydev->autoneg = AUTONEG_DISABLE;
  130. phydev->speed = SPEED_1000;
  131. phydev->duplex = DUPLEX_FULL;
  132. /* LED configuration: 7:4-green (8=Activity) 3:0 amber (8=Link) */
  133. bus->write(bus, 0x10, 0, 0x16, 0x8088);
  134. bus->write(bus, 0x11, 0, 0x16, 0x8088);
  135. bus->write(bus, 0x12, 0, 0x16, 0x8088);
  136. bus->write(bus, 0x13, 0, 0x16, 0x8088);
  137. return 0;
  138. }
  139. #endif // CONFIG_MV88E61XX_SWITCH
  140. #if defined(CONFIG_VIDEO_IPUV3)
  141. static void enable_hdmi(struct display_info_t const *dev)
  142. {
  143. imx_enable_hdmi_phy();
  144. }
  145. static int detect_i2c(struct display_info_t const *dev)
  146. {
  147. return i2c_set_bus_num(dev->bus) == 0 &&
  148. i2c_probe(dev->addr) == 0;
  149. }
  150. static void enable_lvds(struct display_info_t const *dev)
  151. {
  152. struct iomuxc *iomux = (struct iomuxc *)
  153. IOMUXC_BASE_ADDR;
  154. /* set CH0 data width to 24bit (IOMUXC_GPR2:5 0=18bit, 1=24bit) */
  155. u32 reg = readl(&iomux->gpr[2]);
  156. reg |= IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT;
  157. writel(reg, &iomux->gpr[2]);
  158. /* Enable Backlight */
  159. gpio_request(IMX_GPIO_NR(1, 10), "bklt_gpio");
  160. gpio_direction_output(IMX_GPIO_NR(1, 10), 0);
  161. gpio_request(IMX_GPIO_NR(1, 18), "bklt_en");
  162. SETUP_IOMUX_PAD(PAD_SD1_CMD__GPIO1_IO18 | DIO_PAD_CFG);
  163. gpio_direction_output(IMX_GPIO_NR(1, 18), 1);
  164. }
  165. struct display_info_t const displays[] = {{
  166. /* HDMI Output */
  167. .bus = -1,
  168. .addr = 0,
  169. .pixfmt = IPU_PIX_FMT_RGB24,
  170. .detect = detect_hdmi,
  171. .enable = enable_hdmi,
  172. .mode = {
  173. .name = "HDMI",
  174. .refresh = 60,
  175. .xres = 1024,
  176. .yres = 768,
  177. .pixclock = 15385,
  178. .left_margin = 220,
  179. .right_margin = 40,
  180. .upper_margin = 21,
  181. .lower_margin = 7,
  182. .hsync_len = 60,
  183. .vsync_len = 10,
  184. .sync = FB_SYNC_EXT,
  185. .vmode = FB_VMODE_NONINTERLACED
  186. } }, {
  187. /* Freescale MXC-LVDS1: HannStar HSD100PXN1-A00 w/ egalx_ts cont */
  188. .bus = 2,
  189. .addr = 0x4,
  190. .pixfmt = IPU_PIX_FMT_LVDS666,
  191. .detect = detect_i2c,
  192. .enable = enable_lvds,
  193. .mode = {
  194. .name = "Hannstar-XGA",
  195. .refresh = 60,
  196. .xres = 1024,
  197. .yres = 768,
  198. .pixclock = 15385,
  199. .left_margin = 220,
  200. .right_margin = 40,
  201. .upper_margin = 21,
  202. .lower_margin = 7,
  203. .hsync_len = 60,
  204. .vsync_len = 10,
  205. .sync = FB_SYNC_EXT,
  206. .vmode = FB_VMODE_NONINTERLACED
  207. } }, {
  208. /* DLC700JMG-T-4 */
  209. .bus = 2,
  210. .addr = 0x38,
  211. .detect = NULL,
  212. .enable = enable_lvds,
  213. .pixfmt = IPU_PIX_FMT_LVDS666,
  214. .mode = {
  215. .name = "DLC700JMGT4",
  216. .refresh = 60,
  217. .xres = 1024, /* 1024x600active pixels */
  218. .yres = 600,
  219. .pixclock = 15385, /* 64MHz */
  220. .left_margin = 220,
  221. .right_margin = 40,
  222. .upper_margin = 21,
  223. .lower_margin = 7,
  224. .hsync_len = 60,
  225. .vsync_len = 10,
  226. .sync = FB_SYNC_EXT,
  227. .vmode = FB_VMODE_NONINTERLACED
  228. } }, {
  229. /* DLC800FIG-T-3 */
  230. .bus = 2,
  231. .addr = 0x14,
  232. .detect = NULL,
  233. .enable = enable_lvds,
  234. .pixfmt = IPU_PIX_FMT_LVDS666,
  235. .mode = {
  236. .name = "DLC800FIGT3",
  237. .refresh = 60,
  238. .xres = 1024, /* 1024x768 active pixels */
  239. .yres = 768,
  240. .pixclock = 15385, /* 64MHz */
  241. .left_margin = 220,
  242. .right_margin = 40,
  243. .upper_margin = 21,
  244. .lower_margin = 7,
  245. .hsync_len = 60,
  246. .vsync_len = 10,
  247. .sync = FB_SYNC_EXT,
  248. .vmode = FB_VMODE_NONINTERLACED
  249. } }, {
  250. .bus = 2,
  251. .addr = 0x5d,
  252. .detect = detect_i2c,
  253. .enable = enable_lvds,
  254. .pixfmt = IPU_PIX_FMT_LVDS666,
  255. .mode = {
  256. .name = "Z101WX01",
  257. .refresh = 60,
  258. .xres = 1280,
  259. .yres = 800,
  260. .pixclock = 15385, /* 64MHz */
  261. .left_margin = 220,
  262. .right_margin = 40,
  263. .upper_margin = 21,
  264. .lower_margin = 7,
  265. .hsync_len = 60,
  266. .vsync_len = 10,
  267. .sync = FB_SYNC_EXT,
  268. .vmode = FB_VMODE_NONINTERLACED
  269. }
  270. },
  271. };
  272. size_t display_count = ARRAY_SIZE(displays);
  273. static void setup_display(void)
  274. {
  275. struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
  276. struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
  277. int reg;
  278. enable_ipu_clock();
  279. imx_setup_hdmi();
  280. /* Turn on LDB0,IPU,IPU DI0 clocks */
  281. reg = __raw_readl(&mxc_ccm->CCGR3);
  282. reg |= MXC_CCM_CCGR3_LDB_DI0_MASK;
  283. writel(reg, &mxc_ccm->CCGR3);
  284. /* set LDB0, LDB1 clk select to 011/011 */
  285. reg = readl(&mxc_ccm->cs2cdr);
  286. reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK
  287. |MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
  288. reg |= (3<<MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET)
  289. |(3<<MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
  290. writel(reg, &mxc_ccm->cs2cdr);
  291. reg = readl(&mxc_ccm->cscmr2);
  292. reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV;
  293. writel(reg, &mxc_ccm->cscmr2);
  294. reg = readl(&mxc_ccm->chsccdr);
  295. reg |= (CHSCCDR_CLK_SEL_LDB_DI0
  296. <<MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
  297. writel(reg, &mxc_ccm->chsccdr);
  298. reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
  299. |IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_HIGH
  300. |IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
  301. |IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
  302. |IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
  303. |IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
  304. |IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
  305. |IOMUXC_GPR2_LVDS_CH1_MODE_DISABLED
  306. |IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0;
  307. writel(reg, &iomux->gpr[2]);
  308. reg = readl(&iomux->gpr[3]);
  309. reg = (reg & ~IOMUXC_GPR3_LVDS0_MUX_CTL_MASK)
  310. | (IOMUXC_GPR3_MUX_SRC_IPU1_DI0
  311. <<IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET);
  312. writel(reg, &iomux->gpr[3]);
  313. /* LVDS Backlight GPIO on LVDS connector - output low */
  314. SETUP_IOMUX_PAD(PAD_SD2_CLK__GPIO1_IO10 | DIO_PAD_CFG);
  315. gpio_direction_output(IMX_GPIO_NR(1, 10), 0);
  316. }
  317. #endif /* CONFIG_VIDEO_IPUV3 */
  318. /* setup board specific PMIC */
  319. int power_init_board(void)
  320. {
  321. setup_pmic();
  322. return 0;
  323. }
  324. int imx6_pcie_toggle_reset(void)
  325. {
  326. if (board_type < GW_UNKNOWN) {
  327. uint pin = gpio_cfg[board_type].pcie_rst;
  328. gpio_request(pin, "pci_rst#");
  329. gpio_direction_output(pin, 0);
  330. mdelay(50);
  331. gpio_direction_output(pin, 1);
  332. }
  333. return 0;
  334. }
  335. /*
  336. * Most Ventana boards have a PLX PEX860x PCIe switch onboard and use its
  337. * GPIO's as PERST# signals for its downstream ports - configure the GPIO's
  338. * properly and assert reset for 100ms.
  339. */
  340. #define MAX_PCI_DEVS 32
  341. struct pci_dev {
  342. pci_dev_t devfn;
  343. struct udevice *dev;
  344. unsigned short vendor;
  345. unsigned short device;
  346. unsigned short class;
  347. unsigned short busno; /* subbordinate busno */
  348. struct pci_dev *ppar;
  349. };
  350. struct pci_dev pci_devs[MAX_PCI_DEVS];
  351. int pci_devno;
  352. int pci_bridgeno;
  353. void board_pci_fixup_dev(struct udevice *bus, struct udevice *udev)
  354. {
  355. struct pci_child_plat *pdata = dev_get_parent_plat(udev);
  356. struct pci_dev *pdev = &pci_devs[pci_devno++];
  357. unsigned short vendor = pdata->vendor;
  358. unsigned short device = pdata->device;
  359. unsigned int class = pdata->class;
  360. pci_dev_t dev = dm_pci_get_bdf(udev);
  361. int i;
  362. debug("%s: %02d:%02d.%02d: %04x:%04x\n", __func__,
  363. PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev), vendor, device);
  364. /* store array of devs for later use in device-tree fixup */
  365. pdev->dev = udev;
  366. pdev->devfn = dev;
  367. pdev->vendor = vendor;
  368. pdev->device = device;
  369. pdev->class = class;
  370. pdev->ppar = NULL;
  371. if (class == PCI_CLASS_BRIDGE_PCI)
  372. pdev->busno = ++pci_bridgeno;
  373. else
  374. pdev->busno = 0;
  375. /* fixup RC - it should be 00:00.0 not 00:01.0 */
  376. if (PCI_BUS(dev) == 0)
  377. pdev->devfn = 0;
  378. /* find dev's parent */
  379. for (i = 0; i < pci_devno; i++) {
  380. if (pci_devs[i].busno == PCI_BUS(pdev->devfn)) {
  381. pdev->ppar = &pci_devs[i];
  382. break;
  383. }
  384. }
  385. /* assert downstream PERST# */
  386. if (vendor == PCI_VENDOR_ID_PLX &&
  387. (device & 0xfff0) == 0x8600 &&
  388. PCI_DEV(dev) == 0 && PCI_FUNC(dev) == 0) {
  389. ulong val;
  390. debug("configuring PLX 860X downstream PERST#\n");
  391. pci_bus_read_config(bus, dev, 0x62c, &val, PCI_SIZE_32);
  392. val |= 0xaaa8; /* GPIO1-7 outputs */
  393. pci_bus_write_config(bus, dev, 0x62c, val, PCI_SIZE_32);
  394. pci_bus_read_config(bus, dev, 0x644, &val, PCI_SIZE_32);
  395. val |= 0xfe; /* GPIO1-7 output high */
  396. pci_bus_write_config(bus, dev, 0x644, val, PCI_SIZE_32);
  397. mdelay(100);
  398. }
  399. }
  400. #ifdef CONFIG_SERIAL_TAG
  401. /*
  402. * called when setting up ATAGS before booting kernel
  403. * populate serialnum from the following (in order of priority):
  404. * serial# env var
  405. * eeprom
  406. */
  407. void get_board_serial(struct tag_serialnr *serialnr)
  408. {
  409. char *serial = env_get("serial#");
  410. if (serial) {
  411. serialnr->high = 0;
  412. serialnr->low = simple_strtoul(serial, NULL, 10);
  413. } else if (ventana_info.model[0]) {
  414. serialnr->high = 0;
  415. serialnr->low = ventana_info.serial;
  416. } else {
  417. serialnr->high = 0;
  418. serialnr->low = 0;
  419. }
  420. }
  421. #endif
  422. /*
  423. * Board Support
  424. */
  425. int board_early_init_f(void)
  426. {
  427. #if defined(CONFIG_VIDEO_IPUV3)
  428. setup_display();
  429. #endif
  430. return 0;
  431. }
  432. int dram_init(void)
  433. {
  434. gd->ram_size = imx_ddr_size();
  435. return 0;
  436. }
  437. int board_init(void)
  438. {
  439. struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
  440. clrsetbits_le32(&iomuxc_regs->gpr[1],
  441. IOMUXC_GPR1_OTG_ID_MASK,
  442. IOMUXC_GPR1_OTG_ID_GPIO1);
  443. /* address of linux boot parameters */
  444. gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
  445. /* read Gateworks EEPROM into global struct (used later) */
  446. setup_ventana_i2c(0);
  447. board_type = read_eeprom(CONFIG_I2C_GSC, &ventana_info);
  448. setup_ventana_i2c(1);
  449. setup_ventana_i2c(2);
  450. setup_iomux_gpio(board_type, &ventana_info);
  451. return 0;
  452. }
  453. int board_fit_config_name_match(const char *name)
  454. {
  455. static char init;
  456. const char *dtb;
  457. char buf[32];
  458. int i = 0;
  459. do {
  460. dtb = gsc_get_dtb_name(i++, buf, sizeof(buf));
  461. if (dtb && !strcmp(dtb, name)) {
  462. if (!init++)
  463. printf("DTB: %s\n", name);
  464. return 0;
  465. }
  466. } while (dtb);
  467. return -1;
  468. }
  469. #if defined(CONFIG_DISPLAY_BOARDINFO_LATE)
  470. /*
  471. * called during late init (after relocation and after board_init())
  472. * by virtue of CONFIG_DISPLAY_BOARDINFO_LATE as we needed i2c initialized and
  473. * EEPROM read.
  474. */
  475. int checkboard(void)
  476. {
  477. struct ventana_board_info *info = &ventana_info;
  478. unsigned char buf[4];
  479. const char *p;
  480. int quiet; /* Quiet or minimal output mode */
  481. quiet = 0;
  482. p = env_get("quiet");
  483. if (p)
  484. quiet = simple_strtol(p, NULL, 10);
  485. else
  486. env_set("quiet", "0");
  487. puts("\nGateworks Corporation Copyright 2014\n");
  488. if (info->model[0]) {
  489. printf("Model: %s\n", info->model);
  490. printf("MFGDate: %02x-%02x-%02x%02x\n",
  491. info->mfgdate[0], info->mfgdate[1],
  492. info->mfgdate[2], info->mfgdate[3]);
  493. printf("Serial:%d\n", info->serial);
  494. } else {
  495. puts("Invalid EEPROM - board will not function fully\n");
  496. }
  497. if (quiet)
  498. return 0;
  499. /* Display GSC firmware revision/CRC/status */
  500. gsc_info(0);
  501. /* Display RTC */
  502. if (!gsc_i2c_read(GSC_RTC_ADDR, 0x00, 1, buf, 4)) {
  503. printf("RTC: %d\n",
  504. buf[0] | buf[1]<<8 | buf[2]<<16 | buf[3]<<24);
  505. }
  506. return 0;
  507. }
  508. #endif
  509. #ifdef CONFIG_CMD_BMODE
  510. /*
  511. * BOOT_CFG1, BOOT_CFG2, BOOT_CFG3, BOOT_CFG4
  512. * see Table 8-11 and Table 5-9
  513. * BOOT_CFG1[7] = 1 (boot from NAND)
  514. * BOOT_CFG1[5] = 0 - raw NAND
  515. * BOOT_CFG1[4] = 0 - default pad settings
  516. * BOOT_CFG1[3:2] = 00 - devices = 1
  517. * BOOT_CFG1[1:0] = 00 - Row Address Cycles = 3
  518. * BOOT_CFG2[4:3] = 00 - Boot Search Count = 2
  519. * BOOT_CFG2[2:1] = 01 - Pages In Block = 64
  520. * BOOT_CFG2[0] = 0 - Reset time 12ms
  521. */
  522. static const struct boot_mode board_boot_modes[] = {
  523. /* NAND: 64pages per block, 3 row addr cycles, 2 copies of FCB/DBBT */
  524. { "nand", MAKE_CFGVAL(0x80, 0x02, 0x00, 0x00) },
  525. { "emmc2", MAKE_CFGVAL(0x60, 0x48, 0x00, 0x00) }, /* GW5600 */
  526. { "emmc3", MAKE_CFGVAL(0x60, 0x50, 0x00, 0x00) }, /* GW5903/4/5 */
  527. { NULL, 0 },
  528. };
  529. #endif
  530. /* late init */
  531. int misc_init_r(void)
  532. {
  533. struct ventana_board_info *info = &ventana_info;
  534. char buf[256];
  535. int i;
  536. /* set env vars based on EEPROM data */
  537. if (ventana_info.model[0]) {
  538. char str[16], fdt[36];
  539. char *p;
  540. const char *cputype = "";
  541. /*
  542. * FDT name will be prefixed with CPU type. Three versions
  543. * will be created each increasingly generic and bootloader
  544. * env scripts will try loading each from most specific to
  545. * least.
  546. */
  547. if (is_cpu_type(MXC_CPU_MX6Q) ||
  548. is_cpu_type(MXC_CPU_MX6D))
  549. cputype = "imx6q";
  550. else if (is_cpu_type(MXC_CPU_MX6DL) ||
  551. is_cpu_type(MXC_CPU_MX6SOLO))
  552. cputype = "imx6dl";
  553. env_set("soctype", cputype);
  554. if (8 << (ventana_info.nand_flash_size-1) >= 2048)
  555. env_set("flash_layout", "large");
  556. else
  557. env_set("flash_layout", "normal");
  558. memset(str, 0, sizeof(str));
  559. for (i = 0; i < (sizeof(str)-1) && info->model[i]; i++)
  560. str[i] = tolower(info->model[i]);
  561. env_set("model", str);
  562. if (!env_get("fdt_file")) {
  563. sprintf(fdt, "%s-%s.dtb", cputype, str);
  564. env_set("fdt_file", fdt);
  565. }
  566. p = strchr(str, '-');
  567. if (p) {
  568. *p++ = 0;
  569. env_set("model_base", str);
  570. sprintf(fdt, "%s-%s.dtb", cputype, str);
  571. env_set("fdt_file1", fdt);
  572. if (board_type != GW551x &&
  573. board_type != GW552x &&
  574. board_type != GW553x &&
  575. board_type != GW560x)
  576. str[4] = 'x';
  577. str[5] = 'x';
  578. str[6] = 0;
  579. sprintf(fdt, "%s-%s.dtb", cputype, str);
  580. env_set("fdt_file2", fdt);
  581. }
  582. /* initialize env from EEPROM */
  583. if (test_bit(EECONFIG_ETH0, info->config) &&
  584. !env_get("ethaddr")) {
  585. eth_env_set_enetaddr("ethaddr", info->mac0);
  586. }
  587. if (test_bit(EECONFIG_ETH1, info->config) &&
  588. !env_get("eth1addr")) {
  589. eth_env_set_enetaddr("eth1addr", info->mac1);
  590. }
  591. /* board serial-number */
  592. sprintf(str, "%6d", info->serial);
  593. env_set("serial#", str);
  594. /* memory MB */
  595. sprintf(str, "%d", (int) (gd->ram_size >> 20));
  596. env_set("mem_mb", str);
  597. }
  598. /* Set a non-initialized hwconfig based on board configuration */
  599. if (!strcmp(env_get("hwconfig"), "_UNKNOWN_")) {
  600. buf[0] = 0;
  601. if (gpio_cfg[board_type].rs232_en)
  602. strcat(buf, "rs232;");
  603. for (i = 0; i < gpio_cfg[board_type].dio_num; i++) {
  604. char buf1[32];
  605. sprintf(buf1, "dio%d:mode=gpio;", i);
  606. if (strlen(buf) + strlen(buf1) < sizeof(buf))
  607. strcat(buf, buf1);
  608. }
  609. env_set("hwconfig", buf);
  610. }
  611. /* setup baseboard specific GPIO based on board and env */
  612. setup_board_gpio(board_type, info);
  613. #ifdef CONFIG_CMD_BMODE
  614. add_board_boot_modes(board_boot_modes);
  615. #endif
  616. /* disable boot watchdog */
  617. gsc_boot_wd_disable();
  618. return 0;
  619. }
  620. #ifdef CONFIG_OF_BOARD_SETUP
  621. static int ft_sethdmiinfmt(void *blob, char *mode)
  622. {
  623. int off;
  624. if (!mode)
  625. return -EINVAL;
  626. off = fdt_node_offset_by_compatible(blob, -1, "nxp,tda1997x");
  627. if (off < 0)
  628. return off;
  629. if (0 == strcasecmp(mode, "yuv422bt656")) {
  630. u8 cfg[] = { 0x00, 0x00, 0x00, 0x82, 0x81, 0x00,
  631. 0x00, 0x00, 0x00 };
  632. mode = "422_ccir";
  633. fdt_setprop(blob, off, "vidout_fmt", mode, strlen(mode) + 1);
  634. fdt_setprop_u32(blob, off, "vidout_trc", 1);
  635. fdt_setprop_u32(blob, off, "vidout_blc", 1);
  636. fdt_setprop(blob, off, "vidout_portcfg", cfg, sizeof(cfg));
  637. printf(" set HDMI input mode to %s\n", mode);
  638. } else if (0 == strcasecmp(mode, "yuv422smp")) {
  639. u8 cfg[] = { 0x00, 0x00, 0x00, 0x88, 0x87, 0x00,
  640. 0x82, 0x81, 0x00 };
  641. mode = "422_smp";
  642. fdt_setprop(blob, off, "vidout_fmt", mode, strlen(mode) + 1);
  643. fdt_setprop_u32(blob, off, "vidout_trc", 0);
  644. fdt_setprop_u32(blob, off, "vidout_blc", 0);
  645. fdt_setprop(blob, off, "vidout_portcfg", cfg, sizeof(cfg));
  646. printf(" set HDMI input mode to %s\n", mode);
  647. } else {
  648. return -EINVAL;
  649. }
  650. return 0;
  651. }
  652. #if defined(CONFIG_CMD_PCI)
  653. #define PCI_ID(x) ( \
  654. (PCI_BUS(x->devfn)<<16)| \
  655. (PCI_DEV(x->devfn)<<11)| \
  656. (PCI_FUNC(x->devfn)<<8) \
  657. )
  658. int fdt_add_pci_node(void *blob, int par, struct pci_dev *dev)
  659. {
  660. uint32_t reg[5];
  661. char node[32];
  662. int np;
  663. sprintf(node, "pcie@%d,%d,%d", PCI_BUS(dev->devfn),
  664. PCI_DEV(dev->devfn), PCI_FUNC(dev->devfn));
  665. np = fdt_subnode_offset(blob, par, node);
  666. if (np >= 0)
  667. return np;
  668. np = fdt_add_subnode(blob, par, node);
  669. if (np < 0) {
  670. printf(" %s failed: no space\n", __func__);
  671. return np;
  672. }
  673. memset(reg, 0, sizeof(reg));
  674. reg[0] = cpu_to_fdt32(PCI_ID(dev));
  675. fdt_setprop(blob, np, "reg", reg, sizeof(reg));
  676. return np;
  677. }
  678. /* build a path of nested PCI devs for all bridges passed through */
  679. int fdt_add_pci_path(void *blob, struct pci_dev *dev)
  680. {
  681. struct pci_dev *bridges[MAX_PCI_DEVS];
  682. int k, np;
  683. /* build list of parents */
  684. np = fdt_node_offset_by_compatible(blob, -1, "fsl,imx6q-pcie");
  685. if (np < 0)
  686. return np;
  687. k = 0;
  688. while (dev) {
  689. bridges[k++] = dev;
  690. dev = dev->ppar;
  691. };
  692. /* now add them the to DT in reverse order */
  693. while (k--) {
  694. np = fdt_add_pci_node(blob, np, bridges[k]);
  695. if (np < 0)
  696. break;
  697. }
  698. return np;
  699. }
  700. /*
  701. * The GW16082 has a hardware errata errata such that it's
  702. * INTA/B/C/D are mis-mapped to its four slots (slot12-15). Because
  703. * of this normal PCI interrupt swizzling will not work so we will
  704. * provide an irq-map via device-tree.
  705. */
  706. int fdt_fixup_gw16082(void *blob, int np, struct pci_dev *dev)
  707. {
  708. int len;
  709. int host;
  710. uint32_t imap_new[8*4*4];
  711. const uint32_t *imap;
  712. uint32_t irq[4];
  713. uint32_t reg[4];
  714. int i;
  715. /* build irq-map based on host controllers map */
  716. host = fdt_node_offset_by_compatible(blob, -1, "fsl,imx6q-pcie");
  717. if (host < 0) {
  718. printf(" %s failed: missing host\n", __func__);
  719. return host;
  720. }
  721. /* use interrupt data from root complex's node */
  722. imap = fdt_getprop(blob, host, "interrupt-map", &len);
  723. if (!imap || len != 128) {
  724. printf(" %s failed: invalid interrupt-map\n",
  725. __func__);
  726. return -FDT_ERR_NOTFOUND;
  727. }
  728. /* obtain irq's of host controller in pin order */
  729. for (i = 0; i < 4; i++)
  730. irq[(fdt32_to_cpu(imap[(i*8)+3])-1)%4] = imap[(i*8)+6];
  731. /*
  732. * determine number of swizzles necessary:
  733. * For each bridge we pass through we need to swizzle
  734. * the number of the slot we are on.
  735. */
  736. struct pci_dev *d;
  737. int b;
  738. b = 0;
  739. d = dev->ppar;
  740. while(d && d->ppar) {
  741. b += PCI_DEV(d->devfn);
  742. d = d->ppar;
  743. }
  744. /* create new irq mappings for slots12-15
  745. * <skt> <idsel> <slot> <skt-inta> <skt-intb>
  746. * J3 AD28 12 INTD INTA
  747. * J4 AD29 13 INTC INTD
  748. * J5 AD30 14 INTB INTC
  749. * J2 AD31 15 INTA INTB
  750. */
  751. for (i = 0; i < 4; i++) {
  752. /* addr matches bus:dev:func */
  753. u32 addr = dev->busno << 16 | (12+i) << 11;
  754. /* default cells from root complex */
  755. memcpy(&imap_new[i*32], imap, 128);
  756. /* first cell is PCI device address (BDF) */
  757. imap_new[(i*32)+(0*8)+0] = cpu_to_fdt32(addr);
  758. imap_new[(i*32)+(1*8)+0] = cpu_to_fdt32(addr);
  759. imap_new[(i*32)+(2*8)+0] = cpu_to_fdt32(addr);
  760. imap_new[(i*32)+(3*8)+0] = cpu_to_fdt32(addr);
  761. /* third cell is pin */
  762. imap_new[(i*32)+(0*8)+3] = cpu_to_fdt32(1);
  763. imap_new[(i*32)+(1*8)+3] = cpu_to_fdt32(2);
  764. imap_new[(i*32)+(2*8)+3] = cpu_to_fdt32(3);
  765. imap_new[(i*32)+(3*8)+3] = cpu_to_fdt32(4);
  766. /* sixth cell is relative interrupt */
  767. imap_new[(i*32)+(0*8)+6] = irq[(15-(12+i)+b+0)%4];
  768. imap_new[(i*32)+(1*8)+6] = irq[(15-(12+i)+b+1)%4];
  769. imap_new[(i*32)+(2*8)+6] = irq[(15-(12+i)+b+2)%4];
  770. imap_new[(i*32)+(3*8)+6] = irq[(15-(12+i)+b+3)%4];
  771. }
  772. fdt_setprop(blob, np, "interrupt-map", imap_new,
  773. sizeof(imap_new));
  774. reg[0] = cpu_to_fdt32(0xfff00);
  775. reg[1] = 0;
  776. reg[2] = 0;
  777. reg[3] = cpu_to_fdt32(0x7);
  778. fdt_setprop(blob, np, "interrupt-map-mask", reg, sizeof(reg));
  779. fdt_setprop_cell(blob, np, "#interrupt-cells", 1);
  780. fdt_setprop_string(blob, np, "device_type", "pci");
  781. fdt_setprop_cell(blob, np, "#address-cells", 3);
  782. fdt_setprop_cell(blob, np, "#size-cells", 2);
  783. printf(" Added custom interrupt-map for GW16082\n");
  784. return 0;
  785. }
  786. /* The sky2 GigE MAC obtains it's MAC addr from device-tree by default */
  787. int fdt_fixup_sky2(void *blob, int np, struct pci_dev *dev)
  788. {
  789. char *tmp, *end;
  790. char mac[16];
  791. unsigned char mac_addr[6];
  792. int j;
  793. sprintf(mac, "eth1addr");
  794. tmp = env_get(mac);
  795. if (tmp) {
  796. for (j = 0; j < 6; j++) {
  797. mac_addr[j] = tmp ?
  798. simple_strtoul(tmp, &end,16) : 0;
  799. if (tmp)
  800. tmp = (*end) ? end+1 : end;
  801. }
  802. fdt_setprop(blob, np, "local-mac-address", mac_addr,
  803. sizeof(mac_addr));
  804. printf(" Added mac addr for eth1\n");
  805. return 0;
  806. }
  807. return -1;
  808. }
  809. /*
  810. * PCI DT nodes must be nested therefore if we need to apply a DT fixup
  811. * we will walk the PCI bus and add bridge nodes up to the device receiving
  812. * the fixup.
  813. */
  814. void ft_board_pci_fixup(void *blob, struct bd_info *bd)
  815. {
  816. int i, np;
  817. struct pci_dev *dev;
  818. for (i = 0; i < pci_devno; i++) {
  819. dev = &pci_devs[i];
  820. /*
  821. * The GW16082 consists of a TI XIO2001 PCIe-to-PCI bridge and
  822. * an EEPROM at i2c1-0x50.
  823. */
  824. if ((dev->vendor == PCI_VENDOR_ID_TI) &&
  825. (dev->device == 0x8240) &&
  826. (i2c_set_bus_num(1) == 0) &&
  827. (i2c_probe(0x50) == 0))
  828. {
  829. np = fdt_add_pci_path(blob, dev);
  830. if (np > 0)
  831. fdt_fixup_gw16082(blob, np, dev);
  832. }
  833. /* ethernet1 mac address */
  834. else if ((dev->vendor == PCI_VENDOR_ID_MARVELL) &&
  835. (dev->device == 0x4380))
  836. {
  837. np = fdt_add_pci_path(blob, dev);
  838. if (np > 0)
  839. fdt_fixup_sky2(blob, np, dev);
  840. }
  841. }
  842. }
  843. #endif /* if defined(CONFIG_CMD_PCI) */
  844. void ft_board_wdog_fixup(void *blob, phys_addr_t addr)
  845. {
  846. int off = fdt_node_offset_by_compat_reg(blob, "fsl,imx6q-wdt", addr);
  847. if (off) {
  848. fdt_delprop(blob, off, "ext-reset-output");
  849. fdt_delprop(blob, off, "fsl,ext-reset-output");
  850. }
  851. }
  852. /*
  853. * called prior to booting kernel or by 'fdt boardsetup' command
  854. *
  855. * unless 'fdt_noauto' env var is set we will update the following in the DTB:
  856. * - mtd partitions based on mtdparts/mtdids env
  857. * - system-serial (board serial num from EEPROM)
  858. * - board (full model from EEPROM)
  859. * - peripherals removed from DTB if not loaded on board (per EEPROM config)
  860. */
  861. #define WDOG1_ADDR 0x20bc000
  862. #define WDOG2_ADDR 0x20c0000
  863. #define GPIO3_ADDR 0x20a4000
  864. #define USDHC3_ADDR 0x2198000
  865. #define PWM0_ADDR 0x2080000
  866. int ft_board_setup(void *blob, struct bd_info *bd)
  867. {
  868. struct ventana_board_info *info = &ventana_info;
  869. struct ventana_eeprom_config *cfg;
  870. static const struct node_info nodes[] = {
  871. { "sst,w25q256", MTD_DEV_TYPE_NOR, }, /* SPI flash */
  872. { "fsl,imx6q-gpmi-nand", MTD_DEV_TYPE_NAND, }, /* NAND flash */
  873. };
  874. const char *model = env_get("model");
  875. const char *display = env_get("display");
  876. int i;
  877. char rev = 0;
  878. /* determine board revision */
  879. for (i = sizeof(ventana_info.model) - 1; i > 0; i--) {
  880. if (ventana_info.model[i] >= 'A') {
  881. rev = ventana_info.model[i];
  882. break;
  883. }
  884. }
  885. if (env_get("fdt_noauto")) {
  886. puts(" Skiping ft_board_setup (fdt_noauto defined)\n");
  887. return 0;
  888. }
  889. if (test_bit(EECONFIG_NAND, info->config)) {
  890. /* Update partition nodes using info from mtdparts env var */
  891. puts(" Updating MTD partitions...\n");
  892. fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
  893. }
  894. /* Update display timings from display env var */
  895. if (display) {
  896. if (fdt_fixup_display(blob, fdt_get_alias(blob, "lvds0"),
  897. display) >= 0)
  898. printf(" Set display timings for %s...\n", display);
  899. }
  900. printf(" Adjusting FDT per EEPROM for %s...\n", model);
  901. /* board serial number */
  902. fdt_setprop(blob, 0, "system-serial", env_get("serial#"),
  903. strlen(env_get("serial#")) + 1);
  904. /* board (model contains model from device-tree) */
  905. fdt_setprop(blob, 0, "board", info->model,
  906. strlen((const char *)info->model) + 1);
  907. /* set desired digital video capture format */
  908. ft_sethdmiinfmt(blob, env_get("hdmiinfmt"));
  909. /*
  910. * Board model specific fixups
  911. */
  912. switch (board_type) {
  913. case GW51xx:
  914. /*
  915. * disable wdog node for GW51xx-A/B to work around
  916. * errata causing wdog timer to be unreliable.
  917. */
  918. if (rev >= 'A' && rev < 'C') {
  919. i = fdt_node_offset_by_compat_reg(blob, "fsl,imx6q-wdt",
  920. WDOG1_ADDR);
  921. if (i)
  922. fdt_status_disabled(blob, i);
  923. }
  924. /* GW51xx-E adds WDOG1_B external reset */
  925. if (rev < 'E')
  926. ft_board_wdog_fixup(blob, WDOG1_ADDR);
  927. break;
  928. case GW52xx:
  929. /* GW522x Uses GPIO3_IO23 instead of GPIO1_IO29 */
  930. if (info->model[4] == '2') {
  931. u32 handle = 0;
  932. u32 *range = NULL;
  933. i = fdt_node_offset_by_compatible(blob, -1,
  934. "fsl,imx6q-pcie");
  935. if (i)
  936. range = (u32 *)fdt_getprop(blob, i,
  937. "reset-gpio", NULL);
  938. if (range) {
  939. i = fdt_node_offset_by_compat_reg(blob,
  940. "fsl,imx6q-gpio", GPIO3_ADDR);
  941. if (i)
  942. handle = fdt_get_phandle(blob, i);
  943. if (handle) {
  944. range[0] = cpu_to_fdt32(handle);
  945. range[1] = cpu_to_fdt32(23);
  946. }
  947. }
  948. /* these have broken usd_vsel */
  949. if (strstr((const char *)info->model, "SP318-B") ||
  950. strstr((const char *)info->model, "SP331-B"))
  951. gpio_cfg[board_type].usd_vsel = 0;
  952. /* GW522x-B adds WDOG1_B external reset */
  953. if (rev < 'B')
  954. ft_board_wdog_fixup(blob, WDOG1_ADDR);
  955. }
  956. /* GW520x-E adds WDOG1_B external reset */
  957. else if (info->model[4] == '0' && rev < 'E')
  958. ft_board_wdog_fixup(blob, WDOG1_ADDR);
  959. break;
  960. case GW53xx:
  961. /* GW53xx-E adds WDOG1_B external reset */
  962. if (rev < 'E')
  963. ft_board_wdog_fixup(blob, WDOG1_ADDR);
  964. break;
  965. case GW54xx:
  966. /*
  967. * disable serial2 node for GW54xx for compatibility with older
  968. * 3.10.x kernel that improperly had this node enabled in the DT
  969. */
  970. fdt_set_status_by_alias(blob, "serial2", FDT_STATUS_DISABLED,
  971. 0);
  972. /* GW54xx-E adds WDOG2_B external reset */
  973. if (rev < 'E')
  974. ft_board_wdog_fixup(blob, WDOG2_ADDR);
  975. break;
  976. case GW551x:
  977. /*
  978. * isolate CSI0_DATA_EN for GW551x-A to work around errata
  979. * causing non functional digital video in (it is not hooked up)
  980. */
  981. if (rev == 'A') {
  982. u32 *range = NULL;
  983. int len;
  984. const u32 *handle = NULL;
  985. i = fdt_node_offset_by_compatible(blob, -1,
  986. "fsl,imx-tda1997x-video");
  987. if (i)
  988. handle = fdt_getprop(blob, i, "pinctrl-0",
  989. NULL);
  990. if (handle)
  991. i = fdt_node_offset_by_phandle(blob,
  992. fdt32_to_cpu(*handle));
  993. if (i)
  994. range = (u32 *)fdt_getprop(blob, i, "fsl,pins",
  995. &len);
  996. if (range) {
  997. len /= sizeof(u32);
  998. for (i = 0; i < len; i += 6) {
  999. u32 mux_reg = fdt32_to_cpu(range[i+0]);
  1000. u32 conf_reg = fdt32_to_cpu(range[i+1]);
  1001. /* mux PAD_CSI0_DATA_EN to GPIO */
  1002. if (is_cpu_type(MXC_CPU_MX6Q) &&
  1003. mux_reg == 0x260 &&
  1004. conf_reg == 0x630)
  1005. range[i+3] = cpu_to_fdt32(0x5);
  1006. else if (!is_cpu_type(MXC_CPU_MX6Q) &&
  1007. mux_reg == 0x08c &&
  1008. conf_reg == 0x3a0)
  1009. range[i+3] = cpu_to_fdt32(0x5);
  1010. }
  1011. fdt_setprop_inplace(blob, i, "fsl,pins", range,
  1012. len);
  1013. }
  1014. /* set BT656 video format */
  1015. ft_sethdmiinfmt(blob, "yuv422bt656");
  1016. }
  1017. /* GW551x-C adds WDOG1_B external reset */
  1018. if (rev < 'C')
  1019. ft_board_wdog_fixup(blob, WDOG1_ADDR);
  1020. break;
  1021. case GW5901:
  1022. case GW5902:
  1023. /* GW5901/GW5901 revB adds WDOG1_B as an external reset */
  1024. if (rev < 'B')
  1025. ft_board_wdog_fixup(blob, WDOG1_ADDR);
  1026. break;
  1027. }
  1028. /* Configure DIO */
  1029. for (i = 0; i < gpio_cfg[board_type].dio_num; i++) {
  1030. struct dio_cfg *cfg = &gpio_cfg[board_type].dio_cfg[i];
  1031. char arg[10];
  1032. sprintf(arg, "dio%d", i);
  1033. if (!hwconfig(arg))
  1034. continue;
  1035. if (hwconfig_subarg_cmp(arg, "mode", "pwm") && cfg->pwm_param)
  1036. {
  1037. phys_addr_t addr;
  1038. int off;
  1039. printf(" Enabling pwm%d for DIO%d\n",
  1040. cfg->pwm_param, i);
  1041. addr = PWM0_ADDR + (0x4000 * (cfg->pwm_param - 1));
  1042. off = fdt_node_offset_by_compat_reg(blob,
  1043. "fsl,imx6q-pwm",
  1044. addr);
  1045. if (off)
  1046. fdt_status_okay(blob, off);
  1047. }
  1048. }
  1049. /* remove no-1-8-v if UHS-I support is present */
  1050. if (gpio_cfg[board_type].usd_vsel) {
  1051. debug("Enabling UHS-I support\n");
  1052. i = fdt_node_offset_by_compat_reg(blob, "fsl,imx6q-usdhc",
  1053. USDHC3_ADDR);
  1054. if (i)
  1055. fdt_delprop(blob, i, "no-1-8-v");
  1056. }
  1057. #if defined(CONFIG_CMD_PCI)
  1058. if (!env_get("nopcifixup"))
  1059. ft_board_pci_fixup(blob, bd);
  1060. #endif
  1061. /*
  1062. * Peripheral Config:
  1063. * remove nodes by alias path if EEPROM config tells us the
  1064. * peripheral is not loaded on the board.
  1065. */
  1066. if (env_get("fdt_noconfig")) {
  1067. puts(" Skiping periperhal config (fdt_noconfig defined)\n");
  1068. return 0;
  1069. }
  1070. cfg = econfig;
  1071. while (cfg->name) {
  1072. if (!test_bit(cfg->bit, info->config)) {
  1073. fdt_del_node_and_alias(blob, cfg->dtalias ?
  1074. cfg->dtalias : cfg->name);
  1075. }
  1076. cfg++;
  1077. }
  1078. return 0;
  1079. }
  1080. #endif /* CONFIG_OF_BOARD_SETUP */