1/*
2 * (C) Copyright 2015
3 * Dirk Eibach,  Guntermann & Drunck GmbH, eibach@gdsys.de
4 *
5 * SPDX-License-Identifier:	GPL-2.0+
6 */
7
8#include <common.h>
9#include <command.h>
10#include <dm.h>
11#include <env.h>
12#include <event.h>
13#include <fdt_support.h>
14#include <fsl_esdhc.h>
15#include <init.h>
16#include <miiphy.h>
17#include <misc.h>
18#include <sysinfo.h>
19#include <tpm-v1.h>
20#include <video_osd.h>
21#include <asm/global_data.h>
22
23#include "../common/ihs_mdio.h"
24#include "../../../drivers/sysinfo/gazerbeam.h"
25
26DECLARE_GLOBAL_DATA_PTR;
27
28struct ihs_mdio_info ihs_mdio_info[] = {
29	{ .fpga = NULL, .name = "ihs0", .base = 0x58 },
30	{ .fpga = NULL, .name = "ihs1", .base = 0x58 },
31};
32
33static int get_tpm(struct udevice **devp)
34{
35	int rc;
36
37	rc = uclass_first_device_err(UCLASS_TPM, devp);
38	if (rc) {
39		printf("Could not find TPM (ret=%d)\n", rc);
40		return CMD_RET_FAILURE;
41	}
42
43	return 0;
44}
45
46int board_early_init_r(void)
47{
48	struct udevice *sysinfo;
49	struct udevice *serdes;
50	int mc = 0;
51	int con = 0;
52
53	if (sysinfo_get(&sysinfo)) {
54		puts("Could not find sysinfo information device.\n");
55		sysinfo = NULL;
56	}
57
58	/* Initialize serdes */
59	uclass_get_device_by_phandle(UCLASS_MISC, sysinfo, "serdes", &serdes);
60
61	if (sysinfo_detect(sysinfo))
62		puts("Device information detection failed.\n");
63
64	sysinfo_get_int(sysinfo, BOARD_MULTICHANNEL, &mc);
65	sysinfo_get_int(sysinfo, BOARD_VARIANT, &con);
66
67	if (mc == 2 || mc == 1)
68		dev_disable_by_path("/immr@e0000000/i2c@3100/pca9698@22");
69
70	if (mc == 4) {
71		dev_disable_by_path("/immr@e0000000/i2c@3100/pca9698@20");
72		dev_enable_by_path("/localbus@e0005000/iocon_uart@2,0");
73		dev_enable_by_path("/fpga1bus");
74	}
75
76	if (mc == 2 || con == VAR_CON) {
77		dev_enable_by_path("/fpga0bus/fpga0_video1");
78		dev_enable_by_path("/fpga0bus/fpga0_iic_video1");
79		dev_enable_by_path("/fpga0bus/fpga0_axi_video1");
80	}
81
82	if (con == VAR_CON) {
83		dev_enable_by_path("/fpga0bus/fpga0_video0");
84		dev_enable_by_path("/fpga0bus/fpga0_iic_video0");
85		dev_enable_by_path("/fpga0bus/fpga0_axi_video0");
86	}
87
88	return 0;
89}
90
91int checksysinfo(void)
92{
93	struct udevice *sysinfo;
94	char *s = env_get("serial#");
95	int mc = 0;
96	int con = 0;
97
98	if (sysinfo_get(&sysinfo)) {
99		puts("Could not find sysinfo information device.\n");
100		sysinfo = NULL;
101	}
102
103	sysinfo_get_int(sysinfo, BOARD_MULTICHANNEL, &mc);
104	sysinfo_get_int(sysinfo, BOARD_VARIANT, &con);
105
106	puts("Board: Gazerbeam ");
107	printf("%s ", mc == 4 ? "MC4" : mc == 2 ? "MC2" : "SC");
108	printf("%s", con == VAR_CON ? "CON" : "CPU");
109
110	if (s) {
111		puts(", serial# ");
112		puts(s);
113	}
114
115	puts("\n");
116
117	return 0;
118}
119
120static void display_osd_info(struct udevice *osd,
121			     struct video_osd_info *osd_info)
122{
123	printf("OSD-%s: Digital-OSD version %01d.%02d, %d x %d characters\n",
124	       osd->name, osd_info->major_version, osd_info->minor_version,
125	       osd_info->width, osd_info->height);
126}
127
128static int last_stage_init(void)
129{
130	int fpga_hw_rev = 0;
131	int i;
132	struct udevice *sysinfo;
133	struct udevice *osd;
134	struct video_osd_info osd_info;
135	struct udevice *tpm;
136	int ret;
137
138	if (sysinfo_get(&sysinfo)) {
139		puts("Could not find sysinfo information device.\n");
140		sysinfo = NULL;
141	}
142
143	if (sysinfo) {
144		int res = sysinfo_get_int(sysinfo, BOARD_HWVERSION,
145					  &fpga_hw_rev);
146
147		if (res)
148			printf("Could not determind FPGA HW revision (res = %d)\n",
149			       res);
150	}
151
152	env_set_ulong("fpga_hw_rev", fpga_hw_rev);
153
154	ret = get_tpm(&tpm);
155	if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR) ||
156	    tpm1_continue_self_test(tpm)) {
157		printf("TPM init failed\n");
158	}
159
160	if (fpga_hw_rev >= 4) {
161		for (i = 0; i < 4; i++) {
162			struct udevice *rxaui;
163			char name[8];
164
165			snprintf(name, sizeof(name), "rxaui%d", i);
166			/* Disable RXAUI polarity inversion */
167			ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo,
168							   name, &rxaui);
169			if (!ret)
170				misc_set_enabled(rxaui, false);
171		}
172	}
173
174	for (uclass_first_device(UCLASS_VIDEO_OSD, &osd);
175	     osd;
176	     uclass_next_device(&osd)) {
177		video_osd_get_info(osd, &osd_info);
178		display_osd_info(osd, &osd_info);
179	}
180
181	return 0;
182}
183EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init);
184
185#if defined(CONFIG_OF_BOARD_SETUP)
186int ft_board_setup(void *blob, struct bd_info *bd)
187{
188	ft_cpu_setup(blob, bd);
189	fsl_fdt_fixup_dr_usb(blob, bd);
190	fdt_fixup_esdhc(blob, bd);
191
192	return 0;
193}
194#endif
195