diff options
Diffstat (limited to 'board/synopsys/axs10x')
-rw-r--r-- | board/synopsys/axs10x/Kconfig | 12 | ||||
-rw-r--r-- | board/synopsys/axs10x/MAINTAINERS | 7 | ||||
-rw-r--r-- | board/synopsys/axs10x/Makefile | 8 | ||||
-rw-r--r-- | board/synopsys/axs10x/axs10x.c | 76 | ||||
-rw-r--r-- | board/synopsys/axs10x/axs10x.h | 16 | ||||
-rw-r--r-- | board/synopsys/axs10x/nand.c | 243 |
6 files changed, 362 insertions, 0 deletions
diff --git a/board/synopsys/axs10x/Kconfig b/board/synopsys/axs10x/Kconfig new file mode 100644 index 0000000000..c60b6a2047 --- /dev/null +++ b/board/synopsys/axs10x/Kconfig @@ -0,0 +1,12 @@ +if TARGET_AXS10X + +config SYS_BOARD + default "axs10x" + +config SYS_VENDOR + default "synopsys" + +config SYS_CONFIG_NAME + default "axs10x" + +endif diff --git a/board/synopsys/axs10x/MAINTAINERS b/board/synopsys/axs10x/MAINTAINERS new file mode 100644 index 0000000000..abb890b714 --- /dev/null +++ b/board/synopsys/axs10x/MAINTAINERS @@ -0,0 +1,7 @@ +AXS10X BOARD +M: Alexey Brodkin <abrodkin@synopsys.com> +S: Maintained +F: board/synopsys/axs10x/ +F: include/configs/axs10x.h +F: configs/axs101_defconfig +F: configs/axs103_defconfig diff --git a/board/synopsys/axs10x/Makefile b/board/synopsys/axs10x/Makefile new file mode 100644 index 0000000000..e29d52046f --- /dev/null +++ b/board/synopsys/axs10x/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (C) 2013-2016 Synopsys, Inc. All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += axs10x.o +obj-$(CONFIG_CMD_NAND) += nand.o diff --git a/board/synopsys/axs10x/axs10x.c b/board/synopsys/axs10x/axs10x.c new file mode 100644 index 0000000000..a5e774b2cf --- /dev/null +++ b/board/synopsys/axs10x/axs10x.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dwmmc.h> +#include <malloc.h> +#include "axs10x.h" + +DECLARE_GLOBAL_DATA_PTR; + +int board_mmc_init(bd_t *bis) +{ + struct dwmci_host *host = NULL; + + host = malloc(sizeof(struct dwmci_host)); + if (!host) { + printf("dwmci_host malloc fail!\n"); + return 1; + } + + memset(host, 0, sizeof(struct dwmci_host)); + host->name = "Synopsys Mobile storage"; + host->ioaddr = (void *)ARC_DWMMC_BASE; + host->buswidth = 4; + host->dev_index = 0; + host->bus_hz = 50000000; + + add_dwmci(host, host->bus_hz / 2, 400000); + + return 0; +} + +#define AXS_MB_CREG 0xE0011000 + +int board_early_init_f(void) +{ + if (readl((void __iomem *)AXS_MB_CREG + 0x234) & (1 << 28)) + gd->board_type = AXS_MB_V3; + else + gd->board_type = AXS_MB_V2; + + return 0; +} + +#ifdef CONFIG_ISA_ARCV2 +#define RESET_VECTOR_ADDR 0x0 + +void smp_set_core_boot_addr(unsigned long addr, int corenr) +{ + /* All cores have reset vector pointing to 0 */ + writel(addr, (void __iomem *)RESET_VECTOR_ADDR); + + /* Make sure other cores see written value in memory */ + flush_dcache_all(); +} + +void smp_kick_all_cpus(void) +{ +/* CPU start CREG */ +#define AXC003_CREG_CPU_START 0xF0001400 + +/* Bits positions in CPU start CREG */ +#define BITS_START 0 +#define BITS_POLARITY 8 +#define BITS_CORE_SEL 9 +#define BITS_MULTICORE 12 + +#define CMD (1 << BITS_MULTICORE) | (1 << BITS_CORE_SEL) | \ + (1 << BITS_POLARITY) | (1 << BITS_START) + + writel(CMD, (void __iomem *)AXC003_CREG_CPU_START); +} +#endif diff --git a/board/synopsys/axs10x/axs10x.h b/board/synopsys/axs10x/axs10x.h new file mode 100644 index 0000000000..8e8c41f865 --- /dev/null +++ b/board/synopsys/axs10x/axs10x.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2015 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _BOARD_SYNOPSYS_AXS10X_H +#define _BOARD_SYNOPSYS_AXS10X_H + +enum { + AXS_MB_V2, + AXS_MB_V3 +}; + +#endif /* _BOARD_SYNOPSYS_AXS10X_H */ + diff --git a/board/synopsys/axs10x/nand.c b/board/synopsys/axs10x/nand.c new file mode 100644 index 0000000000..4be52e22c0 --- /dev/null +++ b/board/synopsys/axs10x/nand.c @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <bouncebuf.h> +#include <common.h> +#include <malloc.h> +#include <nand.h> +#include <asm/io.h> +#include "axs10x.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define BUS_WIDTH 8 /* AXI data bus width in bytes */ + +/* DMA buffer descriptor bits & masks */ +#define BD_STAT_OWN (1 << 31) +#define BD_STAT_BD_FIRST (1 << 3) +#define BD_STAT_BD_LAST (1 << 2) +#define BD_SIZES_BUFFER1_MASK 0xfff + +#define BD_STAT_BD_COMPLETE (BD_STAT_BD_FIRST | BD_STAT_BD_LAST) + +/* Controller command flags */ +#define B_WFR (1 << 19) /* 1b - Wait for ready */ +#define B_LC (1 << 18) /* 1b - Last cycle */ +#define B_IWC (1 << 13) /* 1b - Interrupt when complete */ + +/* NAND cycle types */ +#define B_CT_ADDRESS (0x0 << 16) /* Address operation */ +#define B_CT_COMMAND (0x1 << 16) /* Command operation */ +#define B_CT_WRITE (0x2 << 16) /* Write operation */ +#define B_CT_READ (0x3 << 16) /* Write operation */ + +enum nand_isr_t { + NAND_ISR_DATAREQUIRED = 0, + NAND_ISR_TXUNDERFLOW, + NAND_ISR_TXOVERFLOW, + NAND_ISR_DATAAVAILABLE, + NAND_ISR_RXUNDERFLOW, + NAND_ISR_RXOVERFLOW, + NAND_ISR_TXDMACOMPLETE, + NAND_ISR_RXDMACOMPLETE, + NAND_ISR_DESCRIPTORUNAVAILABLE, + NAND_ISR_CMDDONE, + NAND_ISR_CMDAVAILABLE, + NAND_ISR_CMDERROR, + NAND_ISR_DATATRANSFEROVER, + NAND_ISR_NONE +}; + +enum nand_regs_t { + AC_FIFO = 0, /* address and command fifo */ + IDMAC_BDADDR = 0x18, /* idmac descriptor list base address */ + INT_STATUS = 0x118, /* interrupt status register */ + INT_CLR_STATUS = 0x120, /* interrupt clear status register */ +}; + +struct nand_bd { + uint32_t status; /* DES0 */ + uint32_t sizes; /* DES1 */ + uint32_t buffer_ptr0; /* DES2 */ + uint32_t buffer_ptr1; /* DES3 */ +}; + +#define NAND_REG_WRITE(r, v) \ + writel(v, (volatile void __iomem *)(CONFIG_SYS_NAND_BASE + r)) +#define NAND_REG_READ(r) \ + readl((const volatile void __iomem *)(CONFIG_SYS_NAND_BASE + r)) + +static struct nand_bd *bd; /* DMA buffer descriptors */ + +/** + * axs101_nand_write_buf - write buffer to chip + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write + */ +static uint32_t nand_flag_is_set(uint32_t flag) +{ + uint32_t reg = NAND_REG_READ(INT_STATUS); + + if (reg & (1 << NAND_ISR_CMDERROR)) + return 0; + + if (reg & (1 << flag)) { + NAND_REG_WRITE(INT_CLR_STATUS, 1 << flag); + return 1; + } + + return 0; +} + +/** + * axs101_nand_write_buf - write buffer to chip + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write + */ +static void axs101_nand_write_buf(struct mtd_info *mtd, const u_char *buf, + int len) +{ + struct bounce_buffer bbstate; + + bounce_buffer_start(&bbstate, (void *)buf, len, GEN_BB_READ); + + /* Setup buffer descriptor */ + writel(BD_STAT_OWN | BD_STAT_BD_COMPLETE, &bd->status); + writel(ALIGN(len, BUS_WIDTH) & BD_SIZES_BUFFER1_MASK, &bd->sizes); + writel(bbstate.bounce_buffer, &bd->buffer_ptr0); + writel(0, &bd->buffer_ptr1); + + /* Flush modified buffer descriptor */ + flush_dcache_range((unsigned long)bd, + (unsigned long)bd + sizeof(struct nand_bd)); + + /* Issue "write" command */ + NAND_REG_WRITE(AC_FIFO, B_CT_WRITE | B_WFR | B_IWC | B_LC | (len-1)); + + /* Wait for NAND command and DMA to complete */ + while (!nand_flag_is_set(NAND_ISR_CMDDONE)) + ; + while (!nand_flag_is_set(NAND_ISR_TXDMACOMPLETE)) + ; + + bounce_buffer_stop(&bbstate); +} + +/** + * axs101_nand_read_buf - read chip data into buffer + * @mtd: MTD device structure + * @buf: buffer to store data + * @len: number of bytes to read + */ +static void axs101_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +{ + struct bounce_buffer bbstate; + + bounce_buffer_start(&bbstate, buf, len, GEN_BB_WRITE); + + /* Setup buffer descriptor */ + writel(BD_STAT_OWN | BD_STAT_BD_COMPLETE, &bd->status); + writel(ALIGN(len, BUS_WIDTH) & BD_SIZES_BUFFER1_MASK, &bd->sizes); + writel(bbstate.bounce_buffer, &bd->buffer_ptr0); + writel(0, &bd->buffer_ptr1); + + /* Flush modified buffer descriptor */ + flush_dcache_range((unsigned long)bd, + (unsigned long)bd + sizeof(struct nand_bd)); + + /* Issue "read" command */ + NAND_REG_WRITE(AC_FIFO, B_CT_READ | B_WFR | B_IWC | B_LC | (len - 1)); + + /* Wait for NAND command and DMA to complete */ + while (!nand_flag_is_set(NAND_ISR_CMDDONE)) + ; + while (!nand_flag_is_set(NAND_ISR_RXDMACOMPLETE)) + ; + + bounce_buffer_stop(&bbstate); +} + +/** + * axs101_nand_read_byte - read one byte from the chip + * @mtd: MTD device structure + */ +static u_char axs101_nand_read_byte(struct mtd_info *mtd) +{ + u8 byte; + + axs101_nand_read_buf(mtd, (uchar *)&byte, sizeof(byte)); + return byte; +} + +/** + * axs101_nand_read_word - read one word from the chip + * @mtd: MTD device structure + */ +static u16 axs101_nand_read_word(struct mtd_info *mtd) +{ + u16 word; + + axs101_nand_read_buf(mtd, (uchar *)&word, sizeof(word)); + return word; +} + +/** + * axs101_nand_hwcontrol - NAND control functions wrapper. + * @mtd: MTD device structure + * @cmd: Command + */ +static void axs101_nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, + unsigned int ctrl) +{ + if (cmd == NAND_CMD_NONE) + return; + + cmd = cmd & 0xff; + + switch (ctrl & (NAND_ALE | NAND_CLE)) { + /* Address */ + case NAND_ALE: + cmd |= B_CT_ADDRESS; + break; + + /* Command */ + case NAND_CLE: + cmd |= B_CT_COMMAND | B_WFR; + + break; + + default: + debug("%s: unknown ctrl %#x\n", __func__, ctrl); + } + + NAND_REG_WRITE(AC_FIFO, cmd | B_LC); + while (!nand_flag_is_set(NAND_ISR_CMDDONE)) + ; +} + +int board_nand_init(struct nand_chip *nand) +{ + bd = (struct nand_bd *)memalign(ARCH_DMA_MINALIGN, + sizeof(struct nand_bd)); + + /* Set buffer descriptor address in IDMAC */ + NAND_REG_WRITE(IDMAC_BDADDR, bd); + + nand->ecc.mode = NAND_ECC_SOFT; + nand->cmd_ctrl = axs101_nand_hwcontrol; + nand->read_byte = axs101_nand_read_byte; + nand->read_word = axs101_nand_read_word; + nand->write_buf = axs101_nand_write_buf; + nand->read_buf = axs101_nand_read_buf; + + /* MBv3 has NAND IC with 16-bit data bus */ + if (gd->board_type == AXS_MB_V3) + nand->options |= NAND_BUSWIDTH_16; + + return 0; +} |