xref: /openbmc/linux/arch/sparc/include/asm/timer_64.h (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2a439fe51SSam Ravnborg /* timer.h: System timer definitions for sun5.
3a439fe51SSam Ravnborg  *
4a439fe51SSam Ravnborg  * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net)
5a439fe51SSam Ravnborg  */
6a439fe51SSam Ravnborg 
7a439fe51SSam Ravnborg #ifndef _SPARC64_TIMER_H
8a439fe51SSam Ravnborg #define _SPARC64_TIMER_H
9a439fe51SSam Ravnborg 
10*0cd39f46SPeter Zijlstra #include <uapi/asm/asi.h>
11a439fe51SSam Ravnborg #include <linux/types.h>
12a439fe51SSam Ravnborg #include <linux/init.h>
13a439fe51SSam Ravnborg 
14178bf2b9SPavel Tatashin /* The most frequently accessed fields should be first,
15178bf2b9SPavel Tatashin  * to fit into the same cacheline.
16178bf2b9SPavel Tatashin  */
17a439fe51SSam Ravnborg struct sparc64_tick_ops {
18178bf2b9SPavel Tatashin 	unsigned long ticks_per_nsec_quotient;
19178bf2b9SPavel Tatashin 	unsigned long offset;
2090181136SSam Ravnborg 	unsigned long long (*get_tick)(void);
21a439fe51SSam Ravnborg 	int (*add_compare)(unsigned long);
22a439fe51SSam Ravnborg 	unsigned long softint_mask;
23a439fe51SSam Ravnborg 	void (*disable_irq)(void);
24a439fe51SSam Ravnborg 
25a439fe51SSam Ravnborg 	void (*init_tick)(void);
26a439fe51SSam Ravnborg 	unsigned long (*add_tick)(unsigned long);
2789108c34SPavel Tatashin 	unsigned long (*get_frequency)(void);
2889108c34SPavel Tatashin 	unsigned long frequency;
29a439fe51SSam Ravnborg 
30a439fe51SSam Ravnborg 	char *name;
31a439fe51SSam Ravnborg };
32a439fe51SSam Ravnborg 
33a439fe51SSam Ravnborg extern struct sparc64_tick_ops *tick_ops;
34a439fe51SSam Ravnborg 
35f05a6865SSam Ravnborg unsigned long sparc64_get_clock_tick(unsigned int cpu);
36f05a6865SSam Ravnborg void setup_sparc64_timer(void);
37a439fe51SSam Ravnborg 
384929c83aSPavel Tatashin #define TICK_PRIV_BIT		BIT(63)
394929c83aSPavel Tatashin #define TICKCMP_IRQ_BIT		BIT(63)
404929c83aSPavel Tatashin 
414929c83aSPavel Tatashin #define HBIRD_STICKCMP_ADDR	0x1fe0000f060UL
424929c83aSPavel Tatashin #define HBIRD_STICK_ADDR	0x1fe0000f070UL
434929c83aSPavel Tatashin 
444929c83aSPavel Tatashin #define GET_TICK_NINSTR		13
454929c83aSPavel Tatashin struct get_tick_patch {
464929c83aSPavel Tatashin 	unsigned int	addr;
474929c83aSPavel Tatashin 	unsigned int	tick[GET_TICK_NINSTR];
484929c83aSPavel Tatashin 	unsigned int	stick[GET_TICK_NINSTR];
494929c83aSPavel Tatashin };
504929c83aSPavel Tatashin 
514929c83aSPavel Tatashin extern struct get_tick_patch __get_tick_patch;
524929c83aSPavel Tatashin extern struct get_tick_patch __get_tick_patch_end;
534929c83aSPavel Tatashin 
get_tick(void)544929c83aSPavel Tatashin static inline unsigned long get_tick(void)
554929c83aSPavel Tatashin {
564929c83aSPavel Tatashin 	unsigned long tick, tmp1, tmp2;
574929c83aSPavel Tatashin 
584929c83aSPavel Tatashin 	__asm__ __volatile__(
594929c83aSPavel Tatashin 	/* read hbtick 13 instructions */
604929c83aSPavel Tatashin 	"661:\n"
614929c83aSPavel Tatashin 	"	mov	0x1fe, %1\n"
624929c83aSPavel Tatashin 	"	sllx	%1, 0x20, %1\n"
634929c83aSPavel Tatashin 	"	sethi	%%hi(0xf000), %2\n"
644929c83aSPavel Tatashin 	"	or	%2, 0x70, %2\n"
654929c83aSPavel Tatashin 	"	or	%1, %2, %1\n"	/* %1 = HBIRD_STICK_ADDR */
664929c83aSPavel Tatashin 	"	add	%1, 8, %2\n"
674929c83aSPavel Tatashin 	"	ldxa	[%2]%3, %0\n"
684929c83aSPavel Tatashin 	"	ldxa	[%1]%3, %1\n"
694929c83aSPavel Tatashin 	"	ldxa	[%2]%3, %2\n"
704929c83aSPavel Tatashin 	"	sub	%2, %0, %0\n"	/* don't modify %xcc */
714929c83aSPavel Tatashin 	"	brnz,pn	%0, 661b\n"	/* restart to save one register */
724929c83aSPavel Tatashin 	"	 sllx	%2, 32, %2\n"
734929c83aSPavel Tatashin 	"	or	%2, %1, %0\n"
744929c83aSPavel Tatashin 	/* Common/not patched code */
754929c83aSPavel Tatashin 	"	sllx	%0, 1, %0\n"
764929c83aSPavel Tatashin 	"	srlx	%0, 1, %0\n"	/* Clear TICK_PRIV_BIT */
774929c83aSPavel Tatashin 	/* Beginning of patch section */
784929c83aSPavel Tatashin 	"	.section .get_tick_patch, \"ax\"\n"
794929c83aSPavel Tatashin 	"	.word	661b\n"
804929c83aSPavel Tatashin 	/* read tick 2 instructions and 11 skipped */
814929c83aSPavel Tatashin 	"	ba	1f\n"
824929c83aSPavel Tatashin 	"	 rd	%%tick, %0\n"
834929c83aSPavel Tatashin 	"	.skip	4 * (%4 - 2)\n"
844929c83aSPavel Tatashin 	"1:\n"
854929c83aSPavel Tatashin 	/* read stick 2 instructions and 11 skipped */
864929c83aSPavel Tatashin 	"	ba	1f\n"
874929c83aSPavel Tatashin 	"	 rd	%%asr24, %0\n"
884929c83aSPavel Tatashin 	"	.skip	4 * (%4 - 2)\n"
894929c83aSPavel Tatashin 	"1:\n"
904929c83aSPavel Tatashin 	/* End of patch section */
914929c83aSPavel Tatashin 	"	.previous\n"
924929c83aSPavel Tatashin 	: "=&r" (tick), "=&r" (tmp1), "=&r" (tmp2)
934929c83aSPavel Tatashin 	: "i" (ASI_PHYS_BYPASS_EC_E), "i" (GET_TICK_NINSTR));
944929c83aSPavel Tatashin 
954929c83aSPavel Tatashin 	return tick;
964929c83aSPavel Tatashin }
974929c83aSPavel Tatashin 
98a439fe51SSam Ravnborg #endif /* _SPARC64_TIMER_H */
99