generic_timer.cc (10845:75df7a87be83) generic_timer.cc (10847:1826ee736709)
1/*
2 * Copyright (c) 2013, 2015 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 29 unchanged lines hidden (view full) ---

38 * Andreas Sandberg
39 */
40
41#include "dev/arm/generic_timer.hh"
42
43#include "arch/arm/system.hh"
44#include "debug/Timer.hh"
45#include "dev/arm/base_gic.hh"
1/*
2 * Copyright (c) 2013, 2015 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 29 unchanged lines hidden (view full) ---

38 * Andreas Sandberg
39 */
40
41#include "dev/arm/generic_timer.hh"
42
43#include "arch/arm/system.hh"
44#include "debug/Timer.hh"
45#include "dev/arm/base_gic.hh"
46#include "mem/packet_access.hh"
46#include "params/GenericTimer.hh"
47#include "params/GenericTimer.hh"
48#include "params/GenericTimerMem.hh"
47
48SystemCounter::SystemCounter()
49 : _freq(0), _period(0), _resetTick(0), _regCntkctl(0)
50{
51 setFreq(0x01800000);
52}
53
54void

--- 419 unchanged lines hidden (view full) ---

474
475 default:
476 warn("Reading from unknown register: %s\n", miscRegName[reg]);
477 return 0;
478 }
479}
480
481
49
50SystemCounter::SystemCounter()
51 : _freq(0), _period(0), _resetTick(0), _regCntkctl(0)
52{
53 setFreq(0x01800000);
54}
55
56void

--- 419 unchanged lines hidden (view full) ---

