xref: /rk3399_rockchip-uboot/board/raspberrypi/rpi/rpi.c (revision 9316e14400c255e02f66bfb6d1e3d1dce3daf86a)
1*9316e144SStephen Warren /*
2*9316e144SStephen Warren  * (C) Copyright 2012-2013 Stephen Warren
3*9316e144SStephen Warren  *
4*9316e144SStephen Warren  * See file CREDITS for list of people who contributed to this
5*9316e144SStephen Warren  * project.
6*9316e144SStephen Warren  *
7*9316e144SStephen Warren  * This program is free software; you can redistribute it and/or
8*9316e144SStephen Warren  * modify it under the terms of the GNU General Public License
9*9316e144SStephen Warren  * version 2 as published by the Free Software Foundation.
10*9316e144SStephen Warren  *
11*9316e144SStephen Warren  * This program is distributed in the hope that it will be useful, but
12*9316e144SStephen Warren  * WITHOUT ANY WARRANTY; without even the implied warranty of
13*9316e144SStephen Warren  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*9316e144SStephen Warren  * GNU General Public License for more details.
15*9316e144SStephen Warren  */
16*9316e144SStephen Warren 
17*9316e144SStephen Warren #include <common.h>
18*9316e144SStephen Warren #include <config.h>
19*9316e144SStephen Warren #include <dm.h>
20*9316e144SStephen Warren #include <fdt_support.h>
21*9316e144SStephen Warren #include <lcd.h>
22*9316e144SStephen Warren #include <mmc.h>
23*9316e144SStephen Warren #include <asm/gpio.h>
24*9316e144SStephen Warren #include <asm/arch/mbox.h>
25*9316e144SStephen Warren #include <asm/arch/sdhci.h>
26*9316e144SStephen Warren #include <asm/global_data.h>
27*9316e144SStephen Warren 
28*9316e144SStephen Warren DECLARE_GLOBAL_DATA_PTR;
29*9316e144SStephen Warren 
30*9316e144SStephen Warren static const struct bcm2835_gpio_platdata gpio_platdata = {
31*9316e144SStephen Warren 	.base = BCM2835_GPIO_BASE,
32*9316e144SStephen Warren };
33*9316e144SStephen Warren 
34*9316e144SStephen Warren U_BOOT_DEVICE(bcm2835_gpios) = {
35*9316e144SStephen Warren 	.name = "gpio_bcm2835",
36*9316e144SStephen Warren 	.platdata = &gpio_platdata,
37*9316e144SStephen Warren };
38*9316e144SStephen Warren 
39*9316e144SStephen Warren struct msg_get_arm_mem {
40*9316e144SStephen Warren 	struct bcm2835_mbox_hdr hdr;
41*9316e144SStephen Warren 	struct bcm2835_mbox_tag_get_arm_mem get_arm_mem;
42*9316e144SStephen Warren 	u32 end_tag;
43*9316e144SStephen Warren };
44*9316e144SStephen Warren 
45*9316e144SStephen Warren struct msg_get_board_rev {
46*9316e144SStephen Warren 	struct bcm2835_mbox_hdr hdr;
47*9316e144SStephen Warren 	struct bcm2835_mbox_tag_get_board_rev get_board_rev;
48*9316e144SStephen Warren 	u32 end_tag;
49*9316e144SStephen Warren };
50*9316e144SStephen Warren 
51*9316e144SStephen Warren struct msg_get_mac_address {
52*9316e144SStephen Warren 	struct bcm2835_mbox_hdr hdr;
53*9316e144SStephen Warren 	struct bcm2835_mbox_tag_get_mac_address get_mac_address;
54*9316e144SStephen Warren 	u32 end_tag;
55*9316e144SStephen Warren };
56*9316e144SStephen Warren 
57*9316e144SStephen Warren struct msg_set_power_state {
58*9316e144SStephen Warren 	struct bcm2835_mbox_hdr hdr;
59*9316e144SStephen Warren 	struct bcm2835_mbox_tag_set_power_state set_power_state;
60*9316e144SStephen Warren 	u32 end_tag;
61*9316e144SStephen Warren };
62*9316e144SStephen Warren 
63*9316e144SStephen Warren struct msg_get_clock_rate {
64*9316e144SStephen Warren 	struct bcm2835_mbox_hdr hdr;
65*9316e144SStephen Warren 	struct bcm2835_mbox_tag_get_clock_rate get_clock_rate;
66*9316e144SStephen Warren 	u32 end_tag;
67*9316e144SStephen Warren };
68*9316e144SStephen Warren 
69*9316e144SStephen Warren /* See comments in mbox.h for data source */
70*9316e144SStephen Warren static const struct {
71*9316e144SStephen Warren 	const char *name;
72*9316e144SStephen Warren 	const char *fdtfile;
73*9316e144SStephen Warren } models[] = {
74*9316e144SStephen Warren 	[BCM2835_BOARD_REV_B_I2C0_2] = {
75*9316e144SStephen Warren 		"Model B (no P5)",
76*9316e144SStephen Warren 		"bcm2835-rpi-b-i2c0.dtb",
77*9316e144SStephen Warren 	},
78*9316e144SStephen Warren 	[BCM2835_BOARD_REV_B_I2C0_3] = {
79*9316e144SStephen Warren 		"Model B (no P5)",
80*9316e144SStephen Warren 		"bcm2835-rpi-b-i2c0.dtb",
81*9316e144SStephen Warren 	},
82*9316e144SStephen Warren 	[BCM2835_BOARD_REV_B_I2C1_4] = {
83*9316e144SStephen Warren 		"Model B",
84*9316e144SStephen Warren 		"bcm2835-rpi-b.dtb",
85*9316e144SStephen Warren 	},
86*9316e144SStephen Warren 	[BCM2835_BOARD_REV_B_I2C1_5] = {
87*9316e144SStephen Warren 		"Model B",
88*9316e144SStephen Warren 		"bcm2835-rpi-b.dtb",
89*9316e144SStephen Warren 	},
90*9316e144SStephen Warren 	[BCM2835_BOARD_REV_B_I2C1_6] = {
91*9316e144SStephen Warren 		"Model B",
92*9316e144SStephen Warren 		"bcm2835-rpi-b.dtb",
93*9316e144SStephen Warren 	},
94*9316e144SStephen Warren 	[BCM2835_BOARD_REV_A_7] = {
95*9316e144SStephen Warren 		"Model A",
96*9316e144SStephen Warren 		"bcm2835-rpi-a.dtb",
97*9316e144SStephen Warren 	},
98*9316e144SStephen Warren 	[BCM2835_BOARD_REV_A_8] = {
99*9316e144SStephen Warren 		"Model A",
100*9316e144SStephen Warren 		"bcm2835-rpi-a.dtb",
101*9316e144SStephen Warren 	},
102*9316e144SStephen Warren 	[BCM2835_BOARD_REV_A_9] = {
103*9316e144SStephen Warren 		"Model A",
104*9316e144SStephen Warren 		"bcm2835-rpi-a.dtb",
105*9316e144SStephen Warren 	},
106*9316e144SStephen Warren 	[BCM2835_BOARD_REV_B_REV2_d] = {
107*9316e144SStephen Warren 		"Model B rev2",
108*9316e144SStephen Warren 		"bcm2835-rpi-b-rev2.dtb",
109*9316e144SStephen Warren 	},
110*9316e144SStephen Warren 	[BCM2835_BOARD_REV_B_REV2_e] = {
111*9316e144SStephen Warren 		"Model B rev2",
112*9316e144SStephen Warren 		"bcm2835-rpi-b-rev2.dtb",
113*9316e144SStephen Warren 	},
114*9316e144SStephen Warren 	[BCM2835_BOARD_REV_B_REV2_f] = {
115*9316e144SStephen Warren 		"Model B rev2",
116*9316e144SStephen Warren 		"bcm2835-rpi-b-rev2.dtb",
117*9316e144SStephen Warren 	},
118*9316e144SStephen Warren 	[BCM2835_BOARD_REV_B_PLUS] = {
119*9316e144SStephen Warren 		"Model B+",
120*9316e144SStephen Warren 		"bcm2835-rpi-b-plus.dtb",
121*9316e144SStephen Warren 	},
122*9316e144SStephen Warren 	[BCM2835_BOARD_REV_CM] = {
123*9316e144SStephen Warren 		"Compute Module",
124*9316e144SStephen Warren 		"bcm2835-rpi-cm.dtb",
125*9316e144SStephen Warren 	},
126*9316e144SStephen Warren };
127*9316e144SStephen Warren 
128*9316e144SStephen Warren u32 rpi_board_rev = 0;
129*9316e144SStephen Warren 
130*9316e144SStephen Warren int dram_init(void)
131*9316e144SStephen Warren {
132*9316e144SStephen Warren 	ALLOC_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1, 16);
133*9316e144SStephen Warren 	int ret;
134*9316e144SStephen Warren 
135*9316e144SStephen Warren 	BCM2835_MBOX_INIT_HDR(msg);
136*9316e144SStephen Warren 	BCM2835_MBOX_INIT_TAG(&msg->get_arm_mem, GET_ARM_MEMORY);
137*9316e144SStephen Warren 
138*9316e144SStephen Warren 	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
139*9316e144SStephen Warren 	if (ret) {
140*9316e144SStephen Warren 		printf("bcm2835: Could not query ARM memory size\n");
141*9316e144SStephen Warren 		return -1;
142*9316e144SStephen Warren 	}
143*9316e144SStephen Warren 
144*9316e144SStephen Warren 	gd->ram_size = msg->get_arm_mem.body.resp.mem_size;
145*9316e144SStephen Warren 
146*9316e144SStephen Warren 	return 0;
147*9316e144SStephen Warren }
148*9316e144SStephen Warren 
149*9316e144SStephen Warren static void set_fdtfile(void)
150*9316e144SStephen Warren {
151*9316e144SStephen Warren 	const char *fdtfile;
152*9316e144SStephen Warren 
153*9316e144SStephen Warren 	if (getenv("fdtfile"))
154*9316e144SStephen Warren 		return;
155*9316e144SStephen Warren 
156*9316e144SStephen Warren 	fdtfile = models[rpi_board_rev].fdtfile;
157*9316e144SStephen Warren 	if (!fdtfile)
158*9316e144SStephen Warren 		fdtfile = "bcm2835-rpi-other.dtb";
159*9316e144SStephen Warren 
160*9316e144SStephen Warren 	setenv("fdtfile", fdtfile);
161*9316e144SStephen Warren }
162*9316e144SStephen Warren 
163*9316e144SStephen Warren static void set_usbethaddr(void)
164*9316e144SStephen Warren {
165*9316e144SStephen Warren 	ALLOC_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1, 16);
166*9316e144SStephen Warren 	int ret;
167*9316e144SStephen Warren 
168*9316e144SStephen Warren 	if (getenv("usbethaddr"))
169*9316e144SStephen Warren 		return;
170*9316e144SStephen Warren 
171*9316e144SStephen Warren 	BCM2835_MBOX_INIT_HDR(msg);
172*9316e144SStephen Warren 	BCM2835_MBOX_INIT_TAG(&msg->get_mac_address, GET_MAC_ADDRESS);
173*9316e144SStephen Warren 
174*9316e144SStephen Warren 	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
175*9316e144SStephen Warren 	if (ret) {
176*9316e144SStephen Warren 		printf("bcm2835: Could not query MAC address\n");
177*9316e144SStephen Warren 		/* Ignore error; not critical */
178*9316e144SStephen Warren 		return;
179*9316e144SStephen Warren 	}
180*9316e144SStephen Warren 
181*9316e144SStephen Warren 	eth_setenv_enetaddr("usbethaddr", msg->get_mac_address.body.resp.mac);
182*9316e144SStephen Warren 
183*9316e144SStephen Warren 	return;
184*9316e144SStephen Warren }
185*9316e144SStephen Warren 
186*9316e144SStephen Warren int misc_init_r(void)
187*9316e144SStephen Warren {
188*9316e144SStephen Warren 	set_fdtfile();
189*9316e144SStephen Warren 	set_usbethaddr();
190*9316e144SStephen Warren 	return 0;
191*9316e144SStephen Warren }
192*9316e144SStephen Warren 
193*9316e144SStephen Warren static int power_on_module(u32 module)
194*9316e144SStephen Warren {
195*9316e144SStephen Warren 	ALLOC_ALIGN_BUFFER(struct msg_set_power_state, msg_pwr, 1, 16);
196*9316e144SStephen Warren 	int ret;
197*9316e144SStephen Warren 
198*9316e144SStephen Warren 	BCM2835_MBOX_INIT_HDR(msg_pwr);
199*9316e144SStephen Warren 	BCM2835_MBOX_INIT_TAG(&msg_pwr->set_power_state,
200*9316e144SStephen Warren 			      SET_POWER_STATE);
201*9316e144SStephen Warren 	msg_pwr->set_power_state.body.req.device_id = module;
202*9316e144SStephen Warren 	msg_pwr->set_power_state.body.req.state =
203*9316e144SStephen Warren 		BCM2835_MBOX_SET_POWER_STATE_REQ_ON |
204*9316e144SStephen Warren 		BCM2835_MBOX_SET_POWER_STATE_REQ_WAIT;
205*9316e144SStephen Warren 
206*9316e144SStephen Warren 	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN,
207*9316e144SStephen Warren 				     &msg_pwr->hdr);
208*9316e144SStephen Warren 	if (ret) {
209*9316e144SStephen Warren 		printf("bcm2835: Could not set module %u power state\n",
210*9316e144SStephen Warren 		       module);
211*9316e144SStephen Warren 		return -1;
212*9316e144SStephen Warren 	}
213*9316e144SStephen Warren 
214*9316e144SStephen Warren 	return 0;
215*9316e144SStephen Warren }
216*9316e144SStephen Warren 
217*9316e144SStephen Warren static void get_board_rev(void)
218*9316e144SStephen Warren {
219*9316e144SStephen Warren 	ALLOC_ALIGN_BUFFER(struct msg_get_board_rev, msg, 1, 16);
220*9316e144SStephen Warren 	int ret;
221*9316e144SStephen Warren 	const char *name;
222*9316e144SStephen Warren 
223*9316e144SStephen Warren 	BCM2835_MBOX_INIT_HDR(msg);
224*9316e144SStephen Warren 	BCM2835_MBOX_INIT_TAG(&msg->get_board_rev, GET_BOARD_REV);
225*9316e144SStephen Warren 
226*9316e144SStephen Warren 	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
227*9316e144SStephen Warren 	if (ret) {
228*9316e144SStephen Warren 		printf("bcm2835: Could not query board revision\n");
229*9316e144SStephen Warren 		/* Ignore error; not critical */
230*9316e144SStephen Warren 		return;
231*9316e144SStephen Warren 	}
232*9316e144SStephen Warren 
233*9316e144SStephen Warren 	rpi_board_rev = msg->get_board_rev.body.resp.rev;
234*9316e144SStephen Warren 	if (rpi_board_rev >= ARRAY_SIZE(models))
235*9316e144SStephen Warren 		rpi_board_rev = 0;
236*9316e144SStephen Warren 
237*9316e144SStephen Warren 	name = models[rpi_board_rev].name;
238*9316e144SStephen Warren 	if (!name)
239*9316e144SStephen Warren 		name = "Unknown model";
240*9316e144SStephen Warren 	printf("RPI model: %s\n", name);
241*9316e144SStephen Warren }
242*9316e144SStephen Warren 
243*9316e144SStephen Warren int board_init(void)
244*9316e144SStephen Warren {
245*9316e144SStephen Warren 	get_board_rev();
246*9316e144SStephen Warren 
247*9316e144SStephen Warren 	gd->bd->bi_boot_params = 0x100;
248*9316e144SStephen Warren 
249*9316e144SStephen Warren 	return power_on_module(BCM2835_MBOX_POWER_DEVID_USB_HCD);
250*9316e144SStephen Warren }
251*9316e144SStephen Warren 
252*9316e144SStephen Warren int board_mmc_init(bd_t *bis)
253*9316e144SStephen Warren {
254*9316e144SStephen Warren 	ALLOC_ALIGN_BUFFER(struct msg_get_clock_rate, msg_clk, 1, 16);
255*9316e144SStephen Warren 	int ret;
256*9316e144SStephen Warren 
257*9316e144SStephen Warren 	power_on_module(BCM2835_MBOX_POWER_DEVID_SDHCI);
258*9316e144SStephen Warren 
259*9316e144SStephen Warren 	BCM2835_MBOX_INIT_HDR(msg_clk);
260*9316e144SStephen Warren 	BCM2835_MBOX_INIT_TAG(&msg_clk->get_clock_rate, GET_CLOCK_RATE);
261*9316e144SStephen Warren 	msg_clk->get_clock_rate.body.req.clock_id = BCM2835_MBOX_CLOCK_ID_EMMC;
262*9316e144SStephen Warren 
263*9316e144SStephen Warren 	ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_clk->hdr);
264*9316e144SStephen Warren 	if (ret) {
265*9316e144SStephen Warren 		printf("bcm2835: Could not query eMMC clock rate\n");
266*9316e144SStephen Warren 		return -1;
267*9316e144SStephen Warren 	}
268*9316e144SStephen Warren 
269*9316e144SStephen Warren 	return bcm2835_sdhci_init(BCM2835_SDHCI_BASE,
270*9316e144SStephen Warren 				  msg_clk->get_clock_rate.body.resp.rate_hz);
271*9316e144SStephen Warren }
272*9316e144SStephen Warren 
273*9316e144SStephen Warren int ft_board_setup(void *blob, bd_t *bd)
274*9316e144SStephen Warren {
275*9316e144SStephen Warren 	/*
276*9316e144SStephen Warren 	 * For now, we simply always add the simplefb DT node. Later, we
277*9316e144SStephen Warren 	 * should be more intelligent, and e.g. only do this if no enabled DT
278*9316e144SStephen Warren 	 * node exists for the "real" graphics driver.
279*9316e144SStephen Warren 	 */
280*9316e144SStephen Warren 	lcd_dt_simplefb_add_node(blob);
281*9316e144SStephen Warren 
282*9316e144SStephen Warren 	return 0;
283*9316e144SStephen Warren }
284