uboot/board/synopsys/axs10x/nand.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <bouncebuf.h>
   8#include <common.h>
   9#include <malloc.h>
  10#include <nand.h>
  11#include <asm/io.h>
  12#include "axs10x.h"
  13
  14DECLARE_GLOBAL_DATA_PTR;
  15
  16#define BUS_WIDTH       8               /* AXI data bus width in bytes  */
  17
  18/* DMA buffer descriptor bits & masks */
  19#define BD_STAT_OWN                     (1 << 31)
  20#define BD_STAT_BD_FIRST                (1 << 3)
  21#define BD_STAT_BD_LAST                 (1 << 2)
  22#define BD_SIZES_BUFFER1_MASK           0xfff
  23
  24#define BD_STAT_BD_COMPLETE     (BD_STAT_BD_FIRST | BD_STAT_BD_LAST)
  25
  26/* Controller command flags */
  27#define B_WFR           (1 << 19)       /* 1b - Wait for ready          */
  28#define B_LC            (1 << 18)       /* 1b - Last cycle              */
  29#define B_IWC           (1 << 13)       /* 1b - Interrupt when complete */
  30
  31/* NAND cycle types */
  32#define B_CT_ADDRESS    (0x0 << 16)     /* Address operation            */
  33#define B_CT_COMMAND    (0x1 << 16)     /* Command operation            */
  34#define B_CT_WRITE      (0x2 << 16)     /* Write operation              */
  35#define B_CT_READ       (0x3 << 16)     /* Write operation              */
  36
  37enum nand_isr_t {
  38        NAND_ISR_DATAREQUIRED = 0,
  39        NAND_ISR_TXUNDERFLOW,
  40        NAND_ISR_TXOVERFLOW,
  41        NAND_ISR_DATAAVAILABLE,
  42        NAND_ISR_RXUNDERFLOW,
  43        NAND_ISR_RXOVERFLOW,
  44        NAND_ISR_TXDMACOMPLETE,
  45        NAND_ISR_RXDMACOMPLETE,
  46        NAND_ISR_DESCRIPTORUNAVAILABLE,
  47        NAND_ISR_CMDDONE,
  48        NAND_ISR_CMDAVAILABLE,
  49        NAND_ISR_CMDERROR,
  50        NAND_ISR_DATATRANSFEROVER,
  51        NAND_ISR_NONE
  52};
  53
  54enum nand_regs_t {
  55        AC_FIFO = 0,            /* address and command fifo */
  56        IDMAC_BDADDR = 0x18,    /* idmac descriptor list base address */
  57        INT_STATUS = 0x118,     /* interrupt status register */
  58        INT_CLR_STATUS = 0x120, /* interrupt clear status register */
  59};
  60
  61struct nand_bd {
  62        uint32_t status;        /* DES0 */
  63        uint32_t sizes;         /* DES1 */
  64        uint32_t buffer_ptr0;   /* DES2 */
  65        uint32_t buffer_ptr1;   /* DES3 */
  66};
  67
  68#define NAND_REG_WRITE(r, v)    \
  69        writel(v, (volatile void __iomem *)(CONFIG_SYS_NAND_BASE + r))
  70#define NAND_REG_READ(r)                \
  71        readl((const volatile void __iomem *)(CONFIG_SYS_NAND_BASE + r))
  72
  73static struct nand_bd *bd;      /* DMA buffer descriptors       */
  74
  75/**
  76 * axs101_nand_write_buf -  write buffer to chip
  77 * @mtd:        MTD device structure
  78 * @buf:        data buffer
  79 * @len:        number of bytes to write
  80 */
  81static uint32_t nand_flag_is_set(uint32_t flag)
  82{
  83        uint32_t reg = NAND_REG_READ(INT_STATUS);
  84
  85        if (reg & (1 << NAND_ISR_CMDERROR))
  86                return 0;
  87
  88        if (reg & (1 << flag)) {
  89                NAND_REG_WRITE(INT_CLR_STATUS, 1 << flag);
  90                return 1;
  91        }
  92
  93        return 0;
  94}
  95
  96/**
  97 * axs101_nand_write_buf -  write buffer to chip
  98 * @mtd:        MTD device structure
  99 * @buf:        data buffer
 100 * @len:        number of bytes to write
 101 */
 102static void axs101_nand_write_buf(struct mtd_info *mtd, const u_char *buf,
 103                                   int len)
 104{
 105        struct bounce_buffer bbstate;
 106
 107        bounce_buffer_start(&bbstate, (void *)buf, len, GEN_BB_READ);
 108
 109        /* Setup buffer descriptor */
 110        writel(BD_STAT_OWN | BD_STAT_BD_COMPLETE, &bd->status);
 111        writel(ALIGN(len, BUS_WIDTH) & BD_SIZES_BUFFER1_MASK, &bd->sizes);
 112        writel(bbstate.bounce_buffer, &bd->buffer_ptr0);
 113        writel(0, &bd->buffer_ptr1);
 114
 115        /* Flush modified buffer descriptor */
 116        flush_dcache_range((unsigned long)bd,
 117                           (unsigned long)bd + sizeof(struct nand_bd));
 118
 119        /* Issue "write" command */
 120        NAND_REG_WRITE(AC_FIFO, B_CT_WRITE | B_WFR | B_IWC | B_LC | (len-1));
 121
 122        /* Wait for NAND command and DMA to complete */
 123        while (!nand_flag_is_set(NAND_ISR_CMDDONE))
 124                ;
 125        while (!nand_flag_is_set(NAND_ISR_TXDMACOMPLETE))
 126                ;
 127
 128        bounce_buffer_stop(&bbstate);
 129}
 130
 131/**
 132 * axs101_nand_read_buf -  read chip data into buffer
 133 * @mtd:        MTD device structure
 134 * @buf:        buffer to store data
 135 * @len:        number of bytes to read
 136 */
 137static void axs101_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 138{
 139        struct bounce_buffer bbstate;
 140
 141        bounce_buffer_start(&bbstate, buf, len, GEN_BB_WRITE);
 142
 143        /* Setup buffer descriptor */
 144        writel(BD_STAT_OWN | BD_STAT_BD_COMPLETE, &bd->status);
 145        writel(ALIGN(len, BUS_WIDTH) & BD_SIZES_BUFFER1_MASK, &bd->sizes);
 146        writel(bbstate.bounce_buffer, &bd->buffer_ptr0);
 147        writel(0, &bd->buffer_ptr1);
 148
 149        /* Flush modified buffer descriptor */
 150        flush_dcache_range((unsigned long)bd,
 151                           (unsigned long)bd + sizeof(struct nand_bd));
 152
 153        /* Issue "read" command */
 154        NAND_REG_WRITE(AC_FIFO, B_CT_READ | B_WFR | B_IWC | B_LC | (len - 1));
 155
 156        /* Wait for NAND command and DMA to complete */
 157        while (!nand_flag_is_set(NAND_ISR_CMDDONE))
 158                ;
 159        while (!nand_flag_is_set(NAND_ISR_RXDMACOMPLETE))
 160                ;
 161
 162        bounce_buffer_stop(&bbstate);
 163}
 164
 165/**
 166 * axs101_nand_read_byte -  read one byte from the chip
 167 * @mtd:        MTD device structure
 168 */
 169static u_char axs101_nand_read_byte(struct mtd_info *mtd)
 170{
 171        u8 byte;
 172
 173        axs101_nand_read_buf(mtd, (uchar *)&byte, sizeof(byte));
 174        return byte;
 175}
 176
 177/**
 178 * axs101_nand_read_word -  read one word from the chip
 179 * @mtd:        MTD device structure
 180 */
 181static u16 axs101_nand_read_word(struct mtd_info *mtd)
 182{
 183        u16 word;
 184
 185        axs101_nand_read_buf(mtd, (uchar *)&word, sizeof(word));
 186        return word;
 187}
 188
 189/**
 190 * axs101_nand_hwcontrol - NAND control functions wrapper.
 191 * @mtd:        MTD device structure
 192 * @cmd:        Command
 193 */
 194static void axs101_nand_hwcontrol(struct mtd_info *mtdinfo, int cmd,
 195                                   unsigned int ctrl)
 196{
 197        if (cmd == NAND_CMD_NONE)
 198                return;
 199
 200        cmd = cmd & 0xff;
 201
 202        switch (ctrl & (NAND_ALE | NAND_CLE)) {
 203        /* Address */
 204        case NAND_ALE:
 205                cmd |= B_CT_ADDRESS;
 206                break;
 207
 208        /* Command */
 209        case NAND_CLE:
 210                cmd |= B_CT_COMMAND | B_WFR;
 211
 212                break;
 213
 214        default:
 215                debug("%s: unknown ctrl %#x\n", __func__, ctrl);
 216        }
 217
 218        NAND_REG_WRITE(AC_FIFO, cmd | B_LC);
 219        while (!nand_flag_is_set(NAND_ISR_CMDDONE))
 220                ;
 221}
 222
 223int board_nand_init(struct nand_chip *nand)
 224{
 225        bd = (struct nand_bd *)memalign(ARCH_DMA_MINALIGN,
 226                                        sizeof(struct nand_bd));
 227
 228        /* Set buffer descriptor address in IDMAC */
 229        NAND_REG_WRITE(IDMAC_BDADDR, bd);
 230
 231        nand->ecc.mode = NAND_ECC_SOFT;
 232        nand->cmd_ctrl = axs101_nand_hwcontrol;
 233        nand->read_byte = axs101_nand_read_byte;
 234        nand->read_word = axs101_nand_read_word;
 235        nand->write_buf = axs101_nand_write_buf;
 236        nand->read_buf = axs101_nand_read_buf;
 237
 238        /* MBv3 has NAND IC with 16-bit data bus */
 239        if (gd->board_type == AXS_MB_V3)
 240                nand->options |= NAND_BUSWIDTH_16;
 241
 242        return 0;
 243}
 244