1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* timer.h: System timer definitions for sun5. 3 * 4 * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net) 5 */ 6 7 #ifndef _SPARC64_TIMER_H 8 #define _SPARC64_TIMER_H 9 10 #include <uapi/asm/asi.h> 11 #include <linux/types.h> 12 #include <linux/init.h> 13 14 /* The most frequently accessed fields should be first, 15 * to fit into the same cacheline. 16 */ 17 struct sparc64_tick_ops { 18 unsigned long ticks_per_nsec_quotient; 19 unsigned long offset; 20 unsigned long long (*get_tick)(void); 21 int (*add_compare)(unsigned long); 22 unsigned long softint_mask; 23 void (*disable_irq)(void); 24 25 void (*init_tick)(void); 26 unsigned long (*add_tick)(unsigned long); 27 unsigned long (*get_frequency)(void); 28 unsigned long frequency; 29 30 char *name; 31 }; 32 33 extern struct sparc64_tick_ops *tick_ops; 34 35 unsigned long sparc64_get_clock_tick(unsigned int cpu); 36 void setup_sparc64_timer(void); 37 void __init time_init(void); 38 39 #define TICK_PRIV_BIT BIT(63) 40 #define TICKCMP_IRQ_BIT BIT(63) 41 42 #define HBIRD_STICKCMP_ADDR 0x1fe0000f060UL 43 #define HBIRD_STICK_ADDR 0x1fe0000f070UL 44 45 #define GET_TICK_NINSTR 13 46 struct get_tick_patch { 47 unsigned int addr; 48 unsigned int tick[GET_TICK_NINSTR]; 49 unsigned int stick[GET_TICK_NINSTR]; 50 }; 51 52 extern struct get_tick_patch __get_tick_patch; 53 extern struct get_tick_patch __get_tick_patch_end; 54 55 static inline unsigned long get_tick(void) 56 { 57 unsigned long tick, tmp1, tmp2; 58 59 __asm__ __volatile__( 60 /* read hbtick 13 instructions */ 61 "661:\n" 62 " mov 0x1fe, %1\n" 63 " sllx %1, 0x20, %1\n" 64 " sethi %%hi(0xf000), %2\n" 65 " or %2, 0x70, %2\n" 66 " or %1, %2, %1\n" /* %1 = HBIRD_STICK_ADDR */ 67 " add %1, 8, %2\n" 68 " ldxa [%2]%3, %0\n" 69 " ldxa [%1]%3, %1\n" 70 " ldxa [%2]%3, %2\n" 71 " sub %2, %0, %0\n" /* don't modify %xcc */ 72 " brnz,pn %0, 661b\n" /* restart to save one register */ 73 " sllx %2, 32, %2\n" 74 " or %2, %1, %0\n" 75 /* Common/not patched code */ 76 " sllx %0, 1, %0\n" 77 " srlx %0, 1, %0\n" /* Clear TICK_PRIV_BIT */ 78 /* Beginning of patch section */ 79 " .section .get_tick_patch, \"ax\"\n" 80 " .word 661b\n" 81 /* read tick 2 instructions and 11 skipped */ 82 " ba 1f\n" 83 " rd %%tick, %0\n" 84 " .skip 4 * (%4 - 2)\n" 85 "1:\n" 86 /* read stick 2 instructions and 11 skipped */ 87 " ba 1f\n" 88 " rd %%asr24, %0\n" 89 " .skip 4 * (%4 - 2)\n" 90 "1:\n" 91 /* End of patch section */ 92 " .previous\n" 93 : "=&r" (tick), "=&r" (tmp1), "=&r" (tmp2) 94 : "i" (ASI_PHYS_BYPASS_EC_E), "i" (GET_TICK_NINSTR)); 95 96 return tick; 97 } 98 99 #endif /* _SPARC64_TIMER_H */ 100