diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/arm/pl011/aarch32/pl011_console.S | 5 | ||||
-rw-r--r-- | drivers/arm/pl011/aarch64/pl011_console.S | 5 | ||||
-rw-r--r-- | drivers/cadence/uart/aarch64/cdns_console.S | 5 | ||||
-rw-r--r-- | drivers/cfi/v2m/v2m_flash.c | 195 | ||||
-rw-r--r-- | drivers/coreboot/cbmem_console/aarch64/cbmem_console.S | 4 | ||||
-rw-r--r-- | drivers/imx/usdhc/imx_usdhc.c | 2 | ||||
-rw-r--r-- | drivers/ti/uart/aarch64/16550_console.S | 5 |
7 files changed, 210 insertions, 11 deletions
diff --git a/drivers/arm/pl011/aarch32/pl011_console.S b/drivers/arm/pl011/aarch32/pl011_console.S index b7892e12e..841ea446c 100644 --- a/drivers/arm/pl011/aarch32/pl011_console.S +++ b/drivers/arm/pl011/aarch32/pl011_console.S @@ -89,8 +89,9 @@ endfunc console_pl011_core_init .globl console_pl011_register /* ------------------------------------------------------- - * init console_pl011_register(console_pl011_t *console, - * uintptr_t base, uint32_t clk, uint32_t baud) + * int console_pl011_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_pl011_t *console); * Function to initialize and register a new PL011 * console. Storage passed in for the console struct * *must* be persistent (i.e. not from the stack). diff --git a/drivers/arm/pl011/aarch64/pl011_console.S b/drivers/arm/pl011/aarch64/pl011_console.S index 448501a22..d6a2d6b89 100644 --- a/drivers/arm/pl011/aarch64/pl011_console.S +++ b/drivers/arm/pl011/aarch64/pl011_console.S @@ -85,8 +85,9 @@ endfunc console_pl011_core_init .globl console_pl011_register /* ----------------------------------------------- - * int console_pl011_register(console_pl011_t *console, - uintptr_t base, uint32_t clk, uint32_t baud) + * int console_pl011_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_pl011_t *console); * Function to initialize and register a new PL011 * console. Storage passed in for the console struct * *must* be persistent (i.e. not from the stack). diff --git a/drivers/cadence/uart/aarch64/cdns_console.S b/drivers/cadence/uart/aarch64/cdns_console.S index 673263197..71359a6d2 100644 --- a/drivers/cadence/uart/aarch64/cdns_console.S +++ b/drivers/cadence/uart/aarch64/cdns_console.S @@ -54,8 +54,9 @@ endfunc console_cdns_core_init .globl console_cdns_register /* ----------------------------------------------- - * int console_cdns_register(console_cdns_t *console, - uintptr_t base, uint32_t clk, uint32_t baud) + * int console_cdns_register(uint64_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_cdns_t *console); * Function to initialize and register a new CDNS * console. Storage passed in for the console struct * *must* be persistent (i.e. not from the stack). diff --git a/drivers/cfi/v2m/v2m_flash.c b/drivers/cfi/v2m/v2m_flash.c new file mode 100644 index 000000000..9b80e2f2a --- /dev/null +++ b/drivers/cfi/v2m/v2m_flash.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <errno.h> +#include <mmio.h> +#include <v2m_flash.h> + +/* + * This file supplies a low level interface to the vexpress NOR flash + * memory of juno and fvp. This memory is organized as an interleaved + * memory of two chips with a 16 bit word. It means that every 32 bit + * access is going to access to two different chips. This is very + * important when we send commands or read status of the chips. + */ + +/* + * DWS ready poll retries. The number of retries in this driver have been + * obtained empirically from Juno. FVP implements a zero wait state NOR flash + * model + */ +#define DWS_WORD_PROGRAM_RETRIES 1000 +#define DWS_WORD_ERASE_RETRIES 3000000 +#define DWS_WORD_LOCK_RETRIES 1000 + +/* Helper macro to detect end of command */ +#define NOR_CMD_END (NOR_DWS | NOR_DWS << 16l) + +/* Helper macros to access two flash banks in parallel */ +#define NOR_2X16(d) ((d << 16) | (d & 0xffff)) + +static unsigned int nor_status(uintptr_t base_addr) +{ + unsigned long status; + + nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG); + status = mmio_read_32(base_addr); + status |= status >> 16; /* merge status from both flash banks */ + + return status & 0xFFFF; +} + +/* + * Poll Write State Machine. + * Return values: + * 0 = WSM ready + * -EBUSY = WSM busy after the number of retries + */ +static int nor_poll_dws(uintptr_t base_addr, unsigned long int retries) +{ + unsigned long status; + + do { + nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG); + status = mmio_read_32(base_addr); + if ((status & NOR_CMD_END) == NOR_CMD_END) + return 0; + } while (retries-- > 0); + + return -EBUSY; +} + +/* + * Return values: + * 0 = success + * -EPERM = Device protected or Block locked + * -EIO = General I/O error + */ +static int nor_full_status_check(uintptr_t base_addr) +{ + unsigned long status; + + /* Full status check */ + status = nor_status(base_addr); + + if (status & (NOR_PS | NOR_BLS | NOR_ESS | NOR_PSS)) + return -EPERM; + if (status & (NOR_VPPS | NOR_ES)) + return -EIO; + return 0; +} + +void nor_send_cmd(uintptr_t base_addr, unsigned long cmd) +{ + mmio_write_32(base_addr, NOR_2X16(cmd)); +} + +/* + * This function programs a word in the flash. Be aware that it only + * can reset bits that were previously set. It cannot set bits that + * were previously reset. The resulting bits = old_bits & new bits. + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_word_program(uintptr_t base_addr, unsigned long data) +{ + uint32_t status; + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + /* Set the device in write word mode */ + nor_send_cmd(base_addr, NOR_CMD_WORD_PROGRAM); + mmio_write_32(base_addr, data); + + ret = nor_poll_dws(base_addr, DWS_WORD_PROGRAM_RETRIES); + if (ret == 0) { + /* Full status check */ + nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG); + status = mmio_read_32(base_addr); + + if (status & (NOR_PS | NOR_BLS)) { + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + ret = -EPERM; + } + } + + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} + +/* + * Erase a full 256K block + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_erase(uintptr_t base_addr) +{ + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + nor_send_cmd(base_addr, NOR_CMD_BLOCK_ERASE); + nor_send_cmd(base_addr, NOR_CMD_BLOCK_ERASE_ACK); + + ret = nor_poll_dws(base_addr, DWS_WORD_ERASE_RETRIES); + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} + +/* + * Lock a full 256 block + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_lock(uintptr_t base_addr) +{ + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK); + nor_send_cmd(base_addr, NOR_LOCK_BLOCK); + + ret = nor_poll_dws(base_addr, DWS_WORD_LOCK_RETRIES); + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} + +/* + * unlock a full 256 block + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_unlock(uintptr_t base_addr) +{ + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK); + nor_send_cmd(base_addr, NOR_UNLOCK_BLOCK); + + ret = nor_poll_dws(base_addr, DWS_WORD_LOCK_RETRIES); + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} diff --git a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S index 2fc060334..184853d9d 100644 --- a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S +++ b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S @@ -19,8 +19,8 @@ .globl console_cbmc_flush /* ----------------------------------------------- - * int console_cbmc_register(console_cbmc_t *console, - * uintptr_t base) + * int console_cbmc_register(uintptr_t base, + * console_cbmc_t *console); * Registers a new CBMEM console instance. Reads * the size field from the buffer header structure * and stores it in our console_cbmc_t struct, so diff --git a/drivers/imx/usdhc/imx_usdhc.c b/drivers/imx/usdhc/imx_usdhc.c index ea96833f5..1f9550e17 100644 --- a/drivers/imx/usdhc/imx_usdhc.c +++ b/drivers/imx/usdhc/imx_usdhc.c @@ -160,7 +160,7 @@ static int imx_usdhc_send_cmd(struct mmc_cmd *cmd) mixctl |= MIXCTRL_DMAEN; } - if (cmd->resp_type & MMC_RSP_48) + if (cmd->resp_type & MMC_RSP_48 && cmd->resp_type != MMC_RESPONSE_R2) xfertype |= XFERTYPE_RSPTYP_48; else if (cmd->resp_type & MMC_RSP_136) xfertype |= XFERTYPE_RSPTYP_136; diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S index d46fa6119..0f9a9d576 100644 --- a/drivers/ti/uart/aarch64/16550_console.S +++ b/drivers/ti/uart/aarch64/16550_console.S @@ -87,8 +87,9 @@ endfunc console_16550_core_init .globl console_16550_register /* ----------------------------------------------- - * int console_16550_register(console_16550_t *console, - uintptr_t base, uint32_t clk, uint32_t baud) + * int console_16550_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_16550_t *console); * Function to initialize and register a new 16550 * console. Storage passed in for the console struct * *must* be persistent (i.e. not from the stack). |