/* * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include "uniphier.h" #define UNIPHIER_LD11_USB_DESC_BASE 0x30010000 #define UNIPHIER_LD20_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; }; 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 int uniphier_pxs3_usb_read(int lba, uintptr_t buf, size_t size) { static int (*rom_usb_read)(unsigned int lba, unsigned int size, uintptr_t buf); rom_usb_read = (__typeof(rom_usb_read))0x100c; return rom_usb_read(lba, size, buf); } 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] = { .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 = { .buffer = { .offset = UNIPHIER_BLOCK_BUF_BASE, .length = UNIPHIER_BLOCK_BUF_SIZE, }, .ops = { .read = uniphier_usb_read, }, .block_size = 512, }; int uniphier_usb_init(unsigned int soc, uintptr_t *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 = (uintptr_t)&uniphier_usb_dev_spec; return 0; }