123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- /*++
- Copyright (c) 2015 Minoca Corp. All Rights Reserved
- Module Name:
- mailbox.c
- Abstract:
- This module implements mailbox support for the TI AM33xx SoCs.
- Author:
- Evan Green 1-Oct-2015
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/driver.h>
- #include <minoca/fw/acpitabs.h>
- #include <minoca/soc/am335x.h>
- #include "mailbox.h"
- //
- // --------------------------------------------------------------------- Macros
- //
- #define AM3_READ_MAILBOX(_Controller, _Register) \
- HlReadRegister32((_Controller)->ControllerBase + (_Register))
- #define AM3_WRITE_MAILBOX(_Controller, _Register, _Value) \
- HlWriteRegister32((_Controller)->ControllerBase + (_Register), (_Value))
- #define AM3_MAILBOX_MESSAGE(_Index) (Am3MailboxMessage0 + ((_Index) * 4))
- #define AM3_MAILBOX_FIFO_STATUS(_Index) (Am3MailboxFifoStatus0 + ((_Index) * 4))
- #define AM3_MAILBOX_MESSAGE_STATUS(_Index) \
- (Am3MailboxMessageStatus0 + ((_Index) * 4))
- //
- // There are four possible users of the mailbox:
- // 0 - MPU subsystem
- // 1 - PRU_ICSS PRU0
- // 2 - PRU_ICSS PRU1
- // 3 - WakeM3
- //
- // Each user has their own interrupt.
- //
- #define AM3_MAILBOX_INTERRUPT_STATUS(_User) \
- (Am3MailboxInterruptStatusClear0 + ((_User) * 0x10))
- #define AM3_MAILBOX_INTERRUPT_ENABLE(_User) \
- (Am3MailboxInterruptEnableSet0 + ((_User) * 0x10))
- #define AM3_MAILBOX_INTERRUPT_DISABLE(_User) \
- (Am3MailboxInterruptEnableClear0 + ((_User) * 0x10))
- //
- // This macro returns a bitmask of the given interrupt for the given mailbox
- // index.
- //
- #define AM3_MAILBOX_INTERRUPT(_Mask, _Index) ((_Mask) << ((_Index) * 2))
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define AM3_MAILBOX_INTERRUPT_MESSAGE 0x00000001
- #define AM3_MAILBOX_INTERRUPT_NOT_FULL 0x00000002
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- typedef enum _AM3_MAILBOX_REGISTER {
- Am3MailboxRevision = 0x000,
- Am3MailboxSysConfig = 0x010,
- Am3MailboxMessage0 = 0x040,
- Am3MailboxFifoStatus0 = 0x080,
- Am3MailboxMessageStatus0 = 0x0C0,
- Am3MailboxInterruptStatusRaw0 = 0x100,
- Am3MailboxInterruptStatusClear0 = 0x104,
- Am3MailboxInterruptEnableSet0 = 0x108,
- Am3MailboxInterruptEnableClear0 = 0x10C,
- } AM3_MAILBOX_REGISTER, *PAM3_MAILBOX_REGISTER;
- typedef enum _AM3_MAILBOX_USER {
- Am3MailboxUserMpu = 0,
- Am3MailboxUserPru0 = 1,
- Am3MailboxUserPru1 = 2,
- Am3MailboxUserWakeM3 = 3
- } AM3_MAILBOX_USER, *PAM3_MAILBOX_USER;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- INTERRUPT_STATUS
- Am3MailboxInterruptService (
- PVOID Context
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- Am3MailboxInitialize (
- PAM3_MAILBOX Mailbox,
- PIRP Irp,
- PRESOURCE_ALLOCATION ControllerPhysical,
- ULONGLONG InterruptLine,
- ULONGLONG InterruptVector
- )
- /*++
- Routine Description:
- This routine initializes support for the mailbox.
- Arguments:
- Irp - Supplies a pointer to the start IRP.
- Mailbox - Supplies a pointer to the controller, which is assumed to have
- been zeroed.
- ControllerPhysical - Supplies a pointer to the physical resource allocation
- of the mailbox controller.
- InterruptLine - Supplies the interrupt line the mailbox is connected on.
- InterruptVector - Supplies the interrupt vector the mailbox should use.
- Return Value:
- Status code.
- --*/
- {
- UINTN AlignmentOffset;
- IO_CONNECT_INTERRUPT_PARAMETERS Connect;
- PHYSICAL_ADDRESS EndAddress;
- ULONG PageSize;
- PHYSICAL_ADDRESS PhysicalAddress;
- ULONG Register;
- UINTN Size;
- KSTATUS Status;
- ULONG Value;
- ASSERT(Mailbox->ControllerBase == NULL);
- Mailbox->InterruptHandle = INVALID_HANDLE;
- Mailbox->InterruptLine = InterruptLine;
- Mailbox->InterruptVector = InterruptVector;
- //
- // Map the registers.
- //
- if (Mailbox->ControllerBase == NULL) {
- //
- // Page align the mapping request.
- //
- PageSize = MmPageSize();
- PhysicalAddress = ControllerPhysical->Allocation;
- EndAddress = PhysicalAddress + ControllerPhysical->Length;
- PhysicalAddress = ALIGN_RANGE_DOWN(PhysicalAddress, PageSize);
- AlignmentOffset = ControllerPhysical->Allocation - PhysicalAddress;
- EndAddress = ALIGN_RANGE_UP(EndAddress, PageSize);
- Size = (ULONG)(EndAddress - PhysicalAddress);
- //
- // If the size is not a the constant, then the failure code at the
- // bottom needs to be fancier.
- //
- ASSERT(Size == AM335_MAILBOX_SIZE);
- Mailbox->ControllerBase = MmMapPhysicalAddress(PhysicalAddress,
- Size,
- TRUE,
- FALSE,
- TRUE);
- if (Mailbox->ControllerBase == NULL) {
- Status = STATUS_NO_MEMORY;
- goto MailboxInitializeEnd;
- }
- Mailbox->ControllerBase += AlignmentOffset;
- }
- ASSERT(Mailbox->ControllerBase != NULL);
- //
- // Connect the mailbox interrupt.
- //
- ASSERT(Mailbox->InterruptHandle == INVALID_HANDLE);
- RtlZeroMemory(&Connect, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
- Connect.Version = IO_CONNECT_INTERRUPT_PARAMETERS_VERSION;
- Connect.Device = Irp->Device;
- Connect.LineNumber = Mailbox->InterruptLine;
- Connect.Vector = Mailbox->InterruptVector;
- Connect.InterruptServiceRoutine = Am3MailboxInterruptService;
- Connect.Context = Mailbox;
- Connect.Interrupt = &(Mailbox->InterruptHandle);
- Status = IoConnectInterrupt(&Connect);
- if (!KSUCCESS(Status)) {
- goto MailboxInitializeEnd;
- }
- //
- // Enable interrupts towards the Cortex M3 for the mailbox dedicated to it.
- //
- Register = AM3_MAILBOX_INTERRUPT_ENABLE(Am3MailboxUserWakeM3);
- Value = AM3_MAILBOX_INTERRUPT(AM3_MAILBOX_INTERRUPT_MESSAGE,
- AM335_WAKEM3_MAILBOX);
- AM3_WRITE_MAILBOX(Mailbox, Register, Value);
- MailboxInitializeEnd:
- if (!KSUCCESS(Status)) {
- Am3MailboxDestroy(Mailbox);
- }
- return Status;
- }
- VOID
- Am3MailboxDestroy (
- PAM3_MAILBOX Mailbox
- )
- /*++
- Routine Description:
- This routine tears down a mailbox controller.
- Arguments:
- Mailbox - Supplies a pointer to the initialized controller.
- Return Value:
- None.
- --*/
- {
- if (Mailbox->InterruptHandle != INVALID_HANDLE) {
- IoDisconnectInterrupt(Mailbox->InterruptHandle);
- Mailbox->InterruptHandle = INVALID_HANDLE;
- }
- if (Mailbox->ControllerBase != NULL) {
- MmUnmapAddress(Mailbox->ControllerBase, AM335_MAILBOX_SIZE);
- Mailbox->ControllerBase = NULL;
- }
- return;
- }
- VOID
- Am3MailboxSend (
- PAM3_MAILBOX Mailbox,
- ULONG Index,
- ULONG Message
- )
- /*++
- Routine Description:
- This routine writes a new message to the AM3 mailbox.
- Arguments:
- Mailbox - Supplies a pointer to the controller.
- Index - Supplies the mailbox number to write to. Valid values are 0-7.
- Message - Supplies the value to write.
- Return Value:
- None.
- --*/
- {
- ULONG Register;
- Register = AM3_MAILBOX_MESSAGE(Index);
- AM3_WRITE_MAILBOX(Mailbox, Register, Message);
- return;
- }
- VOID
- Am3MailboxFlush (
- PAM3_MAILBOX Mailbox,
- ULONG Index
- )
- /*++
- Routine Description:
- This routine reads all messages back out of the mailbox and discards them.
- Arguments:
- Mailbox - Supplies a pointer to the controller.
- Index - Supplies the mailbox number to write to. Valid values are 0-7.
- Return Value:
- None.
- --*/
- {
- ULONG InterruptStatus;
- ULONG InterruptStatusRegister;
- ULONG MessageRegister;
- ULONG MessageStatusRegister;
- MessageRegister = AM3_MAILBOX_MESSAGE(Index);
- MessageStatusRegister = AM3_MAILBOX_MESSAGE_STATUS(Index);
- while (AM3_READ_MAILBOX(Mailbox, MessageStatusRegister) != 0) {
- AM3_READ_MAILBOX(Mailbox, MessageRegister);
- }
- //
- // Remove any interrupts from the Cortex M3 status as well.
- //
- if (Index == AM335_WAKEM3_MAILBOX) {
- InterruptStatusRegister =
- AM3_MAILBOX_INTERRUPT_STATUS(Am3MailboxUserWakeM3);
- InterruptStatus = AM3_READ_MAILBOX(Mailbox, InterruptStatusRegister);
- if (InterruptStatus != 0) {
- AM3_WRITE_MAILBOX(Mailbox,
- InterruptStatusRegister,
- InterruptStatus);
- }
- }
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- INTERRUPT_STATUS
- Am3MailboxInterruptService (
- PVOID Context
- )
- /*++
- Routine Description:
- This routine represents an interrupt service routine.
- Arguments:
- Context - Supplies the context supplied when this interrupt was initially
- connected.
- Return Value:
- Returns an interrupt status indicating if this ISR is claiming the
- interrupt, not claiming the interrupt, or needs the interrupt to be
- masked temporarily.
- --*/
- {
- //
- // Complete official mailbox support is not yet implemented. The only user
- // is currently the sleep code, which has interrupts disabled the whole
- // time.
- //
- ASSERT(FALSE);
- return InterruptStatusNotClaimed;
- }
|