导航

    全志在线开发者论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 在线文档
    • 社区主页

    T113 AXP313 调试记录

    T Series
    1
    1
    21
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • L
      leomini5 LV 6 最后由 编辑

      之前玩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掉了,反正这样就可以 了 哈哈哈

      1 条回复 最后回复 回复 引用 分享 0
      • 1 / 1
      • First post
        Last post

      Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

      行为准则 | 用户协议 | 隐私权政策