mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-12-18 17:53:10 +00:00
119 lines
3 KiB
Python
119 lines
3 KiB
Python
|
from setup import *
|
||
|
import asm
|
||
|
import struct
|
||
|
|
||
|
base = 0x235010000
|
||
|
|
||
|
# register defines from https://github.com/torvalds/linux/blob/master/drivers/i2c/busses/i2c-pasemi.c
|
||
|
# Copyright (C) 2006-2007 PA Semi, Inc
|
||
|
# SMBus host driver for PA Semi PWRficient
|
||
|
REG_MTXFIFO = 0x00
|
||
|
REG_MRXFIFO = 0x04
|
||
|
REG_SMSTA = 0x14
|
||
|
REG_CTL = 0x1c
|
||
|
|
||
|
MTXFIFO_READ = 0x00000400
|
||
|
MTXFIFO_STOP = 0x00000200
|
||
|
MTXFIFO_START = 0x00000100
|
||
|
MTXFIFO_DATA_M = 0x000000ff
|
||
|
|
||
|
MRXFIFO_EMPTY = 0x00000100
|
||
|
MRXFIFO_DATA_M = 0x000000ff
|
||
|
|
||
|
SMSTA_XEN = 0x08000000
|
||
|
SMSTA_MTN = 0x00200000
|
||
|
|
||
|
CTL_MRR = 0x00000400
|
||
|
CTL_MTR = 0x00000200
|
||
|
CTL_CLK_M = 0x000000ff
|
||
|
|
||
|
CLK_100K_DIV = 84
|
||
|
CLK_400K_DIV = 21
|
||
|
|
||
|
|
||
|
def i2c_read_reg(addr, reg, reg_size):
|
||
|
p.set32(base + REG_CTL, CTL_MTR | CTL_MRR)
|
||
|
p.write32(base + REG_SMSTA, 0xffffffff)
|
||
|
|
||
|
p.write32(base + REG_MTXFIFO, MTXFIFO_START | (addr << 1))
|
||
|
p.write32(base + REG_MTXFIFO, MTXFIFO_STOP | reg)
|
||
|
|
||
|
while not (p.read32(base + REG_SMSTA) & SMSTA_XEN):
|
||
|
pass
|
||
|
|
||
|
p.write32(base + REG_MTXFIFO, MTXFIFO_START | (addr << 1) | 1)
|
||
|
p.write32(base + REG_MTXFIFO, MTXFIFO_READ | MTXFIFO_STOP | reg_size + 1)
|
||
|
|
||
|
res = []
|
||
|
while len(res) < reg_size+1:
|
||
|
v = p.read32(base + REG_MRXFIFO)
|
||
|
if v & 0x100:
|
||
|
continue
|
||
|
res.append(v)
|
||
|
|
||
|
if res[0] < reg_size:
|
||
|
print("only read %d instead of %d bytes" % (res[0], reg_size))
|
||
|
return res[1:]
|
||
|
|
||
|
|
||
|
def i2c_write_reg(addr, reg, data):
|
||
|
p.set32(base + REG_CTL, CTL_MTR | CTL_MRR)
|
||
|
p.write32(base + REG_SMSTA, 0xffffffff)
|
||
|
|
||
|
p.write32(base + REG_MTXFIFO, MTXFIFO_START | (addr << 1))
|
||
|
p.write32(base + REG_MTXFIFO, reg)
|
||
|
for i in range(len(data)-1):
|
||
|
p.write32(base + REG_MTXFIFO, data[i])
|
||
|
p.write32(base + REG_MTXFIFO, data[-1] | MTXFIFO_STOP)
|
||
|
|
||
|
while not (p.read32(base + REG_SMSTA) & SMSTA_XEN):
|
||
|
pass
|
||
|
|
||
|
|
||
|
def i2c_read16(addr, reg):
|
||
|
data = struct.pack(">2b", *i2c_read_reg(addr, reg, 2))
|
||
|
return struct.unpack(">H", data)[0]
|
||
|
|
||
|
|
||
|
def i2c_read32(addr, reg):
|
||
|
data = struct.pack(">4b", *i2c_read_reg(addr, reg, 4))
|
||
|
return struct.unpack(">I", data)[0]
|
||
|
|
||
|
|
||
|
def tps6598x_exec_cmd(addr, cmd, data_in, out_len):
|
||
|
if data_in:
|
||
|
data = [len(data_in)] + data_in
|
||
|
|
||
|
# TPS_REG_DATA1
|
||
|
i2c_write_reg(addr, 0x09, data)
|
||
|
|
||
|
# TPS_REG_CMD1
|
||
|
cmd = [4] + list(map(ord, cmd))
|
||
|
i2c_write_reg(addr, 0x08, cmd)
|
||
|
|
||
|
# TPS_REG_CMD1
|
||
|
v = i2c_read32(addr, 0x08)
|
||
|
while v != 0:
|
||
|
if v == 0x21434d44: # !CMD
|
||
|
raise Exception("Invalid command!")
|
||
|
v = i2c_read32(addr, 0x08)
|
||
|
|
||
|
if not out_len:
|
||
|
return
|
||
|
|
||
|
# TPS_REG_DATA1
|
||
|
return i2c_read_reg(addr, 0x09, out_len)
|
||
|
|
||
|
|
||
|
print("make sure to run pmgr_adt_clocks_enable for /arm-io/i2c0 before this script.")
|
||
|
|
||
|
# apple-specific command to bring the power state to zero
|
||
|
# (or any other value specified as an argument)
|
||
|
tps6598x_exec_cmd(0x3f, "SSPS", [0], 0)
|
||
|
tps6598x_exec_cmd(0x38, "SSPS", [0], 0)
|
||
|
|
||
|
tps6598x_exec_cmd(0x3f, "SWDF", None, 0)
|
||
|
tps6598x_exec_cmd(0x3f, "SWSr", None, 0)
|
||
|
tps6598x_exec_cmd(0x38, "SWDF", None, 0)
|
||
|
tps6598x_exec_cmd(0x38, "SWSr", None, 0)
|