|
@@ -53,6 +53,11 @@
|
|
|
|
|
|
#define HPET_RANGE_SIZE 1024 /* from HPET spec */
|
|
|
|
|
|
+
|
|
|
+/* WARNING -- don't get confused. These macros are never used
|
|
|
+ * to write the (single) counter, and rarely to read it.
|
|
|
+ * They're badly named; to fix, someday.
|
|
|
+ */
|
|
|
#if BITS_PER_LONG == 64
|
|
|
#define write_counter(V, MC) writeq(V, MC)
|
|
|
#define read_counter(MC) readq(MC)
|
|
@@ -77,7 +82,7 @@ static struct clocksource clocksource_hpet = {
|
|
|
.rating = 250,
|
|
|
.read = read_hpet,
|
|
|
.mask = CLOCKSOURCE_MASK(64),
|
|
|
- .mult = 0, /*to be caluclated*/
|
|
|
+ .mult = 0, /* to be calculated */
|
|
|
.shift = 10,
|
|
|
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
|
|
};
|
|
@@ -86,8 +91,6 @@ static struct clocksource *hpet_clocksource;
|
|
|
|
|
|
/* A lock for concurrent access by app and isr hpet activity. */
|
|
|
static DEFINE_SPINLOCK(hpet_lock);
|
|
|
-/* A lock for concurrent intermodule access to hpet and isr hpet activity. */
|
|
|
-static DEFINE_SPINLOCK(hpet_task_lock);
|
|
|
|
|
|
#define HPET_DEV_NAME (7)
|
|
|
|
|
@@ -99,7 +102,6 @@ struct hpet_dev {
|
|
|
unsigned long hd_irqdata;
|
|
|
wait_queue_head_t hd_waitqueue;
|
|
|
struct fasync_struct *hd_async_queue;
|
|
|
- struct hpet_task *hd_task;
|
|
|
unsigned int hd_flags;
|
|
|
unsigned int hd_irq;
|
|
|
unsigned int hd_hdwirq;
|
|
@@ -173,11 +175,6 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
|
|
|
writel(isr, &devp->hd_hpet->hpet_isr);
|
|
|
spin_unlock(&hpet_lock);
|
|
|
|
|
|
- spin_lock(&hpet_task_lock);
|
|
|
- if (devp->hd_task)
|
|
|
- devp->hd_task->ht_func(devp->hd_task->ht_data);
|
|
|
- spin_unlock(&hpet_task_lock);
|
|
|
-
|
|
|
wake_up_interruptible(&devp->hd_waitqueue);
|
|
|
|
|
|
kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN);
|
|
@@ -260,8 +257,7 @@ static int hpet_open(struct inode *inode, struct file *file)
|
|
|
|
|
|
for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
|
|
|
for (i = 0; i < hpetp->hp_ntimer; i++)
|
|
|
- if (hpetp->hp_dev[i].hd_flags & HPET_OPEN
|
|
|
- || hpetp->hp_dev[i].hd_task)
|
|
|
+ if (hpetp->hp_dev[i].hd_flags & HPET_OPEN)
|
|
|
continue;
|
|
|
else {
|
|
|
devp = &hpetp->hp_dev[i];
|
|
@@ -504,7 +500,11 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
|
|
|
devp->hd_irq = irq;
|
|
|
t = devp->hd_ireqfreq;
|
|
|
v = readq(&timer->hpet_config);
|
|
|
- g = v | Tn_INT_ENB_CNF_MASK;
|
|
|
+
|
|
|
+ /* 64-bit comparators are not yet supported through the ioctls,
|
|
|
+ * so force this into 32-bit mode if it supports both modes
|
|
|
+ */
|
|
|
+ g = v | Tn_32MODE_CNF_MASK | Tn_INT_ENB_CNF_MASK;
|
|
|
|
|
|
if (devp->hd_flags & HPET_PERIODIC) {
|
|
|
write_counter(t, &timer->hpet_compare);
|
|
@@ -514,6 +514,12 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
|
|
|
v |= Tn_VAL_SET_CNF_MASK;
|
|
|
writeq(v, &timer->hpet_config);
|
|
|
local_irq_save(flags);
|
|
|
+
|
|
|
+ /* NOTE: what we modify here is a hidden accumulator
|
|
|
+ * register supported by periodic-capable comparators.
|
|
|
+ * We never want to modify the (single) counter; that
|
|
|
+ * would affect all the comparators.
|
|
|
+ */
|
|
|
m = read_counter(&hpet->hpet_mc);
|
|
|
write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
|
|
|
} else {
|
|
@@ -667,57 +673,6 @@ static int hpet_is_known(struct hpet_data *hdp)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static inline int hpet_tpcheck(struct hpet_task *tp)
|
|
|
-{
|
|
|
- struct hpet_dev *devp;
|
|
|
- struct hpets *hpetp;
|
|
|
-
|
|
|
- devp = tp->ht_opaque;
|
|
|
-
|
|
|
- if (!devp)
|
|
|
- return -ENXIO;
|
|
|
-
|
|
|
- for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
|
|
|
- if (devp >= hpetp->hp_dev
|
|
|
- && devp < (hpetp->hp_dev + hpetp->hp_ntimer)
|
|
|
- && devp->hd_hpet == hpetp->hp_hpet)
|
|
|
- return 0;
|
|
|
-
|
|
|
- return -ENXIO;
|
|
|
-}
|
|
|
-
|
|
|
-#if 0
|
|
|
-int hpet_unregister(struct hpet_task *tp)
|
|
|
-{
|
|
|
- struct hpet_dev *devp;
|
|
|
- struct hpet_timer __iomem *timer;
|
|
|
- int err;
|
|
|
-
|
|
|
- if ((err = hpet_tpcheck(tp)))
|
|
|
- return err;
|
|
|
-
|
|
|
- spin_lock_irq(&hpet_task_lock);
|
|
|
- spin_lock(&hpet_lock);
|
|
|
-
|
|
|
- devp = tp->ht_opaque;
|
|
|
- if (devp->hd_task != tp) {
|
|
|
- spin_unlock(&hpet_lock);
|
|
|
- spin_unlock_irq(&hpet_task_lock);
|
|
|
- return -ENXIO;
|
|
|
- }
|
|
|
-
|
|
|
- timer = devp->hd_timer;
|
|
|
- writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
|
|
|
- &timer->hpet_config);
|
|
|
- devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC);
|
|
|
- devp->hd_task = NULL;
|
|
|
- spin_unlock(&hpet_lock);
|
|
|
- spin_unlock_irq(&hpet_task_lock);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-#endif /* 0 */
|
|
|
-
|
|
|
static ctl_table hpet_table[] = {
|
|
|
{
|
|
|
.ctl_name = CTL_UNNUMBERED,
|
|
@@ -872,9 +827,12 @@ int hpet_alloc(struct hpet_data *hdp)
|
|
|
printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
|
|
|
printk("\n");
|
|
|
|
|
|
- printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n",
|
|
|
- hpetp->hp_which, hpetp->hp_ntimer,
|
|
|
- cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq);
|
|
|
+ printk(KERN_INFO
|
|
|
+ "hpet%u: %u comparators, %d-bit %u.%06u MHz counter\n",
|
|
|
+ hpetp->hp_which, hpetp->hp_ntimer,
|
|
|
+ cap & HPET_COUNTER_SIZE_MASK ? 64 : 32,
|
|
|
+ (unsigned) (hpetp->hp_tick_freq / 1000000),
|
|
|
+ (unsigned) (hpetp->hp_tick_freq % 1000000));
|
|
|
|
|
|
mcfg = readq(&hpet->hpet_config);
|
|
|
if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
|