手码-在U-boot SPL 移植新的PMIC芯片驱动

入手一块飞凌嵌入式 imx8mm开发板. 但是本人需要修改其显示分辨率, 但是飞凌嵌入式不提供其u-boot源码, 也不提供其显示驱动源码. 同时飞凌不提供安卓11镜像和源码

无奈,下载nxp官方源码, 自己找驱动源码,自行移植. 如何下载NXP源码, 如何在源码中配置uboot,参看上一篇文章.

以下为个人移植NXP官方u-boot到飞凌PCBA的过程, 如有侵犯厂家权利, 请联系删除

编译主机 Ubuntu-16.04.7-LTS, PMIC芯片为pca9450

在U-boot新增PMIC支持.

1, 新增PMIC驱动程序

A, 拷贝源码

将源码pca9450.c 拷贝到uboot-imx/drivers/power/pmic/文件夹下

~/android_build/vendor/nxp-opensource/uboot-imx/drivers/power/pmic/pca9450.c

将源码pmic_pca9450.c拷贝到uboot-imx/drivers/power/pmic/文件夹下

~/android_build/vendor/nxp-opensource/uboot-imx/drivers/power/pmic/pmic_pca9450.c

将pca9450.h头文件拷贝到/uboot-imx/include/power/文件夹

~/android_build/vendor/nxp-opensource/uboot-imx/include/power/pca9450.h

B,修改编译环境

修改Kconfig, 修改 PMIC驱动程序所在文件夹的Kconfig

~/android_build/vendor/nxp-opensource/uboot-imx/drivers/power/pmic/Kconfig

新增如下

config DM_PMIC_PCA9450

bool "Enable Driver Model for PMIC PCA9450"

depends on DM_PMIC

help

This config enables implementation of driver-model pmic uclass features

for PMIC PCA9450. The driver implements read/write operations.

修改Makefile, 修改 PMIC驱动程序所在文件夹的Makefile

~/android_build/vendor/nxp-opensource/uboot-imx/drivers/power/pmic/Makefile

新增如下

obj-$(CONFIG_$(SPL_)DM_PMIC_PCA9450) += pca9450.o

obj-$(CONFIG_POWER_PCA9450) += pmic_pca9450.o

2,修改imx8mm_evk.h

~/android_build/vendor/nxp-opensource/uboot-imx/include/configs/imx8mm_evk.h

#if 0

#define CONFIG_POWER_BD71837 //将原电源驱动程序注释掉

#else

#define CONFIG_POWER_PCA9450 //新增新电源驱动程序配置

#endif

3, 修改u-boot设备树.

~/android_build/vendor/nxp-opensource/uboot-imx/arch/arm/dts/fsl-imx8mm-ddr4-evk.dts

在fsl-imx8mm-ddr4-evk.dts中将原PMIC信息注释掉,新增PMIC pca9450.

代码改动很多,&i2c1 模块所有代码如下:

