Home | History | Annotate | Line # | Download | only in bfin
dv-bfin_ppi.c revision 1.11
      1   1.1  christos /* Blackfin Parallel Port Interface (PPI) model
      2   1.1  christos    For "old style" PPIs on BF53x/etc... parts.
      3   1.1  christos 
      4  1.11  christos    Copyright (C) 2010-2024 Free Software Foundation, Inc.
      5   1.1  christos    Contributed by Analog Devices, Inc.
      6   1.1  christos 
      7   1.1  christos    This file is part of simulators.
      8   1.1  christos 
      9   1.1  christos    This program is free software; you can redistribute it and/or modify
     10   1.1  christos    it under the terms of the GNU General Public License as published by
     11   1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12   1.1  christos    (at your option) any later version.
     13   1.1  christos 
     14   1.1  christos    This program is distributed in the hope that it will be useful,
     15   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17   1.1  christos    GNU General Public License for more details.
     18   1.1  christos 
     19   1.1  christos    You should have received a copy of the GNU General Public License
     20   1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     21   1.1  christos 
     22  1.10  christos /* This must come before any other includes.  */
     23  1.10  christos #include "defs.h"
     24   1.1  christos 
     25   1.1  christos #include "sim-main.h"
     26   1.1  christos #include "devices.h"
     27   1.1  christos #include "dv-bfin_ppi.h"
     28   1.1  christos #include "gui.h"
     29   1.1  christos 
     30   1.1  christos /* XXX: TX is merely a stub.  */
     31   1.1  christos 
     32   1.1  christos struct bfin_ppi
     33   1.1  christos {
     34   1.1  christos   /* This top portion matches common dv_bfin struct.  */
     35   1.1  christos   bu32 base;
     36   1.1  christos   struct hw *dma_master;
     37   1.1  christos   bool acked;
     38   1.1  christos 
     39   1.1  christos   struct hw_event *handler;
     40   1.1  christos   char saved_byte;
     41   1.1  christos   int saved_count;
     42   1.1  christos 
     43   1.1  christos   /* GUI state.  */
     44   1.1  christos   void *gui_state;
     45   1.1  christos   int color;
     46   1.1  christos 
     47   1.1  christos   /* Order after here is important -- matches hardware MMR layout.  */
     48   1.1  christos   bu16 BFIN_MMR_16(control);
     49   1.1  christos   bu16 BFIN_MMR_16(status);
     50   1.1  christos   bu16 BFIN_MMR_16(count);
     51   1.1  christos   bu16 BFIN_MMR_16(delay);
     52   1.1  christos   bu16 BFIN_MMR_16(frame);
     53   1.1  christos };
     54   1.1  christos #define mmr_base()      offsetof(struct bfin_ppi, control)
     55   1.1  christos #define mmr_offset(mmr) (offsetof(struct bfin_ppi, mmr) - mmr_base())
     56   1.1  christos 
     57   1.1  christos static const char * const mmr_names[] =
     58   1.1  christos {
     59   1.1  christos   "PPI_CONTROL", "PPI_STATUS", "PPI_COUNT", "PPI_DELAY", "PPI_FRAME",
     60   1.1  christos };
     61   1.1  christos #define mmr_name(off) mmr_names[(off) / 4]
     62   1.1  christos 
     63   1.1  christos static void
     64   1.1  christos bfin_ppi_gui_setup (struct bfin_ppi *ppi)
     65   1.1  christos {
     66   1.1  christos   int bpp;
     67   1.1  christos 
     68   1.1  christos   /* If we are in RX mode, nothing to do.  */
     69   1.1  christos   if (!(ppi->control & PORT_DIR))
     70   1.1  christos     return;
     71   1.1  christos 
     72   1.1  christos   bpp = bfin_gui_color_depth (ppi->color);
     73   1.1  christos   ppi->gui_state = bfin_gui_setup (ppi->gui_state,
     74   1.1  christos 				   ppi->control & PORT_EN,
     75   1.1  christos 				   (ppi->count + 1) / (bpp / 8),
     76   1.1  christos 				   ppi->frame,
     77   1.1  christos 				   ppi->color);
     78   1.1  christos }
     79   1.1  christos 
     80   1.1  christos static unsigned
     81   1.1  christos bfin_ppi_io_write_buffer (struct hw *me, const void *source, int space,
     82   1.1  christos 			  address_word addr, unsigned nr_bytes)
     83   1.1  christos {
     84   1.1  christos   struct bfin_ppi *ppi = hw_data (me);
     85   1.1  christos   bu32 mmr_off;
     86   1.1  christos   bu32 value;
     87   1.1  christos   bu16 *valuep;
     88   1.1  christos 
     89   1.6  christos   /* Invalid access mode is higher priority than missing register.  */
     90   1.6  christos   if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true))
     91   1.6  christos     return 0;
     92   1.6  christos 
     93   1.1  christos   value = dv_load_2 (source);
     94   1.1  christos   mmr_off = addr - ppi->base;
     95  1.10  christos   valuep = (void *)((uintptr_t)ppi + mmr_base() + mmr_off);
     96   1.1  christos 
     97   1.1  christos   HW_TRACE_WRITE ();
     98   1.1  christos 
     99   1.1  christos   switch (mmr_off)
    100   1.1  christos     {
    101   1.1  christos     case mmr_offset(control):
    102   1.1  christos       *valuep = value;
    103   1.1  christos       bfin_ppi_gui_setup (ppi);
    104   1.1  christos       break;
    105   1.1  christos     case mmr_offset(count):
    106   1.1  christos     case mmr_offset(delay):
    107   1.1  christos     case mmr_offset(frame):
    108   1.1  christos       *valuep = value;
    109   1.1  christos       break;
    110   1.1  christos     case mmr_offset(status):
    111   1.1  christos       dv_w1c_2 (valuep, value, ~(1 << 10));
    112   1.1  christos       break;
    113   1.1  christos     default:
    114   1.1  christos       dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
    115   1.6  christos       return 0;
    116   1.1  christos     }
    117   1.1  christos 
    118   1.1  christos   return nr_bytes;
    119   1.1  christos }
    120   1.1  christos 
    121   1.1  christos static unsigned
    122   1.1  christos bfin_ppi_io_read_buffer (struct hw *me, void *dest, int space,
    123   1.1  christos 			 address_word addr, unsigned nr_bytes)
    124   1.1  christos {
    125   1.1  christos   struct bfin_ppi *ppi = hw_data (me);
    126   1.1  christos   bu32 mmr_off;
    127   1.1  christos   bu16 *valuep;
    128   1.1  christos 
    129   1.6  christos   /* Invalid access mode is higher priority than missing register.  */
    130   1.6  christos   if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, false))
    131   1.6  christos     return 0;
    132   1.6  christos 
    133   1.1  christos   mmr_off = addr - ppi->base;
    134  1.10  christos   valuep = (void *)((uintptr_t)ppi + mmr_base() + mmr_off);
    135   1.1  christos 
    136   1.1  christos   HW_TRACE_READ ();
    137   1.1  christos 
    138   1.1  christos   switch (mmr_off)
    139   1.1  christos     {
    140   1.1  christos     case mmr_offset(control):
    141   1.1  christos     case mmr_offset(count):
    142   1.1  christos     case mmr_offset(delay):
    143   1.1  christos     case mmr_offset(frame):
    144   1.1  christos     case mmr_offset(status):
    145   1.1  christos       dv_store_2 (dest, *valuep);
    146   1.1  christos       break;
    147   1.1  christos     default:
    148   1.1  christos       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
    149   1.6  christos       return 0;
    150   1.1  christos     }
    151   1.1  christos 
    152   1.1  christos   return nr_bytes;
    153   1.1  christos }
    154   1.1  christos 
    155   1.1  christos static unsigned
    156   1.1  christos bfin_ppi_dma_read_buffer (struct hw *me, void *dest, int space,
    157   1.1  christos 			  unsigned_word addr, unsigned nr_bytes)
    158   1.1  christos {
    159   1.1  christos   HW_TRACE_DMA_READ ();
    160   1.1  christos   return 0;
    161   1.1  christos }
    162   1.1  christos 
    163   1.1  christos static unsigned
    164   1.1  christos bfin_ppi_dma_write_buffer (struct hw *me, const void *source,
    165   1.1  christos 			   int space, unsigned_word addr,
    166   1.1  christos 			   unsigned nr_bytes,
    167   1.1  christos 			   int violate_read_only_section)
    168   1.1  christos {
    169   1.1  christos   struct bfin_ppi *ppi = hw_data (me);
    170   1.1  christos 
    171   1.1  christos   HW_TRACE_DMA_WRITE ();
    172   1.1  christos 
    173   1.1  christos   return bfin_gui_update (ppi->gui_state, source, nr_bytes);
    174   1.1  christos }
    175   1.1  christos 
    176   1.1  christos static const struct hw_port_descriptor bfin_ppi_ports[] =
    177   1.1  christos {
    178   1.1  christos   { "stat", 0, 0, output_port, },
    179   1.1  christos   { NULL, 0, 0, 0, },
    180   1.1  christos };
    181   1.1  christos 
    182   1.1  christos static void
    183   1.1  christos attach_bfin_ppi_regs (struct hw *me, struct bfin_ppi *ppi)
    184   1.1  christos {
    185   1.1  christos   address_word attach_address;
    186   1.1  christos   int attach_space;
    187   1.1  christos   unsigned attach_size;
    188   1.1  christos   reg_property_spec reg;
    189   1.1  christos 
    190   1.1  christos   if (hw_find_property (me, "reg") == NULL)
    191   1.1  christos     hw_abort (me, "Missing \"reg\" property");
    192   1.1  christos 
    193   1.1  christos   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
    194   1.1  christos     hw_abort (me, "\"reg\" property must contain three addr/size entries");
    195   1.1  christos 
    196   1.1  christos   hw_unit_address_to_attach_address (hw_parent (me),
    197   1.1  christos 				     &reg.address,
    198   1.1  christos 				     &attach_space, &attach_address, me);
    199   1.1  christos   hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
    200   1.1  christos 
    201   1.1  christos   if (attach_size != BFIN_MMR_PPI_SIZE)
    202   1.1  christos     hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_PPI_SIZE);
    203   1.1  christos 
    204   1.1  christos   hw_attach_address (hw_parent (me),
    205   1.1  christos 		     0, attach_space, attach_address, attach_size, me);
    206   1.1  christos 
    207   1.1  christos   ppi->base = attach_address;
    208   1.1  christos }
    209   1.1  christos 
    210   1.1  christos static void
    211   1.1  christos bfin_ppi_finish (struct hw *me)
    212   1.1  christos {
    213   1.1  christos   struct bfin_ppi *ppi;
    214   1.1  christos   const char *color;
    215   1.1  christos 
    216   1.1  christos   ppi = HW_ZALLOC (me, struct bfin_ppi);
    217   1.1  christos 
    218   1.1  christos   set_hw_data (me, ppi);
    219   1.1  christos   set_hw_io_read_buffer (me, bfin_ppi_io_read_buffer);
    220   1.1  christos   set_hw_io_write_buffer (me, bfin_ppi_io_write_buffer);
    221   1.1  christos   set_hw_dma_read_buffer (me, bfin_ppi_dma_read_buffer);
    222   1.1  christos   set_hw_dma_write_buffer (me, bfin_ppi_dma_write_buffer);
    223   1.1  christos   set_hw_ports (me, bfin_ppi_ports);
    224   1.1  christos 
    225   1.1  christos   attach_bfin_ppi_regs (me, ppi);
    226   1.1  christos 
    227   1.1  christos   /* Initialize the PPI.  */
    228   1.1  christos   if (hw_find_property (me, "color"))
    229   1.1  christos     color = hw_find_string_property (me, "color");
    230   1.1  christos   else
    231   1.1  christos     color = NULL;
    232   1.1  christos   ppi->color = bfin_gui_color (color);
    233   1.1  christos }
    234   1.1  christos 
    235   1.1  christos const struct hw_descriptor dv_bfin_ppi_descriptor[] =
    236   1.1  christos {
    237   1.1  christos   {"bfin_ppi", bfin_ppi_finish,},
    238   1.1  christos   {NULL, NULL},
    239   1.1  christos };
    240