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 38 #define TICK_PRIV_BIT BIT(63) 39 #define TICKCMP_IRQ_BIT BIT(63) 40 41 #define HBIRD_STICKCMP_ADDR 0x1fe0000f060UL 42 #define HBIRD_STICK_ADDR 0x1fe0000f070UL 43 44 #define GET_TICK_NINSTR 13 45 struct get_tick_patch { 46 unsigned int addr; 47 unsigned int tick[GET_TICK_NINSTR]; 48 unsigned int stick[GET_TICK_NINSTR]; 49 }; 50 51 extern struct get_tick_patch __get_tick_patch; 52 extern struct get_tick_patch __get_tick_patch_end; 53 54 static inline unsigned long get_tick(void) 55 { 56 unsigned long tick, tmp1, tmp2; 57 58 __asm__ __volatile__( 59 /* read hbtick 13 instructions */ 60 "661:\n" 61 " mov 0x1fe, %1\n" 62 " sllx %1, 0x20, %1\n" 63 " sethi %%hi(0xf000), %2\n" 64 " or %2, 0x70, %2\n" 65 " or %1, %2, %1\n" /* %1 = HBIRD_STICK_ADDR */ 66 " add %1, 8, %2\n" 67 " ldxa [%2]%3, %0\n" 68 " ldxa [%1]%3, %1\n" 69 " ldxa [%2]%3, %2\n" 70 " sub %2, %0, %0\n" /* don't modify %xcc */ 71 " brnz,pn %0, 661b\n" /* restart to save one register */ 72 " sllx %2, 32, %2\n" 73 " or %2, %1, %0\n" 74 /* Common/not patched code */ 75 " sllx %0, 1, %0\n" 76 " srlx %0, 1, %0\n" /* Clear TICK_PRIV_BIT */ 77 /* Beginning of patch section */ 78 " .section .get_tick_patch, \"ax\"\n" 79 " .word 661b\n" 80 /* read tick 2 instructions and 11 skipped */ 81 " ba 1f\n" 82 " rd %%tick, %0\n" 83 " .skip 4 * (%4 - 2)\n" 84 "1:\n" 85 /* read stick 2 instructions and 11 skipped */ 86 " ba 1f\n" 87 " rd %%asr24, %0\n" 88 " .skip 4 * (%4 - 2)\n" 89 "1:\n" 90 /* End of patch section */ 91 " .previous\n" 92 : "=&r" (tick), "=&r" (tmp1), "=&r" (tmp2) 93 : "i" (ASI_PHYS_BYPASS_EC_E), "i" (GET_TICK_NINSTR)); 94 95 return tick; 96 } 97 98 #endif /* _SPARC64_TIMER_H */ 99