^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Intel & MS High Precision Event Timer Implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2003 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Venki Pallipadi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Bob Picco <robert.picco@hp.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/sysctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/bcd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/clocksource.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/hpet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/current.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * The High Precision Event Timer driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * This driver is closely modelled after the rtc.c driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * See HPET spec revision 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define HPET_USER_FREQ (64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define HPET_DRIFT (500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define HPET_RANGE_SIZE 1024 /* from HPET spec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* WARNING -- don't get confused. These macros are never used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * to write the (single) counter, and rarely to read it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * They're badly named; to fix, someday.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #if BITS_PER_LONG == 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define write_counter(V, MC) writeq(V, MC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define read_counter(MC) readq(MC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define write_counter(V, MC) writel(V, MC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define read_counter(MC) readl(MC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static DEFINE_MUTEX(hpet_mutex); /* replaces BKL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* This clocksource driver currently only works on ia64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #ifdef CONFIG_IA64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static void __iomem *hpet_mctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static u64 read_hpet(struct clocksource *cs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return (u64)read_counter((void __iomem *)hpet_mctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static struct clocksource clocksource_hpet = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .name = "hpet",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .rating = 250,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .read = read_hpet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .mask = CLOCKSOURCE_MASK(64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .flags = CLOCK_SOURCE_IS_CONTINUOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static struct clocksource *hpet_clocksource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* A lock for concurrent access by app and isr hpet activity. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static DEFINE_SPINLOCK(hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define HPET_DEV_NAME (7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct hpet_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct hpets *hd_hpets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct hpet __iomem *hd_hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct hpet_timer __iomem *hd_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned long hd_ireqfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned long hd_irqdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) wait_queue_head_t hd_waitqueue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct fasync_struct *hd_async_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned int hd_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned int hd_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned int hd_hdwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) char hd_name[HPET_DEV_NAME];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct hpets {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct hpets *hp_next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct hpet __iomem *hp_hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned long hp_hpet_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct clocksource *hp_clocksource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) unsigned long long hp_tick_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) unsigned long hp_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned int hp_ntimer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) unsigned int hp_which;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct hpet_dev hp_dev[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static struct hpets *hpets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define HPET_OPEN 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define HPET_IE 0x0002 /* interrupt enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define HPET_PERIODIC 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define HPET_SHARED_IRQ 0x0008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #ifndef readq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static inline unsigned long long readq(void __iomem *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #ifndef writeq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static inline void writeq(unsigned long long v, void __iomem *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) writel(v & 0xffffffff, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) writel(v >> 32, addr + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static irqreturn_t hpet_interrupt(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct hpet_dev *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) unsigned long isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) devp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) isr = 1 << (devp - devp->hd_hpets->hp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if ((devp->hd_flags & HPET_SHARED_IRQ) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) !(isr & readl(&devp->hd_hpet->hpet_isr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) spin_lock(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) devp->hd_irqdata++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * For non-periodic timers, increment the accumulator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * This has the effect of treating non-periodic like periodic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned long m, t, mc, base, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct hpet __iomem *hpet = devp->hd_hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct hpets *hpetp = devp->hd_hpets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) t = devp->hd_ireqfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) m = read_counter(&devp->hd_timer->hpet_compare);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) mc = read_counter(&hpet->hpet_mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* The time for the next interrupt would logically be t + m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * however, if we are very unlucky and the interrupt is delayed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * for longer than t then we will completely miss the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * interrupt if we set t + m and an application will hang.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * Therefore we need to make a more complex computation assuming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * that there exists a k for which the following is true:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * k * t + base < mc + delta
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * (k + 1) * t + base > mc + delta
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * where t is the interval in hpet ticks for the given freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * base is the theoretical start value 0 < base < t,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * mc is the main counter value at the time of the interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * delta is the time it takes to write the a value to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * comparator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * k may then be computed as (mc - base + delta) / t .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) base = mc % t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) k = (mc - base + hpetp->hp_delta) / t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) write_counter(t * (k + 1) + base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) &devp->hd_timer->hpet_compare);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (devp->hd_flags & HPET_SHARED_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) writel(isr, &devp->hd_hpet->hpet_isr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) spin_unlock(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) wake_up_interruptible(&devp->hd_waitqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static void hpet_timer_set_irq(struct hpet_dev *devp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int irq, gsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct hpet_timer __iomem *timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) spin_lock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (devp->hd_hdwirq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) timer = devp->hd_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* we prefer level triggered mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) v = readl(&timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (!(v & Tn_INT_TYPE_CNF_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) v |= Tn_INT_TYPE_CNF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) writel(v, &timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) v = (readq(&timer->hpet_config) & Tn_INT_ROUTE_CAP_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) Tn_INT_ROUTE_CAP_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * In PIC mode, skip IRQ0-4, IRQ6-9, IRQ12-15 which is always used by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * legacy device. In IO APIC mode, we skip all the legacy IRQS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) v &= ~0xf3df;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) v &= ~0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) for_each_set_bit(irq, &v, HPET_MAX_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (irq >= nr_irqs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) irq = HPET_MAX_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) gsi = acpi_register_gsi(NULL, irq, ACPI_LEVEL_SENSITIVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ACPI_ACTIVE_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (gsi > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* FIXME: Setup interrupt source table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (irq < HPET_MAX_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) spin_lock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) v = readl(&timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) v |= irq << Tn_INT_ROUTE_CNF_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) writel(v, &timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) devp->hd_hdwirq = gsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static int hpet_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct hpet_dev *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct hpets *hpetp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (file->f_mode & FMODE_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) mutex_lock(&hpet_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) spin_lock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) for (i = 0; i < hpetp->hp_ntimer; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (hpetp->hp_dev[i].hd_flags & HPET_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) devp = &hpetp->hp_dev[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!devp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mutex_unlock(&hpet_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) file->private_data = devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) devp->hd_irqdata = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) devp->hd_flags |= HPET_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) mutex_unlock(&hpet_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) hpet_timer_set_irq(devp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) DECLARE_WAITQUEUE(wait, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) unsigned long data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ssize_t retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct hpet_dev *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) devp = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (!devp->hd_ireqfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (count < sizeof(unsigned long))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) add_wait_queue(&devp->hd_waitqueue, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) for ( ; ; ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) spin_lock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) data = devp->hd_irqdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) devp->hd_irqdata = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) else if (file->f_flags & O_NONBLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) retval = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) } else if (signal_pending(current)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) retval = -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) retval = put_user(data, (unsigned long __user *)buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (!retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) retval = sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) remove_wait_queue(&devp->hd_waitqueue, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static __poll_t hpet_poll(struct file *file, poll_table * wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct hpet_dev *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) devp = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (!devp->hd_ireqfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) poll_wait(file, &devp->hd_waitqueue, wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) spin_lock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) v = devp->hd_irqdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (v != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return EPOLLIN | EPOLLRDNORM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) #ifdef CONFIG_HPET_MMAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) #ifdef CONFIG_HPET_MMAP_DEFAULT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static int hpet_mmap_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static int hpet_mmap_enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static __init int hpet_mmap_enable(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) get_option(&str, &hpet_mmap_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) pr_info("HPET mmap %s\n", hpet_mmap_enabled ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) __setup("hpet_mmap=", hpet_mmap_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct hpet_dev *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (!hpet_mmap_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) devp = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) addr = devp->hd_hpets->hp_hpet_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (addr & (PAGE_SIZE - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return vm_iomap_memory(vma, addr, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static int hpet_fasync(int fd, struct file *file, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct hpet_dev *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) devp = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (fasync_helper(fd, file, on, &devp->hd_async_queue) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static int hpet_release(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct hpet_dev *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct hpet_timer __iomem *timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) devp = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) timer = devp->hd_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) spin_lock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) &timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) irq = devp->hd_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) devp->hd_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) devp->hd_ireqfreq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (devp->hd_flags & HPET_PERIODIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) && readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) v = readq(&timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) v ^= Tn_TYPE_CNF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) writeq(v, &timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) devp->hd_flags &= ~(HPET_OPEN | HPET_IE | HPET_PERIODIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) free_irq(irq, devp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) file->private_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static int hpet_ioctl_ieon(struct hpet_dev *devp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct hpet_timer __iomem *timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct hpet __iomem *hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct hpets *hpetp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) unsigned long g, v, t, m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) unsigned long flags, isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) timer = devp->hd_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) hpet = devp->hd_hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) hpetp = devp->hd_hpets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (!devp->hd_ireqfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) spin_lock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (devp->hd_flags & HPET_IE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) devp->hd_flags |= HPET_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (readl(&timer->hpet_config) & Tn_INT_TYPE_CNF_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) devp->hd_flags |= HPET_SHARED_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) irq = devp->hd_hdwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) unsigned long irq_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (devp->hd_flags & HPET_SHARED_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * To prevent the interrupt handler from seeing an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * unwanted interrupt status bit, program the timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * so that it will not fire in the near future ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) writel(readl(&timer->hpet_config) & ~Tn_TYPE_CNF_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) &timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) write_counter(read_counter(&hpet->hpet_mc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) &timer->hpet_compare);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* ... and clear any left-over status. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) isr = 1 << (devp - devp->hd_hpets->hp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) writel(isr, &hpet->hpet_isr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) irq_flags = devp->hd_flags & HPET_SHARED_IRQ ? IRQF_SHARED : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (request_irq(irq, hpet_interrupt, irq_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) devp->hd_name, (void *)devp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (irq == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) spin_lock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) devp->hd_flags ^= HPET_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) spin_unlock_irq(&hpet_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) devp->hd_irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) t = devp->hd_ireqfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) v = readq(&timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* 64-bit comparators are not yet supported through the ioctls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * so force this into 32-bit mode if it supports both modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) g = v | Tn_32MODE_CNF_MASK | Tn_INT_ENB_CNF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (devp->hd_flags & HPET_PERIODIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) g |= Tn_TYPE_CNF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) v |= Tn_TYPE_CNF_MASK | Tn_VAL_SET_CNF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) writeq(v, &timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * NOTE: First we modify the hidden accumulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * register supported by periodic-capable comparators.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * We never want to modify the (single) counter; that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * would affect all the comparators. The value written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * is the counter value when the first interrupt is due.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) m = read_counter(&hpet->hpet_mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * Then we modify the comparator, indicating the period
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * for subsequent interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) write_counter(t, &timer->hpet_compare);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) m = read_counter(&hpet->hpet_mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (devp->hd_flags & HPET_SHARED_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) isr = 1 << (devp - devp->hd_hpets->hp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) writel(isr, &hpet->hpet_isr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) writeq(g, &timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /* converts Hz to number of timer ticks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static inline unsigned long hpet_time_div(struct hpets *hpets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) unsigned long dis)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) unsigned long long m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) m = hpets->hp_tick_freq + (dis >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return div64_ul(m, dis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) hpet_ioctl_common(struct hpet_dev *devp, unsigned int cmd, unsigned long arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct hpet_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct hpet_timer __iomem *timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) struct hpets *hpetp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) case HPET_IE_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) case HPET_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) case HPET_EPI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) case HPET_DPI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) case HPET_IRQFREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) timer = devp->hd_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) hpetp = devp->hd_hpets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) case HPET_IE_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return hpet_ioctl_ieon(devp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) case HPET_IE_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if ((devp->hd_flags & HPET_IE) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) v = readq(&timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) v &= ~Tn_INT_ENB_CNF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) writeq(v, &timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (devp->hd_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) free_irq(devp->hd_irq, devp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) devp->hd_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) devp->hd_flags ^= HPET_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) case HPET_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) memset(info, 0, sizeof(*info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (devp->hd_ireqfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) info->hi_ireqfreq =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) hpet_time_div(hpetp, devp->hd_ireqfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) info->hi_flags =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) info->hi_hpet = hpetp->hp_which;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) info->hi_timer = devp - hpetp->hp_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) case HPET_EPI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) v = readq(&timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if ((v & Tn_PER_INT_CAP_MASK) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) devp->hd_flags |= HPET_PERIODIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) case HPET_DPI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) v = readq(&timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if ((v & Tn_PER_INT_CAP_MASK) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (devp->hd_flags & HPET_PERIODIC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) readq(&timer->hpet_config) & Tn_TYPE_CNF_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) v = readq(&timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) v ^= Tn_TYPE_CNF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) writeq(v, &timer->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) devp->hd_flags &= ~HPET_PERIODIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) case HPET_IRQFREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if ((arg > hpet_max_freq) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) !capable(CAP_SYS_RESOURCE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) err = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (!arg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) devp->hd_ireqfreq = hpet_time_div(hpetp, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) hpet_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct hpet_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) mutex_lock(&hpet_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) mutex_unlock(&hpet_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if ((cmd == HPET_INFO) && !err &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) (copy_to_user((void __user *)arg, &info, sizeof(info))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct compat_hpet_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) compat_ulong_t hi_ireqfreq; /* Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) compat_ulong_t hi_flags; /* information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) unsigned short hi_hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) unsigned short hi_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) static long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct hpet_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) mutex_lock(&hpet_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) mutex_unlock(&hpet_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if ((cmd == HPET_INFO) && !err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct compat_hpet_info __user *u = compat_ptr(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (put_user(info.hi_ireqfreq, &u->hi_ireqfreq) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) put_user(info.hi_flags, &u->hi_flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) put_user(info.hi_hpet, &u->hi_hpet) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) put_user(info.hi_timer, &u->hi_timer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static const struct file_operations hpet_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) .read = hpet_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) .poll = hpet_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) .unlocked_ioctl = hpet_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) .compat_ioctl = hpet_compat_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) .open = hpet_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) .release = hpet_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) .fasync = hpet_fasync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) .mmap = hpet_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static int hpet_is_known(struct hpet_data *hdp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct hpets *hpetp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (hpetp->hp_hpet_phys == hdp->hd_phys_address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) static struct ctl_table hpet_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) .procname = "max-user-freq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) .data = &hpet_max_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) .maxlen = sizeof(int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) .mode = 0644,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) .proc_handler = proc_dointvec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) static struct ctl_table hpet_root[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) .procname = "hpet",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) .maxlen = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) .mode = 0555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) .child = hpet_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static struct ctl_table dev_root[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) .procname = "dev",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) .maxlen = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) .mode = 0555,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) .child = hpet_root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) static struct ctl_table_header *sysctl_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * Adjustment for when arming the timer with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * initial conditions. That is, main counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * ticks expired before interrupts are enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) #define TICK_CALIBRATE (1000UL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) static unsigned long __hpet_calibrate(struct hpets *hpetp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) struct hpet_timer __iomem *timer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) unsigned long t, m, count, i, flags, start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) struct hpet_dev *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) struct hpet __iomem *hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) for (j = 0, devp = hpetp->hp_dev; j < hpetp->hp_ntimer; j++, devp++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if ((devp->hd_flags & HPET_OPEN) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) timer = devp->hd_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (!timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) hpet = hpetp->hp_hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) t = read_counter(&timer->hpet_compare);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) count = hpet_time_div(hpetp, TICK_CALIBRATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) start = read_counter(&hpet->hpet_mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) m = read_counter(&hpet->hpet_mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) } while (i++, (m - start) < count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return (m - start) / i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) static unsigned long hpet_calibrate(struct hpets *hpetp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) unsigned long ret = ~0UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * Try to calibrate until return value becomes stable small value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * If SMI interruption occurs in calibration loop, the return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * will be big. This avoids its impact.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) for ( ; ; ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) tmp = __hpet_calibrate(hpetp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (ret <= tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) ret = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) int hpet_alloc(struct hpet_data *hdp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) u64 cap, mcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) struct hpet_dev *devp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) u32 i, ntimer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) struct hpets *hpetp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) struct hpet __iomem *hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static struct hpets *last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) unsigned long period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) unsigned long long temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) u32 remainder;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * hpet_alloc can be called by platform dependent code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * If platform dependent code has allocated the hpet that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * ACPI has also reported, then we catch it here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (hpet_is_known(hdp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) printk(KERN_DEBUG "%s: duplicate HPET ignored\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) hpetp = kzalloc(struct_size(hpetp, hp_dev, hdp->hd_nirqs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (!hpetp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) hpetp->hp_which = hpet_nhpet++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) hpetp->hp_hpet = hdp->hd_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) hpetp->hp_hpet_phys = hdp->hd_phys_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) hpetp->hp_ntimer = hdp->hd_nirqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) for (i = 0; i < hdp->hd_nirqs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) hpet = hpetp->hp_hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) cap = readq(&hpet->hpet_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) ntimer = ((cap & HPET_NUM_TIM_CAP_MASK) >> HPET_NUM_TIM_CAP_SHIFT) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (hpetp->hp_ntimer != ntimer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) printk(KERN_WARNING "hpet: number irqs doesn't agree"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) " with number of timers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) kfree(hpetp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) last->hp_next = hpetp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) hpets = hpetp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) last = hpetp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) HPET_COUNTER_CLK_PERIOD_SHIFT; /* fs, 10^-15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) temp = 1000000000000000uLL; /* 10^15 femtoseconds per second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) temp += period >> 1; /* round */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) do_div(temp, period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) hpetp->hp_tick_freq = temp; /* ticks per second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) hpetp->hp_which, hdp->hd_phys_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) hpetp->hp_ntimer > 1 ? "s" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) for (i = 0; i < hpetp->hp_ntimer; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) printk(KERN_CONT "%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) printk(KERN_CONT "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) temp = hpetp->hp_tick_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) remainder = do_div(temp, 1000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) printk(KERN_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) "hpet%u: %u comparators, %d-bit %u.%06u MHz counter\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) hpetp->hp_which, hpetp->hp_ntimer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) cap & HPET_COUNTER_SIZE_MASK ? 64 : 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) (unsigned) temp, remainder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) mcfg = readq(&hpet->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) write_counter(0L, &hpet->hpet_mc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) mcfg |= HPET_ENABLE_CNF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) writeq(mcfg, &hpet->hpet_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; i++, devp++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct hpet_timer __iomem *timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) devp->hd_hpets = hpetp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) devp->hd_hpet = hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) devp->hd_timer = timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) * If the timer was reserved by platform code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * then make timer unavailable for opens.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (hdp->hd_state & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) devp->hd_flags = HPET_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) init_waitqueue_head(&devp->hd_waitqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) hpetp->hp_delta = hpet_calibrate(hpetp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /* This clocksource driver currently only works on ia64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) #ifdef CONFIG_IA64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (!hpet_clocksource) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) clocksource_hpet.archdata.fsys_mmio = hpet_mctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) clocksource_register_hz(&clocksource_hpet, hpetp->hp_tick_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) hpetp->hp_clocksource = &clocksource_hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) hpet_clocksource = &clocksource_hpet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) static acpi_status hpet_resources(struct acpi_resource *res, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) struct hpet_data *hdp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct acpi_resource_address64 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) hdp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) status = acpi_resource_to_address64(res, &addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (ACPI_SUCCESS(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) hdp->hd_phys_address = addr.address.minimum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) hdp->hd_address = ioremap(addr.address.minimum, addr.address.address_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (!hdp->hd_address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) return AE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (hpet_is_known(hdp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) iounmap(hdp->hd_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) return AE_ALREADY_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) struct acpi_resource_fixed_memory32 *fixmem32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) fixmem32 = &res->data.fixed_memory32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) hdp->hd_phys_address = fixmem32->address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) hdp->hd_address = ioremap(fixmem32->address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) HPET_RANGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (!hdp->hd_address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return AE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (hpet_is_known(hdp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) iounmap(hdp->hd_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) return AE_ALREADY_EXISTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct acpi_resource_extended_irq *irqp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) int i, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) irqp = &res->data.extended_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) for (i = 0; i < irqp->interrupt_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (hdp->hd_nirqs >= HPET_MAX_TIMERS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) irq = acpi_register_gsi(NULL, irqp->interrupts[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) irqp->triggering, irqp->polarity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return AE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) hdp->hd_irq[hdp->hd_nirqs] = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) hdp->hd_nirqs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) static int hpet_acpi_add(struct acpi_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) acpi_status result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) struct hpet_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) memset(&data, 0, sizeof(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) acpi_walk_resources(device->handle, METHOD_NAME__CRS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) hpet_resources, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) if (ACPI_FAILURE(result))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) if (!data.hd_address || !data.hd_nirqs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (data.hd_address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) iounmap(data.hd_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) printk("%s: no address or irqs in _CRS\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return hpet_alloc(&data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) static const struct acpi_device_id hpet_device_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) {"PNP0103", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) {"", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static struct acpi_driver hpet_acpi_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) .name = "hpet",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) .ids = hpet_device_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) .ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) .add = hpet_acpi_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) static int __init hpet_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) result = misc_register(&hpet_misc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) sysctl_header = register_sysctl_table(dev_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) result = acpi_bus_register_driver(&hpet_acpi_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if (sysctl_header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) unregister_sysctl_table(sysctl_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) misc_deregister(&hpet_misc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) device_initcall(hpet_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) MODULE_AUTHOR("Bob Picco <Robert.Picco@hp.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) */