]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/char/hpet.c
[PATCH] pcmcia: new suspend core
[linux-2.6-omap-h63xx.git] / drivers / char / hpet.c
index 0159c463f0f9b6dfad57fa687cff9f8621e2252a..3808d95726195d3bb5c18ab8946d77cc341d765b 100644 (file)
@@ -49,6 +49,8 @@
 #define        HPET_USER_FREQ  (64)
 #define        HPET_DRIFT      (500)
 
+#define HPET_RANGE_SIZE                1024    /* from HPET spec */
+
 static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
 
 /* A lock for concurrent access by app and isr hpet activity. */
@@ -282,7 +284,8 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
 
        if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
                                        PAGE_SIZE, vma->vm_page_prot)) {
-               printk(KERN_ERR "remap_pfn_range failed in hpet.c\n");
+               printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
+                       __FUNCTION__);
                return -EAGAIN;
        }
 
@@ -563,6 +566,17 @@ static struct file_operations hpet_fops = {
        .mmap = hpet_mmap,
 };
 
+static int hpet_is_known(struct hpet_data *hdp)
+{
+       struct hpets *hpetp;
+
+       for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
+               if (hpetp->hp_hpet_phys == hdp->hd_phys_address)
+                       return 1;
+
+       return 0;
+}
+
 EXPORT_SYMBOL(hpet_alloc);
 EXPORT_SYMBOL(hpet_register);
 EXPORT_SYMBOL(hpet_unregister);
@@ -728,11 +742,10 @@ static void hpet_register_interpolator(struct hpets *hpetp)
 #ifdef CONFIG_TIME_INTERPOLATION
        struct time_interpolator *ti;
 
-       ti = kmalloc(sizeof(*ti), GFP_KERNEL);
+       ti = kzalloc(sizeof(*ti), GFP_KERNEL);
        if (!ti)
                return;
 
-       memset(ti, 0, sizeof(*ti));
        ti->source = TIME_SOURCE_MMIO64;
        ti->shift = 10;
        ti->addr = &hpetp->hp_hpet->hpet_mc;
@@ -797,29 +810,29 @@ int hpet_alloc(struct hpet_data *hdp)
        struct hpets *hpetp;
        size_t siz;
        struct hpet __iomem *hpet;
-       static struct hpets *last = (struct hpets *)0;
+       static struct hpets *last = NULL;
        unsigned long period;
        unsigned long long temp;
 
        /*
         * hpet_alloc can be called by platform dependent code.
-        * if platform dependent code has allocated the hpet
-        * ACPI also reports hpet, then we catch it here.
+        * If platform dependent code has allocated the hpet that
+        * ACPI has also reported, then we catch it here.
         */
-       for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-               if (hpetp->hp_hpet == hdp->hd_address)
-                       return 0;
+       if (hpet_is_known(hdp)) {
+               printk(KERN_DEBUG "%s: duplicate HPET ignored\n",
+                       __FUNCTION__);
+               return 0;
+       }
 
        siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
                                      sizeof(struct hpet_dev));
 
-       hpetp = kmalloc(siz, GFP_KERNEL);
+       hpetp = kzalloc(siz, GFP_KERNEL);
 
        if (!hpetp)
                return -ENOMEM;
 
-       memset(hpetp, 0, siz);
-
        hpetp->hp_which = hpet_nhpet++;
        hpetp->hp_hpet = hdp->hd_address;
        hpetp->hp_hpet_phys = hdp->hd_phys_address;
@@ -856,8 +869,8 @@ int hpet_alloc(struct hpet_data *hdp)
        do_div(temp, period);
        hpetp->hp_tick_freq = temp; /* ticks per second */
 
-       printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s",
-               hpetp->hp_which, hdp->hd_phys_address,
+       printk(KERN_INFO "hpet%d: at MMIO 0x%lx (virtual 0x%p), IRQ%s",
+               hpetp->hp_which, hdp->hd_phys_address, hdp->hd_address,
                hpetp->hp_ntimer > 1 ? "s" : "");
        for (i = 0; i < hpetp->hp_ntimer; i++)
                printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
@@ -906,7 +919,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
        struct hpet_data *hdp;
        acpi_status status;
        struct acpi_resource_address64 addr;
-       struct hpets *hpetp;
 
        hdp = data;
 
@@ -919,9 +931,29 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
                hdp->hd_phys_address = addr.min_address_range;
                hdp->hd_address = ioremap(addr.min_address_range, size);
 
-               for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-                       if (hpetp->hp_hpet == hdp->hd_address)
-                               return -EBUSY;
+               if (hpet_is_known(hdp)) {
+                       printk(KERN_DEBUG "%s: 0x%lx is busy\n",
+                               __FUNCTION__, hdp->hd_phys_address);
+                       iounmap(hdp->hd_address);
+                       return -EBUSY;
+               }
+       } else if (res->id == ACPI_RSTYPE_FIXED_MEM32) {
+               struct acpi_resource_fixed_mem32 *fixmem32;
+
+               fixmem32 = &res->data.fixed_memory32;
+               if (!fixmem32)
+                       return -EINVAL;
+
+               hdp->hd_phys_address = fixmem32->range_base_address;
+               hdp->hd_address = ioremap(fixmem32->range_base_address,
+                                               HPET_RANGE_SIZE);
+
+               if (hpet_is_known(hdp)) {
+                       printk(KERN_DEBUG "%s: 0x%lx is busy\n",
+                               __FUNCTION__, hdp->hd_phys_address);
+                       iounmap(hdp->hd_address);
+                       return -EBUSY;
+               }
        } else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
                struct acpi_resource_ext_irq *irqp;
                int i;