root/arch/m68k/atari/ataints.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. atari_irq_startup
  2. atari_irq_shutdown
  3. atari_irq_enable
  4. atari_irq_disable
  5. mfp_timer_d_handler
  6. atari_mfptimer_enable
  7. atari_mfptimer_disable
  8. atari_ethernat_startup
  9. atari_ethernat_enable
  10. atari_ethernat_disable
  11. atari_ethernat_shutdown
  12. atari_init_IRQ
  13. atari_register_vme_int
  14. atari_unregister_vme_int

   1 /*
   2  * arch/m68k/atari/ataints.c -- Atari Linux interrupt handling code
   3  *
   4  * 5/2/94 Roman Hodek:
   5  *  Added support for TT interrupts; setup for TT SCU (may someone has
   6  *  twiddled there and we won't get the right interrupts :-()
   7  *
   8  *  Major change: The device-independent code in m68k/ints.c didn't know
   9  *  about non-autovec ints yet. It hardcoded the number of possible ints to
  10  *  7 (IRQ1...IRQ7). But the Atari has lots of non-autovec ints! I made the
  11  *  number of possible ints a constant defined in interrupt.h, which is
  12  *  47 for the Atari. So we can call request_irq() for all Atari interrupts
  13  *  just the normal way. Additionally, all vectors >= 48 are initialized to
  14  *  call trap() instead of inthandler(). This must be changed here, too.
  15  *
  16  * 1995-07-16 Lars Brinkhoff <f93labr@dd.chalmers.se>:
  17  *  Corrected a bug in atari_add_isr() which rejected all SCC
  18  *  interrupt sources if there were no TT MFP!
  19  *
  20  * 12/13/95: New interface functions atari_level_triggered_int() and
  21  *  atari_register_vme_int() as support for level triggered VME interrupts.
  22  *
  23  * 02/12/96: (Roman)
  24  *  Total rewrite of Atari interrupt handling, for new scheme see comments
  25  *  below.
  26  *
  27  * 1996-09-03 lars brinkhoff <f93labr@dd.chalmers.se>:
  28  *  Added new function atari_unregister_vme_int(), and
  29  *  modified atari_register_vme_int() as well as IS_VALID_INTNO()
  30  *  to work with it.
  31  *
  32  * This file is subject to the terms and conditions of the GNU General Public
  33  * License.  See the file COPYING in the main directory of this archive
  34  * for more details.
  35  *
  36  */
  37 
  38 #include <linux/types.h>
  39 #include <linux/kernel.h>
  40 #include <linux/kernel_stat.h>
  41 #include <linux/init.h>
  42 #include <linux/seq_file.h>
  43 #include <linux/module.h>
  44 #include <linux/irq.h>
  45 
  46 #include <asm/traps.h>
  47 
  48 #include <asm/atarihw.h>
  49 #include <asm/atariints.h>
  50 #include <asm/atari_stdma.h>
  51 #include <asm/irq.h>
  52 #include <asm/entry.h>
  53 #include <asm/io.h>
  54 
  55 
  56 /*
  57  * Atari interrupt handling scheme:
  58  * --------------------------------
  59  *
  60  * All interrupt source have an internal number (defined in
  61  * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
  62  * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
  63  * be allocated by atari_register_vme_int().
  64  */
  65 
  66 /*
  67  * Bitmap for free interrupt vector numbers
  68  * (new vectors starting from 0x70 can be allocated by
  69  * atari_register_vme_int())
  70  */
  71 static int free_vme_vec_bitmap;
  72 
  73 /* GK:
  74  * HBL IRQ handler for Falcon. Nobody needs it :-)
  75  * ++andreas: raise ipl to disable further HBLANK interrupts.
  76  */
  77 asmlinkage void falcon_hblhandler(void);
  78 asm(".text\n"
  79 __ALIGN_STR "\n\t"
  80 "falcon_hblhandler:\n\t"
  81         "orw    #0x200,%sp@\n\t"        /* set saved ipl to 2 */
  82         "rte");
  83 
  84 extern void atari_microwire_cmd(int cmd);
  85 
  86 static unsigned int atari_irq_startup(struct irq_data *data)
  87 {
  88         unsigned int irq = data->irq;
  89 
  90         m68k_irq_startup(data);
  91         atari_turnon_irq(irq);
  92         atari_enable_irq(irq);
  93         return 0;
  94 }
  95 
  96 static void atari_irq_shutdown(struct irq_data *data)
  97 {
  98         unsigned int irq = data->irq;
  99 
 100         atari_disable_irq(irq);
 101         atari_turnoff_irq(irq);
 102         m68k_irq_shutdown(data);
 103 
 104         if (irq == IRQ_AUTO_4)
 105             vectors[VEC_INT4] = falcon_hblhandler;
 106 }
 107 
 108 static void atari_irq_enable(struct irq_data *data)
 109 {
 110         atari_enable_irq(data->irq);
 111 }
 112 
 113 static void atari_irq_disable(struct irq_data *data)
 114 {
 115         atari_disable_irq(data->irq);
 116 }
 117 
 118 static struct irq_chip atari_irq_chip = {
 119         .name           = "atari",
 120         .irq_startup    = atari_irq_startup,
 121         .irq_shutdown   = atari_irq_shutdown,
 122         .irq_enable     = atari_irq_enable,
 123         .irq_disable    = atari_irq_disable,
 124 };
 125 
 126 /*
 127  * ST-MFP timer D chained interrupts - each driver gets its own timer
 128  * interrupt instance.
 129  */
 130 
 131 struct mfptimerbase {
 132         volatile struct MFP *mfp;
 133         unsigned char mfp_mask, mfp_data;
 134         unsigned short int_mask;
 135         int handler_irq, mfptimer_irq, server_irq;
 136         char *name;
 137 } stmfp_base = {
 138         .mfp            = &st_mfp,
 139         .int_mask       = 0x0,
 140         .handler_irq    = IRQ_MFP_TIMD,
 141         .mfptimer_irq   = IRQ_MFP_TIMER1,
 142         .name           = "MFP Timer D"
 143 };
 144 
 145 static irqreturn_t mfp_timer_d_handler(int irq, void *dev_id)
 146 {
 147         struct mfptimerbase *base = dev_id;
 148         int mach_irq;
 149         unsigned char ints;
 150 
 151         mach_irq = base->mfptimer_irq;
 152         ints = base->int_mask;
 153         for (; ints; mach_irq++, ints >>= 1) {
 154                 if (ints & 1)
 155                         generic_handle_irq(mach_irq);
 156         }
 157         return IRQ_HANDLED;
 158 }
 159 
 160 
 161 static void atari_mfptimer_enable(struct irq_data *data)
 162 {
 163         int mfp_num = data->irq - IRQ_MFP_TIMER1;
 164         stmfp_base.int_mask |= 1 << mfp_num;
 165         atari_enable_irq(IRQ_MFP_TIMD);
 166 }
 167 
 168 static void atari_mfptimer_disable(struct irq_data *data)
 169 {
 170         int mfp_num = data->irq - IRQ_MFP_TIMER1;
 171         stmfp_base.int_mask &= ~(1 << mfp_num);
 172         if (!stmfp_base.int_mask)
 173                 atari_disable_irq(IRQ_MFP_TIMD);
 174 }
 175 
 176 static struct irq_chip atari_mfptimer_chip = {
 177         .name           = "timer_d",
 178         .irq_enable     = atari_mfptimer_enable,
 179         .irq_disable    = atari_mfptimer_disable,
 180 };
 181 
 182 
 183 /*
 184  * EtherNAT CPLD interrupt handling
 185  * CPLD interrupt register is at phys. 0x80000023
 186  * Need this mapped in at interrupt startup time
 187  * Possibly need this mapped on demand anyway -
 188  * EtherNAT USB driver needs to disable IRQ before
 189  * startup!
 190  */
 191 
 192 static unsigned char *enat_cpld;
 193 
 194 static unsigned int atari_ethernat_startup(struct irq_data *data)
 195 {
 196         int enat_num = 140 - data->irq + 1;
 197 
 198         m68k_irq_startup(data);
 199         /*
 200         * map CPLD interrupt register
 201         */
 202         if (!enat_cpld)
 203                 enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
 204         /*
 205          * do _not_ enable the USB chip interrupt here - causes interrupt storm
 206          * and triggers dead interrupt watchdog
 207          * Need to reset the USB chip to a sane state in early startup before
 208          * removing this hack
 209          */
 210         if (enat_num == 1)
 211                 *enat_cpld |= 1 << enat_num;
 212 
 213         return 0;
 214 }
 215 
 216 static void atari_ethernat_enable(struct irq_data *data)
 217 {
 218         int enat_num = 140 - data->irq + 1;
 219         /*
 220         * map CPLD interrupt register
 221         */
 222         if (!enat_cpld)
 223                 enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
 224         *enat_cpld |= 1 << enat_num;
 225 }
 226 
 227 static void atari_ethernat_disable(struct irq_data *data)
 228 {
 229         int enat_num = 140 - data->irq + 1;
 230         /*
 231         * map CPLD interrupt register
 232         */
 233         if (!enat_cpld)
 234                 enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
 235         *enat_cpld &= ~(1 << enat_num);
 236 }
 237 
 238 static void atari_ethernat_shutdown(struct irq_data *data)
 239 {
 240         int enat_num = 140 - data->irq + 1;
 241         if (enat_cpld) {
 242                 *enat_cpld &= ~(1 << enat_num);
 243                 iounmap(enat_cpld);
 244                 enat_cpld = NULL;
 245         }
 246 }
 247 
 248 static struct irq_chip atari_ethernat_chip = {
 249         .name           = "ethernat",
 250         .irq_startup    = atari_ethernat_startup,
 251         .irq_shutdown   = atari_ethernat_shutdown,
 252         .irq_enable     = atari_ethernat_enable,
 253         .irq_disable    = atari_ethernat_disable,
 254 };
 255 
 256 /*
 257  * void atari_init_IRQ (void)
 258  *
 259  * Parameters:  None
 260  *
 261  * Returns:     Nothing
 262  *
 263  * This function should be called during kernel startup to initialize
 264  * the atari IRQ handling routines.
 265  */
 266 
 267 void __init atari_init_IRQ(void)
 268 {
 269         m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER);
 270         m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1,
 271                                   NUM_ATARI_SOURCES - 1);
 272 
 273         /* Initialize the MFP(s) */
 274 
 275 #ifdef ATARI_USE_SOFTWARE_EOI
 276         st_mfp.vec_adr  = 0x48; /* Software EOI-Mode */
 277 #else
 278         st_mfp.vec_adr  = 0x40; /* Automatic EOI-Mode */
 279 #endif
 280         st_mfp.int_en_a = 0x00; /* turn off MFP-Ints */
 281         st_mfp.int_en_b = 0x00;
 282         st_mfp.int_mk_a = 0xff; /* no Masking */
 283         st_mfp.int_mk_b = 0xff;
 284 
 285         if (ATARIHW_PRESENT(TT_MFP)) {
 286 #ifdef ATARI_USE_SOFTWARE_EOI
 287                 tt_mfp.vec_adr  = 0x58;         /* Software EOI-Mode */
 288 #else
 289                 tt_mfp.vec_adr  = 0x50;         /* Automatic EOI-Mode */
 290 #endif
 291                 tt_mfp.int_en_a = 0x00;         /* turn off MFP-Ints */
 292                 tt_mfp.int_en_b = 0x00;
 293                 tt_mfp.int_mk_a = 0xff;         /* no Masking */
 294                 tt_mfp.int_mk_b = 0xff;
 295         }
 296 
 297         if (ATARIHW_PRESENT(SCC) && !atari_SCC_reset_done) {
 298                 atari_scc.cha_a_ctrl = 9;
 299                 MFPDELAY();
 300                 atari_scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */
 301         }
 302 
 303         if (ATARIHW_PRESENT(SCU)) {
 304                 /* init the SCU if present */
 305                 tt_scu.sys_mask = 0x10;         /* enable VBL (for the cursor) and
 306                                                                          * disable HSYNC interrupts (who
 307                                                                          * needs them?)  MFP and SCC are
 308                                                                          * enabled in VME mask
 309                                                                          */
 310                 tt_scu.vme_mask = 0x60;         /* enable MFP and SCC ints */
 311         } else {
 312                 /* If no SCU and no Hades, the HSYNC interrupt needs to be
 313                  * disabled this way. (Else _inthandler in kernel/sys_call.S
 314                  * gets overruns)
 315                  */
 316 
 317                 vectors[VEC_INT2] = falcon_hblhandler;
 318                 vectors[VEC_INT4] = falcon_hblhandler;
 319         }
 320 
 321         if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
 322                 /* Initialize the LM1992 Sound Controller to enable
 323                    the PSG sound.  This is misplaced here, it should
 324                    be in an atasound_init(), that doesn't exist yet. */
 325                 atari_microwire_cmd(MW_LM1992_PSG_HIGH);
 326         }
 327 
 328         stdma_init();
 329 
 330         /* Initialize the PSG: all sounds off, both ports output */
 331         sound_ym.rd_data_reg_sel = 7;
 332         sound_ym.wd_data = 0xff;
 333 
 334         m68k_setup_irq_controller(&atari_mfptimer_chip, handle_simple_irq,
 335                                   IRQ_MFP_TIMER1, 8);
 336 
 337         irq_set_status_flags(IRQ_MFP_TIMER1, IRQ_IS_POLLED);
 338         irq_set_status_flags(IRQ_MFP_TIMER2, IRQ_IS_POLLED);
 339 
 340         /* prepare timer D data for use as poll interrupt */
 341         /* set Timer D data Register - needs to be > 0 */
 342         st_mfp.tim_dt_d = 254;  /* < 100 Hz */
 343         /* start timer D, div = 1:100 */
 344         st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 0xf0) | 0x6;
 345 
 346         /* request timer D dispatch handler */
 347         if (request_irq(IRQ_MFP_TIMD, mfp_timer_d_handler, IRQF_SHARED,
 348                         stmfp_base.name, &stmfp_base))
 349                 pr_err("Couldn't register %s interrupt\n", stmfp_base.name);
 350 
 351         /*
 352          * EtherNAT ethernet / USB interrupt handlers
 353          */
 354 
 355         m68k_setup_irq_controller(&atari_ethernat_chip, handle_simple_irq,
 356                                   139, 2);
 357 }
 358 
 359 
 360 /*
 361  * atari_register_vme_int() returns the number of a free interrupt vector for
 362  * hardware with a programmable int vector (probably a VME board).
 363  */
 364 
 365 unsigned int atari_register_vme_int(void)
 366 {
 367         int i;
 368 
 369         for (i = 0; i < 32; i++)
 370                 if ((free_vme_vec_bitmap & (1 << i)) == 0)
 371                         break;
 372 
 373         if (i == 16)
 374                 return 0;
 375 
 376         free_vme_vec_bitmap |= 1 << i;
 377         return VME_SOURCE_BASE + i;
 378 }
 379 EXPORT_SYMBOL(atari_register_vme_int);
 380 
 381 
 382 void atari_unregister_vme_int(unsigned int irq)
 383 {
 384         if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
 385                 irq -= VME_SOURCE_BASE;
 386                 free_vme_vec_bitmap &= ~(1 << irq);
 387         }
 388 }
 389 EXPORT_SYMBOL(atari_unregister_vme_int);
 390 
 391 

/* [<][>][^][v][top][bottom][index][help] */