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