1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 #ifndef _HPET_ACPI_H
  26 #define _HPET_ACPI_H
  27 
  28 #if defined(_KERNEL)
  29 #include <sys/acpi/acpi.h>
  30 #include <sys/acpi/actbl1.h>
  31 #include <sys/acpica.h>
  32 #endif  /* defined(_KERNEL) */
  33 
  34 #ifdef __cplusplus
  35 extern "C" {
  36 #endif
  37 
  38 /*
  39  * Solaris uses an HPET Timer to generate interrupts for CPUs in Deep C-state
  40  * with stalled LAPIC Timers.  All CPUs use one HPET timer.  The timer's
  41  * interrupt targets one CPU (via the I/O APIC).  The one CPU that receives
  42  * the HPET's interrupt wakes up other CPUs as needed during the HPET Interrupt
  43  * Service Routing.  The HPET ISR uses poke_cpus to wake up other CPUs with an
  44  * Inter Processor Interrupt.
  45  *
  46  * Please see the Intel Programmer's guides.  Interrupts are disabled before
  47  * a CPU Halts into Deep C-state.  (This allows CPU-hardware-specific cleanup
  48  * before servicing interrupts.)  When a Deep C-state CPU wakes up (due to
  49  * an externally generated interrupt), it resume execution where it halted.
  50  * The CPU returning from Deep C-state must enable interrupts before it will
  51  * handle the pending interrupt that woke it from Deep C-state.
  52  *
  53  *
  54  * HPET bits as defined in the Intel IA-PC HPET Specification Rev 1.0a.
  55  *
  56  * The physical address space layout of the memory mapped HPET looks like this:
  57  *
  58  * struct hpet {
  59  *      uint64_t        gen_cap;
  60  *      uint64_t        res1;
  61  *      uint64_t        gen_config;
  62  *      uint64_t        res2;
  63  *      uint64_t        gen_inter_stat;
  64  *      uint64_t        res3;
  65  *      uint64_t        main_counter_value;
  66  *      uint64_t        res4;
  67  *      stuct hpet_timer {
  68  *              uint64_t        config_and_capability;
  69  *              uint64_t        comparator_value;
  70  *              uint64_t        FSB_interrupt_route;
  71  *              uint64_t        reserved;
  72  *      } timers[32];
  73  * }
  74  *
  75  * There are 32 possible timers in an hpet.  Only the first 3 timers are
  76  * required.  The other 29 timers are optional.
  77  *
  78  * HPETs can have 64-bit or 32-bit timers.  Timers/compare registers can
  79  * be 64-bit or 32-bit and can be a mixture of both.
  80  * The first two timers are not used.  The HPET spec intends the first two
  81  * timers to be used as "legacy replacement" for the PIT and RTC timers.
  82  *
  83  * Solaris uses the first available non-legacy replacement timer as a proxy
  84  * timer for processor Local APIC Timers that stop in deep idle C-states.
  85  */
  86 
  87 /*
  88  * We only use HPET table 1 on x86.  Typical x86 systems only have 1 HPET.
  89  * ACPI allows for multiple HPET tables to describe multiple HPETs.
  90  */
  91 #define HPET_TABLE_1            (1)
  92 
  93 /*
  94  * HPET Specification 1.0a defines the HPET to occupy 1024 bytes regardless of
  95  * the number of counters (3 to 32) in this implementation.
  96  */
  97 #define HPET_SIZE               (1024)
  98 
  99 /*
 100  * Offsets of hpet registers and macros to access them from HPET base address.
 101  */
 102 #define HPET_GEN_CAP_OFFSET             (0)
 103 #define HPET_GEN_CONFIG_OFFSET          (0x10)
 104 #define HPET_GEN_INTR_STAT_OFFSET       (0x20)
 105 #define HPET_MAIN_COUNTER_OFFSET        (0xF0)
 106 #define HPET_TIMER_N_CONF_OFFSET(n)     (0x100 + (n * 0x20))
 107 #define HPET_TIMER_N_COMP_OFFSET(n)     (0x108 + (n * 0x20))
 108 
 109 #define OFFSET_ADDR(a, o)               (((uintptr_t)(a)) + (o))
 110 #define HPET_GEN_CAP_ADDRESS(la)                                \
 111                     OFFSET_ADDR(la, HPET_GEN_CAP_OFFSET)
 112 #define HPET_GEN_CONFIG_ADDRESS(la)                             \
 113                     OFFSET_ADDR(la, HPET_GEN_CONFIG_OFFSET)
 114 #define HPET_GEN_INTR_STAT_ADDRESS(la)                          \
 115                     OFFSET_ADDR(la, HPET_GEN_INTR_STAT_OFFSET)
 116 #define HPET_MAIN_COUNTER_ADDRESS(la)                           \
 117                     OFFSET_ADDR(la, HPET_MAIN_COUNTER_OFFSET)
 118 #define HPET_TIMER_N_CONF_ADDRESS(la, n)                        \
 119                     OFFSET_ADDR(la, HPET_TIMER_N_CONF_OFFSET(n))
 120 #define HPET_TIMER_N_COMP_ADDRESS(la, n)                        \
 121                     OFFSET_ADDR(la, HPET_TIMER_N_COMP_OFFSET(n))
 122 
 123 /*
 124  * HPET General Capabilities and ID Register
 125  */
 126 typedef struct hpet_gen_cap {
 127         uint32_t        counter_clk_period;     /* period in femtoseconds */
 128         uint32_t        vendor_id       :16;    /* vendor */
 129         uint32_t        leg_route_cap   :1;     /* 1=LegacyReplacemnt support */
 130         uint32_t        res1            :1;     /* reserved */
 131         uint32_t        count_size_cap  :1;     /* 0=32bit, 1=64bit wide */
 132         uint32_t        num_tim_cap     :5;     /* number of timers -1 */
 133         uint32_t        rev_id          :8;     /* revision number */
 134 } hpet_gen_cap_t;
 135 
 136 /*
 137  * Macros to parse fields of the hpet General Capabilities and ID Register.
 138  */
 139 #define HPET_GCAP_CNTR_CLK_PERIOD(l)    (l >> 32)
 140 #define HPET_GCAP_VENDOR_ID(l)          BITX(l, 31, 16)
 141 #define HPET_GCAP_LEG_ROUTE_CAP(l)      BITX(l, 15, 15)
 142 #define HPET_GCAP_CNT_SIZE_CAP(l)       BITX(l, 13, 13)
 143 #define HPET_GCAP_NUM_TIM_CAP(l)        BITX(l, 12, 8)
 144 #define HPET_GCAP_REV_ID(l)             BITX(l, 7, 0)
 145 
 146 /*
 147  * From HPET spec "The value in this field must be less than or equal to":
 148  */
 149 #define HPET_MAX_CLK_PERIOD     (0x5F5E100)
 150 
 151 /*
 152  * Femto seconds in a second.
 153  */
 154 #if defined(__i386)
 155 #define HPET_FEMTO_TO_NANO      (1000000LL)
 156 #define HRTIME_TO_HPET_TICKS(t) (((t) * HPET_FEMTO_TO_NANO) / hpet_info.period)
 157 #else
 158 #define HPET_FEMTO_TO_NANO      (1000000L)
 159 #define HRTIME_TO_HPET_TICKS(t) (((t) * HPET_FEMTO_TO_NANO) / hpet_info.period)
 160 #endif  /* (__i386) */
 161 
 162 /*
 163  * HPET General Configuration Register
 164  */
 165 typedef struct hpet_gen_config_bitfield {
 166         uint32_t        leg_rt_cnf :1;          /* legacy replacement route */
 167         uint32_t        enable_cnf :1;          /* overal enable */
 168 } hpet_gen_conf_t;
 169 
 170 /*
 171  * General Configuration Register fields.
 172  */
 173 #define HPET_GCFR_LEG_RT_CNF            (0x2)           /* bit field value */
 174 #define HPET_GCFR_ENABLE_CNF            (0x1)           /* bit field value */
 175 #define HPET_GCFR_LEG_RT_CNF_BITX(l)    BITX(l, 1, 1)
 176 #define HPET_GCFR_ENABLE_CNF_BITX(l)    BITX(l, 0, 0)
 177 
 178 /*
 179  * General Interrupt Status Register.
 180  */
 181 #define HPET_GIS_T2_INT_STS(l)          BITX(l, 2, 2)
 182 #define HPET_GIS_T1_INT_STS(l)          BITX(l, 1, 1)
 183 #define HPET_GIS_T0_INT_STS(l)          BITX(l, 0, 0)
 184 #define HPET_GIS_TN_INT_STS(l, n)       BITX(l, n, n)
 185 
 186 #define HPET_INTR_STATUS_MASK(timer)    ((uint64_t)1 << (timer))
 187 
 188 /*
 189  * HPET Timer N Configuration and Capabilities Register
 190  */
 191 typedef struct hpet_TN_conf_cap {
 192         uint32_t        int_route_cap;          /* available I/O APIC intrups */
 193         uint32_t        res1            :16;    /* reserved */
 194         uint32_t        fsb_int_del_cap :1;     /* FSB interrupt supported */
 195         uint32_t        fsb_int_en_cnf  :1;     /* Set FSB intr delivery */
 196         uint32_t        int_route_cnf   :5;     /* I/O APIC interrupt to use */
 197         uint32_t        mode32_cnf      :1;     /* Force 32-bit mode */
 198         uint32_t        res2            :1;     /* reserved */
 199         uint32_t        val_set_cnf     :1;     /* Set periodic mode accumula */
 200         uint32_t        size_cap        :1;     /* 1=64bit, 0=32bit timer */
 201         uint32_t        per_int_cap     :1;     /* 1=periodic mode supported */
 202         uint32_t        type_cnf        :1;     /* Enable periodic mode */
 203         uint32_t        int_enb_cnf     :1;     /* Enable interrupt generat */
 204         uint32_t        int_type_cnf    :1;     /* 0=edge, 1=level triggered */
 205         uint32_t        res3            :1;     /* reserved */
 206 } hpet_TN_conf_cap_t;
 207 
 208 /*
 209  * There are 3 to 32 timers on each HPET.
 210  */
 211 #define HPET_TIMER_N_INT_ROUTE_CAP(l)   (l >> 32)
 212 #define HPET_TIMER_N_INT_TYPE_CNF(l)    BITX(l, 1, 1)
 213 #define HPET_TIMER_N_INT_ENB_CNF(l)     BITX(l, 2, 2)
 214 #define HPET_TIMER_N_TYPE_CNF(l)        BITX(l, 3, 3)
 215 #define HPET_TIMER_N_PER_INT_CAP(l)     BITX(l, 4, 4)
 216 #define HPET_TIMER_N_SIZE_CAP(l)        BITX(l, 5, 5)
 217 #define HPET_TIMER_N_VAL_SET_CNF(l)     BITX(l, 6, 6)
 218 #define HPET_TIMER_N_MODE32_CNF(l)      BITX(l, 8, 8)
 219 #define HPET_TIMER_N_INT_ROUTE_CNF(l)   BITX(l, 13, 9)
 220 #define HPET_TIMER_N_FSB_EN_CNF(l)      BITX(l, 14, 14)
 221 #define HPET_TIMER_N_FSB_INT_DEL_CAP(l) BITX(l, 15, 15)
 222 
 223 #define HPET_TIMER_N_INT_TYPE_CNF_BIT   (1 << 1)
 224 #define HPET_TIMER_N_INT_ENB_CNF_BIT    (1 << 2)
 225 #define HPET_TIMER_N_TYPE_CNF_BIT       (1 << 3)
 226 #define HPET_TIMER_N_FSB_EN_CNF_BIT     (1 << 14)
 227 #define HPET_TIMER_N_INT_ROUTE_SHIFT(i) (i << 9)
 228 
 229 /*
 230  * HPET Spec reserves timers 0 and 1 for legacy timer replacement (PIT and RTC).
 231  * Available timers for other use such as LACPI proxy during Deep C-State
 232  * start at timer 2.
 233  */
 234 #define HPET_FIRST_NON_LEGACY_TIMER     (2)
 235 
 236 /*
 237  * HPET timer and interrupt used as LAPIC proxy during deep C-State.
 238  */
 239 typedef struct cstate_timer {
 240         int     timer;
 241         int     intr;
 242 } cstate_timer_t;
 243 
 244 /*
 245  * Data structure of useful HPET device information.
 246  */
 247 typedef struct hpet_info {
 248         hpet_gen_cap_t  gen_cap;
 249         hpet_gen_conf_t gen_config;
 250         uint64_t        gen_intrpt_stat;
 251         uint64_t        main_counter_value;
 252         void            *logical_address;       /* HPET VA memory map */
 253         hpet_TN_conf_cap_t *timer_n_config;     /* N Timer config and cap */
 254         uint32_t        num_timers;             /* number of timers */
 255         uint32_t        allocated_timers;       /* bitmap of timers in use */
 256         cstate_timer_t  cstate_timer;   /* HPET Timer used for LAPIC proxy */
 257         uint64_t        hpet_main_counter_reads[2];
 258         hrtime_t        tsc[3];
 259         hrtime_t        period;         /* counter_clk_period in Femto Secs */
 260 } hpet_info_t;
 261 
 262 #if defined(_KERNEL)
 263 
 264 /*
 265  * Spin mutexes are used in several places because idle threads cannot block.
 266  * These defines provide a mechanism to break out of spin loops to prevent
 267  * system hangs if a CPU can never get the lock (due to an unknown
 268  * hardware/software bug).  100 microsecond was chosen after extensive stress
 269  * testing.
 270  */
 271 #define HPET_SPIN_CHECK         (1000)
 272 #define HPET_SPIN_TIMEOUT       (100000)
 273 
 274 /*
 275  * There is one of these per CPU using the HPET as a proxy for its stalled
 276  * local APIC while in c-state >= C2.
 277  */
 278 typedef hrtime_t hpet_proxy_t;
 279 
 280 extern ACPI_TABLE_HPET  *hpet_table;
 281 extern hpet_info_t      hpet_info;
 282 
 283 #endif  /* defined(_KERNEL) */
 284 
 285 #ifdef __cplusplus
 286 }
 287 #endif
 288 
 289 #endif  /* _HPET_ACPI_H */