0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel_stat.h>
0010 #include <linux/slab.h>
0011 #include <linux/seq_file.h>
0012
0013 #include <asm/timer.h>
0014 #include <asm/traps.h>
0015 #include <asm/irq.h>
0016 #include <asm/io.h>
0017 #include <asm/sbi.h>
0018 #include <asm/cacheflush.h>
0019 #include <asm/setup.h>
0020 #include <asm/oplib.h>
0021
0022 #include "kernel.h"
0023 #include "irq.h"
0024
0025
0026
0027
0028
0029
0030
0031
0032 struct sun4d_handler_data {
0033 unsigned int cpuid;
0034 unsigned int real_irq;
0035 };
0036
0037
0038 static unsigned int sun4d_encode_irq(int board, int lvl, int slot)
0039 {
0040 return (board + 1) << 5 | (lvl << 2) | slot;
0041 }
0042
0043 struct sun4d_timer_regs {
0044 u32 l10_timer_limit;
0045 u32 l10_cur_countx;
0046 u32 l10_limit_noclear;
0047 u32 ctrl;
0048 u32 l10_cur_count;
0049 };
0050
0051 static struct sun4d_timer_regs __iomem *sun4d_timers;
0052
0053 #define SUN4D_TIMER_IRQ 10
0054
0055
0056
0057
0058 static unsigned char board_to_cpu[32];
0059
0060 static int pil_to_sbus[] = {
0061 0,
0062 0,
0063 1,
0064 2,
0065 0,
0066 3,
0067 0,
0068 4,
0069 0,
0070 5,
0071 0,
0072 6,
0073 0,
0074 7,
0075 0,
0076 0,
0077 };
0078
0079
0080 DEFINE_SPINLOCK(sun4d_imsk_lock);
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 static void sun4d_sbus_handler_irq(int sbusl)
0099 {
0100 unsigned int bus_mask;
0101 unsigned int sbino, slot;
0102 unsigned int sbil;
0103
0104 bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff;
0105 bw_clear_intr_mask(sbusl, bus_mask);
0106
0107 sbil = (sbusl << 2);
0108
0109 for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) {
0110 unsigned int idx, mask;
0111
0112 if (!(bus_mask & 1))
0113 continue;
0114
0115
0116
0117
0118
0119 mask = acquire_sbi(SBI2DEVID(sbino), 0xf << sbil);
0120 mask &= (0xf << sbil);
0121
0122
0123 slot = (1 << sbil);
0124 for (idx = 0; mask != 0; idx++, slot <<= 1) {
0125 unsigned int pil;
0126 struct irq_bucket *p;
0127
0128 if (!(mask & slot))
0129 continue;
0130
0131 mask &= ~slot;
0132 pil = sun4d_encode_irq(sbino, sbusl, idx);
0133
0134 p = irq_map[pil];
0135 while (p) {
0136 struct irq_bucket *next;
0137
0138 next = p->next;
0139 generic_handle_irq(p->irq);
0140 p = next;
0141 }
0142 release_sbi(SBI2DEVID(sbino), slot);
0143 }
0144 }
0145 }
0146
0147 void sun4d_handler_irq(unsigned int pil, struct pt_regs *regs)
0148 {
0149 struct pt_regs *old_regs;
0150
0151 int sbusl = pil_to_sbus[pil];
0152
0153
0154 cc_get_ipen();
0155
0156 cc_set_iclr(1 << pil);
0157
0158 #ifdef CONFIG_SMP
0159
0160
0161
0162
0163 if (pil == SUN4D_IPI_IRQ)
0164 sun4d_ipi_interrupt();
0165 #endif
0166
0167 old_regs = set_irq_regs(regs);
0168 irq_enter();
0169 if (sbusl == 0) {
0170
0171 struct irq_bucket *p;
0172
0173 p = irq_map[pil];
0174 while (p) {
0175 struct irq_bucket *next;
0176
0177 next = p->next;
0178 generic_handle_irq(p->irq);
0179 p = next;
0180 }
0181 } else {
0182
0183 sun4d_sbus_handler_irq(sbusl);
0184 }
0185 irq_exit();
0186 set_irq_regs(old_regs);
0187 }
0188
0189
0190 static void sun4d_mask_irq(struct irq_data *data)
0191 {
0192 struct sun4d_handler_data *handler_data = irq_data_get_irq_handler_data(data);
0193 unsigned int real_irq;
0194 #ifdef CONFIG_SMP
0195 int cpuid = handler_data->cpuid;
0196 unsigned long flags;
0197 #endif
0198 real_irq = handler_data->real_irq;
0199 #ifdef CONFIG_SMP
0200 spin_lock_irqsave(&sun4d_imsk_lock, flags);
0201 cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | (1 << real_irq));
0202 spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
0203 #else
0204 cc_set_imsk(cc_get_imsk() | (1 << real_irq));
0205 #endif
0206 }
0207
0208 static void sun4d_unmask_irq(struct irq_data *data)
0209 {
0210 struct sun4d_handler_data *handler_data = irq_data_get_irq_handler_data(data);
0211 unsigned int real_irq;
0212 #ifdef CONFIG_SMP
0213 int cpuid = handler_data->cpuid;
0214 unsigned long flags;
0215 #endif
0216 real_irq = handler_data->real_irq;
0217
0218 #ifdef CONFIG_SMP
0219 spin_lock_irqsave(&sun4d_imsk_lock, flags);
0220 cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) & ~(1 << real_irq));
0221 spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
0222 #else
0223 cc_set_imsk(cc_get_imsk() & ~(1 << real_irq));
0224 #endif
0225 }
0226
0227 static unsigned int sun4d_startup_irq(struct irq_data *data)
0228 {
0229 irq_link(data->irq);
0230 sun4d_unmask_irq(data);
0231 return 0;
0232 }
0233
0234 static void sun4d_shutdown_irq(struct irq_data *data)
0235 {
0236 sun4d_mask_irq(data);
0237 irq_unlink(data->irq);
0238 }
0239
0240 static struct irq_chip sun4d_irq = {
0241 .name = "sun4d",
0242 .irq_startup = sun4d_startup_irq,
0243 .irq_shutdown = sun4d_shutdown_irq,
0244 .irq_unmask = sun4d_unmask_irq,
0245 .irq_mask = sun4d_mask_irq,
0246 };
0247
0248 #ifdef CONFIG_SMP
0249
0250 void __init sun4d_distribute_irqs(void)
0251 {
0252 struct device_node *dp;
0253
0254 int cpuid = cpu_logical_map(1);
0255
0256 if (cpuid == -1)
0257 cpuid = cpu_logical_map(0);
0258 for_each_node_by_name(dp, "sbi") {
0259 int devid = of_getintprop_default(dp, "device-id", 0);
0260 int board = of_getintprop_default(dp, "board#", 0);
0261 board_to_cpu[board] = cpuid;
0262 set_sbi_tid(devid, cpuid << 3);
0263 }
0264 printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid);
0265 }
0266 #endif
0267
0268 static void sun4d_clear_clock_irq(void)
0269 {
0270 sbus_readl(&sun4d_timers->l10_timer_limit);
0271 }
0272
0273 static void sun4d_load_profile_irq(int cpu, unsigned int limit)
0274 {
0275 unsigned int value = limit ? timer_value(limit) : 0;
0276 bw_set_prof_limit(cpu, value);
0277 }
0278
0279 static void __init sun4d_load_profile_irqs(void)
0280 {
0281 int cpu = 0, mid;
0282
0283 while (!cpu_find_by_instance(cpu, NULL, &mid)) {
0284 sun4d_load_profile_irq(mid >> 3, 0);
0285 cpu++;
0286 }
0287 }
0288
0289 static unsigned int _sun4d_build_device_irq(unsigned int real_irq,
0290 unsigned int pil,
0291 unsigned int board)
0292 {
0293 struct sun4d_handler_data *handler_data;
0294 unsigned int irq;
0295
0296 irq = irq_alloc(real_irq, pil);
0297 if (irq == 0) {
0298 prom_printf("IRQ: allocate for %d %d %d failed\n",
0299 real_irq, pil, board);
0300 goto err_out;
0301 }
0302
0303 handler_data = irq_get_handler_data(irq);
0304 if (unlikely(handler_data))
0305 goto err_out;
0306
0307 handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC);
0308 if (unlikely(!handler_data)) {
0309 prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n");
0310 prom_halt();
0311 }
0312 handler_data->cpuid = board_to_cpu[board];
0313 handler_data->real_irq = real_irq;
0314 irq_set_chip_and_handler_name(irq, &sun4d_irq,
0315 handle_level_irq, "level");
0316 irq_set_handler_data(irq, handler_data);
0317
0318 err_out:
0319 return irq;
0320 }
0321
0322
0323
0324 static unsigned int sun4d_build_device_irq(struct platform_device *op,
0325 unsigned int real_irq)
0326 {
0327 struct device_node *dp = op->dev.of_node;
0328 struct device_node *board_parent, *bus = dp->parent;
0329 char *bus_connection;
0330 const struct linux_prom_registers *regs;
0331 unsigned int pil;
0332 unsigned int irq;
0333 int board, slot;
0334 int sbusl;
0335
0336 irq = real_irq;
0337 while (bus) {
0338 if (of_node_name_eq(bus, "sbi")) {
0339 bus_connection = "io-unit";
0340 break;
0341 }
0342
0343 if (of_node_name_eq(bus, "bootbus")) {
0344 bus_connection = "cpu-unit";
0345 break;
0346 }
0347
0348 bus = bus->parent;
0349 }
0350 if (!bus)
0351 goto err_out;
0352
0353 regs = of_get_property(dp, "reg", NULL);
0354 if (!regs)
0355 goto err_out;
0356
0357 slot = regs->which_io;
0358
0359
0360
0361
0362
0363 if (!of_node_name_eq(bus->parent, bus_connection)) {
0364 printk(KERN_ERR "%pOF: Error, parent is not %s.\n",
0365 bus, bus_connection);
0366 goto err_out;
0367 }
0368 board_parent = bus->parent;
0369 board = of_getintprop_default(board_parent, "board#", -1);
0370 if (board == -1) {
0371 printk(KERN_ERR "%pOF: Error, lacks board# property.\n",
0372 board_parent);
0373 goto err_out;
0374 }
0375
0376 sbusl = pil_to_sbus[real_irq];
0377 if (sbusl)
0378 pil = sun4d_encode_irq(board, sbusl, slot);
0379 else
0380 pil = real_irq;
0381
0382 irq = _sun4d_build_device_irq(real_irq, pil, board);
0383 err_out:
0384 return irq;
0385 }
0386
0387 static unsigned int sun4d_build_timer_irq(unsigned int board,
0388 unsigned int real_irq)
0389 {
0390 return _sun4d_build_device_irq(real_irq, real_irq, board);
0391 }
0392
0393
0394 static void __init sun4d_fixup_trap_table(void)
0395 {
0396 #ifdef CONFIG_SMP
0397 unsigned long flags;
0398 struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
0399
0400
0401 lvl14_save[2] += smp4d_ticker - real_irq_entry;
0402
0403
0404
0405
0406
0407 local_irq_save(flags);
0408 patchme_maybe_smp_msg[0] = 0x01000000;
0409 trap_table->inst_one = lvl14_save[0];
0410 trap_table->inst_two = lvl14_save[1];
0411 trap_table->inst_three = lvl14_save[2];
0412 trap_table->inst_four = lvl14_save[3];
0413 local_ops->cache_all();
0414 local_irq_restore(flags);
0415 #endif
0416 }
0417
0418 static void __init sun4d_init_timers(void)
0419 {
0420 struct device_node *dp;
0421 struct resource res;
0422 unsigned int irq;
0423 const u32 *reg;
0424 int err;
0425 int board;
0426
0427 dp = of_find_node_by_name(NULL, "cpu-unit");
0428 if (!dp) {
0429 prom_printf("sun4d_init_timers: Unable to find cpu-unit\n");
0430 prom_halt();
0431 }
0432
0433
0434
0435
0436
0437 reg = of_get_property(dp, "reg", NULL);
0438 if (!reg) {
0439 prom_printf("sun4d_init_timers: No reg property\n");
0440 prom_halt();
0441 }
0442
0443 board = of_getintprop_default(dp, "board#", -1);
0444 if (board == -1) {
0445 prom_printf("sun4d_init_timers: No board# property on cpu-unit\n");
0446 prom_halt();
0447 }
0448
0449 of_node_put(dp);
0450
0451 res.start = reg[1];
0452 res.end = reg[2] - 1;
0453 res.flags = reg[0] & 0xff;
0454 sun4d_timers = of_ioremap(&res, BW_TIMER_LIMIT,
0455 sizeof(struct sun4d_timer_regs), "user timer");
0456 if (!sun4d_timers) {
0457 prom_printf("sun4d_init_timers: Can't map timer regs\n");
0458 prom_halt();
0459 }
0460
0461 #ifdef CONFIG_SMP
0462 sparc_config.cs_period = SBUS_CLOCK_RATE * 2;
0463 #else
0464 sparc_config.cs_period = SBUS_CLOCK_RATE / HZ;
0465 sparc_config.features |= FEAT_L10_CLOCKEVENT;
0466 #endif
0467 sparc_config.features |= FEAT_L10_CLOCKSOURCE;
0468 sbus_writel(timer_value(sparc_config.cs_period),
0469 &sun4d_timers->l10_timer_limit);
0470
0471 master_l10_counter = &sun4d_timers->l10_cur_count;
0472
0473 irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ);
0474 err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
0475 if (err) {
0476 prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
0477 err);
0478 prom_halt();
0479 }
0480 sun4d_load_profile_irqs();
0481 sun4d_fixup_trap_table();
0482 }
0483
0484 void __init sun4d_init_sbi_irq(void)
0485 {
0486 struct device_node *dp;
0487 int target_cpu;
0488
0489 target_cpu = boot_cpu_id;
0490 for_each_node_by_name(dp, "sbi") {
0491 int devid = of_getintprop_default(dp, "device-id", 0);
0492 int board = of_getintprop_default(dp, "board#", 0);
0493 unsigned int mask;
0494
0495 set_sbi_tid(devid, target_cpu << 3);
0496 board_to_cpu[board] = target_cpu;
0497
0498
0499 mask = acquire_sbi(devid, 0xffffffff);
0500 if (mask) {
0501 printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n",
0502 mask, board);
0503 release_sbi(devid, mask);
0504 }
0505 }
0506 }
0507
0508 void __init sun4d_init_IRQ(void)
0509 {
0510 local_irq_disable();
0511
0512 sparc_config.init_timers = sun4d_init_timers;
0513 sparc_config.build_device_irq = sun4d_build_device_irq;
0514 sparc_config.clock_rate = SBUS_CLOCK_RATE;
0515 sparc_config.clear_clock_irq = sun4d_clear_clock_irq;
0516 sparc_config.load_profile_irq = sun4d_load_profile_irq;
0517
0518
0519 }