Home | History | Annotate | Line # | Download | only in bfin
      1   1.1  christos /* Blackfin Watchdog (WDOG) model.
      2   1.1  christos 
      3  1.11  christos    Copyright (C) 2010-2024 Free Software Foundation, Inc.
      4   1.1  christos    Contributed by Analog Devices, Inc.
      5   1.1  christos 
      6   1.1  christos    This file is part of simulators.
      7   1.1  christos 
      8   1.1  christos    This program is free software; you can redistribute it and/or modify
      9   1.1  christos    it under the terms of the GNU General Public License as published by
     10   1.1  christos    the Free Software Foundation; either version 3 of the License, or
     11   1.1  christos    (at your option) any later version.
     12   1.1  christos 
     13   1.1  christos    This program is distributed in the hope that it will be useful,
     14   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16   1.1  christos    GNU General Public License for more details.
     17   1.1  christos 
     18   1.1  christos    You should have received a copy of the GNU General Public License
     19   1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20   1.1  christos 
     21  1.10  christos /* This must come before any other includes.  */
     22  1.10  christos #include "defs.h"
     23   1.1  christos 
     24   1.1  christos #include "sim-main.h"
     25   1.1  christos #include "dv-sockser.h"
     26   1.1  christos #include "devices.h"
     27   1.1  christos #include "dv-bfin_wdog.h"
     28   1.1  christos 
     29   1.1  christos /* XXX: Should we bother emulating the TX/RX FIFOs ?  */
     30   1.1  christos 
     31   1.1  christos struct bfin_wdog
     32   1.1  christos {
     33   1.1  christos   bu32 base;
     34   1.1  christos 
     35   1.1  christos   /* Order after here is important -- matches hardware MMR layout.  */
     36   1.1  christos   bu16 BFIN_MMR_16(ctl);
     37   1.1  christos   bu32 cnt, stat;
     38   1.1  christos };
     39   1.1  christos #define mmr_base()      offsetof(struct bfin_wdog, ctl)
     40   1.1  christos #define mmr_offset(mmr) (offsetof(struct bfin_wdog, mmr) - mmr_base())
     41   1.1  christos 
     42   1.1  christos static const char * const mmr_names[] =
     43   1.1  christos {
     44   1.1  christos   "WDOG_CTL", "WDOG_CNT", "WDOG_STAT",
     45   1.1  christos };
     46   1.1  christos #define mmr_name(off) mmr_names[(off) / 4]
     47   1.1  christos 
     48   1.1  christos static bool
     49   1.1  christos bfin_wdog_enabled (struct bfin_wdog *wdog)
     50   1.1  christos {
     51   1.1  christos   return ((wdog->ctl & WDEN) != WDDIS);
     52   1.1  christos }
     53   1.1  christos 
     54   1.1  christos static unsigned
     55   1.1  christos bfin_wdog_io_write_buffer (struct hw *me, const void *source,
     56   1.1  christos 			   int space, address_word addr, unsigned nr_bytes)
     57   1.1  christos {
     58   1.1  christos   struct bfin_wdog *wdog = hw_data (me);
     59   1.1  christos   bu32 mmr_off;
     60   1.1  christos   bu32 value;
     61   1.1  christos   bu16 *value16p;
     62   1.1  christos   bu32 *value32p;
     63   1.1  christos   void *valuep;
     64   1.1  christos 
     65   1.6  christos   /* Invalid access mode is higher priority than missing register.  */
     66   1.6  christos   if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, true))
     67   1.6  christos     return 0;
     68   1.6  christos 
     69   1.1  christos   if (nr_bytes == 4)
     70   1.1  christos     value = dv_load_4 (source);
     71   1.1  christos   else
     72   1.1  christos     value = dv_load_2 (source);
     73   1.1  christos 
     74   1.1  christos   mmr_off = addr - wdog->base;
     75  1.10  christos   valuep = (void *)((uintptr_t)wdog + mmr_base() + mmr_off);
     76   1.1  christos   value16p = valuep;
     77   1.1  christos   value32p = valuep;
     78   1.1  christos 
     79   1.1  christos   HW_TRACE_WRITE ();
     80   1.1  christos 
     81   1.1  christos   switch (mmr_off)
     82   1.1  christos     {
     83   1.1  christos     case mmr_offset(ctl):
     84   1.1  christos       dv_w1c_2_partial (value16p, value, WDRO);
     85   1.1  christos       /* XXX: Should enable an event here to handle timeouts.  */
     86   1.1  christos       break;
     87   1.1  christos 
     88   1.1  christos     case mmr_offset(cnt):
     89   1.1  christos       /* Writes are discarded when enabeld.  */
     90   1.1  christos       if (!bfin_wdog_enabled (wdog))
     91   1.1  christos 	{
     92   1.1  christos 	  *value32p = value;
     93   1.1  christos 	  /* Writes to CNT preloads the STAT.  */
     94   1.1  christos 	  wdog->stat = wdog->cnt;
     95   1.1  christos 	}
     96   1.1  christos       break;
     97   1.1  christos 
     98   1.1  christos     case mmr_offset(stat):
     99   1.1  christos       /* When enabled, writes to STAT reload the counter.  */
    100   1.1  christos       if (bfin_wdog_enabled (wdog))
    101   1.1  christos 	wdog->stat = wdog->cnt;
    102   1.1  christos       /* XXX: When disabled, are writes just ignored ?  */
    103   1.1  christos       break;
    104   1.1  christos     }
    105   1.1  christos 
    106   1.1  christos   return nr_bytes;
    107   1.1  christos }
    108   1.1  christos 
    109   1.1  christos static unsigned
    110   1.1  christos bfin_wdog_io_read_buffer (struct hw *me, void *dest,
    111   1.1  christos 			  int space, address_word addr, unsigned nr_bytes)
    112   1.1  christos {
    113   1.1  christos   struct bfin_wdog *wdog = hw_data (me);
    114   1.1  christos   bu32 mmr_off;
    115   1.1  christos   bu16 *value16p;
    116   1.1  christos   bu32 *value32p;
    117   1.1  christos   void *valuep;
    118   1.1  christos 
    119   1.6  christos   /* Invalid access mode is higher priority than missing register.  */
    120   1.6  christos   if (!dv_bfin_mmr_require_16_32 (me, addr, nr_bytes, false))
    121   1.6  christos     return 0;
    122   1.6  christos 
    123   1.1  christos   mmr_off = addr - wdog->base;
    124  1.10  christos   valuep = (void *)((uintptr_t)wdog + mmr_base() + mmr_off);
    125   1.1  christos   value16p = valuep;
    126   1.1  christos   value32p = valuep;
    127   1.1  christos 
    128   1.1  christos   HW_TRACE_READ ();
    129   1.1  christos 
    130   1.1  christos   switch (mmr_off)
    131   1.1  christos     {
    132   1.1  christos     case mmr_offset(ctl):
    133   1.6  christos       if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, false))
    134   1.6  christos 	return 0;
    135   1.1  christos       dv_store_2 (dest, *value16p);
    136   1.1  christos       break;
    137   1.1  christos 
    138   1.1  christos     case mmr_offset(cnt):
    139   1.1  christos     case mmr_offset(stat):
    140   1.1  christos       dv_store_4 (dest, *value32p);
    141   1.1  christos       break;
    142   1.1  christos     }
    143   1.1  christos 
    144   1.1  christos   return nr_bytes;
    145   1.1  christos }
    146   1.1  christos 
    147   1.1  christos static const struct hw_port_descriptor bfin_wdog_ports[] =
    148   1.1  christos {
    149   1.1  christos   { "reset", WDEV_RESET, 0, output_port, },
    150   1.1  christos   { "nmi",   WDEV_NMI,   0, output_port, },
    151   1.1  christos   { "gpi",   WDEV_GPI,   0, output_port, },
    152   1.1  christos   { NULL, 0, 0, 0, },
    153   1.1  christos };
    154   1.1  christos 
    155   1.1  christos static void
    156   1.1  christos bfin_wdog_port_event (struct hw *me, int my_port, struct hw *source,
    157   1.1  christos 		      int source_port, int level)
    158   1.1  christos {
    159   1.1  christos   struct bfin_wdog *wdog = hw_data (me);
    160   1.1  christos   bu16 wdev;
    161   1.1  christos 
    162   1.1  christos   wdog->ctl |= WDRO;
    163   1.1  christos   wdev = (wdog->ctl & WDEV);
    164   1.1  christos   if (wdev != WDEV_NONE)
    165   1.1  christos     hw_port_event (me, wdev, 1);
    166   1.1  christos }
    167   1.1  christos 
    168   1.1  christos static void
    169   1.1  christos attach_bfin_wdog_regs (struct hw *me, struct bfin_wdog *wdog)
    170   1.1  christos {
    171   1.1  christos   address_word attach_address;
    172   1.1  christos   int attach_space;
    173   1.1  christos   unsigned attach_size;
    174   1.1  christos   reg_property_spec reg;
    175   1.1  christos 
    176   1.1  christos   if (hw_find_property (me, "reg") == NULL)
    177   1.1  christos     hw_abort (me, "Missing \"reg\" property");
    178   1.1  christos 
    179   1.1  christos   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
    180   1.1  christos     hw_abort (me, "\"reg\" property must contain three addr/size entries");
    181   1.1  christos 
    182   1.1  christos   hw_unit_address_to_attach_address (hw_parent (me),
    183   1.1  christos 				     &reg.address,
    184   1.1  christos 				     &attach_space, &attach_address, me);
    185   1.1  christos   hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
    186   1.1  christos 
    187   1.1  christos   if (attach_size != BFIN_MMR_WDOG_SIZE)
    188   1.1  christos     hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_WDOG_SIZE);
    189   1.1  christos 
    190   1.1  christos   hw_attach_address (hw_parent (me),
    191   1.1  christos 		     0, attach_space, attach_address, attach_size, me);
    192   1.1  christos 
    193   1.1  christos   wdog->base = attach_address;
    194   1.1  christos }
    195   1.1  christos 
    196   1.1  christos static void
    197   1.1  christos bfin_wdog_finish (struct hw *me)
    198   1.1  christos {
    199   1.1  christos   struct bfin_wdog *wdog;
    200   1.1  christos 
    201   1.1  christos   wdog = HW_ZALLOC (me, struct bfin_wdog);
    202   1.1  christos 
    203   1.1  christos   set_hw_data (me, wdog);
    204   1.1  christos   set_hw_io_read_buffer (me, bfin_wdog_io_read_buffer);
    205   1.1  christos   set_hw_io_write_buffer (me, bfin_wdog_io_write_buffer);
    206   1.1  christos   set_hw_ports (me, bfin_wdog_ports);
    207   1.1  christos   set_hw_port_event (me, bfin_wdog_port_event);
    208   1.1  christos 
    209   1.1  christos   attach_bfin_wdog_regs (me, wdog);
    210   1.1  christos 
    211   1.1  christos   /* Initialize the Watchdog.  */
    212   1.1  christos   wdog->ctl = WDDIS;
    213   1.1  christos }
    214   1.1  christos 
    215   1.1  christos const struct hw_descriptor dv_bfin_wdog_descriptor[] =
    216   1.1  christos {
    217   1.1  christos   {"bfin_wdog", bfin_wdog_finish,},
    218   1.1  christos   {NULL, NULL},
    219   1.1  christos };
    220