mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 13:43:28 +00:00
board: purism: add the Purism Librem5 phone
Initial commit of Librem5 u-boot and SPL Signed-off-by: Angus Ainslie <angus@akkea.ca> Co-developed-by: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm> Signed-off-by: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm> Reviewed-by: Fabio Estevam <festevam@denx.de>
This commit is contained in:
parent
1f650d9ec6
commit
466a9ea2a1
19 changed files with 5400 additions and 1 deletions
|
@ -974,7 +974,8 @@ dtb-$(CONFIG_ARCH_IMX8M) += \
|
|||
imx8mp-venice-gw74xx.dtb \
|
||||
imx8mp-verdin-wifi-dev.dtb \
|
||||
imx8mq-pico-pi.dtb \
|
||||
imx8mq-kontron-pitx-imx8m.dtb
|
||||
imx8mq-kontron-pitx-imx8m.dtb \
|
||||
imx8mq-librem5-r4.dtb
|
||||
|
||||
dtb-$(CONFIG_ARCH_IMX9) += \
|
||||
imx93-11x11-evk.dtb
|
||||
|
|
24
arch/arm/dts/imx8mq-librem5-r4-u-boot.dtsi
Normal file
24
arch/arm/dts/imx8mq-librem5-r4-u-boot.dtsi
Normal file
|
@ -0,0 +1,24 @@
|
|||
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
|
||||
#include "imx8mq-u-boot.dtsi"
|
||||
|
||||
&pinctrl_uart1 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&uart1 { /* console */
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&binman {
|
||||
/delete-node/ signed-hdmi;
|
||||
|
||||
signed-hdmi {
|
||||
filename = "signed_hdmi.bin";
|
||||
|
||||
signed-dp-imx8m {
|
||||
filename = "signed_dp_imx8m.bin";
|
||||
type = "blob-ext";
|
||||
};
|
||||
};
|
||||
};
|
35
arch/arm/dts/imx8mq-librem5-r4.dts
Normal file
35
arch/arm/dts/imx8mq-librem5-r4.dts
Normal file
|
@ -0,0 +1,35 @@
|
|||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
// Copyright (C) 2020 Purism SPC <kernel@puri.sm>
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "imx8mq-librem5.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Purism Librem 5r4";
|
||||
compatible = "purism,librem5r4", "purism,librem5", "fsl,imx8mq";
|
||||
};
|
||||
|
||||
&accel_gyro {
|
||||
mount-matrix = "1", "0", "0",
|
||||
"0", "1", "0",
|
||||
"0", "0", "-1";
|
||||
};
|
||||
|
||||
&bat {
|
||||
maxim,rsns-microohm = <1667>;
|
||||
};
|
||||
|
||||
&bq25895 {
|
||||
ti,battery-regulation-voltage = <4200000>; /* uV */
|
||||
ti,charge-current = <1500000>; /* uA */
|
||||
ti,termination-current = <144000>; /* uA */
|
||||
};
|
||||
|
||||
&led_backlight {
|
||||
led-max-microamp = <25000>;
|
||||
};
|
||||
|
||||
&proximity {
|
||||
proximity-near-level = <10>;
|
||||
};
|
1255
arch/arm/dts/imx8mq-librem5.dtsi
Normal file
1255
arch/arm/dts/imx8mq-librem5.dtsi
Normal file
File diff suppressed because it is too large
Load diff
|
@ -269,6 +269,14 @@ config TARGET_IMX8MP_RSB3720A1_6G
|
|||
select IMX8MP
|
||||
select SUPPORT_SPL
|
||||
select IMX8M_LPDDR4
|
||||
|
||||
config TARGET_LIBREM5
|
||||
bool "Purism Librem5 Phone"
|
||||
select BINMAN
|
||||
select IMX8MQ
|
||||
select SUPPORT_SPL
|
||||
select IMX8M_LPDDR4
|
||||
|
||||
endchoice
|
||||
|
||||
source "board/advantech/imx8mp_rsb3720a1/Kconfig"
|
||||
|
@ -290,6 +298,7 @@ source "board/kontron/sl-mx8mm/Kconfig"
|
|||
source "board/menlo/mx8menlo/Kconfig"
|
||||
source "board/phytec/phycore_imx8mm/Kconfig"
|
||||
source "board/phytec/phycore_imx8mp/Kconfig"
|
||||
source "board/purism/librem5/Kconfig"
|
||||
source "board/ronetix/imx8mq-cm/Kconfig"
|
||||
source "board/technexion/pico-imx8mq/Kconfig"
|
||||
source "board/variscite/imx8mn_var_som/Kconfig"
|
||||
|
|
15
board/purism/librem5/Kconfig
Normal file
15
board/purism/librem5/Kconfig
Normal file
|
@ -0,0 +1,15 @@
|
|||
if TARGET_LIBREM5
|
||||
|
||||
config SYS_BOARD
|
||||
default "librem5"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "purism"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "librem5"
|
||||
|
||||
config IMX_CONFIG
|
||||
default "board/purism/librem5/imximage-8mq-lpddr4.cfg"
|
||||
|
||||
endif
|
8
board/purism/librem5/MAINTAINERS
Normal file
8
board/purism/librem5/MAINTAINERS
Normal file
|
@ -0,0 +1,8 @@
|
|||
PURISM LIBREM5 PHONE
|
||||
M: Angus Ainslie <angus@akkea.ca>
|
||||
R: kernel@puri.sm
|
||||
S: Supported
|
||||
F: arch/arm/dts/imx8mq-librem5*
|
||||
F: board/purism/librem5/
|
||||
F: configs/librem5_defconfig
|
||||
F: include/configs/librem5.h
|
13
board/purism/librem5/Makefile
Normal file
13
board/purism/librem5/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Copyright 2017 NXP
|
||||
# Copyright 2019 Purism
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += librem5.o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-y += spl.o
|
||||
obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_timing.o lpddr4_timing_b0.o
|
||||
endif
|
9
board/purism/librem5/imximage-8mq-lpddr4.cfg
Normal file
9
board/purism/librem5/imximage-8mq-lpddr4.cfg
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2021 NXP
|
||||
*/
|
||||
|
||||
FIT
|
||||
BOOT_FROM sd
|
||||
SIGNED_HDMI signed_hdmi.bin
|
||||
LOADER u-boot-spl-ddr.bin 0x7E1000
|
425
board/purism/librem5/librem5.c
Normal file
425
board/purism/librem5/librem5.c
Normal file
|
@ -0,0 +1,425 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2018 NXP
|
||||
* Copyright 2021 Purism
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <miiphy.h>
|
||||
#include <asm/mach-imx/iomux-v3.h>
|
||||
#include <asm-generic/gpio.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <fsl_esdhc.h>
|
||||
#include <mmc.h>
|
||||
#include <asm/arch/imx8mq_pins.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/mach-imx/gpio.h>
|
||||
#include <asm/mach-imx/mxc_i2c.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/mach-imx/video.h>
|
||||
#include <fuse.h>
|
||||
#include <i2c.h>
|
||||
#include <spl.h>
|
||||
#include <usb.h>
|
||||
#include <dwc3-uboot.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <power/regulator.h>
|
||||
#include <usb/xhci.h>
|
||||
#include "librem5.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_LOAD_ENV_FROM_MMC_BOOT_PARTITION)
|
||||
uint board_mmc_get_env_part(struct mmc *mmc)
|
||||
{
|
||||
uint part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
|
||||
|
||||
if (part == 7)
|
||||
part = 0;
|
||||
return part;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tps65982_wait_for_app(int timeout, int timeout_step)
|
||||
{
|
||||
int ret;
|
||||
char response[6];
|
||||
struct udevice *udev, *bus;
|
||||
|
||||
log_debug("%s: starting\n", __func__);
|
||||
|
||||
/* Set the i2c bus */
|
||||
ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &bus);
|
||||
if (ret) {
|
||||
log_err("%s: No bus %d\n", __func__, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = i2c_get_chip(bus, 0x3f, 1, &udev);
|
||||
if (ret) {
|
||||
log_err("%s: setting chip offset failed %d\n", __func__, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (timeout > 0) {
|
||||
ret = dm_i2c_read(udev, 0x03, (u8 *)response, 5);
|
||||
log_debug("tps65982 mode %s\n", response);
|
||||
if (response[1] == 'A')
|
||||
return 0;
|
||||
mdelay(timeout_step);
|
||||
timeout -= timeout_step;
|
||||
log_debug("tps65982 waited %d ms %c\n", timeout_step, response[1]);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tps65982_clear_dead_battery(void)
|
||||
{
|
||||
int ret;
|
||||
char cmd[5] = "\04DBfg";
|
||||
struct udevice *udev, *bus;
|
||||
|
||||
log_debug("%s: starting\n", __func__);
|
||||
|
||||
/* Set the i2c bus */
|
||||
ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &bus);
|
||||
if (ret) {
|
||||
log_err("%s: No bus %d\n", __func__, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = i2c_get_chip(bus, 0x3f, 1, &udev);
|
||||
if (ret) {
|
||||
log_err("%s: setting chip offset failed %d\n", __func__, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* clearing the dead battery flag when not in dead battery condition
|
||||
* is a no-op, so there's no need to check if it's in effect
|
||||
*/
|
||||
ret = dm_i2c_write(udev, 0x08, cmd, 5);
|
||||
if (ret) {
|
||||
log_err("%s: writing 4CC command failed %d", __func__, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TPS_POWER_STATUS_PWROPMODE(x) FIELD_GET(GENMASK(3, 2), x)
|
||||
|
||||
#define TPS_PDO_CONTRACT_TYPE(x) FIELD_GET(GENMASK(31, 30), x)
|
||||
#define TPS_PDO_CONTRACT_FIXED 0
|
||||
#define TPS_PDO_CONTRACT_BATTERY 1
|
||||
#define TPS_PDO_CONTRACT_VARIABLE 2
|
||||
|
||||
#define TPS_TYPEC_PWR_MODE_USB 0
|
||||
#define TPS_TYPEC_PWR_MODE_1_5A 1
|
||||
#define TPS_TYPEC_PWR_MODE_3_0A 2
|
||||
#define TPS_TYPEC_PWR_MODE_PD 3
|
||||
|
||||
#define TPS_PDO_FIXED_CONTRACT_MAX_CURRENT(x) (FIELD_GET(GENMASK(9, 0), x) * 10)
|
||||
#define TPS_PDO_VAR_CONTRACT_MAX_CURRENT(x) (FIELD_GET(GENMASK(9, 0), x) * 10)
|
||||
#define TPS_PDO_BAT_CONTRACT_MAX_VOLTAGE(x) (FIELD_GET(GENMASK(29, 20), x) * 50)
|
||||
#define TPS_PDO_BAT_CONTRACT_MAX_POWER(x) (FIELD_GET(GENMASK(9, 0), x) * 250)
|
||||
|
||||
int tps65982_get_max_current(void)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[7];
|
||||
u8 pwr_status;
|
||||
u32 contract;
|
||||
int type, mode;
|
||||
struct udevice *udev, *bus;
|
||||
|
||||
log_debug("%s: starting\n", __func__);
|
||||
|
||||
/* Set the i2c bus */
|
||||
ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &bus);
|
||||
if (ret) {
|
||||
log_debug("%s: No bus %d\n", __func__, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = i2c_get_chip(bus, 0x3f, 1, &udev);
|
||||
if (ret) {
|
||||
log_debug("%s: setting chip offset failed %d\n", __func__, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = dm_i2c_read(udev, 0x3f, buf, 3);
|
||||
if (ret) {
|
||||
log_debug("%s: reading pwr_status failed %d\n", __func__, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pwr_status = buf[1];
|
||||
|
||||
if (!(pwr_status & 1))
|
||||
return 0;
|
||||
|
||||
mode = TPS_POWER_STATUS_PWROPMODE(pwr_status);
|
||||
switch (mode) {
|
||||
case TPS_TYPEC_PWR_MODE_1_5A:
|
||||
return 1500;
|
||||
case TPS_TYPEC_PWR_MODE_3_0A:
|
||||
return 3000;
|
||||
case TPS_TYPEC_PWR_MODE_PD:
|
||||
ret = dm_i2c_read(udev, 0x34, buf, 7);
|
||||
if (ret) {
|
||||
log_debug("%s: reading active contract failed %d\n", __func__, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
contract = buf[1] + (buf[2] << 8) + (buf[3] << 16) + (buf[4] << 24);
|
||||
|
||||
type = TPS_PDO_CONTRACT_TYPE(contract);
|
||||
|
||||
switch (type) {
|
||||
case TPS_PDO_CONTRACT_FIXED:
|
||||
return TPS_PDO_FIXED_CONTRACT_MAX_CURRENT(contract);
|
||||
case TPS_PDO_CONTRACT_BATTERY:
|
||||
return 1000 * TPS_PDO_BAT_CONTRACT_MAX_POWER(contract)
|
||||
/ TPS_PDO_BAT_CONTRACT_MAX_VOLTAGE(contract);
|
||||
case TPS_PDO_CONTRACT_VARIABLE:
|
||||
return TPS_PDO_VAR_CONTRACT_MAX_CURRENT(contract);
|
||||
default:
|
||||
log_debug("Unknown contract type: %d\n", type);
|
||||
return -1;
|
||||
}
|
||||
case TPS_TYPEC_PWR_MODE_USB:
|
||||
return 500;
|
||||
default:
|
||||
log_debug("Unknown power mode: %d\n", mode);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int init_tps65982(void)
|
||||
{
|
||||
log_debug("%s: starting\n", __func__);
|
||||
|
||||
if (tps65982_wait_for_app(500, 100)) {
|
||||
log_err("tps65982 APP boot failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_info("tps65982 boot successful\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bq25895_set_iinlim(int current)
|
||||
{
|
||||
u8 val, iinlim;
|
||||
int ret;
|
||||
struct udevice *udev, *bus;
|
||||
|
||||
/* Set the i2c bus */
|
||||
ret = uclass_get_device_by_seq(UCLASS_I2C, 3, &bus);
|
||||
if (ret) {
|
||||
log_err("%s: No bus 3\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = i2c_get_chip(bus, 0x6a, 1, &udev);
|
||||
if (ret) {
|
||||
log_err("%s: setting chip offset failed %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (current > 3250)
|
||||
current = 3250;
|
||||
if (current < 100)
|
||||
current = 100;
|
||||
|
||||
val = dm_i2c_reg_read(udev, 0x00);
|
||||
iinlim = ((current - 100) / 50) & 0x3f;
|
||||
val = (val & 0xc0) | iinlim;
|
||||
dm_i2c_reg_write(udev, 0x00, val);
|
||||
log_debug("REG00 0x%x\n", val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool bq25895_battery_present(void)
|
||||
{
|
||||
u8 val;
|
||||
int ret;
|
||||
struct udevice *udev, *bus;
|
||||
|
||||
/* Set the i2c bus */
|
||||
ret = uclass_get_device_by_seq(UCLASS_I2C, 3, &bus);
|
||||
if (ret) {
|
||||
log_err("%s: No bus 3\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = i2c_get_chip(bus, 0x6a, 1, &udev);
|
||||
if (ret) {
|
||||
log_err("%s: setting chip offset failed %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* note that this may return false negatives when there's
|
||||
* no external power applied and the battery voltage is below
|
||||
* Vsys. this isn't a problem when used for clearing the dead
|
||||
* battery flag though, since it's certain that there's an external
|
||||
* power applied in this case
|
||||
*/
|
||||
val = dm_i2c_reg_read(udev, 0x0e) & 0x7f;
|
||||
if (val == 0x00 || val == 0x7f)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* set some safe defaults for the battery charger
|
||||
*/
|
||||
int init_charger_bq25895(void)
|
||||
{
|
||||
u8 val;
|
||||
int iinlim, ret;
|
||||
struct udevice *udev, *bus;
|
||||
|
||||
/* Set the i2c bus */
|
||||
ret = uclass_get_device_by_seq(UCLASS_I2C, 3, &bus);
|
||||
if (ret) {
|
||||
log_debug("%s: No bus 3\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = i2c_get_chip(bus, 0x6a, 1, &udev);
|
||||
if (ret) {
|
||||
log_debug("%s: setting chip offset failed %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
val = dm_i2c_reg_read(udev, 0x0b);
|
||||
log_debug("REG0B 0x%x\n", val);
|
||||
|
||||
log_debug("VBUS_STAT 0x%x\n", val >> 5);
|
||||
switch (val >> 5) {
|
||||
case 0:
|
||||
log_debug("VBUS not detected\n");
|
||||
break;
|
||||
case 1:
|
||||
log_debug("USB SDP IINLIM 500mA\n");
|
||||
break;
|
||||
case 2:
|
||||
log_debug("USB CDP IINLIM 1500mA\n");
|
||||
break;
|
||||
case 3:
|
||||
log_debug("USB DCP IINLIM 3500mA\n");
|
||||
break;
|
||||
case 4:
|
||||
log_debug("MAXCHARGE IINLIM 1500mA\n");
|
||||
break;
|
||||
case 5:
|
||||
log_debug("Unknown IINLIM 500mA\n");
|
||||
break;
|
||||
case 6:
|
||||
log_debug("DIVIDER IINLIM > 1000mA\n");
|
||||
break;
|
||||
case 7:
|
||||
log_debug("OTG\n");
|
||||
break;
|
||||
};
|
||||
|
||||
log_debug("CHRG_STAT 0x%x\n", (val >> 3) & 0x3);
|
||||
log_debug("PG_STAT 0x%x\n", (val >> 2) & 1);
|
||||
log_debug("SDP_STAT 0x%x\n", (val >> 1) & 1);
|
||||
log_debug("VSYS_STAT 0x%x\n", val & 1);
|
||||
|
||||
val = dm_i2c_reg_read(udev, 0x00);
|
||||
log_debug("REG00 0x%x\n", val);
|
||||
iinlim = 100 + (val & 0x3f) * 50;
|
||||
log_debug("IINLIM %d mA\n", iinlim);
|
||||
log_debug("EN_HIZ 0x%x\n", (val >> 7) & 1);
|
||||
log_debug("EN_ILIM 0x%x\n", (val >> 6) & 1);
|
||||
|
||||
/* set 1.6A charge limit */
|
||||
dm_i2c_reg_write(udev, 0x04, 0x19);
|
||||
|
||||
/* re-enable charger */
|
||||
val = dm_i2c_reg_read(udev, 0x03);
|
||||
val = val | 0x10;
|
||||
dm_i2c_reg_write(udev, 0x03, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int tps_ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_USB_DWC3) || IS_ENABLED(CONFIG_USB_XHCI_IMX8M)) {
|
||||
log_debug("%s: initializing USB clk\n", __func__);
|
||||
|
||||
/* init_usb_clk won't enable the second clock if it's a USB boot */
|
||||
if (is_usb_boot()) {
|
||||
clock_enable(CCGR_USB_CTRL2, 1);
|
||||
clock_enable(CCGR_USB_PHY2, 1);
|
||||
}
|
||||
|
||||
printf("Enabling regulator-hub\n");
|
||||
if (!regulator_get_by_devname("regulator-hub", &dev)) {
|
||||
if (regulator_set_enable(dev, true))
|
||||
pr_err("Failed to enable regulator-hub\n");
|
||||
}
|
||||
}
|
||||
|
||||
tps_ret = init_tps65982();
|
||||
init_charger_bq25895();
|
||||
|
||||
if (!tps_ret) {
|
||||
int current = tps65982_get_max_current();
|
||||
|
||||
if (current > 500)
|
||||
bq25895_set_iinlim(current);
|
||||
|
||||
if (bq25895_battery_present())
|
||||
tps65982_clear_dead_battery();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_late_init(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)) {
|
||||
u32 rev;
|
||||
char rev_str[3];
|
||||
|
||||
env_set("board_name", "librem5");
|
||||
if (fuse_read(9, 0, &rev)) {
|
||||
env_set("board_rev", BOARD_REV_ERROR);
|
||||
} else if (rev == 0) {
|
||||
env_set("board_rev", BOARD_REV_UNKNOWN);
|
||||
} else if (rev > 0) {
|
||||
sprintf(rev_str, "%u", rev);
|
||||
env_set("board_rev", rev_str);
|
||||
}
|
||||
|
||||
printf("Board name: %s\n", env_get("board_name"));
|
||||
printf("Board rev: %s\n", env_get("board_rev"));
|
||||
}
|
||||
|
||||
if (is_usb_boot()) {
|
||||
puts("USB Boot\n");
|
||||
env_set("bootcmd", "fastboot 0");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
181
board/purism/librem5/librem5.h
Normal file
181
board/purism/librem5/librem5.h
Normal file
|
@ -0,0 +1,181 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2021 Purism
|
||||
*/
|
||||
|
||||
#ifndef __LIBREM5_H__
|
||||
#define __LIBREM5_H__
|
||||
|
||||
#define CAMERA_EN IMX_GPIO_NR(1, 0)
|
||||
#define SD_EN IMX_GPIO_NR(1, 3)
|
||||
#define AUDIO_EN IMX_GPIO_NR(1, 4)
|
||||
#define DSI_EN IMX_GPIO_NR(1, 5)
|
||||
#define SMC_EN IMX_GPIO_NR(1, 6)
|
||||
#define TYPEC_MUX_EN IMX_GPIO_NR(1, 11)
|
||||
#define HUB_NRESET IMX_GPIO_NR(1, 12)
|
||||
#define HUB_EN IMX_GPIO_NR(1, 14)
|
||||
#define VOL_UP IMX_GPIO_NR(1, 16)
|
||||
#define VOL_DOWN IMX_GPIO_NR(1, 17)
|
||||
#define DSI_BIAS_EN IMX_GPIO_NR(1, 20)
|
||||
#define FLASH_EN IMX_GPIO_NR(1, 23)
|
||||
#define WWAN_NRESET IMX_GPIO_NR(3, 1)
|
||||
#define CHG_EN IMX_GPIO_NR(3, 2)
|
||||
#define CHG_OTG_OUT_EN IMX_GPIO_NR(3, 4)
|
||||
#define WIFI_EN IMX_GPIO_NR(3, 10)
|
||||
#define GPS_EN IMX_GPIO_NR(3, 12)
|
||||
#define BL_EN IMX_GPIO_NR(3, 14)
|
||||
#define WWAN_EN IMX_GPIO_NR(3, 18)
|
||||
#define NFC_EN IMX_GPIO_NR(4, 28)
|
||||
#define LED_G IMX_GPIO_NR(5, 2)
|
||||
#define LED_R IMX_GPIO_NR(5, 3)
|
||||
#define LED_B IMX_GPIO_NR(1, 13)
|
||||
#define MOTO IMX_GPIO_NR(5, 5)
|
||||
#define SPI1_SCLK IMX_GPIO_NR(5, 6)
|
||||
#define SPI1_MOSI IMX_GPIO_NR(5, 7)
|
||||
#define SPI1_MISO IMX_GPIO_NR(5, 8)
|
||||
#define SPI1_SS0 IMX_GPIO_NR(5, 9)
|
||||
|
||||
#define UART1_TX IMX_GPIO_NR(5, 23)
|
||||
#define UART1_RX IMX_GPIO_NR(5, 22)
|
||||
#define UART2_TX IMX_GPIO_NR(5, 25)
|
||||
#define UART2_RX IMX_GPIO_NR(5, 24)
|
||||
#define UART3_TX IMX_GPIO_NR(5, 27)
|
||||
#define UART3_RX IMX_GPIO_NR(5, 26)
|
||||
#define UART4_TX IMX_GPIO_NR(5, 11)
|
||||
#define UART4_RX IMX_GPIO_NR(5, 10)
|
||||
|
||||
#define TPS_RESET IMX_GPIO_NR(3, 24)
|
||||
|
||||
#define PURISM_VID 0x316d
|
||||
#define PURISM_PID 0x4c05
|
||||
|
||||
#define BOARD_REV_ERROR "unknown"
|
||||
#define BOARD_REV_BIRCH "1"
|
||||
#define BOARD_REV_CHESTNUT "2"
|
||||
#define BOARD_REV_DOGWOOD "3"
|
||||
#define BOARD_REV_EVERGREEN "4"
|
||||
/* Could be ASPEN, BIRCH or CHESTNUT. assume CHESTNUT */
|
||||
#define BOARD_REV_UNKNOWN BOARD_REV_CHESTNUT
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
static const iomux_v3_cfg_t configure_pads[] = {
|
||||
IMX8MQ_PAD_GPIO1_IO00__GPIO1_IO0 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_GPIO1_IO03__GPIO1_IO3 | MUX_PAD_CTRL(PAD_CTL_DSE6) | MUX_MODE_SION,
|
||||
IMX8MQ_PAD_GPIO1_IO04__GPIO1_IO4 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_GPIO1_IO05__GPIO1_IO5 | MUX_PAD_CTRL(PAD_CTL_DSE6) | MUX_MODE_SION,
|
||||
IMX8MQ_PAD_GPIO1_IO06__GPIO1_IO6 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_GPIO1_IO11__GPIO1_IO11 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_GPIO1_IO12__GPIO1_IO12 | MUX_PAD_CTRL(PAD_CTL_DSE6) | MUX_MODE_SION,
|
||||
IMX8MQ_PAD_GPIO1_IO13__GPIO1_IO13 | MUX_PAD_CTRL(PAD_CTL_DSE6) | MUX_MODE_SION,
|
||||
IMX8MQ_PAD_GPIO1_IO14__GPIO1_IO14 | MUX_PAD_CTRL(PAD_CTL_DSE6) | MUX_MODE_SION,
|
||||
IMX8MQ_PAD_ENET_MDC__GPIO1_IO16 | MUX_PAD_CTRL(PAD_CTL_PUE),
|
||||
IMX8MQ_PAD_ENET_MDIO__GPIO1_IO17 | MUX_PAD_CTRL(PAD_CTL_PUE),
|
||||
IMX8MQ_PAD_ENET_TD1__GPIO1_IO20 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_ENET_TXC__GPIO1_IO23 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_NAND_CE0_B__GPIO3_IO1 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_NAND_CE1_B__GPIO3_IO2 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_NAND_CE3_B__GPIO3_IO4 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_NAND_DATA04__GPIO3_IO10 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_NAND_DATA06__GPIO3_IO12 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_NAND_DQS__GPIO3_IO14 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_NAND_WP_B__GPIO3_IO18 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_SAI3_RXFS__GPIO4_IO28 | MUX_PAD_CTRL(PAD_CTL_DSE6),
|
||||
IMX8MQ_PAD_SAI3_MCLK__GPIO5_IO2 | MUX_PAD_CTRL(PAD_CTL_DSE6) | MUX_MODE_SION,
|
||||
IMX8MQ_PAD_SPDIF_TX__GPIO5_IO3 | MUX_PAD_CTRL(PAD_CTL_DSE6) | MUX_MODE_SION,
|
||||
IMX8MQ_PAD_SAI5_RXD3__GPIO3_IO24 | MUX_PAD_CTRL(PAD_CTL_DSE6) | MUX_MODE_SION,
|
||||
};
|
||||
|
||||
static inline void init_pinmux(void)
|
||||
{
|
||||
imx_iomux_v3_setup_multiple_pads(configure_pads, ARRAY_SIZE(configure_pads));
|
||||
|
||||
gpio_request(LED_R, "LED_R");
|
||||
gpio_request(LED_G, "LED_G");
|
||||
gpio_request(LED_B, "LED_B");
|
||||
gpio_request(VOL_UP, "VOL_UP");
|
||||
gpio_request(VOL_DOWN, "VOL_DOWN");
|
||||
|
||||
gpio_request(NFC_EN, "NFC_EN");
|
||||
gpio_request(CHG_EN, "CHG_EN");
|
||||
gpio_request(CHG_OTG_OUT_EN, "CHG_OTG_OUT_EN");
|
||||
|
||||
gpio_request(TYPEC_MUX_EN, "TYPEC_MUX_EN");
|
||||
|
||||
gpio_request(TPS_RESET, "TPS_RESET");
|
||||
|
||||
gpio_request(WWAN_EN, "WWAN_EN");
|
||||
gpio_request(WWAN_NRESET, "WWAN_NRESET");
|
||||
|
||||
gpio_request(HUB_EN, "HUB_EN");
|
||||
gpio_request(HUB_NRESET, "HUB_NRESET");
|
||||
gpio_request(SD_EN, "SD_EN");
|
||||
gpio_request(AUDIO_EN, "AUDIO_EN");
|
||||
gpio_request(DSI_EN, "DSI_EN");
|
||||
gpio_request(SMC_EN, "SMC_EN");
|
||||
gpio_request(CAMERA_EN, "CAMERA_EN");
|
||||
gpio_request(FLASH_EN, "FLASH_EN");
|
||||
gpio_request(DSI_BIAS_EN, "DSI_BIAS_EN");
|
||||
gpio_request(GPS_EN, "GPS_EN");
|
||||
gpio_request(BL_EN, "BL_EN");
|
||||
#ifndef CONSOLE_ON_UART4
|
||||
gpio_request(WIFI_EN, "WIFI_EN");
|
||||
gpio_direction_output(WIFI_EN, 0);
|
||||
#endif /* CONSOLE_ON_UART4 */
|
||||
gpio_direction_input(VOL_UP);
|
||||
gpio_direction_input(VOL_DOWN);
|
||||
|
||||
/* ensure charger is in the automated mode */
|
||||
gpio_direction_output(NFC_EN, 0);
|
||||
gpio_direction_output(CHG_EN, 0);
|
||||
gpio_direction_output(CHG_OTG_OUT_EN, 0);
|
||||
|
||||
gpio_direction_input(TYPEC_MUX_EN);
|
||||
|
||||
gpio_direction_output(TPS_RESET, 0);
|
||||
|
||||
gpio_direction_output(WWAN_EN, 0);
|
||||
gpio_direction_output(WWAN_NRESET, 1);
|
||||
|
||||
gpio_direction_output(HUB_EN, 1);
|
||||
gpio_direction_output(HUB_NRESET, 1);
|
||||
mdelay(10);
|
||||
gpio_direction_output(SD_EN, 1);
|
||||
gpio_direction_output(SMC_EN, 0);
|
||||
gpio_direction_output(CAMERA_EN, 0);
|
||||
gpio_direction_output(FLASH_EN, 0);
|
||||
gpio_direction_output(DSI_BIAS_EN, 0);
|
||||
gpio_direction_output(GPS_EN, 0);
|
||||
gpio_direction_output(BL_EN, 0);
|
||||
|
||||
/* turn these on for i2c busses */
|
||||
gpio_direction_output(AUDIO_EN, 1);
|
||||
gpio_direction_output(DSI_EN, 1);
|
||||
}
|
||||
#endif /* CONFIG_SPL_BUILD */
|
||||
|
||||
#define USB1_BASE_ADDR 0x38100000
|
||||
#define USB2_BASE_ADDR 0x38200000
|
||||
#define USB1_PHY_BASE_ADDR 0x381F0000
|
||||
#define USB2_PHY_BASE_ADDR 0x382F0000
|
||||
|
||||
#define USB_PHY_CTRL0 0xF0040
|
||||
#define USB_PHY_CTRL0_REF_SSP_EN BIT(2)
|
||||
#define USB_PHY_CTRL0_SSC_RANGE_MASK GENMASK(23, 21)
|
||||
#define USB_PHY_CTRL0_SSC_RANGE_4003PPM (0x2 << 21)
|
||||
|
||||
#define USB_PHY_CTRL1 0xF0044
|
||||
#define USB_PHY_CTRL1_RESET BIT(0)
|
||||
#define USB_PHY_CTRL1_COMMONONN BIT(1)
|
||||
#define USB_PHY_CTRL1_ATERESET BIT(3)
|
||||
#define USB_PHY_CTRL1_VDATSRCENB0 BIT(19)
|
||||
#define USB_PHY_CTRL1_VDATDETENB0 BIT(20)
|
||||
|
||||
#define USB_PHY_CTRL2 0xF0048
|
||||
#define USB_PHY_CTRL2_TXENABLEN0 BIT(8)
|
||||
|
||||
#define USB_PHY_CTRL6 0x18
|
||||
#define USB_PHY_CTRL6_RXTERM_OVERRIDE_SEL BIT(29)
|
||||
|
||||
extern struct dram_timing_info dram_timing_b0;
|
||||
|
||||
#endif
|
1324
board/purism/librem5/lpddr4_timing.c
Normal file
1324
board/purism/librem5/lpddr4_timing.c
Normal file
File diff suppressed because it is too large
Load diff
1191
board/purism/librem5/lpddr4_timing_b0.c
Normal file
1191
board/purism/librem5/lpddr4_timing_b0.c
Normal file
File diff suppressed because it is too large
Load diff
592
board/purism/librem5/spl.c
Normal file
592
board/purism/librem5/spl.c
Normal file
|
@ -0,0 +1,592 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2018 NXP
|
||||
* Copyright 2021 Purism
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
#include <asm/arch/imx8mq_pins.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/mach-imx/boot_mode.h>
|
||||
#include <asm/mach-imx/iomux-v3.h>
|
||||
#include <asm/mach-imx/gpio.h>
|
||||
#include <asm/mach-imx/mxc_i2c.h>
|
||||
#include <fsl_esdhc_imx.h>
|
||||
#include <mmc.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/bd71837.h>
|
||||
#include <hang.h>
|
||||
#include <init.h>
|
||||
#include <spl.h>
|
||||
#include <usb.h>
|
||||
#include <dwc3-uboot.h>
|
||||
#include <linux/delay.h>
|
||||
#include "librem5.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void spl_dram_init(void)
|
||||
{
|
||||
/* ddr init */
|
||||
if ((get_cpu_rev() & 0xfff) == CHIP_REV_2_1)
|
||||
ddr_init(&dram_timing);
|
||||
else
|
||||
ddr_init(&dram_timing_b0);
|
||||
}
|
||||
|
||||
int spl_board_boot_device(enum boot_device boot_dev_spl)
|
||||
{
|
||||
log_debug("%s : starting\n", __func__);
|
||||
|
||||
switch (boot_dev_spl) {
|
||||
case SD1_BOOT:
|
||||
case MMC1_BOOT:
|
||||
return BOOT_DEVICE_MMC1;
|
||||
case USB_BOOT:
|
||||
return BOOT_DEVICE_BOARD;
|
||||
default:
|
||||
return BOOT_DEVICE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
#define ECSPI_PAD_CTRL (PAD_CTL_DSE2 | PAD_CTL_HYS)
|
||||
|
||||
static const iomux_v3_cfg_t ecspi_pads[] = {
|
||||
IMX8MQ_PAD_ECSPI1_SCLK__ECSPI1_SCLK | MUX_PAD_CTRL(ECSPI_PAD_CTRL),
|
||||
IMX8MQ_PAD_ECSPI1_SS0__GPIO5_IO9 | MUX_PAD_CTRL(ECSPI_PAD_CTRL),
|
||||
IMX8MQ_PAD_ECSPI1_MOSI__ECSPI1_MOSI | MUX_PAD_CTRL(ECSPI_PAD_CTRL),
|
||||
IMX8MQ_PAD_ECSPI1_MISO__ECSPI1_MISO | MUX_PAD_CTRL(ECSPI_PAD_CTRL),
|
||||
};
|
||||
|
||||
int board_ecspi_init(void)
|
||||
{
|
||||
imx_iomux_v3_setup_multiple_pads(ecspi_pads, ARRAY_SIZE(ecspi_pads));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_spi_cs_gpio(unsigned int bus, unsigned int cs)
|
||||
{
|
||||
return (bus == 0 && cs == 0) ? (SPI1_SS0) : -1;
|
||||
}
|
||||
|
||||
#define I2C_PAD_CTRL (PAD_CTL_PUE | PAD_CTL_ODE | PAD_CTL_DSE7 | PAD_CTL_FSEL3)
|
||||
#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
|
||||
struct i2c_pads_info i2c_pad_info1 = {
|
||||
.scl = {
|
||||
.i2c_mode = IMX8MQ_PAD_I2C1_SCL__I2C1_SCL | PC,
|
||||
.gpio_mode = IMX8MQ_PAD_I2C1_SCL__GPIO5_IO14 | PC,
|
||||
.gp = IMX_GPIO_NR(5, 14),
|
||||
},
|
||||
.sda = {
|
||||
.i2c_mode = IMX8MQ_PAD_I2C1_SDA__I2C1_SDA | PC,
|
||||
.gpio_mode = IMX8MQ_PAD_I2C1_SDA__GPIO5_IO15 | PC,
|
||||
.gp = IMX_GPIO_NR(5, 15),
|
||||
},
|
||||
};
|
||||
|
||||
struct i2c_pads_info i2c_pad_info2 = {
|
||||
.scl = {
|
||||
.i2c_mode = IMX8MQ_PAD_I2C2_SCL__I2C2_SCL | PC,
|
||||
.gpio_mode = IMX8MQ_PAD_I2C2_SCL__GPIO5_IO16 | PC,
|
||||
.gp = IMX_GPIO_NR(5, 16),
|
||||
},
|
||||
.sda = {
|
||||
.i2c_mode = IMX8MQ_PAD_I2C2_SDA__I2C2_SDA | PC,
|
||||
.gpio_mode = IMX8MQ_PAD_I2C2_SDA__GPIO5_IO17 | PC,
|
||||
.gp = IMX_GPIO_NR(5, 17),
|
||||
},
|
||||
};
|
||||
|
||||
struct i2c_pads_info i2c_pad_info3 = {
|
||||
.scl = {
|
||||
.i2c_mode = IMX8MQ_PAD_I2C3_SCL__I2C3_SCL | PC,
|
||||
.gpio_mode = IMX8MQ_PAD_I2C3_SCL__GPIO5_IO18 | PC,
|
||||
.gp = IMX_GPIO_NR(5, 18),
|
||||
},
|
||||
.sda = {
|
||||
.i2c_mode = IMX8MQ_PAD_I2C3_SDA__I2C3_SDA | PC,
|
||||
.gpio_mode = IMX8MQ_PAD_I2C3_SDA__GPIO5_IO19 | PC,
|
||||
.gp = IMX_GPIO_NR(5, 19),
|
||||
},
|
||||
};
|
||||
|
||||
struct i2c_pads_info i2c_pad_info4 = {
|
||||
.scl = {
|
||||
.i2c_mode = IMX8MQ_PAD_I2C4_SCL__I2C4_SCL | PC,
|
||||
.gpio_mode = IMX8MQ_PAD_I2C4_SCL__GPIO5_IO20 | PC,
|
||||
.gp = IMX_GPIO_NR(5, 20),
|
||||
},
|
||||
.sda = {
|
||||
.i2c_mode = IMX8MQ_PAD_I2C4_SDA__I2C4_SDA | PC,
|
||||
.gpio_mode = IMX8MQ_PAD_I2C4_SDA__GPIO5_IO21 | PC,
|
||||
.gp = IMX_GPIO_NR(5, 21),
|
||||
},
|
||||
};
|
||||
|
||||
#define UART_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_FSEL1)
|
||||
|
||||
static const iomux_v3_cfg_t uart_pads[] = {
|
||||
IMX8MQ_PAD_UART1_RXD__UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
|
||||
IMX8MQ_PAD_UART1_TXD__UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
|
||||
IMX8MQ_PAD_UART2_RXD__UART2_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
|
||||
IMX8MQ_PAD_UART2_TXD__UART2_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
|
||||
IMX8MQ_PAD_UART3_RXD__UART3_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
|
||||
IMX8MQ_PAD_UART3_TXD__UART3_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
|
||||
IMX8MQ_PAD_ECSPI2_SCLK__UART4_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
|
||||
IMX8MQ_PAD_ECSPI2_MOSI__UART4_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
|
||||
};
|
||||
|
||||
#define USDHC1_PWR_GPIO IMX_GPIO_NR(2, 10)
|
||||
#define USDHC2_PWR_GPIO IMX_GPIO_NR(2, 19)
|
||||
|
||||
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 USDHC1_BASE_ADDR:
|
||||
ret = 1;
|
||||
break;
|
||||
case USDHC2_BASE_ADDR:
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define USDHC_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | \
|
||||
PAD_CTL_FSEL1)
|
||||
#define USDHC_GPIO_PAD_CTRL (PAD_CTL_PUE | PAD_CTL_DSE1)
|
||||
|
||||
static const iomux_v3_cfg_t usdhc1_pads[] = {
|
||||
IMX8MQ_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
||||
IMX8MQ_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
||||
IMX8MQ_PAD_SD1_DATA0__USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
||||
IMX8MQ_PAD_SD1_DATA1__USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
||||
IMX8MQ_PAD_SD1_DATA2__USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
||||
IMX8MQ_PAD_SD1_DATA3__USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
||||
IMX8MQ_PAD_SD1_DATA4__USDHC1_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
||||
IMX8MQ_PAD_SD1_DATA5__USDHC1_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
||||
IMX8MQ_PAD_SD1_DATA6__USDHC1_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
||||
IMX8MQ_PAD_SD1_DATA7__USDHC1_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
|
||||
IMX8MQ_PAD_SD1_RESET_B__GPIO2_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
|
||||
};
|
||||
|
||||
static const iomux_v3_cfg_t usdhc2_pads[] = {
|
||||
IMX8MQ_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
|
||||
IMX8MQ_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
|
||||
IMX8MQ_PAD_SD2_DATA0__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
|
||||
IMX8MQ_PAD_SD2_DATA1__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
|
||||
IMX8MQ_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0x16 */
|
||||
IMX8MQ_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
|
||||
IMX8MQ_PAD_SD2_RESET_B__GPIO2_IO19 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL),
|
||||
};
|
||||
|
||||
static struct fsl_esdhc_cfg usdhc_cfg[2] = {
|
||||
{USDHC1_BASE_ADDR, 0, 8},
|
||||
{USDHC2_BASE_ADDR, 0, 4},
|
||||
};
|
||||
|
||||
int board_mmc_init(struct bd_info *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++) {
|
||||
log_debug("Initializing FSL USDHC port %d\n", i);
|
||||
switch (i) {
|
||||
case 0:
|
||||
init_clk_usdhc(0);
|
||||
usdhc_cfg[0].sdhc_clk = mxc_get_clock(USDHC1_CLK_ROOT);
|
||||
imx_iomux_v3_setup_multiple_pads(usdhc1_pads,
|
||||
ARRAY_SIZE(usdhc1_pads));
|
||||
gpio_request(USDHC1_PWR_GPIO, "usdhc1_reset");
|
||||
gpio_direction_output(USDHC1_PWR_GPIO, 0);
|
||||
udelay(500);
|
||||
gpio_direction_output(USDHC1_PWR_GPIO, 1);
|
||||
break;
|
||||
case 1:
|
||||
init_clk_usdhc(1);
|
||||
usdhc_cfg[1].sdhc_clk = mxc_get_clock(USDHC2_CLK_ROOT);
|
||||
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;
|
||||
default:
|
||||
log_err("Warning: USDHC controller(%d) not supported\n", i + 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LDO_VOLT_EN BIT(6)
|
||||
|
||||
/*
|
||||
* Disable the charger - it will be re-enabled in u-boot
|
||||
*/
|
||||
void disable_charger_bq25895(void)
|
||||
{
|
||||
u8 val;
|
||||
int timeout = 1000; // ms
|
||||
|
||||
/* Set the i2c bus */
|
||||
i2c_set_bus_num(3);
|
||||
|
||||
/* disable ship mode if BATFET_DLY is set */
|
||||
val = i2c_reg_read(0x6a, 0x09);
|
||||
log_debug("REG09 0x%x\n", val);
|
||||
if (val & 0x28) {
|
||||
val = val & ~0x28;
|
||||
i2c_reg_write(0x6a, 0x09, val);
|
||||
}
|
||||
|
||||
/* disable and trigger DPDM, ICO, HVDCP and MaxCharge */
|
||||
val = i2c_reg_read(0x6a, 0x02);
|
||||
log_debug("REG02 0x%x\n", val);
|
||||
val &= 0xe0;
|
||||
i2c_reg_write(0x6a, 0x02, val);
|
||||
|
||||
/* disable charger and enable BAT_LOADEN */
|
||||
val = i2c_reg_read(0x6a, 0x03);
|
||||
log_debug("REG03 0x%x\n", val);
|
||||
val = (val | 0x80) & ~0x10;
|
||||
i2c_reg_write(0x6a, 0x03, val);
|
||||
|
||||
mdelay(10);
|
||||
|
||||
/* force ADC conversions */
|
||||
val = i2c_reg_read(0x6a, 0x02);
|
||||
log_debug("REG02 0x%x\n", val);
|
||||
val = (val | 0x80) & ~0x40;
|
||||
i2c_reg_write(0x6a, 0x02, val);
|
||||
|
||||
do {
|
||||
mdelay(10);
|
||||
timeout -= 10;
|
||||
} while ((i2c_reg_read(0x6a, 0x02) & 0x80) && (timeout > 0));
|
||||
|
||||
/* enable STAT pin */
|
||||
val = i2c_reg_read(0x6a, 0x07);
|
||||
log_debug("REG07 0x%x\n", val);
|
||||
val = val & ~0x40;
|
||||
i2c_reg_write(0x6a, 0x07, val);
|
||||
|
||||
/* check VBUS */
|
||||
val = i2c_reg_read(0x6a, 0x11);
|
||||
log_debug("VBUS good %d\n", (val >> 7) & 1);
|
||||
log_debug("VBUS mV %d\n", (val & 0x7f) * 100 + 2600);
|
||||
|
||||
/* check VBAT */
|
||||
val = i2c_reg_read(0x6a, 0x0e);
|
||||
log_debug("VBAT mV %d\n", (val & 0x7f) * 20 + 2304);
|
||||
|
||||
/* limit the VINDPM to 3.9V */
|
||||
i2c_reg_write(0x6a, 0x0d, 0x8d);
|
||||
|
||||
/* set the max voltage to 4.192V */
|
||||
val = i2c_reg_read(0x6a, 0x6);
|
||||
val = (val & ~0xFC) | 0x16 << 2;
|
||||
i2c_reg_write(0x6a, 0x6, val);
|
||||
|
||||
/* set the SYS_MIN to 3.7V */
|
||||
val = i2c_reg_read(0x6a, 0x3);
|
||||
val = val | 0xE;
|
||||
i2c_reg_write(0x6a, 0x3, val);
|
||||
|
||||
/* disable BAT_LOADEN */
|
||||
val = i2c_reg_read(0x6a, 0x03);
|
||||
log_debug("REG03 0x%x\n", val);
|
||||
val = val & ~0x80;
|
||||
i2c_reg_write(0x6a, 0x03, val);
|
||||
}
|
||||
|
||||
#define I2C_PMIC 0
|
||||
|
||||
int power_bd71837_init(unsigned char bus)
|
||||
{
|
||||
static const char name[] = BD718XX_REGULATOR_DRIVER;
|
||||
struct pmic *p = pmic_alloc();
|
||||
|
||||
if (!p) {
|
||||
log_err("%s: POWER allocation error!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
p->name = name;
|
||||
p->interface = I2C_PMIC;
|
||||
p->number_of_regs = BD718XX_MAX_REGISTER;
|
||||
p->hw.i2c.addr = CONFIG_POWER_BD71837_I2C_ADDR;
|
||||
p->hw.i2c.tx_num = 1;
|
||||
p->bus = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int power_init_board(void)
|
||||
{
|
||||
struct pmic *p;
|
||||
int ldo[] = {BD718XX_LDO5_VOLT, BD718XX_LDO6_VOLT,
|
||||
BD71837_LDO7_VOLT};
|
||||
u32 val;
|
||||
int i, rv;
|
||||
|
||||
/* Set the i2c bus */
|
||||
setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
|
||||
|
||||
/*
|
||||
* Init PMIC
|
||||
*/
|
||||
rv = power_bd71837_init(CONFIG_POWER_BD71837_I2C_BUS);
|
||||
if (rv) {
|
||||
log_err("%s: power_bd71837_init(%d) error %d\n", __func__,
|
||||
CONFIG_POWER_BD71837_I2C_BUS, rv);
|
||||
goto out;
|
||||
}
|
||||
|
||||
p = pmic_get(BD718XX_REGULATOR_DRIVER);
|
||||
if (!p) {
|
||||
log_err("%s: pmic_get(%s) failed\n", __func__, BD718XX_REGULATOR_DRIVER);
|
||||
rv = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = pmic_probe(p);
|
||||
if (rv) {
|
||||
log_err("%s: pmic_probe() error %d\n", __func__, rv);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlock all regs
|
||||
*/
|
||||
pmic_reg_write(p, BD718XX_REGLOCK, 0);
|
||||
|
||||
/* find the reset cause */
|
||||
pmic_reg_read(p, 0x29, &val);
|
||||
log_debug("%s: reset cause %d\n", __func__, val);
|
||||
|
||||
/*
|
||||
* Reconfigure default voltages and disable:
|
||||
* - BUCK3: VDD_GPU_0V9 (1.00 -> 0.90)
|
||||
* - BUCK4: VDD_VPU_0V9 (1.00 -> 0.90)
|
||||
*/
|
||||
pmic_reg_write(p, BD71837_BUCK3_VOLT_RUN, 0x14);
|
||||
pmic_reg_write(p, BD71837_BUCK4_VOLT_RUN, 0x14);
|
||||
|
||||
/*
|
||||
* Enable PHYs voltages: LDO5-7
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(ldo); i++) {
|
||||
rv = pmic_reg_read(p, ldo[i], &val);
|
||||
if (rv) {
|
||||
log_err("%s: pmic_read(%x) error %d\n", __func__,
|
||||
ldo[i], rv);
|
||||
continue;
|
||||
}
|
||||
|
||||
pmic_reg_write(p, ldo[i], val | LDO_VOLT_EN);
|
||||
}
|
||||
|
||||
udelay(500);
|
||||
|
||||
rv = 0;
|
||||
out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
int usb_gadget_handle_interrupts(void)
|
||||
{
|
||||
dwc3_uboot_handle_interrupt(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dwc3_nxp_usb_phy_init(struct dwc3_device *dwc3)
|
||||
{
|
||||
u32 RegData;
|
||||
|
||||
RegData = readl(dwc3->base + USB_PHY_CTRL1);
|
||||
RegData &= ~(USB_PHY_CTRL1_VDATSRCENB0 | USB_PHY_CTRL1_VDATDETENB0 |
|
||||
USB_PHY_CTRL1_COMMONONN);
|
||||
RegData |= USB_PHY_CTRL1_RESET | USB_PHY_CTRL1_ATERESET;
|
||||
writel(RegData, dwc3->base + USB_PHY_CTRL1);
|
||||
|
||||
RegData = readl(dwc3->base + USB_PHY_CTRL0);
|
||||
RegData |= USB_PHY_CTRL0_REF_SSP_EN;
|
||||
RegData &= ~USB_PHY_CTRL0_SSC_RANGE_MASK;
|
||||
RegData |= USB_PHY_CTRL0_SSC_RANGE_4003PPM;
|
||||
writel(RegData, dwc3->base + USB_PHY_CTRL0);
|
||||
|
||||
RegData = readl(dwc3->base + USB_PHY_CTRL2);
|
||||
RegData |= USB_PHY_CTRL2_TXENABLEN0;
|
||||
writel(RegData, dwc3->base + USB_PHY_CTRL2);
|
||||
|
||||
RegData = readl(dwc3->base + USB_PHY_CTRL1);
|
||||
RegData &= ~(USB_PHY_CTRL1_RESET | USB_PHY_CTRL1_ATERESET);
|
||||
writel(RegData, dwc3->base + USB_PHY_CTRL1);
|
||||
|
||||
/* Disable rx term override */
|
||||
RegData = readl(dwc3->base + USB_PHY_CTRL6);
|
||||
RegData &= ~USB_PHY_CTRL6_RXTERM_OVERRIDE_SEL;
|
||||
writel(RegData, dwc3->base + USB_PHY_CTRL6);
|
||||
}
|
||||
|
||||
static struct dwc3_device dwc3_device0_data = {
|
||||
.maximum_speed = USB_SPEED_HIGH,
|
||||
.base = USB1_BASE_ADDR,
|
||||
.dr_mode = USB_DR_MODE_PERIPHERAL,
|
||||
.index = 0,
|
||||
};
|
||||
|
||||
static struct dwc3_device dwc3_device1_data = {
|
||||
.maximum_speed = USB_SPEED_HIGH,
|
||||
.base = USB2_BASE_ADDR,
|
||||
.dr_mode = USB_DR_MODE_HOST,
|
||||
.index = 1,
|
||||
};
|
||||
|
||||
int board_usb_init(int index, enum usb_init_type init)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
printf("%s : index %d type %d\n", __func__, index, init);
|
||||
|
||||
if (index == 0 && init == USB_INIT_DEVICE) {
|
||||
dwc3_nxp_usb_phy_init(&dwc3_device0_data);
|
||||
ret = dwc3_uboot_init(&dwc3_device0_data);
|
||||
}
|
||||
if (index == 1 && init == USB_INIT_HOST) {
|
||||
dwc3_nxp_usb_phy_init(&dwc3_device1_data);
|
||||
ret = dwc3_uboot_init(&dwc3_device1_data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int board_usb_cleanup(int index, enum usb_init_type init)
|
||||
{
|
||||
u32 RegData;
|
||||
struct dwc3_device *dwc3;
|
||||
|
||||
printf("%s : %d\n", __func__, index);
|
||||
|
||||
if (index == 0 && init == USB_INIT_DEVICE)
|
||||
dwc3 = &dwc3_device0_data;
|
||||
if (index == 1 && init == USB_INIT_HOST)
|
||||
dwc3 = &dwc3_device1_data;
|
||||
|
||||
dwc3_uboot_exit(index);
|
||||
|
||||
/* reset the phy */
|
||||
RegData = readl(dwc3->base + USB_PHY_CTRL1);
|
||||
RegData &= ~(USB_PHY_CTRL1_VDATSRCENB0 | USB_PHY_CTRL1_VDATDETENB0 |
|
||||
USB_PHY_CTRL1_COMMONONN);
|
||||
RegData |= USB_PHY_CTRL1_RESET | USB_PHY_CTRL1_ATERESET;
|
||||
writel(RegData, dwc3->base + USB_PHY_CTRL1);
|
||||
|
||||
/* enable rx term override */
|
||||
RegData = readl(dwc3->base + USB_PHY_CTRL6);
|
||||
RegData |= USB_PHY_CTRL6_RXTERM_OVERRIDE_SEL;
|
||||
writel(RegData, dwc3->base + USB_PHY_CTRL6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spl_board_init(void)
|
||||
{
|
||||
if (is_usb_boot())
|
||||
puts("USB Boot\n");
|
||||
else
|
||||
puts("Normal Boot\n");
|
||||
}
|
||||
|
||||
void board_boot_order(u32 *spl_boot_list)
|
||||
{
|
||||
if (is_usb_boot())
|
||||
spl_boot_list[0] = BOOT_DEVICE_BOARD;
|
||||
else
|
||||
spl_boot_list[0] = BOOT_DEVICE_MMC1;
|
||||
}
|
||||
|
||||
#define WDOG_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE)
|
||||
|
||||
static const iomux_v3_cfg_t wdog_pads[] = {
|
||||
IMX8MQ_PAD_GPIO1_IO02__WDOG1_WDOG_B | MUX_PAD_CTRL(WDOG_PAD_CTRL),
|
||||
};
|
||||
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
int ret;
|
||||
struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
|
||||
|
||||
arch_cpu_init();
|
||||
|
||||
imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads));
|
||||
set_wdog_reset(wdog);
|
||||
|
||||
init_uart_clk(CONSOLE_UART_CLK);
|
||||
imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads));
|
||||
|
||||
#ifdef CONSOLE_ON_UART4
|
||||
gpio_request(WIFI_EN, "WIFI_EN");
|
||||
gpio_direction_output(WIFI_EN, 1);
|
||||
#endif
|
||||
|
||||
board_early_init_f();
|
||||
|
||||
timer_init();
|
||||
|
||||
preloader_console_init();
|
||||
|
||||
ret = spl_init();
|
||||
if (ret) {
|
||||
log_err("spl_init() failed: %d\n", ret);
|
||||
hang();
|
||||
}
|
||||
|
||||
enable_tzc380();
|
||||
|
||||
printf("Initializing pinmux\n");
|
||||
init_pinmux();
|
||||
gpio_direction_output(LED_G, 1);
|
||||
gpio_direction_output(MOTO, 1);
|
||||
mdelay(50);
|
||||
gpio_direction_output(MOTO, 0);
|
||||
|
||||
/* Enable and configure i2c buses not used below */
|
||||
setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
|
||||
setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3);
|
||||
setup_i2c(3, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info4);
|
||||
|
||||
power_init_board();
|
||||
|
||||
disable_charger_bq25895();
|
||||
|
||||
/* initialize this for M4 even if u-boot doesn't have SF_CMD */
|
||||
printf("Initializing ECSPI\n");
|
||||
board_ecspi_init();
|
||||
|
||||
/* DDR initialization */
|
||||
printf("Initializing DRAM\n");
|
||||
spl_dram_init();
|
||||
}
|
152
configs/librem5_defconfig
Normal file
152
configs/librem5_defconfig
Normal file
|
@ -0,0 +1,152 @@
|
|||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_IMX8M=y
|
||||
CONFIG_SYS_TEXT_BASE=0x40200000
|
||||
CONFIG_SPL_GPIO=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_ENV_SIZE=0x2000
|
||||
CONFIG_ENV_OFFSET=0x3FE000
|
||||
CONFIG_SYS_I2C_MXC_I2C1=y
|
||||
CONFIG_SYS_I2C_MXC_I2C2=y
|
||||
CONFIG_SYS_I2C_MXC_I2C3=y
|
||||
CONFIG_SYS_I2C_MXC_I2C4=y
|
||||
CONFIG_DM_GPIO=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="imx8mq-librem5-r4"
|
||||
CONFIG_SPL_TEXT_BASE=0x7E1000
|
||||
CONFIG_TARGET_LIBREM5=y
|
||||
CONFIG_SPL_MMC=y
|
||||
CONFIG_SPL_SERIAL=y
|
||||
CONFIG_SPL_DRIVERS_MISC=y
|
||||
CONFIG_SPL=y
|
||||
CONFIG_IMX_BOOTAUX=y
|
||||
CONFIG_SYS_LOAD_ADDR=0x40480000
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
CONFIG_REMAKE_ELF=y
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_EXTERNAL_OFFSET=0x3000
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
# CONFIG_USE_SPL_FIT_GENERATOR is not set
|
||||
CONFIG_OF_SYSTEM_SETUP=y
|
||||
CONFIG_BOOTDELAY=0
|
||||
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
|
||||
# CONFIG_SYS_DEVICE_NULLDEV is not set
|
||||
CONFIG_ARCH_MISC_INIT=y
|
||||
CONFIG_BOARD_EARLY_INIT_F=y
|
||||
CONFIG_BOARD_LATE_INIT=y
|
||||
CONFIG_SPL_MAX_SIZE=0x25000
|
||||
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
|
||||
CONFIG_SPL_BSS_START_ADDR=0x180000
|
||||
CONFIG_SPL_BSS_MAX_SIZE=0x2000
|
||||
CONFIG_SPL_BOARD_INIT=y
|
||||
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
|
||||
CONFIG_SPL_STACK=0x187ff0
|
||||
CONFIG_SYS_SPL_MALLOC=y
|
||||
CONFIG_HAS_CUSTOM_SPL_MALLOC_START=y
|
||||
CONFIG_CUSTOM_SYS_SPL_MALLOC_ADDR=0x42200000
|
||||
CONFIG_SYS_SPL_MALLOC_SIZE=0x80000
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x300
|
||||
CONFIG_SPL_I2C=y
|
||||
CONFIG_SPL_POWER=y
|
||||
CONFIG_SPL_USB_GADGET=y
|
||||
CONFIG_SPL_USB_SDP_SUPPORT=y
|
||||
CONFIG_SPL_WATCHDOG=y
|
||||
CONFIG_SYS_PROMPT="u-boot=> "
|
||||
CONFIG_SYS_MAXARGS=64
|
||||
CONFIG_SYS_PBSIZE=1050
|
||||
CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_SYS_ALT_MEMTEST=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_FUSE=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_USB_SDP=y
|
||||
CONFIG_CMD_CACHE=y
|
||||
CONFIG_CMD_REGULATOR=y
|
||||
CONFIG_CMD_EXT4_WRITE=y
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_ENV_OVERWRITE=y
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
|
||||
CONFIG_SPL_DM=y
|
||||
CONFIG_DEVRES=y
|
||||
# CONFIG_SPL_BLK is not set
|
||||
CONFIG_BUTTON=y
|
||||
CONFIG_BUTTON_GPIO=y
|
||||
CONFIG_SAVED_DRAM_TIMING_BASE=0x40000000
|
||||
CONFIG_DMA=y
|
||||
CONFIG_DMA_CHANNELS=y
|
||||
CONFIG_USB_FUNCTION_FASTBOOT=y
|
||||
CONFIG_FASTBOOT_BUF_ADDR=0x43000000
|
||||
CONFIG_FASTBOOT_BUF_SIZE=0x40000000
|
||||
CONFIG_FASTBOOT_FLASH=y
|
||||
CONFIG_FASTBOOT_UUU_SUPPORT=y
|
||||
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
|
||||
CONFIG_FASTBOOT_MMC_BOOT_SUPPORT=y
|
||||
CONFIG_FASTBOOT_MMC_USER_SUPPORT=y
|
||||
CONFIG_FASTBOOT_CMD_OEM_PARTCONF=y
|
||||
CONFIG_FASTBOOT_CMD_OEM_BOOTBUS=y
|
||||
# CONFIG_SPL_DM_GPIO is not set
|
||||
CONFIG_GPIO_HOG=y
|
||||
CONFIG_DM_GPIO_LOOKUP_LABEL=y
|
||||
CONFIG_MXC_GPIO=y
|
||||
CONFIG_DM_I2C=y
|
||||
# CONFIG_SPL_DM_I2C is not set
|
||||
CONFIG_SPL_SYS_I2C_LEGACY=y
|
||||
CONFIG_SYS_I2C_EARLY_INIT=y
|
||||
CONFIG_SYS_MXC_I2C1_SPEED=50000
|
||||
CONFIG_SYS_MXC_I2C2_SPEED=50000
|
||||
CONFIG_SYS_MXC_I2C3_SPEED=50000
|
||||
CONFIG_SYS_MXC_I2C4_SPEED=50000
|
||||
CONFIG_SYS_I2C_SPEED=50000
|
||||
CONFIG_LED=y
|
||||
CONFIG_LED_BLINK=y
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_MISC=y
|
||||
CONFIG_PWRSEQ=y
|
||||
CONFIG_MMC_BROKEN_CD=y
|
||||
# CONFIG_SPL_DM_MMC is not set
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
CONFIG_MMC_HS400_ES_SUPPORT=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_FSL_USDHC=y
|
||||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH_STMICRO=y
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_PHY=y
|
||||
CONFIG_PHY_IMX8MQ_USB=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PINCTRL_IMX8M=y
|
||||
CONFIG_POWER_LEGACY=y
|
||||
CONFIG_POWER_DOMAIN=y
|
||||
CONFIG_IMX8M_POWER_DOMAIN=y
|
||||
CONFIG_DM_REGULATOR=y
|
||||
CONFIG_DM_REGULATOR_FIXED=y
|
||||
CONFIG_DM_REGULATOR_GPIO=y
|
||||
CONFIG_POWER_I2C=y
|
||||
CONFIG_DM_RESET=y
|
||||
CONFIG_MXC_UART=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_DM_SPI=y
|
||||
CONFIG_MXC_SPI=y
|
||||
CONFIG_DM_THERMAL=y
|
||||
CONFIG_IMX_TMU=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_DM_USB_GADGET=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
CONFIG_USB_XHCI_DWC3=y
|
||||
CONFIG_USB_DWC3=y
|
||||
CONFIG_USB_DWC3_GENERIC=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_GADGET_MANUFACTURER="Purism"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0525
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
|
||||
CONFIG_SDP_LOADADDR=0x40400000
|
||||
CONFIG_USB_FUNCTION_ACM=y
|
|
@ -28,6 +28,7 @@ Board-specific doc
|
|||
nokia/index
|
||||
nxp/index
|
||||
openpiton/index
|
||||
purism/index
|
||||
qualcomm/index
|
||||
rockchip/index
|
||||
samsung/index
|
||||
|
|
9
doc/board/purism/index.rst
Normal file
9
doc/board/purism/index.rst
Normal file
|
@ -0,0 +1,9 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Purism SPC
|
||||
==========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
librem5
|
60
doc/board/purism/librem5.rst
Normal file
60
doc/board/purism/librem5.rst
Normal file
|
@ -0,0 +1,60 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Librem5
|
||||
==========
|
||||
|
||||
U-Boot for the Purism Librem5 phone
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
- Build the ARM Trusted firmware binary
|
||||
- Get ddr and hdmi firmware
|
||||
- Build U-Boot
|
||||
|
||||
Get and Build the ARM Trusted firmware
|
||||
--------------------------------------
|
||||
|
||||
Note: srctree is U-Boot source directory
|
||||
Get ATF from: https://source.puri.sm/Librem5/arm-trusted-firmware
|
||||
branch: librem5
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ make PLAT=imx8mq CROSS_COMPILE=aarch64-linux-gnu- bl31
|
||||
$ cp build/imx8mq/release/bl31.bin $(builddir)
|
||||
|
||||
Get the ddr and display port firmware
|
||||
-------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.15.bin
|
||||
$ chmod +x firmware-imx-8.15.bin
|
||||
$ ./firmware-imx-8.15.bin
|
||||
$ cp firmware-imx-8.15/firmware/hdmi/cadence/signed_dp_imx8m.bin $(builddir)
|
||||
$ cp firmware-imx-8.15/firmware/ddr/synopsys/lpddr4*.bin $(builddir)
|
||||
|
||||
Build U-Boot
|
||||
------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ export CROSS_COMPILE=aarch64-linux-gnu-
|
||||
$ make librem5_defconfig
|
||||
$ make ARCH=arm
|
||||
|
||||
Burn the flash.bin
|
||||
------------------
|
||||
|
||||
Use uuu to burn flash.bin. Power on the phone while holding vol+ to get it
|
||||
into uuu mode.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git clone https://source.puri.sm/Librem5/librem5-devkit-tools.git
|
||||
$ cd librem5-devkit-tools
|
||||
$ cp $(builddir)/flash.bin files/u-boot-librem5.imx
|
||||
$ uuu uuu_scripts/u-boot_flash_librem5.lst
|
||||
|
||||
Reboot the phone.
|
95
include/configs/librem5.h
Normal file
95
include/configs/librem5.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2017 NXP
|
||||
* Copyright 2018 Emcraft Systems
|
||||
* Copyright 2022 Purism
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LIBREM5_H
|
||||
#define __LIBREM5_H
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <version.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
|
||||
#define CONFIG_SYS_MONITOR_LEN (512 * 1024)
|
||||
|
||||
#ifdef CONFIG_SPL_BUILD
|
||||
|
||||
#define CONFIG_SPL_ABORT_ON_RAW_IMAGE /* For RAW image gives a error info not panic */
|
||||
|
||||
#define CONFIG_POWER_BD71837
|
||||
#define CONFIG_POWER_BD71837_I2C_BUS 0
|
||||
#define CONFIG_POWER_BD71837_I2C_ADDR 0x4B
|
||||
|
||||
#endif /* CONFIG_SPL_BUILD*/
|
||||
|
||||
#define CONFIG_SYS_FSL_USDHC_NUM 2
|
||||
|
||||
#define CONFIG_USBD_HS
|
||||
|
||||
#define CONSOLE_ON_UART1
|
||||
|
||||
#ifdef CONSOLE_ON_UART1
|
||||
#define CONFIG_MXC_UART_BASE UART1_BASE_ADDR
|
||||
#define CONSOLE_UART_CLK 0
|
||||
#define CONSOLE "ttymxc0"
|
||||
#elif defined(CONSOLE_ON_UART2)
|
||||
#define CONFIG_MXC_UART_BASE UART2_BASE_ADDR
|
||||
#define CONSOLE_UART_CLK 1
|
||||
#define CONSOLE "ttymxc1"
|
||||
#elif defined(CONSOLE_ON_UART3)
|
||||
#define CONFIG_MXC_UART_BASE UART3_BASE_ADDR
|
||||
#define CONSOLE_UART_CLK 2
|
||||
#define CONSOLE "ttymxc2"
|
||||
#elif defined(CONSOLE_ON_UART4)
|
||||
#define CONFIG_MXC_UART_BASE UART4_BASE_ADDR
|
||||
#define CONSOLE_UART_CLK 3
|
||||
#define CONSOLE "ttymxc3"
|
||||
#else
|
||||
#define CONFIG_MXC_UART_BASE UART1_BASE_ADDR
|
||||
#define CONSOLE_UART_CLK 0
|
||||
#define CONSOLE "ttymxc0"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SPL_BUILD
|
||||
#define BOOT_TARGET_DEVICES(func) \
|
||||
func(MMC, mmc, 0) \
|
||||
func(USB, usb, 0) \
|
||||
func(DHCP, dhcp, na)
|
||||
#include <config_distro_bootcmd.h>
|
||||
#else
|
||||
#define BOOTENV
|
||||
#endif
|
||||
|
||||
/* Initial environment variables */
|
||||
#define CONFIG_EXTRA_ENV_SETTINGS \
|
||||
"scriptaddr=0x80000000\0" \
|
||||
"pxefile_addr_r=0x80100000\0" \
|
||||
"kernel_addr_r=0x80800000\0" \
|
||||
"fdt_addr_r=0x84800000\0" \
|
||||
"ramdisk_addr_r=0x85000000\0" \
|
||||
"console=" CONSOLE ",115200\0" \
|
||||
"bootargs=u_boot_version=" PLAIN_VERSION "\0" \
|
||||
"stdin=usbacm,serial\0" \
|
||||
"stdout=usbacm,serial\0" \
|
||||
"stderr=usbacm,serial\0" \
|
||||
BOOTENV
|
||||
|
||||
/* Link Definitions */
|
||||
|
||||
#define CONFIG_SYS_INIT_RAM_ADDR 0x40000000
|
||||
#define CONFIG_SYS_INIT_RAM_SIZE 0x80000
|
||||
|
||||
#define CONFIG_SYS_SDRAM_BASE 0x40000000
|
||||
#define PHYS_SDRAM 0x40000000
|
||||
#define PHYS_SDRAM_SIZE 0xc0000000 /* 3GB LPDDR4 one Rank */
|
||||
|
||||
/* Monitor Command Prompt */
|
||||
|
||||
#define CONFIG_SYS_FSL_ESDHC_ADDR 0
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue