Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:44

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * ATTENTION: As MC68349 has no built-in Timer, the following code doesn't work
0005  *            in a MC68349. You can't use FIFO full mode for the moment, but
0006  *            it should be easy to fix this by using an external timer.
0007  *
0008  * Use TIMER 1 for TIMEOUT when using FIFO FULL mode in UART driver
0009  * Use TIMER 2 for timing test suites
0010  *
0011  *  NOTE: It is important that the timer start/stop overhead be
0012  *        determined when porting or modifying this code.
0013  */
0014 
0015 /*
0016  * Geoffroy Montel
0017  * France Telecom - CNET/DSM/TAM/CAT
0018  * 4, rue du Clos Courtel
0019  * 35512 CESSON-SEVIGNE
0020  * FRANCE
0021  *
0022  * e-mail: g_montel@yahoo.com
0023  *
0024  *  COPYRIGHT (c) 1989-1999.
0025  *  On-Line Applications Research Corporation (OAR).
0026  *
0027  * Redistribution and use in source and binary forms, with or without
0028  * modification, are permitted provided that the following conditions
0029  * are met:
0030  * 1. Redistributions of source code must retain the above copyright
0031  *    notice, this list of conditions and the following disclaimer.
0032  * 2. Redistributions in binary form must reproduce the above copyright
0033  *    notice, this list of conditions and the following disclaimer in the
0034  *    documentation and/or other materials provided with the distribution.
0035  *
0036  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0037  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0038  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0039  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0040  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0041  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0042  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0043  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0044  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0045  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0046  * POSSIBILITY OF SUCH DAMAGE.
0047  */
0048 
0049 #include <rtems.h>
0050 #include <bsp.h>
0051 #include <rtems/btimer.h>
0052 #include <m340uart.h>
0053 #include <m340timer.h>
0054 #include <m68340.h>
0055 
0056 #define TIMER1_VECTOR 122
0057 #define TIMER1_IRQ_LEVEL 5
0058 #define TIMER1_INTERRUPT_ARBITRATION 5
0059 
0060 #define TIMER2_VECTOR 123
0061 #define TIMER2_IRQ_LEVEL 4
0062 #define TIMER2_INTERRUPT_ARBITRATION 4
0063 
0064 #define CLOCK_SPEED 25    /* in Mhz */
0065 
0066 #define max(a,b) (((a)>(b)) ? (a) : (b))
0067 
0068 void (*Restart_Fifo_Full_A_Timer)(void);
0069 void (*Restart_Check_A_Timer)(void);
0070 void (*Restart_Fifo_Full_B_Timer)(void);
0071 void (*Restart_Check_B_Timer)(void);
0072 
0073 int preload = 0;
0074 
0075 /*
0076  * __Restart_Fifo_Full_Timer
0077  *
0078  * When a character is received, sets the TIMER to raise an interrupt at
0079  * TIMEOUT.  It's necessary to prevent from not getting n-1 characters
0080  * (with n the Uart Fifo size).
0081  */
0082 static void __Restart_Fifo_Full_Timer (void)
0083 {
0084   TSR1 |= m340_TO;
0085   TCR1 &= ~m340_CPE;
0086   WPREL11 = preload;
0087   TCR1 |= m340_CPE;
0088 }
0089 
0090 /*
0091  * __Restart_Check_Timer
0092  *
0093  * When no character has been received recently, check now and then if whether
0094  * a there's a character in the FIFO
0095  */
0096 static void __Restart_Check_Timer (void)
0097 {
0098  TSR1 |= m340_TO;
0099  TCR1 &= ~m340_CPE;
0100  WPREL11 = 0xFFFF;
0101  TCR1 |= m340_CPE;
0102 }
0103 
0104 /*
0105  * __do_nothing
0106  *
0107  * We always restart the fifo full timer with a call to Restart_*_Timer
0108  * if we do not use FIFO full, Restart_X_Timer are set to do __do_nothing
0109  */
0110 static void __do_nothing (void)
0111 {
0112 }
0113 
0114 #define Fifo_Full_on_A \
0115    (m340_uart_config[UART_CHANNEL_A].rx_mode==UART_FIFO_FULL && \
0116     m340_uart_config[UART_CHANNEL_A].enable && \
0117     m340_uart_config[UART_CHANNEL_A].mode==UART_INTERRUPTS)
0118 #define Fifo_Full_on_B \
0119     (m340_uart_config[UART_CHANNEL_B].rx_mode==UART_FIFO_FULL && \
0120     m340_uart_config[UART_CHANNEL_B].enable && \
0121     m340_uart_config[UART_CHANNEL_B].mode==UART_INTERRUPTS)
0122 
0123 /*
0124  * Fifo_Full_benchmark_timer_initialize
0125  *
0126  * initialize Timer 1 for FIFO full mode
0127  */
0128 void Fifo_Full_benchmark_timer_initialize (void)
0129 {
0130   float max_baud_rate;
0131   int prescaler_output_tap = -1;
0132   int nb_of_clock_ticks = 0;
0133   rtems_isr_entry old_handler;
0134 
0135   /*
0136    *  USE TIMER 1 for UART FIFO FULL mode
0137    */
0138   if ( Fifo_Full_on_A || Fifo_Full_on_B ) {
0139     /* Disable the timer */
0140     TCR1 &= ~m340_SWR;
0141 
0142     /* Reset the interrupts */
0143     TSR1 &= ~(m340_TO | m340_TG | m340_TC);
0144 
0145     /* Init the stop bit for normal operation, ignore FREEZE, user privileges,
0146      * set interrupt arbitration.
0147      */
0148     TMCR1 = TIMER1_INTERRUPT_ARBITRATION;
0149 
0150     /* interrupt priority level and interrupt vector */
0151     TIR1 = TIMER1_VECTOR | (TIMER1_IRQ_LEVEL << 8);
0152 
0153     /* compute prescaler */
0154     if ( Fifo_Full_on_A && Fifo_Full_on_B) {
0155       max_baud_rate = max(
0156         m340_uart_config[UART_CHANNEL_A].rx_baudrate,
0157         m340_uart_config[UART_CHANNEL_B].rx_baudrate
0158       );
0159     } else if ( Fifo_Full_on_A ) {
0160       max_baud_rate = m340_uart_config[UART_CHANNEL_A].rx_baudrate;
0161     } else
0162       max_baud_rate = m340_uart_config[UART_CHANNEL_B].rx_baudrate;
0163 
0164     /* find out config */
0165     nb_of_clock_ticks = (10/max_baud_rate)*(CLOCK_SPEED*1000000)*1.2;
0166     if (nb_of_clock_ticks < 0xFFFF) {
0167       preload = nb_of_clock_ticks;
0168       prescaler_output_tap = -1;
0169     } else if (nb_of_clock_ticks/2 < 0xFFFF) {
0170       preload = nb_of_clock_ticks/2;
0171       prescaler_output_tap = m340_Divide_by_2;
0172     } else if (nb_of_clock_ticks/4 < 0xFFFF) {
0173       preload = nb_of_clock_ticks/4;
0174       prescaler_output_tap = m340_Divide_by_4;
0175     } else if (nb_of_clock_ticks/8 < 0xFFFF) {
0176       preload = nb_of_clock_ticks/8;
0177       prescaler_output_tap = m340_Divide_by_16;
0178     } else if (nb_of_clock_ticks/16 < 0xFFFF) {
0179       preload = nb_of_clock_ticks/16;
0180       prescaler_output_tap = m340_Divide_by_16;
0181     } else if (nb_of_clock_ticks/32 < 0xFFFF) {
0182       preload = nb_of_clock_ticks/32;
0183       prescaler_output_tap = m340_Divide_by_32;
0184     } else if (nb_of_clock_ticks/64 < 0xFFFF) {
0185       preload = nb_of_clock_ticks/64;
0186       prescaler_output_tap = m340_Divide_by_64;
0187     } else if (nb_of_clock_ticks/128 < 0xFFFF) {
0188       preload = nb_of_clock_ticks/128;
0189       prescaler_output_tap = m340_Divide_by_128;
0190     } else if (nb_of_clock_ticks/256 < 0xFFFF) {
0191       preload = nb_of_clock_ticks/256;
0192       prescaler_output_tap = m340_Divide_by_256;
0193     }
0194 
0195     /* Input Capture/Output Compare (ICOC) */
0196     TCR1 = m340_SWR | m340_TO_Enabled | m340_ICOC;
0197     if (prescaler_output_tap!=-1) TCR1 |= prescaler_output_tap | m340_PSE;
0198 
0199     /* install interrupt vector */
0200     rtems_interrupt_catch(InterruptHandler, TIMER1_VECTOR, &old_handler);
0201 
0202   } /* fifo full mode on a uart */
0203 
0204   /* install routines */
0205   if ( Fifo_Full_on_A ) {
0206     Restart_Check_A_Timer     = __Restart_Check_Timer;
0207     Restart_Fifo_Full_A_Timer = __Restart_Fifo_Full_Timer;
0208   } else {
0209     Restart_Check_A_Timer     = __do_nothing;
0210     Restart_Fifo_Full_A_Timer = __do_nothing;
0211   }
0212 
0213   if ( Fifo_Full_on_B ) {
0214     Restart_Check_B_Timer     = __Restart_Check_Timer;
0215     Restart_Fifo_Full_B_Timer = __Restart_Fifo_Full_Timer;
0216   } else {
0217     Restart_Check_B_Timer     = __do_nothing;
0218     Restart_Fifo_Full_B_Timer = __do_nothing;
0219   }
0220 
0221   /* start checking timer */
0222   Restart_Check_A_Timer();
0223   Restart_Check_B_Timer();
0224 }
0225 
0226 /*
0227  * benchmark_timer_initialize
0228  *
0229  * init Timer for timing test suites
0230  */
0231 void benchmark_timer_initialize (void)
0232 {
0233   /* Disable the timer */
0234   TCR2 &= ~m340_SWR;
0235 
0236   /* Reset the interrupts */
0237   TSR2 &= ~(m340_TO | m340_TG | m340_TC);
0238 
0239   /* Init the stop bit for normal operation, ignore FREEZE, user privileges,
0240      set interrupt arbitration */
0241   TMCR1 = TIMER2_INTERRUPT_ARBITRATION;
0242 
0243   /* interrupt priority level and interrupt vector */
0244   TIR1 = TIMER2_VECTOR | (TIMER2_IRQ_LEVEL << 8);
0245 
0246   /* Init the stop bit for normal operation, ignore FREEZE, user privileges,
0247      set interrupt arbitration */
0248   TMCR2 = TIMER2_INTERRUPT_ARBITRATION;
0249 
0250   /* Preload register 1 */
0251   WPREL21 = 0xFFFF;
0252 
0253   /* Input Capture/Output Compare (ICOC) */
0254   TCR2 = m340_SWR | m340_ICOC | m340_PSE | m340_Divide_by_16 | m340_CPE;
0255 }
0256 
0257 /*
0258  * benchmark_timer_read
0259  *
0260  * Return timer value in microsecond units
0261  */
0262 uint32_t benchmark_timer_read (void)
0263 {
0264  /* there's CLOCK_SPEED / 16 micro seconds between two timer
0265   * register decrements.
0266   */
0267  return (((0xFFFF - TCNTR2) * CLOCK_SPEED) / 16);
0268 }
0269 
0270 /*
0271  * benchmark_timer_disable_subtracting_average_overhead
0272  */
0273 void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
0274 {
0275 }