<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[T113 AXP313 调试记录]]></title><description><![CDATA[<p dir="auto">之前玩T113S3 都是3个dcdc 供电，那个电路不够简洁，所以换AXP313A</p>
<p dir="auto">但是换之前被一个大问题困扰，这个PMIC没有配置，能直接把T113带起来嘛<br />
所以我整了个测试板，T113 还是dcdc 供电，然后把信号线接过去测试</p>
<p dir="auto">现在结果来了<br />
1 在什么都没有配置的情况下 T113 默认输出 两路 ldo 一个是1.8v 一个是3.3<br />
然后三路dcdc 都是0.9v</p>
<p dir="auto">那么boot0 应该就没问题了</p>
<p dir="auto">有3.3 有 0.9 有1.8 其实 都不需要配置pmic就可以直接带起来，只是没有Dram的1.5 然后系统里面那个ldo的3.3v带别的设备不行</p>
<p dir="auto">所以现在的目标就是把dcdc1 拉到 3.3v 把 dcdc3 拉到1.5v 这样整个板子的供电就基本上都够了 dcdc1 给其他3.3v模块用 1.5v可以直接把dram 带起来</p>
<p dir="auto">然后调试的思路就是 先让系统配置起来，其实这个简单，只需要把你连接的pin配置好即可  在dts里面配置</p>
<p dir="auto">比如我这里<br />
TWI1 PB4 PB5 axp1530=AXP313，这两在系统驱动里面是当一样的东西处理 ，所以这里直接这么写就可以了</p>
<pre><code>&amp;twi1 {
	clock-frequency = &lt;100000&gt;;
	pinctrl-0 = &lt;&amp;twi1_pins_a&gt;;
	pinctrl-1 = &lt;&amp;twi1_pins_b&gt;;
	pinctrl-names = "default", "sleep";
	status = "okay";

	axp1530: pmic@36 {
		compatible = "x-powers,axp1530";
		reg = &lt;0x36&gt;;
		status = "okay";
		wakeup-source;

		regulators {
			reg_dcdc1: dcdc1 {
				regulator-name = "axp1530-dcdc1";
				regulator-min-microvolt = &lt;500000&gt;;
				regulator-max-microvolt = &lt;3300000&gt;;
				regulator-step-delay-us = &lt;25&gt;;
				regulator-final-delay-us = &lt;50&gt;;
				regulator-boot-on;
				regulator-always-on;
			};

			reg_dcdc2: dcdc2 {
				regulator-name = "axp1530-dcdc2";
				regulator-min-microvolt = &lt;500000&gt;;
				regulator-max-microvolt = &lt;1540000&gt;;
				regulator-step-delay-us = &lt;25&gt;;
				regulator-final-delay-us = &lt;50&gt;;
				regulator-ramp-delay = &lt;200&gt;;
				regulator-boot-on;
				regulator-always-on;
			};

			reg_dcdc3: dcdc3 {
				regulator-name = "axp1530-dcdc3";
				regulator-min-microvolt = &lt;500000&gt;;
				regulator-max-microvolt = &lt;1840000&gt;;
				regulator-step-delay-us = &lt;25&gt;;
				regulator-final-delay-us = &lt;50&gt;;
				regulator-boot-on;
				regulator-always-on;
			};

			reg_aldo1: ldo1 {
				regulator-name = "axp1530-aldo1";
				regulator-min-microvolt = &lt;500000&gt;;
				regulator-max-microvolt = &lt;3500000&gt;;
				regulator-step-delay-us = &lt;25&gt;;
				regulator-final-delay-us = &lt;50&gt;;
				regulator-boot-on;
				regulator-always-on;
			};

			reg_dldo1: ldo2 {
				regulator-name = "axp1530-dldo1";
				regulator-min-microvolt = &lt;500000&gt;;
				regulator-max-microvolt = &lt;3500000&gt;;
				regulator-step-delay-us = &lt;25&gt;;
				regulator-final-delay-us = &lt;50&gt;;
				regulator-boot-on;
				regulator-always-on;
			};
		};
	};
};

</code></pre>
<p dir="auto">然后系统基本上就很简单能连接并读取芯片数据了<br />
唯一的坑是，我自己抄大佬的原理图没有注意H616那个IO是1.8v的但是我这里T113是3.3v 那个SDA SDL线需要上拉才能工作，拉错电压就会导致数据错误，连接失败。<br />
弄好了以后系统里面就可以这样直接 操作 pmic了，可以直接往twi上发指令</p>
<pre><code>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 &lt;--&gt; 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 &lt;--&gt; 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 -&gt; 1540000
[    1.000905] axp1530-dcdc3: 500 &lt;--&gt; 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 &lt;--&gt; 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 &lt;--&gt; 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
&gt;     echo "== $r =="
&gt;     cat $r/name 2&gt;/dev/null
&gt;     cat $r/microvolts 2&gt;/dev/null
&gt;     cat $r/state 2&gt;/dev/null
&gt; 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
&gt;     echo "== $r =="
&gt;     cat $r/name 2&gt;/dev/null
&gt;     cat $r/microvolts 2&gt;/dev/null
&gt;     cat $r/state 2&gt;/dev/null
&gt; 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

</code></pre>
<p dir="auto">然后再调试boot0，这个调试过程中我发现系统原先默认的PMU接口是PL0 PL1，但是实际上我这个T113S3并没有引出这两脚，所以只能强行更改</p>
<p dir="auto">但是 改完了以后 也不知道这个系统怎么操作pmu的似乎死活就是连接不上<br />
，所以我直接不改了既然有完整的BOOT0代码，那么直接在boot0里面加自己程序就是最简单的，所以我就直接把自己程序加在里面了</p>
<p dir="auto">lichee/brandy-2.0/spl/nboot/main/boot0_main.c</p>
<pre><code>/*
 * (C) Copyright 2018
* SPDX-License-Identifier:	GPL-2.0+
 * wangwei &lt;wangwei@allwinnertech.com&gt;
 */

 /*
 * 当前测试用：
 * PB4 / PB5 / TWI1
 *
 * normal_gpio_cfg 字段大概是：
 * { port, port_num, mul_sel, pull, drv_level, data, reserved[0] }
 *
 * port = 2      -&gt; PB
 * port_num = 4  -&gt; PB4
 * port_num = 5  -&gt; PB5
 * mul_sel = 2   -&gt; TWI0 复用，先按这个测
 * pull = 1      -&gt; 上拉
 * reserved[0]=0 -&gt; TWI0 bus
 */

#include &lt;common.h&gt;
#include &lt;private_boot0.h&gt;
#include &lt;private_uboot.h&gt;
#include &lt;private_toc.h&gt;
#include &lt;arch/clock.h&gt;
#include &lt;arch/uart.h&gt;
#include &lt;arch/dram.h&gt;
#include &lt;arch/rtc.h&gt;
#include &lt;arch/gpio.h&gt;

#include &lt;arch/pmic_bus.h&gt;
#include &lt;arch/axp1530_reg.h&gt;

#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 &lt;&lt; 0)
#define AXP313A_DCDC2_EN        (1 &lt;&lt; 1)
#define AXP313A_DCDC3_EN        (1 &lt;&lt; 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 &lt;&lt; 0)
#define LEO_DCDC3_EN        (1 &lt;&lt; 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 &gt;&gt; 8) &amp; 0xf,
        //        data,
        //        (data &gt;&gt; 10) &amp; 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,
                            &amp;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,
                            &amp;val);
        printf("LEO: read DCDC1 0x13 ret=%d val=0x%x\n", ret, val);

        ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
                            AXP1530_DC3OUT_VOL,
                            &amp;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,
                        &amp;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,
                            &amp;out);
        //printf("LEO: read output before enable ret=%d val=0x%x\n", ret, out);
        if (ret)
                return;

        out |= (1 &lt;&lt; 0);   /* DCDC1 enable */
        out |= (1 &lt;&lt; 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,
                            &amp;out);
        //printf("LEO: output after ret=%d val=0x%x\n", ret, out);

        ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
                            AXP1530_DC1OUT_VOL,
                            &amp;val);
        //printf("LEO: DCDC1 after ret=%d val=0x%x\n", ret, val);

        ret = pmic_bus_read(AXP1530_RUNTIME_ADDR,
                            AXP1530_DC3OUT_VOL,
                            &amp;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(&amp;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(&amp;uboot_base, &amp;optee_base, &amp;monitor_base, &amp;rtos_base, &amp;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-&gt;secureos_base = optee_base;
		monitor_head-&gt;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-&gt;boot_data.boot_package_size = toc1_head-&gt;valid_len;
	header-&gt;boot_data.dram_scan_size = dram_size;
	memcpy((void *)header-&gt;boot_data.dram_para, &amp;BT0_head.prvt_head.dram_para, 32 * sizeof(int));

	if (monitor_base)
		header-&gt;boot_data.monitor_exist = 1;
	if (optee_base)
		header-&gt;boot_data.secureos_exist = 1;
#ifndef CONFIG_RISCV
	header-&gt;boot_data.func_mask |= get_uboot_func_mask(UBOOT_FUNC_MASK_ALL);
#endif
	update_flash_para(uboot_base);

	header-&gt;boot_data.pmu_type = pmu_type;
	header-&gt;boot_data.uart_input = uart_input;
	header-&gt;boot_data.key_input = key_input;
	header-&gt;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;
}

</code></pre>
<p dir="auto">还需要改的是i2c.c<br />
/lichee/brandy-2.0/spl/drivers/i2c.c</p>
<pre><code>/*
 * (C) Copyright 2016
* SPDX-License-Identifier:	GPL-2.0+
 *Allwinner Technology Co., Ltd. &lt;www.allwinnertech.com&gt;
 *weidonghui &lt;weidonghui@allwinnertech.com&gt;
 *
 */

#include &lt;common.h&gt;
#include &lt;errno.h&gt;
#include &lt;asm/io.h&gt;
#include &lt;arch/i2c.h&gt;
#include &lt;arch/gpio.h&gt;
#include &lt;arch/clock.h&gt;
#include &lt;private_boot0.h&gt;

#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-&gt;addr  :\t0x%x:0x%x\n", &amp;i2c-&gt;addr, i2c-&gt;addr);
	i2c_info("i2c-&gt;xaddr :\t0x%x:0x%x\n", &amp;i2c-&gt;xaddr, i2c-&gt;xaddr);
	i2c_info("i2c-&gt;data  :\t0x%x:0x%x\n", &amp;i2c-&gt;data, i2c-&gt;data);
	i2c_info("i2c-&gt;ctl   :\t0x%x:0x%x\n", &amp;i2c-&gt;ctl, i2c-&gt;ctl);
	i2c_info("i2c-&gt;status:\t0x%x:0x%x\n", &amp;i2c-&gt;status, i2c-&gt;status);
	i2c_info("i2c-&gt;clk   :\t0x%x:0x%x\n", &amp;i2c-&gt;clk, i2c-&gt;clk);
	i2c_info("i2c-&gt;srst  :\t0x%x:0x%x\n", &amp;i2c-&gt;srst, i2c-&gt;srst);
	i2c_info("i2c-&gt;eft   :\t0x%x:0x%x\n", &amp;i2c-&gt;eft, i2c-&gt;eft);
	i2c_info("i2c-&gt;lcr   :\t0x%x:0x%x\n", &amp;i2c-&gt;lcr, i2c-&gt;lcr);
	i2c_info("i2c-&gt;dvfs  :\t0x%x:0x%x\n", &amp;i2c-&gt;dvfs, i2c-&gt;dvfs);

}
static __s32 i2c_sendbyteaddr(__u32 byteaddr)
{
	__s32 time = 0xffff;
	__u32 tmp_val;

	i2c-&gt;data = byteaddr &amp; 0xff;
	i2c-&gt;ctl |= (0x01 &lt;&lt; 3); /*write 1 to clean int flag*/

	while ((time--) &amp;&amp; (!(i2c-&gt;ctl &amp; 0x08)))
		;
	if (time &lt;= 0) {
		return -I2C_NOK_TOUT;
	}

	tmp_val = i2c-&gt;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-&gt;eft  = 0;
	//leo tmp
	//i2c-&gt;srst = 1;
	i2c-&gt;ctl  |= TWI_CTL_STA;

	while ((time--) &amp;&amp; (!(i2c-&gt;ctl &amp; TWI_CTL_INTFLG)))
		;
	if (time &lt;= 0) {
		return -I2C_NOK_TOUT;
	}

	tmp_val = i2c-&gt;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 &amp;= 1;
	i2c-&gt;data = ((saddr &amp; 0xff) &lt;&lt; 1) | rw;
	i2c-&gt;ctl |= TWI_CTL_INTFLG; /*write 1 to clean int flag*/
	while ((time--) &amp;&amp; (!(i2c-&gt;ctl &amp; TWI_CTL_INTFLG)))
		;
	if (time &lt;= 0) {
		// printf("LEO: sendslave timeout addr=0x%x rw=%d ctl=0x%x status=0x%x\n",
        //       saddr, rw, i2c-&gt;ctl, i2c-&gt;status);
		return -I2C_NOK_TOUT;
	}

	tmp_val = i2c-&gt;status;
	//printf("LEO: sendslave addr=0x%x rw=%d data=0x%x status=0x%x ctl=0x%x\n",
    //       saddr, rw, i2c-&gt;data, tmp_val, i2c-&gt;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-&gt;ctl;

	tmp_val |= 0x20;
	i2c-&gt;ctl = tmp_val;

	while ((time--) &amp;&amp; (!(i2c-&gt;ctl &amp; 0x08)))
		;
	if (time &lt;= 0) {
		return -I2C_NOK_TOUT;
	}

	tmp_val = i2c-&gt;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-&gt;ctl |= (0x01 &lt;&lt; 4);
	i2c-&gt;ctl |= (0x01 &lt;&lt; 3);
	while ((time--) &amp;&amp; (i2c-&gt;ctl &amp; 0x10))
		;
	if (time &lt;= 0) {
		return -I2C_NOK_TOUT;
	}
	time = 0xffff;
	while ((time--) &amp;&amp; (i2c-&gt;status != I2C_READY))
		;
	tmp_val = i2c-&gt;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-&gt;ctl |= (0x01 &lt;&lt; 3);
		while ((time--) &amp;&amp; (!(i2c-&gt;ctl &amp; 0x08)))
			;
		if (time &lt;= 0) {
			return -I2C_NOK_TOUT;
		}
		for (time = 0; time &lt; 100; time++)
			;
		*data_addr = i2c-&gt;data;

		tmp_val = i2c-&gt;status;
		if (tmp_val != I2C_DATAREAD_NACK) {
			return -I2C_DATAREAD_NACK;
		}
	} else {
		for (i = 0; i &lt; data_count - 1; i++) {
			time = 0xffff;
			/*host should send ack every time when a data packet finished*/
			tmp_val = i2c-&gt;ctl | (0x01 &lt;&lt; 2);
			tmp_val = i2c-&gt;ctl | (0x01 &lt;&lt; 3);
			tmp_val |= 0x04;
			i2c-&gt;ctl = tmp_val;
			/*i2c-&gt;ctl |=(0x01&lt;&lt;3);*/

			while ((time--) &amp;&amp; (!(i2c-&gt;ctl &amp; 0x08)))
				;
			if (time &lt;= 0) {
				return -I2C_NOK_TOUT;
			}
			for (time = 0; time &lt; 100; time++)
				;
			time	 = 0xffff;
			data_addr[i] = i2c-&gt;data;
			while ((time--) &amp;&amp; (i2c-&gt;status != I2C_DATAREAD_ACK))
				;
			if (time &lt;= 0) {
				return -I2C_NOK_TOUT;
			}
		}

		time = 0xffff;
		i2c-&gt;ctl &amp;= 0xFb; /*the last data packet,not send ack*/
		i2c-&gt;ctl |= (0x01 &lt;&lt; 3);
		while ((time--) &amp;&amp; (!(i2c-&gt;ctl &amp; 0x08)))
			;
		if (time &lt;= 0) {
			return -I2C_NOK_TOUT;
		}
		for (time = 0; time &lt; 100; time++)
			;
		data_addr[data_count - 1] = i2c-&gt;data;
		while ((time--) &amp;&amp; (i2c-&gt;status != I2C_DATAREAD_NACK))
			;
		if (time &lt;= 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 &gt;= 3) {
		addrlen = 2;
	} else if (alen &lt;= 1) {
		addrlen = 0;
	} else {
		addrlen = 1;
	}
	slave_reg = (char *)&amp;addr;

	for (i = addrlen; i &gt;= 0; i--) {
		ret = i2c_sendbyteaddr(slave_reg[i] &amp; 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 &lt; data_count; i++) {
		time      = 0xffff;
		i2c-&gt;data = data_addr[i];
#if defined(CONFIG_ARCH_SUN5I) || defined(CONFIG_ARCH_SUN7I)
		i2c-&gt;ctl &amp;= 0xF7;
#else
		i2c-&gt;ctl |= (0x01 &lt;&lt; 3);
#endif
		while ((time--) &amp;&amp; (!(i2c-&gt;ctl &amp; 0x08)))
			;
		if (time &lt;= 0) {
			return -I2C_NOK_TOUT;
		}
		time = 0xffff;
		while ((time--) &amp;&amp; (i2c-&gt;status != I2C_DATAWRITE_ACK)) {
			;
		}
		if (time &lt;= 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 &gt;= 3) {
		addrlen = 2;
	} else if (alen &lt;= 1) {
		addrlen = 0;
	} else {
		addrlen = 1;
	}
	slave_reg = (char *)&amp;addr;
	for (i = addrlen; i &gt;= 0; i--) {
		ret = i2c_sendbyteaddr(slave_reg[i] &amp; 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, &amp;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-&gt;srst = 1;
	while ((i2c-&gt;srst) &amp;&amp; (i)) {
		i--;
	}
	if ((i2c-&gt;lcr &amp; 0x30) != 0x30) {
		/* toggle I2C SCL and SDA until bus idle */
		i2c-&gt;lcr = 0x05;
		udelay(500);
		i = 10;
		while ((i &gt; 0) &amp;&amp; ((i2c-&gt;lcr &amp; 0x02) != 2)) {
			/*control scl and sda output high level*/
			i2c-&gt;lcr |= 0x08;
			i2c-&gt;lcr |= 0x02;
			udelay(1000);
			/*control scl and sda output low level*/
			i2c-&gt;lcr &amp;= ~0x08;
			i2c-&gt;lcr &amp;= ~0x02;
			udelay(1000);
			i--;
		}
		i2c-&gt;lcr = 0x0;
		udelay(500);
	}
	speed /= 1000; /*khz*/

	if (speed &lt; 100)
		speed = 100;
	else if (speed &gt; 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 &lt; clk_n; ++i)
		pow_2_clk_n *= 2;
	clk_m = (24000 / 10) / (pow_2_clk_n * speed) - 1;


	i2c-&gt;clk = (clk_m &lt;&lt; 3) | clk_n;
	i2c-&gt;ctl |= 0x40;
	i2c-&gt;eft = 0;
	i2c_debug();
	//printf("LEO: final lcr=0x%x lcr&amp;0x30=0x%x\n",
    //    i2c-&gt;lcr, i2c-&gt;lcr &amp; 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 &lt;= 5) {
#if defined(CONFIG_SUNXI_VERSION1)
		if (onoff) {
			//de-assert
			reg_value = readl(&amp;ccm-&gt;apb2_reset_cfg);
			reg_value |= (1 &lt;&lt; bus_num);
			writel(reg_value, &amp;ccm-&gt;apb2_reset_cfg);

			//gating clock pass
			reg_value = readl(&amp;ccm-&gt;apb2_gate);
			reg_value &amp;= ~(1 &lt;&lt; bus_num);
			writel(reg_value, &amp;ccm-&gt;apb2_gate);
			mdelay(1);
			reg_value |= (1 &lt;&lt; bus_num);
			writel(reg_value, &amp;ccm-&gt;apb2_gate);
		} else {
			//gating clock mask
			reg_value = readl(&amp;ccm-&gt;apb2_gate);
			reg_value &amp;= ~(1 &lt;&lt; bus_num);
			writel(reg_value, &amp;ccm-&gt;apb2_gate);

			//assert
			reg_value = readl(&amp;ccm-&gt;apb2_reset_cfg);
			reg_value &amp;= ~(1 &lt;&lt; bus_num);
			writel(reg_value, &amp;ccm-&gt;apb2_reset_cfg);
		}
#else
		if (onoff) {
			//de-assert
			reg_value = readl(&amp;ccm-&gt;twi_gate_reset);
			reg_value |= (1 &lt;&lt; (16 + bus_num));
			writel(reg_value, &amp;ccm-&gt;twi_gate_reset);

			//gating clock pass
			reg_value = readl(&amp;ccm-&gt;twi_gate_reset);
			reg_value &amp;= ~(1 &lt;&lt; bus_num);
			writel(reg_value, &amp;ccm-&gt;twi_gate_reset);
			mdelay(1);
			reg_value |= (1 &lt;&lt; bus_num);
			writel(reg_value, &amp;ccm-&gt;twi_gate_reset);
		} else {
			//gating clock mask
			reg_value = readl(&amp;ccm-&gt;twi_gate_reset);
			reg_value &amp;= ~(1 &lt;&lt; bus_num);
			writel(reg_value, &amp;ccm-&gt;twi_gate_reset);

			//assert
			reg_value = readl(&amp;ccm-&gt;twi_gate_reset);
			reg_value &amp;= ~(1 &lt;&lt; (16 + bus_num));
			writel(reg_value, &amp;ccm-&gt;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 &amp;= ~(1 &lt;&lt; (16 + r_bus_num));
			writel(reg_value, SUNXI_RTWI_BRG_REG);

			reg_value = readl(SUNXI_RTWI_BRG_REG);
			reg_value |= (1 &lt;&lt; (16 + r_bus_num));
			writel(reg_value, SUNXI_RTWI_BRG_REG);

			/*gating clock pass*/
			reg_value = readl(SUNXI_RTWI_BRG_REG);
			reg_value &amp;= ~(1 &lt;&lt; r_bus_num);
			writel(reg_value, SUNXI_RTWI_BRG_REG);
			mdelay(1);
			reg_value |= (1 &lt;&lt; r_bus_num);
			writel(reg_value, SUNXI_RTWI_BRG_REG);
		} else {
			/*gating clock mask*/
			reg_value = readl(SUNXI_RTWI_BRG_REG);
			reg_value &amp;= ~(1 &lt;&lt; r_bus_num);
			writel(reg_value, SUNXI_RTWI_BRG_REG);

			/*assert*/
			reg_value = readl(SUNXI_RTWI_BRG_REG);
			reg_value &amp;= ~(1 &lt;&lt; (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-&gt;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-&gt;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(&amp;ccm-&gt;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 &gt;&gt; 16) &amp; 0xf,
		(cfg0 &gt;&gt; 20) &amp; 0xf);

	printf("LEO: after gpio PB_PULL0=0x%x PB4_pull=%d PB5_pull=%d\n",
		pull0,
		(pull0 &gt;&gt; 8) &amp; 0x3,
		(pull0 &gt;&gt; 10) &amp; 0x3);

	printf("LEO: after gpio PB_DLEVEL0=0x%x PB4_drv=%d PB5_drv=%d\n",
		dlevel0,
		(dlevel0 &gt;&gt; 8) &amp; 0x3,
		(dlevel0 &gt;&gt; 10) &amp; 0x3);

	printf("LEO: after gpio PB_DATA=0x%x PB4=%d PB5=%d\n",
		data,
		(data &gt;&gt; 4) &amp; 1,
		(data &gt;&gt; 5) &amp; 1);
	
	
	 // 再开 TWI1 clock/reset。
	 
	sunxi_i2c_bus_setting(i2c_base, 1);

	printf("LEO: twi_gate_reset after=0x%x\n",
		readl(&amp;ccm-&gt;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-&gt;ctl,
	//	i2c-&gt;clk,
	//	i2c-&gt;srst,
	//	i2c-&gt;eft,
	//	i2c-&gt;status,
	//	i2c-&gt;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 &lt; 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;
	}
}

</code></pre>
<p dir="auto">改好以后boot0 那个pmu就不用管它了，反正自己的程序也能配置好AXP313</p>
<pre><code>[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.
</code></pre>
<p dir="auto">中间调试其实有很多坑，有问题的。。。都被我DEBUG掉了，反正这样就可以 了 哈哈哈</p>
]]></description><link>https://bbs.aw-ol.com/topic/7035/t113-axp313-调试记录</link><generator>RSS for Node</generator><lastBuildDate>Mon, 15 Jun 2026 18:53:48 GMT</lastBuildDate><atom:link href="https://bbs.aw-ol.com/topic/7035.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 10 Jun 2026 06:04:47 GMT</pubDate><ttl>60</ttl></channel></rss>