之前玩T113S3 都是3个dcdc 供电,那个电路不够简洁,所以换AXP313A
但是换之前被一个大问题困扰,这个PMIC没有配置,能直接把T113带起来嘛
所以我整了个测试板,T113 还是dcdc 供电,然后把信号线接过去测试
现在结果来了
1 在什么都没有配置的情况下 T113 默认输出 两路 ldo 一个是1.8v 一个是3.3
然后三路dcdc 都是0.9v
那么boot0 应该就没问题了
有3.3 有 0.9 有1.8 其实 都不需要配置pmic就可以直接带起来,只是没有Dram的1.5 然后系统里面那个ldo的3.3v带别的设备不行
所以现在的目标就是把dcdc1 拉到 3.3v 把 dcdc3 拉到1.5v 这样整个板子的供电就基本上都够了 dcdc1 给其他3.3v模块用 1.5v可以直接把dram 带起来
然后调试的思路就是 先让系统配置起来,其实这个简单,只需要把你连接的pin配置好即可 在dts里面配置
比如我这里
TWI1 PB4 PB5 axp1530=AXP313,这两在系统驱动里面是当一样的东西处理 ,所以这里直接这么写就可以了
&twi1 {
clock-frequency = <100000>;
pinctrl-0 = <&twi1_pins_a>;
pinctrl-1 = <&twi1_pins_b>;
pinctrl-names = "default", "sleep";
status = "okay";
axp1530: pmic@36 {
compatible = "x-powers,axp1530";
reg = <0x36>;
status = "okay";
wakeup-source;
regulators {
reg_dcdc1: dcdc1 {
regulator-name = "axp1530-dcdc1";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3300000>;
regulator-step-delay-us = <25>;
regulator-final-delay-us = <50>;
regulator-boot-on;
regulator-always-on;
};
reg_dcdc2: dcdc2 {
regulator-name = "axp1530-dcdc2";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1540000>;
regulator-step-delay-us = <25>;
regulator-final-delay-us = <50>;
regulator-ramp-delay = <200>;
regulator-boot-on;
regulator-always-on;
};
reg_dcdc3: dcdc3 {
regulator-name = "axp1530-dcdc3";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1840000>;
regulator-step-delay-us = <25>;
regulator-final-delay-us = <50>;
regulator-boot-on;
regulator-always-on;
};
reg_aldo1: ldo1 {
regulator-name = "axp1530-aldo1";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3500000>;
regulator-step-delay-us = <25>;
regulator-final-delay-us = <50>;
regulator-boot-on;
regulator-always-on;
};
reg_dldo1: ldo2 {
regulator-name = "axp1530-dldo1";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3500000>;
regulator-step-delay-us = <25>;
regulator-final-delay-us = <50>;
regulator-boot-on;
regulator-always-on;
};
};
};
};
然后系统基本上就很简单能连接并读取芯片数据了
唯一的坑是,我自己抄大佬的原理图没有注意H616那个IO是1.8v的但是我这里T113是3.3v 那个SDA SDL线需要上拉才能工作,拉错电压就会导致数据错误,连接失败。
弄好了以后系统里面就可以这样直接 操作 pmic了,可以直接往twi上发指令
root@TinaLinux:~# dmesg | grep -iE "axp|dcdc|ldo|regulator|LEO"
[ 0.000000] Linux version 5.4.61 (root@leomini) (arm-openwrt-linux-muslgnueabi-gcc.bin (OpenWrt/Linaro GCC 6.4-2017.11 2017-11) 6.4.1, GNU ld (GNU Binutils) 2.27) #441 SMP PREEMPT Sun Jun 7 16:05:55 UTC 2026
[ 0.019621] calling regulator_init+0x0/0xa8 @ 1
[ 0.019956] regulator-dummy: no parameters
[ 0.020273] initcall regulator_init+0x0/0xa8 returned 0 after 9765 usecs
[ 0.103615] calling regulator_fixed_voltage_init+0x0/0x10 @ 1
[ 0.105134] initcall regulator_fixed_voltage_init+0x0/0x10 returned 0 after 0 usecs
[ 0.105145] calling axp2101_regulator_init+0x0/0x10 @ 1
[ 0.105358] initcall axp2101_regulator_init+0x0/0x10 returned 0 after 0 usecs
[ 0.106347] calling axp2101_i2c_init+0x0/0x34 @ 1
[ 0.106404] initcall axp2101_i2c_init+0x0/0x34 returned 0 after 0 usecs
[ 0.128501] sun8iw20-pinctrl 2000000.pinctrl: 2000000.pinctrl supply vcc-pc not found, using dummy regulator
[ 0.128995] spi spi0: spi0 supply spi not found, using dummy regulator
[ 0.192955] sun8iw20-pinctrl 2000000.pinctrl: 2000000.pinctrl supply vcc-pd not found, using dummy regulator
[ 0.196032] sun8iw20-pinctrl 2000000.pinctrl: 2000000.pinctrl supply vcc-pe not found, using dummy regulator
[ 0.196350] uart uart0: get regulator failed
[ 0.196382] uart uart0: uart0 supply uart not found, using dummy regulator
[ 0.197450] sun8iw20-pinctrl 2000000.pinctrl: 2000000.pinctrl supply vcc-pg not found, using dummy regulator
[ 0.197768] uart uart1: get regulator failed
[ 0.197799] uart uart1: uart1 supply uart not found, using dummy regulator
[ 0.738850] sunxi-ehci 4200000.ehci1-controller: 4200000.ehci1-controller supply drvvbus not found, using dummy regulator
[ 0.739116] sunxi-ehci 4200000.ehci1-controller: 4200000.ehci1-controller supply hci not found, using dummy regulator
[ 0.776756] sunxi-ohci 4200400.ohci1-controller: 4200400.ohci1-controller supply drvvbus not found, using dummy regulator
[ 0.776989] sunxi-ohci 4200400.ohci1-controller: 4200400.ohci1-controller supply hci not found, using dummy regulator
[ 0.859395] sunxi-mmc 4020000.sdmmc: No vmmc regulator found
[ 0.859400] sunxi-mmc 4020000.sdmmc: No vqmmc regulator found
[ 0.859406] sunxi-mmc 4020000.sdmmc: No vdmmc regulator found
[ 0.859411] sunxi-mmc 4020000.sdmmc: No vd33sw regulator found
[ 0.859417] sunxi-mmc 4020000.sdmmc: No vd18sw regulator found
[ 0.859422] sunxi-mmc 4020000.sdmmc: No vq33sw regulator found
[ 0.859428] sunxi-mmc 4020000.sdmmc: No vq18sw regulator found
[ 0.860313] sunxi-mmc 4020000.sdmmc: no vqmmc,Check if there is regulator
[ 0.885065] sunxi-mmc 4021000.sdmmc: No vmmc regulator found
[ 0.885071] sunxi-mmc 4021000.sdmmc: No vqmmc regulator found
[ 0.885076] sunxi-mmc 4021000.sdmmc: No vdmmc regulator found
[ 0.885082] sunxi-mmc 4021000.sdmmc: No vd33sw regulator found
[ 0.885088] sunxi-mmc 4021000.sdmmc: No vd18sw regulator found
[ 0.885093] sunxi-mmc 4021000.sdmmc: No vq33sw regulator found
[ 0.885099] sunxi-mmc 4021000.sdmmc: No vq18sw regulator found
[ 0.885869] sunxi-mmc 4021000.sdmmc: no vqmmc,Check if there is regulator
[ 0.912412] sunxi_get_str_of_property()1693 - failed to get the string of propname led_regulator!
[ 0.985190] sun8iw20-pinctrl 2000000.pinctrl: 2000000.pinctrl supply vcc-pb not found, using dummy regulator
[ 0.985827] sunxi-i2c sunxi-i2c1: sunxi-i2c1 supply twi not found, using dummy regulator
[ 0.987040] axp20x-i2c 1-0036: AXP20x variant AXP1530 found
[ 0.987588] axp20x-i2c 1-0036: LEO smbus read 0x10 ret=31 val=0x1f
[ 0.988103] axp20x-i2c 1-0036: LEO smbus read 0x13 ret=40 val=0x28
[ 0.988607] axp20x-i2c 1-0036: LEO smbus read 0x14 ret=40 val=0x28
[ 0.989112] axp20x-i2c 1-0036: LEO smbus read 0x15 ret=40 val=0x28
[ 0.989618] axp20x-i2c 1-0036: LEO smbus read 0x16 ret=13 val=0x0d
[ 0.990123] axp20x-i2c 1-0036: LEO smbus read 0x17 ret=28 val=0x1c
[ 0.991238] axp2101-regulator axp2101-regulator.0: LEO AXP1530 PATCH 20260607 LOADED
[ 0.991252] axp2101-regulator axp2101-regulator.0: LEO AXP1530 skip dcdc freq
[ 0.991790] axp2101-regulator axp2101-regulator.0: LEO AXP313A read 0x10 ret=0 val=0x1f
[ 0.992300] axp2101-regulator axp2101-regulator.0: LEO AXP313A read 0x13 ret=0 val=0x28
[ 0.992808] axp2101-regulator axp2101-regulator.0: LEO AXP313A read 0x14 ret=0 val=0x28
[ 0.993313] axp2101-regulator axp2101-regulator.0: LEO AXP313A read 0x15 ret=0 val=0x28
[ 0.993817] axp2101-regulator axp2101-regulator.0: LEO AXP313A read 0x16 ret=0 val=0x0d
[ 0.994361] axp2101-regulator axp2101-regulator.0: LEO AXP313A read 0x17 ret=0 val=0x1c
[ 0.994420] axp20x-i2c 1-0036: Looking up vin1-supply from device tree
[ 0.994443] axp20x-i2c 1-0036: Looking up vin1-supply property in node /soc@3000000/twi@2502400/pmic@36 failed
[ 0.994458] dcdc1: supplied by regulator-dummy
[ 0.994470] regulator-dummy: could not add device link regulator.4 err -2
[ 0.996085] axp1530-dcdc1: 500 <--> 3400 mV at 900 mV
[ 0.996878] axp20x-i2c 1-0036: Looking up vin2-supply from device tree
[ 0.996899] axp20x-i2c 1-0036: Looking up vin2-supply property in node /soc@3000000/twi@2502400/pmic@36 failed
[ 0.996909] dcdc2: supplied by regulator-dummy
[ 0.996920] regulator-dummy: could not add device link regulator.5 err -2
[ 0.998503] axp1530-dcdc2: 500 <--> 1540 mV at 900 mV
[ 0.999256] axp20x-i2c 1-0036: Looking up vin3-supply from device tree
[ 0.999276] axp20x-i2c 1-0036: Looking up vin3-supply property in node /soc@3000000/twi@2502400/pmic@36 failed
[ 0.999286] dcdc3: supplied by regulator-dummy
[ 0.999296] regulator-dummy: could not add device link regulator.6 err -2
[ 0.999883] axp1530-dcdc3: override max_uV, 1840000 -> 1540000
[ 1.000905] axp1530-dcdc3: 500 <--> 1540 mV at 900 mV
[ 1.001671] axp20x-i2c 1-0036: Looking up ldo1in-supply from device tree
[ 1.001691] axp20x-i2c 1-0036: Looking up ldo1in-supply property in node /soc@3000000/twi@2502400/pmic@36 failed
[ 1.001702] ldo1: supplied by regulator-dummy
[ 1.001713] regulator-dummy: could not add device link regulator.7 err -2
[ 1.003291] axp1530-aldo1: 500 <--> 3500 mV at 1800 mV
[ 1.004160] axp20x-i2c 1-0036: Looking up ldo2in-supply from device tree
[ 1.004179] axp20x-i2c 1-0036: Looking up ldo2in-supply property in node /soc@3000000/twi@2502400/pmic@36 failed
[ 1.004190] ldo2: supplied by regulator-dummy
[ 1.004200] regulator-dummy: could not add device link regulator.8 err -2
[ 1.005864] axp1530-dldo1: 500 <--> 3500 mV at 3300 mV
[ 1.006666] probe of axp2101-regulator.0 returned 1 after 15487 usecs
[ 1.007493] axp20x-i2c 1-0036: AXP20X driver loaded
[ 1.547358] calling regulatory_init_db+0x0/0x90 @ 1
[ 1.547514] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
[ 1.547524] cfg80211: failed to load regulatory.db
[ 1.547606] initcall regulatory_init_db+0x0/0x90 returned 0 after 15 usecs
[ 1.547640] calling regulator_init_complete+0x0/0x4c @ 1
[ 1.547653] initcall regulator_init_complete+0x0/0x4c returned 0 after 2 usecs
[ 5.186353] sunxi_usb_udc 4100000.udc-controller: 4100000.udc-controller supply udc not found, using dummy regulator
root@TinaLinux:~#
root@TinaLinux:~# for r in /sys/class/regulator/regulator.*; do
> echo "== $r =="
> cat $r/name 2>/dev/null
> cat $r/microvolts 2>/dev/null
> cat $r/state 2>/dev/null
> done
== /sys/class/regulator/regulator.0 ==
regulator-dummy
== /sys/class/regulator/regulator.1 ==
pio-18
1800000
== /sys/class/regulator/regulator.2 ==
pio-33
3300000
== /sys/class/regulator/regulator.3 ==
usb1-vbus
5000000
== /sys/class/regulator/regulator.4 ==
axp1530-dcdc1
900000
enabled
== /sys/class/regulator/regulator.5 ==
axp1530-dcdc2
900000
enabled
== /sys/class/regulator/regulator.6 ==
axp1530-dcdc3
900000
enabled
== /sys/class/regulator/regulator.7 ==
axp1530-aldo1
1800000
enabled
== /sys/class/regulator/regulator.8 ==
axp1530-dldo1
3300000
enabled
root@TinaLinux:~# i2cset -f -y 1 0x36 0x13 0x69
root@TinaLinux:~# for r in /sys/class/regulator/regulator.*; do
> echo "== $r =="
> cat $r/name 2>/dev/null
> cat $r/microvolts 2>/dev/null
> cat $r/state 2>/dev/null
> done
== /sys/class/regulator/regulator.0 ==
regulator-dummy
== /sys/class/regulator/regulator.1 ==
pio-18
1800000
== /sys/class/regulator/regulator.2 ==
pio-33
3300000
== /sys/class/regulator/regulator.3 ==
usb1-vbus
5000000
== /sys/class/regulator/regulator.4 ==
axp1530-dcdc1
3300000
enabled
== /sys/class/regulator/regulator.5 ==
axp1530-dcdc2
900000
enabled
== /sys/class/regulator/regulator.6 ==
axp1530-dcdc3
900000
enabled
== /sys/class/regulator/regulator.7 ==
axp1530-aldo1
1800000
enabled
== /sys/class/regulator/regulator.8 ==
axp1530-dldo1
3300000
enabled
root@TinaLinux:~# Read from remote host 192.168.199.179: Connection reset by peer
Connection to 192.168.199.179 closed.
client_loop: send disconnect: Broken pipe
然后再调试boot0,这个调试过程中我发现系统原先默认的PMU接口是PL0 PL1,但是实际上我这个T113S3并没有引出这两脚,所以只能强行更改
但是 改完了以后 也不知道这个系统怎么操作pmu的似乎死活就是连接不上
,所以我直接不改了既然有完整的BOOT0代码,那么直接在boot0里面加自己程序就是最简单的,所以我就直接把自己程序加在里面了
lichee/brandy-2.0/spl/nboot/main/boot0_main.c
/*
* (C) Copyright 2018
* SPDX-License-Identifier: GPL-2.0+
* wangwei <wangwei@allwinnertech.com>
*/
/*
* 当前测试用:
* PB4 / PB5 / TWI1
*
* normal_gpio_cfg 字段大概是:
* { port, port_num, mul_sel, pull, drv_level, data, reserved[0] }
*
* port = 2 -> PB
* port_num = 4 -> PB4
* port_num = 5 -> PB5
* mul_sel = 2 -> TWI0 复用,先按这个测
* pull = 1 -> 上拉
* reserved[0]=0 -> TWI0 bus
*/
#include <common.h>
#include <private_boot0.h>
#include <private_uboot.h>
#include <private_toc.h>
#include <arch/clock.h>
#include <arch/uart.h>
#include <arch/dram.h>
#include <arch/rtc.h>
#include <arch/gpio.h>
#include <arch/pmic_bus.h>
#include <arch/axp1530_reg.h>
#define AXP313A_ADDR 0x36
#define AXP313A_OUTPUT_CONTROL 0x10
#define AXP313A_DCDC1_CONTROL 0x13
#define AXP313A_DCDC2_CONTROL 0x14
#define AXP313A_DCDC3_CONTROL 0x15
#define AXP313A_DCDC1_3V3 0x69
#define AXP313A_DCDC3_1V5 0x55
#define AXP313A_DCDC1_EN (1 << 0)
#define AXP313A_DCDC2_EN (1 << 1)
#define AXP313A_DCDC3_EN (1 << 2)
#define LEO_AXP_ADDR 0x36
#define LEO_AXP_REG_VERSION 0x03
#define LEO_AXP_REG_OUTPUT 0x10
#define LEO_AXP_REG_DCDC1 0x13
#define LEO_AXP_REG_DCDC3 0x15
#define LEO_DCDC1_3V3 0x69
#define LEO_DCDC3_1V5 0x55
#define LEO_DCDC1_EN (1 << 0)
#define LEO_DCDC3_EN (1 << 2)
#define LEO_TWI1_BASE_REAL 0x02502400U
static normal_gpio_cfg leo_lcd_5v_en_gpio[1] = {
{5, 10, 1, 0, 2, 1, {0}}, /* PE10 output high */
};
static void leo_enable_lcd_5v_pe10(void)
{
//int ret;
//u32 cfg1;
//u32 data;
printf("LEO: enable LCD/FPC 5V by PE10 high\n");
boot_set_gpio(leo_lcd_5v_en_gpio, 1, 1);
mdelay(100);
//cfg1 = readl(PIO_REG_CFG(5, 1)); /* PE8~PE15 在 CFG1 */
//data = readl(PIO_REG_DATA(5));
//printf("LEO: PE10 enable ret=%d PE_CFG1=0x%x PE10_mux=%d PE_DATA=0x%x PE10=%d\n",
// ret,
// cfg1,
// (cfg1 >> 8) & 0xf,
// data,
// (data >> 10) & 1);
}
//extern int i2c_has_init;
//extern normal_gpio_cfg *twi_gpio;
//extern int i2c_read(unsigned char chip, unsigned int addr, int alen,
// unsigned char *buffer, int len);
//extern int i2c_write(unsigned char chip, unsigned int addr, int alen,
// unsigned char *buffer, int len);
static void update_uboot_info(phys_addr_t uboot_base, phys_addr_t optee_base,
phys_addr_t monitor_base, phys_addr_t rtos_base, u32 dram_size,
u16 pmu_type, u16 uart_input, u16 key_input);
static int boot0_clear_env(void);
static void print_commit_log(void)
{
printf("HELLO! BOOT0 is starting!\n");
printf("BOOT0 commit : %s\n", BT0_head.hash);
sunxi_set_printf_debug_mode(BT0_head.prvt_head.debug_mode, 0);
}
static void leo_axp313_init_pmic(void)
{
int ret;
u8 val = 0;
u8 out = 0;
//printf("LEO: axp313 init point before DRAM\n");
/*
* 这里不要用 AXP313A_ADDR 乱写了,
* 直接用系统现成的 AXP1530_DEVICE_ADDR / AXP1530_RUNTIME_ADDR。
* CFG_SUNXI_TWI 下 runtime addr 就是 0x36。
*/
ret = pmic_bus_init(AXP1530_DEVICE_ADDR, AXP1530_RUNTIME_ADDR);
printf("LEO: pmic_bus_init ret=%d\n", ret);
/*
* 先确认 PMIC 已经能访问。
*/
ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
AXP1530_OUTPUT_POWER_ON_OFF_CTL,
&out);
//printf("LEO: read output 0x10 ret=%d val=0x%x\n", ret, out);
if (ret) {
printf("LEO: AXP read failed, skip voltage config\n");
return;
}
ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
AXP1530_DC1OUT_VOL,
&val);
printf("LEO: read DCDC1 0x13 ret=%d val=0x%x\n", ret, val);
ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
AXP1530_DC3OUT_VOL,
&val);
printf("LEO: read DCDC3 0x15 ret=%d val=0x%x\n", ret, val);
/*
* DCDC1 = 3.3V
* AXP1530/AXP313 这套表里:
* 1600mV~3400mV 以 100mV 步进。
* 3.3V 对应 0x28。
*
* 0x69 就是 3.3V。
*/
ret = pmic_bus_write(AXP1530_RUNTIME_ADDR,
AXP1530_DC1OUT_VOL,
0x69);
//printf("LEO: write DCDC1 3.3V ret=%d\n", ret);
if (ret) {
return;
}
mdelay(2);
ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
AXP1530_DC1OUT_VOL,
&val);
printf("LEO: DCDC1 immediately after write ret=%d val=0x%x\n", ret, val);
if (ret) {
return;
}
/*
* DCDC3 = 1.5V
* 1220mV~1540mV 以 20mV 步进。
* 1.5V = 1220 + 14*20,所以寄存器值是前段累计 + 14。
* 你的 Linux 现在也是 0x28,实际显示 DCDC3 at 900mV,
* 这里先不要盲目写 0x55,0x55 很可能超范围/不符合这颗芯片表。
*
* 如果只是验证,不建议立刻改 DCDC3。
* 真要设置 1.5V,建议调用系统已有 axp1530_set_ddr_voltage(1500)。
*/
ret = axp1530_set_ddr_voltage(1500);
//printf("LEO: set DCDC3 1.5V ret=%d\n", ret);
if (ret)
return;
/*
* 使能 DCDC1 和 DCDC3。
* 不能直接写固定值,要保留其他 rail。
*/
ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
AXP1530_OUTPUT_POWER_ON_OFF_CTL,
&out);
//printf("LEO: read output before enable ret=%d val=0x%x\n", ret, out);
if (ret)
return;
out |= (1 << 0); /* DCDC1 enable */
out |= (1 << 2); /* DCDC3 enable */
ret = pmic_bus_write(AXP1530_RUNTIME_ADDR,
AXP1530_OUTPUT_POWER_ON_OFF_CTL,
out);
//printf("LEO: write output enable ret=%d val=0x%x\n", ret, out);
if (ret)
return;
mdelay(10);
ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
AXP1530_OUTPUT_POWER_ON_OFF_CTL,
&out);
//printf("LEO: output after ret=%d val=0x%x\n", ret, out);
ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
AXP1530_DC1OUT_VOL,
&val);
//printf("LEO: DCDC1 after ret=%d val=0x%x\n", ret, val);
ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
AXP1530_DC3OUT_VOL,
&val);
printf("LEO: DCDC3 after ret=%d val=0x%x\n", ret, val);
printf("LEO: axp313 voltage config done\n");
}
void main(void)
{
int dram_size;
int status;
phys_addr_t uboot_base = 0, optee_base = 0, monitor_base = 0, \
rtos_base = 0, opensbi_base = 0;
u16 pmu_type = 0, key_input = 0; /* TODO: set real value */
sunxi_board_init_early();
sunxi_serial_init(BT0_head.prvt_head.uart_port, (void *)BT0_head.prvt_head.uart_ctrl, 6);
print_commit_log();
status = sunxi_board_init();
if (status)
goto _BOOT_ERROR;
leo_enable_lcd_5v_pe10();
//leo_axp313_gpio_i2c_init();
leo_axp313_init_pmic();
if (rtc_probe_fel_flag()) {
rtc_clear_fel_flag();
goto _BOOT_ERROR;
#ifdef CFG_SUNXI_PHY_KEY
} else if (check_update_key(&key_input)) {
goto _BOOT_ERROR;
#endif
}
if (BT0_head.prvt_head.enable_jtag) {
printf("enable_jtag\n");
boot_set_gpio((normal_gpio_cfg *)BT0_head.prvt_head.jtag_gpio, 5, 1);
}
char uart_input_value = get_uart_input();
if (uart_input_value == '2') {
sunxi_set_printf_debug_mode(3, 0);
printf("detected user input 2\n");
goto _BOOT_ERROR;
} else if (uart_input_value == 'd') {
sunxi_set_printf_debug_mode(8, 1);
printf("detected user input d\n");
} else if (uart_input_value == 'q') {
printf("detected user input q\n");
sunxi_set_printf_debug_mode(0, 1);
}
#ifdef FPGA_PLATFORM
dram_size = mctl_init((void *)BT0_head.prvt_head.dram_para);
#else
dram_size = init_DRAM(0, (void *)BT0_head.prvt_head.dram_para);
#endif
if (!dram_size) {
printf("init dram fail\n");
goto _BOOT_ERROR;
} else {
printf("dram size =%d\n", dram_size);
}
mmu_enable(dram_size);
malloc_init(CONFIG_HEAP_BASE, CONFIG_HEAP_SIZE);
status = sunxi_board_late_init();
if (status)
goto _BOOT_ERROR;
status = load_package();
if (status == 0)
load_image(&uboot_base, &optee_base, &monitor_base, &rtos_base, &opensbi_base);
else
goto _BOOT_ERROR;
update_uboot_info(uboot_base, optee_base, monitor_base, rtos_base, dram_size,
pmu_type, uart_input_value, key_input);
mmu_disable( );
printf("Jump to second Boot.\n");
if (opensbi_base) {
boot0_jmp_opensbi(opensbi_base, uboot_base);
} else if (monitor_base) {
struct spare_monitor_head *monitor_head =
(struct spare_monitor_head *)((phys_addr_t)monitor_base);
monitor_head->secureos_base = optee_base;
monitor_head->nboot_base = uboot_base;
boot0_jmp_monitor(monitor_base);
} else if (optee_base)
boot0_jmp_optee(optee_base, uboot_base);
else if (rtos_base) {
printf("jump to rtos\n");
boot0_jmp(rtos_base);
}
else
boot0_jmp(uboot_base);
while(1);
_BOOT_ERROR:
boot0_clear_env();
boot0_jmp(FEL_BASE);
}
static void update_uboot_info(phys_addr_t uboot_base, phys_addr_t optee_base,
phys_addr_t monitor_base, phys_addr_t rtos_base, u32 dram_size,
u16 pmu_type, u16 uart_input, u16 key_input)
{
if (rtos_base)
return;
uboot_head_t *header = (uboot_head_t *) uboot_base;
struct sbrom_toc1_head_info *toc1_head = (struct sbrom_toc1_head_info *)CONFIG_BOOTPKG_BASE;
header->boot_data.boot_package_size = toc1_head->valid_len;
header->boot_data.dram_scan_size = dram_size;
memcpy((void *)header->boot_data.dram_para, &BT0_head.prvt_head.dram_para, 32 * sizeof(int));
if (monitor_base)
header->boot_data.monitor_exist = 1;
if (optee_base)
header->boot_data.secureos_exist = 1;
#ifndef CONFIG_RISCV
header->boot_data.func_mask |= get_uboot_func_mask(UBOOT_FUNC_MASK_ALL);
#endif
update_flash_para(uboot_base);
header->boot_data.pmu_type = pmu_type;
header->boot_data.uart_input = uart_input;
header->boot_data.key_input = key_input;
header->boot_data.debug_mode = sunxi_get_debug_mode_for_uboot();
}
static int boot0_clear_env(void)
{
sunxi_board_exit();
sunxi_board_clock_reset();
mmu_disable();
mdelay(10);
return 0;
}
还需要改的是i2c.c
/lichee/brandy-2.0/spl/drivers/i2c.c
/*
* (C) Copyright 2016
* SPDX-License-Identifier: GPL-2.0+
*Allwinner Technology Co., Ltd. <www.allwinnertech.com>
*weidonghui <weidonghui@allwinnertech.com>
*
*/
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <arch/i2c.h>
#include <arch/gpio.h>
#include <arch/clock.h>
#include <private_boot0.h>
#define I2C_WRITE 0
#define I2C_READ 1
#define I2C_OK 0
#define I2C_NOK 1
#define I2C_NACK 2
#define I2C_NOK_LA 3 /* Lost arbitration */
#define I2C_NOK_TOUT 4 /* time out */
#define I2C_START_TRANSMIT 0x08
#define I2C_RESTART_TRANSMIT 0x10
#define I2C_ADDRWRITE_ACK 0x18
#define I2C_ADDRREAD_ACK 0x40
#define I2C_DATAWRITE_ACK 0x28
#define I2C_READY 0xf8
#define I2C_DATAREAD_NACK 0x58
#define I2C_DATAREAD_ACK 0x50
normal_gpio_cfg *twi_gpio;
int i2c_has_init;
#if defined(CONFIG_ARCH_SUN50IW10)
normal_gpio_cfg i2c_gpio[4] = {
{12, 0, 2, 1, 0, 0, {SUNXI_PHY_R_I2C0} }, /* PL0: 2--SCK */
{12, 1, 2, 1, 0, 0, {SUNXI_PHY_R_I2C0} }, /* PL1: 2--SDA */
};
#elif defined(CONFIG_ARCH_SUN8IW11)
normal_gpio_cfg i2c_gpio[4] = {
{2, 0, 2, 1, 0, 0, {SUNXI_PHY_R_I2C0} }, /* pb0: 2--sck */
{2, 1, 2, 1, 0, 0, {SUNXI_PHY_R_I2C0} }, /* pb1: 2--sda */
};
#else
//系统默认
//normal_gpio_cfg i2c_gpio[4] = {
// {12, 0, 3, 1, 0, 0, {SUNXI_PHY_R_I2C0} }, /* pl0: 3--sck */
// {12, 1, 3, 1, 0, 0, {SUNXI_PHY_R_I2C0} }, /* pl1: 3--sda */
//};
//leo change
normal_gpio_cfg i2c_gpio[4] = {
{2, 4, 4, 1, 0, 0, {1} }, /* PB4: mux4 -- TWI1 SCK/SCL */
{2, 5, 4, 1, 0, 0, {1} }, /* PB5: mux4 -- TWI1 SDA */
};
#endif
/* status or interrupt source */
/*------------------------------------------------------------------------------
* Code Status
* 00h Bus error
* 08h START condition transmitted
* 10h Repeated START condition transmitted
* 18h Address + Write bit transmitted, ACK received
* 20h Address + Write bit transmitted, ACK not received
* 28h Data byte transmitted in master mode, ACK received
* 30h Data byte transmitted in master mode, ACK not received
* 38h Arbitration lost in address or data byte
* 40h Address + Read bit transmitted, ACK received
* 48h Address + Read bit transmitted, ACK not received
* 50h Data byte received in master mode, ACK transmitted
* 58h Data byte received in master mode, not ACK transmitted
* 60h Slave address + Write bit received, ACK transmitted
* 68h Arbitration lost in address as master, slave address + Write bit received, ACK transmitted
* 70h General Call address received, ACK transmitted
* 78h Arbitration lost in address as master, General Call address received, ACK transmitted
* 80h Data byte received after slave address received, ACK transmitted
* 88h Data byte received after slave address received, not ACK transmitted
* 90h Data byte received after General Call received, ACK transmitted
* 98h Data byte received after General Call received, not ACK transmitted
* A0h STOP or repeated START condition received in slave mode
* A8h Slave address + Read bit received, ACK transmitted
* B0h Arbitration lost in address as master, slave address + Read bit received, ACK transmitted
* B8h Data byte transmitted in slave mode, ACK received
* C0h Data byte transmitted in slave mode, ACK not received
* C8h Last byte transmitted in slave mode, ACK received
* D0h Second Address byte + Write bit transmitted, ACK received
* D8h Second Address byte + Write bit transmitted, ACK not received
* F8h No relevant status information or no interrupt
*-----------------------------------------------------------------------------*/
static struct sunxi_twi_reg *i2c;
static void i2c_debug(void)
{
i2c_info("i2c->addr :\t0x%x:0x%x\n", &i2c->addr, i2c->addr);
i2c_info("i2c->xaddr :\t0x%x:0x%x\n", &i2c->xaddr, i2c->xaddr);
i2c_info("i2c->data :\t0x%x:0x%x\n", &i2c->data, i2c->data);
i2c_info("i2c->ctl :\t0x%x:0x%x\n", &i2c->ctl, i2c->ctl);
i2c_info("i2c->status:\t0x%x:0x%x\n", &i2c->status, i2c->status);
i2c_info("i2c->clk :\t0x%x:0x%x\n", &i2c->clk, i2c->clk);
i2c_info("i2c->srst :\t0x%x:0x%x\n", &i2c->srst, i2c->srst);
i2c_info("i2c->eft :\t0x%x:0x%x\n", &i2c->eft, i2c->eft);
i2c_info("i2c->lcr :\t0x%x:0x%x\n", &i2c->lcr, i2c->lcr);
i2c_info("i2c->dvfs :\t0x%x:0x%x\n", &i2c->dvfs, i2c->dvfs);
}
static __s32 i2c_sendbyteaddr(__u32 byteaddr)
{
__s32 time = 0xffff;
__u32 tmp_val;
i2c->data = byteaddr & 0xff;
i2c->ctl |= (0x01 << 3); /*write 1 to clean int flag*/
while ((time--) && (!(i2c->ctl & 0x08)))
;
if (time <= 0) {
return -I2C_NOK_TOUT;
}
tmp_val = i2c->status;
i2c_debug();
if (tmp_val != I2C_DATAWRITE_ACK) {
return -I2C_DATAWRITE_ACK;
}
return I2C_OK;
}
static __s32 i2c_sendstart(void)
{
__s32 time = 0xffff;
__u32 tmp_val;
i2c->eft = 0;
//leo tmp
//i2c->srst = 1;
i2c->ctl |= TWI_CTL_STA;
while ((time--) && (!(i2c->ctl & TWI_CTL_INTFLG)))
;
if (time <= 0) {
return -I2C_NOK_TOUT;
}
tmp_val = i2c->status;
if (tmp_val != I2C_START_TRANSMIT) {
return -I2C_START_TRANSMIT;
}
return I2C_OK;
}
static __s32 i2c_sendslaveaddr(__u32 saddr, __u32 rw)
{
__s32 time = 0xffff;
__u32 tmp_val;
rw &= 1;
i2c->data = ((saddr & 0xff) << 1) | rw;
i2c->ctl |= TWI_CTL_INTFLG; /*write 1 to clean int flag*/
while ((time--) && (!(i2c->ctl & TWI_CTL_INTFLG)))
;
if (time <= 0) {
// printf("LEO: sendslave timeout addr=0x%x rw=%d ctl=0x%x status=0x%x\n",
// saddr, rw, i2c->ctl, i2c->status);
return -I2C_NOK_TOUT;
}
tmp_val = i2c->status;
//printf("LEO: sendslave addr=0x%x rw=%d data=0x%x status=0x%x ctl=0x%x\n",
// saddr, rw, i2c->data, tmp_val, i2c->ctl);
if (rw == I2C_WRITE) /*+write*/
{
if (tmp_val != I2C_ADDRWRITE_ACK) {
//printf("LEO: SLA+W failed, status=0x%x expected=0x18\n", tmp_val);
return -I2C_ADDRWRITE_ACK;
}
}
else /*+read*/
{
if (tmp_val != I2C_ADDRREAD_ACK) {
//printf("LEO: SLA+R failed, status=0x%x expected=0x40\n", tmp_val);
return -I2C_ADDRREAD_ACK;
}
}
i2c_debug();
return I2C_OK;
}
static __s32 i2c_sendRestart(void)
{
__s32 time = 0xffff;
__u32 tmp_val;
tmp_val = i2c->ctl;
tmp_val |= 0x20;
i2c->ctl = tmp_val;
while ((time--) && (!(i2c->ctl & 0x08)))
;
if (time <= 0) {
return -I2C_NOK_TOUT;
}
tmp_val = i2c->status;
if (tmp_val != I2C_RESTART_TRANSMIT) {
return -I2C_RESTART_TRANSMIT;
}
return I2C_OK;
}
static __s32 i2c_stop(void)
{
__s32 time = 0xffff;
__u32 tmp_val;
i2c->ctl |= (0x01 << 4);
i2c->ctl |= (0x01 << 3);
while ((time--) && (i2c->ctl & 0x10))
;
if (time <= 0) {
return -I2C_NOK_TOUT;
}
time = 0xffff;
while ((time--) && (i2c->status != I2C_READY))
;
tmp_val = i2c->status;
if (tmp_val != I2C_READY) {
return -I2C_NOK_TOUT;
}
return I2C_OK;
}
static __s32 i2c_getdata(__u8 *data_addr, __u32 data_count)
{
__s32 time = 0xffff;
__u32 tmp_val;
__u32 i;
if (data_count == 1) {
i2c->ctl |= (0x01 << 3);
while ((time--) && (!(i2c->ctl & 0x08)))
;
if (time <= 0) {
return -I2C_NOK_TOUT;
}
for (time = 0; time < 100; time++)
;
*data_addr = i2c->data;
tmp_val = i2c->status;
if (tmp_val != I2C_DATAREAD_NACK) {
return -I2C_DATAREAD_NACK;
}
} else {
for (i = 0; i < data_count - 1; i++) {
time = 0xffff;
/*host should send ack every time when a data packet finished*/
tmp_val = i2c->ctl | (0x01 << 2);
tmp_val = i2c->ctl | (0x01 << 3);
tmp_val |= 0x04;
i2c->ctl = tmp_val;
/*i2c->ctl |=(0x01<<3);*/
while ((time--) && (!(i2c->ctl & 0x08)))
;
if (time <= 0) {
return -I2C_NOK_TOUT;
}
for (time = 0; time < 100; time++)
;
time = 0xffff;
data_addr[i] = i2c->data;
while ((time--) && (i2c->status != I2C_DATAREAD_ACK))
;
if (time <= 0) {
return -I2C_NOK_TOUT;
}
}
time = 0xffff;
i2c->ctl &= 0xFb; /*the last data packet,not send ack*/
i2c->ctl |= (0x01 << 3);
while ((time--) && (!(i2c->ctl & 0x08)))
;
if (time <= 0) {
return -I2C_NOK_TOUT;
}
for (time = 0; time < 100; time++)
;
data_addr[data_count - 1] = i2c->data;
while ((time--) && (i2c->status != I2C_DATAREAD_NACK))
;
if (time <= 0) {
return -I2C_NOK_TOUT;
}
}
return I2C_OK;
}
int i2c_read(u8 chip, uint addr, int alen, u8 *buffer, int len)
{
int i, ret, addrlen;
char *slave_reg;
if (!i2c_has_init) {
return -I2C_NOK_TOUT;
}
ret = i2c_sendstart();
if (ret) {
goto i2c_read_err_occur;
}
ret = i2c_sendslaveaddr(chip, I2C_WRITE);
if (ret) {
goto i2c_read_err_occur;
}
/*send byte address*/
if (alen >= 3) {
addrlen = 2;
} else if (alen <= 1) {
addrlen = 0;
} else {
addrlen = 1;
}
slave_reg = (char *)&addr;
for (i = addrlen; i >= 0; i--) {
ret = i2c_sendbyteaddr(slave_reg[i] & 0xff);
if (ret) {
goto i2c_read_err_occur;
}
}
ret = i2c_sendRestart();
if (ret) {
goto i2c_read_err_occur;
}
ret = i2c_sendslaveaddr(chip, I2C_READ);
if (ret) {
goto i2c_read_err_occur;
}
/*get data*/
ret = i2c_getdata(buffer, len);
if (ret) {
goto i2c_read_err_occur;
}
i2c_read_err_occur:
i2c_stop();
return ret;
}
static __s32 i2c_senddata(__u8 *data_addr, __u32 data_count)
{
__s32 time = 0xffff;
__u32 i;
for (i = 0; i < data_count; i++) {
time = 0xffff;
i2c->data = data_addr[i];
#if defined(CONFIG_ARCH_SUN5I) || defined(CONFIG_ARCH_SUN7I)
i2c->ctl &= 0xF7;
#else
i2c->ctl |= (0x01 << 3);
#endif
while ((time--) && (!(i2c->ctl & 0x08)))
;
if (time <= 0) {
return -I2C_NOK_TOUT;
}
time = 0xffff;
while ((time--) && (i2c->status != I2C_DATAWRITE_ACK)) {
;
}
if (time <= 0) {
return -I2C_NOK_TOUT;
}
}
return I2C_OK;
}
int i2c_write(u8 chip, uint addr, int alen, u8 *buffer, int len)
{
int i, ret, ret0, addrlen;
char *slave_reg;
if (!i2c_has_init) {
return -I2C_NOK_TOUT;
}
ret0 = -1;
ret = i2c_sendstart();
if (ret) {
goto i2c_write_err_occur;
}
ret = i2c_sendslaveaddr(chip, I2C_WRITE);
if (ret) {
goto i2c_write_err_occur;
}
/*send byte address*/
if (alen >= 3) {
addrlen = 2;
} else if (alen <= 1) {
addrlen = 0;
} else {
addrlen = 1;
}
slave_reg = (char *)&addr;
for (i = addrlen; i >= 0; i--) {
ret = i2c_sendbyteaddr(slave_reg[i] & 0xff);
if (ret) {
goto i2c_write_err_occur;
}
}
ret = i2c_senddata(buffer, len);
if (ret) {
goto i2c_write_err_occur;
}
ret0 = 0;
i2c_write_err_occur:
i2c_stop();
return ret0;
}
int axp_i2c_write(unsigned char chip, unsigned char addr, unsigned char data)
{
return i2c_write(chip, addr, 1, &data, 1);
}
int axp_i2c_read(unsigned char chip, unsigned char addr, unsigned char *buffer)
{
return i2c_read(chip, addr, 1, buffer, 1);
}
void i2c_set_clock(int speed, int slaveaddr)
{
int i, clk_n, clk_m, pow_2_clk_n;
/* reset i2c control */
i = 0xffff;
i2c->srst = 1;
while ((i2c->srst) && (i)) {
i--;
}
if ((i2c->lcr & 0x30) != 0x30) {
/* toggle I2C SCL and SDA until bus idle */
i2c->lcr = 0x05;
udelay(500);
i = 10;
while ((i > 0) && ((i2c->lcr & 0x02) != 2)) {
/*control scl and sda output high level*/
i2c->lcr |= 0x08;
i2c->lcr |= 0x02;
udelay(1000);
/*control scl and sda output low level*/
i2c->lcr &= ~0x08;
i2c->lcr &= ~0x02;
udelay(1000);
i--;
}
i2c->lcr = 0x0;
udelay(500);
}
speed /= 1000; /*khz*/
if (speed < 100)
speed = 100;
else if (speed > 400)
speed = 400;
/*Foscl=24000/(2^CLK_N*(CLK_M+1)*10)*/
clk_n = (speed == 100) ? 1 : 0;
pow_2_clk_n = 1;
for (i = 0; i < clk_n; ++i)
pow_2_clk_n *= 2;
clk_m = (24000 / 10) / (pow_2_clk_n * speed) - 1;
i2c->clk = (clk_m << 3) | clk_n;
i2c->ctl |= 0x40;
i2c->eft = 0;
i2c_debug();
//printf("LEO: final lcr=0x%x lcr&0x30=0x%x\n",
// i2c->lcr, i2c->lcr & 0x30);
}
static void sunxi_i2c_bus_setting(u32 i2c_base, int onoff)
{
int reg_value = 0;
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
u32 bus_num = (i2c_base - SUNXI_TWI0_BASE)/0x400;
if (bus_num <= 5) {
#if defined(CONFIG_SUNXI_VERSION1)
if (onoff) {
//de-assert
reg_value = readl(&ccm->apb2_reset_cfg);
reg_value |= (1 << bus_num);
writel(reg_value, &ccm->apb2_reset_cfg);
//gating clock pass
reg_value = readl(&ccm->apb2_gate);
reg_value &= ~(1 << bus_num);
writel(reg_value, &ccm->apb2_gate);
mdelay(1);
reg_value |= (1 << bus_num);
writel(reg_value, &ccm->apb2_gate);
} else {
//gating clock mask
reg_value = readl(&ccm->apb2_gate);
reg_value &= ~(1 << bus_num);
writel(reg_value, &ccm->apb2_gate);
//assert
reg_value = readl(&ccm->apb2_reset_cfg);
reg_value &= ~(1 << bus_num);
writel(reg_value, &ccm->apb2_reset_cfg);
}
#else
if (onoff) {
//de-assert
reg_value = readl(&ccm->twi_gate_reset);
reg_value |= (1 << (16 + bus_num));
writel(reg_value, &ccm->twi_gate_reset);
//gating clock pass
reg_value = readl(&ccm->twi_gate_reset);
reg_value &= ~(1 << bus_num);
writel(reg_value, &ccm->twi_gate_reset);
mdelay(1);
reg_value |= (1 << bus_num);
writel(reg_value, &ccm->twi_gate_reset);
} else {
//gating clock mask
reg_value = readl(&ccm->twi_gate_reset);
reg_value &= ~(1 << bus_num);
writel(reg_value, &ccm->twi_gate_reset);
//assert
reg_value = readl(&ccm->twi_gate_reset);
reg_value &= ~(1 << (16 + bus_num));
writel(reg_value, &ccm->twi_gate_reset);
}
#endif
} else {
int r_bus_num = (i2c_base - SUNXI_RTWI_BASE)/0x400;
if (onoff) {
/*de-assert*/
reg_value = readl(SUNXI_RTWI_BRG_REG);
reg_value &= ~(1 << (16 + r_bus_num));
writel(reg_value, SUNXI_RTWI_BRG_REG);
reg_value = readl(SUNXI_RTWI_BRG_REG);
reg_value |= (1 << (16 + r_bus_num));
writel(reg_value, SUNXI_RTWI_BRG_REG);
/*gating clock pass*/
reg_value = readl(SUNXI_RTWI_BRG_REG);
reg_value &= ~(1 << r_bus_num);
writel(reg_value, SUNXI_RTWI_BRG_REG);
mdelay(1);
reg_value |= (1 << r_bus_num);
writel(reg_value, SUNXI_RTWI_BRG_REG);
} else {
/*gating clock mask*/
reg_value = readl(SUNXI_RTWI_BRG_REG);
reg_value &= ~(1 << r_bus_num);
writel(reg_value, SUNXI_RTWI_BRG_REG);
/*assert*/
reg_value = readl(SUNXI_RTWI_BRG_REG);
reg_value &= ~(1 << (16 + r_bus_num));
writel(reg_value, SUNXI_RTWI_BRG_REG);
}
}
}
/*
normal_gpio_cfg *get_i2c_gpio(void)
{
normal_gpio_cfg *boot_i2c_gpio, *temp_gpio;
#ifdef CFG_SUNXI_SBOOT
boot_i2c_gpio = (normal_gpio_cfg *)sboot_head.i2c_gpio;
#elif CFG_SUNXI_FES
boot_i2c_gpio = (normal_gpio_cfg *)fes1_head.i2c_gpio;
#else
boot_i2c_gpio = (normal_gpio_cfg *)BT0_head.i2c_gpio;
#endif
if (boot_i2c_gpio->port == 0) {
//
// Setting a non-existent i2c pin
// will cause a very long timeout waiting
// so enable CFG_SUNXI_AUTO_TWI
//
#ifdef CFG_SUNXI_AUTO_TWI
temp_gpio = NULL;
#else
temp_gpio = i2c_gpio;
#endif
} else {
temp_gpio = boot_i2c_gpio;
}
return temp_gpio;
}
*/
normal_gpio_cfg *get_i2c_gpio(void)
{
normal_gpio_cfg *boot_i2c_gpio, *temp_gpio;
const char *src = "unknown";
#ifdef CFG_SUNXI_SBOOT
boot_i2c_gpio = (normal_gpio_cfg *)sboot_head.i2c_gpio;
src = "sboot_head.i2c_gpio";
#elif CFG_SUNXI_FES
boot_i2c_gpio = (normal_gpio_cfg *)fes1_head.i2c_gpio;
src = "fes1_head.i2c_gpio";
#else
boot_i2c_gpio = (normal_gpio_cfg *)BT0_head.i2c_gpio;
src = "BT0_head.i2c_gpio";
#endif
printf("LEO: get_i2c_gpio boot source=%s\n", src);
printf("LEO: boot_i2c_gpio0 port=%d num=%d mul=%d pull=%d drv=%d data=%d bus=%d\n",
boot_i2c_gpio[0].port,
boot_i2c_gpio[0].port_num,
boot_i2c_gpio[0].mul_sel,
boot_i2c_gpio[0].pull,
boot_i2c_gpio[0].drv_level,
boot_i2c_gpio[0].data,
boot_i2c_gpio[0].reserved[0]);
printf("LEO: boot_i2c_gpio1 port=%d num=%d mul=%d pull=%d drv=%d data=%d bus=%d\n",
boot_i2c_gpio[1].port,
boot_i2c_gpio[1].port_num,
boot_i2c_gpio[1].mul_sel,
boot_i2c_gpio[1].pull,
boot_i2c_gpio[1].drv_level,
boot_i2c_gpio[1].data,
boot_i2c_gpio[1].reserved[0]);
printf("LEO: fallback i2c_gpio0 port=%d num=%d mul=%d pull=%d drv=%d data=%d bus=%d\n",
i2c_gpio[0].port,
i2c_gpio[0].port_num,
i2c_gpio[0].mul_sel,
i2c_gpio[0].pull,
i2c_gpio[0].drv_level,
i2c_gpio[0].data,
i2c_gpio[0].reserved[0]);
printf("LEO: fallback i2c_gpio1 port=%d num=%d mul=%d pull=%d drv=%d data=%d bus=%d\n",
i2c_gpio[1].port,
i2c_gpio[1].port_num,
i2c_gpio[1].mul_sel,
i2c_gpio[1].pull,
i2c_gpio[1].drv_level,
i2c_gpio[1].data,
i2c_gpio[1].reserved[0]);
if (boot_i2c_gpio->port == 0) {
/*
* Setting a non-existent i2c pin
* will cause a very long timeout waiting
* so enable CFG_SUNXI_AUTO_TWI
*/
#ifdef CFG_SUNXI_AUTO_TWI
printf("LEO: boot_i2c_gpio port=0, CFG_SUNXI_AUTO_TWI enabled, force fallback i2c_gpio[]\n");
temp_gpio = i2c_gpio;
#else
printf("LEO: boot_i2c_gpio port=0, use fallback i2c_gpio[]\n");
temp_gpio = i2c_gpio;
#endif
} else {
printf("LEO: boot_i2c_gpio port!=0, use boot header i2c_gpio\n");
temp_gpio = boot_i2c_gpio;
}
if (temp_gpio) {
/*
printf("LEO: selected_i2c_gpio0 port=%d num=%d mul=%d pull=%d drv=%d data=%d bus=%d\n",
temp_gpio[0].port,
temp_gpio[0].port_num,
temp_gpio[0].mul_sel,
temp_gpio[0].pull,
temp_gpio[0].drv_level,
temp_gpio[0].data,
temp_gpio[0].reserved[0]);
printf("LEO: selected_i2c_gpio1 port=%d num=%d mul=%d pull=%d drv=%d data=%d bus=%d\n",
temp_gpio[1].port,
temp_gpio[1].port_num,
temp_gpio[1].mul_sel,
temp_gpio[1].pull,
temp_gpio[1].drv_level,
temp_gpio[1].data,
temp_gpio[1].reserved[0]);
*/
} else {
// printf("LEO: selected_i2c_gpio = NULL\n");
}
return temp_gpio;
}
void i2c_init(ulong i2c_base, int speed, int slaveaddr)
{
u32 cfg0;
u32 pull0;
u32 dlevel0;
u32 data;
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
printf("LEO: i2c_init base=0x%x speed=%d slaveaddr=0x%x\n",
i2c_base, speed, slaveaddr);
i2c = (struct sunxi_twi_reg *)i2c_base;
printf("LEO: twi_gate_reset before=0x%x\n",
readl(&ccm->twi_gate_reset));
// 先配置 PB4/PB5 mux4。
// 当前 twi_gpio 已经由 get_i2c_gpio() 选成 fallback i2c_gpio[]。
boot_set_gpio(twi_gpio, 2, 1);
cfg0 = readl(PIO_REG_CFG(2, 0));
pull0 = readl(PIO_REG_PULL(2, 0));
dlevel0 = readl(PIO_REG_DLEVEL(2, 0));
data = readl(PIO_REG_DATA(2));
printf("LEO: after gpio PB_CFG0=0x%x PB4_mux=%d PB5_mux=%d\n",
cfg0,
(cfg0 >> 16) & 0xf,
(cfg0 >> 20) & 0xf);
printf("LEO: after gpio PB_PULL0=0x%x PB4_pull=%d PB5_pull=%d\n",
pull0,
(pull0 >> 8) & 0x3,
(pull0 >> 10) & 0x3);
printf("LEO: after gpio PB_DLEVEL0=0x%x PB4_drv=%d PB5_drv=%d\n",
dlevel0,
(dlevel0 >> 8) & 0x3,
(dlevel0 >> 10) & 0x3);
printf("LEO: after gpio PB_DATA=0x%x PB4=%d PB5=%d\n",
data,
(data >> 4) & 1,
(data >> 5) & 1);
// 再开 TWI1 clock/reset。
sunxi_i2c_bus_setting(i2c_base, 1);
printf("LEO: twi_gate_reset after=0x%x\n",
readl(&ccm->twi_gate_reset));
i2c_set_clock(speed, slaveaddr);
//printf("LEO: TWI regs after set_clock ctl=0x%x clk=0x%x srst=0x%x eft=0x%x status=0x%x lcr=0x%x\n",
// i2c->ctl,
// i2c->clk,
// i2c->srst,
// i2c->eft,
// i2c->status,
// i2c->lcr);
}
/*old
void i2c_init(ulong i2c_base, int speed, int slaveaddr)
{
i2c = (struct sunxi_twi_reg *)i2c_base;
boot_set_gpio(twi_gpio, 2, 1);
sunxi_i2c_bus_setting(i2c_base, 1);
i2c_set_clock(speed, slaveaddr);
}
*/
/*
void i2c_init_cpus(int speed, int slaveaddr)
{
printf("LEO: i2c_init_cpus enter speed=%d slaveaddr=0x%x has_init=%d\n",
speed, slaveaddr, i2c_has_init);
if (!i2c_has_init) {
twi_gpio = get_i2c_gpio();
if (twi_gpio != NULL) {
i2c_init(twi_gpio[0].reserved[0] != SUNXI_PHY_R_I2C0 ?
(SUNXI_TWI0_BASE + 0x400 * twi_gpio[0].reserved[0]) :
(SUNXI_RTWI_BASE + 0x400 * (twi_gpio[0].reserved[0] - SUNXI_PHY_R_I2C0)),
speed, slaveaddr);
i2c_has_init = 1;
printf("LEO: i2c_init_cpus done has_init=%d\n", i2c_has_init);
} else {
i2c_has_init = 0;
printf("LEO: i2c_init_cpus twi_gpio NULL, init skipped\n");
}
}else{
printf("LEO: i2c_init_cpus skipped, already has_init=1\n");
}
return;
}
*/
void i2c_init_cpus(int speed, int slaveaddr)
{
//printf("LEO: i2c_init_cpus enter speed=%d slaveaddr=0x%x has_init=%d\n",
// speed, slaveaddr, i2c_has_init);
speed = 100000;
//printf("LEO: force i2c speed=%d\n", speed);
if (!i2c_has_init) {
ulong base;
twi_gpio = get_i2c_gpio();
if (twi_gpio != NULL) {
base = (twi_gpio[0].reserved[0] != SUNXI_PHY_R_I2C0 ?
(SUNXI_TWI0_BASE + 0x400 * twi_gpio[0].reserved[0]) :
(SUNXI_RTWI_BASE + 0x400 * (twi_gpio[0].reserved[0] - SUNXI_PHY_R_I2C0)));
//printf("LEO: i2c_init_cpus selected base=0x%x bus=%d\n",
// base, twi_gpio[0].reserved[0]);
i2c_init(base, speed, slaveaddr);
i2c_has_init = 1;
//printf("LEO: i2c_init_cpus done has_init=%d\n", i2c_has_init);
} else {
//printf("LEO: i2c_init_cpus twi_gpio NULL, init skipped\n");
i2c_has_init = 0;
}
} else {
//printf("LEO: i2c_init_cpus skipped, already has_init=%d\n",
// i2c_has_init);
}
return;
}
void i2c_exit(void)
{
int i;
u32 i2c_base;
if (i2c_has_init) {
twi_gpio = get_i2c_gpio();
i2c_base = (twi_gpio[0].reserved[0] != SUNXI_PHY_R_I2C0 ?
(SUNXI_TWI0_BASE + 0x400 * twi_gpio[0].reserved[0]) :
(SUNXI_RTWI_BASE + 0x400 * (twi_gpio[0].reserved[0] - SUNXI_PHY_R_I2C0)));
sunxi_i2c_bus_setting(i2c_base, 0);
for (i = 0; i < 2; i++) {
twi_gpio[i].mul_sel = 0x0;
twi_gpio[i].pull = 0;
twi_gpio[i].drv_level = 0x0;
}
boot_set_gpio(twi_gpio, 2, 1);
i2c_has_init = 0;
}
}
改好以后boot0 那个pmu就不用管它了,反正自己的程序也能配置好AXP313
[28]HELLO! BOOT0 is starting!
[31]BOOT0 commit :
[33]set pll start
[39]periph0 has been enabled
[42]set pll end
[44]LEO: get_i2c_gpio boot source=BT0_head.i2c_gpio
[48]LEO: boot_i2c_gpio0 port=0 num=0 mul=0 pull=0 drv=0 data=0 bus=0
[55]LEO: boot_i2c_gpio1 port=0 num=0 mul=0 pull=0 drv=0 data=0 bus=0
[61]LEO: fallback i2c_gpio0 port=2 num=4 mul=4 pull=1 drv=0 data=0 bus=1
[68]LEO: fallback i2c_gpio1 port=2 num=5 mul=4 pull=1 drv=0 data=0 bus=1
[74]LEO: boot_i2c_gpio port=0, CFG_SUNXI_AUTO_TWI enabled, force fallback i2c_gpio[]
[82]LEO: i2c_init base=0x2502400 speed=100000 slaveaddr=0x36
[88]LEO: twi_gate_reset before=0x0
[91]LEO: after gpio PB_CFG0=0xff44ffff PB4_mux=4 PB5_mux=4
[97]LEO: after gpio PB_PULL0=0x500 PB4_pull=1 PB5_pull=1
[102]LEO: after gpio PB_DLEVEL0=0x11111011 PB4_drv=0 PB5_drv=0
[108]LEO: after gpio PB_DATA=0x0 PB4=0 PB5=0
[113]LEO: twi_gate_reset after=0x20002
[117][pmu]: bus read error
[119]board init ok
[121]LEO: enable LCD/FPC 5V by PE10 high
[225]LEO: PE10 enable ret=0 PE_CFG1=0xfffff1ff PE10_mux=1 PE_DATA=0x400 PE10=1
[232]LEO: axp313 init point before DRAM
[236]LEO: pmic_bus_init ret=0
[239]LEO: read output 0x10 ret=0 val=0x1f
[243]LEO: read DCDC1 0x13 ret=0 val=0x28
[247]LEO: read DCDC3 0x15 ret=0 val=0x28
[251]LEO: write DCDC1 3.3V ret=0
[257]LEO: DCDC1 immediately after write ret=0 val=0x69
[282]LEO: set DCDC3 1.5V ret=0
[285]LEO: read output before enable ret=0 val=0x1f
[290]LEO: write output enable ret=0 val=0x1f
[305]LEO: output after ret=0 val=0x1f
[308]LEO: DCDC1 after ret=0 val=0x69
[312]LEO: DCDC3 after ret=0 val=0x55
[316]LEO: axp313 voltage config done
[319]ZQ value = 0x2e
[321]get_pmu_exist() = -1
[324]DRAM BOOT DRIVE INFO: V0.33
[327]DRAM CLK = 936 MHz
[329]DRAM Type = 3 (2:DDR2,3:DDR3)
[332]DRAMC read ODT off.
[335]DRAM ODT value: 0x42.
[337]ddr_efuse_type: 0xa
[341]DRAM SIZE =128 M
[343]dram_tpr4:0x0
[344]PLL_DDR_CTRL_REG:0xf8004d00
[348]DRAM_CLK_REG:0xc0000000
[350][TIMING DEBUG] MR2= 0x20
[358]DRAM simple test OK.
[360]rtc standby flag is 0x0, super standby flag is 0x0
[366]dram size =128
[369]LEO: get_i2c_gpio boot source=BT0_head.i2c_gpio
[373]LEO: boot_i2c_gpio0 port=0 num=0 mul=0 pull=0 drv=0 data=0 bus=0
[380]LEO: boot_i2c_gpio1 port=0 num=0 mul=0 pull=0 drv=0 data=0 bus=0
[386]LEO: fallback i2c_gpio0 port=2 num=4 mul=4 pull=1 drv=0 data=0 bus=1
[393]LEO: fallback i2c_gpio1 port=2 num=5 mul=4 pull=1 drv=0 data=0 bus=1
[399]LEO: boot_i2c_gpio port=0, CFG_SUNXI_AUTO_TWI enabled, force fallback i2c_gpio[]
[407]spinand UBOOT_START_BLK_NUM 8 UBOOT_LAST_BLK_NUM 32
[412]block from 8 to 32
[507]Check is correct.
[509]dma 0x2a534 int is not used yet
[512]dma 0x2a534 int is free, you do not need to free it again
[518]Entry_name = u-boot
[525]Entry_name = optee
[529]Entry_name = dtb
[532]Jump to second Boot.
中间调试其实有很多坑,有问题的。。。都被我DEBUG掉了,反正这样就可以 了 哈哈哈
,哈哈哈,搞定了颜色正常了