fpc/rtl/embedded/aarch64/mailbox.pp
2023-07-27 19:04:03 +02:00

118 lines
2.9 KiB
ObjectPascal

{
Copyright (c) 1998-2022 by the Free Pascal development team
Broadcom "mailbox" call interface
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
{$IFNDEF FPC_DOTTEDUNITS}
unit mailbox;
{$ENDIF FPC_DOTTEDUNITS}
interface
type
TMBox = bitpacked Array[0..36] of DWord;
var
MBox: TMBox;
const
MBOX_REQUEST = 0;
{ Channels }
MBOX_CH_POWER = 0;
MBOX_CH_FB = 1;
MBOX_CH_VUART = 2;
MBOX_CH_VCHIQ = 3;
MBOX_CH_LEDS = 4;
MBOX_CH_BTNS = 5;
MBOX_CH_TOUCH = 6;
MBOX_CH_COUNT = 7;
MBOX_CH_PROP = 8;
{ Tags }
MBOX_TAG_GETSERIAL = $10004;
MBOX_TAG_SETCLKRATE = $38002;
MBOX_TAG_LAST = 0;
{ Responses }
MBOX_RESPONSE = $80000000;
MBOX_FULL = $80000000;
MBOX_EMPTY = $40000000;
{ Mailbox offsets from PeripheralBase }
VIDEOCORE_MBOX = $0000B880;
MBOX_READ = $0;
MBOX_POLL = $10;
MBOX_SENDER = $14;
MBOX_STATUS = $18;
MBOX_CONFIG = $1C;
MBOX_WRITE = $20;
function MailboxCall(BaseAddr: DWord; Channel: DWord): DWord;
implementation
{$IFDEF FPC_DOTTEDUNITS}
uses
EmbeddedApi.mmio;
{$ELSE FPC_DOTTEDUNITS}
uses
mmio;
{$ENDIF FPC_DOTTEDUNITS}
function MailboxCall(BaseAddr: DWord; Channel: DWord): DWord;
var
MBoxPtr: Pointer;
R: PtrUint;
MboxAddr: DWord;
begin
MboxAddr := BaseAddr + VIDEOCORE_MBOX;
MBoxPtr := Addr(MBox);
while True do
begin
DUMMY(1);
if (GET32(MboxAddr + MBOX_STATUS) and MBOX_FULL) = 0 then break;
end;
{ Join the address and channel together to identify our message }
R := (PtrUint(MBoxPtr) and (not $0F)) or (Channel and $0F);
{ Write to the mailbox - put the address of our message on the mailbox }
PUT32(MboxAddr + MBOX_WRITE, R);
while True do
begin
DUMMY(1);
{ Are there any messages pending in the mailbox? }
if (GET32(MboxAddr + MBOX_STATUS) and MBOX_EMPTY) > 0 then continue;
{ Is it a response to our message? }
if (GET32(MboxAddr + MBOX_READ) = R) then
begin
Exit(MBox[1]);
end;
end;
MailboxCall := 0;
end;
end.