mirror of
https://gitee.com/bianbu-linux/uboot-2022.10
synced 2025-04-24 23:07:22 -04:00
Update for v1.0
This commit is contained in:
parent
d0e22fd5b0
commit
c3b72c9393
49 changed files with 1914 additions and 453 deletions
|
@ -28,7 +28,7 @@
|
|||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
status = "okay";
|
||||
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
riscv,isa = "rv64imafdcv_zicsr_zifencei_zicbom_zicboz_zicbop_zihintpause_zicond_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu0_intc: interrupt-controller {
|
||||
|
@ -42,7 +42,7 @@
|
|||
device_type = "cpu";
|
||||
reg = <1>;
|
||||
status = "okay";
|
||||
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
riscv,isa = "rv64imafdcv_zicsr_zifencei_zicbom_zicboz_zicbop_zihintpause_zicond_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu1_intc: interrupt-controller {
|
||||
|
@ -56,7 +56,7 @@
|
|||
device_type = "cpu";
|
||||
reg = <2>;
|
||||
status = "okay";
|
||||
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
riscv,isa = "rv64imafdcv_zicsr_zifencei_zicbom_zicboz_zicbop_zihintpause_zicond_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu2_intc: interrupt-controller {
|
||||
|
@ -70,7 +70,7 @@
|
|||
device_type = "cpu";
|
||||
reg = <3>;
|
||||
status = "okay";
|
||||
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
riscv,isa = "rv64imafdcv_zicsr_zifencei_zicbom_zicboz_zicbop_zihintpause_zicond_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu3_intc: interrupt-controller {
|
||||
|
@ -84,7 +84,7 @@
|
|||
device_type = "cpu";
|
||||
reg = <4>;
|
||||
status = "okay";
|
||||
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
riscv,isa = "rv64imafdcv_zicsr_zifencei_zicbom_zicboz_zicbop_zihintpause_zicond_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu4_intc: interrupt-controller {
|
||||
|
@ -98,7 +98,7 @@
|
|||
device_type = "cpu";
|
||||
reg = <5>;
|
||||
status = "okay";
|
||||
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
riscv,isa = "rv64imafdcv_zicsr_zifencei_zicbom_zicboz_zicbop_zihintpause_zicond_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu5_intc: interrupt-controller {
|
||||
|
@ -112,7 +112,7 @@
|
|||
device_type = "cpu";
|
||||
reg = <6>;
|
||||
status = "okay";
|
||||
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
riscv,isa = "rv64imafdcv_zicsr_zifencei_zicbom_zicboz_zicbop_zihintpause_zicond_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu6_intc: interrupt-controller {
|
||||
|
@ -126,7 +126,7 @@
|
|||
device_type = "cpu";
|
||||
reg = <7>;
|
||||
status = "okay";
|
||||
riscv,isa = "rv64imafdcvsu_zicsr_zifencei_zicbom_zihintpause_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
riscv,isa = "rv64imafdcv_zicsr_zifencei_zicbom_zicboz_zicbop_zihintpause_zicond_zba_zbb_zbc_zbs_svpbmt_sstc_sscofpmf";
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu7_intc: interrupt-controller {
|
||||
|
@ -872,4 +872,20 @@
|
|||
*/
|
||||
<0x0 0x0 0xffffffff 0xffffff00 0x0007fff8>;
|
||||
};
|
||||
|
||||
watchdog:watchdog@D4080000 {
|
||||
compatible = "spacemit,k1x-wdt";
|
||||
reg = <0x0 0xD4080000 0x0 0x1000>,
|
||||
<0x0 0xD4051020 0x0 0x4>;
|
||||
clocks = <&ccu CLK_WDT>;
|
||||
resets = <&reset RESET_WDT>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
wdt_reboot {
|
||||
compatible = "wdt-reboot";
|
||||
wdt = <&watchdog>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -171,10 +171,10 @@
|
|||
dr_mode = "host";
|
||||
phy_type = "utmi";
|
||||
snps,dis_enblslpm_quirk;
|
||||
snps,dis-u2-freeclk-exists-quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis_u2_susphy_quirk;
|
||||
snps,dis_u3_susphy_quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis-tx-ipgap-linecheck-quirk;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -128,10 +128,10 @@
|
|||
dr_mode = "host";
|
||||
phy_type = "utmi";
|
||||
snps,dis_enblslpm_quirk;
|
||||
snps,dis-u2-freeclk-exists-quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis_u2_susphy_quirk;
|
||||
snps,dis_u3_susphy_quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis-tx-ipgap-linecheck-quirk;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -188,10 +188,10 @@
|
|||
dr_mode = "host";
|
||||
phy_type = "utmi";
|
||||
snps,dis_enblslpm_quirk;
|
||||
snps,dis-u2-freeclk-exists-quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis_u2_susphy_quirk;
|
||||
snps,dis_u3_susphy_quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis-tx-ipgap-linecheck-quirk;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -200,7 +200,6 @@
|
|||
pinctrl-0 = <&pinctrl_mmc1 &gpio80_pmx_func0>;
|
||||
bus-width = <4>;
|
||||
cd-gpios = <&gpio 80 0>;
|
||||
cd-inverted;
|
||||
cap-sd-highspeed;
|
||||
sdh-phy-module = <0>;
|
||||
clk-src-freq = <204800000>;
|
||||
|
@ -257,7 +256,7 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
/*&qspi {
|
||||
&qspi {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_qspi>;
|
||||
|
@ -270,7 +269,7 @@
|
|||
broken-flash-reset;
|
||||
status = "okay";
|
||||
};
|
||||
};*/
|
||||
};
|
||||
|
||||
&efuse {
|
||||
status = "okay";
|
||||
|
|
|
@ -173,10 +173,10 @@
|
|||
dr_mode = "host";
|
||||
phy_type = "utmi";
|
||||
snps,dis_enblslpm_quirk;
|
||||
snps,dis-u2-freeclk-exists-quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis_u2_susphy_quirk;
|
||||
snps,dis_u3_susphy_quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis-tx-ipgap-linecheck-quirk;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -170,10 +170,10 @@
|
|||
dr_mode = "host";
|
||||
phy_type = "utmi";
|
||||
snps,dis_enblslpm_quirk;
|
||||
snps,dis-u2-freeclk-exists-quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis_u2_susphy_quirk;
|
||||
snps,dis_u3_susphy_quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis-tx-ipgap-linecheck-quirk;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -121,10 +121,13 @@
|
|||
&usbdrd3 {
|
||||
status = "disabled";
|
||||
dwc3@c0a00000 {
|
||||
maximum-speed = "high-speed";
|
||||
dr_mode = "peripheral";
|
||||
phy_type = "utmi_wide";
|
||||
dr_mode = "host";
|
||||
phy_type = "utmi";
|
||||
snps,dis_enblslpm_quirk;
|
||||
snps,dis_u2_susphy_quirk;
|
||||
snps,dis_u3_susphy_quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis-tx-ipgap-linecheck-quirk;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -121,10 +121,10 @@
|
|||
dr_mode = "host";
|
||||
phy_type = "utmi";
|
||||
snps,dis_enblslpm_quirk;
|
||||
snps,dis-u2-freeclk-exists-quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis_u2_susphy_quirk;
|
||||
snps,dis_u3_susphy_quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis-tx-ipgap-linecheck-quirk;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -141,10 +141,10 @@
|
|||
dr_mode = "host";
|
||||
phy_type = "utmi";
|
||||
snps,dis_enblslpm_quirk;
|
||||
snps,dis-u2-freeclk-exists-quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis_u2_susphy_quirk;
|
||||
snps,dis_u3_susphy_quirk;
|
||||
snps,dis-del-phy-power-chg-quirk;
|
||||
snps,dis-tx-ipgap-linecheck-quirk;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -12,6 +12,13 @@
|
|||
bus = <8>;
|
||||
u-boot,dm-spl;
|
||||
|
||||
pmic-reset {
|
||||
compatible = "spacemit,spm8821-reset";
|
||||
reboot-reg = <0x7e>; /* Address of the reboot register */
|
||||
reboot-mask = <0x02>; /* Bit mask for triggering a reboot */
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
regulators {
|
||||
/* buck */
|
||||
dcdc_6: DCDC_REG1 {
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
# Copyright (c) 2022-2023 Spacemit, Inc
|
||||
|
||||
obj-y += k1x.o
|
||||
obj-$(CONFIG_SPL_BUILD) += spl.o k1x-i2c-eeprom.o
|
||||
obj-$(CONFIG_SPL_BUILD) += spl.o k1x-i2c-eeprom.o k1x-tlvinfo.o
|
||||
obj-$(CONFIG_SPLASH_SOURCE) +=splash.o
|
||||
|
|
|
@ -18,14 +18,23 @@ nor_rootfstype=squashfs
|
|||
// eMMC/SDCard rootfs device
|
||||
mmc_rootfstype=ext4
|
||||
|
||||
// rootfs part number must less than 99
|
||||
rootfs_part_to_ul=echo "set rootfs_part to ul"; setexpr temp_num_0 ${rootfs_part} / a;\
|
||||
setexpr temp_num_1 ${rootfs_part} % a;\
|
||||
setenv rootfs_part ${temp_num_0}${temp_num_1};
|
||||
|
||||
// Get "rootfs" partition number in decimal, and set var "mmc_root"
|
||||
// Variable "boot_devnum" is set during board_lat_init()
|
||||
set_mmc_root=part number mmc ${boot_devnum} rootfs rootfs_part; \
|
||||
setexpr rootfs_part ${rootfs_part} + 0; \
|
||||
if test ${rootfs_part} > 9 ; then run rootfs_part_to_ul;fi; \
|
||||
echo "get rootfs_part index:${rootfs_part}"; \
|
||||
setenv mmc_root "/dev/mmcblk${boot_devnum}p${rootfs_part}";
|
||||
|
||||
set_nvme_root=part number nvme ${boot_devnum} rootfs rootfs_part; \
|
||||
setexpr rootfs_part ${rootfs_part} + 0; \
|
||||
if test ${rootfs_part} > 9 ; then run rootfs_part_to_ul;fi; \
|
||||
echo "get rootfs_part index:${rootfs_part}"; \
|
||||
setenv nvme_root "/dev/nvme${boot_devnum}n1p${rootfs_part}";
|
||||
|
||||
//override here, otherwise gen random addr and save to eeprom by uboot
|
||||
|
@ -74,7 +83,7 @@ dtb_env=if test -n "${product_name}"; then \
|
|||
elif test "${product_name}" = k1_MINI-PC; then \
|
||||
setenv dtb_name ${dtb_dir}/k1-x_MINI-PC.dtb; \
|
||||
else \
|
||||
echo "falling to default dtb: ${dtb_dir}/${product_name}.dtb"; \
|
||||
echo "match dtb by product_name: ${dtb_dir}/${product_name}.dtb"; \
|
||||
setenv dtb_name ${dtb_dir}/${product_name}.dtb; \
|
||||
fi; \
|
||||
fi;
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <asm/io.h>
|
||||
#include <common.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <stdlib.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
|
@ -19,6 +21,7 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
#define PULL_UP BIT(14) | BIT(15) /* pull-up */
|
||||
|
||||
#define I2C_PIN_CONFIG(x) ((x) | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
|
||||
#define READ_I2C_LINE_LEN (16)
|
||||
|
||||
char *spacemit_i2c_eeprom[] = {
|
||||
"atmel,24c02",
|
||||
|
@ -122,3 +125,65 @@ int k1x_eeprom_init(void)
|
|||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int _read_from_i2c(int chip, u32 addr, u32 size, uchar *buf)
|
||||
{
|
||||
u32 nbytes = size;
|
||||
u32 linebytes = 0;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
linebytes = (nbytes > READ_I2C_LINE_LEN) ? READ_I2C_LINE_LEN : nbytes;
|
||||
ret = i2c_read(chip, addr, 1, buf, linebytes);
|
||||
if (ret){
|
||||
pr_err("read from i2c error:%d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf += linebytes;
|
||||
nbytes -= linebytes;
|
||||
addr += linebytes;
|
||||
} while (nbytes > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _write_to_i2c(int chip, u32 addr, u32 size, uchar *buf)
|
||||
{
|
||||
uint nbytes = size;
|
||||
int ret;
|
||||
|
||||
while (nbytes-- > 0) {
|
||||
ret = i2c_write(chip, addr++, 1, buf++, 1);
|
||||
if (ret){
|
||||
pr_err("write to i2c error:%d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* No write delay with FRAM devices.
|
||||
*/
|
||||
#if !defined(CONFIG_SYS_I2C_FRAM)
|
||||
udelay(11000);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clear_eeprom(u32 dev, u32 erase_size)
|
||||
{
|
||||
char *blank_buf = calloc(0, erase_size);
|
||||
|
||||
int chip = k1x_eeprom_init();
|
||||
if (chip < 0){
|
||||
pr_err("can not get i2c bus addr\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_write_to_i2c(chip, 0, erase_size, blank_buf)){
|
||||
pr_err("clear eeprom fail\n");
|
||||
return -1;
|
||||
}
|
||||
free(blank_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
593
board/spacemit/k1-x/k1x-tlvinfo.c
Normal file
593
board/spacemit/k1-x/k1x-tlvinfo.c
Normal file
|
@ -0,0 +1,593 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <stdlib.h>
|
||||
#include <tlv_eeprom.h>
|
||||
#include <u-boot/crc.h>
|
||||
#include <net.h>
|
||||
|
||||
#define EEPROM_SIZE (256)
|
||||
#define EEPROM_SIZE_MAX_TLV_LEN (EEPROM_SIZE - sizeof(struct tlvinfo_header))
|
||||
|
||||
extern int k1x_eeprom_init(void);
|
||||
extern int _read_from_i2c(int chip, u32 addr, u32 size, uchar *buf);
|
||||
extern int _write_to_i2c(int chip, u32 addr, u32 size, uchar *buf);
|
||||
|
||||
/* File scope function prototypes */
|
||||
static bool is_checksum_valid(u8 *eeprom);
|
||||
static void update_crc(u8 *eeprom);
|
||||
static bool tlvinfo_find_tlv(u8 *eeprom, u8 tcode, int *eeprom_index);
|
||||
static bool tlvinfo_delete_tlv(u8 *eeprom, u8 code);
|
||||
static bool tlvinfo_add_tlv(u8 *eeprom, int tcode, char *strval);
|
||||
static int set_mac(char *buf, const char *string);
|
||||
static int set_date(char *buf, const char *string);
|
||||
static int set_bytes(char *buf, const char *string, int *converted_accum);
|
||||
|
||||
static u8 tlvinfo_eeprom[EEPROM_SIZE];
|
||||
static bool had_read_tlvinfo = false;
|
||||
|
||||
/**
|
||||
* _is_valid_tlvinfo_header
|
||||
*
|
||||
* Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM
|
||||
* data pointed to by the parameter:
|
||||
* 1. First 8 bytes contain null-terminated ASCII string "TlvInfo"
|
||||
* 2. Version byte is 1
|
||||
* 3. Total length bytes contain value which is less than or equal
|
||||
* to the allowed maximum (2048-11)
|
||||
*
|
||||
*/
|
||||
static bool _is_valid_tlvinfo_header(struct tlvinfo_header *hdr)
|
||||
{
|
||||
return ((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) &&
|
||||
(hdr->version == TLV_INFO_VERSION) &&
|
||||
(be16_to_cpu(hdr->totallen) <= TLV_TOTAL_LEN_MAX));
|
||||
}
|
||||
|
||||
static inline bool is_valid_tlv(struct tlvinfo_tlv *tlv)
|
||||
{
|
||||
return((tlv->type != 0x00) && (tlv->type != 0xFF));
|
||||
}
|
||||
|
||||
static inline bool is_digit(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
/**
|
||||
* is_hex
|
||||
*
|
||||
* Tests if character is an ASCII hex digit
|
||||
*/
|
||||
static inline u8 is_hex(char p)
|
||||
{
|
||||
return (((p >= '0') && (p <= '9')) ||
|
||||
((p >= 'A') && (p <= 'F')) ||
|
||||
((p >= 'a') && (p <= 'f')));
|
||||
}
|
||||
|
||||
/**
|
||||
* is_checksum_valid
|
||||
*
|
||||
* Validate the checksum in the provided TlvInfo EEPROM data. First,
|
||||
* verify that the TlvInfo header is valid, then make sure the last
|
||||
* TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data
|
||||
* and compare it to the value stored in the EEPROM CRC-32 TLV.
|
||||
*/
|
||||
static bool is_checksum_valid(u8 *eeprom)
|
||||
{
|
||||
struct tlvinfo_header *eeprom_hdr = (struct tlvinfo_header *)eeprom;
|
||||
struct tlvinfo_tlv *eeprom_crc;
|
||||
unsigned int calc_crc;
|
||||
unsigned int stored_crc;
|
||||
|
||||
// Is the eeprom header valid?
|
||||
if (!_is_valid_tlvinfo_header(eeprom_hdr)){
|
||||
pr_err("%s, not valid tlv info header\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the last TLV a CRC?
|
||||
eeprom_crc = (struct tlvinfo_tlv *)(&eeprom[sizeof(struct tlvinfo_header) +
|
||||
be16_to_cpu(eeprom_hdr->totallen) - (sizeof(struct tlvinfo_tlv) + 4)]);
|
||||
if (eeprom_crc->type != TLV_CODE_CRC_32 || eeprom_crc->length != 4)
|
||||
return false;
|
||||
|
||||
// Calculate the checksum
|
||||
calc_crc = crc32(0, (void *)eeprom,
|
||||
sizeof(struct tlvinfo_header) + be16_to_cpu(eeprom_hdr->totallen) - 4);
|
||||
stored_crc = (eeprom_crc->value[0] << 24) |
|
||||
(eeprom_crc->value[1] << 16) |
|
||||
(eeprom_crc->value[2] << 8) |
|
||||
eeprom_crc->value[3];
|
||||
|
||||
return calc_crc == stored_crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_mac
|
||||
*
|
||||
* Converts a string MAC address into a binary buffer.
|
||||
*
|
||||
* This function takes a pointer to a MAC address string
|
||||
* (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number).
|
||||
* The string format is verified and then converted to binary and
|
||||
* stored in a buffer.
|
||||
*/
|
||||
static int set_mac(char *buf, const char *string)
|
||||
{
|
||||
char *p = (char *)string;
|
||||
int i;
|
||||
int err = 0;
|
||||
char *end;
|
||||
|
||||
if (!p) {
|
||||
pr_err("ERROR: NULL mac addr string passed in.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen(p) != 17) {
|
||||
pr_err("ERROR: MAC address strlen() != 17 -- %zu\n", strlen(p));
|
||||
pr_err("ERROR: Bad MAC address format: %s\n", string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 17; i++) {
|
||||
if ((i % 3) == 2) {
|
||||
if (p[i] != ':') {
|
||||
err++;
|
||||
pr_err("ERROR: mac: p[%i] != :, found: `%c'\n",
|
||||
i, p[i]);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
} else if (!is_hex(p[i])) {
|
||||
err++;
|
||||
pr_err("ERROR: mac: p[%i] != hex digit, found: `%c'\n",
|
||||
i, p[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
pr_err("ERROR: Bad MAC address format: %s\n", string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert string to binary */
|
||||
for (i = 0, p = (char *)string; i < 6; i++) {
|
||||
buf[i] = p ? hextoul(p, &end) : 0;
|
||||
if (p)
|
||||
p = (*end) ? end + 1 : end;
|
||||
}
|
||||
|
||||
if (!is_valid_ethaddr((u8 *)buf)) {
|
||||
pr_err("ERROR: MAC address must not be 00:00:00:00:00:00, a multicast address or FF:FF:FF:FF:FF:FF.\n");
|
||||
pr_err("ERROR: Bad MAC address format: %s\n", string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_date
|
||||
*
|
||||
* Validates the format of the data string
|
||||
*
|
||||
* This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss)
|
||||
* and validates that the format is correct. If so the string is copied
|
||||
* to the supplied buffer.
|
||||
*/
|
||||
static int set_date(char *buf, const char *string)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!string) {
|
||||
pr_err("ERROR: NULL date string passed in.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen(string) != 19) {
|
||||
pr_err("ERROR: Date strlen() != 19 -- %zu\n", strlen(string));
|
||||
pr_err("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
|
||||
string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; string[i] != 0; i++) {
|
||||
switch (i) {
|
||||
case 2:
|
||||
case 5:
|
||||
if (string[i] != '/') {
|
||||
pr_err("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
|
||||
string);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (string[i] != ' ') {
|
||||
pr_err("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
|
||||
string);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
case 16:
|
||||
if (string[i] != ':') {
|
||||
pr_err("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
|
||||
string);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!is_digit(string[i])) {
|
||||
pr_err("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
|
||||
string);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
strcpy(buf, string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_bytes
|
||||
*
|
||||
* Converts a space-separated string of decimal numbers into a
|
||||
* buffer of bytes.
|
||||
*
|
||||
* This function takes a pointer to a space-separated string of decimal
|
||||
* numbers (i.e. "128 0x55 0321") with "C" standard radix specifiers
|
||||
* and converts them to an array of bytes.
|
||||
*/
|
||||
static int set_bytes(char *buf, const char *string, int *converted_accum)
|
||||
{
|
||||
char *p = (char *)string;
|
||||
int i;
|
||||
uint byte;
|
||||
|
||||
if (!p) {
|
||||
pr_err("ERROR: NULL string passed in.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert string to bytes */
|
||||
for (i = 0, p = (char *)string; (i < TLV_VALUE_MAX_LEN) && (*p != 0);
|
||||
i++) {
|
||||
while ((*p == ' ') || (*p == '\t') || (*p == ',') ||
|
||||
(*p == ';')) {
|
||||
p++;
|
||||
}
|
||||
if (*p != 0) {
|
||||
if (!is_digit(*p)) {
|
||||
pr_err("ERROR: Non-digit found in byte string: (%s)\n",
|
||||
string);
|
||||
return -1;
|
||||
}
|
||||
byte = simple_strtoul(p, &p, 0);
|
||||
if (byte >= EEPROM_SIZE) {
|
||||
pr_err("ERROR: The value specified is greater than 255: (%u) in string: %s\n",
|
||||
byte, string);
|
||||
return -1;
|
||||
}
|
||||
buf[i] = byte & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == TLV_VALUE_MAX_LEN && (*p != 0)) {
|
||||
pr_err("ERROR: Trying to assign too many bytes (max: %d) in string: %s\n",
|
||||
TLV_VALUE_MAX_LEN, string);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*converted_accum = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* tlvinfo_find_tlv
|
||||
*
|
||||
* This function finds the TLV with the supplied code in the EERPOM.
|
||||
* An offset from the beginning of the EEPROM is returned in the
|
||||
* eeprom_index parameter if the TLV is found.
|
||||
*/
|
||||
static bool tlvinfo_find_tlv(u8 *eeprom, u8 tcode, int *eeprom_index)
|
||||
{
|
||||
struct tlvinfo_header *eeprom_hdr = (struct tlvinfo_header *)eeprom;
|
||||
struct tlvinfo_tlv *eeprom_tlv;
|
||||
int eeprom_end;
|
||||
|
||||
// Search through the TLVs, looking for the first one which matches the
|
||||
// supplied type code.
|
||||
*eeprom_index = sizeof(struct tlvinfo_header);
|
||||
eeprom_end = sizeof(struct tlvinfo_header) + be16_to_cpu(eeprom_hdr->totallen);
|
||||
while (*eeprom_index < eeprom_end) {
|
||||
eeprom_tlv = (struct tlvinfo_tlv *)(&eeprom[*eeprom_index]);
|
||||
if (!is_valid_tlv(eeprom_tlv))
|
||||
return false;
|
||||
if (eeprom_tlv->type == tcode)
|
||||
return true;
|
||||
*eeprom_index += sizeof(struct tlvinfo_tlv) + eeprom_tlv->length;
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* update_crc
|
||||
*
|
||||
* This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then
|
||||
* one is added. This function should be called after each update to the
|
||||
* EEPROM structure, to make sure the CRC is always correct.
|
||||
*/
|
||||
static void update_crc(u8 *eeprom)
|
||||
{
|
||||
struct tlvinfo_header *eeprom_hdr = (struct tlvinfo_header *)eeprom;
|
||||
struct tlvinfo_tlv *eeprom_crc;
|
||||
unsigned int calc_crc;
|
||||
int eeprom_index;
|
||||
|
||||
// Discover the CRC TLV
|
||||
if (!tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index)) {
|
||||
unsigned int totallen = be16_to_cpu(eeprom_hdr->totallen);
|
||||
|
||||
if ((totallen + sizeof(struct tlvinfo_tlv) + 4) > EEPROM_SIZE_MAX_TLV_LEN)
|
||||
return;
|
||||
eeprom_index = sizeof(struct tlvinfo_header) + totallen;
|
||||
eeprom_hdr->totallen = cpu_to_be16(totallen + sizeof(struct tlvinfo_tlv) + 4);
|
||||
}
|
||||
eeprom_crc = (struct tlvinfo_tlv *)(&eeprom[eeprom_index]);
|
||||
eeprom_crc->type = TLV_CODE_CRC_32;
|
||||
eeprom_crc->length = 4;
|
||||
|
||||
// Calculate the checksum
|
||||
calc_crc = crc32(0, (void *)eeprom,
|
||||
sizeof(struct tlvinfo_header) + be16_to_cpu(eeprom_hdr->totallen) - 4);
|
||||
eeprom_crc->value[0] = (calc_crc >> 24) & 0xFF;
|
||||
eeprom_crc->value[1] = (calc_crc >> 16) & 0xFF;
|
||||
eeprom_crc->value[2] = (calc_crc >> 8) & 0xFF;
|
||||
eeprom_crc->value[3] = (calc_crc >> 0) & 0xFF;
|
||||
}
|
||||
|
||||
static bool tlvinfo_add_tlv(u8 *eeprom, int tcode, char *strval)
|
||||
{
|
||||
struct tlvinfo_header *eeprom_hdr = (struct tlvinfo_header *)eeprom;
|
||||
struct tlvinfo_tlv *eeprom_tlv;
|
||||
int new_tlv_len = 0;
|
||||
u32 value;
|
||||
char data[EEPROM_SIZE];
|
||||
int eeprom_index;
|
||||
|
||||
// Encode each TLV type into the format to be stored in the EERPOM
|
||||
switch (tcode) {
|
||||
case TLV_CODE_PRODUCT_NAME:
|
||||
case TLV_CODE_PART_NUMBER:
|
||||
case TLV_CODE_SERIAL_NUMBER:
|
||||
case TLV_CODE_LABEL_REVISION:
|
||||
case TLV_CODE_PLATFORM_NAME:
|
||||
case TLV_CODE_ONIE_VERSION:
|
||||
case TLV_CODE_MANUF_NAME:
|
||||
case TLV_CODE_MANUF_COUNTRY:
|
||||
case TLV_CODE_VENDOR_NAME:
|
||||
case TLV_CODE_DIAG_VERSION:
|
||||
case TLV_CODE_SERVICE_TAG:
|
||||
strncpy(data, strval, EEPROM_SIZE);
|
||||
new_tlv_len = min_t(size_t, EEPROM_SIZE, strlen(strval));
|
||||
break;
|
||||
case TLV_CODE_DEVICE_VERSION:
|
||||
value = simple_strtoul(strval, NULL, 0);
|
||||
if (value >= EEPROM_SIZE) {
|
||||
pr_err("ERROR: Device version must be 255 or less. Value supplied: %u",
|
||||
value);
|
||||
return false;
|
||||
}
|
||||
data[0] = value & 0xFF;
|
||||
new_tlv_len = 1;
|
||||
break;
|
||||
case TLV_CODE_MAC_SIZE:
|
||||
value = simple_strtoul(strval, NULL, 0);
|
||||
if (value >= 65536) {
|
||||
pr_err("ERROR: MAC Size must be 65535 or less. Value supplied: %u",
|
||||
value);
|
||||
return false;
|
||||
}
|
||||
data[0] = (value >> 8) & 0xFF;
|
||||
data[1] = value & 0xFF;
|
||||
new_tlv_len = 2;
|
||||
break;
|
||||
case TLV_CODE_MANUF_DATE:
|
||||
if (set_date(data, strval) != 0)
|
||||
return false;
|
||||
new_tlv_len = 19;
|
||||
break;
|
||||
case TLV_CODE_MAC_BASE:
|
||||
if (set_mac(data, strval) != 0)
|
||||
return false;
|
||||
new_tlv_len = 6;
|
||||
break;
|
||||
case TLV_CODE_CRC_32:
|
||||
pr_err("WARNING: The CRC TLV is set automatically and cannot be set manually.\n");
|
||||
return false;
|
||||
case TLV_CODE_VENDOR_EXT:
|
||||
default:
|
||||
if (set_bytes(data, strval, &new_tlv_len) != 0)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Is there room for this TLV?
|
||||
if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(struct tlvinfo_tlv) + new_tlv_len) >
|
||||
EEPROM_SIZE_MAX_TLV_LEN) {
|
||||
pr_err("ERROR: There is not enough room in the EERPOM to save data.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add TLV at the end, overwriting CRC TLV if it exists
|
||||
if (tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index))
|
||||
eeprom_hdr->totallen =
|
||||
cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) -
|
||||
sizeof(struct tlvinfo_tlv) - 4);
|
||||
else
|
||||
eeprom_index = sizeof(struct tlvinfo_header) + be16_to_cpu(eeprom_hdr->totallen);
|
||||
eeprom_tlv = (struct tlvinfo_tlv *)(&eeprom[eeprom_index]);
|
||||
eeprom_tlv->type = tcode;
|
||||
eeprom_tlv->length = new_tlv_len;
|
||||
memcpy(eeprom_tlv->value, data, new_tlv_len);
|
||||
|
||||
// Update the total length and calculate (add) a new CRC-32 TLV
|
||||
eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) +
|
||||
sizeof(struct tlvinfo_tlv) + new_tlv_len);
|
||||
update_crc(eeprom);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool tlvinfo_delete_tlv(u8 *eeprom, u8 code)
|
||||
{
|
||||
int eeprom_index;
|
||||
int tlength;
|
||||
struct tlvinfo_header *eeprom_hdr = (struct tlvinfo_header *)eeprom;
|
||||
struct tlvinfo_tlv *eeprom_tlv;
|
||||
|
||||
// Find the TLV and then move all following TLVs "forward"
|
||||
if (tlvinfo_find_tlv(eeprom, code, &eeprom_index)) {
|
||||
eeprom_tlv = (struct tlvinfo_tlv *)(&eeprom[eeprom_index]);
|
||||
tlength = sizeof(struct tlvinfo_tlv) + eeprom_tlv->length;
|
||||
memcpy(&eeprom[eeprom_index], &eeprom[eeprom_index + tlength],
|
||||
sizeof(struct tlvinfo_header) +
|
||||
be16_to_cpu(eeprom_hdr->totallen) - eeprom_index -
|
||||
tlength);
|
||||
eeprom_hdr->totallen =
|
||||
cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) -
|
||||
tlength);
|
||||
update_crc(eeprom);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static int read_tlvinfo_from_eeprom(u8 *eeprom)
|
||||
{
|
||||
struct tlvinfo_header *eeprom_hdr = (struct tlvinfo_header *)eeprom;
|
||||
struct tlvinfo_tlv *eeprom_tlv = (struct tlvinfo_tlv *)(&eeprom[sizeof(struct tlvinfo_header)]);
|
||||
int chip;
|
||||
|
||||
chip = k1x_eeprom_init();
|
||||
if (chip < 0){
|
||||
pr_err("can not get i2c bus addr\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*read tlv head info*/
|
||||
if (_read_from_i2c(chip, 0, sizeof(struct tlvinfo_header), (uchar *)eeprom_hdr)){
|
||||
pr_err("read tlvinfo_header from i2c fail\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_is_valid_tlvinfo_header(eeprom_hdr)){
|
||||
if (_read_from_i2c(chip, sizeof(struct tlvinfo_header), be16_to_cpu(eeprom_hdr->totallen),
|
||||
(uchar *)eeprom_tlv)){
|
||||
pr_err("read tlvinvo_tlv from i2c fail\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// If the contents are invalid, start over with default contents
|
||||
if (!_is_valid_tlvinfo_header(eeprom_hdr) ||
|
||||
!is_checksum_valid(eeprom)) {
|
||||
strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING);
|
||||
eeprom_hdr->version = TLV_INFO_VERSION;
|
||||
eeprom_hdr->totallen = cpu_to_be16(0);
|
||||
pr_info("update new tlv info\n");
|
||||
update_crc(eeprom);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_tlvinfo_from_eeprom(int tcode, char *buf)
|
||||
{
|
||||
int tlv_end;
|
||||
int curr_tlv;
|
||||
u8 eeprom[EEPROM_SIZE];
|
||||
memset(eeprom, 0, EEPROM_SIZE);
|
||||
|
||||
if (read_tlvinfo_from_eeprom(eeprom)){
|
||||
pr_err("read tlv info fail\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct tlvinfo_header *eeprom_hdr = (struct tlvinfo_header *)eeprom;
|
||||
struct tlvinfo_tlv *eeprom_tlv;
|
||||
|
||||
curr_tlv = sizeof(struct tlvinfo_header);
|
||||
tlv_end = sizeof(struct tlvinfo_header) + be16_to_cpu(eeprom_hdr->totallen);
|
||||
while (curr_tlv < tlv_end) {
|
||||
eeprom_tlv = (struct tlvinfo_tlv *)(&eeprom[curr_tlv]);
|
||||
if (!is_valid_tlv(eeprom_tlv)) {
|
||||
pr_err("Invalid TLV field starting at EEPROM offset %d\n",
|
||||
curr_tlv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (eeprom_tlv->type == tcode){
|
||||
memcpy(buf, eeprom_tlv->value, eeprom_tlv->length);
|
||||
pr_info("get tlvinfo value:%x,%s\n", tcode, buf);
|
||||
return 0;
|
||||
}
|
||||
curr_tlv += sizeof(struct tlvinfo_tlv) + eeprom_tlv->length;
|
||||
}
|
||||
pr_info("can not get tlvinfo index:%x\n", tcode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int set_val_to_tlvinfo(int tcode, char *val)
|
||||
{
|
||||
if (!had_read_tlvinfo){
|
||||
/*read tlvinfo at first*/
|
||||
read_tlvinfo_from_eeprom(tlvinfo_eeprom);
|
||||
had_read_tlvinfo = true;
|
||||
}
|
||||
|
||||
tlvinfo_delete_tlv(tlvinfo_eeprom, tcode);
|
||||
if (val != NULL)
|
||||
tlvinfo_add_tlv(tlvinfo_eeprom, tcode, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_tlvinfo_to_eeprom(void)
|
||||
{
|
||||
struct tlvinfo_header *eeprom_hdr;
|
||||
int eeprom_len;
|
||||
|
||||
int chip = k1x_eeprom_init();
|
||||
if (chip < 0){
|
||||
pr_err("can not get i2c bus addr\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!had_read_tlvinfo){
|
||||
/*read tlvinfo at first*/
|
||||
read_tlvinfo_from_eeprom(tlvinfo_eeprom);
|
||||
had_read_tlvinfo = true;
|
||||
}
|
||||
|
||||
eeprom_hdr = (struct tlvinfo_header *)tlvinfo_eeprom;
|
||||
update_crc(tlvinfo_eeprom);
|
||||
|
||||
eeprom_len = sizeof(struct tlvinfo_header) + be16_to_cpu(eeprom_hdr->totallen);
|
||||
if (_write_to_i2c(chip, 0, eeprom_len, tlvinfo_eeprom)){
|
||||
pr_err("write to eeprom fail\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -32,13 +32,16 @@
|
|||
#include <tlv_eeprom.h>
|
||||
#include <u-boot/crc.h>
|
||||
#include <fb_mtd.h>
|
||||
#include <power/pmic.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <g_dnl.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
static char found_partition[64] = {0};
|
||||
extern u32 ddr_cs_num;
|
||||
#ifdef CONFIG_DISPLAY_SPACEMIT_HDMI
|
||||
extern int is_hdmi_connected;
|
||||
#endif
|
||||
bool is_video_connected = false;
|
||||
uint32_t reboot_config;
|
||||
void refresh_config_info(u8 *eeprom_data);
|
||||
int mac_read_from_buffer(u8 *eeprom_data);
|
||||
|
||||
|
@ -100,6 +103,16 @@ enum board_boot_mode get_boot_mode(void)
|
|||
return get_boot_pin_select();
|
||||
}
|
||||
|
||||
void set_serialnumber_based_on_boot_mode(void)
|
||||
{
|
||||
const char *s = env_get("serial#");
|
||||
enum board_boot_mode boot_mode = get_boot_mode();
|
||||
|
||||
if (boot_mode != BOOT_MODE_USB && s) {
|
||||
g_dnl_set_serialnumber((char *)s);
|
||||
}
|
||||
}
|
||||
|
||||
enum board_boot_mode get_boot_storage(void)
|
||||
{
|
||||
enum board_boot_mode boot_storage = get_boot_mode();
|
||||
|
@ -218,17 +231,59 @@ void get_ddr_config_info(void)
|
|||
ddr_cs_num = DDR_CS_NUM;
|
||||
}
|
||||
|
||||
u32 get_reboot_config(void)
|
||||
{
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
u32 flag = 0;
|
||||
uint8_t value;
|
||||
|
||||
if (reboot_config)
|
||||
return reboot_config;
|
||||
|
||||
/* K1 has non-reset register(BOOT_CIU_DEBUG_REG0) to save boot config
|
||||
before system reboot, but it will be clear when K1 power is down,
|
||||
then boot config will be save in P1.
|
||||
*/
|
||||
flag = readl((void *)BOOT_CIU_DEBUG_REG0);
|
||||
if ((BOOT_MODE_SHELL == flag) || (BOOT_MODE_USB == flag)) {
|
||||
/* reset */
|
||||
writel(0, (void *)BOOT_CIU_DEBUG_REG0);
|
||||
reboot_config = flag;
|
||||
}
|
||||
else {
|
||||
// select boot mode from boot strap pin
|
||||
reboot_config = BOOT_MODE_BOOTSTRAP;
|
||||
ret = uclass_get_device_by_driver(UCLASS_PMIC,
|
||||
DM_DRIVER_GET(spacemit_pm8xx), &dev);
|
||||
if (ret) {
|
||||
pr_err("PMIC init failed: %d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
pmic_read(dev, P1_NON_RESET_REG, &value, 1);
|
||||
pr_info("Read PMIC reg %x value %x\n", P1_NON_RESET_REG, value);
|
||||
if (1 == (value & 3)) {
|
||||
reboot_config = BOOT_MODE_USB;
|
||||
value &= ~3;
|
||||
pmic_write(dev, P1_NON_RESET_REG, &value, 1);
|
||||
}
|
||||
else if (2 == (value & 3)) {
|
||||
reboot_config = BOOT_MODE_SHELL;
|
||||
value &= ~3;
|
||||
pmic_write(dev, P1_NON_RESET_REG, &value, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return reboot_config;
|
||||
}
|
||||
|
||||
void run_fastboot_command(void)
|
||||
{
|
||||
u32 boot_mode = get_boot_mode();
|
||||
|
||||
/*if define BOOT_MODE_USB flag in BOOT_CIU_DEBUG_REG0, it would excute fastboot*/
|
||||
u32 cui_flasg = readl((void *)BOOT_CIU_DEBUG_REG0);
|
||||
if (boot_mode == BOOT_MODE_USB || cui_flasg == BOOT_MODE_USB){
|
||||
if (boot_mode == BOOT_MODE_USB || BOOT_MODE_USB == get_reboot_config()) {
|
||||
/* show flash log*/
|
||||
env_set("stdout", env_get("stdout_flash"));
|
||||
/*would reset debug_reg0*/
|
||||
writel(0, (void *)BOOT_CIU_DEBUG_REG0);
|
||||
|
||||
char *cmd_para = "fastboot 0";
|
||||
run_command(cmd_para, 0);
|
||||
|
@ -242,11 +297,7 @@ int run_uboot_shell(void)
|
|||
{
|
||||
u32 boot_mode = get_boot_mode();
|
||||
|
||||
/*if define BOOT_MODE_SHELL flag in BOOT_CIU_DEBUG_REG0, it would into uboot shell*/
|
||||
u32 flag = readl((void *)BOOT_CIU_DEBUG_REG0);
|
||||
if (boot_mode == BOOT_MODE_SHELL || flag == BOOT_MODE_SHELL){
|
||||
/*would reset debug_reg0*/
|
||||
writel(0, (void *)BOOT_CIU_DEBUG_REG0);
|
||||
if (boot_mode == BOOT_MODE_SHELL || BOOT_MODE_SHELL == get_reboot_config()) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
@ -640,6 +691,9 @@ void set_env_ethaddr(u8 *eeprom_data) {
|
|||
eth_env_set_enetaddr("ethaddr", mac_addr);
|
||||
eth_env_set_enetaddr("eth1addr", mac1_addr);
|
||||
|
||||
/*must read before set/write to eeprom using tlv_eeprom command*/
|
||||
run_command("tlv_eeprom", 0);
|
||||
|
||||
/* save mac address to eeprom */
|
||||
snprintf(cmd_str, (sizeof(cmd_str) - 1), "tlv_eeprom set 0x24 %02x:%02x:%02x:%02x:%02x:%02x", \
|
||||
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||
|
@ -686,6 +740,9 @@ void set_dev_serial_no(uint8_t *eeprom_data)
|
|||
}
|
||||
pr_info("\n");
|
||||
|
||||
/*must read before set/write to eeprom using tlv_eeprom command*/
|
||||
run_command("tlv_eeprom", 0);
|
||||
|
||||
/* save serial number to eeprom */
|
||||
snprintf(cmd_str, (sizeof(cmd_str) - 1), "tlv_eeprom set 0x23 %02x%02x%02x%02x%02x%02x", \
|
||||
sn[0], sn[1], sn[2], sn[3], sn[4], sn[5]);
|
||||
|
@ -706,7 +763,6 @@ void refresh_config_info(u8 *eeprom_data)
|
|||
struct tlvinfo_tlv *tlv_info = NULL;
|
||||
char *strval;
|
||||
int i;
|
||||
char tmp_name[64];
|
||||
|
||||
const struct code_desc_info {
|
||||
u8 m_code;
|
||||
|
@ -742,15 +798,6 @@ void refresh_config_info(u8 *eeprom_data)
|
|||
strval = malloc(tlv_info->length + 1);
|
||||
memcpy(strval, tlv_info->value, tlv_info->length);
|
||||
strval[tlv_info->length] = '\0';
|
||||
|
||||
/*
|
||||
be compatible to previous format name,
|
||||
such as: k1_deb1 -> k1-x_deb1
|
||||
*/
|
||||
if (info[i].m_code == TLV_CODE_PRODUCT_NAME && strncmp(strval, CONFIG_SYS_BOARD, 4)){
|
||||
sprintf(tmp_name, "%s_%s", CONFIG_SYS_BOARD, &strval[3]);
|
||||
strcpy(strval, tmp_name);
|
||||
}
|
||||
}
|
||||
env_set(info[i].m_name, strval);
|
||||
free(strval);
|
||||
|
@ -809,6 +856,19 @@ int board_late_init(void)
|
|||
refresh_config_info(NULL);
|
||||
}
|
||||
|
||||
set_serialnumber_based_on_boot_mode();
|
||||
|
||||
#ifdef CONFIG_VIDEO_SPACEMIT
|
||||
ret = uclass_probe_all(UCLASS_VIDEO);
|
||||
if (ret) {
|
||||
pr_info("video devices not found or not probed yet: %d\n", ret);
|
||||
}
|
||||
ret = uclass_probe_all(UCLASS_DISPLAY);
|
||||
if (ret) {
|
||||
pr_info("display devices not found or not probed yet: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
run_fastboot_command();
|
||||
|
||||
run_cardfirmware_flash_command();
|
||||
|
@ -822,11 +882,9 @@ int board_late_init(void)
|
|||
/*import env.txt from bootfs*/
|
||||
import_env_from_bootfs();
|
||||
|
||||
#ifdef CONFIG_DISPLAY_SPACEMIT_HDMI
|
||||
if (is_hdmi_connected < 0) {
|
||||
if (!is_video_connected) {
|
||||
env_set("stdout", "serial");
|
||||
}
|
||||
#endif
|
||||
|
||||
setenv_boot_mode();
|
||||
|
||||
|
@ -969,8 +1027,18 @@ ulong board_get_usable_ram_top(ulong total_size)
|
|||
#if !defined(CONFIG_SPL_BUILD)
|
||||
int board_fit_config_name_match(const char *name)
|
||||
{
|
||||
char tmp_name[64];
|
||||
char *product_name = env_get("product_name");
|
||||
|
||||
/*
|
||||
be compatible to previous format name,
|
||||
such as: k1_deb1 -> k1-x_deb1
|
||||
*/
|
||||
if (!strncmp(product_name, "k1_", 3)){
|
||||
sprintf(tmp_name, "%s_%s", "k1-x", &product_name[3]);
|
||||
product_name = tmp_name;
|
||||
}
|
||||
|
||||
if ((NULL != product_name) && (0 == strcmp(product_name, name))) {
|
||||
log_emerg("Boot from fit configuration %s\n", name);
|
||||
return 0;
|
||||
|
|
|
@ -526,11 +526,21 @@ void board_init_f(ulong dummy)
|
|||
int board_fit_config_name_match(const char *name)
|
||||
{
|
||||
char *buildin_name;
|
||||
char tmp_name[64];
|
||||
|
||||
buildin_name = product_name;
|
||||
if (NULL == buildin_name)
|
||||
buildin_name = DEFAULT_PRODUCT_NAME;
|
||||
|
||||
/*
|
||||
be compatible to previous format name,
|
||||
such as: k1_deb1 -> k1-x_deb1
|
||||
*/
|
||||
if (!strncmp(buildin_name, "k1_", 3)){
|
||||
sprintf(tmp_name, "%s_%s", "k1-x", &buildin_name[3]);
|
||||
buildin_name = tmp_name;
|
||||
}
|
||||
|
||||
if ((NULL != buildin_name) && (0 == strcmp(buildin_name, name))) {
|
||||
log_emerg("Boot from fit configuration %s\n", name);
|
||||
return 0;
|
||||
|
@ -643,22 +653,12 @@ char *get_product_name(void)
|
|||
{
|
||||
char *name = NULL;
|
||||
int eeprom_addr;
|
||||
char tmp_name[64];
|
||||
|
||||
eeprom_addr = k1x_eeprom_init();
|
||||
name = calloc(1, 64);
|
||||
if ((eeprom_addr >= 0) && (NULL != name) && (0 == spacemit_eeprom_read(
|
||||
eeprom_addr, name, TLV_CODE_PRODUCT_NAME))) {
|
||||
pr_info("Get product name from eeprom %s\n", name);
|
||||
|
||||
/*
|
||||
be compatible to previous format name,
|
||||
such as: k1_deb1 -> k1-x_deb1
|
||||
*/
|
||||
if (strncmp(name, CONFIG_SYS_BOARD, 4)){
|
||||
sprintf(tmp_name, "%s_%s", CONFIG_SYS_BOARD, &name[3]);
|
||||
strcpy(name, tmp_name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#ifdef CONFIG_VIDEO_SPACEMIT
|
||||
extern bool is_video_connected;
|
||||
#endif
|
||||
|
||||
/* maximum bootmenu entries */
|
||||
#define MAX_COUNT 99
|
||||
|
||||
|
@ -600,7 +604,14 @@ int menu_show(int bootdelay)
|
|||
return 0;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VIDEO_SPACEMIT
|
||||
printf("menu_show:is_video_connected: %d\n", is_video_connected);
|
||||
if (is_video_connected) {
|
||||
env_set("stdout", "serial,vidconsole");
|
||||
} else {
|
||||
env_set("stdout", "serial");
|
||||
}
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
ret = bootmenu_show(bootdelay);
|
||||
|
@ -616,7 +627,8 @@ int menu_show(int bootdelay)
|
|||
|
||||
run_command("run bootcmd", 0);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
if (ret == BOOTMENU_RET_QUIT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,98 +51,6 @@ static void free_flash_dev(struct flash_dev *fdev)
|
|||
free(fdev);
|
||||
}
|
||||
|
||||
|
||||
static int _write_gpt_partition(struct flash_dev *fdev)
|
||||
{
|
||||
__maybe_unused char write_part_command[300] = {"\0"};
|
||||
char *gpt_table_str = NULL;
|
||||
|
||||
u32 boot_mode = get_boot_pin_select();
|
||||
|
||||
if (fdev->gptinfo.gpt_table != NULL && strlen(fdev->gptinfo.gpt_table) > 0){
|
||||
gpt_table_str = malloc(strlen(fdev->gptinfo.gpt_table) + 32);
|
||||
if (gpt_table_str == NULL){
|
||||
return -1;
|
||||
}
|
||||
sprintf(gpt_table_str, "env set -f partitions '%s'", fdev->gptinfo.gpt_table);
|
||||
run_command(gpt_table_str, 0);
|
||||
free(gpt_table_str);
|
||||
}
|
||||
|
||||
switch(boot_mode){
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) || CONFIG_IS_ENABLED(FASTBOOT_MULTI_FLASH_OPTION_MMC)
|
||||
case BOOT_MODE_EMMC:
|
||||
case BOOT_MODE_SD:
|
||||
sprintf(write_part_command, "gpt write mmc %x '%s'",
|
||||
CONFIG_FASTBOOT_FLASH_MMC_DEV, fdev->gptinfo.gpt_table);
|
||||
if (run_command(write_part_command, 0)){
|
||||
printf("write gpt fail\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_SUPPORT_BLOCK_DEV)
|
||||
case BOOT_MODE_NOR:
|
||||
case BOOT_MODE_NAND:
|
||||
printf("write gpt to dev:%s\n", CONFIG_FASTBOOT_SUPPORT_BLOCK_DEV_NAME);
|
||||
|
||||
/*nvme need scan at first*/
|
||||
if (!strncmp("nvme", CONFIG_FASTBOOT_SUPPORT_BLOCK_DEV_NAME, 4)
|
||||
&& nvme_scan_namespace()){
|
||||
printf("can not can nvme devices!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(write_part_command, "gpt write %s %x '%s'",
|
||||
CONFIG_FASTBOOT_SUPPORT_BLOCK_DEV_NAME, CONFIG_FASTBOOT_SUPPORT_BLOCK_DEV_INDEX,
|
||||
fdev->gptinfo.gpt_table);
|
||||
if (run_command(write_part_command, 0)){
|
||||
printf("write gpt fail\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int _write_mtd_partition(char mtd_table[128])
|
||||
{
|
||||
#ifdef CONFIG_MTD
|
||||
struct mtd_info *mtd;
|
||||
char mtd_ids[36] = {"\0"};
|
||||
char mtd_parts[128] = {"\0"};
|
||||
|
||||
mtd_probe_devices();
|
||||
|
||||
/*
|
||||
try to find the first mtd device, it there have mutil mtd device such as nand and nor,
|
||||
it only use the first one.
|
||||
*/
|
||||
mtd_for_each_device(mtd) {
|
||||
if (!mtd_is_partition(mtd))
|
||||
break;
|
||||
}
|
||||
|
||||
if (mtd == NULL){
|
||||
printf("can not get mtd device\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*to mtd device, it should write mtd table to env.*/
|
||||
sprintf(mtd_ids, "%s=spi-dev", mtd->name);
|
||||
sprintf(mtd_parts, "spi-dev:%s", mtd_table);
|
||||
|
||||
env_set("mtdids", mtd_ids);
|
||||
env_set("mtdparts", mtd_parts);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize the mmc device given its number */
|
||||
static int init_mmc_device(int dev_num)
|
||||
{
|
||||
|
@ -899,11 +807,13 @@ static int parse_flash_config(struct flash_dev *fdev)
|
|||
}
|
||||
|
||||
if (fdev->gptinfo.gpt_table != NULL && strlen(fdev->gptinfo.gpt_table) > 1 && fdev->gptinfo.fastboot_flash_gpt){
|
||||
_write_gpt_partition(fdev);
|
||||
if (_write_gpt_partition(fdev))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fdev->mtd_table != NULL && strlen(fdev->mtd_table) > 1){
|
||||
_write_mtd_partition(fdev->mtd_table);
|
||||
if (_write_mtd_partition(fdev))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*set partition to env*/
|
||||
|
|
|
@ -59,6 +59,7 @@ CONFIG_SYS_SPL_MALLOC_SIZE=0x2000000
|
|||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y
|
||||
CONFIG_SPL_ENV_SUPPORT=y
|
||||
CONFIG_SPL_I2C=y
|
||||
CONFIG_SPL_MMC_WRITE=y
|
||||
CONFIG_SPL_MTD_SUPPORT=y
|
||||
CONFIG_SPL_DM_SPI_FLASH=y
|
||||
CONFIG_SPL_DM_RESET=y
|
||||
|
@ -81,6 +82,8 @@ CONFIG_SYS_PBSIZE=276
|
|||
CONFIG_CMD_TLV_EEPROM=y
|
||||
CONFIG_SYS_BOOTM_LEN=0xa000000
|
||||
CONFIG_CMD_EEPROM=y
|
||||
CONFIG_CMD_MD5SUM=y
|
||||
CONFIG_CMD_ZIP=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_GPIO_READ=y
|
||||
|
@ -93,6 +96,7 @@ CONFIG_CMD_MTD=y
|
|||
CONFIG_CMD_PART=y
|
||||
# CONFIG_CMD_SCSI is not set
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_WDT=y
|
||||
CONFIG_CMD_DHCP=y
|
||||
CONFIG_CMD_TFTPPUT=y
|
||||
CONFIG_CMD_TFTPSRV=y
|
||||
|
@ -152,6 +156,9 @@ CONFIG_FASTBOOT_MMC_BOOT2_NAME="fsbl_1"
|
|||
CONFIG_FASTBOOT_CMD_OEM_READ=y
|
||||
CONFIG_FASTBOOT_SUPPORT_BLOCK_DEV=y
|
||||
CONFIG_FASTBOOT_CMD_OEM_CONFIG_ACCESS=y
|
||||
CONFIG_SPL_FASTBOOT_CMD_OEM_CONFIG_ACCESS=y
|
||||
CONFIG_FASTBOOT_CMD_OEM_ERASE=y
|
||||
CONFIG_SPL_FASTBOOT_CMD_OEM_ERASE=y
|
||||
CONFIG_FASTBOOT_CMD_OEM_ENV_ACCESS=y
|
||||
CONFIG_SPL_FASTBOOT_CMD_OEM_ENV_ACCESS=y
|
||||
CONFIG_K1X_GPIO=y
|
||||
|
@ -180,6 +187,7 @@ CONFIG_MMC_SDHCI_K1X=y
|
|||
CONFIG_DM_MTD=y
|
||||
# CONFIG_MTD_NOR_FLASH is not set
|
||||
CONFIG_MTD_SPI_NAND=y
|
||||
CONFIG_SPI_FLASH_GIGADEVICE=y
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_SPI_FLASH_FM=y
|
||||
CONFIG_SPINOR_BLOCK_SUPPORT=y
|
||||
|
@ -201,6 +209,7 @@ CONFIG_DM_PMIC=y
|
|||
CONFIG_PMIC_SPM8XX=y
|
||||
CONFIG_DM_REGULATOR=y
|
||||
CONFIG_DM_REGULATOR_SPM8XX=y
|
||||
CONFIG_DM_REGULATOR_SPACEMIT_HUB=y
|
||||
CONFIG_SPL_SPACEMIT_POWER=y
|
||||
CONFIG_RESET_SPACEMIT_K1X=y
|
||||
# CONFIG_SCSI is not set
|
||||
|
@ -212,6 +221,7 @@ CONFIG_SPI=y
|
|||
CONFIG_K1X_QSPI=y
|
||||
# CONFIG_SYSRESET_SBI is not set
|
||||
# CONFIG_SYSRESET_SYSCON is not set
|
||||
CONFIG_SYSRESET_WATCHDOG=y
|
||||
CONFIG_SYSRESET_SPACEMIT=y
|
||||
CONFIG_TIMER_EARLY=y
|
||||
CONFIG_USB=y
|
||||
|
@ -227,6 +237,7 @@ CONFIG_USB_GADGET=y
|
|||
CONFIG_USB_GADGET_VENDOR_NUM=0x361C
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0x1001
|
||||
CONFIG_USB2_K1X_CI=y
|
||||
# CONFIG_USB_SET_SERIAL_NUMBER is not set
|
||||
CONFIG_DM_VIDEO=y
|
||||
CONFIG_VIDEO_PCI_DEFAULT_FB_SIZE=0x8000000
|
||||
CONFIG_VIDEO_COPY=y
|
||||
|
@ -242,6 +253,8 @@ CONFIG_BMP_32BPP=y
|
|||
CONFIG_VIDEO_SPACEMIT=y
|
||||
CONFIG_DISPLAY_SPACEMIT_HDMI=y
|
||||
CONFIG_DISPLAY_SPACEMIT_MIPI=y
|
||||
CONFIG_WDT=y
|
||||
CONFIG_WDT_SPACEMIT=y
|
||||
CONFIG_JFFS2_NOR=y
|
||||
CONFIG_JFFS2_USE_MTD_READ=y
|
||||
CONFIG_UBIFS_SILENCE_MSG=y
|
||||
|
|
19
debian/u-boot-spacemit.postinst
vendored
19
debian/u-boot-spacemit.postinst
vendored
|
@ -26,7 +26,9 @@ configure)
|
|||
FSBL=/dev/mmcblk0p1
|
||||
FSBL_SEEK=0
|
||||
ENV=/dev/mmcblk0p2
|
||||
ENV_SEEK=0
|
||||
UBOOT=/dev/mmcblk0p4
|
||||
UBOOT_SEEK=0
|
||||
;;
|
||||
"/dev/mmcblk2"*)
|
||||
BOOTINFO_FILE=bootinfo_emmc.bin
|
||||
|
@ -34,13 +36,26 @@ configure)
|
|||
FSBL=/dev/mmcblk2boot0
|
||||
FSBL_SEEK=512
|
||||
ENV=/dev/mmcblk2p2
|
||||
ENV_SEEK=0
|
||||
UBOOT=/dev/mmcblk2p4
|
||||
UBOOT_SEEK=0
|
||||
if [ -e $BOOTINFO ]; then
|
||||
echo 0 | tee /sys/block/mmcblk2boot0/force_ro
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
"/dev/nvme0n1"*)
|
||||
BOOTINFO_FILE=bootinfo_spinor.bin
|
||||
BOOTINFO=/dev/mtdblock0
|
||||
FSBL=/dev/mtdblock0
|
||||
FSBL_SEEK=$((128 * 1024))
|
||||
ENV=/dev/mtdblock0
|
||||
ENV_SEEK=$((384 * 1024))
|
||||
UBOOT=/dev/mtdblock0
|
||||
# 以KB为单位
|
||||
UBOOT_SEEK=640
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported root=$ROOT"
|
||||
exit 0
|
||||
|
@ -65,8 +80,8 @@ configure)
|
|||
# 此前已经做了所有检查
|
||||
dd if=/usr/lib/u-boot/$target/$BOOTINFO_FILE of=$BOOTINFO && sync
|
||||
dd if=/usr/lib/u-boot/$target/FSBL.bin of=$FSBL seek=$FSBL_SEEK bs=1 && sync
|
||||
dd if=/usr/lib/u-boot/$target/env.bin of=$ENV bs=1 && sync
|
||||
dd if=/usr/lib/u-boot/$target/u-boot.itb of=$UBOOT bs=1M && sync
|
||||
dd if=/usr/lib/u-boot/$target/env.bin of=$ENV seek=$ENV_SEEK bs=1 && sync
|
||||
dd if=/usr/lib/u-boot/$target/u-boot.itb of=$UBOOT seek=$UBOOT_SEEK bs=1K && sync
|
||||
|
||||
;;
|
||||
esac
|
||||
|
|
|
@ -261,9 +261,9 @@ static SPACEMIT_CCU_GATE_NO_PARENT(usb30_clk, "usb30_clk", NULL,
|
|||
0);
|
||||
static const char * const qspi_parent_names[] = {"clk_dummy", "clk_dummy", "clk_dummy",
|
||||
"clk_dummy", "clk_dummy", "pll1_d23_106p8"};
|
||||
static SPACEMIT_CCU_DIV_MFC_MUX_GATE(qspi_clk, "qspi_clk", qspi_parent_names,
|
||||
static SPACEMIT_CCU_DIV_MUX_GATE(qspi_clk, "qspi_clk", qspi_parent_names,
|
||||
BASE_TYPE_APMU, APMU_QSPI_CLK_RES_CTRL,
|
||||
9, 3, BIT(12),
|
||||
9, 3,
|
||||
6, 3, BIT(4), BIT(4), 0x0,
|
||||
0);
|
||||
static SPACEMIT_CCU_GATE_NO_PARENT(qspi_bus_clk, "qspi_bus_clk", NULL,
|
||||
|
|
|
@ -275,6 +275,24 @@ config FASTBOOT_CMD_OEM_CONFIG_ACCESS
|
|||
Add support for the "oem config:read/write/flush" command from a fastboot client. This command
|
||||
include configuration read, write and flush operation.
|
||||
|
||||
config SPL_FASTBOOT_CMD_OEM_CONFIG_ACCESS
|
||||
bool "Enable the 'oem config' command in SPL"
|
||||
help
|
||||
Add support for the "oem config:read/write/flush" command from a fastboot client. This command
|
||||
include configuration read, write and flush operation.
|
||||
|
||||
config FASTBOOT_CMD_OEM_ERASE
|
||||
bool "Enable the 'oem erase' command"
|
||||
help
|
||||
Add support for the "oem erase:[eeprom, emmc]" command from a fastboot client. This command
|
||||
include configuration eeprom or emmc.
|
||||
|
||||
config SPL_FASTBOOT_CMD_OEM_ERASE
|
||||
bool "Enable the 'oem erase' command in SPL"
|
||||
help
|
||||
Add support for the "oem erase:[eeprom, emmc]" command from a fastboot client. This command
|
||||
include configuration eeprom or emmc.
|
||||
|
||||
config FASTBOOT_CMD_OEM_ENV_ACCESS
|
||||
bool "Enable the 'oem env' command"
|
||||
help
|
||||
|
|
|
@ -9,5 +9,5 @@ obj-$(CONFIG_$(SPL_)FASTBOOT_FLASH_NAND) += fb_nand.o
|
|||
obj-$(CONFIG_$(SPL_)FASTBOOT_FLASH_MTD) += fb_mtd.o
|
||||
|
||||
obj-$(CONFIG_$(SPL_)FASTBOOT_MULTI_FLASH_OPTION_MMC) += fb_mmc.o
|
||||
obj-$(CONFIG_$(SPL_)FASTBOOT_MULTI_FLASH_OPTION_MTD) += fb_mtd.o
|
||||
obj-$(CONFIG_FASTBOOT_MULTI_FLASH_OPTION_MTD) += fb_mtd.o
|
||||
obj-$(CONFIG_$(SPL_)FASTBOOT_SUPPORT_BLOCK_DEV) += fb_blk.o
|
||||
|
|
|
@ -182,7 +182,7 @@ void fastboot_blk_flash_write(const char *cmd, void *download_buffer,
|
|||
/*save crc value to compare after flash image*/
|
||||
u64 compare_val = 0;
|
||||
/*use for gzip image*/
|
||||
static u32 __maybe_unused part_offset_t = 0;
|
||||
static ulong __maybe_unused part_offset_t = 0;
|
||||
static char __maybe_unused part_name_t[20] = "";
|
||||
unsigned long __maybe_unused src_len = ~0UL;
|
||||
bool gzip_image = false;
|
||||
|
@ -218,7 +218,7 @@ void fastboot_blk_flash_write(const char *cmd, void *download_buffer,
|
|||
if (fastboot_blk_get_part_info(cmd, &dev_desc, &info, response) < 0)
|
||||
return;
|
||||
|
||||
if (gzip_parse_header((uchar *)download_buffer, src_len) >= 0) {
|
||||
if (check_gzip_format((uchar *)download_buffer, src_len) >= 0) {
|
||||
/*is gzip data and equal part name*/
|
||||
gzip_image = true;
|
||||
if (strcmp(cmd, part_name_t)){
|
||||
|
|
|
@ -69,6 +69,10 @@ static void oem_read(char *cmd_parameter, char *response);
|
|||
static void oem_config(char *cmd_parameter, char *response);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ERASE)
|
||||
static void oem_erase(char *cmd_parameter, char *response);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ENV_ACCESS)
|
||||
static void oem_env(char *cmd_parameter, char *response);
|
||||
#endif
|
||||
|
@ -167,6 +171,12 @@ static const struct {
|
|||
.dispatch = oem_config,
|
||||
},
|
||||
#endif
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ERASE)
|
||||
[FASTBOOT_COMMAND_OEM_ERASE] = {
|
||||
.command = "oem erase",
|
||||
.dispatch = oem_erase,
|
||||
},
|
||||
#endif
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ENV_ACCESS)
|
||||
[FASTBOOT_COMMAND_ENV_ACCESS] = {
|
||||
.command = "oem env",
|
||||
|
@ -817,6 +827,20 @@ static void oem_config(char *cmd_parameter, char *response)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ERASE)
|
||||
/**
|
||||
* oem_erase() - Execute the OEM erase command
|
||||
*
|
||||
* @cmd_parameter: Pointer to command parameter
|
||||
* @response: Pointer to fastboot response buffer
|
||||
*/
|
||||
static void oem_erase(char *cmd_parameter, char *response)
|
||||
{
|
||||
clear_storage_data(cmd_parameter, response);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ENV_ACCESS)
|
||||
void fastboot_env_access(char *operation, char *env, char *response);
|
||||
/**
|
||||
|
|
|
@ -524,7 +524,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
|
|||
/*save crc value to compare after flash image*/
|
||||
u64 compare_val = 0;
|
||||
/*use for gzip image*/
|
||||
static u32 __maybe_unused part_offset_t = 0;
|
||||
static ulong __maybe_unused part_offset_t = 0;
|
||||
static char __maybe_unused part_name_t[20] = "";
|
||||
unsigned long __maybe_unused src_len = ~0UL;
|
||||
bool gzip_image = false;
|
||||
|
@ -670,7 +670,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
|
|||
fastboot_mmc_get_part_info(cmd, &dev_desc, &info, response) < 0)
|
||||
return;
|
||||
|
||||
if (gzip_parse_header((uchar *)download_buffer, src_len) >= 0) {
|
||||
if (check_gzip_format((uchar *)download_buffer, src_len) >= 0) {
|
||||
/*is gzip data and equal part name*/
|
||||
gzip_image = true;
|
||||
if (strcmp(cmd, part_name_t)){
|
||||
|
|
|
@ -24,6 +24,8 @@ struct fb_mtd_sparse {
|
|||
struct part_info *part;
|
||||
};
|
||||
|
||||
static bool unlock_flag = false;
|
||||
|
||||
static bool mtd_is_aligned_with_min_io_size(struct mtd_info *mtd, u64 size)
|
||||
{
|
||||
return !do_div(size, mtd->writesize);
|
||||
|
@ -362,14 +364,6 @@ void fastboot_mtd_flash_write(const char *cmd, void *download_buffer,
|
|||
response, fdev);
|
||||
return;
|
||||
}
|
||||
|
||||
/*flash env*/
|
||||
/*if (strcmp(cmd, "env") == 0) {*/
|
||||
/* printf("flash env \n");*/
|
||||
/* fastboot_oem_flash_env(cmd, fastboot_buf_addr, download_bytes,*/
|
||||
/* response, fdev);*/
|
||||
/* return;*/
|
||||
/*}*/
|
||||
#endif
|
||||
|
||||
ret = fb_mtd_lookup(cmd, &mtd, &part);
|
||||
|
@ -380,6 +374,12 @@ void fastboot_mtd_flash_write(const char *cmd, void *download_buffer,
|
|||
return;
|
||||
}
|
||||
|
||||
/*unlock nor flash protect*/
|
||||
if (!unlock_flag && mtd->type == MTD_NORFLASH){
|
||||
run_commandf("sf probe;sf protect unlock 0 0x%x", mtd->size);
|
||||
unlock_flag = true;
|
||||
}
|
||||
|
||||
if (need_erase) {
|
||||
/*must erase at first when write data to mtd devices*/
|
||||
printf("Erasing MTD partition %s\n", part->name);
|
||||
|
@ -492,6 +492,12 @@ void fastboot_mtd_flash_erase(const char *cmd, char *response)
|
|||
return;
|
||||
}
|
||||
|
||||
/*unlock nor flash protect*/
|
||||
if (!unlock_flag && mtd->type == MTD_NORFLASH){
|
||||
run_commandf("sf probe;sf protect unlock 0 0x%x", mtd->size);
|
||||
unlock_flag = true;
|
||||
}
|
||||
|
||||
ret = _fb_mtd_erase(mtd, 0);
|
||||
if (ret) {
|
||||
pr_err("failed erasing from device %s", mtd->name);
|
||||
|
|
|
@ -35,32 +35,38 @@
|
|||
#define EMMC_MAX_BLK_WRITE 16384
|
||||
|
||||
#if CONFIG_IS_ENABLED(SPACEMIT_FLASH)
|
||||
static int _write_gpt_partition(struct flash_dev *fdev, char *response)
|
||||
int _write_gpt_partition(struct flash_dev *fdev)
|
||||
{
|
||||
__maybe_unused char write_part_command[300] = {"\0"};
|
||||
char *gpt_table_str = NULL;
|
||||
int ret = 0;
|
||||
|
||||
u32 boot_mode = get_boot_pin_select();
|
||||
|
||||
if (fdev->gptinfo.gpt_table != NULL && strlen(fdev->gptinfo.gpt_table) > 0){
|
||||
gpt_table_str = malloc(strlen(fdev->gptinfo.gpt_table) + 32);
|
||||
if (gpt_table_str == NULL){
|
||||
pr_err("malloc size fail\n");
|
||||
return -1;
|
||||
}
|
||||
sprintf(gpt_table_str, "env set -f partitions '%s'", fdev->gptinfo.gpt_table);
|
||||
run_command(gpt_table_str, 0);
|
||||
free(gpt_table_str);
|
||||
} else{
|
||||
pr_info("parse gpt table is NULL, do nothing");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(gpt_table_str, 0, strlen(fdev->gptinfo.gpt_table) + 32);
|
||||
|
||||
switch(boot_mode){
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) || CONFIG_IS_ENABLED(FASTBOOT_MULTI_FLASH_OPTION_MMC)
|
||||
case BOOT_MODE_EMMC:
|
||||
case BOOT_MODE_SD:
|
||||
sprintf(write_part_command, "gpt write mmc %x '%s'",
|
||||
sprintf(gpt_table_str, "gpt write mmc %x '%s'",
|
||||
CONFIG_FASTBOOT_FLASH_MMC_DEV, fdev->gptinfo.gpt_table);
|
||||
if (run_command(write_part_command, 0)){
|
||||
fastboot_fail("write gpt fail", response);
|
||||
return -1;
|
||||
if (run_command(gpt_table_str, 0)){
|
||||
pr_err("write gpt fail");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -73,26 +79,31 @@ static int _write_gpt_partition(struct flash_dev *fdev, char *response)
|
|||
/*nvme need scan at first*/
|
||||
if (!strncmp("nvme", CONFIG_FASTBOOT_SUPPORT_BLOCK_DEV_NAME, 4)
|
||||
&& nvme_scan_namespace()){
|
||||
fastboot_fail("can not can nvme devices!", response);
|
||||
return -1;
|
||||
pr_err("can not can nvme devices!");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
sprintf(write_part_command, "gpt write %s %x '%s'",
|
||||
sprintf(gpt_table_str, "gpt write %s %x '%s'",
|
||||
CONFIG_FASTBOOT_SUPPORT_BLOCK_DEV_NAME, CONFIG_FASTBOOT_SUPPORT_BLOCK_DEV_INDEX,
|
||||
fdev->gptinfo.gpt_table);
|
||||
if (run_command(write_part_command, 0)){
|
||||
fastboot_fail("write gpt fail", response);
|
||||
return -1;
|
||||
if (run_command(gpt_table_str, 0)){
|
||||
pr_err("write gpt fail");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
pr_err("no dev to write gpt table, check your env\n");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
pr_info("parse gpt/mtd table okay");
|
||||
err:
|
||||
free(gpt_table_str);
|
||||
|
||||
|
||||
fastboot_okay("parse gpt/mtd table okay", response);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _clear_env_part(void *download_buffer, u32 download_bytes,
|
||||
|
@ -152,12 +163,18 @@ int _clear_env_part(void *download_buffer, u32 download_bytes,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int _write_mtd_partition(char mtd_table[128], char *response)
|
||||
int _write_mtd_partition(struct flash_dev *fdev)
|
||||
{
|
||||
#ifdef CONFIG_MTD
|
||||
struct mtd_info *mtd;
|
||||
char mtd_ids[36] = {"\0"};
|
||||
char mtd_parts[128] = {"\0"};
|
||||
char *mtd_parts = NULL;
|
||||
|
||||
mtd_parts = malloc(strlen(fdev->mtd_table) + 32);
|
||||
if (mtd_parts == NULL){
|
||||
pr_err("malloc size fail\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mtd_probe_devices();
|
||||
|
||||
|
@ -171,18 +188,20 @@ static int _write_mtd_partition(char mtd_table[128], char *response)
|
|||
}
|
||||
|
||||
if (mtd == NULL){
|
||||
fastboot_fail("can not get mtd device", response);
|
||||
pr_err("can not get mtd device");
|
||||
free(mtd_parts);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*to mtd device, it should write mtd table to env.*/
|
||||
sprintf(mtd_ids, "%s=spi-dev", mtd->name);
|
||||
sprintf(mtd_parts, "spi-dev:%s", mtd_table);
|
||||
sprintf(mtd_parts, "spi-dev:%s", fdev->mtd_table);
|
||||
|
||||
env_set("mtdids", mtd_ids);
|
||||
env_set("mtdparts", mtd_parts);
|
||||
|
||||
#endif
|
||||
fastboot_okay("parse gpt/mtd table okay", response);
|
||||
pr_info("parse gpt/mtd table okay");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -256,8 +275,10 @@ int _parse_flash_config(struct flash_dev *fdev, void *load_flash_addr)
|
|||
|
||||
/*init and would remalloc while size is increasing*/
|
||||
combine_str = malloc(combine_len);
|
||||
memset(combine_str, '\0', combine_len);
|
||||
if (combine_str == NULL)
|
||||
return -1;
|
||||
|
||||
memset(combine_str, '\0', combine_len);
|
||||
json_root = cJSON_Parse(load_flash_addr);
|
||||
if (!json_root){
|
||||
pr_err("can not parse json, check your flash_config.cfg is json format or not\n");
|
||||
|
@ -461,11 +482,17 @@ void fastboot_oem_flash_gpt(const char *cmd, void *download_buffer, u32 download
|
|||
}
|
||||
|
||||
if (strlen(fdev->gptinfo.gpt_table) > 0 && fdev->gptinfo.fastboot_flash_gpt){
|
||||
_write_gpt_partition(fdev, response);
|
||||
if (_write_gpt_partition(fdev)){
|
||||
fastboot_fail("write gpt tabel fail", response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(fdev->mtd_table) > 0){
|
||||
_write_mtd_partition(fdev->mtd_table, response);
|
||||
if (_write_mtd_partition(fdev)){
|
||||
fastboot_fail("write mtd tabel fail", response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*set partition to env*/
|
||||
|
@ -833,6 +860,14 @@ void fastboot_oem_flash_bootinfo(const char *cmd, void *download_buffer,
|
|||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_CONFIG_ACCESS)
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
extern int get_tlvinfo_from_eeprom(int tcode, char *buf);
|
||||
extern int set_val_to_tlvinfo(int tcode, char *valvoid);
|
||||
extern int write_tlvinfo_to_eeprom(void);
|
||||
#else
|
||||
static bool tlvinfo_init = false;
|
||||
#endif
|
||||
|
||||
struct oem_config_info
|
||||
{
|
||||
const char *name;
|
||||
|
@ -844,6 +879,7 @@ const struct oem_config_info config_info[] = {
|
|||
{ "product_name", TLV_CODE_PRODUCT_NAME, 16, NULL },
|
||||
{ "serial#", TLV_CODE_SERIAL_NUMBER, 12, NULL },
|
||||
{ "ethaddr", TLV_CODE_MAC_BASE, 17, NULL },
|
||||
{ "ethsize", TLV_CODE_MAC_SIZE, 6, NULL },/*size must equal or less than 65535*/
|
||||
{ "manufacture_date", TLV_CODE_MANUF_DATE, 19, NULL },
|
||||
{ "device_version", TLV_CODE_DEVICE_VERSION, 3, NULL },
|
||||
{ "manufacturer", TLV_CODE_MANUF_NAME, 32, NULL },
|
||||
|
@ -856,39 +892,18 @@ const struct oem_config_info config_info[] = {
|
|||
|
||||
static int write_config_info_to_eeprom(uint32_t id, char *value)
|
||||
{
|
||||
char *cmd_str;
|
||||
|
||||
cmd_str = malloc(256);
|
||||
if (NULL == cmd_str) {
|
||||
pr_err("malloc buffer for cmd string fail\n");
|
||||
return -1;
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
if (set_val_to_tlvinfo(id, value) == 0)
|
||||
#else
|
||||
if (!tlvinfo_init){
|
||||
run_command("tlv_eeprom", 0);
|
||||
tlvinfo_init = true;
|
||||
}
|
||||
|
||||
pr_info("write data to EEPROM, ID:%d, string:%s\n", id, value);
|
||||
/* read eeprom */
|
||||
sprintf(cmd_str, "tlv_eeprom read");
|
||||
if (run_command(cmd_str, 0)) {
|
||||
free(cmd_str);
|
||||
pr_err("tlv_eeprom read fail\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// update eeprom data, need add '' for value string that may have space inside
|
||||
sprintf(cmd_str, "tlv_eeprom set %d '%s'", id, value);
|
||||
if (run_command(cmd_str, 0)) {
|
||||
free(cmd_str);
|
||||
pr_err("tlv_eeprom set %s to %d fail\n", value, id);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (run_command("tlv_eeprom write", 0)) {
|
||||
free(cmd_str);
|
||||
pr_err("tlv_eeprom write fail\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
free(cmd_str);
|
||||
if (run_commandf("tlv_eeprom set 0x%x %s", id, value) == 0)
|
||||
#endif
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(SPACEMIT_K1X_EFUSE)
|
||||
|
@ -936,58 +951,33 @@ static struct oem_config_info* get_config_info(char *key)
|
|||
|
||||
static void read_oem_configuration(char *config, char *response)
|
||||
{
|
||||
char *key;
|
||||
struct oem_config_info* info;
|
||||
char *ack, *value, *temp;
|
||||
int i = 0, j;
|
||||
char *ack;
|
||||
|
||||
ack = malloc(256);
|
||||
ack = calloc(0, 256);
|
||||
if (NULL == ack) {
|
||||
pr_err("malloc buffer for ack fail\n");
|
||||
return;
|
||||
}
|
||||
|
||||
temp = malloc(256);
|
||||
if (NULL == temp) {
|
||||
free(ack);
|
||||
pr_err("malloc buffer for temp fail\n");
|
||||
return;
|
||||
}
|
||||
memset(ack, 0, 256);
|
||||
|
||||
key = strsep(&config, ",");
|
||||
while (NULL != key) {
|
||||
pr_debug("try to find config info for %s\n", key);
|
||||
info = get_config_info(key);
|
||||
info = get_config_info(config);
|
||||
if (NULL != info){
|
||||
value = env_get(key);
|
||||
if (NULL != info->convert)
|
||||
value = info->convert(value);
|
||||
// make sure value string is NOT exceed temp buffer
|
||||
if ((NULL != value) && (strlen(value) < 128)) {
|
||||
memset(temp, 0, 256);
|
||||
sprintf(temp, "%s", value);
|
||||
j = strlen(temp);
|
||||
if ((i + j) < 256) {
|
||||
// add comma between two info dictionary
|
||||
if (0 != i)
|
||||
ack[i++] = ',';
|
||||
memcpy(ack + i, temp, j);
|
||||
i += j;
|
||||
}
|
||||
}
|
||||
}
|
||||
key = strsep(&config, ",");
|
||||
}
|
||||
|
||||
if (0 != i) {
|
||||
pr_info("%s, %x, \n", info->name, info->id);
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
if (get_tlvinfo_from_eeprom(info->id, ack) == 0){
|
||||
#else
|
||||
char *tmp_str = env_get(info->name);
|
||||
if (tmp_str != NULL){
|
||||
strcpy(ack, tmp_str);
|
||||
#endif
|
||||
fastboot_okay(ack, response);
|
||||
}else{
|
||||
fastboot_fail("NOT exist", response);
|
||||
fastboot_fail("key NOT exist", response);
|
||||
}
|
||||
}else{
|
||||
fastboot_fail("key NOT exist", response);
|
||||
}
|
||||
|
||||
free(ack);
|
||||
free(temp);
|
||||
}
|
||||
|
||||
static void write_oem_configuration(char *config, char *response)
|
||||
|
@ -1020,15 +1010,23 @@ static void write_oem_configuration(char *config, char *response)
|
|||
}
|
||||
}
|
||||
|
||||
if (0 == ret)
|
||||
fastboot_okay(NULL, response);
|
||||
else
|
||||
fastboot_fail("NOT exist", response);
|
||||
if (ret){
|
||||
fastboot_fail("write key fail", response);
|
||||
return;
|
||||
}
|
||||
|
||||
static void flush_oem_configuration(char *config, char *response)
|
||||
{
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
if (0 == write_tlvinfo_to_eeprom())
|
||||
#else
|
||||
if (!tlvinfo_init){
|
||||
run_command("tlv_eeprom", 0);
|
||||
tlvinfo_init = true;
|
||||
}
|
||||
if (run_command("tlv_eeprom write", 0) == 0)
|
||||
#endif
|
||||
fastboot_okay(NULL, response);
|
||||
else
|
||||
fastboot_fail("write fail", response);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1047,12 +1045,10 @@ void fastboot_config_access(char *operation, char *config, char *response)
|
|||
read_oem_configuration(config, response);
|
||||
else if (0 == strcmp(operation, "write"))
|
||||
write_oem_configuration(config, response);
|
||||
else if (0 == strcmp(operation, "flush"))
|
||||
flush_oem_configuration(config, response);
|
||||
else
|
||||
fastboot_fail("NOT support", response);
|
||||
}
|
||||
#endif
|
||||
#endif /*CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_CONFIG_ACCESS)*/
|
||||
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ENV_ACCESS)
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
|
@ -1146,3 +1142,169 @@ void fastboot_env_access(char *operation, char *env, char *response)
|
|||
fastboot_fail("NOT support", response);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define GZIP_HEADER_HEAD_CRC 2
|
||||
#define GZIP_HEADER_EXTRA_FIELD 4
|
||||
#define GZIP_HEADER_ORIG_NAME 8
|
||||
#define GZIP_HEADER_COMMENT 0x10
|
||||
#define GZIP_HEADER_RESERVED 0xe0
|
||||
#define GZIP_HEADER_DEFLATED 8
|
||||
int check_gzip_format(const unsigned char *src, unsigned long len)
|
||||
{
|
||||
int i, flags;
|
||||
|
||||
/* skip header */
|
||||
i = 10;
|
||||
flags = src[3];
|
||||
if (src[2] != GZIP_HEADER_DEFLATED || (flags & GZIP_HEADER_RESERVED) != 0) {
|
||||
pr_info("is not gzipped data\n");
|
||||
return (-1);
|
||||
}
|
||||
if ((flags & GZIP_HEADER_EXTRA_FIELD) != 0)
|
||||
i = 12 + src[10] + (src[11] << 8);
|
||||
if ((flags & GZIP_HEADER_ORIG_NAME) != 0)
|
||||
while (src[i++] != 0)
|
||||
;
|
||||
if ((flags & GZIP_HEADER_COMMENT) != 0)
|
||||
while (src[i++] != 0)
|
||||
;
|
||||
if ((flags & GZIP_HEADER_HEAD_CRC) != 0)
|
||||
i += 2;
|
||||
if (i >= len) {
|
||||
pr_info("gunzip out of data in header\n");
|
||||
return (-1);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ERASE)
|
||||
/*boot0,boot1 would erase 128KB size*/
|
||||
#define ERASE_BOOT_SIZE (0x100)
|
||||
|
||||
int clear_emmc(lbaint_t blkcnt)
|
||||
{
|
||||
struct blk_desc *dev_desc;
|
||||
struct mmc *mmc;
|
||||
u32 n;
|
||||
|
||||
mmc_init_device(MMC_DEV_EMMC);
|
||||
mmc = find_mmc_device(MMC_DEV_EMMC);
|
||||
if (!mmc){
|
||||
pr_err("can not get mmc dev\n");
|
||||
return -1;
|
||||
}
|
||||
if (mmc_init(mmc)){
|
||||
pr_err("can not init mmc\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev_desc = mmc_get_blk_desc(mmc);
|
||||
if (!dev_desc){
|
||||
pr_err("can not get blk dev of emmc\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = blk_derase(dev_desc, 0, blkcnt);
|
||||
if (n != blkcnt){
|
||||
pr_err("erase size %lx fail\n", blkcnt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* erase boot0/boot1 partition*/
|
||||
if (mmc_set_part_conf(mmc, 0, 0, 1) ||
|
||||
ERASE_BOOT_SIZE != blk_derase(dev_desc, 0, ERASE_BOOT_SIZE)){
|
||||
pr_err("erase boot0 fail\n");
|
||||
return -1;
|
||||
}
|
||||
if (mmc_set_part_conf(mmc, 0, 0, 2) ||
|
||||
ERASE_BOOT_SIZE != blk_derase(dev_desc, 0, ERASE_BOOT_SIZE)){
|
||||
pr_err("erase boot1 fail\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clear_mtd(char *mtd_dev, u32 erase_size)
|
||||
{
|
||||
static struct mtd_info *mtd = NULL;
|
||||
int ret;
|
||||
|
||||
if (mtd == NULL){
|
||||
pr_info("mtd is not init\n");
|
||||
mtd_probe_devices();
|
||||
}
|
||||
mtd = get_mtd_device_nm(mtd_dev);
|
||||
if (IS_ERR_OR_NULL(mtd)){
|
||||
pr_info("MTD device %s not found\n", mtd_dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
erase_size = round_up(erase_size, mtd->erasesize);
|
||||
ret = _fb_mtd_erase(mtd, erase_size);
|
||||
if (ret)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DEFAULT_EEPROM_ERASE_SIZE (256)
|
||||
#define DEFAULT_EEPROM_DEV (0)
|
||||
#define DEFAULT_EMMC_ERASE_SIZE (0x10000000)
|
||||
#define DEFAULT_MTD_ERASE_SIZE (0x100000)
|
||||
void clear_storage_data(char *cmd_parameter, char *response)
|
||||
{
|
||||
char *cmd_str, *operation;
|
||||
u32 erase_size;
|
||||
|
||||
cmd_str = cmd_parameter;
|
||||
operation = strsep(&cmd_str, " ");
|
||||
if (cmd_str != NULL){
|
||||
pr_info("get erase size:%s\n", cmd_str);
|
||||
erase_size = hextoul(cmd_str, NULL);
|
||||
}else {
|
||||
pr_info("has not define erase size, use default size\n");
|
||||
erase_size = 0;
|
||||
}
|
||||
|
||||
if (!strncmp("eeprom", operation, 6)){
|
||||
erase_size = (erase_size == 0) ? DEFAULT_EEPROM_ERASE_SIZE : erase_size;
|
||||
pr_info("erase eeprom, erase size:%x\n", erase_size);
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
if (clear_eeprom(DEFAULT_EEPROM_DEV, erase_size))
|
||||
#else
|
||||
if (run_command("tlv_eeprom;tlv_eeprom erase;tlv_eeprom write", 0))
|
||||
#endif
|
||||
fastboot_fail("erase eeprom fail", response);
|
||||
else
|
||||
fastboot_okay(NULL, response);
|
||||
return;
|
||||
} else if (!strncmp("emmc", operation, 4)){
|
||||
erase_size = (erase_size == 0) ? DEFAULT_EMMC_ERASE_SIZE : erase_size;
|
||||
pr_info("erase emmc, erase size:%x\n", erase_size);
|
||||
|
||||
if (clear_emmc(erase_size/512))
|
||||
fastboot_fail("erase emmc fail", response);
|
||||
else
|
||||
fastboot_okay(NULL, response);
|
||||
return;
|
||||
}
|
||||
|
||||
erase_size = (erase_size == 0) ? DEFAULT_MTD_ERASE_SIZE : erase_size;
|
||||
if (!strncmp("nor", operation, 3)){
|
||||
if (clear_mtd("nor0", erase_size))
|
||||
fastboot_fail("erase nor fail", response);
|
||||
else
|
||||
fastboot_okay(NULL, response);
|
||||
return;
|
||||
} else if (!strncmp("nand", operation, 4)){
|
||||
if (clear_mtd("spi-nand0", erase_size))
|
||||
fastboot_fail("erase nand fail", response);
|
||||
else
|
||||
fastboot_okay(NULL, response);
|
||||
return;
|
||||
}
|
||||
|
||||
fastboot_response("FAIL", response, "not support erase operation:%s", operation);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /*CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ERASE)*/
|
||||
|
|
|
@ -533,7 +533,7 @@ static int do_del_mtd_partitions(struct mtd_info *master)
|
|||
debug("Deleting %s MTD partition\n", slave->name);
|
||||
ret = del_mtd_device(slave);
|
||||
if (ret < 0) {
|
||||
pr_err("Error when deleting partition \"%s\" (%d)\n",
|
||||
pr_debug("Error when deleting partition \"%s\" (%d)\n",
|
||||
slave->name, ret);
|
||||
err = ret;
|
||||
continue;
|
||||
|
|
|
@ -3837,6 +3837,128 @@ void spi_nor_set_fixups(struct spi_nor *nor)
|
|||
#endif /* SPI_FLASH_MACRONIX */
|
||||
}
|
||||
|
||||
|
||||
/*clear CMP and LB in order to unlock the protect area*/
|
||||
static int generic_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
|
||||
{
|
||||
int ret;
|
||||
u8 val[1] = {0};
|
||||
|
||||
/*if not define SPI_NOR_HAS_LOCK flag, it should not clear the protect bit*/
|
||||
if (!(nor->info->flags & SPI_NOR_HAS_LOCK))
|
||||
return 0;
|
||||
|
||||
/*read register 1*/
|
||||
ret = nor->read_reg(nor, SPINOR_OP_RDSR, val, 1);
|
||||
if (ret < 0) {
|
||||
dev_dbg(nor->dev, "error %d reading CR\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*clear block protect bit at register 1*/
|
||||
val[0] &= ~(SR_BP0 | SR_BP1 | SR_BP2 | SR_TB | SR_SP);
|
||||
write_enable(nor);
|
||||
ret = nor->write_reg(nor, SPINOR_OP_WRSR, val, 1);
|
||||
if (ret < 0) {
|
||||
dev_dbg(nor->dev, "error while writing configuration register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret) {
|
||||
dev_dbg(nor->dev, "timeout while writing configuration register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*read register 2*/
|
||||
ret = nor->read_reg(nor, SPINOR_OP_RDCR, val, 1);
|
||||
if (ret < 0) {
|
||||
dev_dbg(nor->dev, "error %d reading CR\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*write register 2*/
|
||||
val[0] &= ~(SR_LB1 | SR_LB2 | SR_LB3 | SR_CMP);
|
||||
write_enable(nor);
|
||||
ret = nor->write_reg(nor, SPINOR_OP_WDCR, val, 1);
|
||||
if (ret < 0) {
|
||||
dev_dbg(nor->dev, "error while writing configuration register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret) {
|
||||
dev_dbg(nor->dev, "timeout while writing configuration register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set protect area */
|
||||
static int generic_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
|
||||
{
|
||||
/* TODO: should protect area by offset and len*/
|
||||
|
||||
int ret;
|
||||
u8 val[1] = {0};
|
||||
|
||||
/*if not define SPI_NOR_HAS_LOCK flag, it should not clear the protect bit*/
|
||||
if (!(nor->info->flags & SPI_NOR_HAS_LOCK))
|
||||
return 0;
|
||||
|
||||
/*if unlock size is not equal to all size, return*/
|
||||
if (nor->size != len && ofs != 0)
|
||||
return 0;
|
||||
|
||||
/*read register 1*/
|
||||
ret = nor->read_reg(nor, SPINOR_OP_RDSR, val, 1);
|
||||
if (ret < 0) {
|
||||
dev_dbg(nor->dev, "error %d reading CR\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*clear block protect bit at register 1*/
|
||||
val[0] &= ~(SR_BP0 | SR_BP1 | SR_BP2);
|
||||
write_enable(nor);
|
||||
ret = nor->write_reg(nor, SPINOR_OP_WRSR, val, 1);
|
||||
if (ret < 0) {
|
||||
dev_dbg(nor->dev, "error while writing configuration register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret) {
|
||||
dev_dbg(nor->dev, "timeout while writing configuration register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*read register 2*/
|
||||
ret = nor->read_reg(nor, SPINOR_OP_RDCR, val, 1);
|
||||
if (ret < 0) {
|
||||
dev_dbg(nor->dev, "error %d reading CR\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*write register 2*/
|
||||
val[0] |= SR_CMP;
|
||||
write_enable(nor);
|
||||
ret = nor->write_reg(nor, SPINOR_OP_WDCR, val, 1);
|
||||
if (ret < 0) {
|
||||
dev_dbg(nor->dev, "error while writing configuration register\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret) {
|
||||
dev_dbg(nor->dev, "timeout while writing configuration register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spi_nor_scan(struct spi_nor *nor)
|
||||
{
|
||||
struct spi_nor_flash_parameter params;
|
||||
|
@ -3940,6 +4062,12 @@ int spi_nor_scan(struct spi_nor *nor)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* if not define flash_unlock, use generic clear func*/
|
||||
if (!nor->flash_unlock){
|
||||
nor->flash_unlock = generic_unlock;
|
||||
nor->flash_lock = generic_lock;
|
||||
}
|
||||
|
||||
if (info->flags & USE_FSR)
|
||||
nor->flags |= SNOR_F_USE_FSR;
|
||||
if (info->flags & SPI_NOR_HAS_TB)
|
||||
|
|
|
@ -82,7 +82,9 @@ static const struct pmic_child_info pmic_children_info[] = {
|
|||
static int pm8xx_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode regulators_node;
|
||||
ofnode pmic_reset_node;
|
||||
int children;
|
||||
int ret;
|
||||
|
||||
regulators_node = dev_read_subnode(dev, "regulators");
|
||||
if (!ofnode_valid(regulators_node)) {
|
||||
|
@ -97,6 +99,15 @@ static int pm8xx_bind(struct udevice *dev)
|
|||
if (!children)
|
||||
debug("%s: %s - no child found\n", __func__, dev->name);
|
||||
|
||||
pmic_reset_node = dev_read_subnode(dev, "pmic-reset");
|
||||
if (ofnode_valid(pmic_reset_node) && ofnode_is_available(pmic_reset_node)) {
|
||||
debug("Binding pmic-reset node\n");
|
||||
ret = device_bind_driver_to_node(dev, "pmic_sysreset", "pmic_sysreset", pmic_reset_node, NULL);
|
||||
if (ret) {
|
||||
debug("Failed to bind pmic_sysreset driver: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* Always return success for this device */
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -405,7 +405,6 @@ config DM_REGULATOR_SPM8XX
|
|||
|
||||
config DM_REGULATOR_SPACEMIT_HUB
|
||||
tristate "Spacemit onboard USB hub regulator wrapper support"
|
||||
default SOC_SPACEMIT_K1X
|
||||
depends on DM_REGULATOR
|
||||
help
|
||||
Say Y here if you want to support onboard usb hubs on Spacemit
|
||||
|
|
|
@ -408,7 +408,7 @@ static void spacemit_reset_set(struct reset_ctl *rst,
|
|||
u32 value;
|
||||
struct spacemit_reset *reset = dev_get_priv(rst->dev);
|
||||
|
||||
pr_info("[RESET]spacemit_reset_set assert=%d, id=%d \r\n", assert, id);
|
||||
pr_debug("[RESET]spacemit_reset_set assert=%d, id=%d \r\n", assert, id);
|
||||
value = spacemit_reset_read(reset, id);
|
||||
if(assert == true) {
|
||||
value &= ~ reset->signals[id].mask;
|
||||
|
|
|
@ -275,10 +275,12 @@ static void qspi_set_func_clk(struct k1x_qspi *qspi)
|
|||
clk_disable(&qspi->bus_clk);
|
||||
clk_disable(&qspi->clk);
|
||||
|
||||
reset_deassert_bulk(&qspi->resets);
|
||||
clk_enable(&qspi->bus_clk);
|
||||
clk_set_rate(&qspi->clk, qspi->max_hz);
|
||||
clk_enable(&qspi->clk);
|
||||
clk_enable(&qspi->bus_clk);
|
||||
reset_deassert_bulk(&qspi->resets);
|
||||
dev_info(qspi->dev, "bus clock: %dHz, PMUap reg[0x%08x]:0x%08x\n",
|
||||
qspi->max_hz, qspi->pmuap_reg, readl((void __iomem *)((unsigned long)qspi->pmuap_reg)));
|
||||
}
|
||||
|
||||
static int qspi_reset(struct k1x_qspi *qspi)
|
||||
|
|
|
@ -8,91 +8,77 @@
|
|||
#include <errno.h>
|
||||
#include <sysreset.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <power/pmic.h>
|
||||
|
||||
/*wdt*/
|
||||
#define K1X_WDT_REG (0xd4080000)
|
||||
#define K1X_WDT_ENABLE (0xd4080000 + 0xb8)
|
||||
#define K1X_WDT_TIMEOUT (0xd4080000 + 0xbc)
|
||||
#define K1X_WDT_RESET (0xd4080000 + 0xc8)
|
||||
#define K1X_WDT_STATUS (0xd4080000 + 0xc0)
|
||||
#define K1X_WDT_WSAR (0xd4080000 + 0x00b4)
|
||||
#define K1X_WDT_WFAR (0xd4080000 + 0x00b0)
|
||||
struct pmic_sysreset_data {
|
||||
u32 reboot_reg;
|
||||
u32 reboot_mask;
|
||||
int type;
|
||||
};
|
||||
|
||||
#define WDT_CLEAR_STATUS (0x0)
|
||||
#define WDT_RESET_ENABLE (0x1)
|
||||
#define WDT_ENABLE (0x3)
|
||||
#define WDT_TIMEOUT (0x1)
|
||||
|
||||
#define K1X_WDT_START_REG (0xd4051020)
|
||||
#define K1X_WDT_START_ENABLE (BIT(4))
|
||||
|
||||
#define K1X_WDT_CLK_RESET_REG (0xd4050200)
|
||||
#define K1X_WDT_MPU_REG (0xd4051024)
|
||||
#define K1X_WDT_CLK_RESET_ENABLE (0x3)
|
||||
#define K1X_WDT_CLK_RESET_FLAG (BIT(2))
|
||||
#define K1X_WDT_CLK_ENABLE_MPU (BIT(19))
|
||||
|
||||
static void spa_wdt_write_access(void)
|
||||
{
|
||||
writel(0xbaba, (void *)K1X_WDT_WFAR);
|
||||
writel(0xeb10, (void *)K1X_WDT_WSAR);
|
||||
}
|
||||
|
||||
static void spa_wdt_write(u32 val, void *reg)
|
||||
{
|
||||
spa_wdt_write_access();
|
||||
writel(val, reg);
|
||||
}
|
||||
|
||||
static void enable_wdt(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/*enable wdt clk reset*/
|
||||
reg = readl((void *)K1X_WDT_MPU_REG);
|
||||
writel(K1X_WDT_CLK_ENABLE_MPU | reg, (void *)K1X_WDT_MPU_REG);
|
||||
|
||||
reg = readl((void *)K1X_WDT_CLK_RESET_REG);
|
||||
writel(K1X_WDT_CLK_RESET_ENABLE | reg, (void *)K1X_WDT_CLK_RESET_REG);
|
||||
reg = readl((void *)K1X_WDT_CLK_RESET_REG);
|
||||
writel((~K1X_WDT_CLK_RESET_FLAG) & reg,(void *)K1X_WDT_CLK_RESET_REG);
|
||||
|
||||
|
||||
/*set watch dog*/
|
||||
spa_wdt_write(WDT_CLEAR_STATUS, (void *)K1X_WDT_STATUS);
|
||||
spa_wdt_write(WDT_TIMEOUT, (void *)K1X_WDT_TIMEOUT);
|
||||
spa_wdt_write(WDT_ENABLE, (void *)K1X_WDT_ENABLE);
|
||||
spa_wdt_write(WDT_RESET_ENABLE, (void *)K1X_WDT_RESET);
|
||||
|
||||
reg = readl((void*)K1X_WDT_START_REG);
|
||||
writel(K1X_WDT_START_ENABLE | reg, (void *)K1X_WDT_START_REG);
|
||||
}
|
||||
|
||||
static int spacemit_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
enable_wdt();
|
||||
/*wait for reset*/
|
||||
mdelay(5000);
|
||||
|
||||
/*if reset success, it would never return*/
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static int spacemit_sysreset_probe(struct udevice *dev)
|
||||
{
|
||||
static int pmic_sysreboot_types(const char *compat) {
|
||||
if (!strcmp(compat, "spacemit,spm8821-reset"))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmic_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||
{
|
||||
struct pmic_sysreset_data *data = dev_get_priv(dev);
|
||||
struct udevice *pmic_dev;
|
||||
int ret, value;
|
||||
|
||||
static struct sysreset_ops spacemit_sysreset = {
|
||||
.request = spacemit_sysreset_request,
|
||||
ret = uclass_get_device(UCLASS_PMIC, 0, &pmic_dev);
|
||||
if (ret) {
|
||||
pr_err("Failed to find PMIC device\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (data->type) {
|
||||
case 1:
|
||||
value = pmic_reg_read(pmic_dev, data->reboot_reg);
|
||||
if (ret) {
|
||||
pr_err("Failed to read reboot register for spm8821: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
value |= data->reboot_mask;
|
||||
ret = pmic_reg_write(pmic_dev, data->reboot_reg, value);
|
||||
if (ret) {
|
||||
pr_err("Failed to write reboot register for spm8821: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_err("Unsupported PMIC type for sysreset\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
mdelay(100);
|
||||
return -EINPROGRESS;
|
||||
}
|
||||
|
||||
static int pmic_sysreset_probe(struct udevice *dev)
|
||||
{
|
||||
struct pmic_sysreset_data *data = dev_get_priv(dev);
|
||||
const char *compat = dev_read_string(dev, "compatible");
|
||||
|
||||
data->reboot_reg = dev_read_u32_default(dev, "reboot-reg", 0);
|
||||
data->reboot_mask = dev_read_u32_default(dev, "reboot-mask", 0);
|
||||
data->type = pmic_sysreboot_types(compat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysreset_ops pmic_sysreset_ops = {
|
||||
.request = pmic_sysreset_request,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(spacemit_sysreset) = {
|
||||
.name = "spacemit_sysreset",
|
||||
U_BOOT_DRIVER(pmic_sysreset) = {
|
||||
.name = "pmic_sysreset",
|
||||
.id = UCLASS_SYSRESET,
|
||||
.ops = &spacemit_sysreset,
|
||||
.probe = spacemit_sysreset_probe,
|
||||
.priv_auto = sizeof(struct pmic_sysreset_data),
|
||||
.ops = &pmic_sysreset_ops,
|
||||
.probe = pmic_sysreset_probe,
|
||||
};
|
||||
|
|
|
@ -263,4 +263,10 @@ config USBNET_HOST_ADDR
|
|||
|
||||
endif # USB_ETHER
|
||||
|
||||
config USB_SET_SERIAL_NUMBER
|
||||
bool "set serial number while binding usb fastboot device"
|
||||
default y
|
||||
help
|
||||
enable to set serial number while binding fastboot devices
|
||||
|
||||
endif # USB_GADGET
|
||||
|
|
|
@ -262,9 +262,10 @@ static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
}
|
||||
|
||||
s = env_get("serial#");
|
||||
#ifdef CONFIG_USB_SET_SERIAL_NUMBER
|
||||
if (s)
|
||||
g_dnl_set_serialnumber((char *)s);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -220,7 +220,9 @@ static int g_dnl_get_bcd_device_number(struct usb_composite_dev *cdev)
|
|||
static int on_serialno(const char *name, const char *value, enum env_op op,
|
||||
int flags)
|
||||
{
|
||||
#ifdef CONFIG_USB_SET_SERIAL_NUMBER
|
||||
g_dnl_set_serialnumber((char *)value);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
U_BOOT_ENV_CALLBACK(serialno, on_serialno);
|
||||
|
|
|
@ -406,7 +406,10 @@ static int lcd_bl_enable(struct video_tx_device *dev, bool enable)
|
|||
video_tx_get_drvdata(dev);
|
||||
struct spacemit_panel_priv *priv = video_tx_client->priv;
|
||||
|
||||
if (enable)
|
||||
dm_gpio_set_value(&priv->bl, 1);
|
||||
else
|
||||
dm_gpio_set_value(&priv->bl, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "spacemit_dpu.h"
|
||||
|
||||
extern bool is_video_connected;
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct fb_info fbi = {0};
|
||||
|
@ -342,8 +344,10 @@ static int spacemit_display_init(struct udevice *dev, ulong fbbase, ofnode ep_no
|
|||
ret = spacemit_panel_init();
|
||||
if (ret) {
|
||||
pr_info("%s: Failed to init panel\n", __func__);
|
||||
is_video_connected = false;
|
||||
return ret;
|
||||
}
|
||||
is_video_connected = true;
|
||||
|
||||
spacemit_mode = &fbi.mode;
|
||||
uc_priv->xsize = spacemit_mode->xres;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#define SPACEMIT_HDMI_PHY_STATUS 0xC
|
||||
#define SPACEMIT_HDMI_PHY_HPD 0x1000
|
||||
int is_hdmi_connected;
|
||||
extern bool is_video_connected;
|
||||
|
||||
static int hdmi_get_plug_in_status(struct dw_hdmi *hdmi)
|
||||
{
|
||||
|
@ -57,48 +57,213 @@ static int hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi)
|
|||
return -1;
|
||||
}
|
||||
|
||||
enum bit_depth{
|
||||
EIGHT_BPP = 0,
|
||||
TEN_BPP = 1,
|
||||
TWELVE_BPP =2,
|
||||
};
|
||||
|
||||
int power_of_two(int n) {
|
||||
int result = 1;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
result <<= 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int pll8_bit_5_6 (int bit_clock, int n){
|
||||
int ret = 0;
|
||||
bit_clock = bit_clock / n;
|
||||
|
||||
if (bit_clock < 425)
|
||||
ret = 3;
|
||||
else if (bit_clock < 850)
|
||||
ret = 2;
|
||||
else if (bit_clock < 1700)
|
||||
ret = 1;
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pll6_bit_4_5 (int bit_clock, int n){
|
||||
int ret = 0;
|
||||
bit_clock = bit_clock / n;
|
||||
|
||||
if (bit_clock <= 337)
|
||||
ret = 0;
|
||||
else if (bit_clock < 425)
|
||||
ret = 1;
|
||||
else if (bit_clock < 675)
|
||||
ret = 0;
|
||||
else if (bit_clock < 850)
|
||||
ret = 1;
|
||||
else if (bit_clock < 1350)
|
||||
ret = 0;
|
||||
else if (bit_clock < 1700)
|
||||
ret = 1;
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pll5_bit_0_2 (int bit_clock, int n){
|
||||
int value = bit_clock * power_of_two(pll8_bit_5_6(bit_clock, n)) / n;
|
||||
int ret;
|
||||
|
||||
if (value < 1830)
|
||||
ret = 0;
|
||||
else if (value < 2030)
|
||||
ret = 1;
|
||||
else if (value < 2275)
|
||||
ret = 2;
|
||||
else if (value < 2520)
|
||||
ret = 3;
|
||||
else if (value < 2765)
|
||||
ret = 4;
|
||||
else if (value < 3015)
|
||||
ret = 5;
|
||||
else if (value < 3260)
|
||||
ret = 6;
|
||||
else
|
||||
ret = 7;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PLL9_BIT0_1[3] = {0x0, 0x1, 0x2};
|
||||
|
||||
void pll_reg_cal(int bit_clock, int ref_clock, int n, int *integer_part, u32 *hmdi_e8_reg) {
|
||||
long long int_para = 1000000000;
|
||||
long long value = (power_of_two(pll8_bit_5_6(bit_clock, n))) * bit_clock * int_para / (n * (pll6_bit_4_5(bit_clock, n) + 1) * ref_clock);
|
||||
long long integer = (power_of_two(pll8_bit_5_6(bit_clock, n)))* bit_clock / (n * (pll6_bit_4_5(bit_clock, n) + 1) * ref_clock) * int_para;
|
||||
long long fraction = value - integer;
|
||||
bool negative = false;
|
||||
int bit = 0;
|
||||
int frac_20bit = 0;
|
||||
int pll2_reg = 0;
|
||||
int pll1_reg = 0;
|
||||
int pll0_reg = 0;
|
||||
|
||||
negative = fraction > 500000000 ? true : false;
|
||||
fraction = negative ? 1000000000 - fraction : fraction;
|
||||
*integer_part = negative ? integer/int_para + 1 : integer/int_para;
|
||||
|
||||
|
||||
for (int i = 0; i < 20; i++){
|
||||
if (bit >= int_para) {
|
||||
frac_20bit |= 1 << (19 - i);
|
||||
fraction -= int_para;
|
||||
}
|
||||
fraction *= 2;
|
||||
bit = fraction;
|
||||
}
|
||||
|
||||
if (!negative){
|
||||
pll2_reg = ((frac_20bit & 0xF0000) >> 16) | (1 << 5);
|
||||
} else {
|
||||
frac_20bit = (~frac_20bit + 1) & 0xfffff;
|
||||
pll2_reg = 0x10 | ((frac_20bit & 0xF0000) >> 16) | (1 << 5);
|
||||
}
|
||||
|
||||
pll1_reg = (frac_20bit & 0xFF00) >> 8;
|
||||
pll0_reg = frac_20bit & 0xFF;
|
||||
*hmdi_e8_reg = (0x20 << 24) | (pll2_reg << 16) | (pll1_reg << 8) | pll0_reg;
|
||||
}
|
||||
|
||||
int pll_reg (void __iomem *hdmi_addr, int pixel_clock, int bit_depth) {
|
||||
int pll9_reg = 0, pll8_reg = 0, pll7_reg = 0, pll6_reg = 0, pll5_reg = 0, pll4_reg = 0;
|
||||
int n = 100;
|
||||
int ref_clock = 24;
|
||||
int hdmi_ec_reg = 0;
|
||||
int hdmi_f0_reg = 0;
|
||||
int hdmi_e8_reg = 0;
|
||||
int pow = 0;
|
||||
int bit_clock = bit_depth == EIGHT_BPP ? pixel_clock : pixel_clock * 125 / 100;
|
||||
|
||||
int integer_part = 0;
|
||||
|
||||
pll_reg_cal(bit_clock, ref_clock, n, &integer_part, &hdmi_e8_reg);
|
||||
|
||||
pll9_reg = 2 << 2 | PLL9_BIT0_1[bit_depth];
|
||||
pll8_reg = (0 << 7) | (pll8_bit_5_6(bit_clock, n) << 5) | 1;
|
||||
pll7_reg = 0x50;
|
||||
pll6_reg = 0xD | (pll6_bit_4_5(bit_clock, n) << 4) | (2 << 6);
|
||||
pll5_reg = 0x40 | pll5_bit_0_2(bit_clock, n);
|
||||
|
||||
pow = (pll8_bit_5_6(bit_clock, n));
|
||||
|
||||
pll4_reg = integer_part;
|
||||
|
||||
hdmi_ec_reg = (pll7_reg << 24) | (pll6_reg << 16) | (pll5_reg << 8) | pll4_reg;
|
||||
hdmi_f0_reg = (pll9_reg << 8) | pll8_reg;
|
||||
|
||||
writel(hdmi_e8_reg, hdmi_addr + 0xe8);
|
||||
writel(hdmi_ec_reg, hdmi_addr + 0xec);
|
||||
writel(hdmi_f0_reg, hdmi_addr + 0xf0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hdmi_write_bits(void __iomem *hdmi_addr, u16 offset, u32 value, u32 mask, u32 shifts)
|
||||
{
|
||||
u32 reg_val;
|
||||
|
||||
reg_val = readl(hdmi_addr + (offset));
|
||||
reg_val &= ~(mask << shifts);
|
||||
reg_val |= (value << shifts);
|
||||
writel(reg_val, hdmi_addr + (offset));
|
||||
}
|
||||
|
||||
void hdmi_init (void __iomem *hdmi_addr, int pixel_clock, int bit_depth){
|
||||
u32 value = 0;
|
||||
int color_depth = bit_depth == EIGHT_BPP ? 4 : 5;
|
||||
|
||||
u32 good_phase = 0x00;
|
||||
u32 bias_current = 0x01;
|
||||
u32 bias_risistor = 0x07;
|
||||
|
||||
// hdmi phy config
|
||||
writel(0x20200000, hdmi_addr + 0xe8);
|
||||
writel(0x508d425a, hdmi_addr + 0xec);
|
||||
writel(0x861, hdmi_addr + 0xf0);
|
||||
|
||||
writel(0xAE5C410F, hdmi_addr + 0xe0);
|
||||
hdmi_write_bits(hdmi_addr, 0xe0, bias_current, 0x03, 29);
|
||||
hdmi_write_bits(hdmi_addr, 0xe0, bias_risistor, 0x0F, 18);
|
||||
hdmi_write_bits(hdmi_addr, 0xe0, good_phase, 0x03, 14);
|
||||
|
||||
value = 0x0000000d | (color_depth << 4);
|
||||
writel(value, hdmi_addr + 0x34);
|
||||
|
||||
pll_reg(hdmi_addr, pixel_clock, bit_depth);
|
||||
writel(0x00, hdmi_addr + 0xe4);
|
||||
writel(0x03, hdmi_addr + 0xe4);
|
||||
value = readl(hdmi_addr + 0xe4);
|
||||
|
||||
pr_debug("%s() hdmi pll lock status 0x%x\n", __func__, value);
|
||||
// while ( (value & 0x10000) != 0) {
|
||||
// value = readl(hdmi->regs + 0xe4);
|
||||
// }
|
||||
udelay(100);
|
||||
|
||||
value = 0x1C208000 | bit_depth;
|
||||
writel(value, hdmi_addr + 0x28);
|
||||
}
|
||||
|
||||
|
||||
static int hdmi_enable(struct udevice *dev, int panel_bpp,
|
||||
const struct display_timing *edid)
|
||||
{
|
||||
void __iomem *hdmi_addr;
|
||||
hdmi_addr = ioremap(0xC0400500, 0x200);
|
||||
u32 value;
|
||||
u32 pixel_clock = 148500;
|
||||
int bit_depth = EIGHT_BPP;
|
||||
|
||||
// hdmi phy param config
|
||||
#if 0
|
||||
|
||||
writel(0x4d, hdmi_addr + 0x34);
|
||||
writel(0x20200000, hdmi_addr + 0xe8);
|
||||
writel(0x509D453E, hdmi_addr + 0xec);
|
||||
writel(0x821, hdmi_addr + 0xf0);
|
||||
writel(0x3, hdmi_addr + 0xe4);
|
||||
|
||||
udelay(2);
|
||||
value = readl(hdmi_addr + 0xe4);
|
||||
pr_debug("%s() hdmi 0xe4 0x%x\n", __func__, value);
|
||||
|
||||
writel(0x30184000, hdmi_addr + 0x28);
|
||||
|
||||
#else
|
||||
|
||||
writel(0xEE40410F, hdmi_addr + 0xe0);
|
||||
writel(0x0000005d, hdmi_addr + 0x34);
|
||||
writel(0x2022C000, hdmi_addr + 0xe8);
|
||||
writel(0x508D414D, hdmi_addr + 0xec);
|
||||
|
||||
writel(0x00000901, hdmi_addr + 0xf0);
|
||||
writel(0x3, hdmi_addr + 0xe4);
|
||||
|
||||
udelay(2);
|
||||
value = readl(hdmi_addr + 0xe4);
|
||||
pr_debug("%s() hdmi 0xe4 0x%x\n", __func__, value);
|
||||
|
||||
writel(0x3018C001, hdmi_addr + 0x28);
|
||||
|
||||
#endif
|
||||
|
||||
udelay(1000);
|
||||
hdmi_init(hdmi_addr, pixel_clock, bit_depth);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -140,42 +305,43 @@ static int spacemit_hdmi_probe(struct udevice *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_get_by_name(dev, "hdmi_reset", &priv->hdmi_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_get_by_name hdmi reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_deassert(&priv->hdmi_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_assert hdmi reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(&priv->hdmi_mclk);
|
||||
if (ret < 0) {
|
||||
pr_err("clk_enable hdmi mclk failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_get_by_name(dev, "hdmi_reset", &priv->hdmi_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_get_by_name hdmi reset failed: %d\n", ret);
|
||||
ret = clk_set_rate(&priv->hdmi_mclk, 491520000);
|
||||
if (ret < 0) {
|
||||
pr_err("clk_set_rate mipi dsi mclk failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = reset_deassert(&priv->hdmi_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_assert hdmi reset failed: %d\n", ret);
|
||||
goto free_reset;
|
||||
}
|
||||
|
||||
rate = clk_get_rate(&priv->hdmi_mclk);
|
||||
pr_debug("%s clk_get_rate hdmi mclk %ld\n", __func__, rate);
|
||||
|
||||
|
||||
priv->hdmi.ioaddr = (ulong)priv->base;
|
||||
priv->hdmi.reg_io_width = 4;
|
||||
|
||||
ret = hdmi_phy_wait_for_hpd(&priv->hdmi);
|
||||
is_hdmi_connected = ret;
|
||||
if (ret < 0) {
|
||||
pr_info("hdmi can not get hpd signal\n");
|
||||
is_video_connected = (ret >= 0);
|
||||
if (!is_video_connected) {
|
||||
pr_info("HDMI cannot get HPD signal\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
free_reset:
|
||||
clk_disable(&priv->hdmi_mclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -170,6 +170,30 @@ static int spacemit_mipi_dsi_probe(struct udevice *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_deassert(&priv->dsi_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_assert dsi_reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_deassert(&priv->mclk_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_assert mclk_reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_deassert(&priv->esc_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_assert esc_reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_deassert(&priv->lcd_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_assert lcd_reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(&priv->pxclk);
|
||||
if (ret < 0) {
|
||||
pr_err("clk_enable mipi dsi pxclk failed: %d\n", ret);
|
||||
|
@ -206,7 +230,7 @@ static int spacemit_mipi_dsi_probe(struct udevice *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(&priv->mclk, 307200000);
|
||||
ret = clk_set_rate(&priv->mclk, 491520000);
|
||||
if (ret < 0) {
|
||||
pr_err("clk_set_rate mipi dsi mclk failed: %d\n", ret);
|
||||
return ret;
|
||||
|
@ -239,30 +263,6 @@ static int spacemit_mipi_dsi_probe(struct udevice *dev)
|
|||
rate = clk_get_rate(&priv->bitclk);
|
||||
pr_debug("%s clk_get_rate bitclk rate = %ld\n", __func__, rate);
|
||||
|
||||
ret = reset_deassert(&priv->dsi_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_assert dsi_reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_deassert(&priv->mclk_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_assert mclk_reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_deassert(&priv->esc_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_assert esc_reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_deassert(&priv->lcd_reset);
|
||||
if (ret) {
|
||||
pr_err("reset_assert lcd_reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,14 @@ config WDT_APPLE
|
|||
The watchdog will perform a full SoC reset resulting in a
|
||||
reboot of the entire system.
|
||||
|
||||
config WDT_SPACEMIT
|
||||
bool "SPACEMIT watchdog timer support"
|
||||
depends on WDT
|
||||
help
|
||||
Enable support for the watchdog timer on SPACEMIT SoCs.
|
||||
The watchdog will perform a full SoC reset resulting in a
|
||||
reboot of the entire system.
|
||||
|
||||
config WDT_ARMADA_37XX
|
||||
bool "Marvell Armada 37xx watchdog timer support"
|
||||
depends on WDT && ARMADA_3700
|
||||
|
|
|
@ -43,3 +43,4 @@ obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o
|
|||
obj-$(CONFIG_WDT_SUNXI) += sunxi_wdt.o
|
||||
obj-$(CONFIG_WDT_TANGIER) += tangier_wdt.o
|
||||
obj-$(CONFIG_WDT_XILINX) += xilinx_wwdt.o
|
||||
obj-$(CONFIG_WDT_SPACEMIT) += spacemit_wdt.o
|
||||
|
|
199
drivers/watchdog/spacemit_wdt.c
Normal file
199
drivers/watchdog/spacemit_wdt.c
Normal file
|
@ -0,0 +1,199 @@
|
|||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <wdt.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <clk.h>
|
||||
#include <reset-uclass.h>
|
||||
|
||||
/* Register offsets relative to the base address of the WDT */
|
||||
#define WDT_ENABLE_OFFSET 0xB8
|
||||
#define WDT_TIMEOUT_OFFSET 0xBC
|
||||
#define WDT_RESET_OFFSET 0xC8
|
||||
#define WDT_STATUS_OFFSET 0xC0
|
||||
#define WDT_WSAR_OFFSET 0xB4
|
||||
#define WDT_WFAR_OFFSET 0xB0
|
||||
|
||||
/* Watchdog Timer Control Bits */
|
||||
#define WDT_CLEAR_STATUS 0x0
|
||||
#define WDT_RESET_ENABLE 0x1
|
||||
#define WDT_ENABLE 0x3
|
||||
#define WDT_TIMEOUT 0x1
|
||||
|
||||
/* WDT Start Register and its enable bit */
|
||||
#define WDT_START_ENABLE BIT(4)
|
||||
#define WDT_CLK_FREQ 256
|
||||
|
||||
struct spacemit_wdt_priv {
|
||||
struct clk clk;
|
||||
struct reset_ctl reset;
|
||||
fdt_addr_t base;
|
||||
fdt_addr_t start_reg;
|
||||
};
|
||||
|
||||
static void spa_wdt_write_access(fdt_addr_t base)
|
||||
{
|
||||
writel(0xbaba, (void *)(base + WDT_WFAR_OFFSET));
|
||||
writel(0xeb10, (void *)(base + WDT_WSAR_OFFSET));
|
||||
}
|
||||
|
||||
static void spa_wdt_write(u32 val, void *reg, fdt_addr_t base)
|
||||
{
|
||||
spa_wdt_write_access(base);
|
||||
writel(val, reg);
|
||||
}
|
||||
|
||||
static int initialize_wdt(struct udevice *dev, u64 timeout_ms)
|
||||
{
|
||||
struct spacemit_wdt_priv *priv = dev_get_priv(dev);
|
||||
if (!priv) {
|
||||
pr_err("Failed to get private data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int ret;
|
||||
u64 counter = (timeout_ms * WDT_CLK_FREQ) / 1000;
|
||||
|
||||
// Enable the clock
|
||||
ret = clk_enable(&priv->clk);
|
||||
if (ret) {
|
||||
pr_err("Failed to enable clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Deassert the reset
|
||||
ret = reset_deassert(&priv->reset);
|
||||
if (ret) {
|
||||
pr_err("Failed to deassert reset: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 timeout_val = readl((void *)(priv->base + WDT_TIMEOUT_OFFSET));
|
||||
|
||||
/* Set watchdog timer parameters */
|
||||
spa_wdt_write(WDT_CLEAR_STATUS, (void *)(priv->base + WDT_STATUS_OFFSET), priv->base);
|
||||
spa_wdt_write(counter, (void *)(priv->base + WDT_TIMEOUT_OFFSET), priv->base);
|
||||
spa_wdt_write(WDT_ENABLE, (void *)(priv->base + WDT_ENABLE_OFFSET), priv->base);
|
||||
spa_wdt_write(WDT_RESET_ENABLE, (void *)(priv->base + WDT_RESET_OFFSET), priv->base);
|
||||
|
||||
timeout_val = readl((void *)(priv->base + WDT_TIMEOUT_OFFSET));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spacemit_wdt_reset(struct udevice *dev)
|
||||
{
|
||||
struct spacemit_wdt_priv *priv = dev_get_priv(dev);
|
||||
if (!priv) {
|
||||
pr_err("Failed to get private data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Clear watchdog timer status only, do not set timeout */
|
||||
spa_wdt_write(WDT_CLEAR_STATUS, (void *)(priv->base + WDT_STATUS_OFFSET), priv->base);
|
||||
spa_wdt_write(WDT_RESET_ENABLE, (void *)(priv->base + WDT_RESET_OFFSET), priv->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int spacemit_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
|
||||
{
|
||||
struct spacemit_wdt_priv *priv = dev_get_priv(dev);
|
||||
if (!priv) {
|
||||
pr_err("Failed to get private data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int ret = initialize_wdt(dev, timeout_ms);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Start watchdog timer */
|
||||
u32 reg = readl((void*)priv->start_reg);
|
||||
writel(WDT_START_ENABLE | reg, (void *)priv->start_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int spacemit_wdt_stop(struct udevice *dev)
|
||||
{
|
||||
struct spacemit_wdt_priv *priv = dev_get_priv(dev);
|
||||
if (!priv) {
|
||||
pr_err("Failed to get private data\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
// Stop the watchdog timer by clearing the enable bit.
|
||||
spa_wdt_write(0x0, (void *)(priv->base + WDT_ENABLE_OFFSET), priv->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spacemit_wdt_expire_now(struct udevice *dev, ulong flags)
|
||||
{
|
||||
initialize_wdt(dev, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spacemit_wdt_probe(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
struct spacemit_wdt_priv *priv = malloc(sizeof(*priv));
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->priv_ = priv;
|
||||
|
||||
/* Retrieve and store the reset reference */
|
||||
ret = reset_get_by_index(dev, 0, &priv->reset);
|
||||
if (ret) {
|
||||
pr_err("Failed to get the first reset control: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Retrieve and store the clock reference */
|
||||
ret = clk_get_by_index(dev, 0, &priv->clk);
|
||||
if (ret) {
|
||||
pr_err("Failed to get the first clock source: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->base = dev_read_addr(dev);
|
||||
if (priv->base == FDT_ADDR_T_NONE) {
|
||||
pr_err("Failed to get WDT base address\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->start_reg = dev_read_addr_index(dev, 1);
|
||||
if (priv->start_reg == FDT_ADDR_T_NONE) {
|
||||
pr_err("Failed to get Watchdog start register address\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->priv_ = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct wdt_ops spacemit_wdt_ops = {
|
||||
.start = spacemit_wdt_start,
|
||||
.stop = spacemit_wdt_stop,
|
||||
.reset = spacemit_wdt_reset,
|
||||
.expire_now = spacemit_wdt_expire_now,
|
||||
};
|
||||
|
||||
static const struct udevice_id spacemit_wdt_ids[] = {
|
||||
{ .compatible = "spacemit,k1x-wdt" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(spacemit_wdt) = {
|
||||
.name = "spacemit_wdt",
|
||||
.id = UCLASS_WDT,
|
||||
.of_match = spacemit_wdt_ids,
|
||||
.probe = spacemit_wdt_probe,
|
||||
.ops = &spacemit_wdt_ops,
|
||||
};
|
|
@ -68,6 +68,9 @@
|
|||
#define BOOT_CIU_DEBUG_REG1 (BOOT_CIU_REG + 0x0394)
|
||||
#define BOOT_CIU_DEBUG_REG2 (BOOT_CIU_REG + 0x0398)
|
||||
|
||||
// non-reset register in P1
|
||||
#define P1_NON_RESET_REG (0xAB)
|
||||
|
||||
#define K1_EFUSE_USER_BANK0 8
|
||||
#define K1_DEFALT_PMIC_TYPE 0
|
||||
#define K1_DEFALT_EEPROM_I2C_INDEX 2
|
||||
|
@ -91,6 +94,7 @@ enum board_boot_mode {
|
|||
BOOT_MODE_NOR,
|
||||
BOOT_MODE_SD,
|
||||
BOOT_MODE_SHELL = 0x55f,
|
||||
BOOT_MODE_BOOTSTRAP,
|
||||
};
|
||||
|
||||
struct ddr_training_info_t {
|
||||
|
@ -114,7 +118,12 @@ struct boot_storage_op
|
|||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SPL_BUILD)
|
||||
#define MMC_DEV_EMMC (1)
|
||||
#else
|
||||
#define MMC_DEV_EMMC (2)
|
||||
#endif
|
||||
|
||||
#define MMC_DEV_SD (0)
|
||||
|
||||
#define BOOTFS_NAME ("bootfs")
|
||||
|
|
|
@ -51,6 +51,9 @@ enum {
|
|||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_CONFIG_ACCESS)
|
||||
FASTBOOT_COMMAND_CONFIG_ACCESS,
|
||||
#endif
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ERASE)
|
||||
FASTBOOT_COMMAND_OEM_ERASE,
|
||||
#endif
|
||||
#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_ENV_ACCESS)
|
||||
FASTBOOT_COMMAND_ENV_ACCESS,
|
||||
#endif
|
||||
|
|
|
@ -284,5 +284,10 @@ int flash_mmc_boot_op(struct blk_desc *dev_desc, void *buffer,
|
|||
|
||||
char *parse_mtdparts_and_find_bootfs(void);
|
||||
int get_partition_index_by_name(const char *part_name, int *part_index);
|
||||
int check_gzip_format(const unsigned char *src, unsigned long len);
|
||||
int clear_eeprom(u32 dev, u32 erase_size);
|
||||
void clear_storage_data(char *cmd_parameter, char *response);
|
||||
int _write_gpt_partition(struct flash_dev *fdev);
|
||||
int _write_mtd_partition(struct flash_dev *fdev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */
|
||||
#define SPINOR_OP_RDSFDP 0x5a /* Read SFDP */
|
||||
#define SPINOR_OP_RDCR 0x35 /* Read configuration register */
|
||||
#define SPINOR_OP_WDCR 0x31 /* Write configuration register */
|
||||
#define SPINOR_OP_RDFSR 0x70 /* Read flag status register */
|
||||
#define SPINOR_OP_CLFSR 0x50 /* Clear flag status register */
|
||||
#define SPINOR_OP_RDEAR 0xc8 /* Read Extended Address Register */
|
||||
|
@ -161,11 +162,18 @@
|
|||
#define SR_BP1 BIT(3) /* Block protect 1 */
|
||||
#define SR_BP2 BIT(4) /* Block protect 2 */
|
||||
#define SR_TB BIT(5) /* Top/Bottom protect */
|
||||
#define SR_SP BIT(6) /* sector protect */
|
||||
#define SR_SRWD BIT(7) /* SR write protect */
|
||||
/* Spansion/Cypress specific status bits */
|
||||
#define SR_E_ERR BIT(5)
|
||||
#define SR_P_ERR BIT(6)
|
||||
|
||||
/* Register 2 bits. */
|
||||
#define SR_LB1 BIT(3)
|
||||
#define SR_LB2 BIT(4)
|
||||
#define SR_LB3 BIT(5)
|
||||
#define SR_CMP BIT(6)
|
||||
|
||||
#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */
|
||||
|
||||
/* Enhanced Volatile Configuration Register bits */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue