diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
commit | 071ea11e85eb9d529cc5eb3d35f6247466a21b99 (patch) | |
tree | 5deda65b8d7b04d1f4cbc534c3206d328e1267ec /sim/mn10300/dv-mn103tim.c | |
parent | 1730ec6b1848f0f32154277f788fb29f88d8475b (diff) | |
download | gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.zip gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.gz gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.bz2 |
Initial creation of sourceware repository
Diffstat (limited to 'sim/mn10300/dv-mn103tim.c')
-rw-r--r-- | sim/mn10300/dv-mn103tim.c | 823 |
1 files changed, 0 insertions, 823 deletions
diff --git a/sim/mn10300/dv-mn103tim.c b/sim/mn10300/dv-mn103tim.c deleted file mode 100644 index 6347db6..0000000 --- a/sim/mn10300/dv-mn103tim.c +++ /dev/null @@ -1,823 +0,0 @@ -/* This file is part of the program GDB, the GNU debugger. - - Copyright (C) 1998 Free Software Foundation, Inc. - Contributed by Cygnus Solutions. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - -#include "sim-main.h" -#include "hw-main.h" - -/* DEVICE - - - mn103tim - mn103002 timers (8 and 16 bit) - - - DESCRIPTION - - Implements the mn103002 8 and 16 bit timers as described in the mn103002 user guide. - - - PROPERTIES - - reg = <8bit-timers-addr> <8bit-timers-size> <16bit-timers-addr> <16bit-timers-size> - - - BUGS - - */ - - -/* The timers' register address blocks */ - -struct mn103tim_block { - unsigned_word base; - unsigned_word bound; -}; - -enum { TIMER8_BLOCK, TIMER16_BLOCK, NR_TIMER_BLOCKS }; - -enum timer_register_types { - FIRST_MODE_REG = 0, - TM0MD = FIRST_MODE_REG, - TM1MD, - TM2MD, - TM3MD, - TM4MD, - TM5MD, - TM6MD, - LAST_MODE_REG = TM6MD, - FIRST_BASE_REG, - TM0BR = FIRST_BASE_REG, - TM1BR, - TM2BR, - TM3BR, - TM4BR, - TM5BR, - LAST_BASE_REG = TM5BR, - FIRST_COUNTER, - TM0BC = FIRST_COUNTER, - TM1BC, - TM2BC, - TM3BC, - TM4BC, - TM5BC, - TM6BC, - LAST_COUNTER = TM6BC, - TM6MDA, - TM6MDB, - TM6CA, - TM6CB, -}; - - -/* Don't include timer 6 because it's handled specially. */ -#define NR_8BIT_TIMERS 4 -#define NR_16BIT_TIMERS 2 -#define NR_TIMERS 6 - -typedef struct _mn10300_timer { - unsigned32 div_ratio, start, base; - unsigned8 mode; - struct hw_event *event; -} mn10300_timer; - - -struct mn103tim { - struct mn103tim_block block[NR_TIMER_BLOCKS]; - mn10300_timer timer[NR_TIMERS]; - - /* treat timer 6 registers specially. */ - unsigned16 tm6md, tm6bc, tm6mca, tm6mcb; - unsigned8 tm6mda, tm6mdb; /* compare/capture mode regs for timer 6 */ - struct hw_event *event6; -}; - -/* output port ID's */ - -/* for mn103002 */ -enum { - TIMER0_UFLOW, - TIMER1_UFLOW, - TIMER2_UFLOW, - TIMER3_UFLOW, - TIMER4_UFLOW, - TIMER5_UFLOW, - TIMER6_UFLOW, - TIMER6_CMPA, - TIMER6_CMPB, -}; - - -static const struct hw_port_descriptor mn103tim_ports[] = { - - { "timer-0-underflow", TIMER0_UFLOW, 0, output_port, }, - { "timer-1-underflow", TIMER1_UFLOW, 0, output_port, }, - { "timer-2-underflow", TIMER2_UFLOW, 0, output_port, }, - { "timer-3-underflow", TIMER3_UFLOW, 0, output_port, }, - { "timer-4-underflow", TIMER4_UFLOW, 0, output_port, }, - { "timer-5-underflow", TIMER5_UFLOW, 0, output_port, }, - - { "timer-6-underflow", TIMER6_UFLOW, 0, output_port, }, - { "timer-6-compare-a", TIMER6_CMPA, 0, output_port, }, - { "timer-6-compare-b", TIMER6_CMPB, 0, output_port, }, - - { NULL, }, -}; - -#define bits2to5_mask 0x3c -#define load_mask 0x40 -#define count_mask 0x80 -#define count_and_load_mask (load_mask | count_mask) -#define clock_mask 0x03 -#define clk_ioclk 0x00 -#define clk_cascaded 0x03 - - -/* Finish off the partially created hw device. Attach our local - callbacks. Wire up our port names etc */ - -static hw_io_read_buffer_method mn103tim_io_read_buffer; -static hw_io_write_buffer_method mn103tim_io_write_buffer; - -static void -attach_mn103tim_regs (struct hw *me, - struct mn103tim *timers) -{ - int i; - if (hw_find_property (me, "reg") == NULL) - hw_abort (me, "Missing \"reg\" property"); - for (i = 0; i < NR_TIMER_BLOCKS; i++) - { - unsigned_word attach_address; - int attach_space; - unsigned attach_size; - reg_property_spec reg; - if (!hw_find_reg_array_property (me, "reg", i, ®)) - hw_abort (me, "\"reg\" property must contain three addr/size entries"); - hw_unit_address_to_attach_address (hw_parent (me), - ®.address, - &attach_space, - &attach_address, - me); - timers->block[i].base = attach_address; - hw_unit_size_to_attach_size (hw_parent (me), - ®.size, - &attach_size, me); - timers->block[i].bound = attach_address + (attach_size - 1); - hw_attach_address (hw_parent (me), - 0, - attach_space, attach_address, attach_size, - me); - } -} - -static void -mn103tim_finish (struct hw *me) -{ - struct mn103tim *timers; - int i; - - timers = HW_ZALLOC (me, struct mn103tim); - set_hw_data (me, timers); - set_hw_io_read_buffer (me, mn103tim_io_read_buffer); - set_hw_io_write_buffer (me, mn103tim_io_write_buffer); - set_hw_ports (me, mn103tim_ports); - - /* Attach ourself to our parent bus */ - attach_mn103tim_regs (me, timers); - - /* Initialize the timers */ - for ( i=0; i < NR_TIMERS; ++i ) - { - timers->timer[i].event = NULL; - timers->timer[i].mode = 0x00; - timers->timer[i].base = 0; - timers->timer[i].div_ratio = 0; - timers->timer[i].start = 0; - } - timers->tm6md = 0x0000; - timers->tm6bc = 0x0000; - timers->tm6mca = 0x0000; - timers->tm6mcb = 0x0000; - timers->tm6mda = 0x00; - timers->tm6mdb = 0x00; -} - - - -/* read and write */ - -static int -decode_addr (struct hw *me, - struct mn103tim *timers, - unsigned_word address) -{ - unsigned_word offset; - offset = address - timers->block[0].base; - - switch (offset) - { - case 0x00: return TM0MD; - case 0x01: return TM1MD; - case 0x02: return TM2MD; - case 0x03: return TM3MD; - case 0x10: return TM0BR; - case 0x11: return TM1BR; - case 0x12: return TM2BR; - case 0x13: return TM3BR; - case 0x20: return TM0BC; - case 0x21: return TM1BC; - case 0x22: return TM2BC; - case 0x23: return TM3BC; - case 0x80: return TM4MD; - case 0x82: return TM5MD; - case 0x84: return TM6MD; - case 0x90: return TM4BR; - case 0x92: return TM5BR; - case 0xa0: return TM4BC; - case 0xa2: return TM5BC; - case 0xa4: return TM6BC; - case 0xb4: return TM6MDA; - case 0xb5: return TM6MDB; - case 0xc4: return TM6CA; - case 0xd4: return TM6CB; - default: - { - hw_abort (me, "bad address"); - return -1; - } - } -} - -static void -read_mode_reg (struct hw *me, - struct mn103tim *timers, - int timer_nr, - void *dest, - unsigned nr_bytes) -{ - unsigned16 val16; - unsigned32 val32; - - switch ( nr_bytes ) - { - case 1: - /* Accessing 1 byte is ok for all mode registers. */ - *(unsigned8*)dest = timers->timer[timer_nr].mode; - break; - - case 2: - if ( timer_nr == 6 ) - { - *(unsigned16 *)dest = timers->tm6md; - } - else if ( timer_nr == 0 || timer_nr == 2 ) - { - val16 = (timers->timer[timer_nr].mode << 8) - | timers->timer[timer_nr+1].mode; - *(unsigned16*)dest = val16; - } - else - { - hw_abort (me, "bad read size of 2 bytes to TM%dMD.", timer_nr); - } - break; - - case 4: - if ( timer_nr == 0 ) - { - val32 = (timers->timer[0].mode << 24 ) - | (timers->timer[1].mode << 16) - | (timers->timer[2].mode << 8) - | timers->timer[3].mode; - *(unsigned32*)dest = val32; - } - else - { - hw_abort (me, "bad read size of 4 bytes to TM%dMD.", timer_nr); - } - break; - - default: - hw_abort (me, "bad read size of %d bytes to TM%dMD.", - nr_bytes, timer_nr); - } -} - - -static void -read_base_reg (struct hw *me, - struct mn103tim *timers, - int timer_nr, - void *dest, - unsigned nr_bytes) -{ - unsigned16 val16; - unsigned32 val32; - - /* Check nr_bytes: accesses of 1, 2 and 4 bytes allowed depending on timer. */ - switch ( nr_bytes ) - { - case 1: - /* Reading 1 byte is ok for all registers. */ - if ( timer_nr < NR_8BIT_TIMERS ) - { - *(unsigned8*)dest = timers->timer[timer_nr].base; - } - break; - - case 2: - if ( timer_nr == 1 || timer_nr == 3 ) - { - hw_abort (me, "bad read size of 2 bytes to TM%dBR.", timer_nr); - } - else - { - if ( timer_nr < NR_8BIT_TIMERS ) - { - val16 = (timers->timer[timer_nr].base<<8) - | timers->timer[timer_nr+1].base; - } - else - { - val16 = timers->timer[timer_nr].base; - } - *(unsigned16*)dest = val16; - } - break; - - case 4: - if ( timer_nr == 0 ) - { - val32 = (timers->timer[0].base << 24) | (timers->timer[1].base << 16) - | (timers->timer[2].base << 8) | timers->timer[3].base; - *(unsigned32*)dest = val32; - } - else if ( timer_nr == 4 ) - { - val32 = (timers->timer[4].base << 16) | timers->timer[5].base; - *(unsigned32*)dest = val32; - } - else - { - hw_abort (me, "bad read size of 4 bytes to TM%dBR.", timer_nr); - } - break; - - default: - hw_abort (me, "bad read size must of %d bytes to TM%dBR.", - nr_bytes, timer_nr); - } -} - - -static void -read_counter (struct hw *me, - struct mn103tim *timers, - int timer_nr, - void *dest, - unsigned nr_bytes) -{ - unsigned32 val; - - if ( NULL == timers->timer[timer_nr].event ) - { - /* Timer is not counting, use value in base register. */ - val = timers->timer[timer_nr].base; - } - else - { - /* ticks left = start time + div ratio - curr time */ - /* Cannot use base register because it can be written during counting and it - doesn't affect counter until underflow occurs. */ - - val = timers->timer[timer_nr].start + timers->timer[timer_nr].div_ratio - - hw_event_queue_time(me); - } - - switch (nr_bytes) { - case 1: - *(unsigned8 *)dest = val; - break; - - case 2: - *(unsigned16 *)dest = val; - break; - - case 4: - *(unsigned32 *)dest = val; - break; - - default: - hw_abort(me, "bad read size for reading counter"); - } - -} - - -static unsigned -mn103tim_io_read_buffer (struct hw *me, - void *dest, - int space, - unsigned_word base, - unsigned nr_bytes) -{ - struct mn103tim *timers = hw_data (me); - enum timer_register_types timer_reg; - - HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); - - timer_reg = decode_addr (me, timers, base); - - /* It can be either a mode register, a base register or a binary counter. */ - /* Check in that order. */ - if ( timer_reg >= FIRST_MODE_REG && timer_reg <= LAST_MODE_REG ) - { - read_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, dest, nr_bytes); - } - else if ( timer_reg <= LAST_BASE_REG ) - { - read_base_reg(me, timers, timer_reg-FIRST_BASE_REG, dest, nr_bytes); - } - else if ( timer_reg <= LAST_COUNTER ) - { - read_counter(me, timers, timer_reg-FIRST_COUNTER, dest, nr_bytes); - } - else - { - hw_abort(me, "invalid timer register address."); - } - - return nr_bytes; -} - - -static void -do_counter_event (struct hw *me, - void *data) -{ - struct mn103tim *timers = hw_data(me); - int timer_nr = (int) data; - - /* Check if counting is still enabled. */ - if ( (timers->timer[timer_nr].mode & count_mask) != 0 ) - { - /* Generate an interrupt for the timer underflow (TIMERn_UFLOW). */ - hw_port_event (me, timer_nr /*uflow_port[timer_nr]*/, 1 /* level */); - - /* Schedule next timeout. */ - - timers->timer[timer_nr].start = hw_event_queue_time(me); - /* FIX: Check if div_ ratio has changed and if it's now 0. */ - timers->timer[timer_nr].event - = hw_event_queue_schedule (me, timers->timer[timer_nr].div_ratio, - do_counter_event, (void *)timer_nr); - } - -} - -static void -write_base_reg (struct hw *me, - struct mn103tim *timers, - int timer_nr, - const void *source, - unsigned nr_bytes) -{ - unsigned i; - const unsigned8 *buf8 = source; - const unsigned16 *buf16 = source; - unsigned8 mode_val; - - /* If TMnCNE == 0 (counting is off), writing to the base register - (TMnBR) causes a simultaneous write to the counter reg (TMnBC). - Else, the TMnBC is reloaded with the value from TMnBR when - underflow occurs. Since the counter register is not explicitly - maintained, this functionality is handled in read_counter. */ - - mode_val = timers->timer[timer_nr].mode; - - /* Check nr_bytes: write of 1, 2 or 4 bytes allowed depending on timer. */ - switch ( nr_bytes ) - { - case 1: - /* Storing 1 byte is ok for all registers. */ - timers->timer[timer_nr].base = buf8[0]; - break; - - case 2: - if ( timer_nr == 1 || timer_nr == 3 ) - { - hw_abort (me, "bad write size of 2 bytes to TM%dBR.", timer_nr); - } - else - { - if ( timer_nr < NR_8BIT_TIMERS ) - { - timers->timer[timer_nr].base = buf8[0]; - timers->timer[timer_nr+1].base = buf8[1]; - } - else - { - timers->timer[timer_nr].base = buf16[0]; - } - } - break; - - case 4: - if ( timer_nr == 0 ) - { - ASSERT(0); - timers->timer[0].base = buf8[0]; - timers->timer[1].base = buf8[1]; - timers->timer[2].base = buf8[2]; - timers->timer[3].base = buf8[3]; - } - else if ( timer_nr == 4 ) - { - timers->timer[4].base = buf16[0]; - timers->timer[5].base = buf16[1]; - } - else - { - hw_abort (me, "bad write size of 4 bytes to TM%dBR.", timer_nr); - } - break; - - default: - hw_abort (me, "bad write size must of %d bytes to TM%dBR.", - nr_bytes, timer_nr); - } - -} - -static void -write_8bit_mode_reg (struct hw *me, - struct mn103tim *timers, - int timer_nr, - const void *source, - unsigned nr_bytes) - /* for timers 0 to 3 */ -{ - unsigned i; - unsigned8 mode_val, next_mode_val; - unsigned32 div_ratio; - - if ( nr_bytes != 1 ) - { - hw_abort (me, "bad write size of %d bytes to TM%dMD.", nr_bytes, timer_nr); - } - - mode_val = *(unsigned8 *)source; - timers->timer[timer_nr].mode = mode_val; - - if ( ( mode_val & count_and_load_mask ) == count_and_load_mask ) - { - hw_abort(me, "Cannot load base reg and start counting simultaneously."); - } - if ( ( mode_val & bits2to5_mask ) != 0 ) - { - hw_abort(me, "Cannot write to bits 2 to 5 of mode register"); - } - - if ( mode_val & count_mask ) - { - /* - de-schedule any previous event. */ - /* - add new event to queue to start counting. */ - /* - assert that counter == base reg? */ - - /* For cascaded timers, */ - if ( (mode_val & clock_mask) == clk_cascaded ) - { - if ( timer_nr == 0 ) - { - hw_abort(me, "Timer 0 cannot be cascaded."); - } - } - else - { - div_ratio = timers->timer[timer_nr].base; - - /* Check for cascading. */ - next_mode_val = timers->timer[timer_nr+1].mode; - if ( ( next_mode_val & clock_mask ) == clk_cascaded ) - { - /* Check that CNE is on. */ - if ( ( next_mode_val & count_mask ) == 0 ) - { - hw_abort (me, "cascaded timer not ready for counting"); - } - ASSERT(timers->timer[timer_nr+1].event == NULL); - ASSERT(timers->timer[timer_nr+1].div_ratio == 0); - div_ratio = div_ratio | (timers->timer[timer_nr+1].base << 8); - } - - timers->timer[timer_nr].div_ratio = div_ratio; - - if ( NULL != timers->timer[timer_nr].event ) - { - hw_event_queue_deschedule (me, timers->timer[timer_nr].event); - timers->timer[timer_nr].event = NULL; - } - - if ( div_ratio > 0 ) - { - /* Set start time. */ - timers->timer[timer_nr].start = hw_event_queue_time(me); - - timers->timer[timer_nr].event - = hw_event_queue_schedule(me, div_ratio, - do_counter_event, - (void *)(timer_nr)); - } - } - } - else - { - /* Turn off counting */ - if ( NULL != timers->timer[timer_nr].event ) - { - ASSERT((timers->timer[timer_nr].mode & clock_mask) != clk_cascaded); - hw_event_queue_deschedule (me, timers->timer[timer_nr].event); - timers->timer[timer_nr].event = NULL; - } - else - { - if ( (timers->timer[timer_nr].mode & clock_mask) == clk_cascaded ) - { - ASSERT(timers->timer[timer_nr].event == NULL); - } - } - - } - -} - -static void -write_16bit_mode_reg (struct hw *me, - struct mn103tim *timers, - int timer_nr, - const void *source, - unsigned nr_bytes) - /* for timers 4 and 5, not 6 */ -{ - unsigned i; - unsigned8 mode_val, next_mode_val; - unsigned32 div_ratio; - - if ( nr_bytes != 1 ) - { - hw_abort (me, "bad write size of %d bytes to TM%dMD.", nr_bytes, timer_nr); - } - - mode_val = *(unsigned8 *)source; - timers->timer[timer_nr].mode = mode_val; - - if ( ( mode_val & count_and_load_mask ) == count_and_load_mask ) - { - hw_abort(me, "Cannot load base reg and start counting simultaneously."); - } - if ( ( mode_val & bits2to5_mask ) != 0 ) - { - hw_abort(me, "Cannot write to bits 2 to 5 of mode register"); - } - - - if ( mode_val & count_mask ) - { - /* - de-schedule any previous event. */ - /* - add new event to queue to start counting. */ - /* - assert that counter == base reg? */ - - /* For cascaded timers, */ - if ( (mode_val & clock_mask) == clk_cascaded ) - { - if ( timer_nr == 4 ) - { - hw_abort(me, "Timer 4 cannot be cascaded."); - } - } - else - { - div_ratio = timers->timer[timer_nr].base; - - /* Check for cascading. */ - next_mode_val = timers->timer[timer_nr+1].mode; - if ( ( next_mode_val & clock_mask ) == clk_cascaded ) - { - /* Check that CNE is on. */ - if ( ( next_mode_val & count_mask ) == 0 ) - { - hw_abort (me, "cascaded timer not ready for counting"); - } - ASSERT(timers->timer[timer_nr+1].event == NULL); - ASSERT(timers->timer[timer_nr+1].div_ratio == 0); - div_ratio = div_ratio | (timers->timer[timer_nr+1].base << 16); - } - - timers->timer[timer_nr].div_ratio = div_ratio; - - if ( NULL != timers->timer[timer_nr].event ) - { - hw_event_queue_deschedule (me, timers->timer[timer_nr].event); - timers->timer[timer_nr].event = NULL; - } - - if ( div_ratio > 0 ) - { - /* Set start time. */ - timers->timer[timer_nr].start = hw_event_queue_time(me); - - timers->timer[timer_nr].event - = hw_event_queue_schedule(me, div_ratio, do_counter_event, - (void *)(timer_nr)); - } - } - } - else - { - /* Turn off counting */ - if ( NULL != timers->timer[timer_nr].event ) - { - ASSERT((timers->timer[timer_nr].mode & clock_mask) != clk_cascaded); - hw_event_queue_deschedule (me, timers->timer[timer_nr].event); - timers->timer[timer_nr].event = NULL; - } - else - { - if ( (timers->timer[timer_nr].mode & clock_mask) == clk_cascaded ) - { - ASSERT(timers->timer[timer_nr].event == NULL); - } - } - - } - -} - -static unsigned -mn103tim_io_write_buffer (struct hw *me, - const void *source, - int space, - unsigned_word base, - unsigned nr_bytes) -{ - struct mn103tim *timers = hw_data (me); - enum timer_register_types timer_reg; - - HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base, - (int) nr_bytes, *(unsigned32 *)source)); - - timer_reg = decode_addr (me, timers, base); - - /* It can be either a mode register, a base register or a binary counter. */ - /* Check in that order. */ - if ( timer_reg <= LAST_MODE_REG ) - { - if ( timer_reg > 3 ) - { - write_16bit_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, - source, nr_bytes); - } - else - { - write_8bit_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, - source, nr_bytes); - } - } - else if ( timer_reg <= LAST_BASE_REG ) - { - write_base_reg(me, timers, timer_reg-FIRST_BASE_REG, source, nr_bytes); - } - else if ( timer_reg <= LAST_COUNTER ) - { - hw_abort(me, "cannot write to counter"); - } - else - { - hw_abort(me, "invalid reg type"); - } - - return nr_bytes; -} - - -const struct hw_descriptor dv_mn103tim_descriptor[] = { - { "mn103tim", mn103tim_finish, }, - { NULL }, -}; |