summaryrefslogtreecommitdiffstats
path: root/arch/arm/boards/protonic-stm32mp1/board.c
blob: 84a3d8eabc08f353f533c6018efd5d3a4fcf9f04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2021 David Jander, Protonic Holland
// SPDX-FileCopyrightText: 2021 Oleksij Rempel, Pengutronix

#include <bootsource.h>
#include <common.h>
#include <init.h>
#include <mach/bbu.h>
#include <of_device.h>

/* board specific flags */
#define PRT_STM32_BOOTSRC_SD		BIT(2)
#define PRT_STM32_BOOTSRC_EMMC		BIT(1)
#define PRT_STM32_BOOTSRC_SPI_NOR	BIT(0)

struct prt_stm32_machine_data {
	u32 flags;
};

struct prt_stm32_boot_dev {
	char *name;
	char *env;
	char *dev;
	int flags;
	int boot_idx;
	enum bootsource boot_src;
};

static const struct prt_stm32_boot_dev prt_stm32_boot_devs[] = {
	{
		.name = "emmc",
		.env = "/chosen/environment-emmc",
		.dev = "/dev/mmc1.ssbl",
		.flags = PRT_STM32_BOOTSRC_EMMC,
		.boot_src = BOOTSOURCE_MMC,
		.boot_idx = 1,
	}, {
		.name = "qspi",
		.env = "/chosen/environment-qspi",
		.dev = "/dev/flash.ssbl",
		.flags = PRT_STM32_BOOTSRC_SPI_NOR,
		.boot_src = BOOTSOURCE_SPI_NOR,
		.boot_idx = -1,
	}, {
		/* SD is optional boot source and should be last device in the
		 * list. */
		.name = "sd",
		.env = "/chosen/environment-sd",
		.dev = "/dev/mmc0.ssbl",
		.flags = PRT_STM32_BOOTSRC_SD,
		.boot_src = BOOTSOURCE_MMC,
		.boot_idx = 0,
	},
};

static int prt_stm32_probe(struct device_d *dev)
{
	const struct prt_stm32_machine_data *dcfg;
	char *env_path_back = NULL, *env_path = NULL;
	int ret, i;

	dcfg = of_device_get_match_data(dev);
	if (!dcfg) {
		ret = -EINVAL;
		goto exit_get_dcfg;
	}

	for (i = 0; i < ARRAY_SIZE(prt_stm32_boot_devs); i++) {
		const struct prt_stm32_boot_dev *bd = &prt_stm32_boot_devs[i];
		int bbu_flags = 0;

		/* skip not supported boot sources */
		if (!(bd->flags & dcfg->flags))
			continue;

		/* first device is build-in device */
		if (!env_path_back)
			env_path_back = bd->env;

		if (bd->boot_src == bootsource_get() && (bd->boot_idx == -1 ||
		    bd->boot_idx  == bootsource_get_instance())) {
			bbu_flags = BBU_HANDLER_FLAG_DEFAULT;
			env_path = bd->env;
		}

		ret = stm32mp_bbu_mmc_register_handler(bd->name, bd->dev,
						       bbu_flags);
		if (ret < 0)
			dev_warn(dev, "Failed to enable %s bbu (%pe)\n",
				 bd->name, ERR_PTR(ret));
	}

	if (!env_path)
		env_path = env_path_back;
	ret = of_device_enable_path(env_path);
	if (ret < 0)
		dev_warn(dev, "Failed to enable environment partition '%s' (%pe)\n",
			 env_path, ERR_PTR(ret));

	return 0;

exit_get_dcfg:
	dev_err(dev, "Failed to get dcfg: %pe\n", ERR_PTR(ret));
	return ret;
}

static const struct prt_stm32_machine_data prt_stm32_prtt1a = {
	.flags = PRT_STM32_BOOTSRC_SD | PRT_STM32_BOOTSRC_SPI_NOR,
};

static const struct prt_stm32_machine_data prt_stm32_prtt1c = {
	.flags = PRT_STM32_BOOTSRC_SD | PRT_STM32_BOOTSRC_EMMC,
};

static const struct of_device_id prt_stm32_of_match[] = {
	{ .compatible = "prt,prtt1a", .data = &prt_stm32_prtt1a },
	{ .compatible = "prt,prtt1c", .data = &prt_stm32_prtt1c },
	{ .compatible = "prt,prtt1s", .data = &prt_stm32_prtt1a },
	{ /* sentinel */ },
};

static struct driver_d prt_stm32_board_driver = {
	.name = "board-protonic-stm32",
	.probe = prt_stm32_probe,
	.of_compatible = prt_stm32_of_match,
};
postcore_platform_driver(prt_stm32_board_driver);