476
477 default:
478 warn("Reading from unknown register: %s\n", miscRegName[reg]);
479 return 0;
480 }
481}
482
483
484
485GenericTimerMem::GenericTimerMem(GenericTimerMemParams *p)
486 : PioDevice(p),
487 ctrlRange(RangeSize(p->base, TheISA::PageBytes)),
488 timerRange(RangeSize(p->base + TheISA::PageBytes, TheISA::PageBytes)),
489 addrRanges{ctrlRange, timerRange},
490 systemCounter(),
491 physTimer(csprintf("%s.phys_timer0", name()),
492 *this, systemCounter,
493 ArchTimer::Interrupt(*p->gic, p->int_phys)),
494 virtTimer(csprintf("%s.virt_timer0", name()),
495 *this, systemCounter,
496 ArchTimer::Interrupt(*p->gic, p->int_virt))
497{
498}
499
500void
501GenericTimerMem::serialize(std::ostream &os)
502{
503 paramOut(os, "timer_count", 1);
504
505 nameOut(os, csprintf("%s.sys_counter", name()));
506 systemCounter.serialize(os);
507
508 nameOut(os, physTimer.name());
509 physTimer.serialize(os);
510
511 nameOut(os, virtTimer.name());
512 virtTimer.serialize(os);
513}
514
515void
516GenericTimerMem::unserialize(Checkpoint *cp, const std::string &section)
517{
518 systemCounter.unserialize(cp, csprintf("%s.sys_counter", section));
519
520 unsigned timer_count;
521 UNSERIALIZE_SCALAR(timer_count);
522 // The timer count variable is just here for future versions where
523 // we support more than one set of timers.
524 if (timer_count != 1)
525 panic("Incompatible checkpoint: Only one set of timers supported");
526
527 physTimer.unserialize(cp, csprintf("%s.phys_timer0", section));
528 virtTimer.unserialize(cp, csprintf("%s.virt_timer0", section));
529}
530
531Tick
532GenericTimerMem::read(PacketPtr pkt)
533{
534 const unsigned size(pkt->getSize());
535 const Addr addr(pkt->getAddr());
536 uint64_t value;
537
538 pkt->makeResponse();
539 if (ctrlRange.contains(addr)) {
540 value = ctrlRead(addr - ctrlRange.start(), size);
541 } else if (timerRange.contains(addr)) {
542 value = timerRead(addr - timerRange.start(), size);
543 } else {
544 panic("Invalid address: 0x%x\n", addr);
545 }
546
547 DPRINTF(Timer, "Read 0x%x <- 0x%x(%i)\n", value, addr, size);
548
549 if (size == 8) {
550 pkt->set<uint64_t>(value);
551 } else if (size == 4) {
552 pkt->set<uint32_t>(value);
553 } else {
554 panic("Unexpected access size: %i\n", size);
555 }
556
557 return 0;
558}
559
560Tick
561GenericTimerMem::write(PacketPtr pkt)
562{
563 const unsigned size(pkt->getSize());
564 if (size != 8 && size != 4)
565 panic("Unexpected access size\n");
566
567 const Addr addr(pkt->getAddr());
568 const uint64_t value(size == 8 ?
569 pkt->get<uint64_t>() : pkt->get<uint32_t>());
570
571 DPRINTF(Timer, "Write 0x%x -> 0x%x(%i)\n", value, addr, size);
572 if (ctrlRange.contains(addr)) {
573 ctrlWrite(addr - ctrlRange.start(), size, value);
574 } else if (timerRange.contains(addr)) {
575 timerWrite(addr - timerRange.start(), size, value);
576 } else {
577 panic("Invalid address: 0x%x\n", addr);
578 }
579
580 pkt->makeResponse();
581 return 0;
582}
583
584uint64_t
585GenericTimerMem::ctrlRead(Addr addr, size_t size) const
586{
587 if (size == 4) {
588 switch (addr) {
589 case CTRL_CNTFRQ:
590 return systemCounter.freq();
591
592 case CTRL_CNTTIDR:
593 return 0x3; // Frame 0 implemented with virtual timers
594
595 case CTRL_CNTNSAR:
596 case CTRL_CNTACR_BASE:
597 warn("Reading from unimplemented control register (0x%x)\n", addr);
598 return 0;
599
600 case CTRL_CNTVOFF_LO_BASE:
601 return virtTimer.offset();
602
603 case CTRL_CNTVOFF_HI_BASE:
604 return virtTimer.offset() >> 32;
605
606 default:
607 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size);
608 return 0;
609 }
610 } else if (size == 8) {
611 switch (addr) {
612 case CTRL_CNTVOFF_LO_BASE:
613 return virtTimer.offset();
614
615 default:
616 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size);
617 return 0;
618 }
619 } else {
620 panic("Invalid access size: %i\n", size);
621 }
622}
623
624void
625GenericTimerMem::ctrlWrite(Addr addr, size_t size, uint64_t value)
626{
627 if (size == 4) {
628 switch (addr) {
629 case CTRL_CNTFRQ:
630 case CTRL_CNTNSAR:
631 case CTRL_CNTTIDR:
632 case CTRL_CNTACR_BASE:
633 warn("Write to unimplemented control register (0x%x)\n", addr);
634 return;
635
636 case CTRL_CNTVOFF_LO_BASE:
637 virtTimer.setOffset(
638 insertBits(virtTimer.offset(), 31, 0, value));
639 return;
640
641 case CTRL_CNTVOFF_HI_BASE:
642 virtTimer.setOffset(
643 insertBits(virtTimer.offset(), 63, 32, value));
644 return;
645
646 default:
647 warn("Ignoring write to unexpected address (0x%x:%i)\n",
648 addr, size);
649 return;
650 }
651 } else if (size == 8) {
652 switch (addr) {
653 case CTRL_CNTVOFF_LO_BASE:
654 virtTimer.setOffset(value);
655 return;
656
657 default:
658 warn("Ignoring write to unexpected address (0x%x:%i)\n",
659 addr, size);
660 return;
661 }
662 } else {
663 panic("Invalid access size: %i\n", size);
664 }
665}
666
667uint64_t
668GenericTimerMem::timerRead(Addr addr, size_t size) const
669{
670 if (size == 4) {
671 switch (addr) {
672 case TIMER_CNTPCT_LO:
673 return physTimer.value();
674
675 case TIMER_CNTPCT_HI:
676 return physTimer.value() >> 32;
677
678 case TIMER_CNTVCT_LO:
679 return virtTimer.value();
680
681 case TIMER_CNTVCT_HI:
682 return virtTimer.value() >> 32;
683
684 case TIMER_CNTFRQ:
685 return systemCounter.freq();
686
687 case TIMER_CNTEL0ACR:
688 warn("Read from unimplemented timer register (0x%x)\n", addr);
689 return 0;
690
691 case CTRL_CNTVOFF_LO_BASE:
692 return virtTimer.offset();
693
694 case CTRL_CNTVOFF_HI_BASE:
695 return virtTimer.offset() >> 32;
696
697 case TIMER_CNTP_CVAL_LO:
698 return physTimer.compareValue();
699
700 case TIMER_CNTP_CVAL_HI:
701 return physTimer.compareValue() >> 32;
702
703 case TIMER_CNTP_TVAL:
704 return physTimer.timerValue();
705
706 case TIMER_CNTP_CTL:
707 return physTimer.control();
708
709 case TIMER_CNTV_CVAL_LO:
710 return virtTimer.compareValue();
711
712 case TIMER_CNTV_CVAL_HI:
713 return virtTimer.compareValue() >> 32;
714
715 case TIMER_CNTV_TVAL:
716 return virtTimer.timerValue();
717
718 case TIMER_CNTV_CTL:
719 return virtTimer.control();
720
721 default:
722 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size);
723 return 0;
724 }
725 } else if (size == 8) {
726 switch (addr) {
727 case TIMER_CNTPCT_LO:
728 return physTimer.value();
729
730 case TIMER_CNTVCT_LO:
731 return virtTimer.value();
732
733 case CTRL_CNTVOFF_LO_BASE:
734 return virtTimer.offset();
735
736 case TIMER_CNTP_CVAL_LO:
737 return physTimer.compareValue();
738
739 case TIMER_CNTV_CVAL_LO:
740 return virtTimer.compareValue();
741
742 default:
743 warn("Unexpected address (0x%x:%i), assuming RAZ\n", addr, size);
744 return 0;
745 }
746 } else {
747 panic("Invalid access size: %i\n", size);
748 }
749}
750
751void
752GenericTimerMem::timerWrite(Addr addr, size_t size, uint64_t value)
753{
754 if (size == 4) {
755 switch (addr) {
756 case TIMER_CNTEL0ACR:
757 warn("Unimplemented timer register (0x%x)\n", addr);
758 return;
759
760 case TIMER_CNTP_CVAL_LO:
761 physTimer.setCompareValue(
762 insertBits(physTimer.compareValue(), 31, 0, value));
763 return;
764
765 case TIMER_CNTP_CVAL_HI:
766 physTimer.setCompareValue(
767 insertBits(physTimer.compareValue(), 63, 32, value));
768 return;
769
770 case TIMER_CNTP_TVAL:
771 physTimer.setTimerValue(value);
772 return;
773
774 case TIMER_CNTP_CTL:
775 physTimer.setControl(value);
776 return;
777
778 case TIMER_CNTV_CVAL_LO:
779 virtTimer.setCompareValue(
780 insertBits(virtTimer.compareValue(), 31, 0, value));
781 return;
782
783 case TIMER_CNTV_CVAL_HI:
784 virtTimer.setCompareValue(
785 insertBits(virtTimer.compareValue(), 63, 32, value));
786 return;
787
788 case TIMER_CNTV_TVAL:
789 virtTimer.setTimerValue(value);
790 return;
791
792 case TIMER_CNTV_CTL:
793 virtTimer.setControl(value);
794 return;
795
796 default:
797 warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size);
798 return;
799 }
800 } else if (size == 8) {
801 switch (addr) {
802 case TIMER_CNTP_CVAL_LO:
803 return physTimer.setCompareValue(value);
804
805 case TIMER_CNTV_CVAL_LO:
806 return virtTimer.setCompareValue(value);
807
808 default:
809 warn("Unexpected address (0x%x:%i), ignoring write\n", addr, size);
810 return;
811 }
812 } else {
813 panic("Invalid access size: %i\n", size);
814 }
815}
816
482GenericTimer *
483GenericTimerParams::create()
484{
485 return new GenericTimer(this);
486}
817GenericTimer *
818GenericTimerParams::create()
819{
820 return new GenericTimer(this);
821}
822
823GenericTimerMem *
824GenericTimerMemParams::create()
825{
826 return new GenericTimerMem(this);
827}