1 /*
2  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch_helpers.h>
8 #include <assert.h>
9 #include <io/io_block.h>
10 #include <mmio.h>
11 #include <platform_def.h>
12 #include <sys/types.h>
13 #include <utils_def.h>
14 
15 #include "uniphier.h"
16 
17 #define UNIPHIER_LD11_USB_DESC_BASE	0x30010000
18 #define UNIPHIER_LD20_USB_DESC_BASE	0x30014000
19 #define UNIPHIER_PXS3_USB_DESC_BASE	0x30014000
20 
21 #define UNIPHIER_SRB_OCM_CONT		0x61200000
22 
23 struct uniphier_ld11_trans_op {
24 	uint8_t __pad[48];
25 };
26 
27 struct uniphier_ld11_op {
28 	uint8_t __pad[56];
29 	struct uniphier_ld11_trans_op *trans_op;
30 	void *__pad2;
31 	void *dev_desc;
32 };
33 
34 struct uniphier_ld20_trans_op {
35 	uint8_t __pad[40];
36 };
37 
38 struct uniphier_ld20_op {
39 	uint8_t __pad[192];
40 	struct uniphier_ld20_trans_op *trans_op;
41 	void *__pad2;
42 	void *dev_desc;
43 };
44 
45 struct uniphier_pxs3_op {
46 	uint8_t __pad[184];
47 	struct uniphier_ld20_trans_op *trans_op;
48 	void *__pad2;
49 	void *dev_desc;
50 };
51 
52 static int (*__uniphier_usb_read)(int lba, uintptr_t buf, size_t size);
53 
uniphier_ld11_usb_init(void)54 static void uniphier_ld11_usb_init(void)
55 {
56 	struct uniphier_ld11_op *op = (void *)UNIPHIER_LD11_USB_DESC_BASE;
57 
58 	op->trans_op = (void *)(op + 1);
59 
60 	op->dev_desc = op->trans_op + 1;
61 }
62 
uniphier_ld11_usb_read(int lba,uintptr_t buf,size_t size)63 static int uniphier_ld11_usb_read(int lba, uintptr_t buf, size_t size)
64 {
65 	static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
66 				   unsigned int size, uintptr_t buf);
67 	uintptr_t func_addr;
68 
69 	func_addr = uniphier_get_soc_revision() == 1 ? 0x3880 : 0x3958;
70 	rom_usb_read = (__typeof(rom_usb_read))func_addr;
71 
72 	return rom_usb_read(UNIPHIER_LD11_USB_DESC_BASE, lba, size, buf);
73 }
74 
uniphier_ld20_usb_init(void)75 static void uniphier_ld20_usb_init(void)
76 {
77 	struct uniphier_ld20_op *op = (void *)UNIPHIER_LD20_USB_DESC_BASE;
78 
79 	op->trans_op = (void *)(op + 1);
80 
81 	op->dev_desc = op->trans_op + 1;
82 }
83 
uniphier_ld20_usb_read(int lba,uintptr_t buf,size_t size)84 static int uniphier_ld20_usb_read(int lba, uintptr_t buf, size_t size)
85 {
86 	static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
87 				   unsigned int size, uintptr_t buf);
88 	int ret;
89 
90 	rom_usb_read = (__typeof(rom_usb_read))0x37f0;
91 
92 	mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0x1ff);
93 
94 	/* ROM-API - return 1 on success, 0 on error */
95 	ret = rom_usb_read(UNIPHIER_LD20_USB_DESC_BASE, lba, size, buf);
96 
97 	mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0);
98 
99 	return ret ? 0 : -1;
100 }
101 
uniphier_pxs3_usb_init(void)102 static void uniphier_pxs3_usb_init(void)
103 {
104 	struct uniphier_pxs3_op *op = (void *)UNIPHIER_PXS3_USB_DESC_BASE;
105 
106 	op->trans_op = (void *)(op + 1);
107 
108 	op->dev_desc = op->trans_op + 1;
109 }
110 
uniphier_pxs3_usb_read(int lba,uintptr_t buf,size_t size)111 static int uniphier_pxs3_usb_read(int lba, uintptr_t buf, size_t size)
112 {
113 	static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
114 				   unsigned int size, uintptr_t buf);
115 	int ret;
116 
117 	rom_usb_read = (__typeof(rom_usb_read))0x39e8;
118 
119 	/* ROM-API - return 1 on success, 0 on error */
120 	ret = rom_usb_read(UNIPHIER_PXS3_USB_DESC_BASE, lba, size, buf);
121 
122 	return ret ? 0 : -1;
123 }
124 
125 struct uniphier_usb_rom_param {
126 	void (*init)(void);
127 	int (*read)(int lba, uintptr_t buf, size_t size);
128 };
129 
130 static const struct uniphier_usb_rom_param uniphier_usb_rom_params[] = {
131 	[UNIPHIER_SOC_LD11] = {
132 		.init = uniphier_ld11_usb_init,
133 		.read = uniphier_ld11_usb_read,
134 	},
135 	[UNIPHIER_SOC_LD20] = {
136 		.init = uniphier_ld20_usb_init,
137 		.read = uniphier_ld20_usb_read,
138 	},
139 	[UNIPHIER_SOC_PXS3] = {
140 		.init = uniphier_pxs3_usb_init,
141 		.read = uniphier_pxs3_usb_read,
142 	},
143 };
144 
uniphier_usb_read(int lba,uintptr_t buf,size_t size)145 static size_t uniphier_usb_read(int lba, uintptr_t buf, size_t size)
146 {
147 	int ret;
148 
149 	inv_dcache_range(buf, size);
150 
151 	ret = __uniphier_usb_read(lba, buf, size);
152 
153 	inv_dcache_range(buf, size);
154 
155 	return ret ? 0 : size;
156 }
157 
158 static struct io_block_dev_spec uniphier_usb_dev_spec = {
159 	.buffer = {
160 		.offset = UNIPHIER_BLOCK_BUF_BASE,
161 		.length = UNIPHIER_BLOCK_BUF_SIZE,
162 	},
163 	.ops = {
164 		.read = uniphier_usb_read,
165 	},
166 	.block_size = 512,
167 };
168 
uniphier_usb_init(unsigned int soc,uintptr_t * block_dev_spec)169 int uniphier_usb_init(unsigned int soc, uintptr_t *block_dev_spec)
170 {
171 	const struct uniphier_usb_rom_param *param;
172 
173 	assert(soc < ARRAY_SIZE(uniphier_usb_rom_params));
174 	param = &uniphier_usb_rom_params[soc];
175 
176 	if (param->init)
177 		param->init();
178 
179 	__uniphier_usb_read = param->read;
180 
181 	*block_dev_spec = (uintptr_t)&uniphier_usb_dev_spec;
182 
183 	return 0;
184 }
185