PL050 PS/2 Controller: Difference between revisions
[unchecked revision] | [unchecked revision] |
(Add base functions in C and information about registers) |
m (Bot: Replace deprecated source tag with syntaxhighlight) |
||
Line 30: | Line 30: | ||
The table above could be represented as a C struct: |
The table above could be represented as a C struct: |
||
< |
<syntaxhighlight lang="c"> |
||
// PL050(KMI) bases under Integrator/CP compatible board. |
// PL050(KMI) bases under Integrator/CP compatible board. |
||
#define KMI_KB_BASE 0x18000000 // keyboard |
#define KMI_KB_BASE 0x18000000 // keyboard |
||
Line 45: | Line 45: | ||
// Note: set a valid pointer before initialising it. |
// Note: set a valid pointer before initialising it. |
||
KMI_MMIO volatile *mmio; |
KMI_MMIO volatile *mmio; |
||
</syntaxhighlight> |
|||
</source> |
|||
''The above uses memory mapped input/output (MMIO), but other architectures may use I/O ports instead or a combination of I/O ports and MMIO for example the X84/64. So understanding your platform is very important to understand how to proceed in talking to the devices.'' |
''The above uses memory mapped input/output (MMIO), but other architectures may use I/O ports instead or a combination of I/O ports and MMIO for example the X84/64. So understanding your platform is very important to understand how to proceed in talking to the devices.'' |
||
Line 141: | Line 141: | ||
These functions are base ones to communicate with PS/2 devices. Using this functions you can enable mouse by writing ''0xF4'', more information about commands could be found at [[PS/2 Keyboard]] and [[PS/2 Mouse]] |
These functions are base ones to communicate with PS/2 devices. Using this functions you can enable mouse by writing ''0xF4'', more information about commands could be found at [[PS/2 Keyboard]] and [[PS/2 Mouse]] |
||
< |
<syntaxhighlight lang="c"> |
||
int kmi_setup_mouse() |
int kmi_setup_mouse() |
||
{ |
{ |
||
kmi_send(0xF4); |
kmi_send(0xF4); |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Note that, due to the complexity of the Raspberry Pi's USB interface and Qemu's versatilepb being the go-to Pi emulator before raspi2 was developed, some older Pi programs will use the PL050 to easily enable debugging in Qemu. No Pi device so far has PS/2 compatibility hardware. |
Note that, due to the complexity of the Raspberry Pi's USB interface and Qemu's versatilepb being the go-to Pi emulator before raspi2 was developed, some older Pi programs will use the PL050 to easily enable debugging in Qemu. No Pi device so far has PS/2 compatibility hardware. |
Revision as of 04:45, 9 June 2024
PL050 provides a keyboard or mouse interface(KMI) that is IBM PS/2 or AT-compatible and is licensed by ARM.
There are several registers to communicate with the controller, some of them are described in details further.
Address | Type | Description |
---|---|---|
Base + 0x00 | rw | Control register. |
Base + 0x04 | r | Status register. |
Base + 0x08 | rw | Received data (read)/ Data to be transmitted (write). |
Base + 0x0c | rw | Clock divisor register. |
Base + 0x10 | r | Interrupt status register. |
The table above could be represented as a C struct:
// PL050(KMI) bases under Integrator/CP compatible board.
#define KMI_KB_BASE 0x18000000 // keyboard
#define KMI_MS_BASE 0x19000000 // mouse
typedef struct _KMI_MMIO {
uint32 cr; // control register (rw)
uint32 stat; // status register (r)
uint32 data; // data register (rw)
uint32 clk; // clock divisor register (rw)
uint32 ir; // interrupt control register (r)
} KMI_MMIO;
// Note: set a valid pointer before initialising it.
KMI_MMIO volatile *mmio;
The above uses memory mapped input/output (MMIO), but other architectures may use I/O ports instead or a combination of I/O ports and MMIO for example the X84/64. So understanding your platform is very important to understand how to proceed in talking to the devices.
So first, configure the PL050 by enabling it. Let's take a look at control register. It contains five different bit fields:
Bits | Name | Description |
---|---|---|
0 | FKMIC | The force KMI clock LOW bit field is used to force the PrimeCell KMI clock pad LOW regardless of the state of the KMI FSM. |
1 | FKMID | The force KMI data LOW bit field is used to force the PrimeCell KMI data pad LOW regardless of the state of the KMI finite state machine (FSM). |
2 | KmiEn | The enable PrimeCell KMI bit field is used to enable the KMI. |
3 | KMITXINTREn | Enable transmitter interrupt. This bit field is used to enable the PrimeCell KMI transmitter interrupt. |
4 | KMIRXINTREn | Enable receiver interrupt. This bit field is used to enable the PrimeCell KMI receiver interrupt. |
5 | KMITYPE | 0 = PS2/AT mode (default), 1 = No line control bit mode. |
6-7 | - | Reserved. Read unpredictable. |
Setting the KmiEn will enable KMI. After that it's needed to setup a receiver interrupt, all it's needed is to set KMIRXINTREn and configure system's interrupt controller to call the callback which processes the input data.
void kmi_init(device_t* dev)
{
mmio->cr = (1 << 2) | (1 << 4);
}
The core function to implement is a one to send commands to PS/2 devices, like keyboard. For that the data register is used. To send a command, set a command id to data register and wait for an answer. The informations which helps to understand when is located in a status register. Data register does not contain any fields, just used to forward data, while it's interesting to take a detailed look at the status register:
Bits | Name | Description |
---|---|---|
0 | KMID | This bit reflects the status of the KMIDATAIN line after synchronizing. |
1 | KMIC | This bit reflects the status of the KMICLKIN line after synchronizing and sampling. |
2 | RXPARITY | This bit reflects the parity bit for the last received data byte (odd parity). |
3 | RXBUSY | This bit indicates that the PrimeCell KMI is currently receiving data. 0 = idle, 1 = receiving data. |
4 | RXFULL | This bit indicates that the receiver register is full and ready to be read. 0 = receive register empty, 1 = receive register full, ready to be read. |
5 | TXBUSY | This bit indicates that the PrimeCell KMI is currently sending data. 0 = idle, 1 = currently sending data. |
6 | TXEMPTY | This bit indicates that the transmit register is empty and ready to transmit. 0 = transmit register full, 1 = transmit register empty, ready to be written. |
7 | - | Reserved. Read unpredictable. |
void kmi_send(uint8 cmd)
{
kmi->data = cmd;
while ((registers->stat) & (1 << 5)); // wait while data is sending (TXBUSY)
ASSERT(registers->data == 0xfa);
}
These functions are base ones to communicate with PS/2 devices. Using this functions you can enable mouse by writing 0xF4, more information about commands could be found at PS/2 Keyboard and PS/2 Mouse
int kmi_setup_mouse()
{
kmi_send(0xF4);
}
Note that, due to the complexity of the Raspberry Pi's USB interface and Qemu's versatilepb being the go-to Pi emulator before raspi2 was developed, some older Pi programs will use the PL050 to easily enable debugging in Qemu. No Pi device so far has PS/2 compatibility hardware.