Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * sun4m irq support
0004  *
0005  *  djhr: Hacked out of irq.c into a CPU dependent version.
0006  *
0007  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
0008  *  Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
0009  *  Copyright (C) 1995 Pete A. Zaitcev (zaitcev@yahoo.com)
0010  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
0011  */
0012 
0013 #include <linux/slab.h>
0014 #include <linux/sched/debug.h>
0015 #include <linux/pgtable.h>
0016 
0017 #include <asm/timer.h>
0018 #include <asm/traps.h>
0019 #include <asm/irq.h>
0020 #include <asm/io.h>
0021 #include <asm/cacheflush.h>
0022 
0023 #include "irq.h"
0024 #include "kernel.h"
0025 
0026 /* Sample sun4m IRQ layout:
0027  *
0028  * 0x22 - Power
0029  * 0x24 - ESP SCSI
0030  * 0x26 - Lance ethernet
0031  * 0x2b - Floppy
0032  * 0x2c - Zilog uart
0033  * 0x32 - SBUS level 0
0034  * 0x33 - Parallel port, SBUS level 1
0035  * 0x35 - SBUS level 2
0036  * 0x37 - SBUS level 3
0037  * 0x39 - Audio, Graphics card, SBUS level 4
0038  * 0x3b - SBUS level 5
0039  * 0x3d - SBUS level 6
0040  *
0041  * Each interrupt source has a mask bit in the interrupt registers.
0042  * When the mask bit is set, this blocks interrupt deliver.  So you
0043  * clear the bit to enable the interrupt.
0044  *
0045  * Interrupts numbered less than 0x10 are software triggered interrupts
0046  * and unused by Linux.
0047  *
0048  * Interrupt level assignment on sun4m:
0049  *
0050  *  level       source
0051  * ------------------------------------------------------------
0052  *    1     softint-1
0053  *    2     softint-2, VME/SBUS level 1
0054  *    3     softint-3, VME/SBUS level 2
0055  *    4     softint-4, onboard SCSI
0056  *    5     softint-5, VME/SBUS level 3
0057  *    6     softint-6, onboard ETHERNET
0058  *    7     softint-7, VME/SBUS level 4
0059  *    8     softint-8, onboard VIDEO
0060  *    9     softint-9, VME/SBUS level 5, Module Interrupt
0061  *   10     softint-10, system counter/timer
0062  *   11     softint-11, VME/SBUS level 6, Floppy
0063  *   12     softint-12, Keyboard/Mouse, Serial
0064  *   13     softint-13, VME/SBUS level 7, ISDN Audio
0065  *   14     softint-14, per-processor counter/timer
0066  *   15     softint-15, Asynchronous Errors (broadcast)
0067  *
0068  * Each interrupt source is masked distinctly in the sun4m interrupt
0069  * registers.  The PIL level alone is therefore ambiguous, since multiple
0070  * interrupt sources map to a single PIL.
0071  *
0072  * This ambiguity is resolved in the 'intr' property for device nodes
0073  * in the OF device tree.  Each 'intr' property entry is composed of
0074  * two 32-bit words.  The first word is the IRQ priority value, which
0075  * is what we're intersted in.  The second word is the IRQ vector, which
0076  * is unused.
0077  *
0078  * The low 4 bits of the IRQ priority indicate the PIL, and the upper
0079  * 4 bits indicate onboard vs. SBUS leveled vs. VME leveled.  0x20
0080  * means onboard, 0x30 means SBUS leveled, and 0x40 means VME leveled.
0081  *
0082  * For example, an 'intr' IRQ priority value of 0x24 is onboard SCSI
0083  * whereas a value of 0x33 is SBUS level 2.  Here are some sample
0084  * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and
0085  * Tadpole S3 GX systems.
0086  *
0087  * esp:     0x24    onboard ESP SCSI
0088  * le:      0x26    onboard Lance ETHERNET
0089  * p9100:   0x32    SBUS level 1 P9100 video
0090  * bpp:     0x33    SBUS level 2 BPP parallel port device
0091  * DBRI:    0x39    SBUS level 5 DBRI ISDN audio
0092  * SUNW,leo:    0x39    SBUS level 5 LEO video
0093  * pcmcia:  0x3b    SBUS level 6 PCMCIA controller
0094  * uctrl:   0x3b    SBUS level 6 UCTRL device
0095  * modem:   0x3d    SBUS level 7 MODEM
0096  * zs:      0x2c    onboard keyboard/mouse/serial
0097  * floppy:  0x2b    onboard Floppy
0098  * power:   0x22    onboard power device (XXX unknown mask bit XXX)
0099  */
0100 
0101 
0102 /* Code in entry.S needs to get at these register mappings.  */
0103 struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
0104 struct sun4m_irq_global __iomem *sun4m_irq_global;
0105 
0106 struct sun4m_handler_data {
0107     bool    percpu;
0108     long    mask;
0109 };
0110 
0111 /* Dave Redman (djhr@tadpole.co.uk)
0112  * The sun4m interrupt registers.
0113  */
0114 #define SUN4M_INT_ENABLE    0x80000000
0115 #define SUN4M_INT_E14       0x00000080
0116 #define SUN4M_INT_E10       0x00080000
0117 
0118 #define SUN4M_INT_MASKALL   0x80000000    /* mask all interrupts */
0119 #define SUN4M_INT_MODULE_ERR    0x40000000    /* module error */
0120 #define SUN4M_INT_M2S_WRITE_ERR 0x20000000    /* write buffer error */
0121 #define SUN4M_INT_ECC_ERR   0x10000000    /* ecc memory error */
0122 #define SUN4M_INT_VME_ERR   0x08000000    /* vme async error */
0123 #define SUN4M_INT_FLOPPY    0x00400000    /* floppy disk */
0124 #define SUN4M_INT_MODULE    0x00200000    /* module interrupt */
0125 #define SUN4M_INT_VIDEO     0x00100000    /* onboard video */
0126 #define SUN4M_INT_REALTIME  0x00080000    /* system timer */
0127 #define SUN4M_INT_SCSI      0x00040000    /* onboard scsi */
0128 #define SUN4M_INT_AUDIO     0x00020000    /* audio/isdn */
0129 #define SUN4M_INT_ETHERNET  0x00010000    /* onboard ethernet */
0130 #define SUN4M_INT_SERIAL    0x00008000    /* serial ports */
0131 #define SUN4M_INT_KBDMS     0x00004000    /* keyboard/mouse */
0132 #define SUN4M_INT_SBUSBITS  0x00003F80    /* sbus int bits */
0133 #define SUN4M_INT_VMEBITS   0x0000007F    /* vme int bits */
0134 
0135 #define SUN4M_INT_ERROR     (SUN4M_INT_MODULE_ERR |    \
0136                  SUN4M_INT_M2S_WRITE_ERR | \
0137                  SUN4M_INT_ECC_ERR |       \
0138                  SUN4M_INT_VME_ERR)
0139 
0140 #define SUN4M_INT_SBUS(x)   (1 << (x+7))
0141 #define SUN4M_INT_VME(x)    (1 << (x))
0142 
0143 /* Interrupt levels used by OBP */
0144 #define OBP_INT_LEVEL_SOFT  0x10
0145 #define OBP_INT_LEVEL_ONBOARD   0x20
0146 #define OBP_INT_LEVEL_SBUS  0x30
0147 #define OBP_INT_LEVEL_VME   0x40
0148 
0149 #define SUN4M_TIMER_IRQ         (OBP_INT_LEVEL_ONBOARD | 10)
0150 #define SUN4M_PROFILE_IRQ       (OBP_INT_LEVEL_ONBOARD | 14)
0151 
0152 static unsigned long sun4m_imask[0x50] = {
0153     /* 0x00 - SMP */
0154     0,  SUN4M_SOFT_INT(1),
0155     SUN4M_SOFT_INT(2),  SUN4M_SOFT_INT(3),
0156     SUN4M_SOFT_INT(4),  SUN4M_SOFT_INT(5),
0157     SUN4M_SOFT_INT(6),  SUN4M_SOFT_INT(7),
0158     SUN4M_SOFT_INT(8),  SUN4M_SOFT_INT(9),
0159     SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11),
0160     SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13),
0161     SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15),
0162     /* 0x10 - soft */
0163     0,  SUN4M_SOFT_INT(1),
0164     SUN4M_SOFT_INT(2),  SUN4M_SOFT_INT(3),
0165     SUN4M_SOFT_INT(4),  SUN4M_SOFT_INT(5),
0166     SUN4M_SOFT_INT(6),  SUN4M_SOFT_INT(7),
0167     SUN4M_SOFT_INT(8),  SUN4M_SOFT_INT(9),
0168     SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11),
0169     SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13),
0170     SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15),
0171     /* 0x20 - onboard */
0172     0, 0, 0, 0,
0173     SUN4M_INT_SCSI,  0, SUN4M_INT_ETHERNET, 0,
0174     SUN4M_INT_VIDEO, SUN4M_INT_MODULE,
0175     SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY,
0176     (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS),
0177     SUN4M_INT_AUDIO, SUN4M_INT_E14, SUN4M_INT_MODULE_ERR,
0178     /* 0x30 - sbus */
0179     0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1),
0180     0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3),
0181     0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5),
0182     0, SUN4M_INT_SBUS(6), 0, 0,
0183     /* 0x40 - vme */
0184     0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1),
0185     0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3),
0186     0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5),
0187     0, SUN4M_INT_VME(6), 0, 0
0188 };
0189 
0190 static void sun4m_mask_irq(struct irq_data *data)
0191 {
0192     struct sun4m_handler_data *handler_data;
0193     int cpu = smp_processor_id();
0194 
0195     handler_data = irq_data_get_irq_handler_data(data);
0196     if (handler_data->mask) {
0197         unsigned long flags;
0198 
0199         local_irq_save(flags);
0200         if (handler_data->percpu) {
0201             sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->set);
0202         } else {
0203             sbus_writel(handler_data->mask, &sun4m_irq_global->mask_set);
0204         }
0205         local_irq_restore(flags);
0206     }
0207 }
0208 
0209 static void sun4m_unmask_irq(struct irq_data *data)
0210 {
0211     struct sun4m_handler_data *handler_data;
0212     int cpu = smp_processor_id();
0213 
0214     handler_data = irq_data_get_irq_handler_data(data);
0215     if (handler_data->mask) {
0216         unsigned long flags;
0217 
0218         local_irq_save(flags);
0219         if (handler_data->percpu) {
0220             sbus_writel(handler_data->mask, &sun4m_irq_percpu[cpu]->clear);
0221         } else {
0222             sbus_writel(handler_data->mask, &sun4m_irq_global->mask_clear);
0223         }
0224         local_irq_restore(flags);
0225     }
0226 }
0227 
0228 static unsigned int sun4m_startup_irq(struct irq_data *data)
0229 {
0230     irq_link(data->irq);
0231     sun4m_unmask_irq(data);
0232     return 0;
0233 }
0234 
0235 static void sun4m_shutdown_irq(struct irq_data *data)
0236 {
0237     sun4m_mask_irq(data);
0238     irq_unlink(data->irq);
0239 }
0240 
0241 static struct irq_chip sun4m_irq = {
0242     .name       = "sun4m",
0243     .irq_startup    = sun4m_startup_irq,
0244     .irq_shutdown   = sun4m_shutdown_irq,
0245     .irq_mask   = sun4m_mask_irq,
0246     .irq_unmask = sun4m_unmask_irq,
0247 };
0248 
0249 
0250 static unsigned int sun4m_build_device_irq(struct platform_device *op,
0251                        unsigned int real_irq)
0252 {
0253     struct sun4m_handler_data *handler_data;
0254     unsigned int irq;
0255     unsigned int pil;
0256 
0257     if (real_irq >= OBP_INT_LEVEL_VME) {
0258         prom_printf("Bogus sun4m IRQ %u\n", real_irq);
0259         prom_halt();
0260     }
0261     pil = (real_irq & 0xf);
0262     irq = irq_alloc(real_irq, pil);
0263 
0264     if (irq == 0)
0265         goto out;
0266 
0267     handler_data = irq_get_handler_data(irq);
0268     if (unlikely(handler_data))
0269         goto out;
0270 
0271     handler_data = kzalloc(sizeof(struct sun4m_handler_data), GFP_ATOMIC);
0272     if (unlikely(!handler_data)) {
0273         prom_printf("IRQ: kzalloc(sun4m_handler_data) failed.\n");
0274         prom_halt();
0275     }
0276 
0277     handler_data->mask = sun4m_imask[real_irq];
0278     handler_data->percpu = real_irq < OBP_INT_LEVEL_ONBOARD;
0279     irq_set_chip_and_handler_name(irq, &sun4m_irq,
0280                                   handle_level_irq, "level");
0281     irq_set_handler_data(irq, handler_data);
0282 
0283 out:
0284     return irq;
0285 }
0286 
0287 struct sun4m_timer_percpu {
0288     u32     l14_limit;
0289     u32     l14_count;
0290     u32     l14_limit_noclear;
0291     u32     user_timer_start_stop;
0292 };
0293 
0294 static struct sun4m_timer_percpu __iomem *timers_percpu[SUN4M_NCPUS];
0295 
0296 struct sun4m_timer_global {
0297     u32     l10_limit;
0298     u32     l10_count;
0299     u32     l10_limit_noclear;
0300     u32     reserved;
0301     u32     timer_config;
0302 };
0303 
0304 static struct sun4m_timer_global __iomem *timers_global;
0305 
0306 static void sun4m_clear_clock_irq(void)
0307 {
0308     sbus_readl(&timers_global->l10_limit);
0309 }
0310 
0311 void sun4m_nmi(struct pt_regs *regs)
0312 {
0313     unsigned long afsr, afar, si;
0314 
0315     printk(KERN_ERR "Aieee: sun4m NMI received!\n");
0316     /* XXX HyperSparc hack XXX */
0317     __asm__ __volatile__("mov 0x500, %%g1\n\t"
0318                  "lda [%%g1] 0x4, %0\n\t"
0319                  "mov 0x600, %%g1\n\t"
0320                  "lda [%%g1] 0x4, %1\n\t" :
0321                  "=r" (afsr), "=r" (afar));
0322     printk(KERN_ERR "afsr=%08lx afar=%08lx\n", afsr, afar);
0323     si = sbus_readl(&sun4m_irq_global->pending);
0324     printk(KERN_ERR "si=%08lx\n", si);
0325     if (si & SUN4M_INT_MODULE_ERR)
0326         printk(KERN_ERR "Module async error\n");
0327     if (si & SUN4M_INT_M2S_WRITE_ERR)
0328         printk(KERN_ERR "MBus/SBus async error\n");
0329     if (si & SUN4M_INT_ECC_ERR)
0330         printk(KERN_ERR "ECC memory error\n");
0331     if (si & SUN4M_INT_VME_ERR)
0332         printk(KERN_ERR "VME async error\n");
0333     printk(KERN_ERR "you lose buddy boy...\n");
0334     show_regs(regs);
0335     prom_halt();
0336 }
0337 
0338 void sun4m_unmask_profile_irq(void)
0339 {
0340     unsigned long flags;
0341 
0342     local_irq_save(flags);
0343     sbus_writel(sun4m_imask[SUN4M_PROFILE_IRQ], &sun4m_irq_global->mask_clear);
0344     local_irq_restore(flags);
0345 }
0346 
0347 void sun4m_clear_profile_irq(int cpu)
0348 {
0349     sbus_readl(&timers_percpu[cpu]->l14_limit);
0350 }
0351 
0352 static void sun4m_load_profile_irq(int cpu, unsigned int limit)
0353 {
0354     unsigned int value = limit ? timer_value(limit) : 0;
0355     sbus_writel(value, &timers_percpu[cpu]->l14_limit);
0356 }
0357 
0358 static void __init sun4m_init_timers(void)
0359 {
0360     struct device_node *dp = of_find_node_by_name(NULL, "counter");
0361     int i, err, len, num_cpu_timers;
0362     unsigned int irq;
0363     const u32 *addr;
0364 
0365     if (!dp) {
0366         printk(KERN_ERR "sun4m_init_timers: No 'counter' node.\n");
0367         return;
0368     }
0369 
0370     addr = of_get_property(dp, "address", &len);
0371     of_node_put(dp);
0372     if (!addr) {
0373         printk(KERN_ERR "sun4m_init_timers: No 'address' prop.\n");
0374         return;
0375     }
0376 
0377     num_cpu_timers = (len / sizeof(u32)) - 1;
0378     for (i = 0; i < num_cpu_timers; i++) {
0379         timers_percpu[i] = (void __iomem *)
0380             (unsigned long) addr[i];
0381     }
0382     timers_global = (void __iomem *)
0383         (unsigned long) addr[num_cpu_timers];
0384 
0385     /* Every per-cpu timer works in timer mode */
0386     sbus_writel(0x00000000, &timers_global->timer_config);
0387 
0388 #ifdef CONFIG_SMP
0389     sparc_config.cs_period = SBUS_CLOCK_RATE * 2;  /* 2 seconds */
0390     sparc_config.features |= FEAT_L14_ONESHOT;
0391 #else
0392     sparc_config.cs_period = SBUS_CLOCK_RATE / HZ; /* 1/HZ sec  */
0393     sparc_config.features |= FEAT_L10_CLOCKEVENT;
0394 #endif
0395     sparc_config.features |= FEAT_L10_CLOCKSOURCE;
0396     sbus_writel(timer_value(sparc_config.cs_period),
0397                 &timers_global->l10_limit);
0398 
0399     master_l10_counter = &timers_global->l10_count;
0400 
0401     irq = sun4m_build_device_irq(NULL, SUN4M_TIMER_IRQ);
0402 
0403     err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
0404     if (err) {
0405         printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
0406             err);
0407         return;
0408     }
0409 
0410     for (i = 0; i < num_cpu_timers; i++)
0411         sbus_writel(0, &timers_percpu[i]->l14_limit);
0412     if (num_cpu_timers == 4)
0413         sbus_writel(SUN4M_INT_E14, &sun4m_irq_global->mask_set);
0414 
0415 #ifdef CONFIG_SMP
0416     {
0417         unsigned long flags;
0418         struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
0419 
0420         /* For SMP we use the level 14 ticker, however the bootup code
0421          * has copied the firmware's level 14 vector into the boot cpu's
0422          * trap table, we must fix this now or we get squashed.
0423          */
0424         local_irq_save(flags);
0425         trap_table->inst_one = lvl14_save[0];
0426         trap_table->inst_two = lvl14_save[1];
0427         trap_table->inst_three = lvl14_save[2];
0428         trap_table->inst_four = lvl14_save[3];
0429         local_ops->cache_all();
0430         local_irq_restore(flags);
0431     }
0432 #endif
0433 }
0434 
0435 void __init sun4m_init_IRQ(void)
0436 {
0437     struct device_node *dp = of_find_node_by_name(NULL, "interrupt");
0438     int len, i, mid, num_cpu_iregs;
0439     const u32 *addr;
0440 
0441     if (!dp) {
0442         printk(KERN_ERR "sun4m_init_IRQ: No 'interrupt' node.\n");
0443         return;
0444     }
0445 
0446     addr = of_get_property(dp, "address", &len);
0447     of_node_put(dp);
0448     if (!addr) {
0449         printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n");
0450         return;
0451     }
0452 
0453     num_cpu_iregs = (len / sizeof(u32)) - 1;
0454     for (i = 0; i < num_cpu_iregs; i++) {
0455         sun4m_irq_percpu[i] = (void __iomem *)
0456             (unsigned long) addr[i];
0457     }
0458     sun4m_irq_global = (void __iomem *)
0459         (unsigned long) addr[num_cpu_iregs];
0460 
0461     local_irq_disable();
0462 
0463     sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set);
0464     for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++)
0465         sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear);
0466 
0467     if (num_cpu_iregs == 4)
0468         sbus_writel(0, &sun4m_irq_global->interrupt_target);
0469 
0470     sparc_config.init_timers      = sun4m_init_timers;
0471     sparc_config.build_device_irq = sun4m_build_device_irq;
0472     sparc_config.clock_rate       = SBUS_CLOCK_RATE;
0473     sparc_config.clear_clock_irq  = sun4m_clear_clock_irq;
0474     sparc_config.load_profile_irq = sun4m_load_profile_irq;
0475 
0476 
0477     /* Cannot enable interrupts until OBP ticker is disabled. */
0478 }