#include #include #include #include "util.hh" #include "mmio.hh" #include "omap35x.hh" using std::printf; static const char *const omap_names[5] = {"OMAP3530", "OMAP3525", "OMAP3515", "OMAP3503", "UNKNOWN"}; static const char *const omap_ver[8] = {"ES 1.0", "ES 2.0", "ES 2.1", "ES 3.0", "ES 3.1", "UNKNOWN", "UNKNOWN", "ES 3.1.2"}; static std::array qemu_serial = {0x51454d55, 0x51454d55, 0x54000000, 0x51454d55}; class OMAP35x_Info_impl { public: OMAP35x_Info_impl(uintptr_t scm_base, uintptr_t control_base) : scm_base_{scm_base}, control_base_{control_base}, serial_(_get_serial()) { } ~OMAP35x_Info_impl() { } void print_chip_id() { uint16_t omapsr = r_omap_sr()&0xffffu; int omapsr_idx; switch(omapsr) { case 0x0c00: omapsr_idx = 0; break; case 0x4c00: omapsr_idx = 1; break; case 0x1c00: omapsr_idx = 2; break; case 0x5c00: omapsr_idx = 3; break; default: printf("Warning: Unknown OMAP35x type (%.8lx)\n", r_omap_sr()); omapsr_idx = 4; break; } uint32_t idcode = r_idcode(); int id_idx = (idcode&0xf0000000u)>>28; if(id_idx > 7) // Versions 8..15 are unknown id_idx = 6; if(id_idx == 5 || id_idx == 6) printf("Warning: Unknown OMAP35x version (%.8lx)\n", idcode); bool highfreq = false; if((r_skuid()&0xf) == 0x8) highfreq = true; printf("%s %s %s Serial# %.8lx%.8lx%.8lx%.8lx\n", omap_names[omapsr_idx], omap_ver[id_idx], highfreq?"720 MHz":"600 MHz", serial_[0], serial_[1], serial_[2], serial_[3]); } bool running_on_qemu() const { return (serial_ == qemu_serial); } std::array const& get_serial() const { return serial_; } private: std::array _get_serial() { return std::array{r_die_id(3), r_die_id(2), r_die_id(1), r_die_id(0)}; } MMIO_alloc scm_base_, control_base_; std::array serial_; uint32_t volatile& r_omap_sr() { return _reg32(scm_base_.get_virt(), 0x44c); } uint32_t volatile& r_idcode() { return _reg32(control_base_.get_virt(), 0x204); } uint32_t volatile& r_die_id(int n) { assert(n >= 0 && n <= 3); return _reg32(control_base_.get_virt(), 0x218+0x4*n); } uint32_t volatile& r_skuid() { return _reg32(control_base_.get_virt(), 0x20c); } }; OMAP35x_Info::OMAP35x_Info(uintptr_t scm_base, uintptr_t control_base) : impl_{new OMAP35x_Info_impl{scm_base, control_base}} { } OMAP35x_Info::~OMAP35x_Info() { } void OMAP35x_Info::print_chip_id() { impl_->print_chip_id(); } bool OMAP35x_Info::running_on_qemu() const { return impl_->running_on_qemu(); }