Editing Hardware Registers

Jump to navigation Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
= Introduction =
= Introduction =


With the exception of interrupts, almost all the interaction with the PSP hardware is done through memory mapped IO (MMIO) accesses in the 0xBC000000~0xBFFFFFFF address range. The physical address of this range is actually 0x1C000000~0x1FFFFFFF, but we must OR in the 0x40000000 un-cached flag and the 0x80000000 kernel access flag. Knowing how to communicate with the hardware is vital to understanding the inner workings of the PSP.
On the PSP, except interruptions, almost all the interaction with the hardware is done through memory accesses to "hardware registers" located at the 0xBC000000~0xBFFFFFFF range (actually 0x1C000000~0x1FFFFFFF to which we add the 0x4 uncached flag and the 0x8 kernel flag). Which is the reason why documenting this is vital to understand the PSP hardware.


= 0xA7F00000: L2 cache =
= 0xA7F00000: L2 cache =
Line 451: Line 451:
Bits 6-11 = UART 0-5
Bits 6-11 = UART 0-5


Bits 12-15 = APB (Arm Peripheral Bus) Timer 0-3
Bits 12-15 = APB (?) 0-3


Bits 16-17 = Audio 0-1
Bits 16-17 = Audio 0-1


Bits 18 = LCD Controller
Bits 19-21 = ?


Bits 19 = PWM
Bit 22 = SIRCS (?)
 
Bits 20 = ?
 
Bits 21 = I2C
 
Bit 22 = SIRCS (Sony Serial Infra-Red Control)


Bit 23 = GPIO
Bit 23 = GPIO
Line 498: Line 492:
| 0xBC100064 || 4 || RW || SPI clock select
| 0xBC100064 || 4 || RW || SPI clock select
|-
|-
| 0xBC100068 || 4 || RW || Bits 0-7: PLL frequency
| 0xBC100068 || 4 || RW || 0xF - PLL get/set out select (PLL frequency?)
 
Bits 16-31: unknown, checked against by the iplloader, possibly related to jigkick
|-
|-
| 0xBC100070 || 4 || RW || Set Avc power
| 0xBC100070 || 4 || RW || Set Avc power
Line 506: Line 498:
| 0xBC100074 || 4 || RW || Unknown
| 0xBC100074 || 4 || RW || Unknown
|-
|-
| 0xBC100078 || 4 || RW || I/O enable
| 0xBC100078 || 4 || RW || I/O enable (?) (TODO: verify indices)
 
Bit 1 = EMCSM
 
Bit 2 = USB
 
Bit 3 = ATA
 
Bits 4-5 = MSIF
 
Bit 6 = LCDC


Bits 7-8 = Audio
Bit 0 = NAND


Bit 9 = I2c
Bit 1 = USB


Bit 10 = Sircs
Bit 2 = ATA


Bit 11 = AudioClkout
Bits 3-4 = Memstick Interface


Bit 12 = Key (?)
Bit 5 = LCDC


Bit 13 = PWM
Bit 6-7 = Audio


Bit 14 = ATA HDD
Bit 8 = IIC


Bit 15 = TBD - needs more sysreg reversing
Bit 9 = SIRCS


Bits 16-21 = UART 0-5
Bit 10 = Audio?


Bits 22-23 = TBD - needs more sysreg reversing
Bit 11 = KEY


Bits 24-29 = SPI 0-5
Bit 12 = PWM


Bits 30-31 = TBD - needs more sysreg reversing
Bits 13-18 = UART


Bits 19-24 = SPI
|-
|-
| 0xBC10007C || 4 || RW || Either GPIO pin enable, or GPIO pin direction
| 0xBC10007C || 4 || RW || Either GPIO pin enable, or GPIO pin direction
Line 838: Line 821:
|-
|-
| 0xBC50003C || 4 ||    RW || Same as above, for hardware timer 3
| 0xBC50003C || 4 ||    RW || Same as above, for hardware timer 3
|-
| 0xBC500100 || 4 ||    R  || Get status read-only (?) for hardware timer 1
|-
| 0xBC500110 || 4 ||    R  || Get status read-only (?) for hardware timer 1
|-
| 0xBC500120 || 4 ||    R  || Get status read-only (?) for hardware timer 1
|-
| 0xBC500130 || 4 ||    R  || Get status read-only (?) for hardware timer 1
|-
|-
| 0xBC5003D0 || 4 ||    RW || Same as 0xBC500000, but with the current PSP's system time value. A timer's current count is computed by subtracting the timer's base time (the init time point) from this value.
| 0xBC5003D0 || 4 ||    RW || Same as 0xBC500000, but with the current PSP's system time value. A timer's current count is computed by subtracting the timer's base time (the init time point) from this value.
Line 873: Line 848:
|-
|-
|}
|}
= 0xBC700000: ? =


= 0xBC800000: DMACPlus =
= 0xBC800000: DMACPlus =
Line 999: Line 976:
|}
|}


== DMA processing ==
== Unknown ==


{| class="wikitable"
{| class="wikitable"
Line 1,008: Line 985:
! Description
! Description
|-
|-
| 0xBC800180 || 4 || RW || DMA channel 0 source address
| 0xBC800180 || ? || ? || Unknown
|-
|-
| 0xBC800184 || 4 || RW || DMA channel 0 destination address
|}
|-
| 0xBC800188 || 4 || RW || DMA channel 0 address for the next instruction (which is another source/destination/attr/status set)
|-
| 0xBC80018C || 4 || RW || DMA channel 0 attributes


Bits 0-11: length
= 0xBC900000 & 0xBCA00000: DMAC =


Bits 12-14: src step
{| class="wikitable"
 
Bits 15-17: dst step
 
Bits 18-20: src length shift
 
Bits 21-23: dst length shift
 
Bits 24-25: unknown
 
Bit 26: src increment
 
Bit 27: dst increment
 
Bit 31: trigger interrupt
|-
|-
| 0xBC800190 || 4 || RW || DMA channel 0 status
! Address !! Size !! R/W !! Description
 
Bit 0: in progress
 
Bits 4-7: DDR value
 
Bit 8: DDR required
|-
| 0xBC8001A0 || 20 || RW || Same as above, for DMA channel 1
|-
| 0xBC8001C0 || 20 || RW || Same as above, for DMA channel 2
|-
|}
 
= 0xBC900000 & 0xBCA00000: DMAC =
 
TODO: this could be the same as 0xBC800000, just for more processors (8 for 0xBC900000, 8 for 0xBCA00000)
 
{| class="wikitable"
|-
! Address !! Size !! R/W !! Description
|-
|-
| 0xBC900020 || 4 || W? || Unknown (DMA soft request-related)
| 0xBC900020 || 4 || W? || Unknown (DMA soft request-related)
Line 1,109: Line 1,048:
|-
|-
|}
|}
= 0xBCA00000: DMAC related =


= 0xBCC00000: VME Control =
= 0xBCC00000: VME Control =
Line 1,131: Line 1,072:
|}
|}


= 0xBD000000: DDR =
= 0xBD000000: DDR? =
 
= 0xBD100000: NAND Flash =


{| class="wikitable"
{| class="wikitable"
Line 1,140: Line 1,083:
! Description
! Description
|-
|-
| 0xBD000004 || 4 || RW || DDR flush
| 0xBD101000 || 4 || R || NAND control
 
Bit 16 = read ECC (0 = don't calculate, 1 = calculate)
 
Bit 17 = write ECC (0 = don't calculate, 1 = calculate)
|-
|-
| 0xBD000020 || 4 || RW || Unknown
| 0xBD101004 || 4 || R || NAND status
 
Bit 0 = status (0 = busy, 1 = ready)
 
Bit 7 = write protection (1 = write protected)
|-
|-
| 0xBD000024 || 4 || RW || Unknown
| 0xBD101008 || 4 || W || NAND command
|-
| 0xBD00002C || 4 || RW || Unknown, used by IPL
|-
| 0xBD000030 || 4 || RW || Unknown, used during sceDdrChangePllClock()
|-
| 0xBD000034 || 4 || RW || Unknown, used during sceDdrChangePllClock()
|-
| 0xBD000038 || 4 || RW || Unknown, used by IPL
|-
| 0xBD000040 || 4 || RW || Unknown, used during sceDdrChangePllClock()
|-
| 0xBD000044 || 4 || RW || Unknown, used during sceDdrChangePllClock()
|-
|}


= 0xBD100000: NAND Flash =
0x00/0x01 = read (1?)


{| class="wikitable"
0x50 = read (2?)
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBD101000 || 4 || R || NAND control


Bit 16 = read ECC (0 = don't calculate, 1 = calculate)
0x90 = read ID


Bit 17 = write ECC (0 = don't calculate, 1 = calculate)
0xFF = reset
|-
| 0xBD101004 || 4 || R || NAND status


Bit 0 = status (0 = busy, 1 = ready)
0x80, or 0x10 at 2nd cycle = page program


Bit 7 = write protection (1 = write protected)
0x00, or 0x8A at 2nd cycle = copy-back program
|-
| 0xBD101008 || 4 || W || NAND command
 
0x00/0x01 = read (1?)
 
0x50 = read (2?)
 
0x90 = read ID
 
0xFF = reset
 
0x80, or 0x10 at 2nd cycle = page program
 
0x00, or 0x8A at 2nd cycle = copy-back program


0x60, or 0xD0 at 2nd cycle = block erase
0x60, or 0xD0 at 2nd cycle = block erase
Line 1,239: Line 1,153:
! Address !! Size !! R/W !! Description
! Address !! Size !! R/W !! Description
|-
|-
| 0xBD200000 || 2 || RW || MemoryStick interrupt
| 0xBD200030 || 4 || ? || Memstick cmd (?)
 
|-
Bit 0 = reg address
| 0xBD200034 || 4 || ? || Memstick data (?)
 
|-
Bit 4 = cmdnk (command cannot be executed)
| 0xBD200038 || 4 || ? || Memstick status (?)
 
Bit 5 = breq (buffer request)
 
Bit 6 = error
 
Bit 7 = ced (command end)
 
|-
|-
| 0xBD200002 || 2 || W? || Unknown
| 0xBD20003C || 4 || ? || Memstick sys (?)
|-
|-
| 0xBD200004 || 2 || RW || Command state
|}


Bit 0: busy
= 0xBD300000: WLAN =


= 0xBD400000: Graphics Engine =
{| class="wikitable"
|-
|-
| 0xBD200010 || 2 || W? || Number of pages
! Physical Address !! Size !! R/W !! Description
|-
|-
| 0xBD200012 || 2 || W? || OOB length
| 0xBD400000 || 4 || RW || RW bit 1: set to 1 to reset, wait until bit is 0 to know the GE has been reset
|-
|-
| 0xBD200014 || 2 || W? || Start block
| 0xBD400004 || 4 || RW? || Unknown (accessible through sceGeSet/GetReg() and passed to the interrupt handlers but unused)
|-
|-
| 0xBD200016 || 2 || W? || Set command to read and set page LBA
| 0xBD400008 || 4 || R || RO bits 0x0000FFFF: shifted left by 10, gives the EDRAM hardware size (sceGeEdramGetHwSize()) (only used for tachyon < 0x00500000)
|-
|-
| 0xBD200020 || 2 || W? || Unknown
| 0xBD400100 || 4 || RW || RW bit 0x001: 0 = stopped, 1 = running
|-
| 0xBD200024 || 2 || R || Read OOB data
|-
| 0xBD200024 || 1 || W || Write command data
|-
| 0xBD200028 || 2 or 4 || RW || Read/write page data
|-
| 0xBD200030 || 4 || RW || Start TPC


Bits 0-9 = size
R  bit 0x002: 0 = branching condition true, 1 = false


Bits 12-31 = TPC code
R  bit 0x100: 1 = is at depth 1 (or 2) of calls
 
Code 1 = read MG status
 
Code 2 = read page data
 
Code 3 = read short data
 
Code 4 = read reg
 
Code 5 = read IO data
 
Code 7 = get int
 
Code 8 = set rw reg address
 
Code 9 = ex set cmd
 
Code 10 = write IO data
 
Code 11 = write reg
 
Code 12 = write short data
 
Code 13 = write page data
 
Code 14 = set cmd


R  bit 0x200: 1 = is at depth 2 of calls
|-
| 0xBD400104 || 4 || RW? || Unknown (accessible through sceGeSet/GetReg() but unused)
|-
|-
| 0xBD200034 || 2 or 4 || RW || Read/write TPC data
| 0xBD400108 || 4 || RW || Address of the display list currently being run
|-
|-
| 0xBD200038 || 2 or 4 || RW || Memstick status
| 0xBD40010C || 4 || RW || Stall address of the display list (0 = no stall address)
 
Bits 0-3 = bits 4-7 from the reg address register
 
Bit 8 = timeout
 
Bit 9 = CRC error
 
Bit 12 = ready
 
Bit 13 = unknown
 
Bit 14 = FIFO RW
|-
|-
| 0xBD20003C || 4 || RW || Memstick sys
| 0xBD400110 || 4 || RW || First return address (after the first CALL command)
 
Bit 9 = command
 
Bit 11 = interrupt
 
Bit 15 = reset
|-
|-
| 0xBD200040 || 4 || RW || Unknown
| 0xBD400114 || 4 || RW || Second return address (after the second CALL command)
|-
|-
|}
| 0xBD400118 || 4 || RW || Address of vertices (for bezier etc)
 
= 0xBD300000: WLAN =
 
The interface to the WLAN is the same as to the Memorystick, just with different commands.
 
= 0xBD400000: Graphics Engine =
 
{| class="wikitable"
|-
|-
! Physical Address !! Size !! R/W !! Description
| 0xBD40011C || 4 || RW || Address of indices (for bezier etc)
|-
|-
| 0xBD400000 || 4 || RW || RW bit 1: set to 1 to reset, wait until bit is 0 to know the GE has been reset
| 0xBD400120 || 4 || RW || Address of the origin (set by ORIGIN, destination address for JUMP/BJUMP/CALL after adding BASE and the address specified in the command)
|-
|-
| 0xBD400004 || 4 || RW? || Unknown (accessible through sceGeSet/GetReg() and passed to the interrupt handlers but unused)
| 0xBD400124 || 4 || RW || Same as above, for the first call
|-
|-
| 0xBD400008 || 4 || R || RO bits 0x0000FFFF: shifted left by 10, gives the EDRAM hardware size (sceGeEdramGetHwSize()) (only used for tachyon < 0x00500000)
| 0xBD400128 || 4 || RW || Same as above, for the second call
|-
|-
| 0xBD400100 || 4 || RW || RW bit 0x001: 0 = stopped, 1 = running
| 0xBD400200 || 4 || RW || Bit 1 set by sceGeSetGeometryClock(), exact usage unknown
 
R  bit 0x002: 0 = branching condition true, 1 = false
 
R  bit 0x100: 1 = is at depth 1 (or 2) of calls
 
R  bit 0x200: 1 = is at depth 2 of calls
|-
| 0xBD400104 || 4 || RW? || Status? (accessible through sceGeSet/GetReg() but unused)
|-
| 0xBD400108 || 4 || RW || Address of the display list currently being run
|-
| 0xBD40010C || 4 || RW || Stall address of the display list (0 = no stall address)
|-
| 0xBD400110 || 4 || RW || First return address (after the first CALL command)
|-
| 0xBD400114 || 4 || RW || Second return address (after the second CALL command)
|-
| 0xBD400118 || 4 || RW || Address of vertices (for bezier etc)
|-
| 0xBD40011C || 4 || RW || Address of indices (for bezier etc)
|-
| 0xBD400120 || 4 || RW || Address of the origin (set by ORIGIN, destination address for JUMP/BJUMP/CALL after adding BASE and the address specified in the command)
|-
| 0xBD400124 || 4 || RW || Same as above, for the first call
|-
| 0xBD400128 || 4 || RW || Same as above, for the second call
|-
| 0xBD400200 || 4 || RW || Bit 1 set by sceGeSetGeometryClock(), exact usage unknown
|-
|-
| 0xBD400300 || 4 || RW || Unknown (accessible through sceGeSet/GetReg() but unused)
| 0xBD400300 || 4 || RW || Unknown (accessible through sceGeSet/GetReg() but unused)
|-
|-
| 0xBD400304 || 4 || RW || Get/set current command status (1 = SIGNAL, 2 = END, 4 = FINISH, 8 = ERROR)
| 0xBD400304 || 4 || R || Current interrupt status?
|-
|-
| 0xBD400308 || 4 || RW || Get/clear interrupts
| 0xBD400308 || 4 || RW || Currently accepted interrupts? (1 = SIGNAL, 2 = END, 4 = FINISH, 8 = ERROR)
|-
|-
| 0xBD40030C || 4 || W || Change interrupts (ie swap the status of specified interrupts)
| 0xBD40030C || 4 || W? || Set to the value of 0xBD400308 on init & reset
|-
|-
| 0xBD400310 || 4 || W || Change command status (ie swap the status of specified bits)
| 0xBD400310 || 4 || W? || Set current interrupt status? Set to the value of 0xBD400308 on init & reset
|-
|-
| 0xBD400400 || 4 || RW || Set to 4 when the used edram size is 0x00200000 and 2 when it's 0x00400000 (!)
| 0xBD400400 || 4 || RW || Set to 4 when the used edram size is 0x00200000 and 2 when it's 0x00400000 (!)
Line 1,444: Line 1,269:


= 0xBD600000: ATA/UMD =
= 0xBD600000: ATA/UMD =
= 0xBD700000: ATA/UMD =
= 0xBD800000: USB =
= 0xBDE00000: KIRK =


{| class="wikitable"
{| class="wikitable"
Line 1,452: Line 1,283:
! Description
! Description
|-
|-
| 0xBD600000 || 4 || R? || Unknown (returns 0x00010033)
| 0xBDE00000 || 4 || R || KIRK signature 'KIRK' (or 1?)
|-
|-
| 0xBD600004 || 4 || W? || Unknown (0x04028002 is written here)
| 0xBDE00004 || 4 || R || KIRK version '0010' (or 1?)
|-
|-
| 0xBD600010 || 4 || RW || Unknown (reset?)
| 0xBDE00008 || 4 || RW || Set to 1 on error by the command subroutine
|-
|-
| 0xBD600014 || 4 || W? || Unknown
| 0xBDE0000C || 4 || RW || Set to 1 to start processing
|-
|-
| 0xBD60001C || 4 || W? || Unknown (0x00020A0C is written here)
| 0xBDE00010 || 4 || RW || KIRK command
|-
 
| 0xBD600034 || 4 || RW || Unknown (0 is written here)
0x01 = Private decrypt
|-
| 0xBD600038 || 4 || W? || Unknown (0x00010100 is written here)
|-
| 0xBD600040 || 4 || RW || Unknown (0 is written here, flag 0x2 is tested)
|-
| 0xBD600044 || 4 || W? || Unknown
|-
|}


= 0xBD700000: ATA/UMD =
0x02 = Encrypt (type2)


{| class="wikitable"
0x03 = Decrypt (type2)
|-
 
! Address
0x04 = Encrypt (type3) (IV = 0)
! Size
! Read/write
! Description
|-
| 0xBD700000 || 2 || RW || Read/write data
|-
| 0xBD700001 || 1 || RW || Features (?)
|-
| 0xBD700002 || 1 || RW || Sector count
|-
| 0xBD700003 || 1 || RW || Sector number
|-
| 0xBD700004 || 1 || RW || Cylinder low
|-
| 0xBD700005 || 1 || RW || Cylinder high
|-
| 0xBD700006 || 1 || RW || Drive
|-
| 0xBD700007 || 1 || RW || Command


Cmd 0x08 = reset
0x05 = Encrypt (type3) (IV = Fuse)


Cmd 0xA0 = packet
0x06 = Encrypt (type3) (IV = User)


Cmd 0xC8 = read
0x07 = Decrypt (type3) (IV = 0)


Cmd 0xCA = write
0x08 = Decrypt (type3) (IV = Fuse)


Cmd 0xE0 = standby now 1
0x09 = Decrypt (type3) (IV = User)


Cmd 0xE6 = sleep
0x0A = Private Signature Check


Cmd 0xE7 = flush
0x0B = SHA-1 Hash


Cmd 0xEC = ID ATA
0x0C = ECDSA Key Generate


Cmd 0xEF = set features
0x0D = ECDSA Point Multiply


|-
0x0E = Pseudo-random Number Generator
| 0xBD700008 || 1 || W? || End of data
|-
| 0xBD70000E || 1 || RW || Control


Bit 2 = soft reset
0x0F = PRNG Seed? Init?
|-
|}


= 0xBD800000: USB =
0x10 = ECDSA Sign


{| class="wikitable"
0x11 = ECDSA Signature Check
|-
|-
! Address
| 0xBDE00014 || 4 || RW || Result of the command
! Size
|-
! Read/write
| 0xBDE00018 || 4 || RW || Unknown
! Description
|-
|-
| 0xBD800000 || 4 || RW || Get/set control of first sending endpoint
| 0xBDE0001C || 4 || RW || KIRK status


Bit 1 = unknown
Bit 0 = phase finish


Bit 3 = unknown
Bit 1 = phase error?


Bits 4-5 = transfer type
Bit 4 = phase 2 needed


Bit 6 = unknown
Bit 5 = ? (phase 1 error maybe?)


Bit 7 = unknown
This should be used for checking processing status, and will notify when the processing has finished.
 
All bits are 0 while execution is still in progress.
Bit 8 = unknown
If the command has two phases, Phase 2 Needed will be set when Phase Finish gets set.
Bit1 and bit5 are not well known, but it seems that bit1 is Error for Phase 1, and Success for Phase 2? Bit5 is only checked for Phase 1, and leads to the same error codepath as bit1.
|-
|-
| 0xBD800004 || 4 || RW || Read/clear status of first sending endpoint
| 0xBDE00020 || 4 || RW || Unknown
 
Bits 4, 5, 6, 7, 9, 10, 14 = unknown
|-
|-
| 0xBD800008 || 4 || RW || Max packet size in words for first sending endpoint
| 0xBDE00024 || 4 || RW || Unknown
|-
|-
| 0xBD80000C || 4 || RW || Max packet size in bytes for first sending endpoint (possible value: 0x40)
| 0xBDE00028 || 4 || RW || Set to the value of 0xBDE0001C at the end of the command subroutine
|-
|-
| 0xBD800010 || 4 || RW || Unknown address, for first sending endpoint (0x80000000 is written there)
| 0xBDE0002C || 4 || RW || KIRK source buffer (physical address)
|-
|-
| 0xBD800014 || 4 || RW || Unknown address, for first sending endpoint (0x80000000 is written there)
| 0xBDE00030 || 4 || RW || KIRK destination buffer (physical address)
|-
|-
| 0xBD800020 || 24 || RW || Same as above, for 2nd sending endpoint
| 0xBDE0004C || 4 || RW || Unknown
|-
|-
| 0xBD800040 || 24 || RW || Same as above, for 3rd sending endpoint
| 0xBDE00050 || 4 || RW || Unknown
|-
|-
| 0xBD800060 || 24 || RW || Same as above, for 4th sending endpoint
|}
|-
 
| 0xBD800080 || 24 || RW || Same as above, for 5th sending endpoint
= 0xBDF00000: UMD? =
|-
 
| 0xBD800200 || 24 || RW || Same as above, for 1st receiving endpoint
= 0xBE000000: Audio =
 
{| class="wikitable"
|-
|-
| 0xBD800220 || 24 || RW || Same as above, for 2nd receiving endpoint
! Address
|-
! Size
| 0xBD800240 || 24 || RW || Same as above, for 3rd receiving endpoint
! Read/write
|-
! Description
| 0xBD800260 || 24 || RW || Same as above, for 4th receiving endpoint
|-
| 0xBD800280 || 24 || RW || Same as above, for 5th receiving endpoint
|-
|-
| 0xBD800400 || 4 || RW || Unknown (possible values: 0xA0, 0x8 = activated without charging, 0x1)
| 0xBE000000 || 4 || W? || Audio init/reset?
|-
|-
| 0xBD800404 || 4 || RW || Unknown
| 0xBE000004 || 4 || W? || Enable audio input/output?
|-
| 0xBD800408 || 4 || R? || Unknown
|-
| 0xBD80040C || 4 || RW || Clear/read connection interrupt


Value 0 = connect
Bit 0: enable output


Value 1 = streaming
Bit 1: enable SRC output (?)


Value 2 = detach 1
Bit 2: enable audio input


Value 4 = detach 2
Bit 3: ??
 
Value 6 = unknown
|-
|-
| 0xBD800410 || 4 || RW || Set/get enabled connection interrupts (same bits as above)
| 0xBE000008 || 4 || W? || Same as 0xBE000004 but with reversed bits; maybe stop/empty buffer?
|-
|-
| 0xBD800414 || 4 || RW || Unknown
| 0xBE00000C || 4 || R? || Seems to contain the current value for 0xBE000004 (ie the current enabled input/outputs)
|-
|-
| 0xBD800418 || 4 || RW || Disabled endpoints interfaces (bits 0-8 = sending, and bits 16-24 = receiving?)
| 0xBE000010 || 4 || W? || Similar to 0xBE000004 but set only when starting playing something, and input bit is set only for loopback test?
|-
|-
| 0xBD80041C || 4 || RW || Unknown (possible value: 0)
| 0xBE000014 || 4 || W? || Unknown, set to 0x1208 = 4616 during initialization
|-
|-
| 0xBD800504 || 4 || W? || Unknown
| 0xBE000018 || 4 || W? || Unknown, set to 0 during initialization
|-
|-
| 0xBD800508 || 4 || W? || Unknown
| 0xBE00001C || 4 || R? || Similar to 0xBE000004; possibly bits which finished execution?
|-
|-
| 0xBD80050C || 4 || W? || Unknown
| 0xBE000020 || 4 || W? || Another similar set of flags
|-
|-
| 0xBD800510 || 4 || W? || Unknown
| 0xBE000024 || 4 || W? || Another similar set of flags
|-
|-
| 0xBD800514 || 4 || W? || Unknown
| 0xBE000028 || 4 || W? || Another similar set of flags
|-
|-
|}
| 0xBE00002C || 4 || W? || Another similar set of flags
 
= 0xBD900000: EFlash (PSP Go only) =
 
{| class="wikitable"
|-
|-
! Address
| 0xBE000038 || 4 || W? || Set to 256 when frequency in 48kHz, 128 when it is 44.1kHz or during SRC output
! Size
! Read/write
! Description
|-
|-
| 0xBD900004 || 4 || W? || Unknown, set to 0x04024002
| 0xBE00003C || 4 || W? || Same as above, but not set at initialization time
|-
|-
| 0xBD900010 || 4 || W? || Write 1 to reset
| 0xBE000040 || 4 || RW || Frequency-related??
|-
|-
| 0xBD900014 || 4 || W? || Unknown
| 0xBE000044 || 4 || W? || Frequency-related??
|-
|-
| 0xBD900018 || 4 || W? || Unknown
| 0xBE000050 || 4 || RW || Volume?
|-
|-
| 0xBD900024 || 4 || W? || Unknown
| 0xBE000060 || 4 || ? || ??
|-
|-
| 0xBD900028 || 4 || W? || Unknown
| 0xBE000070 || 4 || ? || ??
|-
|-
| 0xBD90002C || 4 || W? || Unknown, set to 0
| 0xBE000080 || 4 || ? || ??
|-
|-
| 0xBD900030 || 4 || W? || Unknown, set to 0
| 0xBE0000D0 || 4 || ? || ??
|-
| 0xBD900034 || 4 || RW || Unknown
|-
| 0xBD900038 || 4 || W? || Unknown
|-
| 0xBD900040 || 4 || W? || Unknown
|-
| 0xBD900044 || 4 || RW || Clear/read interrupt flag
|-
|-
|}
|}


= 0xBDA00000: EFlash ATA (PSP Go only) =
= 0xBE100000: MagicGate hardware for memory stick? =


Same interface as 0xBD700000.
= 0xBE140000: LCDC =
 
= 0xBDB00000: EFlash DMA =


{| class="wikitable"
{| class="wikitable"
Line 1,663: Line 1,436:
! Description
! Description
|-
|-
| 0xBDB00008 || 4 || W? || Set to 1 to reset
| 0xBE140000 || 4 || RW || First LCDC controller enable
|-
| 0xBDB00010 || 4 || W? || Control


Bit 0 = enable
Bits 0-1 = 3 to enable first LCDC controller (tachyon version < 0x800000; otherwise it's set to 0)
 
Bit 1 = 1 if read from ATA, 0 if write to ATA
|-
|-
| 0xBDB00020 || 4 || R? || Read interrupt flag
| 0xBE140004 || 4 || RW || Synchronization difference: (xsync / zoom) - ysync
|-
|-
| 0xBDB00024 || 4 || W? || Clear interrupt flag
| 0xBE140008 || 4 || RW || Unknown (fourth argument of sceLcdcCheckMode and sceLcdcSetMode)
|-
|-
| 0xBDB00028 || 4 || RW || Unknown
| 0xBE140010 || 4 || RW || X back porch
|-
|-
| 0xBDB0002C || 4 || W? || Unknown, clear bits from the previous register
| 0xBE140014 || 4 || RW || X sync width
|-
|-
| 0xBDB00030 || 4 || W? || DMA address
| 0xBE140018 || 4 || RW || X front porch
|-
|-
| 0xBDB00034 || 4 || W? || DMA size
| 0xBE14001C || 4 || RW || X resolution
|-
|-
| 0xBDB00040 || 4 || W? || Unknown
| 0xBE140020 || 4 || RW || Y back porch
|-
|-
| 0xBDB00044 || 4 || W? || Unknown, set to 0
| 0xBE140024 || 4 || RW || Y sync width
|}
|-
| 0xBE140028 || 4 || RW || Y front porch
|-
| 0xBE14002C || 4 || RW || Y resolution
|-
| 0xBE140030 || 4 || R || HPC (?), returned by sceLcdcReadHPC()
|-
| 0xBE140034 || 4 || R || VPC (?), returned by sceLcdcReadVPC()
|-
| 0xBE140040 || 4 || RW || Y shift (between hardware & software resolution)
|-
| 0xBE140044 || 4 || RW || X shift (between hardware & software resolution)
|-
| 0xBE140048 || 4 || RW || Scaled X resolution
|-
| 0xBE14004C || 4 || RW || Scaled Y resolution (same as the physical Y resolution)
|-
| 0xBE140050 || 4 || RW || Unknown, set to 1, maybe used by sceLcdcReadUnderflow (to be verified)
|-
| 0xBE140070 || 4 || W || Set to 1 when running sceLcdcResume() or sceLcdcInit() on tachyon version >= 0x5000000
|-
|}


= 0xBDE00000: KIRK =
The exact same registers are at 0xBE1401.., these ones being used for tachyon version >= 0x8000000 (PSP Go?). <br>
These registers are only set on tachyo version >= 0x8000000:


{| class="wikitable"
{| class="wikitable"
Line 1,697: Line 1,488:
! Description
! Description
|-
|-
| 0xBDE00000 || 4 || R || KIRK signature 'KIRK' (or 1?)
| 0xBE140180 || 4 || RW || Always set to 1 when 0xBE140184 - 0xBE140198 are used
|-
|-
| 0xBDE00004 || 4 || R || KIRK version '0010' (or 1?)
| 0xBE140184 || 4 || RW || Scaled X resolution (read instead of the (real) X resolution above when enabled)
|-
| 0xBE140188 || 4 || RW || Y resolution (read instead of the (real) Y resolution above when enabled)
|-
| 0xBE14018C || 4 || RW || Unknown (0x580 - 0x678)
|-
| 0xBE140190 || 4 || RW || Unknown (0x4C4 - 0x71C)
|-
| 0xBE140194 || 4 || RW || Unknown (0xAFC - 0xCEC)
|-
|-
| 0xBDE00008 || 4 || RW || Set to 1 on error by the command subroutine
| 0xBE140198 || 4 || RW || Unknown (0x910 - 0xE38)
|-
|-
| 0xBDE0000C || 4 || RW || Set to 1 to start processing, or 2 to start processing phase2
| 0xBE140200 || 4 || W || Set to 1 on initialization
|-
|-
| 0xBDE00010 || 4 || RW || KIRK command
|}


0x01 = Private decrypt
= 0xBE200000: I2c =


0x02 = Encrypt (type2)
= 0xBE240000: GPIO =


0x03 = Decrypt (type2)
{| class="wikitable"
 
|-
0x04 = Encrypt (type3) (IV = 0)
! Address
 
! Size
0x05 = Encrypt (type3) (IV = Fuse)
! Read/write
! Description
|-
| 0xBE240000 || 4 || RW || Unknown
|-
| 0xBE240004 || 4 || R || GPIO read pin (1 bit = 1 pin)
|-
| 0xBE240008 || 4 || W || GPIO set pin (1 bit = 1 pin)
|-
| 0xBE24000C || 4 || W|| GPIO clear pin (1 bit = 1 pin)
|-
| 0xBE240010 || 4 || ? || Unknown
|-
| 0xBE240014 || 4 || ? || Unknown
|-
| 0xBE240018 || 4 || ? || Unknown
|-
| 0xBE24001C || 4 || ? || Unknown
|-
| 0xBE240020 || 4 || ? || Unknown
|-
| 0xBE240030 || 4 || ? || Unknown
|-
| 0xBE240040 || 4 || ? || Unknown
|-
| 0xBE240048 || 4 || ? || Unknown
|-
|}


0x06 = Encrypt (type3) (IV = User)
= 0xBE300000: Power management? =
 
0x07 = Decrypt (type3) (IV = 0)


0x08 = Decrypt (type3) (IV = Fuse)
= 0xBE400000 & 0xBE500000: UART =


0x09 = Decrypt (type3) (IV = User)
The second 'xx' bytes of the addresses can be 0x40, 0x44, 0x48, 0x4C, 0x50, 0x54, 0x58, 0x5C for the different UART ports (1-8, in that order).


0x0A = Private Signature Check
Note that:
* UART1 = ?
* UART2 = ?
* UART3 = ?
* UART4 = ?
* UART5 = Headphone/remote SIO
* UART6 = Infrared
* UART7 = Syscon
* UART8 = PSP 2k+ display-related


0x0B = SHA-1 Hash
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBExx0000 || 4 || RW || Read/write FIFO of the UART port


0x0C = ECDSA Key Generate
Bits 0-7 = data


0x0D = ECDSA Point Multiply
Writing writes a byte to the Tx buffer and advances the write position.
Reading reads a byte from the Rx buffer and advances the read position.
The FIFO is 32(?) bytes long.
|-
| 0xBExx0018 || 4 || RW || Port status


0x0E = Pseudo-random Number Generator
Bit 4 = Rx buffer status is empty


0x0F = PRNG Seed? Init?
Bit 5 = Tx buffer status is full
 
|-
0x10 = ECDSA Sign
| 0xBExx0024 || 4 || W || Upper bits of baudrate divisor, ie (96000000 / baudrate) >> 6
 
0x11 = ECDSA Signature Check
|-
|-
| 0xBDE00014 || 4 || RW || Result of the command
| 0xBExx0028 || 4 || W || Lower bits of baudrate divisor, ie (96000000 / baudrate) & 0x3f
|-
|-
| 0xBDE00018 || 4 || RW || Unknown
| 0xBExx002C || 4 || W || Set bits 5-6 to set the baud rate?
|-
| 0xBDE0001C || 4 || RW || KIRK status
 
Bit 0 = phase finish
 
Bit 1 = phase error?
 
Bit 4 = phase 2 needed
 
Bit 5 = ? (phase 1 error maybe?)
 
This should be used for checking processing status, and will notify when the processing has finished.
All bits are 0 while execution is still in progress.
If the command has two phases, Phase 2 Needed will be set when Phase Finish gets set.
Bit1 and bit5 are not well known, but it seems that bit1 is Error for Phase 1, and Success for Phase 2? Bit5 is only checked for Phase 1, and leads to the same error codepath as bit1.
|-
| 0xBDE00020 || 4 || RW || Status async?
|-
| 0xBDE00024 || 4 || RW || Status async end?
|-
| 0xBDE00028 || 4 || RW || Set to the value of 0xBDE0001C at the end of the command subroutine
|-
| 0xBDE0002C || 4 || RW || KIRK source buffer (physical address)
|-
| 0xBDE00030 || 4 || RW || KIRK destination buffer (physical address)
|-
| 0xBDE0004C || 4 || RW || Unknown
|-
| 0xBDE00050 || 4 || RW || Unknown
|-
|-
|}
|}


= 0xBDF00000: UMD =
= 0xBE600000: ? =
 
{| class="wikitable"
|-
! Address !! Size !! R/W !! Description
|-
| 0xBC900008 || 4 || RW || Reset
 
Bit 0 = reset
|-
| 0xBC900010 || 4 || RW || Set command
 
Value 0x01 = ?
 
Value 0x02 = ?
 
Value 0x03 = ?
 
Value 0x04 = write QTGP2 () at the first transfer address
 
Value 0x05 = write QTGP3 () at the first transfer address
 
Value 0x08 = find region
 
Value 0x09 = ?
 
Value 0x0A = read data
 
Value 0x0B = ?
|-
| 0xBD900014 || 4 || R? || Unknown
|-
| 0xBD900018 || 4 || R? || Unknown flags
|-
| 0xBD90001C || 4 || R? || Unknown
|-
| 0xBD900020 || 4 || R? || Get interrupt flags?
|-
| 0xBD900024 || 4 || RW || Clear interrupt?
|-
| 0xBD900028 || 4 || RW || Enable interrupt?
|-
| 0xBD90002C || 4 || RW || Disable interrupt?
|-
| 0xBD900030 || 4 || RW || Unknown, set to 4
|-
| 0xBD900038 || 4 || RW || Unknown, set to 4
|-
| 0xBD900040 || 4 || W? || Transfer address 0
|-
| 0xBD900044 || 4 || W? || Transfer size 0
|-
| 0xBD900048 || 4 || W? || Transfer address 1
|-
| 0xBD90004C || 4 || W? || Transfer size 1
|-
| 0xBD900050 || 4 || W? || Transfer address 2
|-
| 0xBD900054 || 4 || W? || Transfer size 2
|-
| 0xBD900058 || 4 || W? || Transfer address 3
|-
| 0xBD90005C || 4 || W? || Transfer size 3
|-
| 0xBD900060 || 4 || W? || Transfer address 4
|-
| 0xBD900064 || 4 || W? || Transfer size 4
|-
| 0xBD900068 || 4 || W? || Transfer address 5
|-
| 0xBD90006C || 4 || W? || Transfer size 5
|-
| 0xBD900070 || 4 || W? || Transfer address 6
|-
| 0xBD900074 || 4 || W? || Transfer size 6
|-
| 0xBD900078 || 4 || W? || Transfer address 7
|-
| 0xBD90007C || 4 || W? || Transfer size 7
|-
| 0xBD900080 || 4 || W? || Transfer address 8
|-
| 0xBD900084 || 4 || W? || Transfer size 8
|-
| 0xBD900088 || 4 || W? || Transfer address 9
|-
| 0xBD90008C || 4 || W? || Transfer size 9
|-
| 0xBD900090 || 4 || RW || Total transfer length
|-
| 0xBD900094 || 4 || W? || Unknown, can be 0 or 1
|-
|}
 
= 0xBE000000: Audio =
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBE000000 || 4 || RW || Audio init/reset?
|-
| 0xBE000004 || 4 || W? || Disable audio input/output?
 
Bit 0: enable output
 
Bit 1: enable SRC output (?)
 
Bit 2: enable audio input
 
Bit 3: ??
|-
| 0xBE000008 || 4 || W? || Same as 0xBE000004 but with reversed bits; enable audio input/output?
|-
| 0xBE00000C || 4 || RW || Seems to contain the current value for 0xBE000004 (ie the current enabled input/outputs)
|-
| 0xBE000010 || 4 || W? || Similar to 0xBE000004 but set only when starting playing something, and input bit is set only for loopback test?
|-
| 0xBE000014 || 4 || W? || Unknown, set to 0x1208 = 4616 during initialization
|-
| 0xBE000018 || 4 || W? || Unknown, set to 0 during initialization
|-
| 0xBE00001C || 4 || R? || Similar to 0xBE000004; possibly bits which finished execution?
|-
| 0xBE000020 || 4 || W? || Another similar set of flags
|-
| 0xBE000024 || 4 || W? || Another similar set of flags (enabled interrupts?)
|-
| 0xBE000028 || 4 || RW || Another similar set of flags
|-
| 0xBE00002C || 4 || W? || Another similar set of flags
|-
| 0xBE000038 || 4 || W? || Set to 256 when frequency in 48kHz, 128 when it is 44.1kHz or during SRC output
|-
| 0xBE00003C || 4 || W? || Same as above, but not set at initialization time
|-
| 0xBE000040 || 4 || RW || Frequency-related??
|-
| 0xBE000044 || 4 || W? || Hardware frequency?
|-
| 0xBE000050 || 4 || RW || Volume?
|-
| 0xBE000060 || 4 || W? || Send audio data?
|-
| 0xBE000070 || 4 || W? || Send audio data?
|-
| 0xBE000080 || 4 || ? || ??
|-
| 0xBE0000D0 || 4 || ? || ??
|}
 
= 0xBE100000: MagicGate Type-R =
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBE100000 || ? || ? || Unknown
|-
| 0xBE100010 || ? || ? || ?Key size (in bits)?. ex: 0x100 (hardcoded)
|-
| 0xBE100020 || ? || ? || Unknown
|-
| 0xBE100038 || ? || ? || Hardware version 1
|-
| 0xBE100040 || 0x10 || ? || Key
|-
| 0xBE100050 || 8 || ? || Unknown
|-
| 0xBE100060 || 0x10 || ? || IV
|-
| 0xBE100080 || ? || ? || Control
|-
| 0xBE100084 || ? || ? || Status
|-
| 0xBE100088 || ? || ? || Algorithm
|-
| 0xBE100090 || ? || ? || Unknown. Value at bit 8 is used.
|-
| 0xBE100094 || ? || ? || Size
|-
| 0xBE100098 || ? || ? || Hardware version 2
|-
| 0xBE1000A0 || ?0x800? || ? || Input buffer
|}
 
= 0xBE140000: LCDC =
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBE140000 || 4 || RW || First LCDC controller enable
 
Bits 0-1 = 3 to enable first LCDC controller (tachyon version < 0x800000; otherwise it's set to 0)
|-
| 0xBE140004 || 4 || RW || Synchronization difference: (xsync / zoom) - ysync
|-
| 0xBE140008 || 4 || RW || Unknown (fourth argument of sceLcdcCheckMode and sceLcdcSetMode)
|-
| 0xBE140010 || 4 || RW || X back porch
|-
| 0xBE140014 || 4 || RW || X sync width
|-
| 0xBE140018 || 4 || RW || X front porch
|-
| 0xBE14001C || 4 || RW || X resolution
|-
| 0xBE140020 || 4 || RW || Y back porch
|-
| 0xBE140024 || 4 || RW || Y sync width
|-
| 0xBE140028 || 4 || RW || Y front porch
|-
| 0xBE14002C || 4 || RW || Y resolution
|-
| 0xBE140030 || 4 || R || HPC (?), returned by sceLcdcReadHPC()
|-
| 0xBE140034 || 4 || R || VPC (?), returned by sceLcdcReadVPC()
|-
| 0xBE140040 || 4 || RW || Y shift (between hardware & software resolution)
|-
| 0xBE140044 || 4 || RW || X shift (between hardware & software resolution)
|-
| 0xBE140048 || 4 || RW || Scaled X resolution
|-
| 0xBE14004C || 4 || RW || Scaled Y resolution (same as the physical Y resolution)
|-
| 0xBE140050 || 4 || RW || Unknown, set to 1, maybe used by sceLcdcReadUnderflow (to be verified)
|-
| 0xBE140070 || 4 || W || Set to 1 when running sceLcdcResume() or sceLcdcInit() on tachyon version >= 0x5000000
|-
|}
 
The exact same registers are at 0xBE1401.., these ones being used for tachyon version >= 0x8000000 (PSP Go?). <br>
These registers are only set on tachyo version >= 0x8000000:
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBE140180 || 4 || RW || Always set to 1 when 0xBE140184 - 0xBE140198 are used
|-
| 0xBE140184 || 4 || RW || Scaled X resolution (read instead of the (real) X resolution above when enabled)
|-
| 0xBE140188 || 4 || RW || Y resolution (read instead of the (real) Y resolution above when enabled)
|-
| 0xBE14018C || 4 || RW || Unknown (0x580 - 0x678)
|-
| 0xBE140190 || 4 || RW || Unknown (0x4C4 - 0x71C)
|-
| 0xBE140194 || 4 || RW || Unknown (0xAFC - 0xCEC)
|-
| 0xBE140198 || 4 || RW || Unknown (0x910 - 0xE38)
|-
| 0xBE1401A0 || 4 || RW || Display flags?
|-
| 0xBE1401B0 || 4 || RW || Display clock?
|-
| 0xBE140200 || 4 || W || Set to 1 on initialization
|-
|}
 
= 0xBE200000: I2c =
 
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBE200000 || 4 || R? || Unknown
|-
| 0xBE200004 || 4 || RW || Command
 
Value 0x85 = unknown (used after writing the transmit data)
 
Value 0x8A = receive data
 
Value 0x87 = unknown (used after writing the transmit data)
 
|-
| 0xBE200008 || 4 || RW || Data length
|-
| 0xBE20000C || 4 || R? || Read/write data
|-
| 0xBE200010 || 4 || RW || Unknown
|-
| 0xBE200014 || 4 || RW || Unknown
|-
| 0xBE20001C || 4 || RW || Unknown
|-
| 0xBE200028 || 4 || R? || Clear/read interrupt
|-
| 0xBE20002C || 4 || W? || Unknown
|-
|}
 
= 0xBE240000: GPIO =
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBE240000 || 4 || RW || Is output (?)
|-
| 0xBE240004 || 4 || R || GPIO read pin (1 bit = 1 pin)
|-
| 0xBE240008 || 4 || W || GPIO set pin (1 bit = 1 pin)
|-
| 0xBE24000C || 4 || W|| GPIO clear pin (1 bit = 1 pin)
|-
| 0xBE240010 || 4 || RW || Is edge detection (?)
|-
| 0xBE240014 || 4 || RW || Is falling edge (?)
|-
| 0xBE240018 || 4 || RW || Is rising edge (?)
|-
| 0xBE24001C || 4 || RW || Interrupt enable
|-
| 0xBE240020 || 4 || R? || Interrupt Status
|-
| 0xBE240024 || 4 || W || Acknowledge interrupt
|-
| 0xBE240030 || 4 || RW || Capture port enable
|-
| 0xBD240034 || 4 || RW || Timer capture enable
|-
| 0xBE240040 || 4 || RW || Is input on (?)
|-
| 0xBE240048 || 4 || W? || Unknown
|-
|}
 
= 0xBE300000: Power management? =
 
Seems to be composed of 3 controllers, each of size 0x20.
 
= 0xBE4C0000 & 0xBE500000: UART =
 
[https://developer.arm.com/documentation/ddi0183/f/programmer-s-model/summary-of-registers?lang=en ARM PrimeCell UART PL011]
 
There are two similar UART controllers:
* At 0xBE4C0000: UART4 = ?
* At 0xBE500000: UART3 = Headphone/remote SIO
 
There is also possibly an infrared controller at 0xBE540000.
 
UART port numbers vary depending on documentations.
 
Some documentations seem to argue that there are 8 controllers for 0xBE40 to 0xBE5C, but the syscon interface looks very different so it might not be the case.
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBExx0000 || 4 || RW || Read/write FIFO of the UART port
 
Bits 0-7 = data
 
Writing writes a byte to the Tx buffer and advances the write position.
Reading reads a byte from the Rx buffer and advances the read position.
The FIFO is 32(?) bytes long.
|-
| 0xBExx0004 || 4 || RW || Unknown
|-
| 0xBExx0018 || 4 || RW || Port status
 
Bit 4 = Rx buffer status is empty
 
Bit 5 = Tx buffer status is full
|-
| 0xBExx0024 || 4 || W || Upper bits of baudrate divisor, ie (96000000 / baudrate) >> 6
|-
| 0xBExx0028 || 4 || W || Lower bits of baudrate divisor, ie (96000000 / baudrate) & 0x3f
|-
| 0xBExx002C || 4 || RW || Set bits 5-6 to set the baud rate?
|-
| 0xBExx0030 || 4 || RW || Unknown
|-
| 0xBExx0034 || 4 || RW || Unknown
|-
| 0xBExx0038 || 4 || RW || Unknown
|-
| 0xBExx0044 || 4 || RW || Clear interrupt?
|-
|}
 
= 0xBE580000: Syscon =
[https://developer.arm.com/documentation/ddi0194/h/programmer-s-model/summary-of-primecell-ssp-registers?lang=en ARM PrimeCell Synchronous Serial port PL022]
 
TODO: validate register mappings
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBE580000 || 4 || W? || Unknown (0xCF is written there at initialization time)
|-
| 0xBE580004 || 4 || RW || Flags
 
Bit 1 = start syscon command
 
Bit 2 = reset data index
 
Bit 3 = in progress?
|-
| 0xBE580008 || 4 || RW || Read/write data
 
Bits 0-15: 16-bit data
|-
| 0xBE58000C || 4 || R? || Flags
 
Bit 0 = error
 
Bit 2 = not finished
|-
| 0xBE580014 || 4 || W? || Unknown (0 is written there)
|-
| 0xBE580018 || 4 || R? || Unknown
|-
| 0xBE580020 || 4 || W? || Unknown; clear error status?
|-
| 0xBE580024 || 4 || W? || Unknown (0 is written there)
|-
|}
 
= 0xBE5C0000: LCD controller (Slim) =
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBE5C0000 || 4 || W? || Unknown
|-
| 0xBE5C0004 || 4 || W? || Unknown
|-
| 0xBE5C0008 || 4 || RW? || Unknown
|-
| 0xBE5C000C || 4 || R? || Unknown
|-
| 0xBE5C0010 || 4 || W? || Unknown
|-
| 0xBE5C0014 || 4 || W? || Unknown
|-
| 0xBE5C0024 || 4 || W? || Unknown
|-
|}
 
