T113 AXP313 调试记录
-
之前玩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掉了,反正这样就可以 了 哈哈哈
Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号