xref: /reactos/boot/armllb/hw/versatile/hwkmi.c (revision 40462c92)
1 /*
2  * PROJECT:         ReactOS Boot Loader
3  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4  * FILE:            boot/armllb/hw/versatile/hwkmi.c
5  * PURPOSE:         LLB KMI Support for Versatile
6  * PROGRAMMERS:     ReactOS Portable Systems Group
7  */
8 
9 #include "precomp.h"
10 
11 //
12 // Control Register Bits
13 //
14 #define KMICR_TYPE		        (1 << 5)
15 #define KMICR_RXINTREN	        (1 << 4)
16 #define KMICR_TXINTREN	        (1 << 3)
17 #define KMICR_EN		        (1 << 2)
18 #define KMICR_FD		        (1 << 1)
19 #define KMICR_FC		        (1 << 0)
20 
21 //
22 // Status Register Bits
23 //
24 #define KMISTAT_TXEMPTY		    (1 << 6)
25 #define KMISTAT_TXBUSY		    (1 << 5)
26 #define KMISTAT_RXFULL		    (1 << 4)
27 #define KMISTAT_RXBUSY		    (1 << 3)
28 #define KMISTAT_RXPARITY	    (1 << 2)
29 #define KMISTAT_IC		        (1 << 1)
30 #define KMISTAT_ID              (1 << 0)
31 
32 //
33 // KMI Registers
34 //
35 #define PL050_KMICR		        (LlbHwVersaKmiBase + 0x00)
36 #define PL050_KMISTAT		    (LlbHwVersaKmiBase + 0x04)
37 #define PL050_KMIDATA		    (LlbHwVersaKmiBase + 0x08)
38 #define PL050_KMICLKDIV	        (LlbHwVersaKmiBase + 0x0c)
39 static const ULONG LlbHwVersaKmiBase = 0x10006000;
40 
41 //
42 // PS/2 Commands/Requests
43 //
44 #define PS2_O_RESET		        0xff
45 #define PS2_O_RESEND		    0xfe
46 #define PS2_O_DISABLE		    0xf5
47 #define PS2_O_ENABLE		    0xf4
48 #define PS2_O_ECHO		        0xee
49 #define PS2_O_SET_DEFAULT	    0xf6
50 #define PS2_O_SET_RATE_DELAY    0xf3
51 #define PS2_O_SET_SCANSET	    0xf0
52 #define PS2_O_INDICATORS	    0xed
53 #define PS2_I_RESEND		    0xfe
54 #define PS2_I_DIAGFAIL		    0xfd
55 #define PS2_I_ACK		        0xfa
56 #define PS2_I_BREAK		        0xf0
57 #define PS2_I_ECHO		        0xee
58 #define PS2_I_BAT_OK		    0xaa
59 
60 /* FUNCTIONS ******************************************************************/
61 
62 VOID
63 NTAPI
64 LlbHwVersaKmiSendAndWait(IN ULONG Value)
65 {
66     volatile int i = 1000;
67 
68     /* Send the value */
69     LlbHwKbdSend(Value);
70 
71     /* Wait a bit */
72     while (--i);
73 
74     /* Now make sure we received an ACK */
75     if (LlbHwKbdRead() != PS2_I_ACK) DbgPrint("PS/2 FAILURE!\n");
76 }
77 
78 VOID
79 NTAPI
80 LlbHwVersaKmiInitialize(VOID)
81 {
82     UCHAR Divisor;
83 
84     /* Setup divisor and enable KMI */
85     Divisor = (LlbHwGetPClk() / 8000000) - 1;
86     WRITE_REGISTER_UCHAR(PL050_KMICLKDIV, Divisor);
87     WRITE_REGISTER_UCHAR(PL050_KMICR, KMICR_EN);
88 
89     /* Reset PS/2 controller */
90     LlbHwVersaKmiSendAndWait(PS2_O_RESET);
91     if (LlbHwKbdRead() != PS2_I_BAT_OK) DbgPrint("PS/2 RESET FAILURE!\n");
92 
93     /* Send PS/2 Initialization Stream */
94     LlbHwVersaKmiSendAndWait(PS2_O_DISABLE);
95     LlbHwVersaKmiSendAndWait(PS2_O_SET_DEFAULT);
96     LlbHwVersaKmiSendAndWait(PS2_O_SET_SCANSET);
97     LlbHwVersaKmiSendAndWait(1);
98     LlbHwVersaKmiSendAndWait(PS2_O_ENABLE);
99 }
100 
101 VOID
102 NTAPI
103 LlbHwKbdSend(IN ULONG Value)
104 {
105     ULONG Status;
106 
107     /* Wait for ready signal */
108     do
109     {
110         /* Read TX buffer state */
111         Status = READ_REGISTER_UCHAR(PL050_KMISTAT);
112     } while (!(Status & KMISTAT_TXEMPTY));
113 
114     /* Send value */
115     WRITE_REGISTER_UCHAR(PL050_KMIDATA, Value);
116 }
117 
118 BOOLEAN
119 NTAPI
120 LlbHwKbdReady(VOID)
121 {
122     return READ_REGISTER_UCHAR(PL050_KMISTAT) & KMISTAT_RXFULL;
123 }
124 
125 INT
126 NTAPI
127 LlbHwKbdRead(VOID)
128 {
129     /* Read current data on keyboard */
130     return READ_REGISTER_UCHAR(PL050_KMIDATA);
131 }
132 
133 /* EOF */
134