diff options
Diffstat (limited to 'plat/socionext/uniphier/uniphier_usb.c')
-rw-r--r-- | plat/socionext/uniphier/uniphier_usb.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/plat/socionext/uniphier/uniphier_usb.c b/plat/socionext/uniphier/uniphier_usb.c new file mode 100644 index 0000000..7469ad1 --- /dev/null +++ b/plat/socionext/uniphier/uniphier_usb.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdint.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <drivers/io/io_block.h> +#include <lib/mmio.h> +#include <lib/utils_def.h> + +#include "uniphier.h" + +#define UNIPHIER_LD11_USB_DESC_BASE 0x30010000 +#define UNIPHIER_LD20_USB_DESC_BASE 0x30014000 +#define UNIPHIER_PXS3_USB_DESC_BASE 0x30014000 + +#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; +}; + +struct uniphier_pxs3_op { + uint8_t __pad[184]; + struct uniphier_ld20_trans_op *trans_op; + void *__pad2; + void *dev_desc; +}; + +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; +} + +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; +} + +static int uniphier_pxs3_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))0x39e8; + + /* ROM-API - return 1 on success, 0 on error */ + ret = rom_usb_read(UNIPHIER_PXS3_USB_DESC_BASE, lba, size, buf); + + return ret ? 0 : -1; +} + +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] = { + .init = uniphier_pxs3_usb_init, + .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, +}; + +int uniphier_usb_init(unsigned int soc, + struct io_block_dev_spec **block_dev_spec) +{ + 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; + + *block_dev_spec = &uniphier_usb_dev_spec; + + return 0; +} |