入手一块飞凌嵌入式 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);
}