xref: /openbmc/u-boot/board/samtec/vining_2000/vining_2000.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1  // SPDX-License-Identifier: GPL-2.0+
2  /*
3   * Copyright (C) 2016 samtec automotive software & electronics gmbh
4   *
5   * Author: Christoph Fritz <chf.fritz@googlemail.com>
6   */
7  
8  #include <asm/arch/clock.h>
9  #include <asm/arch/crm_regs.h>
10  #include <asm/arch/iomux.h>
11  #include <asm/arch/imx-regs.h>
12  #include <asm/arch/mx6-pins.h>
13  #include <asm/arch/sys_proto.h>
14  #include <asm/gpio.h>
15  #include <asm/mach-imx/iomux-v3.h>
16  #include <asm/io.h>
17  #include <asm/mach-imx/mxc_i2c.h>
18  #include <linux/sizes.h>
19  #include <common.h>
20  #include <environment.h>
21  #include <fsl_esdhc.h>
22  #include <mmc.h>
23  #include <i2c.h>
24  #include <miiphy.h>
25  #include <netdev.h>
26  #include <power/pmic.h>
27  #include <power/pfuze100_pmic.h>
28  #include <usb.h>
29  #include <usb/ehci-ci.h>
30  #include <pwm.h>
31  #include <wait_bit.h>
32  
33  DECLARE_GLOBAL_DATA_PTR;
34  
35  #define UART_PAD_CTRL  (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP |	\
36  	PAD_CTL_PKE | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |	\
37  	PAD_CTL_SRE_FAST)
38  
39  #define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP | PAD_CTL_PKE |	\
40  	PAD_CTL_SPEED_HIGH | PAD_CTL_DSE_48ohm |		\
41  	PAD_CTL_SRE_FAST)
42  
43  #define ENET_CLK_PAD_CTRL  PAD_CTL_DSE_34ohm
44  
45  #define ENET_RX_PAD_CTRL  (PAD_CTL_PKE |			\
46  	PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_HIGH |		\
47  	PAD_CTL_SRE_FAST)
48  
49  #define I2C_PAD_CTRL  (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP |	\
50  	PAD_CTL_PKE | PAD_CTL_ODE | PAD_CTL_SPEED_MED |		\
51  	PAD_CTL_DSE_40ohm)
52  
53  #define USDHC_CLK_PAD_CTRL  (PAD_CTL_HYS | PAD_CTL_SPEED_MED |	\
54  	PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST)
55  
56  #define USDHC_PAD_CTRL  (PAD_CTL_HYS | PAD_CTL_PUS_47K_UP |	\
57  	PAD_CTL_PKE |  PAD_CTL_SPEED_MED | PAD_CTL_DSE_80ohm |	\
58  	PAD_CTL_SRE_FAST)
59  
60  #define GPIO_PAD_CTRL  (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP |	\
61  	PAD_CTL_PKE)
62  
dram_init(void)63  int dram_init(void)
64  {
65  	gd->ram_size = imx_ddr_size();
66  
67  	return 0;
68  }
69  
70  static iomux_v3_cfg_t const uart1_pads[] = {
71  	MX6_PAD_GPIO1_IO04__UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
72  	MX6_PAD_GPIO1_IO05__UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
73  };
74  
75  static iomux_v3_cfg_t const usdhc2_pads[] = {
76  	MX6_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_CLK_PAD_CTRL),
77  	MX6_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
78  	MX6_PAD_SD2_DATA0__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
79  	MX6_PAD_SD2_DATA1__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
80  	MX6_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
81  	MX6_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
82  	MX6_PAD_LCD1_VSYNC__GPIO3_IO_28 | MUX_PAD_CTRL(GPIO_PAD_CTRL),
83  };
84  
85  static iomux_v3_cfg_t const usdhc4_pads[] = {
86  	MX6_PAD_SD4_CLK__USDHC4_CLK | MUX_PAD_CTRL(USDHC_CLK_PAD_CTRL),
87  	MX6_PAD_SD4_CMD__USDHC4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
88  	MX6_PAD_SD4_DATA0__USDHC4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
89  	MX6_PAD_SD4_DATA1__USDHC4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
90  	MX6_PAD_SD4_DATA2__USDHC4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
91  	MX6_PAD_SD4_DATA3__USDHC4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
92  	MX6_PAD_SD4_DATA4__USDHC4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
93  	MX6_PAD_SD4_DATA5__USDHC4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
94  	MX6_PAD_SD4_DATA6__USDHC4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
95  	MX6_PAD_SD4_DATA7__USDHC4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
96  };
97  
98  static iomux_v3_cfg_t const fec1_pads[] = {
99  	MX6_PAD_ENET1_MDC__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
100  	MX6_PAD_ENET1_MDIO__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
101  	MX6_PAD_RGMII1_RD0__ENET1_RX_DATA_0 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
102  	MX6_PAD_RGMII1_RD1__ENET1_RX_DATA_1 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
103  	MX6_PAD_RGMII1_TD0__ENET1_TX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
104  	MX6_PAD_RGMII1_TD1__ENET1_TX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
105  	MX6_PAD_RGMII1_RX_CTL__ENET1_RX_EN | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),
106  	MX6_PAD_RGMII1_TX_CTL__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),
107  	MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL) |
108  		MUX_MODE_SION,
109  	/* LAN8720 PHY Reset */
110  	MX6_PAD_RGMII1_TD3__GPIO5_IO_9 | MUX_PAD_CTRL(NO_PAD_CTRL),
111  };
112  
113  static iomux_v3_cfg_t const pwm_led_pads[] = {
114  	MX6_PAD_RGMII2_RD2__PWM2_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* green */
115  	MX6_PAD_RGMII2_TD2__PWM6_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* red */
116  	MX6_PAD_RGMII2_RD3__PWM1_OUT | MUX_PAD_CTRL(NO_PAD_CTRL), /* blue */
117  };
118  
setup_iomux_uart(void)119  static void setup_iomux_uart(void)
120  {
121  	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
122  }
123  
124  #define PHY_RESET IMX_GPIO_NR(5, 9)
125  
board_eth_init(bd_t * bis)126  int board_eth_init(bd_t *bis)
127  {
128  	struct iomuxc *iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
129  	int ret;
130  	unsigned char eth1addr[6];
131  
132  	/* just to get secound mac address */
133  	imx_get_mac_from_fuse(1, eth1addr);
134  	if (!env_get("eth1addr") && is_valid_ethaddr(eth1addr))
135  		eth_env_set_enetaddr("eth1addr", eth1addr);
136  
137  	imx_iomux_v3_setup_multiple_pads(fec1_pads, ARRAY_SIZE(fec1_pads));
138  
139  	/*
140  	 * Generate phy reference clock via pin IOMUX ENET_REF_CLK1/2 by erasing
141  	 * ENET1/2_TX_CLK_DIR gpr1[14:13], so that reference clock is driven by
142  	 * ref_enetpll0/1 and enable ENET1/2_TX_CLK output driver.
143  	 */
144  	clrsetbits_le32(&iomuxc_regs->gpr[1],
145  			IOMUX_GPR1_FEC1_CLOCK_MUX2_SEL_MASK |
146  			IOMUX_GPR1_FEC2_CLOCK_MUX2_SEL_MASK,
147  			IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK |
148  			IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK);
149  
150  	ret = enable_fec_anatop_clock(0, ENET_50MHZ);
151  	if (ret)
152  		goto eth_fail;
153  
154  	/* reset phy */
155  	gpio_direction_output(PHY_RESET, 0);
156  	mdelay(16);
157  	gpio_set_value(PHY_RESET, 1);
158  	mdelay(1);
159  
160  	ret = fecmxc_initialize_multi(bis, 0, CONFIG_FEC_MXC_PHYADDR,
161  					IMX_FEC_BASE);
162  	if (ret)
163  		goto eth_fail;
164  
165  	return ret;
166  
167  eth_fail:
168  	printf("FEC MXC: %s:failed (%i)\n", __func__, ret);
169  	gpio_set_value(PHY_RESET, 0);
170  	return ret;
171  }
172  
173  #define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
174  /* I2C1 for PMIC */
175  static struct i2c_pads_info i2c_pad_info1 = {
176  	.scl = {
177  		.i2c_mode = MX6_PAD_GPIO1_IO00__I2C1_SCL | PC,
178  		.gpio_mode = MX6_PAD_GPIO1_IO00__GPIO1_IO_0 | PC,
179  		.gp = IMX_GPIO_NR(1, 0),
180  	},
181  	.sda = {
182  		.i2c_mode = MX6_PAD_GPIO1_IO01__I2C1_SDA | PC,
183  		.gpio_mode = MX6_PAD_GPIO1_IO01__GPIO1_IO_1 | PC,
184  		.gp = IMX_GPIO_NR(1, 1),
185  	},
186  };
187  
pfuze_init(unsigned char i2cbus)188  static struct pmic *pfuze_init(unsigned char i2cbus)
189  {
190  	struct pmic *p;
191  	int ret;
192  	u32 reg;
193  
194  	ret = power_pfuze100_init(i2cbus);
195  	if (ret)
196  		return NULL;
197  
198  	p = pmic_get("PFUZE100");
199  	ret = pmic_probe(p);
200  	if (ret)
201  		return NULL;
202  
203  	pmic_reg_read(p, PFUZE100_DEVICEID, &reg);
204  	printf("PMIC:  PFUZE100 ID=0x%02x\n", reg);
205  
206  	/* Set SW1AB stanby volage to 0.975V */
207  	pmic_reg_read(p, PFUZE100_SW1ABSTBY, &reg);
208  	reg &= ~SW1x_STBY_MASK;
209  	reg |= SW1x_0_975V;
210  	pmic_reg_write(p, PFUZE100_SW1ABSTBY, reg);
211  
212  	/* Set SW1AB/VDDARM step ramp up time from 16us to 4us/25mV */
213  	pmic_reg_read(p, PFUZE100_SW1ABCONF, &reg);
214  	reg &= ~SW1xCONF_DVSSPEED_MASK;
215  	reg |= SW1xCONF_DVSSPEED_4US;
216  	pmic_reg_write(p, PFUZE100_SW1ABCONF, reg);
217  
218  	/* Set SW1C standby voltage to 0.975V */
219  	pmic_reg_read(p, PFUZE100_SW1CSTBY, &reg);
220  	reg &= ~SW1x_STBY_MASK;
221  	reg |= SW1x_0_975V;
222  	pmic_reg_write(p, PFUZE100_SW1CSTBY, reg);
223  
224  	/* Set SW1C/VDDSOC step ramp up time from 16us to 4us/25mV */
225  	pmic_reg_read(p, PFUZE100_SW1CCONF, &reg);
226  	reg &= ~SW1xCONF_DVSSPEED_MASK;
227  	reg |= SW1xCONF_DVSSPEED_4US;
228  	pmic_reg_write(p, PFUZE100_SW1CCONF, reg);
229  
230  	return p;
231  }
232  
pfuze_mode_init(struct pmic * p,u32 mode)233  static int pfuze_mode_init(struct pmic *p, u32 mode)
234  {
235  	unsigned char offset, i, switch_num;
236  	u32 id;
237  	int ret;
238  
239  	pmic_reg_read(p, PFUZE100_DEVICEID, &id);
240  	id = id & 0xf;
241  
242  	if (id == 0) {
243  		switch_num = 6;
244  		offset = PFUZE100_SW1CMODE;
245  	} else if (id == 1) {
246  		switch_num = 4;
247  		offset = PFUZE100_SW2MODE;
248  	} else {
249  		printf("Not supported, id=%d\n", id);
250  		return -EINVAL;
251  	}
252  
253  	ret = pmic_reg_write(p, PFUZE100_SW1ABMODE, mode);
254  	if (ret < 0) {
255  		printf("Set SW1AB mode error!\n");
256  		return ret;
257  	}
258  
259  	for (i = 0; i < switch_num - 1; i++) {
260  		ret = pmic_reg_write(p, offset + i * SWITCH_SIZE, mode);
261  		if (ret < 0) {
262  			printf("Set switch 0x%x mode error!\n",
263  			       offset + i * SWITCH_SIZE);
264  			return ret;
265  		}
266  	}
267  
268  	return ret;
269  }
270  
power_init_board(void)271  int power_init_board(void)
272  {
273  	struct pmic *p;
274  	int ret;
275  
276  	p = pfuze_init(I2C_PMIC);
277  	if (!p)
278  		return -ENODEV;
279  
280  	ret = pfuze_mode_init(p, APS_PFM);
281  	if (ret < 0)
282  		return ret;
283  
284  	return 0;
285  }
286  
287  #ifdef CONFIG_USB_EHCI_MX6
288  static iomux_v3_cfg_t const usb_otg_pads[] = {
289  	/* OGT1 */
290  	MX6_PAD_GPIO1_IO09__USB_OTG1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL),
291  	MX6_PAD_GPIO1_IO10__ANATOP_OTG1_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
292  	/* OTG2 */
293  	MX6_PAD_GPIO1_IO12__USB_OTG2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL)
294  };
295  
setup_iomux_usb(void)296  static void setup_iomux_usb(void)
297  {
298  	imx_iomux_v3_setup_multiple_pads(usb_otg_pads,
299  					 ARRAY_SIZE(usb_otg_pads));
300  }
301  
board_usb_phy_mode(int port)302  int board_usb_phy_mode(int port)
303  {
304  	if (port == 1)
305  		return USB_INIT_HOST;
306  	else
307  		return usb_phy_mode(port);
308  }
309  #endif
310  
311  #ifdef CONFIG_PWM_IMX
set_pwm_leds(void)312  static int set_pwm_leds(void)
313  {
314  	int ret;
315  
316  	imx_iomux_v3_setup_multiple_pads(pwm_led_pads,
317  					 ARRAY_SIZE(pwm_led_pads));
318  	/* enable backlight PWM 2, green LED */
319  	ret = pwm_init(1, 0, 0);
320  	if (ret)
321  		goto error;
322  	/* duty cycle 200ns, period: 8000ns */
323  	ret = pwm_config(1, 200, 8000);
324  	if (ret)
325  		goto error;
326  	ret = pwm_enable(1);
327  	if (ret)
328  		goto error;
329  
330  	/* enable backlight PWM 1, blue LED */
331  	ret = pwm_init(0, 0, 0);
332  	if (ret)
333  		goto error;
334  	/* duty cycle 200ns, period: 8000ns */
335  	ret = pwm_config(0, 200, 8000);
336  	if (ret)
337  		goto error;
338  	ret = pwm_enable(0);
339  	if (ret)
340  		goto error;
341  
342  	/* enable backlight PWM 6, red LED */
343  	ret = pwm_init(5, 0, 0);
344  	if (ret)
345  		goto error;
346  	/* duty cycle 200ns, period: 8000ns */
347  	ret = pwm_config(5, 200, 8000);
348  	if (ret)
349  		goto error;
350  	ret = pwm_enable(5);
351  
352  error:
353  	return ret;
354  }
355  #else
set_pwm_leds(void)356  static int set_pwm_leds(void)
357  {
358  	return 0;
359  }
360  #endif
361  
362  #define ADCx_HC0        0x00
363  #define ADCx_HS         0x08
364  #define ADCx_HS_C0      BIT(0)
365  #define ADCx_R0         0x0c
366  #define ADCx_CFG        0x14
367  #define ADCx_CFG_SWMODE 0x308
368  #define ADCx_GC         0x18
369  #define ADCx_GC_CAL     BIT(7)
370  
read_adc(u32 * val)371  static int read_adc(u32 *val)
372  {
373  	int ret;
374  	void __iomem *b = map_physmem(ADC1_BASE_ADDR, 0x100, MAP_NOCACHE);
375  
376  	/* use software mode */
377  	writel(ADCx_CFG_SWMODE, b + ADCx_CFG);
378  
379  	/* start auto calibration */
380  	setbits_le32(b + ADCx_GC, ADCx_GC_CAL);
381  	ret = wait_for_bit_le32(b + ADCx_GC, ADCx_GC_CAL, ADCx_GC_CAL, 10, 0);
382  	if (ret)
383  		goto adc_exit;
384  
385  	/* start conversion */
386  	writel(0, b + ADCx_HC0);
387  
388  	/* wait for conversion */
389  	ret = wait_for_bit_le32(b + ADCx_HS, ADCx_HS_C0, ADCx_HS_C0, 10, 0);
390  	if (ret)
391  		goto adc_exit;
392  
393  	/* read result */
394  	*val = readl(b + ADCx_R0);
395  
396  adc_exit:
397  	if (ret)
398  		printf("ADC failure (ret=%i)\n", ret);
399  	unmap_physmem(b, MAP_NOCACHE);
400  	return ret;
401  }
402  
403  #define VAL_UPPER	2498
404  #define VAL_LOWER	1550
405  
set_pin_state(void)406  static int set_pin_state(void)
407  {
408  	u32 val;
409  	int ret;
410  
411  	ret = read_adc(&val);
412  	if (ret)
413  		return ret;
414  
415  	if (val >= VAL_UPPER)
416  		env_set("pin_state", "connected");
417  	else if (val < VAL_UPPER && val > VAL_LOWER)
418  		env_set("pin_state", "open");
419  	else
420  		env_set("pin_state", "button");
421  
422  	return ret;
423  }
424  
board_late_init(void)425  int board_late_init(void)
426  {
427  	int ret;
428  
429  	ret = set_pwm_leds();
430  	if (ret)
431  		return ret;
432  
433  	ret = set_pin_state();
434  
435  	return ret;
436  }
437  
board_early_init_f(void)438  int board_early_init_f(void)
439  {
440  	setup_iomux_uart();
441  
442  	setup_iomux_usb();
443  
444  	return 0;
445  }
446  
447  static struct fsl_esdhc_cfg usdhc_cfg[2] = {
448  	{USDHC4_BASE_ADDR, 0, 8},
449  	{USDHC2_BASE_ADDR, 0, 4},
450  };
451  
452  #define USDHC2_CD_GPIO IMX_GPIO_NR(3, 28)
453  
board_mmc_getcd(struct mmc * mmc)454  int board_mmc_getcd(struct mmc *mmc)
455  {
456  	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
457  
458  	if (cfg->esdhc_base == USDHC4_BASE_ADDR)
459  		return 1;
460  	if (cfg->esdhc_base == USDHC2_BASE_ADDR)
461  		return !gpio_get_value(USDHC2_CD_GPIO);
462  
463  	return -EINVAL;
464  }
465  
board_mmc_init(bd_t * bis)466  int board_mmc_init(bd_t *bis)
467  {
468  	int ret;
469  
470  	/*
471  	 * According to the board_mmc_init() the following map is done:
472  	 * (U-Boot device node)    (Physical Port)
473  	 * mmc0                    USDHC4
474  	 * mmc1                    USDHC2
475  	 */
476  	imx_iomux_v3_setup_multiple_pads(
477  		usdhc4_pads, ARRAY_SIZE(usdhc4_pads));
478  	usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
479  
480  	imx_iomux_v3_setup_multiple_pads(
481  		usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
482  	gpio_direction_input(USDHC2_CD_GPIO);
483  	usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
484  
485  	ret = fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
486  	if (ret) {
487  		printf("Warning: failed to initialize USDHC4\n");
488  		return ret;
489  	}
490  
491  	ret = fsl_esdhc_initialize(bis, &usdhc_cfg[1]);
492  	if (ret) {
493  		printf("Warning: failed to initialize USDHC2\n");
494  		return ret;
495  	}
496  
497  	return 0;
498  }
499  
board_init(void)500  int board_init(void)
501  {
502  	/* Address of boot parameters */
503  	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
504  
505  #ifdef CONFIG_SYS_I2C_MXC
506  	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
507  #endif
508  
509  	return 0;
510  }
511  
checkboard(void)512  int checkboard(void)
513  {
514  	puts("Board: VIN|ING 2000\n");
515  
516  	return 0;
517  }
518