/* * \brief Pic implementation specific to Rpi 1 * \author Norman Feske * \author Stefan Kalkowski * \date 2016-01-07 */ /* * Copyright (C) 2016-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #include #include using namespace Genode; bool Board::Pic::Usb_dwc_otg::_need_trigger_sof(uint32_t host_frame, uint32_t scheduled_frame) { uint32_t const max_frame = 0x3fff; if (host_frame < scheduled_frame) { if (scheduled_frame - host_frame < max_frame / 2) return false; /* scheduled frame not reached yet */ else return true; /* scheduled frame passed, host frame wrapped */ } else { if (host_frame - scheduled_frame < max_frame / 2) return true; /* scheduled frame passed */ else return false; /* scheduled frame wrapped, not reached */ } } Board::Pic::Usb_dwc_otg::Usb_dwc_otg() : Mmio(Platform::mmio_to_virt(Board::USB_DWC_OTG_BASE)) { write(0); write(false); write(false); } bool Board::Pic::Usb_dwc_otg::handle_sof() { if (!_is_sof()) return false; static int cnt = 0; if (++cnt == 8*20) { cnt = 0; return false; } if (!read() || read()) return false; if (_need_trigger_sof(read(), read())) return false; write(1); return true; } Board::Pic::Pic() : Mmio(Platform::mmio_to_virt(Board::IRQ_CONTROLLER_BASE)) { mask(); } bool Board::Pic::take_request(unsigned &irq) { /* read basic IRQ status mask */ uint32_t const p = read(); /* read GPU IRQ status mask */ uint32_t const p1 = read(), p2 = read(); if (Irq_pending_basic::Timer::get(p)) { irq = Irq_pending_basic::Timer::SHIFT; return true; } /* search for lowest set bit in pending masks */ for (unsigned i = 0; i < NR_OF_IRQ; i++) { if (!_is_pending(i, p1, p2)) continue; irq = Board::GPU_IRQ_BASE + i; /* handle SOF interrupts locally, filter from the user land */ if (irq == Board::DWC_IRQ) if (_usb.handle_sof()) return false; return true; } return false; } void Board::Pic::mask() { write(~0); write(~0); write(~0); } void Board::Pic::unmask(unsigned const i, unsigned) { if (i < 8) write(1 << i); else if (i < 32 + 8) write(1 << (i - 8)); else write(1 << (i - 8 - 32)); } void Board::Pic::mask(unsigned const i) { if (i < 8) write(1 << i); else if (i < 32 + 8) write(1 << (i - 8)); else write(1 << (i - 8 - 32)); }