1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * Copyright (C) 2008-2009 Manuel Lauss <manuel.lauss@gmail.com>
4   *
5   * Previous incarnations were:
6   * Copyright (C) 2001, 2006, 2008 MontaVista Software, <source@mvista.com>
7   * Copied and modified Carsten Langgaard's time.c
8   *
9   * Carsten Langgaard, carstenl@mips.com
10   * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
11   *
12   * ########################################################################
13   *
14   * ########################################################################
15   *
16   * Clocksource/event using the 32.768kHz-clocked Counter1 ('RTC' in the
17   * databooks).  Firmware/Board init code must enable the counters in the
18   * counter control register, otherwise the CP0 counter clocksource/event
19   * will be installed instead (and use of 'wait' instruction is prohibited).
20   */
21  
22  #include <linux/clockchips.h>
23  #include <linux/clocksource.h>
24  #include <linux/interrupt.h>
25  #include <linux/spinlock.h>
26  
27  #include <asm/idle.h>
28  #include <asm/processor.h>
29  #include <asm/time.h>
30  #include <asm/mach-au1x00/au1000.h>
31  
32  /* 32kHz clock enabled and detected */
33  #define CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S)
34  
au1x_counter1_read(struct clocksource * cs)35  static u64 au1x_counter1_read(struct clocksource *cs)
36  {
37  	return alchemy_rdsys(AU1000_SYS_RTCREAD);
38  }
39  
40  static struct clocksource au1x_counter1_clocksource = {
41  	.name		= "alchemy-counter1",
42  	.read		= au1x_counter1_read,
43  	.mask		= CLOCKSOURCE_MASK(32),
44  	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
45  	.rating		= 1500,
46  };
47  
au1x_rtcmatch2_set_next_event(unsigned long delta,struct clock_event_device * cd)48  static int au1x_rtcmatch2_set_next_event(unsigned long delta,
49  					 struct clock_event_device *cd)
50  {
51  	delta += alchemy_rdsys(AU1000_SYS_RTCREAD);
52  	/* wait for register access */
53  	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M21)
54  		;
55  	alchemy_wrsys(delta, AU1000_SYS_RTCMATCH2);
56  
57  	return 0;
58  }
59  
au1x_rtcmatch2_irq(int irq,void * dev_id)60  static irqreturn_t au1x_rtcmatch2_irq(int irq, void *dev_id)
61  {
62  	struct clock_event_device *cd = dev_id;
63  	cd->event_handler(cd);
64  	return IRQ_HANDLED;
65  }
66  
67  static struct clock_event_device au1x_rtcmatch2_clockdev = {
68  	.name		= "rtcmatch2",
69  	.features	= CLOCK_EVT_FEAT_ONESHOT,
70  	.rating		= 1500,
71  	.set_next_event = au1x_rtcmatch2_set_next_event,
72  	.cpumask	= cpu_possible_mask,
73  };
74  
alchemy_time_init(unsigned int m2int)75  static int __init alchemy_time_init(unsigned int m2int)
76  {
77  	struct clock_event_device *cd = &au1x_rtcmatch2_clockdev;
78  	unsigned long t;
79  
80  	au1x_rtcmatch2_clockdev.irq = m2int;
81  
82  	/* Check if firmware (YAMON, ...) has enabled 32kHz and clock
83  	 * has been detected.  If so install the rtcmatch2 clocksource,
84  	 * otherwise don't bother.  Note that both bits being set is by
85  	 * no means a definite guarantee that the counters actually work
86  	 * (the 32S bit seems to be stuck set to 1 once a single clock-
87  	 * edge is detected, hence the timeouts).
88  	 */
89  	if (CNTR_OK != (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & CNTR_OK))
90  		goto cntr_err;
91  
92  	/*
93  	 * setup counter 1 (RTC) to tick at full speed
94  	 */
95  	t = 0xffffff;
96  	while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T1S) && --t)
97  		asm volatile ("nop");
98  	if (!t)
99  		goto cntr_err;
100  
101  	alchemy_wrsys(0, AU1000_SYS_RTCTRIM);	/* 32.768 kHz */
102  
103  	t = 0xffffff;
104  	while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t)
105  		asm volatile ("nop");
106  	if (!t)
107  		goto cntr_err;
108  	alchemy_wrsys(0, AU1000_SYS_RTCWRITE);
109  
110  	t = 0xffffff;
111  	while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t)
112  		asm volatile ("nop");
113  	if (!t)
114  		goto cntr_err;
115  
116  	/* register counter1 clocksource and event device */
117  	clocksource_register_hz(&au1x_counter1_clocksource, 32768);
118  
119  	cd->shift = 32;
120  	cd->mult = div_sc(32768, NSEC_PER_SEC, cd->shift);
121  	cd->max_delta_ns = clockevent_delta2ns(0xffffffff, cd);
122  	cd->max_delta_ticks = 0xffffffff;
123  	cd->min_delta_ns = clockevent_delta2ns(9, cd);
124  	cd->min_delta_ticks = 9;	/* ~0.28ms */
125  	clockevents_register_device(cd);
126  	if (request_irq(m2int, au1x_rtcmatch2_irq, IRQF_TIMER, "timer",
127  			&au1x_rtcmatch2_clockdev))
128  		pr_err("Failed to register timer interrupt\n");
129  
130  	printk(KERN_INFO "Alchemy clocksource installed\n");
131  
132  	return 0;
133  
134  cntr_err:
135  	return -1;
136  }
137  
138  static int alchemy_m2inttab[] __initdata = {
139  	AU1000_RTC_MATCH2_INT,
140  	AU1500_RTC_MATCH2_INT,
141  	AU1100_RTC_MATCH2_INT,
142  	AU1550_RTC_MATCH2_INT,
143  	AU1200_RTC_MATCH2_INT,
144  	AU1300_RTC_MATCH2_INT,
145  };
146  
plat_time_init(void)147  void __init plat_time_init(void)
148  {
149  	int t;
150  
151  	t = alchemy_get_cputype();
152  	if (t == ALCHEMY_CPU_UNKNOWN ||
153  	    alchemy_time_init(alchemy_m2inttab[t]))
154  		cpu_wait = NULL;	/* wait doesn't work with r4k timer */
155  }
156