Home | History | Annotate | Line # | Download | only in bfin
      1 /* Blackfin NAND Flash Memory Controller (NFC) model
      2 
      3    Copyright (C) 2010-2024 Free Software Foundation, Inc.
      4    Contributed by Analog Devices, Inc.
      5 
      6    This file is part of simulators.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20 
     21 /* This must come before any other includes.  */
     22 #include "defs.h"
     23 
     24 #include "sim-main.h"
     25 #include "devices.h"
     26 #include "dv-bfin_nfc.h"
     27 
     28 /* XXX: This is merely a stub.  */
     29 
     30 struct bfin_nfc
     31 {
     32   /* This top portion matches common dv_bfin struct.  */
     33   bu32 base;
     34   struct hw *dma_master;
     35   bool acked;
     36 
     37   struct hw_event *handler;
     38   char saved_byte;
     39   int saved_count;
     40 
     41   /* Order after here is important -- matches hardware MMR layout.  */
     42   bu16 BFIN_MMR_16(ctl);
     43   bu16 BFIN_MMR_16(stat);
     44   bu16 BFIN_MMR_16(irqstat);
     45   bu16 BFIN_MMR_16(irqmask);
     46   bu16 BFIN_MMR_16(ecc0);
     47   bu16 BFIN_MMR_16(ecc1);
     48   bu16 BFIN_MMR_16(ecc2);
     49   bu16 BFIN_MMR_16(ecc3);
     50   bu16 BFIN_MMR_16(count);
     51   bu16 BFIN_MMR_16(rst);
     52   bu16 BFIN_MMR_16(pgctl);
     53   bu16 BFIN_MMR_16(read);
     54   bu32 _pad0[4];
     55   bu16 BFIN_MMR_16(addr);
     56   bu16 BFIN_MMR_16(cmd);
     57   bu16 BFIN_MMR_16(data_wr);
     58   bu16 BFIN_MMR_16(data_rd);
     59 };
     60 #define mmr_base()      offsetof(struct bfin_nfc, ctl)
     61 #define mmr_offset(mmr) (offsetof(struct bfin_nfc, mmr) - mmr_base())
     62 #define mmr_idx(mmr)    (mmr_offset (mmr) / 4)
     63 
     64 static const char * const mmr_names[] =
     65 {
     66   "NFC_CTL", "NFC_STAT", "NFC_IRQSTAT", "NFC_IRQMASK", "NFC_ECC0", "NFC_ECC1",
     67   "NFC_ECC2", "NFC_ECC3", "NFC_COUNT", "NFC_RST", "NFC_PGCTL", "NFC_READ",
     68   [mmr_idx (addr)] = "NFC_ADDR", "NFC_CMD", "NFC_DATA_WR", "NFC_DATA_RD",
     69 };
     70 #define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
     71 
     72 static unsigned
     73 bfin_nfc_io_write_buffer (struct hw *me, const void *source, int space,
     74 			  address_word addr, unsigned nr_bytes)
     75 {
     76   struct bfin_nfc *nfc = hw_data (me);
     77   bu32 mmr_off;
     78   bu32 value;
     79   bu16 *valuep;
     80 
     81   /* Invalid access mode is higher priority than missing register.  */
     82   if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true))
     83     return 0;
     84 
     85   value = dv_load_2 (source);
     86   mmr_off = addr - nfc->base;
     87   valuep = (void *)((uintptr_t)nfc + mmr_base() + mmr_off);
     88 
     89   HW_TRACE_WRITE ();
     90 
     91   switch (mmr_off)
     92     {
     93     case mmr_offset(ctl):
     94     case mmr_offset(stat):
     95     case mmr_offset(irqmask):
     96     case mmr_offset(ecc0):
     97     case mmr_offset(ecc1):
     98     case mmr_offset(ecc2):
     99     case mmr_offset(ecc3):
    100     case mmr_offset(count):
    101     case mmr_offset(rst):
    102     case mmr_offset(pgctl):
    103     case mmr_offset(read):
    104     case mmr_offset(addr):
    105     case mmr_offset(cmd):
    106     case mmr_offset(data_wr):
    107       *valuep = value;
    108       break;
    109     case mmr_offset(data_rd):
    110       nfc->irqstat |= RD_RDY;
    111       *valuep = value;
    112       break;
    113     case mmr_offset(irqstat):
    114       dv_w1c_2 (valuep, value, -1);
    115       break;
    116     default:
    117       dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
    118       return 0;
    119     }
    120 
    121   return nr_bytes;
    122 }
    123 
    124 static unsigned
    125 bfin_nfc_io_read_buffer (struct hw *me, void *dest, int space,
    126 			 address_word addr, unsigned nr_bytes)
    127 {
    128   struct bfin_nfc *nfc = hw_data (me);
    129   bu32 mmr_off;
    130   bu16 *valuep;
    131 
    132   /* Invalid access mode is higher priority than missing register.  */
    133   if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, false))
    134     return 0;
    135 
    136   mmr_off = addr - nfc->base;
    137   valuep = (void *)((uintptr_t)nfc + mmr_base() + mmr_off);
    138 
    139   HW_TRACE_READ ();
    140 
    141   switch (mmr_off)
    142     {
    143     case mmr_offset(ctl):
    144     case mmr_offset(stat):
    145     case mmr_offset(irqstat):
    146     case mmr_offset(irqmask):
    147     case mmr_offset(ecc0):
    148     case mmr_offset(ecc1):
    149     case mmr_offset(ecc2):
    150     case mmr_offset(ecc3):
    151     case mmr_offset(count):
    152     case mmr_offset(rst):
    153     case mmr_offset(read):
    154       dv_store_2 (dest, *valuep);
    155       break;
    156     case mmr_offset(pgctl):
    157     case mmr_offset(addr):
    158     case mmr_offset(cmd):
    159     case mmr_offset(data_wr):
    160     case mmr_offset(data_rd):
    161       /* These regs are write only.  */
    162     default:
    163       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
    164       return 0;
    165     }
    166 
    167   return nr_bytes;
    168 }
    169 
    170 static unsigned
    171 bfin_nfc_dma_read_buffer (struct hw *me, void *dest, int space,
    172 			  unsigned_word addr, unsigned nr_bytes)
    173 {
    174   HW_TRACE_DMA_READ ();
    175   return 0;
    176 }
    177 
    178 static unsigned
    179 bfin_nfc_dma_write_buffer (struct hw *me, const void *source,
    180 			   int space, unsigned_word addr,
    181 			   unsigned nr_bytes,
    182 			   int violate_read_only_section)
    183 {
    184   HW_TRACE_DMA_WRITE ();
    185   return nr_bytes;
    186 }
    187 
    188 static const struct hw_port_descriptor bfin_nfc_ports[] =
    189 {
    190   { "stat", 0, 0, output_port, },
    191   { NULL, 0, 0, 0, },
    192 };
    193 
    194 static void
    195 attach_bfin_nfc_regs (struct hw *me, struct bfin_nfc *nfc)
    196 {
    197   address_word attach_address;
    198   int attach_space;
    199   unsigned attach_size;
    200   reg_property_spec reg;
    201 
    202   if (hw_find_property (me, "reg") == NULL)
    203     hw_abort (me, "Missing \"reg\" property");
    204 
    205   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
    206     hw_abort (me, "\"reg\" property must contain three addr/size entries");
    207 
    208   hw_unit_address_to_attach_address (hw_parent (me),
    209 				     &reg.address,
    210 				     &attach_space, &attach_address, me);
    211   hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
    212 
    213   if (attach_size != BFIN_MMR_NFC_SIZE)
    214     hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_NFC_SIZE);
    215 
    216   hw_attach_address (hw_parent (me),
    217 		     0, attach_space, attach_address, attach_size, me);
    218 
    219   nfc->base = attach_address;
    220 }
    221 
    222 static void
    223 bfin_nfc_finish (struct hw *me)
    224 {
    225   struct bfin_nfc *nfc;
    226 
    227   nfc = HW_ZALLOC (me, struct bfin_nfc);
    228 
    229   set_hw_data (me, nfc);
    230   set_hw_io_read_buffer (me, bfin_nfc_io_read_buffer);
    231   set_hw_io_write_buffer (me, bfin_nfc_io_write_buffer);
    232   set_hw_dma_read_buffer (me, bfin_nfc_dma_read_buffer);
    233   set_hw_dma_write_buffer (me, bfin_nfc_dma_write_buffer);
    234   set_hw_ports (me, bfin_nfc_ports);
    235 
    236   attach_bfin_nfc_regs (me, nfc);
    237 
    238   /* Initialize the NFC.  */
    239   nfc->ctl     = 0x0200;
    240   nfc->stat    = 0x0011;
    241   nfc->irqstat = 0x0004;
    242   nfc->irqmask = 0x001F;
    243 }
    244 
    245 const struct hw_descriptor dv_bfin_nfc_descriptor[] =
    246 {
    247   {"bfin_nfc", bfin_nfc_finish,},
    248   {NULL, NULL},
    249 };
    250