Home | History | Annotate | Download | only in uniphier
      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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