|
@@ -0,0 +1,65 @@
|
|
|
+#!/usr/bin/python3
|
|
|
+
|
|
|
+# a program to correct the GPIO settings to match the values in the i96 bus spec
|
|
|
+#
|
|
|
+# Pat Beirne <patb@pbeirne.com> 2021
|
|
|
+#
|
|
|
+# this script applies only to the OrangePi-i96, booting from u-boot 2012.04.442
|
|
|
+
|
|
|
+from mmap import mmap
|
|
|
+import os, sys, time, struct
|
|
|
+
|
|
|
+# assert the i96 GPIO pins into GPIO mode
|
|
|
+PORTC_GPIO_MASK = 0 # no pins need changing
|
|
|
+PORTA_GPIO_MASK = 0x7e508000 # rda gpioA 15,20,22,25-30 (i96 gpio group)
|
|
|
+PORTB_GPIO_MASK = 0 # no pins need changing
|
|
|
+PORTD_GPIO_MASK = 0xc # rda gpioD 2,3 (i96 gpioi group)
|
|
|
+PORTB_GPIO_MASK_NO_CTSRTS = 0x300 # assert B 8,9 to reuse uart2_cts,rts
|
|
|
+
|
|
|
+# clear the i96 GPIO pins to special function mode
|
|
|
+PORTC_SF_MASK = 0xfffffe3f # clear bits C c6,7,8 (i96 uarts)
|
|
|
+PORTA_SF_MASK = 0xffff91a0 # clear bits A 0-4,6,9-11,13,14 (i96 i2c, spi, i2s)
|
|
|
+PORTB_SF_MASK = 0xfffffc3f # clear bits B 6-9 (i96 i2c, uart)
|
|
|
+PORTD_SF_MASK = 0xFFFFFFFF # nothing to change
|
|
|
+
|
|
|
+PORTC_IOMUX = 0x11a09008
|
|
|
+PORTA_IOMUX = 0x11a0900c
|
|
|
+PORTB_IOMUX = 0x11a09010
|
|
|
+PORTD_IOMUX = 0x11a09014
|
|
|
+
|
|
|
+PAGE_MASK = ~0xFFF
|
|
|
+PAGE_OFFSET = 0xFFF
|
|
|
+
|
|
|
+# we must read and write 4 bytes at a time, little-endian
|
|
|
+def get_word(mapfile, address):
|
|
|
+ address &= PAGE_OFFSET
|
|
|
+ return struct.unpack("<L", mapfile[address:address+4])[0]
|
|
|
+
|
|
|
+def put_word(mapfile, address, data):
|
|
|
+ address &= PAGE_OFFSET
|
|
|
+ mapfile[address:address+4] = struct.pack("<L",data)
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ print("OrangePi-i96 fixup GPIO pins")
|
|
|
+ print("Version 1.0")
|
|
|
+
|
|
|
+ try:
|
|
|
+ with open("/dev/mem","r+b") as m:
|
|
|
+ mem = mmap(m.fileno(), 32, offset = PORTC_IOMUX & PAGE_MASK)
|
|
|
+ # set the GPIO pins up (to 1)
|
|
|
+ put_word(mem, PORTC_IOMUX, get_word(mem, PORTC_IOMUX) | PORTC_GPIO_MASK)
|
|
|
+ put_word(mem, PORTA_IOMUX, get_word(mem, PORTA_IOMUX) | PORTA_GPIO_MASK)
|
|
|
+ put_word(mem, PORTB_IOMUX, get_word(mem, PORTB_IOMUX) | PORTB_GPIO_MASK)
|
|
|
+ put_word(mem, PORTD_IOMUX, get_word(mem, PORTD_IOMUX) | PORTD_GPIO_MASK)
|
|
|
+
|
|
|
+ # and set the special function bit down (to 0)
|
|
|
+ put_word(mem, PORTC_IOMUX, get_word(mem, PORTC_IOMUX) & PORTC_SF_MASK)
|
|
|
+ put_word(mem, PORTA_IOMUX, get_word(mem, PORTA_IOMUX) & PORTA_SF_MASK)
|
|
|
+ put_word(mem, PORTB_IOMUX, get_word(mem, PORTB_IOMUX) & PORTB_SF_MASK)
|
|
|
+
|
|
|
+ print("GPIO pins corrected to agree with the i96 bus spec")
|
|
|
+
|
|
|
+ except PermissionError:
|
|
|
+ print("failed to open /dev/mem......you must execute this script as root")
|
|
|
+ exit(2)
|
|
|
+
|