XO 1.75 Application Processor to Security Processor Protocol

From OLPC
Revision as of 00:59, 17 June 2011 by Wmb@firmworks.com (talk | contribs) (SP protocol)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

If the XO-1.75's PS/2 keyboard and touchpad are connected to MMP2 SoC instead of to the embedded controller, the Security Processor ARM core inside the SoC serves as the PS/2 interface by bit-banging the PS/2 bus. This page describes the protocol whereby the Security Processor communicates with the main "Application Processor" (PJ4 core) to transmit data to and from the keyboard and touchpad.

Interface Model

Software running on the Application Processor receives keyboard and mouse events. Each event contains a port identifier - 0 for keyboard and 1 for mouse - and a data byte. The event can then be forwarded either to a keyboard driver or a mouse/touchpad driver. This is the "upstream" direction.

In the downstream direction, a byte can be sent either to the keyboard or the mouse/touchpad.

This is the same basic functionality that is provided by an "i8042" driver in a conventional PC system. An "i8042" driver may have additional embellishments to handle hardware-specific details, but the core functionality necessary for keyboard and mouse interfacing is just the bidirectional communication of bytes to and from the keyboard and mouse hardware.

Hardware Support for AP-to-SP Communication

Marvell's usage model for the Security Processor is for it to run "Wireless Trusted Module" (WTM) software that performs cryptography in a "locked-down" environment. OLPC does not use the WTM software, but the hardware support intended for communication between the OS and WTM is convenient for our purposes. That hardware consists of:

A command queue - 4 copies of 17 32-bit registers for sending commands and their parameters from the AP to the SP. Writing a command to the queue automatically interrupts the SP.

A response buffer - 1 copy of 17 32-bit registers for returning results. The SP can explicitly send an interrupt to the AP after writing the results to the response buffer.

For our purposes, we need to transfer only two bytes at a time, so the 17 32-bit registers are more than enough. Neglecting the overkill factor, the basic communication mechanism is well suited for our purpose. Ignoring the registers we don't need, the relevant hardware is:

  • SECURE_PROCESSOR_COMMAND 0xd4290040 - the AP writes to this register (the lower 16 bits are valid) to send a command to the SP. The register is actually a 4-deep FIFO. The act of writing to the register interrupts the SP.
  • COMMAND_FIFO_STATUS 0xd42900c4 - the SP can read this register to see how many entries are in the FIFO, thus checking that it's okay to send a command. In most cases, that shouldn't be necessary, because the overall operation of the protocol ensures that at most 3 commands will be queued at a given time.
  • COMMAND_RETURN_STATUS 0xd4290080 - the SP writes to this register (32 bits are valid) to send data to the AP. It is not a FIFO, just a single register. Writing to it does not automatically generate an interrupt request.
  • PJ_RST_INTERRUPT 0xd42900c8 - the AP can poll bit 0 of this register to see if an upstream event has been sent, or test that bit inside an interrupt service routine to determine that the interrupt is for an upstream event. Writing 1 to bit 0 acknowledges the interrupt, thus clearing the interrupt request.
  • PJ_INTERRUPT_MASK 0xd42900cc - Clearing bit 0 of this register enables the upstream event interrupt to the AP; setting bit 0 masks that interrupt. A polling driver (e.g. OFW's) would typically leave that bit, while an interrupt driver (e.g. Linux's) would clear it.
  • SP_INTERRUPT_SET_REGISTER 0xd4290210 - If bit 1 of this register is set, it means that a command has been written to SECURE_PROCESSOR_COMMAND. Thus the register is used in the SP's interrupt service routine to determine that a command is available. It is not necessary to write to this register.
  • SP_INTERRUPT_RESET 0xd4290218 - the SP writes 1 to bit 1 of this register to acknowledge the command-available interrupt, thus clearing the interrupt request.
  • SP_INTERRUPT_MASK 0xd429021c - the SP clears bit 1 of this register once during initialization, to unmask the command-available interrupt.
  • SP_CONTROL 0xd4290220 - the SP reads bit 0 of this register to determine that another command is available in the command FIFO, and writes 0 to bit 0 after having read the command, thus advancing the next command to the front of the FIFO.
  • PJ_INTERRUPT_SET 0xd4290234 - the SP writes 1 to bit 0 of this register to send an interrupt to the AP, thus causing bit 0 of PJ_RST_INTERRUPT to be set.

AP Side of Protocol

The protocol is very simple, especially from the AP side.

AP Side Initialization

  • If the driver uses interrupts, clear bit 0 of PJ_INTERRUPT_MASK

AP Side Sends Command Downstream

  • Write (port << 8) | data to SECURE_PROCESSOR_COMMAND . port=0 for keyboard, 1 for touchpad/mouse.

AP Side Interrupt Handler (Upstream Reception)

  • Verify that PJ_RST_INTERRUPT bit 0 is set (may be part of the interrupt dispatch logic)
  • Read COMMAND_RETURN_STATUS . Bits 7:0 are the data, bit 15:8 are the port (0 for keyboard, 1 for touchpad).
  • Forward the data byte to the attached driver for that port.
  • Write 1 (bit 0) to PJ_RST_INTERRUPT to acknowledge and clear the interrupt
  • Write 0xff00 to SECURE_PROCESSOR_COMMAND . This special command value tells the SP that the upstream data has been accepted, so that another event may be sent upstream when available.

SP Side of Protocol =

The SP side of the protocol is processed by an interrupt handler that manages command interrupts from this protocol, clock-transition interrupts from the PS/2 buses, and timer interrupts.

  • During reception or transmission of a byte on either PS/2 bus, the command interrupt is masked off. Commands are only recognized during idle periods between PS/2 bytes. That prevents bus contention and race conditions.
  • When a command interrupt is received:
    • If the command is the special "ready" command 0xff00, the SP checks to see if upstream data is available in its queue.
      • If so, the SP deques an event, writes it to COMMAND_RETURN_STATUS, and writes 1 to PJ_INTERRUPT_SET to interrupt the AP.
      • If the queue was empty, the SP sets an "ok_to_send" flag so that the next event that arrives can be sent upstream immediately.
    • If the command is an ordinary downstream event, the SP begins transmitting it to the appropriate PS/2 port.
  • The SP advances the command FIFO by writing 0 to SP_CONTROL
  • If another command is available in the FIFO, the SP processes it as above
  • After all commands have been removed from the FIFO, the SP acknowledges and clears the interrupt request by writing 2 to SP_INTERRUPT_RESET
  • The other two interrupts - timer and clock edge - are used to implement the bit-banging details of PS/2 transmission and reception.