m1n1.hw.i2c: Rename registers to PASemi names, add all bit defs

This can serve as hardware documentation of the PASemi peripheral,
in lieu of public docs.

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2022-01-16 18:55:44 +09:00
parent 0b9829e227
commit 430e8d2e8a

View file

@ -1,33 +1,131 @@
# SPDX-License-Identifier: MIT
from ..utils import *
from enum import IntEnum
__all__ = ["I2C", "I2CRegs"]
class R_FIFO_TX(Register32):
READ = 10
STOP = 9
START = 8
DATA = 7, 0
class R_MTXFIFO(Register32):
READ = 10 # Read (DATA=count)
STOP = 9 # Issue START before
START = 8 # Issue STOP after
DATA = 7, 0 # Byte to send or count
class R_FIFO_RX(Register32):
EMPTY = 8
DATA = 7, 0
class R_MRXFIFO(Register32):
EMPTY = 8 # FIFO empty
DATA = 7, 0 # FIFO data
class R_STATUS(Register32):
XFER_READY = 27
class R_MCNT(Register32):
S_RXCNT = 31, 24 # Slave RX count
S_TXCNT = 23, 16 # Slave TX count
M_RXCNT = 15, 8 # Master RX count
M_TXCNT = 7, 0 # Master TX count
class R_CONTROL(Register32):
ENABLE = 11
CLEAR_RX = 10
CLEAR_TX = 9
CLOCK = 7, 0
class E_MST(IntEnum):
IDLE = 0
FRD1 = 1
FRD2 = 2
COMMAND = 3
START = 4
WRITE = 5
READ = 6
ACK = 7
STOP = 8
BAD = 15
class E_SST(IntEnum):
IDLE = 0
START = 1
ST_ACK = 2
DATA = 3
ACK = 4
class R_XFSTA(Register32):
MST = 27, 24, E_MST # Master controller state
SRD = 20 # Slave read in progress
SWR = 19 # Slave write in progress
SST = 18, 16, E_SST # Slave controller state
XFIFO = 9, 8 # FIFO number for error
XFCNT = 7, 0 # Number of bytes in current xfer
class R_SADDR(Register32):
DEB = 31 # Enable SDA/SCL read debug
DIR = 30 # Direct (bitbang) mode
ENS = 29 # Enable slave interface
RST_STX = 28 # Reset slave TX FIFO
RST_SRX = 27 # Reset master RX fifo (if ^ both, controller too)
PEN = 26 # Promiscuous mode (slave)
AAE = 25 # SALT/ALTMASK enable
SAE = 24 # SADDR enable
ALTMASK = 23, 16 # MASK for SALT bits
SALT = 15, 8 # Alt slave address
SADDR = 7, 0 # Slave address
class R_SMSTA(Register32):
XIP = 28 # Xaction in progress
XEN = 27 # Xaction ended
UJF = 26 # UnJam failure
JMD = 25 # Jam ocurred
JAM = 24 # Currently jammed
MTO = 23 # Master timeout
MTA = 22 # Master arb lost
MTN = 21 # Master received NACK
MRF = 20 # Master RX fifo full
MRNE = 19 # Master RX fifo not empty
MTF = 17 # Master TX fifo full
MTE = 16 # Master RX fifo empty
STO = 15 # Slave timeout
STA = 14 # Slave arb lost
STN = 13 # Slave received NACK
SRF = 12 # Slave RX fifo full
SRNE = 11 # Slave RX fifo not empty
STR = 10 # Slave transmit required
STF = 9 # Slave TX fifo full
STE = 8 # Slave TX fifo empty
TOS = 7 # Timeout due to slave FIFO
TOM = 6 # Timeout due to master FIFO
TOE = 5 # Slave timeout due to ext clock stretch
DCI = 4 # Direct clock in
DDI = 3 # Direct data in
DCO = 2 # Direct clock out
DDO = 1 # Direct data out
NN = 0 # NACK next (slave)
class R_CTL(Register32):
MSW = 26, 16 # Maximum slave write size
ENABLE = 11 # Unknown enable bit (clock sel? Apple thing)
MRR = 10 # Master receive FIFO reset
MTR = 9 # Master transmit FIFO reset
UJM = 8 # Enable auto unjam machine
CLK = 7, 0 # Clock divider
class R_STXFIFO(Register32):
DATA = 7, 0 # Data
class R_SRXFIFO(Register32):
N = 12 # NACK received after this byte
P = 11 # Stop received, data not valid
S = 10 # Start received before
O = 9 # Overflow (promisc only)
E = 8 # Empty (data not valid)
DATA = 7, 0 # Data
# Apple reg
class R_FIFOCTL(Register32):
HALT = 0 # Halt machinery
class I2CRegs(RegMap):
FIFO_TX = 0x00, R_FIFO_TX
FIFO_RX = 0x04, R_FIFO_RX
STATUS = 0x14, R_STATUS
CONTROL = 0x1c, R_CONTROL
MTXFIFO = 0x00, R_MTXFIFO
MRXFIFO = 0x04, R_MRXFIFO
MCNT = 0x08, R_MCNT
XFSTA = 0x0c, R_XFSTA
SADDR = 0x10, R_SADDR
SMSTA = 0x14, R_SMSTA
IMASK = 0x18, R_SMSTA
CTL = 0x1c, R_CTL
STXFIFO = 0x20, R_STXFIFO
SRXFIFO = 0x20, R_SRXFIFO
FIFOCTL = 0x44, R_FIFOCTL
class I2C:
@ -39,18 +137,18 @@ class I2C:
self.regs = I2CRegs(u, self.base)
def clear_fifos(self):
self.regs.CONTROL.set(CLEAR_TX=1, CLEAR_RX=1)
self.regs.CTL.set(MTR=1, MRR=1)
def clear_status(self):
self.regs.STATUS.val = 0xffffffff
self.regs.SMSTA.val = 0xffffffff
def _fifo_read(self, nbytes):
read = []
for _ in range(nbytes):
val = self.regs.FIFO_RX.reg
val = self.regs.MRXFIFO.reg
timeout = 10000
while val.EMPTY and timeout > 0:
val = self.regs.FIFO_RX.reg
val = self.regs.MRXFIFO.reg
timeout -= 1
if timeout == 0:
raise Exception("timeout")
@ -60,13 +158,13 @@ class I2C:
def _fifo_write(self, buf, stop=False):
for no, byte in enumerate(buf):
sending_stop = stop and no == len(buf) - 1
self.regs.FIFO_TX.set(DATA=byte, STOP=int(sending_stop))
self.regs.MTXFIFO.set(DATA=byte, STOP=int(sending_stop))
if not stop:
return
timeout = 10000
while not self.regs.STATUS.reg.XFER_READY and timeout > 0:
while not self.regs.SMSTA.reg.XEN and timeout > 0:
timeout -= 1
if timeout == 0:
raise Exception("timeout")
@ -75,20 +173,20 @@ class I2C:
self.clear_fifos()
self.clear_status()
self.regs.CONTROL.set(ENABLE=1, CLOCK=0x4)
self.regs.FIFO_TX.set(DATA=addr << 1, START=1)
self.regs.CTL.set(ENABLE=1, CLK=0x4)
self.regs.MTXFIFO.set(DATA=addr << 1, START=1)
self._fifo_write(bytes([reg]) + bytes(data), stop=True)
self.regs.CONTROL.set(ENABLE=0, CLOCK=0x4)
self.regs.CTL.set(ENABLE=0, CLK=0x4)
def read_reg(self, addr, reg, nbytes):
self.clear_fifos()
self.clear_status()
self.regs.CONTROL.set(ENABLE=1, CLOCK=0x4)
self.regs.FIFO_TX.set(DATA=addr << 1, START=1)
self.regs.CTL.set(ENABLE=1, CLK=0x4)
self.regs.MTXFIFO.set(DATA=addr << 1, START=1)
self._fifo_write(bytes([reg]), stop=True)
self.regs.FIFO_TX.set(DATA=(addr << 1) | 1, START=1)
self.regs.FIFO_TX.set(DATA=nbytes, STOP=1, READ=1)
self.regs.MTXFIFO.set(DATA=(addr << 1) | 1, START=1)
self.regs.MTXFIFO.set(DATA=nbytes, STOP=1, READ=1)
data = self._fifo_read(nbytes)
self.regs.CONTROL.set(ENABLE=0, CLOCK=0x4)
self.regs.CTL.set(ENABLE=0, CLK=0x4)
return data