/* * The general purpose timer ticks at 1MHz independent if * the rest of the system */ static void sibyte_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned int cpu = smp_processor_id(); void __iomem *cfg, *init; cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); switch (mode) { case CLOCK_EVT_MODE_PERIODIC: __raw_writeq(0, cfg); __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init); __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, cfg); break; case CLOCK_EVT_MODE_ONESHOT: /* Stop the timer until we actually program a shot */ case CLOCK_EVT_MODE_SHUTDOWN: __raw_writeq(0, cfg); break; case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ case CLOCK_EVT_MODE_RESUME: ; } }
static int sibyte_set_periodic(struct clock_event_device *evt) { unsigned int cpu = smp_processor_id(); void __iomem *cfg, *init; cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); __raw_writeq(0, cfg); __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init); __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, cfg); return 0; }
static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) { unsigned int cpu = smp_processor_id(); void __iomem *cfg, *init; cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); __raw_writeq(0, cfg); __raw_writeq(delta - 1, init); __raw_writeq(M_SCD_TIMER_ENABLE, cfg); return 0; }
void sb1250_time_init(void) { int cpu = smp_processor_id(); int irq = K_INT_TIMER_0+cpu; /* Only have 4 general purpose timers */ if (cpu > 3) { BUG(); } if (!cpu) { /* Use our own gettimeoffset() routine */ do_gettimeoffset = sb1250_gettimeoffset; } sb1250_mask_irq(cpu, irq); /* Map the timer interrupt to ip[4] of this cpu */ bus_writeq(IMR_IP4_VAL, IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) + (irq << 3))); /* the general purpose timer ticks at 1 Mhz independent if the rest of the system */ /* Disable the timer and set up the count */ bus_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); #ifdef CONFIG_SIMULATION bus_writeq(50000 / HZ, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT))); #else bus_writeq(1000000/HZ, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT))); #endif /* Set the timer running */ bus_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); sb1250_unmask_irq(cpu, irq); sb1250_steal_irq(irq); /* * This interrupt is "special" in that it doesn't use the request_irq * way to hook the irq line. The timer interrupt is initialized early * enough to make this a major pain, and it's also firing enough to * warrant a bit of special case code. sb1250_timer_interrupt is * called directly from irq_handler.S when IP[4] is set during an * interrupt */ }
static cycle_t bcm1480_hpt_read(void) { /* We assume this function is called xtime_lock held. */ unsigned long count = __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT))); return (jiffies + 1) * (BCM1480_HPT_VALUE / HZ) - count; }
/* * We use our own do_gettimeoffset() instead of the generic one, * because the generic one does not work for SMP case. * In addition, since we use general timer 0 for system time, * we can get accurate intra-jiffy offset without calibration. */ unsigned long sb1250_gettimeoffset(void) { unsigned long count = bus_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT))); return 1000000/HZ - count; }
/* * We use our own do_gettimeoffset() instead of the generic one, * because the generic one does not work for SMP case. * In addition, since we use general timer 0 for system time, * we can get accurate intra-jiffy offset without calibration. */ unsigned long sb1250_gettimeoffset(void) { unsigned long count = in64(KSEG1 + A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)); return 1000000/HZ - count; }
void __init sb1250_clocksource_init(void) { struct clocksource *cs = &bcm1250_clocksource; /* Setup hpt using timer #3 but do not enable irq for it */ __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG))); __raw_writeq(SB1250_HPT_VALUE, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_INIT))); __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG))); <<<<<<< HEAD
void __init sb1250_clocksource_init(void) { struct clocksource *cs = &bcm1250_clocksource; __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG))); __raw_writeq(SB1250_HPT_VALUE, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_INIT))); __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG))); clocksource_register_hz(cs, V_SCD_TIMER_FREQ); }
static cycle_t sb1250_hpt_read(struct clocksource *cs) { unsigned int count; count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT)))); return SB1250_HPT_VALUE - count; }
static int sibyte_shutdown(struct clock_event_device *evt) { unsigned int cpu = smp_processor_id(); void __iomem *cfg; cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); /* Stop the timer until we actually program a shot */ __raw_writeq(0, cfg); return 0; }
void bcm1480_time_init(void) { int cpu = smp_processor_id(); int irq = K_BCM1480_INT_TIMER_0+cpu; /* Only have 4 general purpose timers */ if (cpu > 3) { BUG(); } bcm1480_mask_irq(cpu, irq); /* Map the timer interrupt to ip[4] of this cpu */ __raw_writeq(IMR_IP4_VAL, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + (irq<<3))); /* the general purpose timer ticks at 1 Mhz independent of the rest of the system */ /* Disable the timer and set up the count */ __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); __raw_writeq( BCM1480_HPT_VALUE/HZ , IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT))); /* Set the timer running */ __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); bcm1480_unmask_irq(cpu, irq); bcm1480_steal_irq(irq); /* * This interrupt is "special" in that it doesn't use the request_irq * way to hook the irq line. The timer interrupt is initialized early * enough to make this a major pain, and it's also firing enough to * warrant a bit of special case code. bcm1480_timer_interrupt is * called directly from irq_handler.S when IP[4] is set during an * interrupt */ }
static irqreturn_t sibyte_counter_handler(int irq, void *dev_id) { unsigned int cpu = smp_processor_id(); struct clock_event_device *cd = dev_id; void __iomem *cfg; unsigned long tmode; if (cd->mode == CLOCK_EVT_MODE_PERIODIC) tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS; else tmode = 0; /* ACK interrupt */ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); ____raw_writeq(tmode, cfg); cd->event_handler(cd); return IRQ_HANDLED; }
void sb1250_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); int irq = K_INT_TIMER_0+cpu; /* Reset the timer */ out64(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); /* * CPU 0 handles the global timer interrupt job */ if (cpu == 0) { ll_timer_interrupt(irq, regs); } /* * every CPU should do profiling and process accouting */ ll_local_timer_interrupt(irq, regs); }
void bcm1480_timer_interrupt(void) { int cpu = smp_processor_id(); int irq = K_BCM1480_INT_TIMER_0 + cpu; /* Reset the timer */ __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); if (cpu == 0) { /* * CPU 0 handles the global timer interrupt job */ ll_timer_interrupt(irq); } else { /* * other CPUs should just do profiling and process accounting */ ll_local_timer_interrupt(irq); } }
void sb1250_timer_interrupt(struct pt_regs *regs) { extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); int cpu = smp_processor_id(); int irq = K_INT_TIMER_0 + cpu; /* Reset the timer */ __bus_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); /* * CPU 0 handles the global timer interrupt job */ if (cpu == 0) { ll_timer_interrupt(irq, regs); } if (cpu != 0) { /* * every CPU should do profiling and process accouting */ ll_local_timer_interrupt(irq, regs); } }