Porting Openiboot

From iDroid Project

Revision as of 22:04, 6 December 2021 by Ricky26 (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This page should act as temporary place holder for any technical information found regarding porting Openiboot to newer devices.




There is not a specific WDT device in 3GS device tree. The reboot sequence instead accesses several registers in PMGR.

From 3.1.2 iBoot:

LDR     R1, =0xBF10021C
LDR     R3, =0xBF100214
MOVS    R0, #0
MOVS    R2, #1
STR     R0, [R1]
STR     R2, [R3]
LDR     R2, =0xBF100210
MOV.W   R3, #0x80000000
STR     R3, [R2]
MOVS    R3, #4
STR     R3, [R1]
STR     R0, [R2]

This also appears to be the same code for an iPod Touch 3G.


The MIU setup is found in the miu_init() in the LLB image instead. The register that contains MIU setting is 0xBF100000 (PMGR base address). The bit mask is now 3 instead of 7 for most other devices before this. Assume setting for map to 0x0 is 1, otherwise 2.

From 3.1.2 iLLB:

ROM:84006F44                 CBZ     R0, loc_84006F4C
ROM:84006F46                 CMP     R0, #1
ROM:84006F48                 BNE     loc_84006F68
ROM:84006F4A                 B       loc_84006F5A
ROM:84006F4C loc_84006F4C                            
ROM:84006F4C                 LDR     R2, =0xBF100000
ROM:84006F4E                 LDR     R3, [R2]
ROM:84006F50                 BIC.W   R3, R3, #3
ROM:84006F54                 ORR.W   R3, R3, #1
ROM:84006F58                 B       loc_84006F66
ROM:84006F5A loc_84006F5A                            
ROM:84006F5A                 LDR     R2, =0xBF100000
ROM:84006F5C                 LDR     R3, [R2]
ROM:84006F5E                 BIC.W   R3, R3, #3
ROM:84006F62                 ORR.W   R3, R3, #2
ROM:84006F66 loc_84006F66                            
ROM:84006F66                 STR     R3, [R2]
ROM:84006F68 loc_84006F68                            
ROM:84006F68                 LDR     R3, =0xBF100000
ROM:84006F6A                 LDR     R3, [R3]
ROM:84006F6C                 BX      LR

Vectored Interrupt Controller (VIC)

3GS is using the same PL192 VIC hardware as iPhone 2G therefore the register offsets and definitions remained the same. However the base address for 3GS has now become 0xBF200000. Also, there are now 3 "VIC cells" where each cell can fit up to 0x20 interrupts. The base address of the cells are separated by 0x10000.For example, VIC cell #0, #1 and #2 has base address at 0xBF200000, 0xBF210000 and 0xBF220000 respectively. VIC cell #0 defines interrupt from 0x0-0x1F, cell #1 from 0x20-3F and finally cell #2 from 0x40 - 5F making the maximum number of interrupts 0x60 (iphone 2g has 0x40). Below is the assembly in which this conclusion is based upon.

From 3.1.2 iBoot:

ROM:4FF102CC hw_vic_init                             
ROM:4FF102CC oldR7           = -8
ROM:4FF102CC oldLR           = -4
ROM:4FF102CC                 PUSH    {R7,LR}
ROM:4FF102CE                 ADD     R7, SP, #0
ROM:4FF102D0                 LDR.W   R12, =0xBF200014
ROM:4FF102D4                 MOVS    R0, #0
ROM:4FF102D6 loc_4FF102D6                            
ROM:4FF102D6                 ADD.W   R1, R12, #0xF0
ROM:4FF102DA                 MOVS    R2, #1
ROM:4FF102DC                 MOV.W   R3, #0xFFFFFFFF
ROM:4FF102E0                 STR.W   R3, [R12]
ROM:4FF102E4                 ADDS    R3, #1
ROM:4FF102E6                 STR.W   R3, [R12,#-8]
ROM:4FF102EA                 MOVW    R3, #0xFFFF
ROM:4FF102EE                 STR.W   R3, [R12,#0x10]
ROM:4FF102F2                 STR.W   R0, [R12,#0xEC]
ROM:4FF102F6 loc_4FF102F6                            
ROM:4FF102F6                 ADD.W   R3, R2, R0
ROM:4FF102FA                 ADDS    R2, #1
ROM:4FF102FC                 CMP     R2, #0x20
ROM:4FF102FE                 STR.W   R3, [R1],#4
ROM:4FF10302                 BNE     loc_4FF102F6
ROM:4FF10304                 LDR     R3, =0xBF230014
ROM:4FF10306                 ADD.W   R12, R12, #0x10000
ROM:4FF1030A                 ADDS    R0, #0x20
ROM:4FF1030C                 CMP     R12, R3
ROM:4FF1030E                 BNE     loc_4FF102D6
ROM:4FF10310                 BL      os_exit_critical_section
ROM:4FF10314                 MOVS    R0, #0
ROM:4FF10316                 POP     {R7,PC}
ROM:4FF10316 ; End of function hw_vic_init


Identified 2 timer related registers.

0xBF100200 -> tickslow
0xBF100204 -> tickshigh

From 3.1.2 iBoot:

ROM:4FF04860 hw_get_timer                            
ROM:4FF04860                 LDR     R1, =0xBF100204
ROM:4FF04862                 LDR     R3, =0xBF100200
ROM:4FF04864                 LDR     R2, [R1]
ROM:4FF04866                 LDR.W   R12, [R3]
ROM:4FF0486A                 LDR     R3, [R1]
ROM:4FF0486C                 CMP     R3, R2
ROM:4FF0486E                 BNE     hw_get_timer
ROM:4FF04870                 MOV     R2, R3
ROM:4FF04872                 MOV.W   R3, #0
ROM:4FF04876                 MOVS    R0, #0
ROM:4FF04878                 MOV     R1, R2
ROM:4FF0487A                 MOV     R2, R12
ROM:4FF0487C                 MOV.W   R3, #0
ROM:4FF04880                 ORRS    R0, R2
ROM:4FF04882                 ORRS    R1, R3
ROM:4FF04884                 BX      LR
ROM:4FF04884 ; End of function hw_get_timer

Scheduler related timer registers (?):



Frequency Setting And Derivation

Reversing clock stuffs is a tedious process at least to me therefore I am not surprised if the findings are prone to mistakes.

The base frequency seems to be 24MHz. There are 2 blocks of clock registers that together are used to derive a set of frequencies, in this case, 25 of them. These registers are initialized in iLLB and later set to default or cleared.

The first block, I called it the reference frequency derivation registers. It consists of 3 registers


These registers contains information to derive its own reference frequency based on a formula. My best guess on the bit definition of these registers are as follow:

(a)bit0     - status (?)
(b)bit1-3   - second stage divisor factor
(h)bit5     - accepted bit (this is set when the hardware has accepted the contents of the register)
(c)bit8-15  - base frequency multiplier
(d)bit16    - unknown
(e)bit17    - ready (?)
(f)bit18-19 - unknown
(g)bit20-25 - first stage divisor

For example, iLLB initializes 0xBF100004 as 0x40609601

The formula for calculating the reference frequency is:

(c * 24MHz) / (g * (1 << b))

so for a value of 0x40609601, the derived reference frequency according to the above formula is 600MHz.

So according to iLLB:

*(0xBF100004) = 0x40609601 -> 600MHz 
*(0xBF100008) = 0x40605103 -> 162MHz 
*(0xBF10000C) = 0x40606403 -> 200MHz

An additional reference frequency with the same value as the base frequency (or input frequency) of 24MHz is also defined thus:

reference_frequency[] = {600000000, 162000000, 200000000, 24000000} 

The second block of clock register related to frequency derivation, I like to call it the device frequency configuration registers. It consists of 25 registers ranging from 0xBF100010 to 0xBF100070. Registers at 0xBF100038 and 0xBF10004C correspond to device frequency number 11 and 16 are being treated differently for reasons unknown to me. These registers are used to derive the device frequency from the main frequencies shown above in conjunction with a configuration table.

Assumed bit definitions (device frequency from 1 - 10, 12 - 15 and 17 - 25)

(a)bit0-7   - divisor
(b)bit8-9   - reference frequency selector
(c)bit10    - divisor factor (normally 1)
(d)bit16-23 - divisor

for device frequency 16, bit16-17 is the reference frequency selector instead.

The actual formula that is used to derive the device frequencies is quite hard to explain. I will just paste the result based on iLLB's calculation routine and also the assembly for you to reverse instead.

cfg_table[0]  = 0x00000004, freq_config_register[0]  = 0x00000404, device_freq[0]  = 150MHz
cfg_table[1]  = 0x00000202, freq_config_register[1]  = 0x00000602, device_freq[1]  = 100MHz
cfg_table[2]  = 0x00000202, freq_config_register[2]  = 0x00000602, device_freq[2]  = 100MHz
cfg_table[3]  = 0x00000102, freq_config_register[3]  = 0x00000502, device_freq[3]  =  81MHz
cfg_table[4]  = 0x00000202, freq_config_register[4]  = 0x00000602, device_freq[4]  = 100MHz
cfg_table[5]  = 0x00000202, freq_config_register[5]  = 0x00000602, device_freq[5]  = 100MHz
cfg_table[6]  = 0x00000103, freq_config_register[6]  = 0x00000503, device_freq[6]  =  54MHz
cfg_table[7]  = 0x00000201, freq_config_register[7]  = 0x00000601, device_freq[7]  = 200MHz
cfg_table[8]  = 0x00000001, freq_config_register[8]  = 0x00000401, device_freq[8]  = 150MHz
cfg_table[9]  = 0x00000202, freq_config_register[9]  = 0x00000602, device_freq[9]  = 100MHz
cfg_table[10] = 0x000A0330, freq_config_register[10] = 0x000A0F30, device_freq[10] =  50KHz
cfg_table[11] = 0x00000300, freq_config_register[11] = 0x00000B00, device_freq[11] =  Undefined
cfg_table[12] = 0x00000001, freq_config_register[12] = 0x00000401, device_freq[12] = 150MHz
cfg_table[13] = 0x00000300, freq_config_register[13] = 0x00000B00, device_freq[13] =  Undefined
cfg_table[14] = 0x00000104, freq_config_register[14] = 0x00000504, device_freq[14] =  40.5MHz
cfg_table[15] = 0x00000301, freq_config_register[15] = 0x000C0304, device_freq[15] = 600MHz
cfg_table[16] = 0x00000318, freq_config_register[16] = 0x00000718, device_freq[16] =  1MHz
cfg_table[17] = 0x00000318, freq_config_register[17] = 0x00000718, device_freq[17] =  1MHz
cfg_table[18] = 0x00000318, freq_config_register[18] = 0x00000718, device_freq[18] =  1MHz
cfg_table[19] = 0x00000301, freq_config_register[19] = 0x00000701, device_freq[19] =  24MHz
cfg_table[20] = 0x00000104, freq_config_register[20] = 0x00000504, device_freq[20] =  40.5MHz
cfg_table[21] = 0x00000300, freq_config_register[21] = 0x00000B00, device_freq[21] =  Undefined
cfg_table[22] = 0x0000010F, freq_config_register[22] = 0x0000050F, device_freq[22] =  10.8MHz
cfg_table[23] = 0x00000103, freq_config_register[23] = 0x00000503, device_freq[23] =  54MHz
cfg_table[24] = 0x00000101, freq_config_register[24] = 0x00000501, device_freq[24] = 162MHz
cfg_table[25] = NA        , freq_config_register[25] = NA        , device_freq[25] = 200MHz
cfg_table[26] = NA        , freq_config_register[26] = NA        , device_freq[26] =  24MHz
cfg_table[27] = NA        , freq_config_register[27] = NA        , device_freq[27] =  24MHz

Note: freq_config_register[0] correspond to register 0xBF100010, freq_config_register[1] correspond to register 0xBF100014 and so on.

To obtain the frequency from the registers (except register[10] and [15]), simply follow the following formula:

output_frequency = reference_frequency[b] / (c * a)

For example, register number 23 of value 0x50F will have b=1, c=1 and a=15 producing an output_frequency of 162/(1*15)MHz or 10.8MHz

From 3.1.2 iLLB:

ROM:840071E0 sub_840071E0                  
ROM:840071E0 oldR4           = -0x14
ROM:840071E0 oldR5           = -0x10
ROM:840071E0 oldR6           = -0xC
ROM:840071E0 oldR7           = -8
ROM:840071E0 oldLR           = -4
ROM:840071E0                 PUSH    {R4-R7,LR}
ROM:840071E2                 ADD     R7, SP, #0xC
ROM:840071E4                 PUSH.W  {R8,R10,R11}
ROM:840071E8                 BL      set_clock_config
ROM:840071EC                 MOVS    R0, #0
ROM:840071EE                 MOVS    R1, #6
ROM:840071F0                 MOV     R3, R0
ROM:840071F2                 MOVS    R2, #0x96
ROM:840071F4                 BL      set_main_frequency
ROM:840071F8                 LDR.W   R8, =unk_8400FD40
ROM:840071FC                 LDR     R3, =600000000
ROM:840071FE                 MOVS    R0, #1
ROM:84007200                 MOVS    R1, #6
ROM:84007202                 STR.W   R3, [R8]
ROM:84007206                 MOVS    R2, #0x51
ROM:84007208                 MOV     R3, R0
ROM:8400720A                 BL      set_main_frequency
ROM:8400720E                 LDR     R3, =162000000
ROM:84007210                 MOVS    R2, #0x64
ROM:84007212                 MOVS    R0, #2
ROM:84007214                 STR.W   R3, [R8,#4]
ROM:84007218                 MOVS    R1, #6
ROM:8400721A                 MOVS    R3, #1
ROM:8400721C                 BL      set_main_frequency
ROM:84007220                 LDR     R3, =200000000
ROM:84007222                 MOVS    R2, #2
ROM:84007224                 LDR     R6, =0xBF100010
ROM:84007226                 STR.W   R3, [R8,#8]
ROM:8400722A                 LDR     R3, =24000000
ROM:8400722C                 LDR.W   R11, =frequency_config_setup_table
ROM:84007230                 LDR.W   R10, =derived_device_frequency
ROM:84007234                 STR.W   R3, [R8,#0xC]
ROM:84007238                 LDR     R3, =unk_8400FDC0
ROM:8400723A                 MOVS    R5, #0
ROM:8400723C                 STR     R2, [R3]
ROM:8400723E                 LDR     R3, =unk_8400FDC4
ROM:84007240                 ADDS    R2, R2, R2
ROM:84007242                 STR     R2, [R3]
ROM:84007244 loc_84007244                           
ROM:84007244                 LDR     R2, =0x40EFFFF0
ROM:84007246                 ADD.W   R3, R6, R11
ROM:8400724A                 CMP     R5, #0xA
ROM:8400724C                 LDR     R3, [R3,R2]     ; frequency_config + offset
ROM:8400724E                 BNE     loc_84007278
ROM:84007250                 LSRS    R2, R3, #8
ROM:84007252                 AND.W   R4, R2, #3      
ROM:84007256                 LSRS    R2, R3, #0x10
ROM:84007258                 AND.W   R2, R2, #0xFF
ROM:8400725C                 AND.W   R1, R3, #0xFF
ROM:84007260                 MUL.W   R1, R1, R2   
ROM:84007264                 CBZ     R1, loc_8400726A
ROM:84007266                 ORR.W   R3, R3, #0x400  
ROM:8400726A loc_8400726A                            
ROM:8400726A                 LDR     R2, =0xBF100038
ROM:8400726C                 ORR.W   R3, R3, #0x800
ROM:84007270                 STR     R3, [R2]        
ROM:84007272                 LDR.W   R0, [R8,R4,LSL#2]
ROM:84007276                 B       loc_840072B8    
ROM:84007278 loc_84007278                            
ROM:84007278                 CMP     R5, #0xF
ROM:8400727A                 BNE     loc_8400729C
ROM:8400727C                 LDR     R0, =0xBF10004C
ROM:8400727E                 AND.W   R1, R3, #0xFF
ROM:84007282                 BIC.W   R2, R3, #0xFF
ROM:84007286                 ORR.W   R2, R2, #0xC0000
ROM:8400728A                 LSRS    R3, R3, #0x10
ROM:8400728C                 ORR.W   R2, R2, R1,LSL#2
ROM:84007290                 STR     R2, [R0]
ROM:84007292                 AND.W   R0, R3, #3
ROM:84007296                 LDR.W   R0, [R8,R0,LSL#2]
ROM:8400729A                 B       loc_840072BE
ROM:8400729C loc_8400729C                            
ROM:8400729C                 LSRS    R2, R3, #8
ROM:8400729E                 AND.W   R4, R2, #3
ROM:840072A2                 ANDS.W  R1, R3, #0xFF
ROM:840072A6                 IT NE
ROM:840072A8                 ORRNE.W R3, R3, #0x400
ROM:840072AC                 ORR.W   R3, R3, #0x800
ROM:840072B0                 STR     R3, [R6]
ROM:840072B2                 LDR.W   R0, [R8,R4,LSL#2]
ROM:840072B6                 CBZ     R5, loc_840072BE
ROM:840072B8 loc_840072B8                            
ROM:840072B8                 CBNZ    R4, loc_840072BE
ROM:840072BA                 LDR.W   R0, [R10]
ROM:840072BE loc_840072BE                            
ROM:840072BE                 CBZ     R1, loc_840072CC
ROM:840072C0                 BLX     udiv
ROM:840072C4                 LDR     R3, =0x40EFFFF0
ROM:840072C6                 ADD.W   R4, R6, R10
ROM:840072CA                 STR     R0, [R4,R3]     ; derived_device_frequency + offset
ROM:840072CC loc_840072CC                           
ROM:840072CC                 ADDS    R5, #1
ROM:840072CE                 ADDS    R6, #4
ROM:840072D0                 CMP     R5, #0x19
ROM:840072D2                 BNE     loc_84007244
ROM:840072D4                 LDR.W   R2, [R10,#0x3C]
ROM:840072D8                 LDR     R3, =0xAAAAAAAB
ROM:840072DA                 MOVS    R0, #0
ROM:840072DC                 UMULL.W R1, R3, R2, R3
ROM:840072E0                 LSRS    R3, R3, #1
ROM:840072E2                 STR.W   R3, [R10,#0x64]
ROM:840072E6                 LDR     R3, =24000000
ROM:840072E8                 STR.W   R3, [R10,#0x68]
ROM:840072EC                 STR.W   R3, [R10,#0x6C]
ROM:840072F0                 POP.W   {R8,R10,R11}
ROM:840072F4                 POP     {R4-R7,PC}
ROM:840072F4 ; End of function sub_840071E0

Clock Gates

I actually have some doubts regarding this, what I thought was clock-gate registers. The registers are from 0xBF100078 to 0xBF100144 based on the following assembly:

From 3.1.2 iBoot:

ROM:4FF18E3C set_clear_clock_gate                    
ROM:4FF18E3C                 LDR.W   R12, =0xBF100078
ROM:4FF18E40                 LSLS    R2, R0, #2
ROM:4FF18E42                 ADD.W   R3, R2, R12
ROM:4FF18E46                 LDR     R2, =0xBF100144
ROM:4FF18E48                 CMP     R3, R2
ROM:4FF18E4A                 BHI     locret_4FF18E60
ROM:4FF18E4C                 CBZ     R1, loc_4FF18E56
ROM:4FF18E4E                 LDR     R3, [R3]
ROM:4FF18E50                 ORR.W   R3, R3, #0b1111
ROM:4FF18E54                 B       loc_4FF18E5C

It would imply that the register range allows 51 clock-gates but I am actually seeing clock-gate value higher than 51 from the ioreg output. Someone needs to make sense out of this.


There are a maximum of 0x2E GPIO ports implied by the 3GS iBoot with a group of 8 pins forms a GPIO port.

GPIO base address = 0x83000000

There seems to be a dedicated GPIO control register for each pin.

For example, the iPhone menu button has a value of 0x1606 assigned to the GPIO pin and:

0x1606 >> 8 & 0xFF => GPIO_Port_Number
0x1606 & 0xFF => GPIO_Pin_Number

Therefore, the menu button's GPIO control register is 0x830002D8 since:

GPIO Register = 0x83000000 + (8* GPIO_Port_Number + GPIO_Pin_Number) * sizeof(Register)

So far, I have seen up to 11 lower bits of a control register being used to control a GPIO pin. There are 3 bitmasks being used to set different bits of these registers in the main GPIO control routine:

0x27E=> sets bit 1-6 and 9
0x27F=> sets bit 0-6 and 9
0x3FF=> sets bit 0-10

The available values are:

1) Bitmask 0x27E -> 0x210, 0x212, 0x230, 0x250, 0x270
2) Bitmask 0x27F -> 0x212, 0x213
3) Bitmask 0x3FF -> 0x01E, 0x09E, 0xD1E, 0x11E, 0x210, 0x212, 0x213, 0x230, 0x250, 0x290, 0x310, 0x330, 0x41E, 0x610, 0x632, 0x6B2

There are evidence that bitmask 0x27F is used to set the GPIO pin state and bitmask 0x3FF is used to reset the GPIO registers.

Here is the assembly for the GPIO control routine:

From iBoot 3.1.2:

ROM:4FF01C34 gpio_ctl
ROM:4FF01C34                 PUSH    {R7,LR}
ROM:4FF01C36                 ADD     R7, SP, #0
ROM:4FF01C38                 LSRS    R3, R0, #8
ROM:4FF01C3A                 AND.W   R3, R3, #0xFF
ROM:4FF01C3E                 CMP     R3, #0x2E
ROM:4FF01C40                 AND.W   R2, R0, #7
ROM:4FF01C44                 BNE     loc_4FF01C4E
ROM:4FF01C46                 MOV     R0, R2
ROM:4FF01C48                 BL      spi_setup
ROM:4FF01C4C                 B       locret_4FF01CBA ; default
ROM:4FF01C4E ; ---------------------------------------------------------------------------
ROM:4FF01C4E loc_4FF01C4E                            
ROM:4FF01C4E                 LSLS    R0, R3, #3
ROM:4FF01C50                 ADDS    R0, R0, R2
ROM:4FF01C52                 CMP     R1, #7          ; switch 8 cases
ROM:4FF01C54                 BHI     locret_4FF01CBA ; default
ROM:4FF01C56                 TBB.W   [PC,R1]         ; switch jump
ROM:4FF01C56 ; ---------------------------------------------------------------------------
ROM:4FF01C5A jpt_4FF01C56    DCB 0xB                 ; jump table for switch statement
ROM:4FF01C5B                 DCB 0x18
ROM:4FF01C5C                 DCB 0x10
ROM:4FF01C5D                 DCB 0x13
ROM:4FF01C5E                 DCB 0x1E
ROM:4FF01C5F                 DCB 0x1B
ROM:4FF01C60                 DCB 5
ROM:4FF01C61                 DCB 8
ROM:4FF01C62                 DCB 0x30 ; 0
ROM:4FF01C63                 DCB    0
ROM:4FF01C64 ; ---------------------------------------------------------------------------
ROM:4FF01C64 loc_4FF01C64                            
ROM:4FF01C64                 MOV.W   R1, #0x250      ; jumptable 4FF01C56 case 6
ROM:4FF01C68                 B       loc_4FF01C74
ROM:4FF01C6A ; ---------------------------------------------------------------------------
ROM:4FF01C6A loc_4FF01C6A                           
ROM:4FF01C6A                 MOV.W   R1, #0x270      ; jumptable 4FF01C56 case 7
ROM:4FF01C6E                 B       loc_4FF01C74
ROM:4FF01C70 ; ---------------------------------------------------------------------------
ROM:4FF01C70 loc_4FF01C70                            
ROM:4FF01C70                 MOV.W   R1, #0x210      ; jumptable 4FF01C56 case 0
ROM:4FF01C70                                         ; enable
ROM:4FF01C74 loc_4FF01C74                            
ROM:4FF01C74                 MOVW    R12, #0b1001111110 ; mask out bits 1-6,9
ROM:4FF01C78                 B       loc_4FF01CA0
ROM:4FF01C7A ; ---------------------------------------------------------------------------
ROM:4FF01C7A loc_4FF01C7A                          
ROM:4FF01C7A                 MOVW    R1, #0x212      ; jumptable 4FF01C56 case 2
ROM:4FF01C7E                 B       loc_4FF01C84    ; clear state?
ROM:4FF01C80 ; ---------------------------------------------------------------------------
ROM:4FF01C80 loc_4FF01C80                          
ROM:4FF01C80                 MOVW    R1, #0x213      ; jumptable 4FF01C56 case 3
ROM:4FF01C80                                         ; set state?
ROM:4FF01C84 loc_4FF01C84                           
ROM:4FF01C84                 MOVW    R12, #0x27F     ; mask out bits 0-6, 9
ROM:4FF01C88                 B       loc_4FF01CA0
ROM:4FF01C8A ; ---------------------------------------------------------------------------
ROM:4FF01C8A loc_4FF01C8A                           
ROM:4FF01C8A                 MOVW    R1, #0x212      ; jumptable 4FF01C56 case 1
ROM:4FF01C8E                 B       loc_4FF01C74
ROM:4FF01C90 ; ---------------------------------------------------------------------------
ROM:4FF01C90 loc_4FF01C90                            
ROM:4FF01C90                 MOV.W   R1, #0x230      ; jumptable 4FF01C56 case 5
ROM:4FF01C94                 B       loc_4FF01C74    ; sets bit4,5,9
ROM:4FF01C96 ; ---------------------------------------------------------------------------
ROM:4FF01C96                 LDR     R3, =word_4FF26F24 ; jumptable 4FF01C56 case 4
ROM:4FF01C98                 MOVW    R12, #0x3FF     
ROM:4FF01C9C                 LDRH.W  R1, [R3,R0,LSL#1]
ROM:4FF01CA0                 LSLS    R0, R0, #2
ROM:4FF01CA2                 ADD.W   R0, R0, #0x83000000
ROM:4FF01CA6                 MVN.W   R3, R12
ROM:4FF01CAA                 LDR     R2, [R0]
ROM:4FF01CAC                 AND.W   R2, R3, R2
ROM:4FF01CB0                 AND.W   R3, R12, R1
ROM:4FF01CB4                 ORR.W   R3, R2, R3
ROM:4FF01CB8                 STR     R3, [R0]
ROM:4FF01CBA locret_4FF01CBA                         
ROM:4FF01CBA                 POP     {R7,PC}         ; default
ROM:4FF01CBA ; End of function gpio_ctl

Bits 7 and 8 are set in a separate routine:

From 3.1.2 iBoot:

ROM:4FF01C00                 CMP     R1, #0
ROM:4FF01C02                 IT LT
ROM:4FF01C04                 MOVLT.W R1, #0x100      ; sets bit 8
ROM:4FF01C08                 BLT     loc_4FF01C0E
ROM:4FF01C0A                 IT NE
ROM:4FF01C0C                 MOVNE   R1, #0x80       ; sets bit 7
ROM:4FF01C0E loc_4FF01C0E                        
ROM:4FF01C0E                 LSRS    R3, R0, #5
ROM:4FF01C10                 AND.W   R3, R3, #0x7F8
ROM:4FF01C14                 AND.W   R0, R0, #7
ROM:4FF01C18                 ADD     R0, R3
ROM:4FF01C1A                 AND.W   R2, R1, #0b110000000 ; mask out bits 7, 8
ROM:4FF01C1E                 LSLS    R0, R0, #2
ROM:4FF01C20                 ADD.W   R0, R0, #0x83000000
ROM:4FF01C24                 LDR     R3, [R0]
ROM:4FF01C26                 BIC.W   R1, R3, #0b110000000
ROM:4FF01C2A                 ORR.W   R1, R2, R1
ROM:4FF01C2E                 STR     R1, [R0]
ROM:4FF01C30                 BX      LR

Next task is to try to identify what these control bits control. Typical GPIO control settings are Enable/Disable, Input/Output/Functional, Pull Up/Down, Interrupt Trigger (rising/falling edge), State Setting/Reading, Mode setting (Sleep/Stop/Wake).

Based on the things I am seeing so far, I can roughly make the following assumptions:

bit0    - GPIO pin state
bit1-3  - Direction/Function? (input/output/functional)
bit4    - Always set (enable?)
bit5-6  - Pull Up/Down? (Disable/Pull Down/Pull Up)
bit7-8  - Sleep Mode Pull Up/Down? (Disable/Pull Down/Pull Up)
bit9-10 - Sleep Mode Control? (input/outputs/previous state)

The above should be subjected to heavy scrutiny by someone who posses deadlier reversing kungfu than myself. Hopefully further reversing on how different GPIO pins are setup for different hardware could provide some more hints for this objective.

For example bit 0 is likely the peripheral state bit when the pin is configured as input based on this baseband detection routine.

From 3.1.2 iBoot:

ROM:4FF0EB74                 PUSH    {R4,R5,R7,LR}
ROM:4FF0EB76                 ADD     R7, SP, #8
ROM:4FF0EB78                 MOVW    R4, #0x803      ; radio hardware
ROM:4FF0EB7C                 MOV     R0, R4
ROM:4FF0EB7E                 MOVS    R1, #0
ROM:4FF0EB80                 BL      gpio_ctl
ROM:4FF0EB84                 MOVS    R1, #0
ROM:4FF0EB86                 MOVS    R0, #0x64
ROM:4FF0EB88                 BL      delay
ROM:4FF0EB8C                 MOV     R0, R4
ROM:4FF0EB8E                 BL      gpio_get
ROM:4FF0EB92                 MOVS    R1, #4
ROM:4FF0EB94                 MOV     R5, R0
ROM:4FF0EB96                 MOV     R0, R4
ROM:4FF0EB98                 BL      gpio_ctl
ROM:4FF0EB9C                 MOVS    R0, #0x64
ROM:4FF0EB9E                 MOVS    R1, #0
ROM:4FF0EBA0                 BL      delay
ROM:4FF0EBA4                 MOV     R0, R5
ROM:4FF0EBA6                 POP     {R4,R5,R7,PC}
ROM:4FF0EBA6 ; End of function probe_radio

gpio_get routine:

ROM:4FF01D0C                 PUSH    {R7,LR}
ROM:4FF01D0E                 ADD     R7, SP, #0
ROM:4FF01D10                 LSRS    R3, R0, #8
ROM:4FF01D12                 AND.W   R3, R3, #0xFF
ROM:4FF01D16                 CMP     R3, #0x2E
ROM:4FF01D18                 AND.W   R2, R0, #7
ROM:4FF01D1C                 BNE     loc_4FF01D26
ROM:4FF01D1E                 MOV     R0, R2
ROM:4FF01D20                 BL      sub_4FF11894
ROM:4FF01D24                 B       locret_4FF01D36
ROM:4FF01D26 ; ---------------------------------------------------------------------------
ROM:4FF01D26 loc_4FF01D26                           
ROM:4FF01D26                 LSLS    R0, R3, #3
ROM:4FF01D28                 ADDS    R0, R0, R2
ROM:4FF01D2A                 LSLS    R0, R0, #2
ROM:4FF01D2C                 ADD.W   R0, R0, #0x83000000
ROM:4FF01D30                 LDR     R0, [R0]
ROM:4FF01D32                 AND.W   R0, R0, #1
ROM:4FF01D36 locret_4FF01D36                         
ROM:4FF01D36                 POP     {R7,PC}

Also, possible values for bit 7 and 8 (as shown previously) is 00, 01, 10 so a pull up/down control should make sense.

Bit 5 and 6 as pull up/down control also is viable since register value of 0x270 is never used in any of the iBoots I have seen. This register value is corresponding to "case 7" in the gpio_ctl function in iBoot where both bit 5 and 6 are set.