mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-10 09:44:13 +00:00
Add smc.py script to enable radios
Add a basic SMC client and a script in experiments/ using it to enable the radios. Running this before booting Linux will make the network controller devices show up in lspci, even if Linux lacks an SMC driver. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
parent
925215aea2
commit
8010e38376
2 changed files with 120 additions and 0 deletions
31
proxyclient/experiments/smc.py
Normal file
31
proxyclient/experiments/smc.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: MIT
|
||||
import sys, pathlib
|
||||
import time
|
||||
sys.path.append(str(pathlib.Path(__file__).resolve().parents[1]))
|
||||
|
||||
import struct
|
||||
from m1n1.setup import *
|
||||
from m1n1.fw.smc import SMCClient
|
||||
|
||||
smc_addr = u.adt["arm-io/smc"].get_reg(0)[0]
|
||||
smc = SMCClient(u, smc_addr)
|
||||
smc.start()
|
||||
smc.start_ep(0x20)
|
||||
|
||||
smcep = smc.epmap[0x20]
|
||||
|
||||
def fourcc_key(fourcc):
|
||||
assert(len(fourcc) == 4)
|
||||
return sum([ord(x) << (8 * (3 - i)) for i, x in enumerate(fourcc)])
|
||||
|
||||
def gpio_key(pin):
|
||||
assert(pin < (1 << 16))
|
||||
|
||||
fourcc = 'gP' + ('00'+(hex(pin)[2:]))[-2:]
|
||||
return fourcc_key(fourcc)
|
||||
|
||||
# Enable wifi/bluetooth
|
||||
RFKILL_PIN = 13
|
||||
smcep.write_key(gpio_key(RFKILL_PIN), struct.pack('<I', 0x800000 | 0x0))
|
||||
smcep.write_key(gpio_key(RFKILL_PIN), struct.pack('<I', 0x800000 | 0x1))
|
89
proxyclient/m1n1/fw/smc.py
Normal file
89
proxyclient/m1n1/fw/smc.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
import struct
|
||||
|
||||
from ..utils import *
|
||||
|
||||
from .asc import StandardASC
|
||||
from .asc.base import *
|
||||
|
||||
SMC_READ_KEY = 0x10
|
||||
SMC_WRITE_KEY = 0x11
|
||||
SMC_GET_KEY_BY_INDEX = 0x12
|
||||
SMC_GET_KEY_INFO = 0x13
|
||||
SMC_GET_SRAM_ADDR = 0x17
|
||||
SMC_NOTIFICATION = 0x18
|
||||
SMC_READ_KEY_PAYLOAD = 0x20
|
||||
|
||||
class SMCGetSRAMAddr(Register64):
|
||||
TYPE = 8, 0, Constant(0x17)
|
||||
ID = 16, 12
|
||||
|
||||
class SMCWriteKey(Register64):
|
||||
TYPE = 8, 0, Constant(0x11)
|
||||
ID = 16, 12
|
||||
SIZE = 32, 16
|
||||
KEY = 64, 32
|
||||
|
||||
class SMCMessage(Register64):
|
||||
TYPE = 0, 0
|
||||
VALUE = 64, 0
|
||||
|
||||
class SMCMessage(Register64):
|
||||
TYPE = 8, 0
|
||||
ID = 16, 12
|
||||
HPARAM = 32, 16
|
||||
WPARAM = 64, 32
|
||||
|
||||
class SMCEndpoint(ASCBaseEndpoint):
|
||||
BASE_MESSAGE = SMCMessage
|
||||
SHORT = "smcep"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.shmem = None
|
||||
self.msgid = 0
|
||||
self.outstanding = set()
|
||||
|
||||
def start(self):
|
||||
self.send(SMCGetSRAMAddr(ID = self.new_msgid()))
|
||||
while self.shmem is None:
|
||||
self.asc.work()
|
||||
|
||||
def new_msgid(self):
|
||||
mid = (self.msgid & 0xF)
|
||||
self.msgid += 1
|
||||
assert(mid not in self.outstanding)
|
||||
self.outstanding.add(mid)
|
||||
return mid
|
||||
|
||||
|
||||
def write_key(self, key, data):
|
||||
print(self.shmem, key, data, len(data))
|
||||
self.asc.iface.writemem(self.shmem, data)
|
||||
ID = self.new_msgid()
|
||||
self.send(SMCWriteKey(ID = ID, KEY = key, SIZE = len(data)))
|
||||
while ID in self.outstanding:
|
||||
self.asc.work()
|
||||
return True
|
||||
|
||||
@msg_handler(0x00, SMCMessage)
|
||||
def Startup(self, msg):
|
||||
self.log(hex(msg.value))
|
||||
|
||||
if self.shmem is None:
|
||||
self.log("Starting up")
|
||||
self.shmem = msg.value
|
||||
else:
|
||||
ret = msg.value & 0xFF
|
||||
mid = (msg.value >> 12) & 0xF
|
||||
print(f"msg {mid} return value {ret}")
|
||||
self.outstanding.discard(mid)
|
||||
|
||||
return True
|
||||
|
||||
class SMCClient(StandardASC):
|
||||
pass
|
||||
|
||||
ENDPOINTS = {
|
||||
0x20: SMCEndpoint,
|
||||
}
|
Loading…
Reference in a new issue