xref: /rk3399_ARM-atf/plat/socionext/uniphier/uniphier_usb.c (revision 6311f63de02ee04d93016242977ade4727089de8)
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 
20 #define UNIPHIER_SRB_OCM_CONT		0x61200000
21 
22 struct uniphier_ld11_trans_op {
23 	uint8_t __pad[48];
24 };
25 
26 struct uniphier_ld11_op {
27 	uint8_t __pad[56];
28 	struct uniphier_ld11_trans_op *trans_op;
29 	void *__pad2;
30 	void *dev_desc;
31 };
32 
33 struct uniphier_ld20_trans_op {
34 	uint8_t __pad[40];
35 };
36 
37 struct uniphier_ld20_op {
38 	uint8_t __pad[192];
39 	struct uniphier_ld20_trans_op *trans_op;
40 	void *__pad2;
41 	void *dev_desc;
42 };
43 
44 static int (*__uniphier_usb_read)(int lba, uintptr_t buf, size_t size);
45 
46 static void uniphier_ld11_usb_init(void)
47 {
48 	struct uniphier_ld11_op *op = (void *)UNIPHIER_LD11_USB_DESC_BASE;
49 
50 	op->trans_op = (void *)(op + 1);
51 
52 	op->dev_desc = op->trans_op + 1;
53 }
54 
55 static int uniphier_ld11_usb_read(int lba, uintptr_t buf, size_t size)
56 {
57 	static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
58 				   unsigned int size, uintptr_t buf);
59 	uintptr_t func_addr;
60 
61 	func_addr = uniphier_get_soc_revision() == 1 ? 0x3880 : 0x3958;
62 	rom_usb_read = (__typeof(rom_usb_read))func_addr;
63 
64 	return rom_usb_read(UNIPHIER_LD11_USB_DESC_BASE, lba, size, buf);
65 }
66 
67 static void uniphier_ld20_usb_init(void)
68 {
69 	struct uniphier_ld20_op *op = (void *)UNIPHIER_LD20_USB_DESC_BASE;
70 
71 	op->trans_op = (void *)(op + 1);
72 
73 	op->dev_desc = op->trans_op + 1;
74 }
75 
76 static int uniphier_ld20_usb_read(int lba, uintptr_t buf, size_t size)
77 {
78 	static int (*rom_usb_read)(uintptr_t desc, unsigned int lba,
79 				   unsigned int size, uintptr_t buf);
80 	int ret;
81 
82 	rom_usb_read = (__typeof(rom_usb_read))0x37f0;
83 
84 	mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0x1ff);
85 
86 	/* ROM-API - return 1 on success, 0 on error */
87 	ret = rom_usb_read(UNIPHIER_LD20_USB_DESC_BASE, lba, size, buf);
88 
89 	mmio_write_32(UNIPHIER_SRB_OCM_CONT, 0);
90 
91 	return ret ? 0 : -1;
92 }
93 
94 static int uniphier_pxs3_usb_read(int lba, uintptr_t buf, size_t size)
95 {
96 	static int (*rom_usb_read)(unsigned int lba, unsigned int size,
97 				   uintptr_t buf);
98 
99 	rom_usb_read = (__typeof(rom_usb_read))0x100c;
100 
101 	return rom_usb_read(lba, size, buf);
102 }
103 
104 struct uniphier_usb_rom_param {
105 	void (*init)(void);
106 	int (*read)(int lba, uintptr_t buf, size_t size);
107 };
108 
109 static const struct uniphier_usb_rom_param uniphier_usb_rom_params[] = {
110 	[UNIPHIER_SOC_LD11] = {
111 		.init = uniphier_ld11_usb_init,
112 		.read = uniphier_ld11_usb_read,
113 	},
114 	[UNIPHIER_SOC_LD20] = {
115 		.init = uniphier_ld20_usb_init,
116 		.read = uniphier_ld20_usb_read,
117 	},
118 	[UNIPHIER_SOC_PXS3] = {
119 		.read = uniphier_pxs3_usb_read,
120 	},
121 };
122 
123 static size_t uniphier_usb_read(int lba, uintptr_t buf, size_t size)
124 {
125 	int ret;
126 
127 	inv_dcache_range(buf, size);
128 
129 	ret = __uniphier_usb_read(lba, buf, size);
130 
131 	inv_dcache_range(buf, size);
132 
133 	return ret ? 0 : size;
134 }
135 
136 static struct io_block_dev_spec uniphier_usb_dev_spec = {
137 	.buffer = {
138 		.offset = UNIPHIER_BLOCK_BUF_BASE,
139 		.length = UNIPHIER_BLOCK_BUF_SIZE,
140 	},
141 	.ops = {
142 		.read = uniphier_usb_read,
143 	},
144 	.block_size = 512,
145 };
146 
147 int uniphier_usb_init(unsigned int soc, uintptr_t *block_dev_spec)
148 {
149 	const struct uniphier_usb_rom_param *param;
150 
151 	assert(soc < ARRAY_SIZE(uniphier_usb_rom_params));
152 	param = &uniphier_usb_rom_params[soc];
153 
154 	if (param->init)
155 		param->init();
156 
157 	__uniphier_usb_read = param->read;
158 
159 	*block_dev_spec = (uintptr_t)&uniphier_usb_dev_spec;
160 
161 	return 0;
162 }
163