linux/arch/mn10300/kernel/mn10300-serial-low.S
<<
>>
Prefs
   1###############################################################################
   2#
   3# Virtual DMA driver for MN10300 serial ports
   4#
   5# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   6# Written by David Howells (dhowells@redhat.com)
   7#
   8# This program is free software; you can redistribute it and/or
   9# modify it under the terms of the GNU General Public Licence
  10# as published by the Free Software Foundation; either version
  11# 2 of the Licence, or (at your option) any later version.
  12#
  13###############################################################################
  14#include <linux/sys.h>
  15#include <linux/linkage.h>
  16#include <asm/page.h>
  17#include <asm/smp.h>
  18#include <asm/cpu-regs.h>
  19#include <asm/frame.inc>
  20#include <asm/timer-regs.h>
  21#include <proc/cache.h>
  22#include <unit/timex.h>
  23#include "mn10300-serial.h"
  24
  25#define SCxCTR  0x00
  26#define SCxICR  0x04
  27#define SCxTXB  0x08
  28#define SCxRXB  0x09
  29#define SCxSTR  0x0c
  30#define SCxTIM  0x0d
  31
  32        .text
  33
  34###############################################################################
  35#
  36# serial port interrupt virtual DMA entry point
  37# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
  38#
  39###############################################################################
  40        .balign L1_CACHE_BYTES
  41ENTRY(mn10300_serial_vdma_interrupt)
  42#       or      EPSW_IE,psw                     # permit overriding by
  43                                                # debugging interrupts
  44        movm    [d2,d3,a2,a3,exreg0],(sp)
  45
  46        movhu   (IAGR),a2                       # see if which interrupt is
  47                                                # pending
  48        and     IAGR_GN,a2
  49        add     a2,a2
  50        add     mn10300_serial_int_tbl,a2
  51
  52        mov     (a2+),a3
  53        mov     (__iobase,a3),e2
  54        mov     (a2),a2
  55        jmp     (a2)
  56
  57###############################################################################
  58#
  59# serial port receive interrupt virtual DMA entry point
  60# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
  61# - stores data/status byte pairs in the ring buffer
  62# - induces a scheduler tick timer interrupt when done, which we then subvert
  63# on entry:
  64#       A3      struct mn10300_serial_port *
  65#       E2      I/O port base
  66#
  67###############################################################################
  68ENTRY(mn10300_serial_vdma_rx_handler)
  69        mov     (__rx_icr,a3),e3
  70        mov     GxICR_DETECT,d2
  71        movbu   d2,(e3)                         # ACK the interrupt
  72        movhu   (e3),d2                         # flush
  73
  74        mov     (__rx_inp,a3),d3
  75        mov     d3,a2
  76        add     2,d3
  77        and     MNSC_BUFFER_SIZE-1,d3
  78        mov     (__rx_outp,a3),d2
  79        cmp     d3,d2
  80        beq     mnsc_vdma_rx_overflow
  81
  82        mov     (__rx_buffer,a3),d2
  83        add     d2,a2
  84        movhu   (SCxSTR,e2),d2
  85        movbu   d2,(1,a2)
  86        movbu   (SCxRXB,e2),d2
  87        movbu   d2,(a2)
  88        mov     d3,(__rx_inp,a3)
  89        bset    MNSCx_RX_AVAIL,(__intr_flags,a3)
  90
  91mnsc_vdma_rx_done:
  92        mov     (__tm_icr,a3),a2
  93        mov     GxICR_LEVEL_6|GxICR_ENABLE|GxICR_REQUEST|GxICR_DETECT,d2
  94        movhu   d2,(a2)                         # request a slow interrupt
  95        movhu   (a2),d2                         # flush
  96
  97        movm    (sp),[d2,d3,a2,a3,exreg0]
  98        rti
  99
 100mnsc_vdma_rx_overflow:
 101        bset    MNSCx_RX_OVERF,(__intr_flags,a3)
 102        bra     mnsc_vdma_rx_done
 103
 104###############################################################################
 105#
 106# serial port transmit interrupt virtual DMA entry point
 107# - intended to run at interrupt priority 1 (not affected by local_irq_disable)
 108# - retrieves data bytes from the ring buffer and passes them to the serial port
 109# - induces a scheduler tick timer interrupt when done, which we then subvert
 110#       A3      struct mn10300_serial_port *
 111#       E2      I/O port base
 112#
 113###############################################################################
 114        .balign L1_CACHE_BYTES
 115ENTRY(mn10300_serial_vdma_tx_handler)
 116        mov     (__tx_icr,a3),e3
 117        mov     GxICR_DETECT,d2
 118        movbu   d2,(e3)                 # ACK the interrupt
 119        movhu   (e3),d2                 # flush
 120
 121        btst    0x01,(__tx_break,a3)    # handle transmit break request
 122        bne     mnsc_vdma_tx_break
 123
 124        movbu   (SCxSTR,e2),d2          # don't try and transmit a char if the
 125                                        # buffer is not empty
 126        btst    SC01STR_TBF,d2          # (may have tried to jumpstart)
 127        bne     mnsc_vdma_tx_noint
 128
 129        movbu   (__tx_xchar,a3),d2      # handle hi-pri XON/XOFF
 130        or      d2,d2
 131        bne     mnsc_vdma_tx_xchar
 132
 133        mov     (__uart_state,a3),a2    # see if the TTY Tx queue has anything in it
 134        mov     (__xmit_tail,a2),d3
 135        mov     (__xmit_head,a2),d2
 136        cmp     d3,d2
 137        beq     mnsc_vdma_tx_empty
 138
 139        mov     (__xmit_buffer,a2),d2   # get a char from the buffer and
 140                                        # transmit it
 141        movbu   (d3,d2),d2
 142        movbu   d2,(SCxTXB,e2)          # Tx
 143
 144        inc     d3                      # advance the buffer pointer
 145        and     __UART_XMIT_SIZE-1,d3
 146        mov     (__xmit_head,a2),d2
 147        mov     d3,(__xmit_tail,a2)
 148
 149        sub     d3,d2                   # see if we've written everything
 150        beq     mnsc_vdma_tx_empty
 151
 152        and     __UART_XMIT_SIZE-1,d2   # see if we just made a hole
 153        cmp     __UART_XMIT_SIZE-2,d2
 154        beq     mnsc_vdma_tx_made_hole
 155
 156mnsc_vdma_tx_done:
 157        mov     (__tm_icr,a3),a2
 158        mov     GxICR_LEVEL_6|GxICR_ENABLE|GxICR_REQUEST|GxICR_DETECT,d2
 159        movhu   d2,(a2)                 # request a slow interrupt
 160        movhu   (a2),d2                 # flush
 161
 162mnsc_vdma_tx_noint:
 163        movm    (sp),[d2,d3,a2,a3,exreg0]
 164        rti
 165
 166mnsc_vdma_tx_empty:
 167        mov     +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
 168        movhu   d2,(e3)                 # disable the interrupt
 169        movhu   (e3),d2                 # flush
 170
 171        bset    MNSCx_TX_EMPTY,(__intr_flags,a3)
 172        bra     mnsc_vdma_tx_done
 173
 174mnsc_vdma_tx_break:
 175        movhu   (SCxCTR,e2),d2          # turn on break mode
 176        or      SC01CTR_BKE,d2
 177        movhu   d2,(SCxCTR,e2)
 178        mov     +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
 179        movhu   d2,(e3)                 # disable transmit interrupts on this
 180                                        # channel
 181        movhu   (e3),d2                 # flush
 182        bra     mnsc_vdma_tx_noint
 183
 184mnsc_vdma_tx_xchar:
 185        bclr    0xff,(__tx_xchar,a3)
 186        movbu   d2,(SCxTXB,e2)
 187        bra     mnsc_vdma_tx_done
 188
 189mnsc_vdma_tx_made_hole:
 190        bset    MNSCx_TX_SPACE,(__intr_flags,a3)
 191        bra     mnsc_vdma_tx_done
 192