&i2c1 {
	clock-frequency = <400000>;
	pinctrl-names = "default", "gpio";
	pinctrl-0 = <&pinctrl_i2c1>;
	pinctrl-1 = <&pinctrl_i2c1_gpio>;
	scl-gpios = <&gpio5 14 GPIO_ACTIVE_HIGH>;
	sda-gpios = <&gpio5 15 GPIO_ACTIVE_HIGH>;
	status = "okay";

#if 0				//原PMIC代码不编译
	pmic: bd71837@4b {
		reg = <0x4b>;
		compatible = "rohm,bd71837";
		/* PMIC BD71837 PMIC_nINT GPIO1_IO3 */
		pinctrl-0 = <&pinctrl_pmic>;
		gpio_intr = <&gpio1 3 GPIO_ACTIVE_LOW>;

		gpo {
			rohm,drv = <0x0C>;	/* 0b0000_1100 all gpos with cmos output mode */
		};

		regulators {
			#address-cells = <1>;
			#size-cells = <0>;

			bd71837,pmic-buck2-uses-i2c-dvs;
			bd71837,pmic-buck2-dvs-voltage = <1000000>, <900000>, <0>; /* VDD_ARM: Run-Idle */

			buck1_reg: regulator@0 {
				reg = <0>;
				regulator-compatible = "buck1";
				regulator-min-microvolt = <700000>;
				regulator-max-microvolt = <1300000>;
				regulator-boot-on;
				regulator-always-on;
				regulator-ramp-delay = <1250>;
			};

			buck2_reg: regulator@1 {
				reg = <1>;
				regulator-compatible = "buck2";
				regulator-min-microvolt = <700000>;
				regulator-max-microvolt = <1300000>;
				regulator-boot-on;
				regulator-always-on;
				regulator-ramp-delay = <1250>;
			};

			buck3_reg: regulator@2 {
				reg = <2>;
				regulator-compatible = "buck3";
				regulator-min-microvolt = <700000>;
				regulator-max-microvolt = <1300000>;
			};

			buck4_reg: regulator@3 {
				reg = <3>;
				regulator-compatible = "buck4";
				regulator-min-microvolt = <700000>;
				regulator-max-microvolt = <1300000>;
			};

			buck5_reg: regulator@4 {
				reg = <4>;
				regulator-compatible = "buck5";
				regulator-min-microvolt = <700000>;
				regulator-max-microvolt = <1350000>;
				regulator-boot-on;
				regulator-always-on;
			};

			buck6_reg: regulator@5 {
				reg = <5>;
				regulator-compatible = "buck6";
				regulator-min-microvolt = <3000000>;
				regulator-max-microvolt = <3300000>;
				regulator-boot-on;
				regulator-always-on;
			};

			buck7_reg: regulator@6 {
				reg = <6>;
				regulator-compatible = "buck7";
				regulator-min-microvolt = <1605000>;
				regulator-max-microvolt = <1995000>;
				regulator-boot-on;
				regulator-always-on;
			};

			buck8_reg: regulator@7 {
				reg = <7>;
				regulator-compatible = "buck8";
				regulator-min-microvolt = <800000>;
				regulator-max-microvolt = <1400000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo1_reg: regulator@8 {
				reg = <8>;
				regulator-compatible = "ldo1";
				regulator-min-microvolt = <3000000>;
				regulator-max-microvolt = <3300000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo2_reg: regulator@9 {
				reg = <9>;
				regulator-compatible = "ldo2";
				regulator-min-microvolt = <900000>;
				regulator-max-microvolt = <900000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo3_reg: regulator@10 {
				reg = <10>;
				regulator-compatible = "ldo3";
				regulator-min-microvolt = <1800000>;
				regulator-max-microvolt = <3300000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo4_reg: regulator@11 {
				reg = <11>;
				regulator-compatible = "ldo4";
				regulator-min-microvolt = <900000>;
				regulator-max-microvolt = <1800000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo5_reg: regulator@12 {
				reg = <12>;
				regulator-compatible = "ldo5";
				regulator-min-microvolt = <1800000>;
				regulator-max-microvolt = <3300000>;
			};

			ldo6_reg: regulator@13 {
				reg = <13>;
				regulator-compatible = "ldo6";
				regulator-min-microvolt = <900000>;
				regulator-max-microvolt = <1800000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo7_reg: regulator@14 {
				reg = <14>;
				regulator-compatible = "ldo7";
				regulator-min-microvolt = <1800000>;
				regulator-max-microvolt = <3300000>;
			};
		};
	};
#else				//编译新的pmic设备树代码
	pmic: pca9450@25 {
		reg = <0x25>;
		compatible = "nxp,pca9450";
		/* PMIC PCA9450 PMIC_nINT GPIO1_IO3 */
		pinctrl-0 = <&pinctrl_pmic>;
		gpio_intr = <&gpio1 3 GPIO_ACTIVE_LOW>;

		gpo {
			nxp,drv = <0x0C>;       /* 0b0000_1100 all gpos with cmos output mode */
		};

		regulators {
			#address-cells = <1>;
			#size-cells = <0>;

			pca9450,pmic-buck2-uses-i2c-dvs;
			pca9450,pmic-buck2-dvs-voltage = <1000000>, <900000>, <0>; /* VDD_ARM: Run-Idle */

			buck1_reg: regulator@0 {
				reg = <0>;
				regulator-compatible = "buck1";
				regulator-min-microvolt = <600000>;
				regulator-max-microvolt = <2187500>;
				regulator-boot-on;
				regulator-always-on;
				regulator-ramp-delay = <3125>;
			};

			buck2_reg: regulator@1 {
				reg = <1>;
				regulator-compatible = "buck2";
				regulator-min-microvolt = <600000>;
				regulator-max-microvolt = <2187500>;
				regulator-boot-on;
				regulator-always-on;
				regulator-ramp-delay = <3125>;
			};

			buck3_reg: regulator@2 {
				reg = <2>;
				regulator-compatible = "buck3";
				regulator-min-microvolt = <600000>;
				regulator-max-microvolt = <2187500>;
				regulator-boot-on;
				regulator-always-on;
			};

			buck4_reg: regulator@3 {
				reg = <3>;
				regulator-compatible = "buck4";
				regulator-min-microvolt = <600000>;
				regulator-max-microvolt = <3400000>;
				regulator-boot-on;
				regulator-always-on;
			};

			buck5_reg: regulator@4 {
				reg = <4>;
				regulator-compatible = "buck5";
				regulator-min-microvolt = <600000>;
				regulator-max-microvolt = <3400000>;
				regulator-boot-on;
				regulator-always-on;
			};

			buck6_reg: regulator@5 {
				reg = <5>;
				regulator-compatible = "buck6";
				regulator-min-microvolt = <600000>;
				regulator-max-microvolt = <3400000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo1_reg: regulator@6 {
				reg = <6>;
				regulator-compatible = "ldo1";
				regulator-min-microvolt = <1600000>;
				regulator-max-microvolt = <3300000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo2_reg: regulator@7 {
				reg = <7>;
				regulator-compatible = "ldo2";
				regulator-min-microvolt = <800000>;
				regulator-max-microvolt = <1150000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo3_reg: regulator@8 {
				reg = <8>;
				regulator-compatible = "ldo3";
				regulator-min-microvolt = <800000>;
				regulator-max-microvolt = <3300000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo4_reg: regulator@9 {
				reg = <9>;
				regulator-compatible = "ldo4";
				regulator-min-microvolt = <800000>;
				regulator-max-microvolt = <3300000>;
				regulator-boot-on;
				regulator-always-on;
			};

			ldo5_reg: regulator@10 {
				reg = <10>;
				regulator-compatible = "ldo5";
				regulator-min-microvolt = <1800000>;
				regulator-max-microvolt = <3300000>;
			};
		};
	};
#endif
};

4, 修改spl.c

删除原有PMIC程序, 添加pca9450的代码.

~/android_build/vendor/nxp-opensource/uboot-imx/board/freescale/imx8mm_evk/spl.c

/*
 * Copyright 2018-2019 NXP
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#if 1   //add by cym 20201120
#define CONFIG_PCA9450
#endif


#include <common.h>
#include <spl.h>
#include <asm/io.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/mach-imx/iomux-v3.h>
#include <asm/arch/imx8mm_pins.h>
#include <asm/arch/sys_proto.h>
#include <power/pmic.h>


#include <power/pca9450.h>

#include <asm/arch/clock.h>
#include <asm/mach-imx/gpio.h>
#include <asm/mach-imx/mxc_i2c.h>
#include <fsl_esdhc.h>
#include <mmc.h>
#include <asm/arch/imx8m_ddr.h>

DECLARE_GLOBAL_DATA_PTR;

void spl_dram_init(void)
{
	ddr_init(&dram_timing);
}

#define I2C_PAD_CTRL	(PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | PAD_CTL_PE)
#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
struct i2c_pads_info i2c_pad_info1 = {
	.scl = {
		.i2c_mode = IMX8MM_PAD_I2C1_SCL_I2C1_SCL | PC,
		.gpio_mode = IMX8MM_PAD_I2C1_SCL_GPIO5_IO14 | PC,
		.gp = IMX_GPIO_NR(5, 14),
	},
	.sda = {
		.i2c_mode = IMX8MM_PAD_I2C1_SDA_I2C1_SDA | PC,
		.gpio_mode = IMX8MM_PAD_I2C1_SDA_GPIO5_IO15 | PC,
		.gp = IMX_GPIO_NR(5, 15),
	},
};

#define USDHC2_CD_GPIO	IMX_GPIO_NR(2, 18)
#define USDHC2_PWR_GPIO IMX_GPIO_NR(2, 19)

#define USDHC_PAD_CTRL	(PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE |PAD_CTL_PE | \
			 PAD_CTL_FSEL2)
#define USDHC_GPIO_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_DSE1)

static iomux_v3_cfg_t const usdhc3_pads[] = {
	IMX8MM_PAD_NAND_WE_B_USDHC3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_NAND_WP_B_USDHC3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_NAND_DATA04_USDHC3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_NAND_DATA05_USDHC3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_NAND_DATA06_USDHC3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_NAND_DATA07_USDHC3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_NAND_RE_B_USDHC3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_NAND_CE2_B_USDHC3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_NAND_CE3_B_USDHC3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_NAND_CLE_USDHC3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
};

static iomux_v3_cfg_t const usdhc2_pads[] = {
	IMX8MM_PAD_SD2_CLK_USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_SD2_CMD_USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_SD2_DATA0_USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_SD2_DATA1_USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_SD2_DATA2_USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_SD2_DATA3_USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
	IMX8MM_PAD_SD2_RESET_B_GPIO2_IO19 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL),
};

/*
 * The evk board uses DAT3 to detect CD card plugin,
 * in u-boot we mux the pin to GPIO when doing board_mmc_getcd.
 */
static iomux_v3_cfg_t const usdhc2_cd_pad =
	IMX8MM_PAD_SD2_DATA3_GPIO2_IO18 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL);

static iomux_v3_cfg_t const usdhc2_dat3_pad =
	IMX8MM_PAD_SD2_DATA3_USDHC2_DATA3 |
	MUX_PAD_CTRL(USDHC_PAD_CTRL);


static struct fsl_esdhc_cfg usdhc_cfg[2] = {
	{USDHC2_BASE_ADDR, 0, 1},
	{USDHC3_BASE_ADDR, 0, 1},
};

int board_mmc_init(bd_t *bis)
{
	int i, ret;
	/*
	 * According to the board_mmc_init() the following map is done:
	 * (U-Boot device node)    (Physical Port)
	 * mmc0                    USDHC1
	 * mmc1                    USDHC2
	 */
	for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
		switch (i) {
		case 0:
			usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
			imx_iomux_v3_setup_multiple_pads(
				usdhc2_pads, ARRAY_SIZE(usdhc2_pads));
			gpio_request(USDHC2_PWR_GPIO, "usdhc2_reset");
			gpio_direction_output(USDHC2_PWR_GPIO, 0);
			udelay(500);
			gpio_direction_output(USDHC2_PWR_GPIO, 1);
			break;
		case 1:
			usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
			imx_iomux_v3_setup_multiple_pads(
				usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
			break;
		default:
			printf("Warning: you configured more USDHC controllers"
				"(%d) than supported by the board\n", i + 1);
			return -EINVAL;
		}

		ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
		if (ret)
			return ret;
	}

	return 0;
}

int board_mmc_getcd(struct mmc *mmc)
{
	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
	int ret = 0;

	switch (cfg->esdhc_base) {
	case USDHC3_BASE_ADDR:
		ret = 1;
		break;
	case USDHC2_BASE_ADDR:
		imx_iomux_v3_setup_pad(usdhc2_cd_pad);
		gpio_request(USDHC2_CD_GPIO, "usdhc2 cd");
		gpio_direction_input(USDHC2_CD_GPIO);

		/*
		 * Since it is the DAT3 pin, this pin is pulled to
		 * low voltage if no card
		 */
		ret = gpio_get_value(USDHC2_CD_GPIO);

		imx_iomux_v3_setup_pad(usdhc2_dat3_pad);
		return ret;
	}

	return 1;
}

#ifdef CONFIG_POWER
#define I2C_PMIC	0
int power_init_board(void)
{
        struct pmic *p;
        int ret;

        ret = power_pca9450_init(I2C_PMIC);
        if (ret)
                printf("power init failed");

        p = pmic_get("PCA9450");
        pmic_probe(p);

        /* BUCKxOUT_DVS0/1 control BUCK123 output */
        pmic_reg_write(p, PCA9450_BUCK123_DVS, 0x29);

        /* Buck 1 DVS control through PMIC_STBY_REQ */
        pmic_reg_write(p, PCA9450_BUCK1CTRL, 0x59);

        /* decrease RESET key long push time from the default 10s to 10ms */
        /* Ton_Deb of PCA9450 is 20ms and don't change */

        /* increase VDD_SOC to typical value 0.85v before first DRAM access */
        /* pmic_reg_write(p, PCA9450_BUCK1OUT_DVS0, 0x14); */
        pmic_reg_write(p, PCA9450_BUCK1OUT_DVS0, 0x14);
        pmic_reg_write(p, PCA9450_BUCK1OUT_DVS1, 0x10);

        /* increase VDD_DRAM to 0.975v for 3Ghz DDR -> 0.95V instead of 0.975V, */
        /* because PCA9450 Buck3 can set 0.95V */
        /* Also, set B3_ENMODE=2 (ON by PMIC_ON_REQ=H & PMIC_STBY_REQ=L) */
        pmic_reg_write(p, PCA9450_BUCK3OUT_DVS0, 0x1C);
        pmic_reg_write(p, PCA9450_BUCK3CTRL, 0x4A);

        /* set VDD_SNVS_0V8 from default 0.85V */
        pmic_reg_write(p, PCA9450_LDO2CTRL, 0xC0);

#ifndef CONFIG_IMX8M_LPDDR4
        /* increase NVCC_DRAM_1V2 to 1.2v for DDR4 */
        pmic_reg_write(p, PCA9450_BUCK6OUT, 0x18);
#endif

        /* set WDOG_B_CFG to 10b=Cold Reset, except LDO1/2 */
        //pmic_reg_write(p, PCA9450_RESET_CTRL, 0xA1);
	pmic_reg_write(p, PCA9450_RESET_CTRL, 0x21);

        return 0;
}

#endif

void spl_board_init(void)
{
#ifndef CONFIG_SPL_USB_SDP_SUPPORT
	/* Serial download mode */
	if (is_usb_boot()) {
		puts("Back to ROM, SDP\n");
		restore_boot_params();
	}
#endif
	puts("Normal Boot\n");
}

#ifdef CONFIG_SPL_LOAD_FIT
int board_fit_config_name_match(const char *name)
{
	/* Just empty function now - can't decide what to choose */
	debug("%s: %s\n", __func__, name);

	return 0;
}
#endif

void board_init_f(ulong dummy)
{
	int ret;

	/* Clear the BSS. */
	memset(__bss_start, 0, __bss_end - __bss_start);

	arch_cpu_init();

	board_early_init_f();

	timer_init();

	preloader_console_init();

	ret = spl_init();
	if (ret) {
		debug("spl_init() failed: %d\n", ret);
		hang();
	}

	enable_tzc380();

	/* Adjust pmic voltage to 1.0V for 800M */
	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);

	power_init_board();

	/* DDR initialization */
	spl_dram_init();

	board_init_r(NULL, 0);
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值