Home | History | Annotate | Line # | Download | only in bfin
dv-bfin_pfmon.c revision 1.1.1.4
      1 /* Blackfin Performance Monitor model.
      2 
      3    Copyright (C) 2010-2016 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 #include "config.h"
     22 
     23 #include "sim-main.h"
     24 #include "devices.h"
     25 #include "dv-bfin_pfmon.h"
     26 
     27 /* XXX: This is mostly a stub.  */
     28 
     29 struct bfin_pfmon
     30 {
     31   bu32 base;
     32 
     33   /* Order after here is important -- matches hardware MMR layout.  */
     34   bu32 ctl;
     35   bu32 _pad0[63];
     36   bu32 cntr0, cntr1;
     37 };
     38 #define mmr_base()      offsetof(struct bfin_pfmon, ctl)
     39 #define mmr_offset(mmr) (offsetof(struct bfin_pfmon, mmr) - mmr_base())
     40 
     41 static const char * const mmr_names[] =
     42 {
     43   "PFCTL", [mmr_offset (cntr0)] = "PFCNTR0", "PFCNTR1",
     44 };
     45 #define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
     46 
     47 static unsigned
     48 bfin_pfmon_io_write_buffer (struct hw *me, const void *source, int space,
     49 			    address_word addr, unsigned nr_bytes)
     50 {
     51   struct bfin_pfmon *pfmon = hw_data (me);
     52   bu32 mmr_off;
     53   bu32 value;
     54   bu32 *valuep;
     55 
     56   /* Invalid access mode is higher priority than missing register.  */
     57   if (!dv_bfin_mmr_require_32 (me, addr, nr_bytes, true))
     58     return 0;
     59 
     60   value = dv_load_4 (source);
     61   mmr_off = addr - pfmon->base;
     62   valuep = (void *)((unsigned long)pfmon + mmr_base() + mmr_off);
     63 
     64   HW_TRACE_WRITE ();
     65 
     66   switch (mmr_off)
     67     {
     68     case mmr_offset(ctl):
     69     case mmr_offset(cntr0):
     70     case mmr_offset(cntr1):
     71       *valuep = value;
     72       break;
     73     default:
     74       dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
     75       return 0;
     76     }
     77 
     78   return nr_bytes;
     79 }
     80 
     81 static unsigned
     82 bfin_pfmon_io_read_buffer (struct hw *me, void *dest, int space,
     83 			   address_word addr, unsigned nr_bytes)
     84 {
     85   struct bfin_pfmon *pfmon = hw_data (me);
     86   bu32 mmr_off;
     87   bu32 value;
     88   bu32 *valuep;
     89 
     90   /* Invalid access mode is higher priority than missing register.  */
     91   if (!dv_bfin_mmr_require_32 (me, addr, nr_bytes, false))
     92     return 0;
     93 
     94   mmr_off = addr - pfmon->base;
     95   valuep = (void *)((unsigned long)pfmon + mmr_base() + mmr_off);
     96 
     97   HW_TRACE_READ ();
     98 
     99   switch (mmr_off)
    100     {
    101     case mmr_offset(ctl):
    102     case mmr_offset(cntr0):
    103     case mmr_offset(cntr1):
    104       value = *valuep;
    105       break;
    106     default:
    107       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
    108       return 0;
    109     }
    110 
    111   dv_store_4 (dest, value);
    112 
    113   return nr_bytes;
    114 }
    115 
    116 static void
    117 attach_bfin_pfmon_regs (struct hw *me, struct bfin_pfmon *pfmon)
    118 {
    119   address_word attach_address;
    120   int attach_space;
    121   unsigned attach_size;
    122   reg_property_spec reg;
    123 
    124   if (hw_find_property (me, "reg") == NULL)
    125     hw_abort (me, "Missing \"reg\" property");
    126 
    127   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
    128     hw_abort (me, "\"reg\" property must contain three addr/size entries");
    129 
    130   hw_unit_address_to_attach_address (hw_parent (me),
    131 				     &reg.address,
    132 				     &attach_space, &attach_address, me);
    133   hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
    134 
    135   if (attach_size != BFIN_COREMMR_PFMON_SIZE)
    136     hw_abort (me, "\"reg\" size must be %#x", BFIN_COREMMR_PFMON_SIZE);
    137 
    138   hw_attach_address (hw_parent (me),
    139 		     0, attach_space, attach_address, attach_size, me);
    140 
    141   pfmon->base = attach_address;
    142 }
    143 
    144 static void
    145 bfin_pfmon_finish (struct hw *me)
    146 {
    147   struct bfin_pfmon *pfmon;
    148 
    149   pfmon = HW_ZALLOC (me, struct bfin_pfmon);
    150 
    151   set_hw_data (me, pfmon);
    152   set_hw_io_read_buffer (me, bfin_pfmon_io_read_buffer);
    153   set_hw_io_write_buffer (me, bfin_pfmon_io_write_buffer);
    154 
    155   attach_bfin_pfmon_regs (me, pfmon);
    156 }
    157 
    158 const struct hw_descriptor dv_bfin_pfmon_descriptor[] =
    159 {
    160   {"bfin_pfmon", bfin_pfmon_finish,},
    161   {NULL, NULL},
    162 };
    163