Home | History | Annotate | Line # | Download | only in mn10300
dv-mn103tim.c revision 1.10
      1   1.1  christos /*  This file is part of the program GDB, the GNU debugger.
      2   1.1  christos 
      3  1.10  christos     Copyright (C) 1998-2023 Free Software Foundation, Inc.
      4   1.1  christos     Contributed by Cygnus Solutions.
      5   1.1  christos 
      6   1.1  christos     This program is free software; you can redistribute it and/or modify
      7   1.1  christos     it under the terms of the GNU General Public License as published by
      8   1.1  christos     the Free Software Foundation; either version 3 of the License, or
      9   1.1  christos     (at your option) any later version.
     10   1.1  christos 
     11   1.1  christos     This program is distributed in the hope that it will be useful,
     12   1.1  christos     but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   1.1  christos     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14   1.1  christos     GNU General Public License for more details.
     15   1.1  christos 
     16   1.1  christos     You should have received a copy of the GNU General Public License
     17   1.1  christos     along with this program.  If not, see <http://www.gnu.org/licenses/>.
     18   1.1  christos 
     19   1.1  christos     */
     20   1.1  christos 
     21  1.10  christos /* This must come before any other includes.  */
     22  1.10  christos #include "defs.h"
     23  1.10  christos 
     24   1.1  christos #include "sim-main.h"
     25   1.1  christos #include "hw-main.h"
     26   1.1  christos #include "sim-assert.h"
     27   1.1  christos 
     28   1.1  christos /* DEVICE
     29   1.1  christos 
     30   1.1  christos 
     31   1.1  christos    mn103tim - mn103002 timers (8 and 16 bit)
     32   1.1  christos 
     33   1.1  christos 
     34   1.1  christos    DESCRIPTION
     35   1.1  christos 
     36   1.1  christos    Implements the mn103002 8 and 16 bit timers as described in the mn103002 user guide.
     37   1.1  christos 
     38   1.1  christos 
     39   1.1  christos    PROPERTIES
     40   1.1  christos 
     41   1.1  christos    reg = <8bit-timers-addr> <8bit-timers-size> <16bit-timers-addr> <16bit-timers-size>
     42   1.1  christos 
     43   1.1  christos 
     44   1.1  christos    BUGS
     45   1.1  christos 
     46   1.1  christos    */
     47   1.1  christos 
     48   1.1  christos 
     49   1.1  christos /* The timers' register address blocks */
     50   1.1  christos 
     51   1.1  christos struct mn103tim_block {
     52   1.1  christos   unsigned_word base;
     53   1.1  christos   unsigned_word bound;
     54   1.1  christos };
     55   1.1  christos 
     56   1.1  christos enum { TIMER8_BLOCK, TIMER16_BLOCK, NR_TIMER_BLOCKS };
     57   1.1  christos 
     58   1.1  christos enum timer_register_types {
     59   1.1  christos   FIRST_MODE_REG = 0,
     60   1.1  christos   TM0MD = FIRST_MODE_REG,
     61   1.1  christos   TM1MD,
     62   1.1  christos   TM2MD,
     63   1.1  christos   TM3MD,
     64   1.1  christos   TM4MD,
     65   1.1  christos   TM5MD,
     66   1.1  christos   TM6MD,
     67   1.1  christos   LAST_MODE_REG = TM6MD,
     68   1.1  christos   FIRST_BASE_REG,
     69   1.1  christos   TM0BR = FIRST_BASE_REG,
     70   1.1  christos   TM1BR,
     71   1.1  christos   TM2BR,
     72   1.1  christos   TM3BR,
     73   1.1  christos   TM4BR,
     74   1.1  christos   TM5BR,
     75   1.1  christos   LAST_BASE_REG = TM5BR,
     76   1.1  christos   FIRST_COUNTER,
     77   1.1  christos   TM0BC = FIRST_COUNTER,
     78   1.1  christos   TM1BC,
     79   1.1  christos   TM2BC,
     80   1.1  christos   TM3BC,
     81   1.1  christos   TM4BC,
     82   1.1  christos   TM5BC,
     83   1.1  christos   TM6BC,
     84   1.1  christos   LAST_COUNTER = TM6BC,
     85   1.1  christos   TM6MDA,
     86   1.1  christos   TM6MDB,
     87   1.1  christos   TM6CA,
     88   1.1  christos   TM6CB,
     89   1.1  christos   LAST_TIMER_REG = TM6BC,
     90   1.1  christos };
     91   1.1  christos 
     92   1.1  christos 
     93   1.1  christos /* Don't include timer 6 because it's handled specially. */
     94   1.1  christos #define NR_8BIT_TIMERS 4
     95   1.1  christos #define NR_16BIT_TIMERS 2
     96   1.1  christos #define NR_REG_TIMERS 6 /* Exclude timer 6 - it's handled specially. */
     97   1.1  christos #define NR_TIMERS 7
     98   1.1  christos 
     99   1.1  christos typedef struct _mn10300_timer_regs {
    100  1.10  christos   uint32_t base;
    101  1.10  christos   uint8_t  mode;
    102   1.1  christos } mn10300_timer_regs;
    103   1.1  christos 
    104   1.1  christos typedef struct _mn10300_timer {
    105  1.10  christos   uint32_t div_ratio, start;
    106   1.1  christos   struct hw_event *event;
    107   1.1  christos } mn10300_timer;
    108   1.1  christos 
    109   1.1  christos 
    110   1.1  christos struct mn103tim {
    111   1.1  christos   struct mn103tim_block block[NR_TIMER_BLOCKS];
    112   1.1  christos   mn10300_timer_regs reg[NR_REG_TIMERS];
    113   1.1  christos   mn10300_timer timer[NR_TIMERS];
    114   1.1  christos 
    115   1.1  christos   /* treat timer 6 registers specially. */
    116  1.10  christos   uint16_t   tm6md0, tm6md1, tm6bc, tm6ca, tm6cb;
    117  1.10  christos   uint8_t  tm6mda, tm6mdb;  /* compare/capture mode regs for timer 6 */
    118   1.1  christos };
    119   1.1  christos 
    120   1.1  christos /* output port ID's */
    121   1.1  christos 
    122   1.1  christos /* for mn103002 */
    123   1.1  christos enum {
    124   1.1  christos   TIMER0_UFLOW,
    125   1.1  christos   TIMER1_UFLOW,
    126   1.1  christos   TIMER2_UFLOW,
    127   1.1  christos   TIMER3_UFLOW,
    128   1.1  christos   TIMER4_UFLOW,
    129   1.1  christos   TIMER5_UFLOW,
    130   1.1  christos   TIMER6_UFLOW,
    131   1.1  christos   TIMER6_CMPA,
    132   1.1  christos   TIMER6_CMPB,
    133   1.1  christos };
    134   1.1  christos 
    135   1.1  christos 
    136   1.1  christos static const struct hw_port_descriptor mn103tim_ports[] = {
    137   1.1  christos 
    138   1.1  christos   { "timer-0-underflow", TIMER0_UFLOW, 0, output_port, },
    139   1.1  christos   { "timer-1-underflow", TIMER1_UFLOW, 0, output_port, },
    140   1.1  christos   { "timer-2-underflow", TIMER2_UFLOW, 0, output_port, },
    141   1.1  christos   { "timer-3-underflow", TIMER3_UFLOW, 0, output_port, },
    142   1.1  christos   { "timer-4-underflow", TIMER4_UFLOW, 0, output_port, },
    143   1.1  christos   { "timer-5-underflow", TIMER5_UFLOW, 0, output_port, },
    144   1.1  christos 
    145   1.1  christos   { "timer-6-underflow", TIMER6_UFLOW, 0, output_port, },
    146   1.1  christos   { "timer-6-compare-a", TIMER6_CMPA, 0, output_port, },
    147   1.1  christos   { "timer-6-compare-b", TIMER6_CMPB, 0, output_port, },
    148   1.1  christos 
    149   1.1  christos   { NULL, },
    150   1.1  christos };
    151   1.1  christos 
    152   1.1  christos #define bits2to5_mask 0x3c
    153   1.1  christos #define bits0to2_mask 0x07
    154   1.1  christos #define load_mask     0x40
    155   1.1  christos #define count_mask    0x80
    156   1.1  christos #define count_and_load_mask (load_mask | count_mask)
    157   1.1  christos #define clock_mask    0x03
    158   1.1  christos #define clk_ioclk    0x00
    159   1.1  christos #define clk_cascaded 0x03
    160   1.1  christos 
    161   1.1  christos 
    162   1.1  christos /* Finish off the partially created hw device.  Attach our local
    163   1.1  christos    callbacks.  Wire up our port names etc */
    164   1.1  christos 
    165   1.1  christos static hw_io_read_buffer_method mn103tim_io_read_buffer;
    166   1.1  christos static hw_io_write_buffer_method mn103tim_io_write_buffer;
    167   1.1  christos 
    168   1.1  christos static void
    169   1.1  christos attach_mn103tim_regs (struct hw *me,
    170   1.1  christos 		      struct mn103tim *timers)
    171   1.1  christos {
    172   1.1  christos   int i;
    173   1.1  christos   if (hw_find_property (me, "reg") == NULL)
    174   1.1  christos     hw_abort (me, "Missing \"reg\" property");
    175   1.1  christos   for (i = 0; i < NR_TIMER_BLOCKS; i++)
    176   1.1  christos     {
    177   1.1  christos       unsigned_word attach_address;
    178   1.1  christos       int attach_space;
    179   1.1  christos       unsigned attach_size;
    180   1.1  christos       reg_property_spec reg;
    181   1.1  christos       if (!hw_find_reg_array_property (me, "reg", i, &reg))
    182   1.1  christos 	hw_abort (me, "\"reg\" property must contain three addr/size entries");
    183   1.1  christos       hw_unit_address_to_attach_address (hw_parent (me),
    184   1.1  christos 					 &reg.address,
    185   1.1  christos 					 &attach_space,
    186   1.1  christos 					 &attach_address,
    187   1.1  christos 					 me);
    188   1.1  christos       timers->block[i].base = attach_address;
    189   1.1  christos       hw_unit_size_to_attach_size (hw_parent (me),
    190   1.1  christos 				   &reg.size,
    191   1.1  christos 				   &attach_size, me);
    192   1.1  christos       timers->block[i].bound = attach_address + (attach_size - 1);
    193   1.1  christos       hw_attach_address (hw_parent (me),
    194   1.1  christos 			 0,
    195   1.1  christos 			 attach_space, attach_address, attach_size,
    196   1.1  christos 			 me);
    197   1.1  christos     }
    198   1.1  christos }
    199   1.1  christos 
    200   1.1  christos static void
    201   1.1  christos mn103tim_finish (struct hw *me)
    202   1.1  christos {
    203   1.1  christos   struct mn103tim *timers;
    204   1.1  christos   int i;
    205   1.1  christos 
    206   1.1  christos   timers = HW_ZALLOC (me, struct mn103tim);
    207   1.1  christos   set_hw_data (me, timers);
    208   1.1  christos   set_hw_io_read_buffer (me, mn103tim_io_read_buffer);
    209   1.1  christos   set_hw_io_write_buffer (me, mn103tim_io_write_buffer);
    210   1.1  christos   set_hw_ports (me, mn103tim_ports);
    211   1.1  christos 
    212   1.1  christos   /* Attach ourself to our parent bus */
    213   1.1  christos   attach_mn103tim_regs (me, timers);
    214   1.1  christos 
    215   1.1  christos   /* Initialize the timers */
    216   1.1  christos   for ( i=0; i < NR_REG_TIMERS; ++i )
    217   1.1  christos     {
    218   1.1  christos       timers->reg[i].mode = 0x00;
    219   1.1  christos       timers->reg[i].base = 0;
    220   1.1  christos     }
    221   1.1  christos   for ( i=0; i < NR_TIMERS; ++i )
    222   1.1  christos     {
    223   1.1  christos       timers->timer[i].event = NULL;
    224   1.1  christos       timers->timer[i].div_ratio = 0;
    225   1.1  christos       timers->timer[i].start = 0;
    226   1.1  christos     }
    227   1.1  christos   timers->tm6md0 = 0x00;
    228   1.1  christos   timers->tm6md1 = 0x00;
    229   1.1  christos   timers->tm6bc = 0x0000;
    230   1.1  christos   timers->tm6ca = 0x0000;
    231   1.1  christos   timers->tm6cb = 0x0000;
    232   1.1  christos   timers->tm6mda = 0x00;
    233   1.1  christos   timers->tm6mdb = 0x00;
    234   1.1  christos }
    235   1.1  christos 
    236   1.1  christos 
    237   1.1  christos 
    238   1.1  christos /* read and write */
    239   1.1  christos 
    240   1.1  christos static int
    241   1.1  christos decode_addr (struct hw *me,
    242   1.1  christos 	     struct mn103tim *timers,
    243   1.1  christos 	     unsigned_word address)
    244   1.1  christos {
    245   1.1  christos   unsigned_word offset;
    246   1.1  christos   offset = address - timers->block[0].base;
    247   1.1  christos 
    248   1.1  christos   switch (offset)
    249   1.1  christos     {
    250   1.1  christos     case 0x00: return TM0MD;
    251   1.1  christos     case 0x01: return TM1MD;
    252   1.1  christos     case 0x02: return TM2MD;
    253   1.1  christos     case 0x03: return TM3MD;
    254   1.1  christos     case 0x10: return TM0BR;
    255   1.1  christos     case 0x11: return TM1BR;
    256   1.1  christos     case 0x12: return TM2BR;
    257   1.1  christos     case 0x13: return TM3BR;
    258   1.1  christos     case 0x20: return TM0BC;
    259   1.1  christos     case 0x21: return TM1BC;
    260   1.1  christos     case 0x22: return TM2BC;
    261   1.1  christos     case 0x23: return TM3BC;
    262   1.1  christos     case 0x80: return TM4MD;
    263   1.1  christos     case 0x82: return TM5MD;
    264   1.1  christos     case 0x84: /* fall through */
    265   1.1  christos     case 0x85: return TM6MD;
    266   1.1  christos     case 0x90: return TM4BR;
    267   1.1  christos     case 0x92: return TM5BR;
    268   1.1  christos     case 0xa0: return TM4BC;
    269   1.1  christos     case 0xa2: return TM5BC;
    270   1.1  christos     case 0xa4: return TM6BC;
    271   1.1  christos     case 0xb4: return TM6MDA;
    272   1.1  christos     case 0xb5: return TM6MDB;
    273   1.1  christos     case 0xc4: return TM6CA;
    274   1.1  christos     case 0xd4: return TM6CB;
    275   1.1  christos     default:
    276   1.1  christos       {
    277   1.1  christos 	hw_abort (me, "bad address");
    278   1.1  christos 	return -1;
    279   1.1  christos       }
    280   1.1  christos     }
    281   1.1  christos }
    282   1.1  christos 
    283   1.1  christos static void
    284   1.1  christos read_mode_reg (struct hw *me,
    285   1.1  christos 	       struct mn103tim *timers,
    286   1.1  christos 	       int timer_nr,
    287   1.1  christos 	       void *dest,
    288   1.1  christos 	       unsigned nr_bytes)
    289   1.1  christos {
    290  1.10  christos   uint16_t val16;
    291  1.10  christos   uint32_t val32;
    292   1.1  christos 
    293   1.1  christos   switch ( nr_bytes )
    294   1.1  christos     {
    295   1.1  christos     case 1:
    296   1.1  christos       /* Accessing 1 byte is ok for all mode registers. */
    297   1.1  christos       if ( timer_nr == 6 )
    298   1.1  christos 	{
    299  1.10  christos 	  *(uint8_t*)dest = timers->tm6md0;
    300   1.1  christos 	}
    301   1.1  christos       else
    302   1.1  christos 	{
    303  1.10  christos 	  *(uint8_t*)dest = timers->reg[timer_nr].mode;
    304   1.1  christos 	}
    305   1.1  christos       break;
    306   1.1  christos 
    307   1.1  christos     case 2:
    308   1.1  christos       if ( timer_nr == 6 )
    309   1.1  christos 	{
    310  1.10  christos 	  *(uint16_t *)dest = (timers->tm6md0 << 8) | timers->tm6md1;
    311   1.1  christos 	}
    312   1.1  christos       else if ( timer_nr == 0 || timer_nr == 2 )
    313   1.1  christos 	{
    314   1.1  christos 	  val16 = (timers->reg[timer_nr].mode << 8)
    315   1.1  christos 	    | timers->reg[timer_nr+1].mode;
    316  1.10  christos 	  *(uint16_t*)dest = val16;
    317   1.1  christos 	}
    318   1.1  christos       else
    319   1.1  christos 	{
    320   1.1  christos 	  hw_abort (me, "bad read size of 2 bytes to TM%dMD.", timer_nr);
    321   1.1  christos 	}
    322   1.1  christos       break;
    323   1.1  christos 
    324   1.1  christos     case 4:
    325   1.1  christos       if ( timer_nr == 0 )
    326   1.1  christos 	{
    327   1.1  christos 	  val32 = (timers->reg[0].mode << 24 )
    328   1.1  christos 	    | (timers->reg[1].mode << 16)
    329   1.1  christos 	    | (timers->reg[2].mode << 8)
    330   1.1  christos 	    | timers->reg[3].mode;
    331  1.10  christos 	  *(uint32_t*)dest = val32;
    332   1.1  christos 	}
    333   1.1  christos       else
    334   1.1  christos 	{
    335   1.1  christos 	  hw_abort (me, "bad read size of 4 bytes to TM%dMD.", timer_nr);
    336   1.1  christos 	}
    337   1.1  christos       break;
    338   1.1  christos 
    339   1.1  christos     default:
    340   1.1  christos       hw_abort (me, "bad read size of %d bytes to TM%dMD.",
    341   1.1  christos 		nr_bytes, timer_nr);
    342   1.1  christos     }
    343   1.1  christos }
    344   1.1  christos 
    345   1.1  christos 
    346   1.1  christos static void
    347   1.1  christos read_base_reg (struct hw *me,
    348   1.1  christos 	       struct mn103tim *timers,
    349   1.1  christos 	       int timer_nr,
    350   1.1  christos 	       void *dest,
    351   1.1  christos 	       unsigned  nr_bytes)
    352   1.1  christos {
    353  1.10  christos   uint16_t val16;
    354  1.10  christos   uint32_t val32;
    355   1.1  christos 
    356   1.1  christos   /* Check nr_bytes: accesses of 1, 2 and 4 bytes allowed depending on timer. */
    357   1.1  christos   switch ( nr_bytes )
    358   1.1  christos     {
    359   1.1  christos     case 1:
    360   1.1  christos       /* Reading 1 byte is ok for all registers. */
    361   1.1  christos       if ( timer_nr < NR_8BIT_TIMERS )
    362   1.1  christos 	{
    363  1.10  christos 	  *(uint8_t*)dest = timers->reg[timer_nr].base;
    364   1.1  christos 	}
    365   1.1  christos       break;
    366   1.1  christos 
    367   1.1  christos     case 2:
    368   1.1  christos       if ( timer_nr == 1 || timer_nr == 3 )
    369   1.1  christos 	{
    370   1.1  christos 	  hw_abort (me, "bad read size of 2 bytes to TM%dBR.", timer_nr);
    371   1.1  christos 	}
    372   1.1  christos       else
    373   1.1  christos 	{
    374   1.1  christos 	  if ( timer_nr < NR_8BIT_TIMERS )
    375   1.1  christos 	    {
    376   1.1  christos 	      val16 = (timers->reg[timer_nr].base<<8)
    377   1.1  christos 		| timers->reg[timer_nr+1].base;
    378   1.1  christos 	    }
    379   1.1  christos 	  else
    380   1.1  christos 	    {
    381   1.1  christos 	      val16 = timers->reg[timer_nr].base;
    382   1.1  christos 	    }
    383  1.10  christos 	  *(uint16_t*)dest = val16;
    384   1.1  christos 	}
    385   1.1  christos       break;
    386   1.1  christos 
    387   1.1  christos     case 4:
    388   1.1  christos       if ( timer_nr == 0 )
    389   1.1  christos 	{
    390   1.1  christos 	  val32 = (timers->reg[0].base << 24) | (timers->reg[1].base << 16)
    391   1.1  christos 	    | (timers->reg[2].base << 8) | timers->reg[3].base;
    392  1.10  christos 	  *(uint32_t*)dest = val32;
    393   1.1  christos 	}
    394   1.1  christos       else if ( timer_nr == 4 )
    395   1.1  christos 	{
    396   1.1  christos 	  val32 = (timers->reg[4].base << 16) | timers->reg[5].base;
    397  1.10  christos 	  *(uint32_t*)dest = val32;
    398   1.1  christos 	}
    399   1.1  christos       else
    400   1.1  christos 	{
    401   1.1  christos 	  hw_abort (me, "bad read size of 4 bytes to TM%dBR.", timer_nr);
    402   1.1  christos 	}
    403   1.1  christos       break;
    404   1.1  christos 
    405   1.1  christos     default:
    406   1.1  christos       hw_abort (me, "bad read size must of %d bytes to TM%dBR.",
    407   1.1  christos 		nr_bytes, timer_nr);
    408   1.1  christos     }
    409   1.1  christos }
    410   1.1  christos 
    411   1.1  christos 
    412   1.1  christos static void
    413   1.1  christos read_counter (struct hw *me,
    414   1.1  christos 	      struct mn103tim *timers,
    415   1.1  christos 	      int timer_nr,
    416   1.1  christos 	      void *dest,
    417   1.1  christos 	      unsigned  nr_bytes)
    418   1.1  christos {
    419  1.10  christos   uint32_t val;
    420   1.1  christos 
    421   1.1  christos   if ( NULL == timers->timer[timer_nr].event )
    422   1.1  christos     {
    423   1.1  christos       /* Timer is not counting, use value in base register. */
    424   1.1  christos       if ( timer_nr == 6 )
    425   1.1  christos 	{
    426   1.1  christos 	  val = 0;  /* timer 6 is an up counter */
    427   1.1  christos 	}
    428   1.1  christos       else
    429   1.1  christos 	{
    430   1.1  christos 	  val = timers->reg[timer_nr].base;
    431   1.1  christos 	}
    432   1.1  christos     }
    433   1.1  christos   else
    434   1.1  christos     {
    435   1.1  christos       if ( timer_nr == 6 )  /* timer 6 is an up counter. */
    436   1.1  christos 	{
    437   1.1  christos 	  val = hw_event_queue_time(me) - timers->timer[timer_nr].start;
    438   1.1  christos 	}
    439   1.1  christos       else
    440   1.1  christos 	{
    441   1.1  christos 	  /* ticks left = start time + div ratio - curr time */
    442   1.1  christos 	  /* Cannot use base register because it can be written during counting and it
    443   1.1  christos 	     doesn't affect counter until underflow occurs. */
    444   1.1  christos 
    445   1.1  christos 	  val = timers->timer[timer_nr].start + timers->timer[timer_nr].div_ratio
    446   1.1  christos 	    - hw_event_queue_time(me);
    447   1.1  christos 	}
    448   1.1  christos     }
    449   1.1  christos 
    450   1.1  christos   switch (nr_bytes) {
    451   1.1  christos   case 1:
    452  1.10  christos     *(uint8_t *)dest = val;
    453   1.1  christos     break;
    454   1.1  christos 
    455   1.1  christos   case 2:
    456  1.10  christos     *(uint16_t *)dest = val;
    457   1.1  christos     break;
    458   1.1  christos 
    459   1.1  christos   case 4:
    460  1.10  christos     *(uint32_t *)dest = val;
    461   1.1  christos     break;
    462   1.1  christos 
    463   1.1  christos   default:
    464   1.1  christos     hw_abort(me, "bad read size for reading counter");
    465   1.1  christos   }
    466   1.1  christos 
    467   1.1  christos }
    468   1.1  christos 
    469   1.1  christos 
    470   1.1  christos static void
    471   1.1  christos read_special_timer6_reg (struct hw *me,
    472   1.1  christos 			 struct mn103tim *timers,
    473   1.1  christos 			 int timer_nr,
    474   1.1  christos 			 void *dest,
    475   1.1  christos 			 unsigned  nr_bytes)
    476   1.1  christos {
    477  1.10  christos   uint32_t val;
    478   1.1  christos 
    479   1.1  christos   switch (nr_bytes) {
    480   1.1  christos   case 1:
    481   1.1  christos     {
    482   1.1  christos       switch ( timer_nr ) {
    483   1.1  christos       case TM6MDA:
    484  1.10  christos 	*(uint8_t *)dest = timers->tm6mda;
    485   1.1  christos 	break;
    486   1.1  christos 
    487   1.1  christos       case TM6MDB:
    488  1.10  christos 	*(uint8_t *)dest = timers->tm6mdb;
    489   1.1  christos 	break;
    490   1.1  christos 
    491   1.1  christos       case TM6CA:
    492  1.10  christos 	*(uint8_t *)dest = timers->tm6ca;
    493   1.1  christos 	break;
    494   1.1  christos 
    495   1.1  christos       case TM6CB:
    496  1.10  christos 	*(uint8_t *)dest = timers->tm6cb;
    497   1.1  christos 	break;
    498   1.1  christos 
    499   1.1  christos       default:
    500   1.1  christos 	break;
    501   1.1  christos       }
    502   1.1  christos       break;
    503   1.1  christos     }
    504   1.1  christos 
    505   1.1  christos   case 2:
    506   1.1  christos     if ( timer_nr == TM6CA )
    507   1.1  christos       {
    508  1.10  christos 	*(uint16_t *)dest = timers->tm6ca;
    509   1.1  christos       }
    510   1.1  christos     else if ( timer_nr == TM6CB )
    511   1.1  christos       {
    512  1.10  christos 	*(uint16_t *)dest = timers->tm6cb;
    513   1.1  christos       }
    514   1.1  christos     else
    515   1.1  christos       {
    516   1.1  christos 	hw_abort(me, "bad read size for timer 6 mode A/B register");
    517   1.1  christos       }
    518   1.1  christos     break;
    519   1.1  christos 
    520   1.1  christos   default:
    521   1.1  christos     hw_abort(me, "bad read size for timer 6 register");
    522   1.1  christos   }
    523   1.1  christos 
    524   1.1  christos }
    525   1.1  christos 
    526   1.1  christos 
    527   1.1  christos static unsigned
    528   1.1  christos mn103tim_io_read_buffer (struct hw *me,
    529   1.1  christos 			 void *dest,
    530   1.1  christos 			 int space,
    531   1.1  christos 			 unsigned_word base,
    532   1.1  christos 			 unsigned nr_bytes)
    533   1.1  christos {
    534   1.1  christos   struct mn103tim *timers = hw_data (me);
    535   1.1  christos   enum timer_register_types timer_reg;
    536   1.1  christos 
    537   1.1  christos   HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
    538   1.1  christos 
    539   1.1  christos   timer_reg = decode_addr (me, timers, base);
    540   1.1  christos 
    541   1.1  christos   /* It can be either a mode register, a base register, a binary counter, */
    542   1.1  christos   /* or a special timer 6 register.  Check in that order. */
    543   1.1  christos   if ( timer_reg >= FIRST_MODE_REG && timer_reg <= LAST_MODE_REG )
    544   1.1  christos     {
    545   1.1  christos       read_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, dest, nr_bytes);
    546   1.1  christos     }
    547   1.1  christos   else if ( timer_reg <= LAST_BASE_REG )
    548   1.1  christos     {
    549   1.1  christos       read_base_reg(me, timers, timer_reg-FIRST_BASE_REG, dest, nr_bytes);
    550   1.1  christos     }
    551   1.1  christos   else if ( timer_reg <= LAST_COUNTER )
    552   1.1  christos     {
    553   1.1  christos       read_counter(me, timers, timer_reg-FIRST_COUNTER, dest, nr_bytes);
    554   1.1  christos     }
    555   1.1  christos   else if ( timer_reg <= LAST_TIMER_REG )
    556   1.1  christos     {
    557   1.1  christos       read_special_timer6_reg(me, timers, timer_reg, dest, nr_bytes);
    558   1.1  christos     }
    559   1.1  christos   else
    560   1.1  christos     {
    561   1.1  christos       hw_abort(me, "invalid timer register address.");
    562   1.1  christos     }
    563   1.1  christos 
    564   1.1  christos   return nr_bytes;
    565   1.1  christos }
    566   1.1  christos 
    567   1.1  christos 
    568   1.1  christos static void
    569   1.1  christos do_counter_event (struct hw *me,
    570   1.1  christos 		  void *data)
    571   1.1  christos {
    572   1.1  christos   struct mn103tim *timers = hw_data(me);
    573  1.10  christos   long timer_nr = (uintptr_t) data;
    574   1.1  christos   int next_timer;
    575   1.1  christos 
    576   1.1  christos   /* Check if counting is still enabled. */
    577   1.1  christos   if ( (timers->reg[timer_nr].mode & count_mask) != 0 )
    578   1.1  christos     {
    579   1.1  christos       /* Generate an interrupt for the timer underflow (TIMERn_UFLOW). */
    580   1.1  christos 
    581   1.1  christos       /* Port event occurs on port of last cascaded timer. */
    582   1.1  christos       /* This works across timer range from 0 to NR_REG_TIMERS because */
    583   1.1  christos       /* the first 16 bit timer (timer 4) is not allowed to be set as  */
    584   1.1  christos       /* a cascading timer. */
    585   1.1  christos       for ( next_timer = timer_nr+1; next_timer < NR_REG_TIMERS; ++next_timer )
    586   1.1  christos 	{
    587   1.1  christos 	  if ( (timers->reg[next_timer].mode & clock_mask) != clk_cascaded )
    588   1.1  christos 	    {
    589   1.1  christos 	      break;
    590   1.1  christos 	    }
    591   1.1  christos 	}
    592   1.1  christos       hw_port_event (me, next_timer-1, 1);
    593   1.1  christos 
    594   1.1  christos       /* Schedule next timeout.  */
    595   1.1  christos       timers->timer[timer_nr].start = hw_event_queue_time(me);
    596   1.1  christos       /* FIX: Check if div_ratio has changed and if it's now 0. */
    597   1.1  christos       timers->timer[timer_nr].event
    598   1.1  christos 	= hw_event_queue_schedule (me, timers->timer[timer_nr].div_ratio,
    599  1.10  christos 				   do_counter_event, (void *)(uintptr_t)timer_nr);
    600   1.1  christos     }
    601   1.1  christos   else
    602   1.1  christos     {
    603   1.1  christos       timers->timer[timer_nr].event = NULL;
    604   1.1  christos     }
    605   1.1  christos 
    606   1.1  christos }
    607   1.1  christos 
    608   1.1  christos 
    609   1.1  christos static void
    610   1.1  christos do_counter6_event (struct hw *me,
    611   1.1  christos 		  void *data)
    612   1.1  christos {
    613   1.1  christos   struct mn103tim *timers = hw_data(me);
    614  1.10  christos   long timer_nr = (uintptr_t) data;
    615   1.1  christos   int next_timer;
    616   1.1  christos 
    617   1.1  christos   /* Check if counting is still enabled. */
    618   1.1  christos   if ( (timers->reg[timer_nr].mode & count_mask) != 0 )
    619   1.1  christos     {
    620   1.1  christos       /* Generate an interrupt for the timer underflow (TIMERn_UFLOW). */
    621   1.1  christos       hw_port_event (me, timer_nr, 1);
    622   1.1  christos 
    623   1.1  christos       /* Schedule next timeout.  */
    624   1.1  christos       timers->timer[timer_nr].start = hw_event_queue_time(me);
    625   1.1  christos       /* FIX: Check if div_ratio has changed and if it's now 0. */
    626   1.1  christos       timers->timer[timer_nr].event
    627   1.1  christos 	= hw_event_queue_schedule (me, timers->timer[timer_nr].div_ratio,
    628  1.10  christos 				   do_counter6_event, (void *)(uintptr_t)timer_nr);
    629   1.1  christos     }
    630   1.1  christos   else
    631   1.1  christos     {
    632   1.1  christos       timers->timer[timer_nr].event = NULL;
    633   1.1  christos     }
    634   1.1  christos 
    635   1.1  christos }
    636   1.1  christos 
    637   1.1  christos static void
    638   1.1  christos write_base_reg (struct hw *me,
    639   1.1  christos 		struct mn103tim *timers,
    640   1.1  christos 		int timer_nr,
    641   1.1  christos 		const void *source,
    642   1.1  christos 		unsigned  nr_bytes)
    643   1.1  christos {
    644   1.1  christos   unsigned i;
    645  1.10  christos   const uint8_t *buf8 = source;
    646  1.10  christos   const uint16_t *buf16 = source;
    647   1.1  christos 
    648   1.1  christos   /* If TMnCNE == 0 (counting is off),  writing to the base register
    649   1.1  christos      (TMnBR) causes a simultaneous write to the counter reg (TMnBC).
    650   1.1  christos      Else, the TMnBC is reloaded with the value from TMnBR when
    651   1.1  christos      underflow occurs.  Since the counter register is not explicitly
    652   1.1  christos      maintained, this functionality is handled in read_counter. */
    653   1.1  christos 
    654   1.1  christos   /* Check nr_bytes: write of 1, 2 or 4 bytes allowed depending on timer. */
    655   1.1  christos   switch ( nr_bytes )
    656   1.1  christos     {
    657   1.1  christos     case 1:
    658   1.1  christos       /* Storing 1 byte is ok for all registers. */
    659   1.1  christos       timers->reg[timer_nr].base = buf8[0];
    660   1.1  christos       break;
    661   1.1  christos 
    662   1.1  christos     case 2:
    663   1.1  christos       if ( timer_nr == 1 || timer_nr == 3 )
    664   1.1  christos 	{
    665   1.1  christos 	  hw_abort (me, "bad write size of 2 bytes to TM%dBR.", timer_nr);
    666   1.1  christos 	}
    667   1.1  christos       else
    668   1.1  christos 	{
    669   1.1  christos 	  if ( timer_nr < NR_8BIT_TIMERS )
    670   1.1  christos 	    {
    671   1.1  christos 	      timers->reg[timer_nr].base = buf8[0];
    672   1.1  christos 	      timers->reg[timer_nr+1].base = buf8[1];
    673   1.1  christos 	    }
    674   1.1  christos 	  else
    675   1.1  christos 	    {
    676   1.1  christos 	      timers->reg[timer_nr].base = buf16[0];
    677   1.1  christos 	    }
    678   1.1  christos 	}
    679   1.1  christos       break;
    680   1.1  christos 
    681   1.1  christos     case 4:
    682   1.1  christos       if ( timer_nr == 0 )
    683   1.1  christos 	{
    684   1.1  christos 	  timers->reg[0].base = buf8[0];
    685   1.1  christos 	  timers->reg[1].base = buf8[1];
    686   1.1  christos 	  timers->reg[2].base = buf8[2];
    687   1.1  christos 	  timers->reg[3].base = buf8[3];
    688   1.1  christos 	}
    689   1.1  christos       else if ( timer_nr == 4 )
    690   1.1  christos 	{
    691   1.1  christos 	  timers->reg[4].base = buf16[0];
    692   1.1  christos 	  timers->reg[5].base = buf16[1];
    693   1.1  christos 	}
    694   1.1  christos       else
    695   1.1  christos 	{
    696   1.1  christos 	  hw_abort (me, "bad write size of 4 bytes to TM%dBR.", timer_nr);
    697   1.1  christos 	}
    698   1.1  christos       break;
    699   1.1  christos 
    700   1.1  christos     default:
    701   1.1  christos       hw_abort (me, "bad write size must of %d bytes to TM%dBR.",
    702   1.1  christos 		nr_bytes, timer_nr);
    703   1.1  christos     }
    704   1.1  christos 
    705   1.1  christos }
    706   1.1  christos 
    707   1.1  christos static void
    708   1.1  christos write_mode_reg (struct hw *me,
    709   1.1  christos 		struct mn103tim *timers,
    710   1.1  christos 		long timer_nr,
    711   1.1  christos 		const void *source,
    712   1.1  christos 		unsigned nr_bytes)
    713   1.1  christos      /* for timers 0 to 5 */
    714   1.1  christos {
    715   1.1  christos   unsigned i;
    716  1.10  christos   uint8_t mode_val, next_mode_val;
    717  1.10  christos   uint32_t div_ratio;
    718   1.1  christos 
    719   1.1  christos   if ( nr_bytes != 1 )
    720   1.1  christos     {
    721   1.1  christos       hw_abort (me, "bad write size of %d bytes to TM%ldMD.", nr_bytes,
    722   1.1  christos 		timer_nr);
    723   1.1  christos     }
    724   1.1  christos 
    725  1.10  christos   mode_val = *(uint8_t *)source;
    726   1.1  christos   timers->reg[timer_nr].mode = mode_val;
    727   1.1  christos 
    728   1.1  christos   if ( ( mode_val & count_and_load_mask ) == count_and_load_mask )
    729   1.1  christos     {
    730   1.1  christos       hw_abort(me, "Cannot load base reg and start counting simultaneously.");
    731   1.1  christos     }
    732   1.1  christos   if ( ( mode_val & bits2to5_mask ) != 0 )
    733   1.1  christos     {
    734   1.1  christos       hw_abort(me, "Cannot write to bits 2 to 5 of mode register");
    735   1.1  christos     }
    736   1.1  christos 
    737   1.1  christos   if ( mode_val & count_mask )
    738   1.1  christos     {
    739   1.1  christos       /* - de-schedule any previous event. */
    740   1.1  christos       /* - add new event to queue to start counting. */
    741   1.1  christos       /* - assert that counter == base reg? */
    742   1.1  christos 
    743   1.1  christos       /* For cascaded timers, */
    744   1.1  christos       if ( (mode_val & clock_mask) == clk_cascaded )
    745   1.1  christos 	{
    746   1.1  christos 	  if ( timer_nr == 0 || timer_nr == 4 )
    747   1.1  christos 	    {
    748   1.1  christos 	      hw_abort(me, "Timer %ld cannot be cascaded.", timer_nr);
    749   1.1  christos 	    }
    750   1.1  christos 	}
    751   1.1  christos       else
    752   1.1  christos 	{
    753   1.1  christos 	  div_ratio = timers->reg[timer_nr].base;
    754   1.1  christos 
    755   1.1  christos 	  /* Check for cascading. */
    756   1.1  christos 	  if ( timer_nr < NR_8BIT_TIMERS )
    757   1.1  christos 	    {
    758   1.1  christos 	      for ( i = timer_nr + 1; i <= 3; ++i )
    759   1.1  christos 		{
    760   1.1  christos 		  next_mode_val = timers->reg[i].mode;
    761   1.1  christos 		  if ( ( next_mode_val & clock_mask ) == clk_cascaded )
    762   1.1  christos 		    {
    763   1.1  christos 		      /* Check that CNE is on. */
    764   1.1  christos 		      if ( ( next_mode_val & count_mask ) == 0 )
    765   1.1  christos 			{
    766   1.1  christos 			  hw_abort (me, "cascaded timer not ready for counting");
    767   1.1  christos 			}
    768   1.1  christos 		      ASSERT(timers->timer[i].event == NULL);
    769   1.1  christos 		      ASSERT(timers->timer[i].div_ratio == 0);
    770   1.1  christos 		      div_ratio = div_ratio
    771   1.1  christos 			| (timers->reg[i].base << (8*(i-timer_nr)));
    772   1.1  christos 		    }
    773   1.1  christos 		  else
    774   1.1  christos 		    {
    775   1.1  christos 		      break;
    776   1.1  christos 		    }
    777   1.1  christos 		}
    778   1.1  christos 	    }
    779   1.1  christos 	  else
    780   1.1  christos 	    {
    781   1.1  christos 	      /* Mode register for a 16 bit timer */
    782   1.1  christos 	      next_mode_val = timers->reg[timer_nr+1].mode;
    783   1.1  christos 	      if ( ( next_mode_val & clock_mask ) == clk_cascaded )
    784   1.1  christos 		{
    785   1.1  christos 		  /* Check that CNE is on. */
    786   1.1  christos 		  if ( ( next_mode_val & count_mask ) == 0 )
    787   1.1  christos 		    {
    788   1.1  christos 		      hw_abort (me, "cascaded timer not ready for counting");
    789   1.1  christos 		    }
    790   1.1  christos 		  ASSERT(timers->timer[timer_nr+1].event == NULL);
    791   1.1  christos 		  ASSERT(timers->timer[timer_nr+1].div_ratio == 0);
    792   1.1  christos 		  div_ratio = div_ratio | (timers->reg[timer_nr+1].base << 16);
    793   1.1  christos 		}
    794   1.1  christos 	    }
    795   1.1  christos 
    796   1.1  christos 	  timers->timer[timer_nr].div_ratio = div_ratio;
    797   1.1  christos 
    798   1.1  christos 	  if ( NULL != timers->timer[timer_nr].event )
    799   1.1  christos 	    {
    800   1.1  christos 	      hw_event_queue_deschedule (me, timers->timer[timer_nr].event);
    801   1.1  christos 	      timers->timer[timer_nr].event = NULL;
    802   1.1  christos 	    }
    803   1.1  christos 
    804   1.1  christos 	  if ( div_ratio > 0 )
    805   1.1  christos 	    {
    806   1.1  christos 	      /* Set start time. */
    807   1.1  christos 	      timers->timer[timer_nr].start = hw_event_queue_time(me);
    808   1.1  christos 	      timers->timer[timer_nr].event
    809   1.1  christos 		= hw_event_queue_schedule(me, div_ratio,
    810   1.1  christos 					  do_counter_event,
    811  1.10  christos 					  (void *)(uintptr_t)timer_nr);
    812   1.1  christos 	    }
    813   1.1  christos 	}
    814   1.1  christos     }
    815   1.1  christos   else
    816   1.1  christos     {
    817   1.1  christos       /* Turn off counting */
    818   1.1  christos       if ( NULL != timers->timer[timer_nr].event )
    819   1.1  christos 	{
    820   1.1  christos 	  ASSERT((timers->reg[timer_nr].mode & clock_mask) != clk_cascaded);
    821   1.1  christos 	  hw_event_queue_deschedule (me, timers->timer[timer_nr].event);
    822   1.1  christos 	  timers->timer[timer_nr].event = NULL;
    823   1.1  christos 	}
    824   1.1  christos       else
    825   1.1  christos 	{
    826   1.1  christos 	  if ( (timers->reg[timer_nr].mode & clock_mask) == clk_cascaded )
    827   1.1  christos 	    {
    828   1.1  christos 	      ASSERT(timers->timer[timer_nr].event == NULL);
    829   1.1  christos 	    }
    830   1.1  christos 	}
    831   1.1  christos 
    832   1.1  christos     }
    833   1.1  christos 
    834   1.1  christos }
    835   1.1  christos 
    836   1.1  christos static void
    837   1.1  christos write_tm6md (struct hw *me,
    838   1.1  christos 	     struct mn103tim *timers,
    839   1.1  christos 	     unsigned_word address,
    840   1.1  christos 	     const void *source,
    841   1.1  christos 	     unsigned nr_bytes)
    842   1.1  christos {
    843  1.10  christos   uint8_t mode_val0 = 0x00, mode_val1 = 0x00;
    844  1.10  christos   uint32_t div_ratio;
    845   1.1  christos   long timer_nr = 6;
    846   1.1  christos 
    847   1.1  christos   unsigned_word offset = address - timers->block[0].base;
    848   1.1  christos 
    849   1.1  christos   if ((offset != 0x84 && nr_bytes > 1) || nr_bytes > 2 )
    850   1.1  christos     {
    851   1.1  christos       hw_abort (me, "Bad write size of %d bytes to TM6MD", nr_bytes);
    852   1.1  christos     }
    853   1.1  christos 
    854   1.1  christos   if ( offset == 0x84 )  /* address of TM6MD */
    855   1.1  christos     {
    856   1.1  christos       /*  Fill in first byte of mode */
    857  1.10  christos       mode_val0 = *(uint8_t *)source;
    858   1.1  christos       timers->tm6md0 = mode_val0;
    859   1.1  christos 
    860   1.1  christos       if ( ( mode_val0 & 0x26 ) != 0 )
    861   1.1  christos 	{
    862   1.1  christos 	  hw_abort(me, "Cannot write to bits 5, 3, and 2 of TM6MD");
    863   1.1  christos 	}
    864   1.1  christos     }
    865   1.1  christos 
    866   1.1  christos   if ( offset == 0x85 || nr_bytes == 2 )
    867   1.1  christos     {
    868   1.1  christos       /*  Fill in second byte of mode */
    869   1.1  christos       if ( nr_bytes == 2 )
    870   1.1  christos 	{
    871  1.10  christos 	  mode_val1 = *(uint8_t *)source+1;
    872   1.1  christos 	}
    873   1.1  christos       else
    874   1.1  christos 	{
    875  1.10  christos 	  mode_val1 = *(uint8_t *)source;
    876   1.1  christos 	}
    877   1.1  christos 
    878   1.1  christos       timers->tm6md1 = mode_val1;
    879   1.1  christos 
    880   1.1  christos       if ( ( mode_val1 & count_and_load_mask ) == count_and_load_mask )
    881   1.1  christos 	{
    882   1.1  christos 	  hw_abort(me, "Cannot load base reg and start counting simultaneously.");
    883   1.1  christos 	}
    884   1.1  christos       if ( ( mode_val1 & bits0to2_mask ) != 0 )
    885   1.1  christos 	{
    886   1.1  christos 	  hw_abort(me, "Cannot write to bits 8 to 10 of TM6MD");
    887   1.1  christos 	}
    888   1.1  christos     }
    889   1.1  christos 
    890   1.1  christos   if ( mode_val1 & count_mask )
    891   1.1  christos     {
    892   1.1  christos       /* - de-schedule any previous event. */
    893   1.1  christos       /* - add new event to queue to start counting. */
    894   1.1  christos       /* - assert that counter == base reg? */
    895   1.1  christos 
    896   1.1  christos       div_ratio = timers->tm6ca;  /* binary counter for timer 6 */
    897   1.1  christos       timers->timer[timer_nr].div_ratio = div_ratio;
    898   1.1  christos       if ( NULL != timers->timer[timer_nr].event )
    899   1.1  christos 	{
    900   1.1  christos 	  hw_event_queue_deschedule (me, timers->timer[timer_nr].event);
    901   1.1  christos 	  timers->timer[timer_nr].event = NULL;
    902   1.1  christos 	}
    903   1.1  christos 
    904   1.1  christos       if ( div_ratio > 0 )
    905   1.1  christos 	{
    906   1.1  christos 	  /* Set start time. */
    907   1.1  christos 	  timers->timer[timer_nr].start = hw_event_queue_time(me);
    908   1.1  christos 	  timers->timer[timer_nr].event
    909   1.1  christos 	    = hw_event_queue_schedule(me, div_ratio,
    910   1.1  christos 				      do_counter6_event,
    911  1.10  christos 				      (void *)(uintptr_t)timer_nr);
    912   1.1  christos 	}
    913   1.1  christos     }
    914   1.1  christos   else
    915   1.1  christos     {
    916   1.1  christos       /* Turn off counting */
    917   1.1  christos       if ( NULL != timers->timer[timer_nr].event )
    918   1.1  christos 	{
    919   1.1  christos 	  hw_event_queue_deschedule (me, timers->timer[timer_nr].event);
    920   1.1  christos 	  timers->timer[timer_nr].event = NULL;
    921   1.1  christos 	}
    922   1.1  christos     }
    923   1.1  christos }
    924   1.1  christos 
    925   1.1  christos 
    926   1.1  christos 
    927   1.1  christos static void
    928   1.1  christos write_special_timer6_reg (struct hw *me,
    929   1.1  christos 			  struct mn103tim *timers,
    930   1.1  christos 			  int timer_nr,
    931   1.1  christos 			  const void *source,
    932   1.1  christos 			  unsigned  nr_bytes)
    933   1.1  christos {
    934  1.10  christos   uint32_t val;
    935   1.1  christos 
    936   1.1  christos   switch (nr_bytes) {
    937   1.1  christos   case 1:
    938   1.1  christos     {
    939   1.1  christos       switch ( timer_nr ) {
    940   1.1  christos       case TM6MDA:
    941  1.10  christos 	timers->tm6mda = *(uint8_t *)source;
    942   1.1  christos 	break;
    943   1.1  christos 
    944   1.1  christos       case TM6MDB:
    945  1.10  christos 	timers->tm6mdb = *(uint8_t *)source;
    946   1.1  christos 	break;
    947   1.1  christos 
    948   1.1  christos       case TM6CA:
    949  1.10  christos 	timers->tm6ca = *(uint8_t *)source;
    950   1.1  christos 	break;
    951   1.1  christos 
    952   1.1  christos       case TM6CB:
    953  1.10  christos 	timers->tm6cb = *(uint8_t *)source;
    954   1.1  christos 	break;
    955   1.1  christos 
    956   1.1  christos       default:
    957   1.1  christos 	break;
    958   1.1  christos       }
    959   1.1  christos       break;
    960   1.1  christos     }
    961   1.1  christos 
    962   1.1  christos   case 2:
    963   1.1  christos     if ( timer_nr == TM6CA )
    964   1.1  christos       {
    965  1.10  christos 	timers->tm6ca = *(uint16_t *)source;
    966   1.1  christos       }
    967   1.1  christos     else if ( timer_nr == TM6CB )
    968   1.1  christos       {
    969  1.10  christos 	timers->tm6cb = *(uint16_t *)source;
    970   1.1  christos       }
    971   1.1  christos     else
    972   1.1  christos       {
    973   1.1  christos 	hw_abort(me, "bad read size for timer 6 mode A/B register");
    974   1.1  christos       }
    975   1.1  christos     break;
    976   1.1  christos 
    977   1.1  christos   default:
    978   1.1  christos     hw_abort(me, "bad read size for timer 6 register");
    979   1.1  christos   }
    980   1.1  christos 
    981   1.1  christos }
    982   1.1  christos 
    983   1.1  christos 
    984   1.1  christos static unsigned
    985   1.1  christos mn103tim_io_write_buffer (struct hw *me,
    986   1.1  christos 			  const void *source,
    987   1.1  christos 			  int space,
    988   1.1  christos 			  unsigned_word base,
    989   1.1  christos 			  unsigned nr_bytes)
    990   1.1  christos {
    991   1.1  christos   struct mn103tim *timers = hw_data (me);
    992   1.1  christos   enum timer_register_types timer_reg;
    993   1.1  christos 
    994   1.1  christos   HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base,
    995  1.10  christos 	     (int) nr_bytes, *(uint32_t *)source));
    996   1.1  christos 
    997   1.1  christos   timer_reg = decode_addr (me, timers, base);
    998   1.1  christos 
    999   1.1  christos   /* It can be either a mode register, a base register, a binary counter, */
   1000   1.1  christos   /* or a special timer 6 register.  Check in that order. */
   1001   1.1  christos   if ( timer_reg <= LAST_MODE_REG )
   1002   1.1  christos     {
   1003   1.1  christos       if ( timer_reg == 6 )
   1004   1.1  christos 	{
   1005   1.1  christos 	  write_tm6md(me, timers, base, source, nr_bytes);
   1006   1.1  christos 	}
   1007   1.1  christos       else
   1008   1.1  christos 	{
   1009   1.1  christos 	  write_mode_reg(me, timers, timer_reg-FIRST_MODE_REG,
   1010   1.1  christos 			 source, nr_bytes);
   1011   1.1  christos 	}
   1012   1.1  christos     }
   1013   1.1  christos   else if ( timer_reg <= LAST_BASE_REG )
   1014   1.1  christos     {
   1015   1.1  christos       write_base_reg(me, timers, timer_reg-FIRST_BASE_REG, source, nr_bytes);
   1016   1.1  christos     }
   1017   1.1  christos   else if ( timer_reg <= LAST_COUNTER )
   1018   1.1  christos     {
   1019   1.1  christos       hw_abort(me, "cannot write to counter");
   1020   1.1  christos     }
   1021   1.1  christos   else if ( timer_reg <= LAST_TIMER_REG )
   1022   1.1  christos     {
   1023   1.1  christos       write_special_timer6_reg(me, timers, timer_reg, source, nr_bytes);
   1024   1.1  christos     }
   1025   1.1  christos   else
   1026   1.1  christos     {
   1027   1.1  christos       hw_abort(me, "invalid reg type");
   1028   1.1  christos     }
   1029   1.1  christos 
   1030   1.1  christos   return nr_bytes;
   1031   1.1  christos }
   1032   1.1  christos 
   1033   1.1  christos 
   1034   1.1  christos const struct hw_descriptor dv_mn103tim_descriptor[] = {
   1035   1.1  christos   { "mn103tim", mn103tim_finish, },
   1036   1.1  christos   { NULL },
   1037   1.1  christos };
   1038