Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 1999, 2000, 05, 06 Ralf Baechle (ralf@linux-mips.org)
0004  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
0005  */
0006 #include <linux/bcd.h>
0007 #include <linux/clockchips.h>
0008 #include <linux/init.h>
0009 #include <linux/kernel.h>
0010 #include <linux/sched.h>
0011 #include <linux/sched_clock.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/kernel_stat.h>
0014 #include <linux/param.h>
0015 #include <linux/smp.h>
0016 #include <linux/time.h>
0017 #include <linux/timex.h>
0018 #include <linux/mm.h>
0019 #include <linux/platform_device.h>
0020 
0021 #include <asm/time.h>
0022 #include <asm/sgialib.h>
0023 #include <asm/sn/klconfig.h>
0024 #include <asm/sn/arch.h>
0025 #include <asm/sn/addrs.h>
0026 #include <asm/sn/agent.h>
0027 
0028 #include "ip27-common.h"
0029 
0030 static int rt_next_event(unsigned long delta, struct clock_event_device *evt)
0031 {
0032     unsigned int cpu = smp_processor_id();
0033     int slice = cputoslice(cpu);
0034     unsigned long cnt;
0035 
0036     cnt = LOCAL_HUB_L(PI_RT_COUNT);
0037     cnt += delta;
0038     LOCAL_HUB_S(PI_RT_COMPARE_A + PI_COUNT_OFFSET * slice, cnt);
0039 
0040     return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0;
0041 }
0042 
0043 static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent);
0044 static DEFINE_PER_CPU(char [11], hub_rt_name);
0045 
0046 static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id)
0047 {
0048     unsigned int cpu = smp_processor_id();
0049     struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu);
0050     int slice = cputoslice(cpu);
0051 
0052     /*
0053      * Ack
0054      */
0055     LOCAL_HUB_S(PI_RT_PEND_A + PI_COUNT_OFFSET * slice, 0);
0056     cd->event_handler(cd);
0057 
0058     return IRQ_HANDLED;
0059 }
0060 
0061 struct irqaction hub_rt_irqaction = {
0062     .handler    = hub_rt_counter_handler,
0063     .percpu_dev_id  = &hub_rt_clockevent,
0064     .flags      = IRQF_PERCPU | IRQF_TIMER,
0065     .name       = "hub-rt",
0066 };
0067 
0068 /*
0069  * This is a hack; we really need to figure these values out dynamically
0070  *
0071  * Since 800 ns works very well with various HUB frequencies, such as
0072  * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time.
0073  *
0074  * Ralf: which clock rate is used to feed the counter?
0075  */
0076 #define NSEC_PER_CYCLE      800
0077 #define CYCLES_PER_SEC      (NSEC_PER_SEC / NSEC_PER_CYCLE)
0078 
0079 void hub_rt_clock_event_init(void)
0080 {
0081     unsigned int cpu = smp_processor_id();
0082     struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu);
0083     unsigned char *name = per_cpu(hub_rt_name, cpu);
0084 
0085     sprintf(name, "hub-rt %d", cpu);
0086     cd->name        = name;
0087     cd->features        = CLOCK_EVT_FEAT_ONESHOT;
0088     clockevent_set_clock(cd, CYCLES_PER_SEC);
0089     cd->max_delta_ns    = clockevent_delta2ns(0xfffffffffffff, cd);
0090     cd->max_delta_ticks = 0xfffffffffffff;
0091     cd->min_delta_ns    = clockevent_delta2ns(0x300, cd);
0092     cd->min_delta_ticks = 0x300;
0093     cd->rating      = 200;
0094     cd->irq         = IP27_RT_TIMER_IRQ;
0095     cd->cpumask     = cpumask_of(cpu);
0096     cd->set_next_event  = rt_next_event;
0097     clockevents_register_device(cd);
0098 
0099     enable_percpu_irq(IP27_RT_TIMER_IRQ, IRQ_TYPE_NONE);
0100 }
0101 
0102 static void __init hub_rt_clock_event_global_init(void)
0103 {
0104     irq_set_handler(IP27_RT_TIMER_IRQ, handle_percpu_devid_irq);
0105     irq_set_percpu_devid(IP27_RT_TIMER_IRQ);
0106     setup_percpu_irq(IP27_RT_TIMER_IRQ, &hub_rt_irqaction);
0107 }
0108 
0109 static u64 hub_rt_read(struct clocksource *cs)
0110 {
0111     return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT);
0112 }
0113 
0114 struct clocksource hub_rt_clocksource = {
0115     .name   = "HUB-RT",
0116     .rating = 200,
0117     .read   = hub_rt_read,
0118     .mask   = CLOCKSOURCE_MASK(52),
0119     .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
0120 };
0121 
0122 static u64 notrace hub_rt_read_sched_clock(void)
0123 {
0124     return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT);
0125 }
0126 
0127 static void __init hub_rt_clocksource_init(void)
0128 {
0129     struct clocksource *cs = &hub_rt_clocksource;
0130 
0131     clocksource_register_hz(cs, CYCLES_PER_SEC);
0132 
0133     sched_clock_register(hub_rt_read_sched_clock, 52, CYCLES_PER_SEC);
0134 }
0135 
0136 void __init plat_time_init(void)
0137 {
0138     hub_rt_clocksource_init();
0139     hub_rt_clock_event_global_init();
0140     hub_rt_clock_event_init();
0141 }
0142 
0143 void hub_rtc_init(nasid_t nasid)
0144 {
0145 
0146     /*
0147      * We only need to initialize the current node.
0148      * If this is not the current node then it is a cpuless
0149      * node and timeouts will not happen there.
0150      */
0151     if (get_nasid() == nasid) {
0152         LOCAL_HUB_S(PI_RT_EN_A, 1);
0153         LOCAL_HUB_S(PI_RT_EN_B, 1);
0154         LOCAL_HUB_S(PI_PROF_EN_A, 0);
0155         LOCAL_HUB_S(PI_PROF_EN_B, 0);
0156         LOCAL_HUB_S(PI_RT_COUNT, 0);
0157         LOCAL_HUB_S(PI_RT_PEND_A, 0);
0158         LOCAL_HUB_S(PI_RT_PEND_B, 0);
0159     }
0160 }