uniphier_usb.c 3.94 KB
Newer Older
1
/*
2
 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
3
4
5
6
7
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
8
#include <stdint.h>
9
10
11
12
13
14
15

#include <platform_def.h>

#include <arch_helpers.h>
#include <drivers/io/io_block.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
16
17
18
19
20

#include "uniphier.h"

#define UNIPHIER_LD11_USB_DESC_BASE	0x30010000
#define UNIPHIER_LD20_USB_DESC_BASE	0x30014000
21
#define UNIPHIER_PXS3_USB_DESC_BASE	0x30014000
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

#define UNIPHIER_SRB_OCM_CONT		0x61200000

struct uniphier_ld11_trans_op {
	uint8_t __pad[48];
};

struct uniphier_ld11_op {
	uint8_t __pad[56];
	struct uniphier_ld11_trans_op *trans_op;
	void *__pad2;
	void *dev_desc;
};

struct uniphier_ld20_trans_op {
	uint8_t __pad[40];
};

struct uniphier_ld20_op {
	uint8_t __pad[192];
	struct uniphier_ld20_trans_op *trans_op;
	void *__pad2;
	void *dev_desc;
};

47
48
49
50
51
52
53
struct uniphier_pxs3_op {
	uint8_t __pad[184];
	struct uniphier_ld20_trans_op *trans_op;
	void *__pad2;
	void *dev_desc;
};

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
static int (*__uniphier_usb_read)(int lba, uintptr_t buf, size_t size);

static void uniphier_ld11_usb_init(void)
{
	struct uniphier_ld11_op *op = (void *)UNIPHIER_LD11_USB_DESC_BASE;

	op->trans_op = (void *)(op + 1);

	op->dev_desc = op->trans_op + 1;
}

static int uniphier_ld11_usb_read(int lba, uintptr_t buf, size_t size)
{
	static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
				   unsigned int size, uintptr_t buf);
	uintptr_t func_addr;

	func_addr = uniphier_get_soc_revision() == 1 ? 0x3880 : 0x3958;
	rom_usb_read = (__typeof(rom_usb_read))func_addr;

	return rom_usb_read(UNIPHIER_LD11_USB_DESC_BASE, lba, size, buf);
}

static void uniphier_ld20_usb_init(void)
{
	struct uniphier_ld20_op *op = (void *)UNIPHIER_LD20_USB_DESC_BASE;

	op->trans_op = (void *)(op + 1);

	op->dev_desc = op->trans_op + 1;
}

static int uniphier_ld20_usb_read(int lba, uintptr_t buf, size_t size)
{
	static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
				   unsigned int size, uintptr_t buf);
	int ret;

	rom_usb_read = (__typeof(rom_usb_read))0x37f0;

	mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0x1ff);

	/* ROM-API - return 1 on success, 0 on error */
	ret = rom_usb_read(UNIPHIER_LD20_USB_DESC_BASE, lba, size, buf);

	mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0);

	return ret ? 0 : -1;
}

104
105
106
107
108
109
110
111
112
static void uniphier_pxs3_usb_init(void)
{
	struct uniphier_pxs3_op *op = (void *)UNIPHIER_PXS3_USB_DESC_BASE;

	op->trans_op = (void *)(op + 1);

	op->dev_desc = op->trans_op + 1;
}

113
114
static int uniphier_pxs3_usb_read(int lba, uintptr_t buf, size_t size)
{
115
116
117
118
119
	static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
				   unsigned int size, uintptr_t buf);
	int ret;

	rom_usb_read = (__typeof(rom_usb_read))0x39e8;
120

121
122
	/* ROM-API - return 1 on success, 0 on error */
	ret = rom_usb_read(UNIPHIER_PXS3_USB_DESC_BASE, lba, size, buf);
123

124
	return ret ? 0 : -1;
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
}

struct uniphier_usb_rom_param {
	void (*init)(void);
	int (*read)(int lba, uintptr_t buf, size_t size);
};

static const struct uniphier_usb_rom_param uniphier_usb_rom_params[] = {
	[UNIPHIER_SOC_LD11] = {
		.init = uniphier_ld11_usb_init,
		.read = uniphier_ld11_usb_read,
	},
	[UNIPHIER_SOC_LD20] = {
		.init = uniphier_ld20_usb_init,
		.read = uniphier_ld20_usb_read,
	},
	[UNIPHIER_SOC_PXS3] = {
142
		.init = uniphier_pxs3_usb_init,
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
		.read = uniphier_pxs3_usb_read,
	},
};

static size_t uniphier_usb_read(int lba, uintptr_t buf, size_t size)
{
	int ret;

	inv_dcache_range(buf, size);

	ret = __uniphier_usb_read(lba, buf, size);

	inv_dcache_range(buf, size);

	return ret ? 0 : size;
}

static struct io_block_dev_spec uniphier_usb_dev_spec = {
	.ops = {
		.read = uniphier_usb_read,
	},
	.block_size = 512,
};

167
168
int uniphier_usb_init(unsigned int soc,
		      struct io_block_dev_spec **block_dev_spec)
169
170
171
172
173
174
175
176
177
178
179
{
	const struct uniphier_usb_rom_param *param;

	assert(soc < ARRAY_SIZE(uniphier_usb_rom_params));
	param = &uniphier_usb_rom_params[soc];

	if (param->init)
		param->init();

	__uniphier_usb_read = param->read;

180
	*block_dev_spec = &uniphier_usb_dev_spec;
181
182
183

	return 0;
}