= 0xBE740000: Display =
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBE740000 || 4 || W? || Unknown
|-
| 0xBE740004 || 4 || RW || Get/set row sync (?)
|-
| 0xBE740008 || 4 || R? || Get sync (?)
|-
| 0xBE74000C || 4 || W? || Unknown
|-
| 0xBE740010 || 4 || W? || Unknown
|-
| 0xBE740014 || 4 || W? || Unknown
|-
| 0xBE740020 || 4 || R? || Unknown
|-
| 0xBE740024 || 4 || W? || Unknown
|-
|}
 
= 0xBE780000: Display (Slim) =
 
{| class="wikitable"
|-
! Address
! Size
! Read/write
! Description
|-
| 0xBE780000 || 4 || ? || Unknown
|-
| 0xBE78001C || 4 || ? || Unknown
|}
 
= 0xBFC00000 & 0xBFD00000 & 0xBFE00000: MIPS Reset Vector and RAM =
 
Note this is not a hardware register *per se*.


At boot time, the PSP [[iplloader]] is mapped to read-only 0xBFC00000 then executed. An additional 4096-byte scratchpad-like RAM is accessible at 0xBFD00000 and used as a temporary space to decrypt the IPL blocks.
= 0xBE700000: Display =
Then, once the CPU is reset (0xBC10004C |= 2), the iplloader is unmapped, and the memory which was then at 0xBFD00000 is now mapped at 0xBFC00000 and execution restarts at 0xBFC00000.


On devkit, bloadp is copied to 0xBFE00000 then executed. IPL blocks are usually copied to 0xBFE01000, decrypted in place then executed.
= 0xBFC00000: MIPS Reset Vector =


= 0xBFF00000: NAND DMA buffer =
= 0xBFF00000: NAND DMA buffer =
Line 2,320: Line 1,613:
= References =
= References =


* [http://daifukkat.su/docs/psptek/ PSPTEK]
* [http://daifukkat.su/docs/psptek/ PSPTEK] (done)
* [https://gigawiz.github.io/yapspd/html_chapters_split/chap8.html yapspd]
* [https://gigawiz.github.io/yapspd/html_chapters_split/chap8.html yapspd] (done)
* [https://github.com/uofw/uofw uOFW]
* [https://github.com/uofw/uofw uOFW] (todo: some more info to grab in some modules)
* [https://github.com/jpcsp/jpcsp Jpcsp]
* [https://github.com/jpcsp/jpcsp Jpcsp] (todo: contains a lot of stuff)
Please note that all contributions to PSP Developer wiki are considered to be released under the GNU Free Documentation License 1.2 (see PSP Developer wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following hCaptcha:

Cancel Editing help (opens in new window)