Diff for /qemu/hw/arm_timer.c between versions 1.1.1.11 and 1.1.1.12

version 1.1.1.11, 2018/04/24 19:27:58 version 1.1.1.12, 2018/04/24 19:47:42
Line 9 Line 9
   
 #include "sysbus.h"  #include "sysbus.h"
 #include "qemu-timer.h"  #include "qemu-timer.h"
   #include "qemu-common.h"
   #include "qdev.h"
   #include "ptimer.h"
   
 /* Common timer implementation.  */  /* Common timer implementation.  */
   
Line 61  static uint32_t arm_timer_read(void *opa Line 64  static uint32_t arm_timer_read(void *opa
             return 0;              return 0;
         return s->int_level;          return s->int_level;
     default:      default:
         hw_error("arm_timer_read: Bad offset %x\n", (int)offset);          hw_error("%s: Bad offset %x\n", __func__, (int)offset);
         return 0;          return 0;
     }      }
 }  }
Line 128  static void arm_timer_write(void *opaque Line 131  static void arm_timer_write(void *opaque
         arm_timer_recalibrate(s, 0);          arm_timer_recalibrate(s, 0);
         break;          break;
     default:      default:
         hw_error("arm_timer_write: Bad offset %x\n", (int)offset);          hw_error("%s: Bad offset %x\n", __func__, (int)offset);
     }      }
     arm_timer_update(s);      arm_timer_update(s);
 }  }
Line 170  static arm_timer_state *arm_timer_init(u Line 173  static arm_timer_state *arm_timer_init(u
 }  }
   
 /* ARM PrimeCell SP804 dual timer module.  /* ARM PrimeCell SP804 dual timer module.
    Docs for this device don't seem to be publicly available.  This   * Docs at
    implementation is based on guesswork, the linux kernel sources and the   * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html
    Integrator/CP timer modules.  */  */
   
 typedef struct {  typedef struct {
     SysBusDevice busdev;      SysBusDevice busdev;
     MemoryRegion iomem;      MemoryRegion iomem;
     arm_timer_state *timer[2];      arm_timer_state *timer[2];
       uint32_t freq0, freq1;
     int level[2];      int level[2];
     qemu_irq irq;      qemu_irq irq;
 } sp804_state;  } sp804_state;
   
   static const uint8_t sp804_ids[] = {
       /* Timer ID */
       0x04, 0x18, 0x14, 0,
       /* PrimeCell ID */
       0xd, 0xf0, 0x05, 0xb1
   };
   
 /* Merge the IRQs from the two component devices.  */  /* Merge the IRQs from the two component devices.  */
 static void sp804_set_irq(void *opaque, int irq, int level)  static void sp804_set_irq(void *opaque, int irq, int level)
 {  {
Line 196  static uint64_t sp804_read(void *opaque, Line 207  static uint64_t sp804_read(void *opaque,
 {  {
     sp804_state *s = (sp804_state *)opaque;      sp804_state *s = (sp804_state *)opaque;
   
     /* ??? Don't know the PrimeCell ID for this device.  */  
     if (offset < 0x20) {      if (offset < 0x20) {
         return arm_timer_read(s->timer[0], offset);          return arm_timer_read(s->timer[0], offset);
     } else {      }
       if (offset < 0x40) {
         return arm_timer_read(s->timer[1], offset - 0x20);          return arm_timer_read(s->timer[1], offset - 0x20);
     }      }
   
       /* TimerPeriphID */
       if (offset >= 0xfe0 && offset <= 0xffc) {
           return sp804_ids[(offset - 0xfe0) >> 2];
       }
   
       switch (offset) {
       /* Integration Test control registers, which we won't support */
       case 0xf00: /* TimerITCR */
       case 0xf04: /* TimerITOP (strictly write only but..) */
           return 0;
       }
   
       hw_error("%s: Bad offset %x\n", __func__, (int)offset);
       return 0;
 }  }
   
 static void sp804_write(void *opaque, target_phys_addr_t offset,  static void sp804_write(void *opaque, target_phys_addr_t offset,
Line 211  static void sp804_write(void *opaque, ta Line 237  static void sp804_write(void *opaque, ta
   
     if (offset < 0x20) {      if (offset < 0x20) {
         arm_timer_write(s->timer[0], offset, value);          arm_timer_write(s->timer[0], offset, value);
     } else {          return;
       }
   
       if (offset < 0x40) {
         arm_timer_write(s->timer[1], offset - 0x20, value);          arm_timer_write(s->timer[1], offset - 0x20, value);
           return;
     }      }
   
       /* Technically we could be writing to the Test Registers, but not likely */
       hw_error("%s: Bad offset %x\n", __func__, (int)offset);
 }  }
   
 static const MemoryRegionOps sp804_ops = {  static const MemoryRegionOps sp804_ops = {
Line 240  static int sp804_init(SysBusDevice *dev) Line 273  static int sp804_init(SysBusDevice *dev)
   
     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);      qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     sysbus_init_irq(dev, &s->irq);      sysbus_init_irq(dev, &s->irq);
     /* ??? The timers are actually configurable between 32kHz and 1MHz, but      s->timer[0] = arm_timer_init(s->freq0);
        we don't implement that.  */      s->timer[1] = arm_timer_init(s->freq1);
     s->timer[0] = arm_timer_init(1000000);  
     s->timer[1] = arm_timer_init(1000000);  
     s->timer[0]->irq = qi[0];      s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];      s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);      memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
     sysbus_init_mmio_region(dev, &s->iomem);      sysbus_init_mmio(dev, &s->iomem);
     vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);      vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
     return 0;      return 0;
 }  }
   
   
 /* Integrator/CP timer module.  */  /* Integrator/CP timer module.  */
   
 typedef struct {  typedef struct {
Line 270  static uint64_t icp_pit_read(void *opaqu Line 300  static uint64_t icp_pit_read(void *opaqu
     /* ??? Don't know the PrimeCell ID for this device.  */      /* ??? Don't know the PrimeCell ID for this device.  */
     n = offset >> 8;      n = offset >> 8;
     if (n > 2) {      if (n > 2) {
         hw_error("sp804_read: Bad timer %d\n", n);          hw_error("%s: Bad timer %d\n", __func__, n);
     }      }
   
     return arm_timer_read(s->timer[n], offset & 0xff);      return arm_timer_read(s->timer[n], offset & 0xff);
Line 284  static void icp_pit_write(void *opaque,  Line 314  static void icp_pit_write(void *opaque, 
   
     n = offset >> 8;      n = offset >> 8;
     if (n > 2) {      if (n > 2) {
         hw_error("sp804_write: Bad timer %d\n", n);          hw_error("%s: Bad timer %d\n", __func__, n);
     }      }
   
     arm_timer_write(s->timer[n], offset & 0xff, value);      arm_timer_write(s->timer[n], offset & 0xff, value);
Line 311  static int icp_pit_init(SysBusDevice *de Line 341  static int icp_pit_init(SysBusDevice *de
     sysbus_init_irq(dev, &s->timer[2]->irq);      sysbus_init_irq(dev, &s->timer[2]->irq);
   
     memory_region_init_io(&s->iomem, &icp_pit_ops, s, "icp_pit", 0x1000);      memory_region_init_io(&s->iomem, &icp_pit_ops, s, "icp_pit", 0x1000);
     sysbus_init_mmio_region(dev, &s->iomem);      sysbus_init_mmio(dev, &s->iomem);
     /* This device has no state to save/restore.  The component timers will      /* This device has no state to save/restore.  The component timers will
        save themselves.  */         save themselves.  */
     return 0;      return 0;
 }  }
   
 static void arm_timer_register_devices(void)  static void icp_pit_class_init(ObjectClass *klass, void *data)
   {
       SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
   
       sdc->init = icp_pit_init;
   }
   
   static TypeInfo icp_pit_info = {
       .name          = "integrator_pit",
       .parent        = TYPE_SYS_BUS_DEVICE,
       .instance_size = sizeof(icp_pit_state),
       .class_init    = icp_pit_class_init,
   };
   
   static Property sp804_properties[] = {
       DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000),
       DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000),
       DEFINE_PROP_END_OF_LIST(),
   };
   
   static void sp804_class_init(ObjectClass *klass, void *data)
   {
       SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
       DeviceClass *k = DEVICE_CLASS(klass);
   
       sdc->init = sp804_init;
       k->props = sp804_properties;
   }
   
   static TypeInfo sp804_info = {
       .name          = "sp804",
       .parent        = TYPE_SYS_BUS_DEVICE,
       .instance_size = sizeof(sp804_state),
       .class_init    = sp804_class_init,
   };
   
   static void arm_timer_register_types(void)
 {  {
     sysbus_register_dev("integrator_pit", sizeof(icp_pit_state), icp_pit_init);      type_register_static(&icp_pit_info);
     sysbus_register_dev("sp804", sizeof(sp804_state), sp804_init);      type_register_static(&sp804_info);
 }  }
   
 device_init(arm_timer_register_devices)  type_init(arm_timer_register_types)

Removed from v.1.1.1.11  
changed lines
  Added in v.1.1.1.12


unix.superglobalmegacorp.com