MODULE SdEnvironment; (** AUTHOR Timothée Martiel, 01/2016 PURPOSE SD driver environment for Minos *) IMPORT Platform, Board, Trace, Caches, Interrupts, GlobalTimer; CONST MaxHandlers = 2; VAR Char *: PROCEDURE (c: CHAR); String *: PROCEDURE (CONST str: ARRAY OF CHAR); Int *: PROCEDURE (i: HUGEINT; w: LONGINT); Hex *: PROCEDURE (i: LONGINT; w: LONGINT); Address *: PROCEDURE (a: ADDRESS); Set *: PROCEDURE (s: SET); Boolean *: PROCEDURE (b: BOOLEAN); Ln *: PROCEDURE; FlushDCacheRange *, InvalidateDCacheRange *: PROCEDURE (adr: ADDRESS; size: SIZE); GetTimeCounter *: PROCEDURE (): Time; handlers: ARRAY MaxHandlers OF RECORD irq: LONGINT; handle: PROCEDURE END; TYPE Time * = HUGEINT; PROCEDURE InstallHandler * (handler: PROCEDURE; irq: LONGINT); VAR i: LONGINT; BEGIN i := 0; WHILE (i < MaxHandlers) & (handlers[i].handle # NIL) DO INC(i) END; ASSERT(i < MaxHandlers); handlers[i].irq := irq; handlers[i].handle := handler; Interrupts.InstallHandler(InterruptHandler, irq) END InstallHandler; PROCEDURE Enable * (sd: LONGINT): BOOLEAN; VAR enable: BOOLEAN; BEGIN CASE sd OF 0: enable := Board.SdEnable0 |1: enable := Board.SdEnable1 END; RETURN enable END Enable; PROCEDURE HcClock * (sd: LONGINT): LONGINT; VAR reg, div, base: LONGINT; BEGIN div := LSH(Platform.slcr.SDIO_CLK_CTRL, -8) MOD 40H; CASE LSH(Platform.slcr.SDIO_CLK_CTRL, -4) MOD 4 OF 0: reg := Platform.slcr.IO_PLL_CTRL; base := Board.PsRefClockHz |2: reg := Platform.slcr.ARM_PLL_CTRL; base := Board.CpuClockHz DIV 2 |3: reg := Platform.slcr.DDR_PLL_CTRL; Trace.StringLn("ERROR: DDR PLL clock source for SD not supported") END; base := base * (LSH(reg, -12) MOD 80H); RETURN base DIV div END HcClock; (** Convert microseconds to time counts *) PROCEDURE FromMicro*(us: Time): Time; BEGIN RETURN us * ENTIERH(0.5D0+Board.CpuClockHz/2.0D6); END FromMicro; (** Convert time counts to microseconds *) PROCEDURE ToMicro*(time: Time): Time; BEGIN RETURN ENTIERH((0.5D0 + time) / (LONGREAL(Board.CpuClockHz)) * 2.0D6) END ToMicro; (** Convert milliseconds to time counts *) PROCEDURE FromMilli*(ms: Time): Time; BEGIN RETURN ms * ENTIERH(0.5D0+Board.CpuClockHz/2.0D3); END FromMilli; (** Convert time counts to milliseconds *) PROCEDURE ToMilli*(time: Time): Time; BEGIN RETURN ENTIERH((0.5D0 + time) / (LONGREAL(Board.CpuClockHz)) * 2.0D3) END ToMilli; PROCEDURE GetLock * (VAR acq, rel: PROCEDURE {DELEGATE}); END GetLock; PROCEDURE InterruptHandler (irq: LONGINT); VAR i: LONGINT; BEGIN FOR i := 0 TO MaxHandlers - 1 DO IF handlers[i].irq = irq THEN handlers[i].handle END END END InterruptHandler; BEGIN GlobalTimer.EnableTimer; Char := Trace.Char; String := Trace.String; Int := Trace.HInt; Hex := Trace.Hex; Address := Trace.Address; Set := Trace.Set; Boolean := Trace.Boolean; Ln := Trace.Ln; FlushDCacheRange := Caches.CleanDCacheRange; InvalidateDCacheRange := Caches.InvalidateDCacheRange; GetTimeCounter := GlobalTimer.GetTime; END SdEnvironment.