1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2000, 2001 Broadcom Corporation 4 */ 5 #include <linux/clockchips.h> 6 #include <linux/interrupt.h> 7 #include <linux/irq.h> 8 #include <linux/percpu.h> 9 #include <linux/smp.h> 10 11 #include <asm/addrspace.h> 12 #include <asm/io.h> 13 #include <asm/time.h> 14 15 #include <asm/sibyte/sb1250.h> 16 #include <asm/sibyte/sb1250_regs.h> 17 #include <asm/sibyte/sb1250_int.h> 18 #include <asm/sibyte/sb1250_scd.h> 19 20 #define IMR_IP2_VAL K_INT_MAP_I0 21 #define IMR_IP3_VAL K_INT_MAP_I1 22 #define IMR_IP4_VAL K_INT_MAP_I2 23 24 /* 25 * The general purpose timer ticks at 1MHz independent if 26 * the rest of the system 27 */ 28 29 static int sibyte_shutdown(struct clock_event_device *evt) 30 { 31 void __iomem *cfg; 32 33 cfg = IOADDR(A_SCD_TIMER_REGISTER(smp_processor_id(), R_SCD_TIMER_CFG)); 34 35 /* Stop the timer until we actually program a shot */ 36 __raw_writeq(0, cfg); 37 38 return 0; 39 } 40 41 static int sibyte_set_periodic(struct clock_event_device *evt) 42 { 43 unsigned int cpu = smp_processor_id(); 44 void __iomem *cfg, *init; 45 46 cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); 47 init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); 48 49 __raw_writeq(0, cfg); 50 __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init); 51 __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, cfg); 52 53 return 0; 54 } 55 56 static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) 57 { 58 unsigned int cpu = smp_processor_id(); 59 void __iomem *cfg, *init; 60 61 cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); 62 init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); 63 64 __raw_writeq(0, cfg); 65 __raw_writeq(delta - 1, init); 66 __raw_writeq(M_SCD_TIMER_ENABLE, cfg); 67 68 return 0; 69 } 70 71 static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) 72 { 73 unsigned int cpu = smp_processor_id(); 74 struct clock_event_device *cd = dev_id; 75 void __iomem *cfg; 76 unsigned long tmode; 77 78 if (clockevent_state_periodic(cd)) 79 tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS; 80 else 81 tmode = 0; 82 83 /* ACK interrupt */ 84 cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); 85 ____raw_writeq(tmode, cfg); 86 87 cd->event_handler(cd); 88 89 return IRQ_HANDLED; 90 } 91 92 static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent); 93 static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction); 94 static DEFINE_PER_CPU(char [18], sibyte_hpt_name); 95 96 void sb1250_clockevent_init(void) 97 { 98 unsigned int cpu = smp_processor_id(); 99 unsigned int irq = K_INT_TIMER_0 + cpu; 100 struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu); 101 struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu); 102 unsigned char *name = per_cpu(sibyte_hpt_name, cpu); 103 104 /* Only have 4 general purpose timers, and we use last one as hpt */ 105 BUG_ON(cpu > 2); 106 107 sprintf(name, "sb1250-counter-%d", cpu); 108 cd->name = name; 109 cd->features = CLOCK_EVT_FEAT_PERIODIC | 110 CLOCK_EVT_FEAT_ONESHOT; 111 clockevent_set_clock(cd, V_SCD_TIMER_FREQ); 112 cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd); 113 cd->max_delta_ticks = 0x7fffff; 114 cd->min_delta_ns = clockevent_delta2ns(2, cd); 115 cd->min_delta_ticks = 2; 116 cd->rating = 200; 117 cd->irq = irq; 118 cd->cpumask = cpumask_of(cpu); 119 cd->set_next_event = sibyte_next_event; 120 cd->set_state_shutdown = sibyte_shutdown; 121 cd->set_state_periodic = sibyte_set_periodic; 122 cd->set_state_oneshot = sibyte_shutdown; 123 clockevents_register_device(cd); 124 125 sb1250_mask_irq(cpu, irq); 126 127 /* 128 * Map the timer interrupt to IP[4] of this cpu 129 */ 130 __raw_writeq(IMR_IP4_VAL, 131 IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) + 132 (irq << 3))); 133 134 sb1250_unmask_irq(cpu, irq); 135 136 action->handler = sibyte_counter_handler; 137 action->flags = IRQF_PERCPU | IRQF_TIMER; 138 action->name = name; 139 action->dev_id = cd; 140 141 irq_set_affinity(irq, cpumask_of(cpu)); 142 setup_irq(irq, action); 143 } 144