1 Commits

Author SHA1 Message Date
devops_admin
316b169ffe Linux_SDK_V2.0.2
Signed-off-by: devops_admin <devops_admin@alibabacloud.com>
2024-09-20 22:46:25 +08:00
113 changed files with 19667 additions and 785 deletions

View File

@@ -727,6 +727,7 @@ UBOOTINCLUDE := \
-I$(srctree)/arch/$(ARCH)/thumb1/include),) \
-I$(srctree)/arch/$(ARCH)/include \
$(if $(CONFIG_TARGET_LIGHT_C910), -I$(srctree)/lib/sec_library/include) \
$(if $(CONFIG_TARGET_LIGHT_C910), -I$(srctree)/lib/sec_library/include/soft_crypto) \
-include $(srctree)/include/linux/kconfig.h
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
@@ -757,6 +758,8 @@ libs-y += drivers/net/phy/
libs-y += drivers/power/ \
drivers/power/domain/ \
drivers/power/fuel_gauge/ \
drivers/power/charge/ \
drivers/mcu/ \
drivers/power/mfd/ \
drivers/power/pmic/ \
drivers/power/battery/ \

View File

@@ -5,7 +5,7 @@ dtb-$(CONFIG_TARGET_SIFIVE_FU540) += hifive-unleashed-a00.dtb
dtb-$(CONFIG_TARGET_ICE_C910) += ice-c910.dtb
dtb-$(CONFIG_TARGET_LIGHT_EVB_MPW_C910) += light-evb-mpw-c910.dtb
dtb-$(CONFIG_TARGET_LIGHT_FPGA_FM_C910) += light-fpga-fm-c910.dtb
dtb-$(CONFIG_TARGET_LIGHT_C910) += light-a-ref.dtb light-b-ref.dtb light-a-val.dtb light-b-product.dtb light-a-product.dtb light-ant-ref.dtb light-beagle.dtb light-b-power.dtb light-lpi4a.dtb
dtb-$(CONFIG_TARGET_LIGHT_C910) += light-a-ref.dtb light-b-ref.dtb light-a-val.dtb light-b-product.dtb light-a-product.dtb light-ant-ref.dtb light-beagle.dtb light-b-power.dtb light-lpi4a.dtb th1520-rvbook.dtb
targets += $(dtb-y)

View File

@@ -312,7 +312,7 @@
tpm@0{
compatible = "z32h330tc,z32h330tc-spi";
reg = <0>;
spi-max-frequency = <40000000>;
spi-max-frequency = <20000000>;
};
};
@@ -513,8 +513,6 @@
compatible = "thead,light-dialog-pmic";
status = "okay";
soc_dvdd18_aon_reg: soc_dvdd18_aon {
regulator-name = "soc_dvdd18_aon";
regulator-boot-on;
@@ -669,6 +667,7 @@
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
iic-config = <0 0 2>;
pmic_dev_0: pmic-dev@0 {
pmic-name = "dialog,da9063,v1";
pmic-addr = <0x5a 0x5b>;

View File

@@ -663,8 +663,8 @@
compatible = "thead,light-pmic-conf";
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
#size-cells = <0>;
iic-config = <0 0 2>;
pmic_dev_0: pmic-dev@0 {
pmic-name = "ricoh,rn5t567,v0";
pmic-addr = <0x31>;

View File

@@ -677,7 +677,7 @@
#address-cells = <1>;
#size-cells = <0>;
iic-config = <0 0 2>;
pmic_dev_0: pmic-dev@0 {
pmic-name = "dialog,da9063,v1";
pmic-addr = <0x5a 0x5b>;

View File

@@ -0,0 +1,947 @@
/dts-v1/;
#include <dt-bindings/usb/pd.h>
#include <dt-bindings/pmic/light_pmic.h>
/ {
model = "T-HEAD c910 light";
compatible = "thead,c910_light";
#address-cells = <2>;
#size-cells = <2>;
charge-animation {
compatible = "rockchip,uboot-charge";
uboot-low-power-voltage = <7300>;
powerkey-gpio= <&ao_gpio_porta 6 0>;
status = "okay";
};
leds {
status = "okay";
compatible = "gpio-leds";
red-led {
gpios = <&gpio1_porta 14 0>; // GPIO_ACTIVE_HIGH: 0
label = "battery_charging";
default-state = "off";
};
green-led {
gpios = <&gpio1_porta 13 0>; // GPIO_ACTIVE_HIGH: 0
label = "battery_full";
default-state = "off";
};
blue-led {
gpios = <&gpio1_porta 15 0>; // GPIO_ACTIVE_HIGH: 0
label = "battery_start";
default-state = "off";
};
};
memory@0 {
device_type = "memory";
reg = <0x0 0xc0000000 0x0 0x40000000>;
};
aliases {
spi0 = &spi0;
spi1 = &qspi0;
spi2 = &qspi1;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <3000000>;
u-boot,dm-pre-reloc;
cpu@0 {
device_type = "cpu";
reg = <0>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcvsu";
mmu-type = "riscv,sv39";
u-boot,dm-pre-reloc;
};
};
soc {
#address-cells = <2>;
#size-cells = <2>;
compatible = "simple-bus";
ranges;
u-boot,dm-pre-reloc;
intc: interrupt-controller@ffd8000000 {
compatible = "riscv,plic0";
reg = <0xff 0xd8000000 0x0 0x04000000>;
status = "disabled";
};
dummy_apb: apb-clock {
compatible = "fixed-clock";
clock-frequency = <62500000>;
clock-output-names = "dummy_apb";
#clock-cells = <0>;
u-boot,dm-pre-reloc;
};
dummy_ahb: ahb-clock {
compatible = "fixed-clock";
clock-frequency = <250000000>;
clock-output-names = "core";
#clock-cells = <0>;
u-boot,dm-pre-reloc;
};
dummy_spi: spi-clock {
compatible = "fixed-clock";
clock-frequency = <396000000>;
clock-output-names = "dummy_spi";
#clock-cells = <0>;
u-boot,dm-pre-reloc;
};
dummy_qspi0: qspi0-clock {
compatible = "fixed-clock";
clock-frequency = <792000000>;
clock-output-names = "dummy_qspi0";
#clock-cells = <0>;
u-boot,dm-pre-reloc;
};
dummy_uart_sclk: uart-sclk-clock {
compatible = "fixed-clock";
clock-frequency = <100000000>;
clock-output-names = "dummy_uart_sclk";
#clock-cells = <0>;
u-boot,dm-pre-reloc;
};
dummy_i2c_icclk: i2c-icclk-clock {
compatible = "fixed-clock";
clock-frequency = <50000000>;
clock-output-names = "dummy_i2c_icclk";
#clock-cells = <0>;
u-boot,dm-pre-reloc;
};
dummy_dpu_pixclk: dpu-pix-clock {
compatible = "fixed-clock";
clock-frequency = <74250000>;
clock-output-names = "dummy_dpu_pixclk";
#clock-cells = <0>;
u-boot,dm-pre-reloc;
};
dummy_dphy_refclk: dphy-ref-clock {
compatible = "fixed-clock";
clock-frequency = <24000000>;
clock-output-names = "dummy_dpu_refclk";
#clock-cells = <0>;
u-boot,dm-pre-reloc;
};
i2c0: i2c@ffe7f20000 {
compatible = "snps,designware-i2c";
reg = <0xff 0xe7f20000 0x0 0x4000>;
clocks = <&dummy_i2c_icclk>;
clock-frequency = <100000>;
#address-cells = <1>;
#size-cells = <0>;
usbc0: husb311_0@4e {
compatible = "hynetek,husb311";
int-n-gpios = <&gpio3_porta 10 1>;
reg = <0x4e>;
status = "okay";
usb_con0: connector {
compatible = "usb-c-connector";
label = "USB-C";
data-role = "dual";
power-role = "dual";
try-power-role = "sink";
source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>;
sink-pdos =
<PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
PDO_FIXED(9000, 3000, PDO_FIXED_USB_COMM)
PDO_FIXED(12000, 3000, PDO_FIXED_USB_COMM)>;
op-sink-microwatt = <10000000>;
};
};
cw2015@62 {
clock-frequency = <100000>;
status = "okay";
compatible = "cellwise,cw2015";
reg = <0x62>;
cellwise,battery-profile = /bits/ 8
<0x17 0x67 0x66 0x65 0x64 0x63 0x61 0x5E
0x52 0x6D 0x4D 0x58 0x5B 0x51 0x44 0x3B
0x33 0x2C 0x26 0x23 0x24 0x29 0x34 0x42
0x49 0x16 0x0E 0xB8 0x3D 0x5D 0x68 0x7D
0x78 0x75 0x7B 0x7A 0x3F 0x18 0x82 0x48
0x09 0x4A 0x1A 0x47 0x86 0x93 0x97 0x15
0x49 0x71 0x9A 0xC3 0x80 0x41 0x4F 0xCB
0x2F 0x00 0x64 0xA5 0xB5 0x0D 0xB8 0x91>;
cellwise,monitor-interval-ms = <5000>;
cellwise,dual-cell = <1>;
};
bq25703: bq25703@6b {
status = "okay";
compatible = "ti,bq25703";
reg = <0x6b>;
typec0-enable-gpios = <&gpio3_porta 13 0>; //CHG_PATH_SEL0_180
typec1-enable-gpios = <&gpio3_porta 12 0>; //CHG_PATH_SEL1_180
ti,charge-current = <2500000>;
ti,max-input-voltage = <5000000>;
ti,input-current = <2000000>;
};
};
i2c1: i2c@ffe7f24000{
compatible = "snps,designware-i2c";
reg = <0xff 0xe7f24000 0x0 0x4000>;
clocks = <&dummy_i2c_icclk>;
clock-frequency = <100000>;
#address-cells = <1>;
#size-cells = <0>;
mcu_hc32fx:mcu-hc32fx@0x4c {
status = "okay";
compatible = "mcu_hc32fx";
reg = <0x4c>;
};
usbc1: husb311_1@4e {
compatible = "hynetek,husb311";
int-n-gpios = <&gpio1_porta 5 1>;
reg = <0x4e>;
status = "okay";
usb_con1: connector {
compatible = "usb-c-connector";
label = "USB-C";
data-role = "dual";
power-role = "dual";
try-power-role = "sink";
source-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)>;
sink-pdos =
<PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
PDO_FIXED(9000, 3000, PDO_FIXED_USB_COMM)
PDO_FIXED(12000, 3000, PDO_FIXED_USB_COMM)>;
op-sink-microwatt = <10000000>;
};
};
};
i2c2: i2c@ffec00c000{
compatible = "snps,designware-i2c";
reg = <0xff 0xec00c000 0x0 0x4000>;
clocks = <&dummy_i2c_icclk>;
clock-frequency = <100000>;
#address-cells = <1>;
#size-cells = <0>;
};
i2c3: i2c@ffec014000{
compatible = "snps,designware-i2c";
reg = <0xff 0xec014000 0x0 0x4000>;
clocks = <&dummy_i2c_icclk>;
clock-frequency = <100000>;
#address-cells = <1>;
#size-cells = <0>;
};
i2c4: i2c@ffe7f28000{
compatible = "snps,designware-i2c";
reg = <0xff 0xe7f28000 0x0 0x4000>;
clocks = <&dummy_i2c_icclk>;
clock-frequency = <100000>;
#address-cells = <1>;
#size-cells = <0>;
pcal6408ahk_a: gpio@20 {
compatible = "nxp,pca9554";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
};
};
i2c5: i2c@fff7f2c000{
compatible = "snps,designware-i2c";
reg = <0xff 0xf7f2c000 0x0 0x4000>;
clocks = <&dummy_i2c_icclk>;
clock-frequency = <100000>;
#address-cells = <1>;
#size-cells = <0>;
};
serial@ffe7014000 {
compatible = "snps,dw-apb-uart";
reg = <0xff 0xe7014000 0x0 0x400>;
clocks = <&dummy_uart_sclk>;
clock-frequency = <100000000>;
clock-names = "baudclk";
reg-shift = <2>;
reg-io-width = <4>;
u-boot,dm-pre-reloc;
};
gmac0: ethernet@ffe7070000 {
compatible = "snps,dwmac";
reg = <0xff 0xe7070000 0x0 0x2000>;
clocks = <&dummy_apb>;
clock-names = "stmmaceth";
snps,pbl = <32>;
snps,fixed-burst;
phy-mode = "rgmii-id";
phy-handle = <&phy_88E1111_a>;
status = "disabled";
mdio0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
phy_88E1111_a: ethernet-phy@1 {
reg = <0x1>;
};
phy_88E1111_b: ethernet-phy@2 {
reg = <0x2>;
};
};
};
gmac1: ethernet@ffe7060000 {
compatible = "snps,dwmac";
reg = <0xff 0xe7060000 0x0 0x2000>;
clocks = <&dummy_apb>;
clock-names = "stmmaceth";
snps,pbl = <32>;
snps,fixed-burst;
phy-mode = "rgmii-id";
phy-handle = <&phy_88E1111_b>;
status = "disabled";
};
emmc: sdhci@ffe7080000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7080000 0x0 0x10000>;
index = <0x0>;
clocks = <&dummy_ahb>;
clock-frequency = <198000000>;
clock-names = "core";
max-frequency = <198000000>;
sdhci-caps-mask = <0x0 0x1000000>;
mmc-hs400-1_8v;
non-removable;
no-sdio;
no-sd;
bus-width = <8>;
voltage= "1.8v";
pull_up;
io_fixed_1v8;
fifo-mode;
u-boot,dm-pre-reloc;
};
sdhci0: sd@ffe7090000 {
compatible = "snps,dwcmshc-sdhci";
reg = <0xff 0xe7090000 0x0 0x10000>;
index = <0x1>;
clocks = <&dummy_ahb>;
clock-frequency = <198000000>;
max-frequency = <198000000>;
sd-uhs-sdr104;
pull_up;
clock-names = "core";
bus-width = <4>;
voltage= "3.3v";
};
qspi0: spi@ffea000000 {
compatible = "snps,dw-apb-ssi-quad";
reg = <0xff 0xea000000 0x0 0x1000>;
clocks = <&dummy_qspi0>;
num-cs = <1>;
cs-gpio = <&gpio2_porta 3 0>; // GPIO_ACTIVE_HIGH: 0
spi-max-frequency = <100000000>;
#address-cells = <1>;
#size-cells =<0>;
spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-nand";
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <0>;
};
};
qspi1: spi@fff8000000 {
compatible = "snps,dw-apb-ssi-quad";
reg = <0xff 0xf8000000 0x0 0x1000>;
clocks = <&dummy_spi>;
num-cs = <1>;
cs-gpio = <&gpio0_porta 1 0>; // GPIO_ACTIVE_HIGH: 0
spi-max-frequency = <66000000>;
#address-cells = <1>;
#size-cells =<0>;
spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-nand";
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reg = <0>;
};
};
spi0: spi@ffe700c000 {
compatible = "snps,dw-apb-ssi";
reg = <0xff 0xe700c000 0x0 0x1000>;
clocks = <&dummy_spi>;
cs-gpio = <&gpio2_porta 15 0>;
spi-max-frequency = <100000000>;
#address-cells = <1>;
#size-cells = <0>;
tpm@0{
compatible = "z32h330tc,z32h330tc-spi";
reg = <0>;
spi-max-frequency = <22000000>;
};
};
gpio2: gpio@ffe7f34000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xe7f34000 0x0 0x1000>;
clocks = <&dummy_apb>;
#address-cells = <1>;
#size-cells = <0>;
gpio2_porta: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
snps,nr-gpios = <32>;
reg = <0>;
};
};
gpio3: gpio@ffe7f38000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xe7f38000 0x0 0x1000>;
clocks = <&dummy_apb>;
#address-cells = <1>;
#size-cells = <0>;
gpio3_porta: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
snps,nr-gpios = <32>;
reg = <0>;
};
};
gpio0: gpio@ffec005000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xec005000 0x0 0x1000>;
clocks = <&dummy_apb>;
#address-cells = <1>;
#size-cells = <0>;
gpio0_porta: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
snps,nr-gpios = <32>;
reg = <0>;
};
};
ao_gpio: gpio@fffff41000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xfff41000 0x0 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
ao_gpio_porta: ao_gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
nr-gpios-snps = <32>;
reg = <0>;
};
};
gpio1: gpio@ffec006000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff 0xec006000 0x0 0x1000>;
clocks = <&dummy_apb>;
#address-cells = <1>;
#size-cells = <0>;
gpio1_porta: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
snps,nr-gpios = <32>;
reg = <0>;
};
};
pwm: pwm@ffec01c000 {
compatible = "thead,pwm-light";
reg = <0xff 0xec01c000 0x0 0x4000>;
#pwm-cells = <2>;
};
dsi_regs: dsi-controller@ffef500000 {
compatible = "thead,light-dsi-regs", "syscon";
reg = <0xff 0xef500000 0x0 0x10000>;
status = "okay";
};
vosys_regs: vosys@ffef528000 {
compatible = "thead,light-vo-subsys", "syscon";
reg = <0xff 0xef528000 0x0 0x1000>;
status = "okay";
};
dpu: dc8200@ffef600000 {
compatible = "verisilicon,dc8200";
reg = <0xff 0xef600000 0x0 0x100>;
};
axiscr {
compatible = "thead,axiscr";
reg = <0xff 0xff004000 0x0 0x1000>;
lock-read = "okay";
lock-write = "okay";
#address-cells = <2>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
axiscr0: axisrc@0 {
device_type = "axiscr";
region = <0x00 0x00000000 0x00 0x80000000>; // 4KB align
status = "disabled";
#address-cells = <2>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
};
axiscr1: axisrc@1 {
device_type = "axiscr";
region = <0x00 0x80000000 0x00 0x80000000>; // 4KB align
status = "disabled";
#address-cells = <2>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
};
axiscr2: axisrc@2 {
device_type = "axiscr";
region = <0x01 0x00000000 0x00 0x80000000>; // 4KB align
status = "disabled";
#address-cells = <2>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
};
};
axiparity {
compatible = "thead,axiparity";
reg = <0xff 0xff00c000 0x0 0x1000>;
lock = "okay";
#address-cells = <2>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
axiparity0: axiparity@0 {
device_type = "axiparity";
region = <0x00 0x00000000 0x01 0x0000000>; // 4KB align
status = "disabled";
#address-cells = <2>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
};
axiparity1: axiparity@1 {
device_type = "axiparity";
region = <0x01 0x00000000 0x01 0x00000000>; // 4KB align
status = "disabled";
#address-cells = <2>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
};
};
dsi_bridge: dsi-bridge {
compatible = "thead,light-dsi-bridge";
clocks = <&dummy_dpu_pixclk>;
clock-names = "pix-clk";
phys = <&dsi_dphy>;
phy-names = "dphy";
};
dsi_host: dsi-host {
compatible = "synopsys,dw-mipi-dsi";
regmap = <&dsi_regs>;
status = "okay";
};
dsi_dphy: dsi-dphy {
compatible = "synopsys,dw-dphy";
regmap = <&dsi_regs>;
vosys-regmap = <&vosys_regs>;
clocks = <&dummy_dpu_pixclk>, <&dummy_dphy_refclk>;
clock-names = "pix-clk", "ref-clk";
#phy-cells = <0>;
status = "okay";
};
lcd_backlight: pwm-backlight {
compatible = "pwm-backlight";
pwms = <&pwm 0 5000000>;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <7>;
};
ili9881c_panel {
status = "disabled";
compatible = "ilitek,ili9881c";
backlight = <&lcd_backlight>;
reset-gpios = <&gpio1_porta 5 1>; /* active low */
lcd-en-gpios = <&pcal6408ahk_a 2 0>; /* active high */
lcd-bias-en-gpios = <&pcal6408ahk_a 4 0>;/* active high */
};
aon {
compatible = "thead,light-aon";
status = "okay";
wakeup-by-gpio-on;
wakeup-by-rtc-on;
pd: light-aon-pd {
compatible = "thead,light-aon-pd";
#power-domain-cells = <1>;
};
light-regu-reg {
compatible = "thead,light-dialog-pmic";
status = "okay";
soc_dvdd18_aon_reg: soc_dvdd18_aon {
regulator-name = "soc_dvdd18_aon";
regulator-boot-on;
regulator-always-on;
};
soc_avdd33_usb3_reg: soc_avdd33_usb3 {
regulator-name = "soc_avdd33_usb3";
regulator-boot-on;
regulator-always-on;
};
soc_dvdd08_aon_reg: soc_dvdd08_aon {
regulator-name = "soc_dvdd08_aon";
regulator-boot-on;
regulator-always-on;
};
soc_apcpu_dvdd_dvddm_reg: soc_apcpu_dvdd_dvddm {
regulator-name = "soc_apcpu_dvdd_dvddm";
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1570000>;
regulator-boot-on;
regulator-always-on;
};
soc_dvdd08_ddr_reg: soc_dvdd08_ddr {
regulator-name = "soc_dvdd08_ddr";
regulator-boot-on;
regulator-always-on;
};
soc_vdd_ddr_1v8_reg: soc_vdd_ddr_1v8 {
regulator-name = "soc_vdd_ddr_1v8";
regulator-boot-on;
regulator-always-on;
};
soc_vdd_ddr_1v1_reg: soc_vdd_ddr_1v1 {
regulator-name = "soc_vdd_ddr_1v1";
regulator-boot-on;
regulator-always-on;
};
soc_vdd_ddr_0v6_reg: soc_vdd_ddr_0v6 {
regulator-name = "soc_vdd_ddr_0v6";
regulator-boot-on;
regulator-always-on;
};
soc_dvdd18_ap_reg: soc_dvdd18_ap {
regulator-name = "soc_dvdd18_ap";
regulator-boot-on;
regulator-always-on;
};
soc_dvdd08_ap_reg: soc_dvdd08_ap {
regulator-name = "soc_dvdd08_ap";
regulator-boot-on;
regulator-always-on;
};
soc_avdd08_mipi_hdmi_reg: soc_avdd08_mipi_hdmi {
regulator-name = "soc_avdd08_mipi_hdmi";
regulator-boot-on;
regulator-always-on;
};
soc_avdd18_mipi_hdmi_reg: soc_avdd18_mipi_hdmi {
regulator-name = "soc_avdd18_mipi_hdmi";
regulator-boot-on;
regulator-always-on;
};
soc_dvdd33_emmc_reg: soc_dvdd33_emmc {
regulator-name = "soc_dvdd33_emmc";
regulator-boot-on;
regulator-always-on;
};
soc_dvdd18_emmc_reg: soc_dvdd18_emmc {
regulator-name = "soc_vdd18_emmc";
regulator-boot-on;
regulator-always-on;
};
soc_dovdd18_scan_reg: soc_dovdd18_scan {
regulator-name = "soc_dovdd18_scan";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <3600000>;
};
soc_vext_2v8_reg: soc_vext_2v8 {
regulator-name = "soc_vext_2v8";
regulator-boot-on;
regulator-always-on;
};
soc_dvdd12_scan_reg: soc_dvdd12_scan {
regulator-name = "soc_dvdd12_scan";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <3600000>;
};
soc_avdd28_scan_en_reg: soc_avdd28_scan_en {
regulator-name = "soc_avdd28_scan_en";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
};
};
aon_pmic_config {
compatible = "thead,light-pmic-conf";
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
iic-config = <0 0 2>;
pmic_dev_0: pmic-dev@0 {
pmic-name = "dialog,da9063,v1";
pmic-addr = <0x5a 0x5b>;
pmic_wdt_on;
status = "okay";
};
pmic_dev_1: pmic-dev@1 {
pmic-name = "dialog,da9121,v1";
pmic-addr = <0x68>;
status = "okay";
};
regu_config_0 {
reg_info = <&soc_dvdd18_aon_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO3>;
};
};
regu_config_1 {
reg_info = <&soc_avdd33_usb3_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO9>;
};
};
regu_config_2 {
reg_info = <&soc_dvdd08_aon_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO2>;
};
};
regu_config_3 {
reg_info = <&soc_apcpu_dvdd_dvddm_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_BCORE1>;
auto_on_info = <0 0 800000>;
};
regu_id@1 {
pmic_dev = <&pmic_dev_0 DA9063_ID_BCORE2>;
auto_on_info = <1 0 800000>;
};
regu_id@2 {
pmic_dev = <&pmic_dev_0 DA9063_ID_BUCKIO>;
auto_on_info = <2 0 800000>;
};
coupling_info@0 {
negative-min;
info = <0 2 5 30>;
};
coupling_info@1 {
negative-min;
info = <1 2 5 30>;
};
};
regu_config_4 {
reg_info = <&soc_dvdd08_ddr_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_BUCKPERI>;
};
};
regu_config_5 {
reg_info = <&soc_vdd_ddr_1v8_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO4>;
};
};
regu_config_6 {
reg_info = <&soc_vdd_ddr_1v1_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_BUCKMEM>;
};
};
regu_config_7 {
reg_info = <&soc_vdd_ddr_0v6_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_BUCKPRO>;
};
};
regu_config_8 {
reg_info = <&soc_dvdd18_ap_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO11>;
};
};
regu_config_9 {
reg_info = <&soc_dvdd08_ap_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_1 DA9121_ID_BUCK1>;
parent_pmic_dev = <&pmic_dev_0 2 0>;
};
};
regu_config_10 {
reg_info = <&soc_avdd08_mipi_hdmi_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO1>;
};
};
regu_config_11 {
reg_info = <&soc_avdd18_mipi_hdmi_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO5>;
};
};
regu_config_12 {
reg_info = <&soc_dvdd33_emmc_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO10>;
};
};
regu_config_13 {
reg_info = <&soc_dvdd18_emmc_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_GPIO7>;
parent_pmic_dev = <&pmic_dev_0 7 0>;
};
};
regu_config_14 {
reg_info = <&soc_dovdd18_scan_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO6>;
auto_on_info = <2 1 1800000>;
auto_off_info = <7 1>;
};
};
regu_config_15 {
reg_info = <&soc_vext_2v8_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO7>;
auto_on_info = <3 1 2800000>;
auto_off_info = <8 1>;
};
};
regu_config_16 {
reg_info = <&soc_dvdd12_scan_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_LDO8>;
auto_on_info = <4 1 1200000>;
auto_off_info = <9 1>;
};
};
regu_config_17 {
reg_info = <&soc_avdd28_scan_en_reg>;
status = "okay";
regu_id@0 {
pmic_dev = <&pmic_dev_0 DA9063_ID_GPIO4>;
};
};
};
};
};
chosen {
bootargs = "console=ttyS0,115200";
stdout-path = "/soc/serial@ffe7014000:115200";
};
};

View File

@@ -86,6 +86,10 @@ config LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A
bool "light lpi4a security boot with verification"
default n
config LIGHT_SEC_BOOT_WITH_VERIFY_RVBOOK
bool "light lpi4a security boot with verification"
default n
config TARGET_LIGHT_FPGA_FM_C910
bool "light fullmask FPGA board"
default n
@@ -126,6 +130,10 @@ config TARGET_LIGHT_FM_C910_LPI4A
bool "light fullmask for Lichee Pi 4A board "
default n
config TARGET_LIGHT_FM_C910_RVBOOK
bool "light fullmask for RVBOOK board "
default n
config TARGET_LIGHT_FM_C910_B_POWER
bool "light fullmask for light-b-power board "
default n

View File

@@ -7,6 +7,10 @@ DDR_SRC_PATH=lpddr4/src
DDR_REGU_SRC=lpddr-regu
DDR_FW_PATH=$(DDR_SRC_PATH)/ddr_phy_fw
ifdef CONFIG_RV_BOOK
obj-y += sys_clk.o
endif
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
obj-y += sys_clk.o

View File

@@ -16,11 +16,16 @@
#ifdef CONFIG_LIGHT_AON_CONF
#include "../../../drivers/misc/light_regu.h"
#include "dm/device.h"
#include "dm/uclass.h"
#endif
#ifdef CONFIG_USB_DWC3
static struct dwc3_device dwc3_device_data = {
#ifdef CONFIG_RV_BOOK
.maximum_speed = USB_SPEED_HIGH,
#else
.maximum_speed = USB_SPEED_SUPER,
#endif
.dr_mode = USB_DR_MODE_PERIPHERAL,
.index = 0,
};
@@ -140,7 +145,7 @@ void boot_audio(void)
#ifdef CONFIG_LIGHT_AON_CONF
int get_and_set_aon_config_data()
int get_and_set_aon_config_data(void)
{
int ret =0;
struct udevice *dev;
@@ -155,12 +160,12 @@ int get_and_set_aon_config_data()
config_data = (struct mic_regu_platdata *)(dev->platdata);
volatile aon_config_t* read_config = (aon_config_t* )C910_E902_START_ADDRESS;
if(strncmp(read_config->magic , AON_CONFIG_MAGIC, strlen(AON_CONFIG_MAGIC))) {
if(strncmp((const char*)read_config->magic , AON_CONFIG_MAGIC, strlen(AON_CONFIG_MAGIC))) {
printf("No aon config magic found in aon bin, please check the aon bin\n");
return -1;
}
if(strncmp(read_config->version, AON_CONFIG_VERSION, strlen(AON_CONFIG_VERSION))) {
if(strncmp((const char*)read_config->version, AON_CONFIG_VERSION, strlen(AON_CONFIG_VERSION))) {
printf("Err aon config version, aon bin is:%s, u-boot is:%s\n", read_config->version, AON_CONFIG_VERSION);
return -1;
}
@@ -173,25 +178,28 @@ int get_and_set_aon_config_data()
/*set pmic dev info */
int pmic_dev_num = config_data->pmic_list.pmic_num;
int pmic_dev_list_offset = sizeof(aon_config_t);
uintptr_t pmic_dev_start_addr = C910_E902_START_ADDRESS + pmic_dev_list_offset;
uint64_t pmic_dev_start_addr = C910_E902_START_ADDRESS + pmic_dev_list_offset;
int regu_num = config_data->regu_id_list.regu_id_num;
int regu_id_list_offset = pmic_dev_list_offset + pmic_dev_num * sizeof(pmic_dev_info_t);
uintptr_t regu_start_addr = C910_E902_START_ADDRESS + regu_id_list_offset;
uint64_t regu_start_addr = C910_E902_START_ADDRESS + regu_id_list_offset;
int aon_bin_size = regu_id_list_offset + regu_num* sizeof(csi_regu_id_t);
if( aon_bin_size > read_config->aon_config_partition_size) {
printf("Invalid aon partition size, aon bin support:%d, u-boot is %d\n", read_config->aon_config_partition_size, aon_bin_size);
printf("Invalid aon partition size, aon bin support:%lld, u-boot is %d\n", read_config->aon_config_partition_size, aon_bin_size);
return -1;
}
printf("pmic_dev_num:%d offset:%d addr:0x%10x\n",pmic_dev_num, pmic_dev_list_offset, pmic_dev_start_addr);
printf("pmic_dev_num:%d offset:%d addr:%lld\n",pmic_dev_num, pmic_dev_list_offset, pmic_dev_start_addr);
memcpy(pmic_dev_start_addr, config_data->pmic_list.pmic_list, pmic_dev_num * sizeof(pmic_dev_info_t));
printf("regu_num:%d offset:%d addr:0x%10x\n",regu_num,regu_id_list_offset, regu_start_addr);
memcpy((void*)pmic_dev_start_addr, config_data->pmic_list.pmic_list, pmic_dev_num * sizeof(pmic_dev_info_t));
printf("regu_num:%d offset:%d addr:%lld\n",regu_num,regu_id_list_offset, regu_start_addr);
memcpy(regu_start_addr, config_data->regu_id_list.regu_id_list, regu_num * sizeof(csi_regu_id_t));
memcpy((void*)regu_start_addr, config_data->regu_id_list.regu_id_list, regu_num * sizeof(csi_regu_id_t));
read_config->wakeup_flag = config_data->wakeup_flag;
read_config->aon_pmic.iic_config.iic_id = config_data->iic_config.iic_id;
read_config->aon_pmic.iic_config.addr_mode = config_data->iic_config.addr_mode;
read_config->aon_pmic.iic_config.speed = config_data->iic_config.speed;
read_config->aon_pmic.pmic_dev_num = pmic_dev_num;
read_config->aon_pmic.pmic_dev_list_offset = pmic_dev_list_offset;
@@ -199,11 +207,12 @@ int get_and_set_aon_config_data()
read_config->aon_pmic.regu_num = regu_num;
read_config->aon_pmic.regu_id_list_offset = regu_id_list_offset;
memcpy((void*)read_config->uboot_set_magic, UBOOT_CONFIG_MAGIC, strlen(UBOOT_CONFIG_MAGIC));
flush_cache((uintptr_t)C910_E902_START_ADDRESS, aon_bin_size);
printf("-->pmic_dev_num:%d offset:%d\n",read_config->aon_pmic.pmic_dev_num, read_config->aon_pmic.pmic_dev_list_offset);
printf("-->regu_num:%d offset:%d\n",read_config->aon_pmic.regu_num,read_config->aon_pmic.regu_id_list_offset);
return 0;
}
#endif

View File

@@ -15,6 +15,7 @@
#include "../../../lib/sec_library/include/sec_crypto_sha.h"
#include "../../../lib/sec_library/include/kdf.h"
#include "../../../lib/sec_library/include/sec_crypto_mac.h"
#include "fastboot.h"
#if CONFIG_IS_ENABLED(LIGHT_SEC_UPGRADE)
@@ -24,6 +25,14 @@
/* The macro is used to enable uboot version in efuse */
#define LIGHT_UBOOT_VERSION_IN_ENV 1
/* The macro is used to enable secimg version in env */
#define LIGHT_SECIMG_VERSION_IN_ENV 1
/* vimage return value */
#define VIMAGE_UPGRADE_NOT_REQUIRED 1
#define VIMAGE_BREAK_VERSION_RULE_ERROR 2
#define VIMAGE_SIGNATRE_VERIFICATION_FAILED 3
/* The macro is used to enble RPMB ACCESS KEY from KDF */
//#define LIGHT_KDF_RPMB_KEY 1
@@ -38,7 +47,8 @@ static const unsigned char emmc_rpmb_key_sample[32] = {0x33, 0x22, 0x11, 0x00, 0
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
#endif
static unsigned int upgrade_image_version = 0;
static char *current_slot = "a";
static char *update_slot = "b";
#define RPMB_EMMC_CID_SIZE 16
#define RPMB_CID_PRV_OFFSET 9
#define RPMB_CID_CRC_OFFSET 15
@@ -46,8 +56,8 @@ static unsigned int upgrade_image_version = 0;
static int tee_rpmb_key_gen(uint8_t* key, uint32_t * length)
{
uint32_t data[RPMB_EMMC_CID_SIZE / 4];
uint8_t huk[32];
uint32_t huk_len;
uint8_t huk[32];
uint32_t huk_len;
struct mmc *mmc = find_mmc_device(0);
int i;
sc_mac_t mac_handle;
@@ -72,14 +82,14 @@ static int tee_rpmb_key_gen(uint8_t* key, uint32_t * length)
memset((void *)((uint64_t)data + RPMB_CID_PRV_OFFSET), 0, 1);
memset((void *)((uint64_t)data + RPMB_CID_CRC_OFFSET), 0, 1);
/* Step1: Derive HUK from KDF function */
/* Step1: Derive HUK from KDF function */
ret = csi_kdf_gen_hmac_key(huk, &huk_len);
if (ret) {
printf("kdf gen hmac key faild[%d]\r\n", ret);
return -1;
}
/* Step2: Using HUK and data to generate RPMB key */
/* Step2: Using HUK and data to generate RPMB key */
ret = sc_mac_init(&mac_handle, 0);
if (ret) {
printf("mac init faild[%d]\r\n", ret);
@@ -152,22 +162,25 @@ int csi_rpmb_write_access_key(void)
int csi_tf_get_image_version(unsigned int *ver)
{
int ret = 0;
#if !LIGHT_SECIMG_VERSION_IN_ENV
char runcmd[64] = {0};
unsigned char blkdata[256];
int ret = 0;
/* tf version reside in RPMB block#0, offset#16*/
sprintf(runcmd, "mmc rpmb read 0x%lx 0 1", (unsigned long)blkdata);
ret = run_command(runcmd, 0);
if (ret == 0) {
*ver = (blkdata[16] << 8) + blkdata[17];
}
#else
*ver = env_get_hex("tf_version", 0);
#endif
return ret;
}
int csi_tf_set_image_version(unsigned int ver)
{
#if !LIGHT_SECIMG_VERSION_IN_ENV
char runcmd[64] = {0};
unsigned char blkdata[256];
unsigned long *temp_rpmb_key_addr = NULL;
@@ -194,7 +207,9 @@ int csi_tf_set_image_version(unsigned int ver)
sprintf(runcmd, "mmc rpmb write 0x%lx 0 1 0x%lx", (unsigned long)blkdata, (unsigned long)temp_rpmb_key_addr);
run_command(runcmd, 0);
#else
env_set_hex("tf_version", ver);
#endif
return 0;
}
@@ -205,17 +220,19 @@ int csi_tf_set_upgrade_version(void)
int csi_tee_get_image_version(unsigned int *ver)
{
int ret = 0;
#if !LIGHT_SECIMG_VERSION_IN_ENV
char runcmd[64] = {0};
unsigned char blkdata[256];
int ret = 0;
/* tf version reside in RPMB block#0, offset#0*/
sprintf(runcmd, "mmc rpmb read 0x%lx 0 1", (unsigned long)blkdata);
ret = run_command(runcmd, 0);
if (ret == 0) {
*ver = (blkdata[0] << 8) + blkdata[1];
}
#else
*ver = env_get_hex("tee_version", 0);
#endif
return ret;
}
@@ -234,6 +251,7 @@ int csi_kernel_get_image_version(unsigned int *ver)
int csi_tee_set_image_version(unsigned int ver)
{
#if !LIGHT_SECIMG_VERSION_IN_ENV
char runcmd[64] = {0};
unsigned char blkdata[256];
unsigned long *temp_rpmb_key_addr = NULL;
@@ -259,7 +277,9 @@ int csi_tee_set_image_version(unsigned int ver)
#endif
sprintf(runcmd, "mmc rpmb write 0x%lx 0 1 0x%lx", (unsigned long)blkdata, (unsigned long)temp_rpmb_key_addr);
run_command(runcmd, 0);
#else
env_set_hex("tee_version", ver);
#endif
return 0;
}
@@ -270,22 +290,25 @@ int csi_tee_set_upgrade_version(void)
int csi_sbmeta_get_image_version(unsigned int *ver)
{
int ret = 0;
#if !LIGHT_SECIMG_VERSION_IN_ENV
char runcmd[64] = {0};
unsigned char blkdata[256];
int ret = 0;
/* sbmeta version reside in RPMB block#0, offset#48*/
sprintf(runcmd, "mmc rpmb read 0x%lx 0 1", (unsigned long)blkdata);
ret = run_command(runcmd, 0);
if (ret == 0) {
*ver = (blkdata[48] << 8) + blkdata[49];
}
#else
*ver = env_get_hex("sbmeta_version", 0);
#endif
return ret;
}
int csi_sbmeta_set_image_version(unsigned int ver)
{
#if !LIGHT_SECIMG_VERSION_IN_ENV
char runcmd[64] = {0};
unsigned char blkdata[256];
unsigned long *temp_rpmb_key_addr = NULL;
@@ -310,7 +333,9 @@ int csi_sbmeta_set_image_version(unsigned int ver)
#endif
sprintf(runcmd, "mmc rpmb write 0x%lx 0 1 0x%lx", (unsigned long)blkdata, (unsigned long)temp_rpmb_key_addr);
run_command(runcmd, 0);
#else
env_set_hex("sbmeta_version", ver);
#endif
return 0;
}
@@ -438,13 +463,13 @@ int verify_image_version_rule(unsigned int new_ver, unsigned int cur_ver)
/* This is unsecure function */
if ((new_ver_y - cur_ver_y) == 0) {
printf("New version is equal to Current version, upgrade process terminates \n\n\n");
return -1;
return VIMAGE_UPGRADE_NOT_REQUIRED;
}
printf("This is unsecure function upgrade, going on uprade anyway\n");
} else if ((new_ver_x - cur_ver_x) != 1) {
/* Check the seure version rule */
printf("The upgrade version(X) breaks against the rule\n\n\n");
return -1;
return VIMAGE_BREAK_VERSION_RULE_ERROR;
}
printf("check image verison rule pass\n\n\n");
@@ -560,7 +585,7 @@ int light_vimage(int argc, char *const argv[])
unsigned long vimage_addr = 0;
unsigned int new_img_version = 0;
unsigned int cur_img_version = 0;
char imgname[32] = {0};
char imgname[32] = {0};
if (argc < 3)
return CMD_RET_USAGE;
@@ -575,35 +600,43 @@ int light_vimage(int argc, char *const argv[])
printf("get new img version fail\n");
return CMD_RET_FAILURE;
}
if (strcmp(imgname, UBOOT_PART_NAME) == 0) {
new_img_version = (((new_img_version & 0xff )+1) << 8) | ((new_img_version & 0xff00)>>8);
}
if (strcmp(imgname, UBOOT_PART_NAME) == 0) {
new_img_version = (((new_img_version & 0xff )+1) << 8) | ((new_img_version & 0xff00)>>8);
}
printf("Get new image version from image header: v%d.%d\n", (new_img_version & 0xff00)>>8, new_img_version & 0xff);
/* Check image version for ROLLBACK resisance */
/* Check image version for ROLLBACK resisance */
if (strcmp(imgname, TF_PART_NAME) == 0) {
ret = csi_tf_get_image_version(&cur_img_version);
if (ret != 0) {
printf("Get tf img version fail\n");
return CMD_RET_FAILURE;
}
#if LIGHT_NON_COT_BOOT
/* if in non-cot mode, tf and tee will not be signed at first */
if (image_have_head(vimage_addr) == 0 && ((cur_img_version & 0xFF00) >> 8 == 0)) {
return VIMAGE_UPGRADE_NOT_REQUIRED;
}
#endif
} else if (strcmp(imgname, TEE_PART_NAME) == 0){
ret = csi_tee_get_image_version(&cur_img_version);
if (ret != 0) {
printf("Get tee img version fail\n");
return CMD_RET_FAILURE;
}
#if LIGHT_NON_COT_BOOT
/* if in non-cot mode, tf and tee will not be signed at first */
if (image_have_head(vimage_addr) == 0 && ((cur_img_version & 0xFF00) >> 8 == 0)) {
return VIMAGE_UPGRADE_NOT_REQUIRED;
}
#endif
} else if (strcmp(imgname, KERNEL_PART_NAME) == 0){
ret = csi_kernel_get_image_version(&cur_img_version);
if (ret != 0) {
printf("Get kernel img version fail\n");
return CMD_RET_FAILURE;
}
} else if (strcmp(imgname, SBMETA_PART_NAME) == 0){
ret = csi_sbmeta_get_image_version(&cur_img_version);
if (ret != 0) {
printf("Get sbmeta img version fail\n");
@@ -626,13 +659,13 @@ int light_vimage(int argc, char *const argv[])
printf("unsupport image file\n");
return CMD_RET_FAILURE;
}
/* Verify image version rule */
ret = verify_image_version_rule(new_img_version, cur_img_version);
if (ret != 0) {
return CMD_RET_FAILURE;
return ret;
}
/* Save new image version to allow caller upgrade image version */
upgrade_image_version = new_img_version;
@@ -646,27 +679,27 @@ int light_vimage(int argc, char *const argv[])
if (strcmp(imgname, TF_PART_NAME) == 0) {
ret = verify_customer_image(T_TF, vimage_addr);
if (ret != 0) {
return CMD_RET_FAILURE;
return VIMAGE_SIGNATRE_VERIFICATION_FAILED;
}
} else if (strcmp(imgname, TEE_PART_NAME) == 0) {
ret = verify_customer_image(T_TEE, vimage_addr);
if (ret != 0) {
return CMD_RET_FAILURE;
return VIMAGE_SIGNATRE_VERIFICATION_FAILED;
}
} else if (strcmp(imgname, KERNEL_PART_NAME) == 0) {
ret = verify_customer_image(T_KRLIMG, vimage_addr);
if (ret != 0) {
return CMD_RET_FAILURE;
return VIMAGE_SIGNATRE_VERIFICATION_FAILED;
}
} else if (strcmp(imgname, UBOOT_PART_NAME) == 0) {
ret = verify_customer_image(T_UBOOT, vimage_addr);
if (ret != 0) {
return CMD_RET_FAILURE;
return VIMAGE_SIGNATRE_VERIFICATION_FAILED;
}
} else if (strcmp(imgname, SBMETA_PART_NAME) == 0) {
ret = verify_customer_image(T_SBMETA, vimage_addr);
if (ret != 0) {
return CMD_RET_FAILURE;
return VIMAGE_SIGNATRE_VERIFICATION_FAILED;
}
} else {
printf("Error: unknow image name\n");
@@ -687,8 +720,8 @@ int light_secboot(int argc, char * const argv[])
printf("\n\n");
printf("Now, we start to verify all trust firmware before boot kernel !\n");
/* Enject RPMB KEY directly in startup */
csi_rpmb_write_access_key();
/* Enject RPMB KEY directly in startup */
csi_rpmb_write_access_key();
/* Initialize secure basis of functions */
ret = csi_sec_init();
@@ -825,273 +858,317 @@ void sec_firmware_version_dump(void)
printf("\n\n");
}
void sec_upgrade_thread(void)
struct sec_img_upgrade_entry {
const char* filename;
const char* imgtype;
int (*set_version_func)(void);
const char *part_str;
};
static struct sec_img_upgrade_entry sec_img_list[] = {
{"sbmeta.bin", "sbmeta", csi_sbmeta_set_upgrade_version, "sbmeta"},
{"trust_firmware.bin", "tf", csi_tf_set_upgrade_version, "tee"},
{"tee.bin", "tee", csi_tee_set_upgrade_version, "tee"},
{NULL, NULL, NULL, NULL},
};
static struct blk_desc *dev_desc;
static int ab_get_blk(void)
{
struct disk_partition part_info;
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (dev_desc == NULL) {
printf("Failed to find MMC device\n");
return -1;
}
return 0;
}
static int ab_get_sec_part(const char *part_str, int update_part)
{
struct disk_partition part_info;
char partname[10] = {0};
int part = 0;
if (update_part) {
sprintf(partname, "%s_%s", part_str, update_slot);
} else {
sprintf(partname, "%s_%s", part_str, current_slot);
}
part = part_get_info_by_name(dev_desc, partname, &part_info);
if (part < 0) {
printf("Failed to find MMC device\n");
}
return part;
}
static int single_img_upgrade(struct sec_img_upgrade_entry *sec_img_entry)
{
const unsigned long temp_addr=0x200000;
char runcmd[80];
uint8_t * image_buffer = NULL;
uint8_t * image_malloc_buffer = NULL;
int ret = 0;
unsigned int sec_upgrade_flag = 0;
uint8_t * image_buffer = NULL;
uint8_t * image_malloc_buffer = NULL;
unsigned int upgrade_file_size = 0;
const char *filename = NULL;
int update_part = 0;
int current_part = 0;
int ret = 0;
char *argv[3] = {"vimage", NULL, NULL};
if (sec_img_entry == NULL) {
return -1;
}
update_part = ab_get_sec_part(sec_img_entry->part_str, 1);
if (update_part < 0) {
return -1;
}
filename = sec_img_entry->filename;
/* STEP 1: read upgrade image from storage */
printf("read upgrade image (%s) from storage \n", filename);
sprintf(runcmd, "ext4load mmc ${mmcdev}:%x 0x%p %s", update_part, (void *)temp_addr, filename);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("%s upgrade process is terminated due to some reason\n", filename);
return -1;
}
/* Fetch the total file size after read out operation end */
upgrade_file_size = env_get_hex("filesize", 0);
printf("upgrade file size: %d\n", upgrade_file_size);
/*store image to temp buffer as temp_addr may be decrypted*/
image_malloc_buffer = malloc(upgrade_file_size);
if (image_malloc_buffer == NULL) {
image_buffer = (uint8_t*)temp_addr + upgrade_file_size;
} else {
image_buffer = image_malloc_buffer;
}
memcpy(image_buffer, (void*)temp_addr, upgrade_file_size);
/* STEP 2: verify secure image */
sprintf(runcmd, "0x%lx", temp_addr);
argv[1] = runcmd;
argv[2] = sec_img_entry->imgtype;
ret = light_vimage(3, argv);
if (ret == VIMAGE_UPGRADE_NOT_REQUIRED) {
printf("%s Image may not need upgrade\n", sec_img_entry->imgtype);
return 0;
} else if (ret != 0) {
return -1;
}
/* STEP 3: update partition image in another slot */
current_part = ab_get_sec_part(sec_img_entry->part_str, 0);
if (current_part < 0) {
return -1;
}
printf("write upgrade image (%s) into another slot \n", filename);
sprintf(runcmd, "ext4write mmc 0:%x 0x%p /%s 0x%x", current_part, (void *)image_buffer, filename, upgrade_file_size);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("%s upgrade process is terminated due to some reason\n", filename);
return -1;
}
/* STEP 4: update secure image version */
sec_img_entry->set_version_func();
printf("\n\n%s image ugprade process is successful\n\n", filename);
return 0;
}
static int sec_img_upgrade(void)
{
int ret = 0;
struct sec_img_upgrade_entry *sec_img_entry = sec_img_list;
ab_get_blk();
while (sec_img_entry->filename != NULL) {
ret = single_img_upgrade(sec_img_entry);
if (ret) {
printf("Fail to upgrade image\n");
return -1;
}
sec_img_entry++;
}
return 0;
}
extern int hibernate_image_cleaned_flag;
extern void clean_hibernate_image_header(char *response);
static char *response[FASTBOOT_RESPONSE_LEN] = {0};
void sec_upgrade_thread(void)
{
const unsigned long temp_addr=0x200000;
char runcmd[80];
int ret = 0;
unsigned int sec_upgrade_flag = 0;
unsigned int upgrade_file_size = 0;
sec_upgrade_flag = env_get_hex("sec_upgrade_mode", 0);
current_slot = env_get("slot_suffix");
update_slot = strcmp(current_slot, "a") == 0 ? "b" : "a";
if (sec_upgrade_flag == 0) {
return;
}
clean_hibernate_image_header(response);
printf("bootstrap: sec_upgrade_flag: %x\n", sec_upgrade_flag);
if (sec_upgrade_flag == UBOOT_SEC_UPGRADE_FLAG) {
unsigned int block_cnt;
struct blk_desc *dev_desc;
const unsigned long uboot_temp_addr=0x80000000;
#define BLOCK_SIZE 512
#define PUBKEY_HEADER_SIZE 0x1000
/* STEP 1: read upgrade image (u-boot-with-spl.bin) from stash partition */
printf("read upgrade image (u-boot-with-spl.bin) from stash partition \n");
sprintf(runcmd, "ext4load mmc 0:4 0x%p u-boot-with-spl.bin", (void *)temp_addr);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("UBOOT Upgrade process is terminated due to some reason\n");
goto _upgrade_uboot_exit;
}
/* Fetch the total file size after read out operation end */
upgrade_file_size = env_get_hex("filesize", 0);
printf("uboot upgrade file size: %d\n", upgrade_file_size);
/* STEP 2: verify its authentiticy here */
memmove((void *)uboot_temp_addr, (const void *)temp_addr, upgrade_file_size);
sprintf(runcmd, "vimage 0x%p uboot", (void *)(uboot_temp_addr+PUBKEY_HEADER_SIZE));
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("UBOOT Image verification fail and upgrade process terminates\n");
goto _upgrade_uboot_exit;
}
/* STEP 3: update uboot partition */
printf("write upgrade image (u-boot-with-spl.bin) into uboot partition \n");
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
printf("Invalid mmc device\n");
goto _upgrade_uboot_exit;
}
block_cnt = upgrade_file_size / BLOCK_SIZE;
if (upgrade_file_size % BLOCK_SIZE) {
block_cnt = block_cnt +1;
}
run_command("mmc partconf 0 1 0 1", 0);
sprintf(runcmd, "mmc write 0x%p 0 %x", (void *)temp_addr, block_cnt);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
run_command("mmc partconf 0 1 0 0", 0);
if (ret != 0) {
printf("UBOOT upgrade process is terminated due to some reason\n");
goto _upgrade_uboot_exit;
}
/* STEP 4: update tee version */
ret = csi_uboot_set_upgrade_version();
if (ret != 0) {
printf("Set uboot upgrade version fail\n");
goto _upgrade_uboot_exit;
}
printf("\n\nUBOOT image ugprade process is successful\n\n");
_upgrade_uboot_exit:
/* set secure upgrade flag to 0 that indicate upgrade over */
run_command("env set sec_upgrade_mode 0", 0);
run_command("saveenv", 0);
run_command("reset", 0);
} else if ((sec_upgrade_flag >> 16) == SEC_IMG_UPGRADE_FLAG) {
ret = sec_img_upgrade();
if (ret) {
printf("secure image upgrade failed\n");
/* if failed, clear upgrade flag, terminate upgradation */
sec_upgrade_flag = 0;
} else {
/* if succeed, clear secure flag */
sec_upgrade_flag = sec_upgrade_flag & 0x0000FFFF;
/* if boot need not update, switch current slot to update slot */
if ((sec_upgrade_flag & 0xFF00) != BOOT_IMG_UPGRADE_FLAG) {
sprintf(runcmd, "env set slot_suffix %s", update_slot);
run_command(runcmd, 0);
}
}
/* set upgrade flag */
sprintf(runcmd, "env set sec_upgrade_mode %x", sec_upgrade_flag);
run_command(runcmd, 0);
run_command("saveenv", 0);
run_command("reset", 0);
} else if (((sec_upgrade_flag & 0xFF00) != BOOT_IMG_UPGRADE_FLAG) &&
((sec_upgrade_flag & 0xFF) != ROOT_IMG_UPGRADE_FLAG)) {
printf("Unknown bootstrap, Force sysem reboot\n");
run_command("env set sec_upgrade_mode 0", 0);
run_command("saveenv", 0);
run_command("reset", 0);
}
}
void nonsec_upgrade_thread(void)
{
unsigned int sec_upgrade_flag;
unsigned long retries;
char runcmd[32] = {0};
sec_upgrade_flag = env_get_hex("sec_upgrade_mode", 0);
if (sec_upgrade_flag == 0)
return;
printf("bootstrap: sec_upgrade_flag: %x\n", sec_upgrade_flag);
if (sec_upgrade_flag == TF_SEC_UPGRADE_FLAG) {
/* STEP 1: read upgrade image (trust_firmware.bin) from stash partition */
printf("read upgrade image (trust_firmware.bin) from stash partition \n");
sprintf(runcmd, "ext4load mmc 0:4 0x%p trust_firmware.bin", (void *)temp_addr);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("TF upgrade process is terminated due to some reason\n");
goto _upgrade_tf_exit;
retries = env_get_ulong("retries", 10, 5);
if (sec_upgrade_flag == 0) {
if (retries < 5 && retries > 0) {
printf("boot upgradation is successful!\n");
run_command("env set retries 5", 0);
run_command("env save", 0);
}
/* Fetch the total file size after read out operation end */
upgrade_file_size = env_get_hex("filesize", 0);
printf("upgrade file size: %d\n", upgrade_file_size);
/*store image to temp buffer as temp_addr may be decrypted*/
image_malloc_buffer = malloc(upgrade_file_size);
if ( image_malloc_buffer == NULL ) {
image_buffer = (uint8_t*)temp_addr + upgrade_file_size;
} else {
image_buffer = image_malloc_buffer;
return;
}
memcpy(image_buffer, (void*)temp_addr, upgrade_file_size);
/* STEP 2: verify its authentiticy here */
sprintf(runcmd, "vimage 0x%p tf", (void *)temp_addr);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("TF Image verification fail and upgrade process terminates\n");
goto _upgrade_tf_exit;
/* when sec_upgrade_mode != 0 and the first time try to boot. switch current slot to update slot*/
if (retries == 5) {
printf("upgrade images are in slot %s...\n", update_slot);
sprintf(runcmd, "env set slot_suffix %s", update_slot);
run_command(runcmd, 0);
}
/* if ROOT image need upgrade, clear flag */
if ((sec_upgrade_flag & 0xFF) == ROOT_IMG_UPGRADE_FLAG) {
printf("in root image upgrade process...\n");
sec_upgrade_flag = sec_upgrade_flag & 0xFF00;
sprintf(runcmd, "env set sec_upgrade_mode %X", sec_upgrade_flag);
run_command(runcmd, 0);
}
/* if boot image need upgrade, decrement retries */
if ((sec_upgrade_flag & 0xFF00) == BOOT_IMG_UPGRADE_FLAG) {
printf("in boot image upgrade process...\n");
retries--;
printf("remaining retry times: %ld\n", retries);
if (retries == 0 || retries > 5) {
/*
* upgrade failed. Now updated images are in current slot
* switch to original slot
*/
printf("boot images upgrade failed. switch slot to %s...\n", update_slot);
sprintf(runcmd, "env set slot_suffix %s", update_slot);
run_command(runcmd, 0);
run_command("env set sec_upgrade_mode 0", 0);
retries = 5;
}
/* STEP 3: update tf partition */
printf("read upgrade image (trust_firmware.bin) into tf partition \n");
sprintf(runcmd, "ext4write mmc 0:3 0x%p /trust_firmware.bin 0x%x", (void *)image_buffer, upgrade_file_size);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("TF upgrade process is terminated due to some reason\n");
goto _upgrade_tf_exit;
}
/* STEP 4: update tf version */
ret = csi_tf_set_upgrade_version();
if (ret != 0) {
printf("Set trustfirmware upgrade version fail\n");
goto _upgrade_tf_exit;
}
printf("\n\nTF image ugprade process is successful\n\n");
_upgrade_tf_exit:
/* set secure upgrade flag to 0 that indicate upgrade over */
run_command("env set sec_upgrade_mode 0", 0);
run_command("saveenv", 0);
run_command("reset", 0);
if ( image_malloc_buffer != NULL ) {
free(image_malloc_buffer);
image_malloc_buffer = NULL;
}
} else if (sec_upgrade_flag == TEE_SEC_UPGRADE_FLAG) {
/* STEP 1: read upgrade image (tee.bin) from stash partition */
printf("read upgrade image (tee.bin) from stash partition \n");
sprintf(runcmd, "ext4load mmc 0:4 0x%p tee.bin", (void *)temp_addr);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("TEE Upgrade process is terminated due to some reason\n");
goto _upgrade_tee_exit;
}
/* Fetch the total file size after read out operation end */
upgrade_file_size = env_get_hex("filesize", 0);
printf("TEE upgrade file size: %d\n", upgrade_file_size);
/*store image to temp buffer as temp_addr may be decrypted*/
image_malloc_buffer = malloc(upgrade_file_size);
if ( image_malloc_buffer == NULL ) {
image_buffer = (uint8_t*)temp_addr + upgrade_file_size;
} else {
image_buffer = image_malloc_buffer;
}
memcpy(image_buffer, (void*)temp_addr, upgrade_file_size);
/* STEP 2: verify its authentiticy here */
sprintf(runcmd, "vimage 0x%p tee", (void *)temp_addr);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("TEE Image verification fail and upgrade process terminates\n");
goto _upgrade_tee_exit;
}
/* STEP 3: update tee partition */
printf("read upgrade image (tee.bin) into sbmeta partition \n");
sprintf(runcmd, "ext4write mmc 0:3 0x%p /tee.bin 0x%x", (void *)image_buffer, upgrade_file_size);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("TEE upgrade process is terminated due to some reason\n");
goto _upgrade_tee_exit;
}
/* STEP 4: update tee version */
ret = csi_tee_set_upgrade_version();
if (ret != 0) {
printf("Set tee upgrade version fail\n");
goto _upgrade_tee_exit;
}
printf("\n\nTEE image ugprade process is successful\n\n");
_upgrade_tee_exit:
/* set secure upgrade flag to 0 that indicate upgrade over */
run_command("env set sec_upgrade_mode 0", 0);
run_command("saveenv", 0);
run_command("reset", 0);
if ( image_malloc_buffer != NULL ) {
free(image_malloc_buffer);
image_malloc_buffer = NULL;
}
} else if (sec_upgrade_flag == SBMETA_SEC_UPGRADE_FLAG) {
/* STEP 1: read upgrade image (sbmeta.bin) from stash partition */
printf("read upgrade image (sbmeta.bin) from stash partition \n");
sprintf(runcmd, "ext4load mmc 0:4 0x%p sbmeta.bin", (void *)temp_addr);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("SBMETA Upgrade process is terminated due to some reason\n");
goto _upgrade_sbmeta_exit;
}
/* Fetch the total file size after read out operation end */
upgrade_file_size = env_get_hex("filesize", 0);
printf("SBMETA upgrade file size: %d\n", upgrade_file_size);
/*store image to temp buffer as temp_addr may be decrypted*/
image_malloc_buffer = malloc(upgrade_file_size);
if ( image_malloc_buffer == NULL ) {
image_buffer = (uint8_t*)temp_addr + upgrade_file_size;
} else {
image_buffer = image_malloc_buffer;
}
memcpy(image_buffer, (void*)temp_addr, upgrade_file_size);
/* STEP 2: verify its authentiticy here */
sprintf(runcmd, "vimage 0x%p sbmeta", (void *)temp_addr);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("SBMETA Image verification fail and upgrade process terminates\n");
goto _upgrade_sbmeta_exit;
}
/* STEP 3: update sbmeta partition */
printf("read upgrade image (SBMETA.bin) into sbmeta partition \n");
sprintf(runcmd, "ext4write mmc 0:3 0x%p /sbmeta.bin 0x%x", (void *)image_buffer, upgrade_file_size);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("SBMETA upgrade process is terminated due to some reason\n");
goto _upgrade_sbmeta_exit;
}
/* STEP 4: update sbmeta version */
ret = csi_sbmeta_set_upgrade_version();
if (ret != 0) {
printf("Set sbmeta upgrade version fail\n");
goto _upgrade_sbmeta_exit;
}
printf("\n\nSBMETA image ugprade process is successful\n\n");
_upgrade_sbmeta_exit:
/* set secure upgrade flag to 0 that indicate upgrade over */
run_command("env set sec_upgrade_mode 0", 0);
run_command("saveenv", 0);
run_command("reset", 0);
if ( image_malloc_buffer != NULL ) {
free(image_malloc_buffer);
image_malloc_buffer = NULL;
}
} else if (sec_upgrade_flag == UBOOT_SEC_UPGRADE_FLAG) {
unsigned int block_cnt;
struct blk_desc *dev_desc;
const unsigned long uboot_temp_addr=0x80000000;
#define BLOCK_SIZE 512
#define PUBKEY_HEADER_SIZE 0x1000
/* STEP 1: read upgrade image (u-boot-with-spl.bin) from stash partition */
printf("read upgrade image (u-boot-with-spl.bin) from stash partition \n");
sprintf(runcmd, "ext4load mmc 0:4 0x%p u-boot-with-spl.bin", (void *)temp_addr);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("UBOOT Upgrade process is terminated due to some reason\n");
goto _upgrade_uboot_exit;
}
/* Fetch the total file size after read out operation end */
upgrade_file_size = env_get_hex("filesize", 0);
printf("uboot upgrade file size: %d\n", upgrade_file_size);
/* STEP 2: verify its authentiticy here */
memmove((void *)uboot_temp_addr, (const void *)temp_addr, upgrade_file_size);
sprintf(runcmd, "vimage 0x%p uboot", (void *)(uboot_temp_addr+PUBKEY_HEADER_SIZE));
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
if (ret != 0) {
printf("UBOOT Image verification fail and upgrade process terminates\n");
goto _upgrade_uboot_exit;
}
/* STEP 3: update uboot partition */
printf("write upgrade image (u-boot-with-spl.bin) into boot partition \n");
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
printf("Invalid mmc device\n");
goto _upgrade_uboot_exit;
}
block_cnt = upgrade_file_size / BLOCK_SIZE;
if (upgrade_file_size % BLOCK_SIZE) {
block_cnt = block_cnt +1;
}
run_command("mmc partconf 0 1 0 1", 0);
sprintf(runcmd, "mmc write 0x%p 0 %x", (void *)temp_addr, block_cnt);
printf("runcmd:%s\n", runcmd);
ret = run_command(runcmd, 0);
run_command("mmc partconf 0 1 0 0", 0);
if (ret != 0) {
printf("UBOOT upgrade process is terminated due to some reason\n");
goto _upgrade_uboot_exit;
}
/* STEP 4: update tee version */
ret = csi_uboot_set_upgrade_version();
if (ret != 0) {
printf("Set uboot upgrade version fail\n");
goto _upgrade_uboot_exit;
}
printf("\n\nUBOOT image ugprade process is successful\n\n");
_upgrade_uboot_exit:
/* set secure upgrade flag to 0 that indicate upgrade over */
run_command("env set sec_upgrade_mode 0", 0);
run_command("saveenv", 0);
run_command("reset", 0);
} else {
printf("Unknown bootstrap, Force sysem reboot\n");
run_command("reset", 0);
sprintf(runcmd, "env set retries %ld", retries);
run_command(runcmd, 0);
run_command("env save", 0);
}
}
#endif

View File

@@ -1146,7 +1146,7 @@ void ap_mipi_dsi1_clk_endisable(bool en)
writel(cfg1, (void __iomem *)AP_DPU1_PLL_CFG1);
}
#if defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_DISCRETE) || defined (CONFIG_TARGET_LIGHT_FM_C910_BEAGLE) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_POWER) || defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_B) || defined (CONFIG_TARGET_LIGHT_FM_C910_LPI4A)
#if defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_DISCRETE) || defined (CONFIG_TARGET_LIGHT_FM_C910_BEAGLE) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_POWER) || defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_B)
static void ap_multimedia_div_num_set(enum multimedia_div_type type, unsigned int div_num)
{
unsigned long div_reg;
@@ -1305,7 +1305,7 @@ int clk_config(void)
/* The boards other than the LightA board perform the bus down-speed operation */
#if defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_DISCRETE) || defined (CONFIG_TARGET_LIGHT_FM_C910_BEAGLE) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_POWER) || defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_B) || defined (CONFIG_TARGET_LIGHT_FM_C910_LPI4A)
#if defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_DISCRETE) || defined (CONFIG_TARGET_LIGHT_FM_C910_BEAGLE) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_POWER) || defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_B)
ap_multimedia_div_num_set(VI_MIPI_CSI0_DIV, 12); /* Input frquency: 2376MHZ */
ap_multimedia_div_num_set(VI_ISP0_CORE_DIV, 12); /* Input frquency: 2376MHZ */
ap_multimedia_div_num_set(VI_ISP1_CORE_DIV, 12); /* Input frquency: 2376MHZ */

View File

@@ -15,6 +15,11 @@
#include <fdt_support.h>
#include <fs.h>
#include <asm/global_data.h>
#ifdef CONFIG_RV_BOOK
#include <memalign.h>
#include <fdt_support.h>
#include <fs.h>
#endif
#define SOC_PIN_AP_RIGHT_TOP (0x0)
#define SOC_PIN_AP_LEFT_TOP (0x1)
@@ -343,6 +348,193 @@ static int light_pinmx_get_mux_base(pin_name_t pin_name, uint32_t** cfg_base)
return 0;
}
#ifdef CONFIG_FASTBOOT_FLASH_MMC
/*
* The SN data is stored in the first 512B of the NV partition. It should be read out
* and updated. In the following situations, the update will fail:
* a. The NV partition cannot be found
* b. The length of the SN is out of range
* c. The value of the SN contains unprintable characters
*/
#define MAX_SN_SIZE (64 + 2) /* extra two bytes is used for magic number */
#define MAX_READ_SIZE 512
#define NV_MAC_OFFSET 128
#define NV_MAC_SIZE 20
static int is_env_setted(const char *env_name)
{
#ifdef U_BUILD_DEBUG
return 0;
#else
const char *env = env_get(env_name);
if(env && *env) {
return 1;
}
return 0;
#endif
}
static void update_sn(void)
{
struct blk_desc *dev_desc;
struct disk_partition part_info;
unsigned char buffer[MAX_READ_SIZE];
int ret;
ulong block_start;
ulong block_count;
ulong n;
size_t length;
unsigned int i;
ret = is_env_setted("serial#");
if (ret) {
printf("serial# has been setted,skip read from nv partition\n");
return;
}
/* Get mmc dev */
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (dev_desc == NULL) {
printf("Failed to find MMC device\n");
goto err_exit;
}
/* Get the nv partition infomation */
ret = part_get_info_by_name(dev_desc, NV_PARTITION_NAME, &part_info);
if (ret < 0) {
printf("Failed to find '%s' partition\n", NV_PARTITION_NAME);
goto err_exit;
}
/* Read the first MAX_READ_SIZE from NV partition data */
block_start = part_info.start;
block_count = (MAX_READ_SIZE + dev_desc->blksz - 1) / dev_desc->blksz;
n = blk_dread(dev_desc, block_start, block_count, buffer);
if (n != block_count) {
printf("Failed to read data from '%s' partition\n", NV_PARTITION_NAME);
goto err_exit;
}
/* Check the length of SN data */
length = strnlen((char *)buffer, MAX_READ_SIZE);
if ((length > MAX_SN_SIZE)) {
printf("The size of SN data(%zu) is out of range \r\n", length);
goto err_exit;
}
/* Check the magic number of NV */
i = 0;
if ((buffer[i++] != 'N') || (buffer[i++] != 'V')) {
printf("The magic number of NV partition is invalid\r\n");
goto err_exit;
}
/* Check the value of the SN data; the SN value should consist of printable characters*/
for (; i < length; i++) {
if ((buffer[i] < 33) || (buffer[i] > 126)) {
printf("Unprintable character detected[0x%x] @%d \r\n", buffer[i], i);
goto err_exit;
}
}
/* The first two bytes are used for NV magic number */
env_set("serial#", (char *)buffer + 2);
printf("Success to read SN value, update SN: %s to env serial# \r\n", buffer + 2);
ret = run_command("env save",0);
if(ret != 0) {
printf("Failed to update SN to env\r\n");
}
return;
err_exit:
printf("Failed to read the SN value; Using the default value instead\r\n");
return;
}
static void update_mac(void)
{
struct blk_desc *dev_desc;
struct disk_partition part_info;
unsigned char buffer[MAX_READ_SIZE];
int ret;
ulong block_start;
ulong block_count;
ulong n;
size_t length;
unsigned int i;
ret = is_env_setted("ethaddr");
if (ret) {
printf("ethaddr has been setted,skip read from nv partition\n");
return;
}
/* Get mmc dev */
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (dev_desc == NULL) {
printf("Failed to find MMC device\n");
goto err_exit;
}
/* Get the nv partition infomation */
ret = part_get_info_by_name(dev_desc, NV_PARTITION_NAME, &part_info);
if (ret < 0) {
printf("Failed to find '%s' partition\n", NV_PARTITION_NAME);
goto err_exit;
}
/* Read the first MAX_READ_SIZE from NV partition data */
block_start = part_info.start;
block_count = (MAX_READ_SIZE + dev_desc->blksz - 1) / dev_desc->blksz;
n = blk_dread(dev_desc, block_start, block_count, buffer);
if (n != block_count) {
printf("Failed to read data from '%s' partition\n", NV_PARTITION_NAME);
goto err_exit;
}
/* Check the length of MAC data */
length = strnlen((char *)buffer + NV_MAC_OFFSET, MAX_READ_SIZE);
if (length != NV_MAC_SIZE) {
printf("The size of MAC data(%zu) is out of range\r\n", length);
goto err_exit;
}
/* Check the magic number of MAC */
i = 0;
if ((buffer[NV_MAC_OFFSET + i++] != 'M') || (buffer[NV_MAC_OFFSET + i++] != 'A') || (buffer[NV_MAC_OFFSET + i++] != 'C')) {
printf("The magic number of NV partition is invalid\r\n");
goto err_exit;
}
/* Check the value of the MAC data; the MAC value should consist of printable characters*/
for (; i < length; i++) {
if ((buffer[NV_MAC_OFFSET + i] < 33) || (buffer[i + NV_MAC_OFFSET] > 126)) {
printf("Unprintable character detected\r\n");
goto err_exit;
}
}
/* The first two bytes are used for MAC magic number */
env_set("ethaddr", (char *)buffer + 3 + NV_MAC_OFFSET);
printf("Success to read MAC value, update MAC: %s to env ethaddr \r\n", buffer + 3 + NV_MAC_OFFSET);
return;
err_exit:
printf("Failed to read the MAC value; Using the default value instead\r\n");
return;
}
#else
static void update_sn(void)
{
}
static void update_mac(void)
{
}
#endif
/*******************************************************************************
* function: danica_ioreuse_inital
*
@@ -1413,7 +1605,7 @@ static void light_iopin_init(void)
light_pin_cfg(GMAC0_RXD2, PIN_SPEED_NORMAL, PIN_PN, 0xF);
light_pin_cfg(GMAC0_RXD3, PIN_SPEED_NORMAL, PIN_PN, 0xF);
}
#elif defined (CONFIG_TARGET_LIGHT_FM_C910_LPI4A)
#elif defined (CONFIG_TARGET_LIGHT_FM_C910_LPI4A) || defined(CONFIG_TARGET_LIGHT_FM_C910_RVBOOK)
static void light_iopin_init(void)
{
/* aon-padmux config */
@@ -1426,7 +1618,10 @@ static void light_iopin_init(void)
light_pin_cfg(CPU_JTG_TMS, PIN_SPEED_NORMAL, PIN_PN, 2);
light_pin_mux(CPU_JTG_TDI, 3);
light_pin_cfg(CPU_JTG_TDI, PIN_SPEED_NORMAL, PIN_PN, 2);
#ifdef CONFIG_RV_BOOK
light_pin_mux(CPU_JTG_TRST, 3);
light_pin_cfg(CPU_JTG_TRST, PIN_SPEED_NORMAL, PIN_PN, 2);
#endif
light_pin_mux(AOGPIO_7, 1);
light_pin_mux(AOGPIO_8, 1);
// light_pin_mux(AOGPIO_9, 0);
@@ -1472,7 +1667,6 @@ static void light_iopin_init(void)
light_pin_cfg(AUDIO_PA29, PIN_SPEED_NORMAL, PIN_PN, 2);
light_pin_mux(AUDIO_PA30, 0);
light_pin_cfg(AUDIO_PA30, PIN_SPEED_NORMAL, PIN_PN, 2);
#warning "aon set to 3"
light_pin_mux(AUDIO_PA30, 3);
// light_pin_mux(AUDIO_PA9,3); ///AUDIO-PA-RESET
@@ -1912,19 +2106,30 @@ static void light_usb_boot_check(void)
run_command("fastboot usb 0", 0);
}
int board_late_init(void)
{
light_usb_boot_check();
#if CONFIG_IS_ENABLED(LIGHT_SEC_UPGRADE)
extern void sec_upgrade_thread(void);
extern void nonsec_upgrade_thread(void);
extern void sec_firmware_version_dump(void);
sec_upgrade_thread();
nonsec_upgrade_thread();
sec_firmware_version_dump();
#endif
light_usb_boot_check();
ap_peri_clk_disable();
#ifdef CONFIG_MCU_HC32fX
mcu_poweron();
#endif
#ifdef CONFIG_DM_CHARGE_DISPLAY
charge_display();
#endif
update_sn();
update_mac();
return 0;
}
@@ -1971,6 +2176,32 @@ static inline int fdt_disabled_node(void *blob,const char *path)
return fdt_status_disabled(blob,offset);
}
/*First check if path1 exist, if not, alternate to path2*/
static inline int fdt_disabled_node_alt(void *blob,const char *path1, const char *path2)
{
int offset;
offset = fdt_path_offset(blob,path1);
if (offset < 0) {
offset = fdt_path_offset(blob,path2);
if(offset < 0)
{
printf("ERROR:failed to find %s node or %s node in dtb (ret %d)\n",path1,path2,offset);
return offset;
}
}
return fdt_status_disabled(blob,offset);
}
/*First check if alias name *fisrt exist, if not, alternate to alias name *alt*/
static inline int fdt_status_disabled_by_alias_alt(void *blob,const char *fisrt,const char* alt)
{
int ret;
ret = fdt_status_disabled_by_alias(blob,fisrt);
if(ret < 0)
ret = fdt_status_disabled_by_alias(blob,alt);
return ret;
}
static int do_board_check_hibernate(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
@@ -1979,15 +2210,25 @@ static int do_board_check_hibernate(cmd_tbl_t *cmdtp, int flag, int argc,
ulong addr;
void *blob = NULL;
ulong mask = 0;
int mmc_parts;
int resume_part;
bool fastresume = 0;
#define ON_RET_ERROR(str) if(ret < 0) printf("set node %s status failed %d\n",str,ret)
ALLOC_CACHE_ALIGN_BUFFER(u8,swsusp_header_buf,PAGE_SIZE);
u8 *header = &swsusp_header_buf[0];
struct blk_desc *dev_desc;
struct disk_partition part_info;
mmc_parts = env_get_hex("mmcpart",3);
resume_part = mmc_parts - 2;
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (dev_desc == NULL) {
printf("Failed to find MMC device\n");
return CMD_RET_FAILURE;
}
resume_part = part_get_info_by_name(dev_desc, "swap", &part_info);
if (resume_part < 0) {
printf("Failed to find swap partition\n");
return CMD_RET_FAILURE;
}
if(argc >= 4) { // is user pass in ,use that
sprintf(runcmd, "read %s %s %s 0 8",
@@ -2057,10 +2298,10 @@ static int do_board_check_hibernate(cmd_tbl_t *cmdtp, int flag, int argc,
ret = fdt_status_disabled_by_alias(blob,"i2c2");
ON_RET_ERROR("i2c2");
ret = fdt_status_disabled_by_alias(blob,"audio_i2c0");
ON_RET_ERROR("audio_i2c0");
ret = fdt_status_disabled_by_alias(blob,"audio_i2c1");
ON_RET_ERROR("audio_i2c1");
ret = fdt_status_disabled_by_alias_alt(blob,"audio_i2c0","i2c5");
ON_RET_ERROR("audio_i2c0 or i2c5");
ret = fdt_status_disabled_by_alias_alt(blob,"audio_i2c1","i2c6");
ON_RET_ERROR("audio_i2c1 or i2c6");
ret = fdt_status_disabled_by_alias(blob,"ethernet0");
ON_RET_ERROR("ethernet0");
ret = fdt_status_disabled_by_alias(blob,"ethernet1");
@@ -2077,24 +2318,24 @@ static int do_board_check_hibernate(cmd_tbl_t *cmdtp, int flag, int argc,
//default mask is 0, need set this node disbaled
if(0 == (mask & 0x01)) {
ret = fdt_disabled_node(blob,"/soc/light_i2s");
ON_RET_ERROR("/soc/light_i2s");
ret = fdt_disabled_node(blob,"/soc/audio_i2s0");
ON_RET_ERROR("/soc/audio_i2s0");
ret = fdt_disabled_node(blob,"/soc/audio_i2s1");
ON_RET_ERROR("/soc/audio_i2s1");
ret = fdt_disabled_node(blob,"/soc/audio_i2s2");
ON_RET_ERROR("/soc/audio_i2s2");
ret = fdt_disabled_node_alt(blob,"/soc/light_i2s","/soc/ap-i2s");
ON_RET_ERROR("/soc/light_i2s or /soc/ap-i2s");
ret = fdt_disabled_node_alt(blob,"/soc/audio_i2s0","/soc/audio-i2s0");
ON_RET_ERROR("/soc/audio_i2s0 or /soc/audio-i2s0");
ret = fdt_disabled_node_alt(blob,"/soc/audio_i2s1","/soc/audio-i2s1");
ON_RET_ERROR("/soc/audio_i2s1 or /soc/audio-i2s1");
ret = fdt_disabled_node_alt(blob,"/soc/audio_i2s2","/soc/audio-i2s2");
ON_RET_ERROR("/soc/audio_i2s2 or /soc/audio-i2s2");
}
if(0 == (mask & 0x02)) {
ret = fdt_disabled_node(blob,"/soc/audio_i2s_8ch_sd0");
ON_RET_ERROR("/soc/audio_i2s_8ch_sd0");
ret = fdt_disabled_node(blob,"/soc/audio_i2s_8ch_sd1");
ON_RET_ERROR("/soc/audio_i2s_8ch_sd1");
ret = fdt_disabled_node(blob,"/soc/audio_i2s_8ch_sd2");
ON_RET_ERROR("/soc/audio_i2s_8ch_sd2");
ret = fdt_disabled_node(blob,"/soc/audio_i2s_8ch_sd3");
ON_RET_ERROR("/soc/audio_i2s_8ch_sd3");
ret = fdt_disabled_node_alt(blob,"/soc/audio_i2s_8ch_sd0","/soc/i2s-8ch-sd0");
ON_RET_ERROR("/soc/audio_i2s_8ch_sd0 or /soc/i2s-8ch-sd0");
ret = fdt_disabled_node_alt(blob,"/soc/audio_i2s_8ch_sd1","/soc/i2s-8ch-sd1");
ON_RET_ERROR("/soc/audio_i2s_8ch_sd1 or /soc/i2s-8ch-sd1");
ret = fdt_disabled_node_alt(blob,"/soc/audio_i2s_8ch_sd2","/soc/i2s-8ch-sd2");
ON_RET_ERROR("/soc/audio_i2s_8ch_sd2 or /soc/i2s-8ch-sd2");
ret = fdt_disabled_node_alt(blob,"/soc/audio_i2s_8ch_sd3","/soc/i2s-8ch-sd3");
ON_RET_ERROR("/soc/audio_i2s_8ch_sd3 or /soc/i2s-8ch-sd3");
}
/*set resume_bootargs for kernel do fast bootup */
sprintf(runcmd,"resume=/dev/mmcblk0p%d notrace noftrace nopty noclkdebug ",resume_part);

View File

@@ -136,7 +136,7 @@ static const struct regulator_t g_apcpu_regu_id_list[] = {
REGU_ID_DEF(IIC_IDX_AONIIC,APCPU_REGU_VDDM,0x31,0x39,0,1,800000,600000,3500000,12500,1),
},
};
#elif defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_A_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_REF) || (CONFIG_TARGET_LIGHT_FM_C910_BEAGLE) || defined (CONFIG_TARGET_LIGHT_FM_C910_LPI4A)
#elif defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_A_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_REF) || (CONFIG_TARGET_LIGHT_FM_C910_BEAGLE) || defined (CONFIG_TARGET_LIGHT_FM_C910_LPI4A) || defined(CONFIG_TARGET_LIGHT_FM_C910_RVBOOK)
/**
* board for ant-ref
*
@@ -955,7 +955,7 @@ int pmic_reset_apcpu_voltage(void)
return ret;
return 0;
}
#elif defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_A_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_REF)|| (CONFIG_TARGET_LIGHT_FM_C910_BEAGLE) || defined (CONFIG_TARGET_LIGHT_FM_C910_LPI4A)
#elif defined (CONFIG_TARGET_LIGHT_FM_C910_VAL_ANT_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_A_REF) || defined (CONFIG_TARGET_LIGHT_FM_C910_B_REF)|| (CONFIG_TARGET_LIGHT_FM_C910_BEAGLE) || defined (CONFIG_TARGET_LIGHT_FM_C910_LPI4A) || defined(CONFIG_TARGET_LIGHT_FM_C910_RVBOOK)
int pmic_reset_apcpu_voltage(void)
{
int ret = -1;

View File

@@ -28,8 +28,11 @@ typedef enum {
typedef struct Ddr_Reg_Config {
uint32_t misc_reg_num;
uint32_t phy_reg_num;
uint8_t ddr_rank;
uint8_t reserve[55];
} Ddr_Reg_Config_t;
int dwc_ddrphy_phyinit_regInterface(regInstr myRegInstr);
void dwc_ddr_misc_regu_save(void);
#endif

View File

@@ -994,7 +994,7 @@ if(bits==64) {
}
}
#define MEMSIZE_MIN_MB (2*1024)
#define MEMSIZE_MIN_MB (1*1024)
#define MEMSIZE_MAX_MB (16*1024)
#define UNIT_MB (1024*1024)
int lpddr4_query_boundary(enum DDR_TYPE type, int rank_num, int speed,
@@ -1007,35 +1007,29 @@ int lpddr4_query_boundary(enum DDR_TYPE type, int rank_num, int speed,
if (bits == DDR_BITWIDTH_32) {// only phy0
if (rank_num == 2) {
if (size == 0x80000000) //2GB
goto err_ret;
goto ret_ok;
else if (size == 0x100000000) //4GB
goto ret_ok;
else if (size == 0x200000000) //8GB
goto ret_ok;
else if (size == 0x400000000) //16GB
goto err_ret;
else
goto err_ret;
}
else { // single rank
if (size == 0x80000000) //2GB
if (size == 0x40000000) //1GB
goto ret_ok;
else if (size == 0x80000000) //2GB
goto ret_ok;
else if (size == 0x100000000) //4GB
goto err_ret;
else if (size == 0x200000000) //8GB
goto err_ret;
else if (size == 0x400000000) //16GB
goto err_ret;
goto ret_ok;
else
goto err_ret;
}
}
else if (bits == DDR_BITWIDTH_64) { // phy0+phy1
if (rank_num == 2) {
if (size == 0x80000000) //2GB
goto err_ret;
else if (size == 0x100000000) //4GB
goto err_ret;
if (size == 0x100000000) //4GB
goto ret_ok;
else if (size == 0x200000000) //8GB
goto ret_ok;
else if (size == 0x400000000) //16GB
@@ -1045,13 +1039,11 @@ int lpddr4_query_boundary(enum DDR_TYPE type, int rank_num, int speed,
}
else { // single rank
if (size == 0x80000000) //2GB
goto err_ret;
goto ret_ok;
else if (size == 0x100000000) //4GB
goto ret_ok;
else if (size == 0x200000000) //8GB
goto err_ret;
else if (size == 0x400000000) //16GB
goto err_ret;
goto ret_ok;
else
goto err_ret;
}
@@ -1075,36 +1067,70 @@ int adjust_ddr_addrmap(enum DDR_TYPE type, int rank_num, int speed,
if (bits == DDR_BITWIDTH_32) {// only phy0
if (rank_num == 2) {
if (size == 0x100000000) {//4GB
if (size == 0x80000000) {//2GB
wr(ADDRMAP0,0x001f0016); // cs_bit0: HIF[28]
wr(ADDRMAP6,0x0f070707); // row15: NULL
wr(ADDRMAP7,0x00000f0f); // row16: NULL
}
else if (size == 0x100000000) {//4GB
wr(ADDRMAP0,0x001f0017); // cs_bit0: HIF[29]
wr(ADDRMAP6,0x07070707); // row15: HIF[28]
wr(ADDRMAP7,0x00000f0f); // row16: NULL
}
else if (size == 0x200000000) {//8GB
wr(ADDRMAP0,0x001f0018); // cs_bit0: HIF[30]
wr(ADDRMAP6,0x07070707); // row15: HIF[28]
wr(ADDRMAP7,0x00000f07); // row16: HIF[29]
}
}
else { // single rank
if (size == 0x80000000) //2GB
wr(ADDRMAP0,0x001f001f); // cs_bit0: NULL
wr(ADDRMAP0,0x001f001f); // cs_bit0: NULL
if (size == 0x40000000) {//1GB
wr(ADDRMAP6,0x0f070707); // row15: NULL
wr(ADDRMAP7,0x00000f0f); // row16: NULL
}
else if (size == 0x80000000) {//2GB
wr(ADDRMAP6,0x07070707); // row15: HIF[28]
wr(ADDRMAP7,0x00000f0f); // row16: NULL
}
else if (size == 0x100000000) {//4GB
wr(ADDRMAP6,0x07070707); // row15: HIF[28]
wr(ADDRMAP7,0x00000f07); // row16: HIF[29]
}
}
}
else if (bits == DDR_BITWIDTH_64) { // phy0+phy1
if (rank_num == 2) {
if (size == 0x200000000) {//8GB
if (size == 0x100000000) {//4GB
wr(ADDRMAP0,0x00040017); // cs_bit0: HIF[29]
wr(ADDRMAP6,0x0f080808); // row15: NULL
wr(ADDRMAP7,0x00000f0f); // row16: NULL
}
else if (size == 0x200000000) {//8GB
wr(ADDRMAP0,0x00040018); // cs_bit0: HIF[30]
wr(ADDRMAP6,0x08080808); // row15: HIF[29]
wr(ADDRMAP7,0x00000f0f); // row16: NULL
}
else if (size == 0x400000000) {//16GB
wr(ADDRMAP0,0x00040019); // cs_bit0: HIF[31]
wr(ADDRMAP6,0x08080808); // row15: HIF[29]
wr(ADDRMAP7,0x00000f08); // row16: HIF[30]
}
}
else { // single rank
if (size == 0x100000000) {//4GB
wr(ADDRMAP0,0x0004001f); // cs_bit0: NULL
wr(ADDRMAP0,0x0004001f); // cs_bit0: NULL
if (size == 0x80000000) {//2GB
wr(ADDRMAP6,0x0f080808); // row15: NULL
wr(ADDRMAP7,0x00000f0f); // row16: NULL
}
else if (size == 0x100000000) {//4GB
wr(ADDRMAP6,0x08080808); // row15: HIF[29]
wr(ADDRMAP7,0x00000f0f); // row16: NULL
}
else if (size == 0x200000000) {//8GB
wr(ADDRMAP6,0x08080808); // row15: HIF[29]
wr(ADDRMAP7,0x00000f08); // row16: HIF[30]
}
}
}
else {

View File

@@ -988,9 +988,8 @@ static const uint32_t RetRegList_addr[934] =
0x13840,
};
void dwc_ddr_misc_regu_save()
void dwc_ddr_misc_regu_save(void)
{
uint32_t data = 0;
ddr_Regu_Config->misc_reg_num = ARRAY_SIZE(MiscRegList);
Reg_Misc_Addr_Val_t* misc_addr_t = (Reg_Misc_Addr_Val_t*)((char*)ddr_Regu_Config + 64);
for(int i = 0; i < ddr_Regu_Config->misc_reg_num; i++) {
@@ -1010,6 +1009,11 @@ int dwc_ddrphy_phyinit_regInterface(regInstr myRegInstr) {
uint32_t phy_reg_num = ARRAY_SIZE(RetRegList_addr);
ddr_Regu_Config->phy_reg_num = phy_reg_num;
#ifdef CONFIG_DDR_DUAL_RANK
ddr_Regu_Config->ddr_rank = 2;
#else
ddr_Regu_Config->ddr_rank = 1;
#endif
Reg_Phy_Addr_Val_t* phy_addr_t = (Reg_Phy_Addr_Val_t*)((char*)ddr_Regu_Config + 64 + sizeof(Reg_Misc_Addr_Val_t) * ARRAY_SIZE(MiscRegList));
#ifdef CONFIG_DDR_MSG

View File

@@ -29,7 +29,7 @@
#define DMSG(fmt, args...) trace_printer("", fmt, ##args)
#endif
#if CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_B) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A)
#if CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_B) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_RVBOOK)
#if CONFIG_IS_ENABLED(LIGHT_SEC_UPGRADE)
/* digest_size corresponding to digest_scheme specified in sbmeta_info_t */
static const int digest_size[] = {0, 20, 16, 28, 32, 48, 64, 32};
@@ -62,7 +62,8 @@ typedef struct {
char filename[MAX_NAME_SIZE];
uint8_t digest[MAX_DIGEST_SIZE];
uint32_t relocated_addr;
uint32_t reserved[4];
uint8_t security_level;
uint8_t reserved[15];
} sbmeta_info_t;
static int is_sbmeta_info(uint32_t entry_src_addr)
@@ -107,6 +108,11 @@ static int dump_sbmeta_info(sbmeta_info_t *sbmeta_info)
IMSG("Image has been loaded\r\n");
}
if (sbmeta_info->security_level > SBMETA_SECURITY_LEVEL_SIGN || sbmeta_info->security_level < SBMETA_SECURITY_LEVEL_NONE) {
EMSG("security level is invalid\n");
return CMD_RET_FAILURE;
}
/* dump sbmeta_info_t */
DMSG("image medium type: %d\n", sbmeta_info->medium_type);
DMSG("image load part: mmc %d:%d\n", sbmeta_info->dev, sbmeta_info->part);
@@ -136,6 +142,10 @@ static int sbmeta_field_verify(sbmeta_info_t *sbmeta_info, unsigned long img_src
return CMD_RET_FAILURE;
}
if (sbmeta_info->security_level < SBMETA_SECURITY_LEVEL_SIGN) {
return 0;
}
/* if image has secure header, check with sbmeta field */
if (image_have_head(img_src_addr)) {
phead = (img_header_t *)img_src_addr;
@@ -221,7 +231,7 @@ static int sbmeta_verify_image(uint32_t image_load_addr, sbmeta_info_t *sbmeta_i
uint8_t checksum_scheme = sbmeta_info->checksum_scheme;
uint8_t *digest = sbmeta_info->digest;
uint8_t is_encrypted = sbmeta_info->isencrypted;
uint32_t security_level = env_get_hex("sbmeta_security_level", 3);
uint32_t security_level = sbmeta_info->security_level;
uint32_t filesize = 0;
char buf[64] = {0};
@@ -253,11 +263,11 @@ static int sbmeta_verify_image(uint32_t image_load_addr, sbmeta_info_t *sbmeta_i
/* start verifying images */
IMSG("Process %s image verification ...\n", image_name);
if (security_level == 3 || is_encrypted != 0) {
if (security_level == SBMETA_SECURITY_LEVEL_SIGN || is_encrypted != 0) {
if (verify_customer_image(image_type, image_load_addr) != 0) {
return CMD_RET_FAILURE;
}
} else if (security_level == 2) {
} else if (security_level == SBMETA_SECURITY_LEVEL_HASH) {
if (memcmp(digest, buf, 64) == 0) {
EMSG("sbmeta info doesn't specify digest value in security level 2\r\n");
return CMD_RET_FAILURE;
@@ -309,7 +319,8 @@ static int light_sbmetaboot(int argc, char *const argv[])
sbmeta_info_t *sbmeta_info = NULL;
/* Load sbmeta image to memory */
snprintf(cmd, sizeof(cmd), "ext4load mmc $mmcdev:%x 0x%p %s", SBMETA_PART, (void *)(uintptr_t)LIGHT_SBMETA_ADDR, SBMETA_FILENAME);
snprintf(cmd, sizeof(cmd), "ext4load mmc ${mmcdev}:${mmcsbmetapart} 0x%x %s", (void *)(uintptr_t)LIGHT_SBMETA_ADDR, SBMETA_FILENAME);
printf("%s\n",cmd);
if (run_command(cmd, 0) != 0) {
/* if sbmeta doesn't exist, do secboot by default */
IMSG("SBMETA doesn't exist, go to verify tf/tee\r\n");
@@ -324,7 +335,6 @@ static int light_sbmetaboot(int argc, char *const argv[])
return 0;
}
/* initialize crypto algorithm interfaces */
if (csi_sec_init() != 0) {
return CMD_RET_FAILURE;

View File

@@ -14,10 +14,9 @@
#define MAX_DIGEST_SIZE 64
#define SBMETA_MAGIC 0x544D4253 /* = {'S', 'B', 'M', 'T'} */
#if CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_B) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A)
#if CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_B) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_RVBOOK)
#define LIGHT_SBMETA_ADDR 0x10000000
#endif
#define SBMETA_PART 5
#define ENTRY_SIZE 128
#define PLAIN_SBMETA_TEXT 4096
#define SBMETA_SIZE 4736 /* 4K SMBETA image + 640 footer */
@@ -27,8 +26,8 @@
#define SIGN_TYPE_NUM 6
#define SBMETA_FILENAME "sbmeta.bin"
#define SBMETA_SECURITY_LEVEL_H 3 /* verify signature and hash */
#define SBMETA_SECURITY_LEVEL_M 2 /* verify checksum */
#define SBMETA_SECURITY_LEVEL_L 1 /* no verification */
#define SBMETA_SECURITY_LEVEL_SIGN 3 /* verify signature and hash */
#define SBMETA_SECURITY_LEVEL_HASH 2 /* verify checksum */
#define SBMETA_SECURITY_LEVEL_NONE 1 /* no verification */
#endif

View File

@@ -75,7 +75,7 @@ void designware_get_mac_from_fuse(unsigned char *mac)
}
}
#if CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_B) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_ANT_REF) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A)
#if CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_B) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_ANT_REF) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_RVBOOK)
/* Secure function for image verificaiton here */
int get_image_version(unsigned long img_src_addr)
{

View File

@@ -377,7 +377,6 @@ int boundary_verify(unsigned long boundary) {
int setup_ddr_addrmap(void)
{
int ret;
unsigned long boundary = (unsigned long)MAXIMAL_DDR_DENSITY_MB * UNIT_MB;
// verify data accessing result firstly
@@ -421,13 +420,14 @@ void cpu_performance_enable(void)
#define CSR_MHINT2_E 0x7cc
#define CSR_MHINT4 0x7ce
csr_write(CSR_SMPEN, 0x1);
csr_write(CSR_MCCR2, 0xe2490009);
csr_write(CSR_MXSTATUS, 0x638000);
csr_write(CSR_MHINT, 0x6e30c | (1<<21) | (1<<22)); // set bit21 & bit 22 to close tlb & fence broadcast
// FIXME: Clear bit[12] to disable L0BTB.
csr_write(CSR_MHCR, 0x17f); // clear bit7 to disable indirect brantch prediction
// FIXME set mhint2[22] to enable core icg en
csr_write(CSR_MHINT2_E, csr_read(CSR_MHINT2_E) | 0x420000);
csr_write(CSR_MHINT4, csr_read(CSR_MHINT4) | 0x410);
csr_write(CSR_MCCR2, 0xe2490009);
// FIXME: Clear bit[12] to disable L0BTB.
csr_write(CSR_MHCR, 0x17f); // clear bit7 to disable indirect brantch prediction
csr_write(CSR_MHINT, 0x6e30c | (1<<21) | (1<<22)); // set bit21 & bit 22 to close tlb & fence broadcast
}
static int bl1_img_have_head(unsigned long img_src_addr)
@@ -508,7 +508,11 @@ void board_init_f(ulong dummy)
}
#endif
ddr_clk_config(0);
#ifdef CONFIG_RV_BOOK
cpu_clk_config(750000000);
#else
cpu_clk_config(0);
#endif
init_ddr();
setup_ddr_scramble();

View File

@@ -20,12 +20,106 @@
#define LIGHT_APSYS_RSTGEN_ADDRBASE 0xffff015000
#define LIGHT_DPU_CLOCK_GATING_CTRL0 0xffef601A28
#define LIGHT_DPU_CLOCK_GATING_CTRL1 0xffef601A2C
#ifdef CONFIG_RV_BOOK
#define LIGHT_CPU_PLL_IDX(x) (x)
#endif
void show_sys_clk(void)
{
/* Do nothing for FPGA */
}
#ifdef CONFIG_RV_BOOK
static int _light_get_pllid(void)
{
unsigned int val;
int ret;
val = readl((void *)LIGHT_APCLK_ADDRBASE + 0x100);
if(val & 0x1)
ret = LIGHT_CPU_PLL_IDX(1);
else
ret = LIGHT_CPU_PLL_IDX(0);
return ret;
}
void update_cpu_freq(uint32_t val)
{
if(_light_get_pllid() == LIGHT_CPU_PLL_IDX(0))
{
/* update cpupll1*/
writel(0x20000000, (void *)LIGHT_APCLK_ADDRBASE + 0x14);
writel(val, (void *)LIGHT_APCLK_ADDRBASE + 0x10);
writel(0x23000000, (void *)LIGHT_APCLK_ADDRBASE + 0x14);
udelay(3);
writel(0x03000000, (void *)LIGHT_APCLK_ADDRBASE + 0x14);
readl((void *)LIGHT_APCLK_ADDRBASE + 0x80);
readl((void *)LIGHT_APCLK_ADDRBASE + 0x80);
while(!(readl((void *)LIGHT_APCLK_ADDRBASE + 0x80) & 0x10));
udelay(11);
}else{
/* update cpupll0*/
writel(0x20000000, (void *)LIGHT_APCLK_ADDRBASE + 0x04);
writel(val, (void *)LIGHT_APCLK_ADDRBASE + 0x00);
writel(0x23000000, (void *)LIGHT_APCLK_ADDRBASE + 0x04);
udelay(3);
writel(0x03000000, (void *)LIGHT_APCLK_ADDRBASE + 0x04);
readl((void *)LIGHT_APCLK_ADDRBASE + 0x80);
readl((void *)LIGHT_APCLK_ADDRBASE + 0x80);
while(!(readl((void *)LIGHT_APCLK_ADDRBASE + 0x80) & 0x02));
udelay(11);
}
}
void cpu_clk_config(int32_t cpu_freq)
{
#ifndef CONFIG_TARGET_LIGHT_FPGA_FM_C910 /* for sillicon */
unsigned int tmp;
switch(cpu_freq){
case 750000000:
{
/* 4. update c910_cclk to 750Mhz */
update_cpu_freq(0x1407d01);
/* config bus: cpu clk ratio to 1:1 */
writel((readl((const volatile void __iomem *)(LIGHT_APCLK_ADDRBASE + 0x100)) & (~(0x7<<8))) | (0x0<<8), (void *)(LIGHT_APCLK_ADDRBASE + 0x100)); // ratio=0
writel(readl((const volatile void __iomem *)(LIGHT_APCLK_ADDRBASE + 0x100)) & (~(0x1<<11)), (void *)(LIGHT_APCLK_ADDRBASE + 0x100)); // sync=0
writel(readl((const volatile void __iomem *)(LIGHT_APCLK_ADDRBASE + 0x100)) | (0x1<<11), (void *)(LIGHT_APCLK_ADDRBASE + 0x100)); // sync=1
printf("cpu frequency to 750\n");
}
break;
case 1500000000:
{
/* 4. update c910_cclk to 1.5Ghz */
update_cpu_freq(0x01207d01);
/* config bus: cpu clk ratio to 1:2 */
writel((readl((const volatile void __iomem *)(LIGHT_APCLK_ADDRBASE + 0x100)) & (~(0x7<<8))) | (0x1<<8), (void *)(LIGHT_APCLK_ADDRBASE + 0x100)); // ratio=0
writel(readl((const volatile void __iomem *)(LIGHT_APCLK_ADDRBASE + 0x100)) & (~(0x1<<11)), (void *)(LIGHT_APCLK_ADDRBASE + 0x100)); // sync=0
writel(readl((const volatile void __iomem *)(LIGHT_APCLK_ADDRBASE + 0x100)) | (0x1<<11), (void *)(LIGHT_APCLK_ADDRBASE + 0x100)); // sync=1
printf("cpu frequency to 1500\n");
}
break;
default:
return;
}
if(_light_get_pllid() == LIGHT_CPU_PLL_IDX(0))
{
/* switch c910_cclk to cpu_pll1_foutpostdiv */
tmp = readl((void *)LIGHT_APCLK_ADDRBASE + 0x100);
tmp |= 0x1;
writel(tmp, (void *)LIGHT_APCLK_ADDRBASE + 0x100);
}else
{
/* switch c910_cclk to cpu_pll0_foutpostdiv */
tmp = readl((void *)LIGHT_APCLK_ADDRBASE + 0x100);
tmp &= ~0x1;
writel(tmp, (void *)LIGHT_APCLK_ADDRBASE + 0x100);
}
udelay(1);
#endif
}
#else
void cpu_clk_config(uint32_t cpu_freq)
{
#ifndef CONFIG_TARGET_LIGHT_FPGA_FM_C910 /* for sillicon */
@@ -54,6 +148,7 @@ void cpu_clk_config(uint32_t cpu_freq)
udelay(1);
#endif
}
#endif
void sys_clk_config(void)
{
@@ -336,6 +431,24 @@ void sys_clk_config(void)
#endif
}
#ifndef CONFIG_SPL_BUILD
static int cpu_switch_freq(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
cpu_clk_config(1500000000);
return 0;
}
U_BOOT_CMD(
cpufreq_switch,
2,
0,
cpu_switch_freq,
"switch cpu freq to highest",
""
);
#endif
void ddr_clk_config(int ddr_freq)
{
/* Do nothing for FPGA */

View File

@@ -137,6 +137,7 @@ obj-$(CONFIG_CMD_TPM) += tpm-common.o
obj-$(CONFIG_CMD_TPM_V1) += tpm-v1.o
obj-$(CONFIG_CMD_TPM_TEST) += tpm_test.o
obj-$(CONFIG_CMD_TPM_V2) += tpm-v2.o
obj-$(CONFIG_CMD_MEASURED_BOOT) += mboot.o
obj-$(CONFIG_CMD_CROS_EC) += cros_ec.o
obj-$(CONFIG_CMD_TSI148) += tsi148.o
obj-$(CONFIG_CMD_UBI) += ubi.o

View File

@@ -237,9 +237,15 @@ static int prepare_data_from_vendor_boot(struct andr_img_hdr *hdr, int dtb_start
if (ramdisk_entry->ramdisk_type != VENDOR_RAMDISK_TYPE_RECOVERY) {
continue;
}
printf("find recovery from ramdisk table.");
printf("find recovery from ramdisk table.\n");
int ramdisk_start = env_get_hex(ENV_RAMDISK_ADDR, DEFAULT_RAMDISK_ADDR);
int recovery_ramdisk_offset = vendor_boot_pagesize * o + ramdisk_entry->ramdisk_offset;
printf("ramdisk_start:%x, ramdisk_size:%x, dtb_start:%x\n", ramdisk_start, ramdisk_entry->ramdisk_size, dtb_start);
if (ramdisk_start + ramdisk_entry->ramdisk_size > dtb_start) {
printf("ramdisk space are overlaped !!!\n");
}
memcpy((void *)(uint64_t)ramdisk_start, vendor_boot_data + recovery_ramdisk_offset,
ramdisk_entry->ramdisk_size);//ramdisk
//get bootconfig form vendor_boot.img and append bootconfig to ramdisk
@@ -292,10 +298,10 @@ static void prepare_loaded_parttion_data(const uint8_t* data, bool isRecovery)
printf("Boot image kernel_start:%x, kernel_offset:%x, kernel_size:%d\n", kernel_start, kernel_offset, hdr->kernel_size);
printf("Boot image ramdisk_start:%x, ramdisk_offset:%x, ramdisk_size:%d\n", ramdisk_start, ramdisk_offset, hdr->ramdisk_size);
printf("Boot image page_size:%d\n", hdr->page_size);
printf("dtb_offset:%x, dtb_size:%d\n", dtb_offset, hdr->dtb_size);
printf("dtb_start:%x, dtb_offset:%x, dtb_size:%d\n", dtb_start, dtb_offset, hdr->dtb_size);
if (kernel_start + hdr->kernel_size > ramdisk_start || kernel_start + hdr->kernel_size > dtb_start) {
printf("boot.img kernel space and ramdis space are overlaped !!!\n");
if (kernel_start + hdr->kernel_size > ramdisk_start || kernel_start + hdr->kernel_size > dtb_start || ramdisk_start + hdr->ramdisk_size > dtb_start) {
printf("boot.img kernel space and ramdisk space are overlaped !!!\n");
} else {
memcpy((void *)(uint64_t)kernel_start, data + kernel_offset, hdr->kernel_size);
if (!isRecovery) {

View File

@@ -118,7 +118,7 @@ U_BOOT_CMD(
#endif
#if CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_B) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_ANT_REF) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A)
#if CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_VAL_B) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_ANT_REF) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A) || CONFIG_IS_ENABLED(LIGHT_SEC_BOOT_WITH_VERIFY_RVBOOK)
#if CONFIG_IS_ENABLED(LIGHT_SEC_UPGRADE)
extern int light_secboot(int argc, char * const argv[]);
#endif
@@ -137,6 +137,91 @@ U_BOOT_CMD(
"vimage addr imgname[[tee/tf] - verify specifed image resides in addr\n"
);
/* check whether partition numbers are consistent with the slot suffix */
static int do_light_bootab(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
char *slot_suffix = env_get("slot_suffix");
int teepart = env_get_hex("mmcteepart", 3);
struct disk_partition part_info;
struct blk_desc *dev_desc;
int part = 0;
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (dev_desc == NULL) {
printf("Failed to find MMC device\n");
return 1;
}
if ((strcmp(slot_suffix, "a") == 0) && (teepart != 3)) {
part = part_get_info_by_name(dev_desc, "boot_a", &part_info);
if (part < 0) {
printf("Failed to find MMC device\n");
return 1;
}
env_set_hex("mmcbootpart", part);
part = part_get_info_by_name(dev_desc, "tee_a", &part_info);
if (part < 0) {
printf("Failed to find MMC device\n");
return 1;
}
env_set_hex("mmcteepart", part);
part = part_get_info_by_name(dev_desc, "sbmeta_a", &part_info);
if (part < 0) {
printf("Failed to find MMC device\n");
return 1;
}
env_set_hex("mmcsbmetapart", part);
part = part_get_info_by_name(dev_desc, "root_a", &part_info);
if (part < 0) {
printf("root AB partition is not enabled\n");
} else {
env_set_hex("mmcpart", part);
}
run_command("env save", 0);
} else if ((strcmp(slot_suffix, "b") == 0) && (teepart != 10)) {
part = part_get_info_by_name(dev_desc, "boot_b", &part_info);
if (part < 0) {
printf("Failed to find MMC device\n");
return 1;
}
env_set_hex("mmcbootpart", part);
part = part_get_info_by_name(dev_desc, "tee_b", &part_info);
if (part < 0) {
printf("Failed to find MMC device\n");
return 1;
}
env_set_hex("mmcteepart", part);
part = part_get_info_by_name(dev_desc, "sbmeta_b", &part_info);
if (part < 0) {
printf("Failed to find MMC device\n");
return 1;
}
env_set_hex("mmcsbmetapart", part);
part = part_get_info_by_name(dev_desc, "root_b", &part_info);
if (part < 0) {
printf("root AB partition is not enabled\n");
} else {
env_set_hex("mmcpart", part);
}
run_command("env save", 0);
}
printf("current active slot is:%s\n", slot_suffix);
return CMD_RET_SUCCESS;
}
U_BOOT_CMD(
light_bootab, CONFIG_SYS_MAXARGS, 1, do_light_bootab,
"Light A/B updates",
NULL
);
#endif
#endif

122
cmd/mboot.c Normal file
View File

@@ -0,0 +1,122 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2018 Bootlin
* Author: Miquel Raynal <miquel.raynal@bootlin.com>
*/
#include <common.h>
#include <dm.h>
#include <log.h>
#include <mapmem.h>
#include <tpm-common.h>
#include <tpm-v2.h>
#include <env.h>
#include <env_internal.h>
#include "tpm-user-utils.h"
#include "sec_library.h"
enum mboot_type {
UBOOT_IMAGE = 0,
KERNEL_IMAGE,
PARTITIONS_STR,
MBOOT_TYPE_MAX,
};
enum pcr_index {
PCR_0 = 0,
PCR_1,
PCR_2,
PCR_3,
PCR_4,
PCR_5,
PCR_6,
PCR_7,
};
static uint8_t image_digest[32] __attribute__((aligned(64))) = { 0 };
#define CHECK_RET_WITH_RET(x, ret) \
do { \
if (!(x)) { \
return ret; \
} \
} while (0)
static uint32_t hash_image_sha256(long image_addr, size_t size, void *digest, uint32_t *digest_len)
{
uint32_t ret;
sc_sha_t sha;
sc_sha_context_t ctx;
CHECK_RET_WITH_RET(ret = csi_sec_library_init(), ret);
CHECK_RET_WITH_RET(ret = sc_sha_init(&sha, 0), ret);
CHECK_RET_WITH_RET(ret = sc_sha_start(&sha, &ctx, SC_SHA_MODE_256), ret);
CHECK_RET_WITH_RET(ret = sc_sha_trans_config(&sha, &ctx, SC_SHA_DMA_MODE), ret);
CHECK_RET_WITH_RET(ret = sc_sha_update(&sha, &ctx, (void *)image_addr, size), ret);
CHECK_RET_WITH_RET(ret = sc_sha_finish(&sha, &ctx, digest, digest_len), ret);
return SC_OK;
}
static int do_measured_boot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct udevice *dev;
struct tpm_chip_priv *priv;
uint32_t index, type;
uint32_t rc;
int ret;
long image_addr = 0;
size_t image_size = 0;
uint32_t image_digest_len = 0;
char *partitions_str = NULL;
if (argc != 1)
return CMD_RET_USAGE;
ret = get_tpm(&dev);
if (ret)
return ret;
tpm_init(dev); /* Initialization TPM2 chip */
rc = tpm2_startup(dev, TPM2_SU_CLEAR); /* Startup TPM2 chip with mode TPM_ST_CLEAR*/
if (rc)
report_return_code(rc);
priv = dev_get_uclass_priv(dev);
if (!priv)
return -EINVAL;
for (type = UBOOT_IMAGE; type < MBOOT_TYPE_MAX; type++) {
if (type == UBOOT_IMAGE) { /*U-BOOT Image */
index = PCR_0;
image_addr = CONFIG_SPL_TEXT_BASE;
image_size = CONFIG_SPL_MAX_SIZE+CONFIG_SYS_MONITOR_LEN;
} else if (type == KERNEL_IMAGE) { /* KERNEL Image */
index = PCR_0;
image_addr = 0x00200000;
if (fs_set_blk_dev("mmc", "0:2", 2))
return -EINVAL;
if (fs_size("Image", &image_size) < 0)
return -EINVAL;
} else if (type == PARTITIONS_STR) { /* PARTITIONS */
index = PCR_5;
partitions_str = env_get("partitions");
image_addr = (long)partitions_str;
image_size = strlen(partitions_str);
}
rc = hash_image_sha256(image_addr, image_size, image_digest, &image_digest_len);
if (rc)
return -EINVAL;
rc = tpm2_pcr_extend(dev, index, image_digest);
if (rc)
break;
}
return report_return_code(rc);
}
U_BOOT_CMD(
measured_boot, CONFIG_SYS_MAXARGS, 1, do_measured_boot,
"extend hash(u-boot), hash(kernel), hash(partitions str) to pcr0 and pcr5",
""
);

View File

@@ -25,6 +25,7 @@ CONFIG_FIXUP_MEMORY_REGION=y
# CONFIG_CMD_TPM_V2 is not set
# CONFIG_CMD_TPM is not set
# CONFIG_CMD_TPM_TEST is not set
# CONFIG_CMD_MEASURED_BOOT is not set
CONFIG_CMD_BOOT_SLAVE=y
CONFIG_CMD_ERASEENV=y
CONFIG_CMD_GPT=y
@@ -114,3 +115,5 @@ CONFIG_DDR_REGU_0V8=800000
CONFIG_DDR_REGU_1V1=1100000
CONFIG_MISC=y
CONFIG_LIGHT_AON_CONF=y
# CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION is not set
# CONFIG_FASTBOOT_ECIES_AUTH is not set

View File

@@ -107,3 +107,5 @@ CONFIG_DDR_REGU_0V8=800000
CONFIG_DDR_REGU_1V1=1100000
CONFIG_MISC=y
CONFIG_LIGHT_AON_CONF=y
# CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION is not set
# CONFIG_FASTBOOT_ECIES_AUTH is not set

View File

@@ -19,7 +19,7 @@ CONFIG_SYS_PROMPT="C910 Light# "
CONFIG_DDR_LP4X_3733_DUALRANK=y
# CONFIG_DDR_LP4_3733_DUALRANK is not set
CONFIG_DDR_BOARD_CONFIG=y
CONFIG_FIXUP_MEMORY_REGION=n
CONFIG_FIXUP_MEMORY_REGION=y
CONFIG_CMD_BOOT_SLAVE=y
CONFIG_CMD_ERASEENV=y
CONFIG_CMD_GPT=y
@@ -93,7 +93,7 @@ CONFIG_CMD_BMP=y
CONFIG_VIDEO_BRIDGE=y
CONFIG_DM_PCA953X=y
CONFIG_VIDEO_VS_DPU=y
CONFIG_VIDEO_LCD_ILITEK_ILI9881C=y
CONFIG_VIDEO_LCD_JD9365DA=y
CONFIG_VIDEO_DW_DSI_LIGHT=y
CONFIG_VIDEO_DW_DPHY=y
CONFIG_VIDEO_DW_DSI_HOST=y

View File

@@ -113,3 +113,5 @@ CONFIG_DDR_REGU_0V8=800000
CONFIG_DDR_REGU_1V1=1100000
CONFIG_MISC=y
CONFIG_LIGHT_AON_CONF=y
# CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION is not set
# CONFIG_FASTBOOT_ECIES_AUTH is not set

View File

@@ -0,0 +1,130 @@
CONFIG_RV_BOOK=y
CONFIG_RISCV=y
CONFIG_SPL_MMC_SUPPORT=y
CONFIG_ENV_SIZE=0x20000
CONFIG_ENV_OFFSET=0xe0000
CONFIG_NR_DRAM_BANKS=8
CONFIG_SPL=y
CONFIG_SMP=y
CONFIG_TARGET_LIGHT_C910=y
CONFIG_TARGET_LIGHT_FM_C910_RVBOOK=y
# CONFIG_THEAD_PLIC is not set
# CONFIG_THEAD_LIGHT_TIMER is not set
# CONFIG_THEAD_LIGHT_DIGITAL_SENSOR is not set
CONFIG_ARCH_RV64I=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_BUILD_TARGET="u-boot-with-spl.bin"
CONFIG_DISPLAY_CPUINFO=y
CONFIG_DISPLAY_BOARDINFO=y
# CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set
CONFIG_SPL_RAM_SUPPORT=y
CONFIG_SPL_RAM_DEVICE=y
CONFIG_SYS_PROMPT="C910 Light# "
CONFIG_DDR_LP4X_3733_DUALRANK=y
# CONFIG_DDR_LP4_3733_DUALRANK is not set
CONFIG_DDR_BOARD_CONFIG=y
CONFIG_FIXUP_MEMORY_REGION=y
CONFIG_CMD_BOOT_SLAVE=y
CONFIG_CMD_ERASEENV=y
CONFIG_CMD_GPT=y
CONFIG_CMD_MTD=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_SPI=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MEMTEST=y
CONFIG_DDR_SCAN=y
CONFIG_DDR_PRBS_TEST=n
# CONFIG_DOS_PARTITION is not set
# CONFIG_ISO_PARTITION is not set
CONFIG_PARTITION_TYPE_GUID=y
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="th1520-rvbook"
CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SPL_CLK=y
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_UDP_FUNCTION_FASTBOOT=y
CONFIG_FASTBOOT_BUF_ADDR=0x10000000
CONFIG_FASTBOOT_FLASH=y
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
CONFIG_DM_GPIO=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_DW=y
CONFIG_DWAPB_GPIO=y
# CONFIG_MMC_SPI is not set
CONFIG_MMC_VERBOSE=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_IO_VOLTAGE=y
CONFIG_MMC_UHS_SUPPORT=y
CONFIG_MMC_HS400_SUPPORT=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_SNPS=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SNPS=y
CONFIG_MMC_SDHCI_SDMA=y
CONFIG_CMD_MMC=y
CONFIG_CMD_MMC_RPMB=y
CONFIG_SUPPORT_EMMC_RPMB=y
CONFIG_DM_MTD=y
CONFIG_MTD_SPI_NAND=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_ETH_DESIGNWARE=y
CONFIG_PHY_REALTEK=y
CONFIG_RTL8211E_PINE64_GIGABIT_FIX=y
CONFIG_RTL8211X_PHY_FORCE_MASTER=y
CONFIG_RTL8211F_PHY_FORCE_EEE_RXC_ON=y
CONFIG_SYS_NS16550=y
CONFIG_SPI=y
CONFIG_DESIGNWARE_SPI=y
CONFIG_DESIGNWARE_QSPI=y
CONFIG_USB=y
CONFIG_USB_DWC3=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="U-Boot-THEAD"
CONFIG_USB_GADGET_VENDOR_NUM=0x1234
CONFIG_USB_GADGET_PRODUCT_NUM=0x8888
# CONFIG_SPL_USE_TINY_PRINTF is not set
# CONFIG_EFI_LOADER is not set
# CONFIG_LIGHT_SEC_BOOT is not set
CONFIG_BOARD_LATE_INIT=y
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_DM_VIDEO=y
CONFIG_PHY=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
CONFIG_CMD_BMP=y
CONFIG_VIDEO_BRIDGE=y
CONFIG_DM_PCA953X=y
CONFIG_VIDEO_VS_DPU=y
CONFIG_VIDEO_LCD_ILITEK_ILI9881C=y
CONFIG_VIDEO_LCD_CUSTOM_LOGO=y
CONFIG_VIDEO_DW_DSI_LIGHT=y
CONFIG_VIDEO_DW_DPHY=y
CONFIG_VIDEO_DW_DSI_HOST=y
CONFIG_SYS_WHITE_ON_BLACK=y
CONFIG_PMIC_VOL_INIT=y
CONFIG_DDR_REGU_0V6=600000
CONFIG_DDR_REGU_0V8=800000
CONFIG_DDR_REGU_1V1=1100000
CONFIG_TPM=y
CONFIG_TPM_V2=y
CONFIG_TPM_Z32H330TC_SPI=y
CONFIG_CMD_TPM=y
CONFIG_CMD_TPM_V2=y
CONFIG_CMD_TPM_TEST=y
CONFIG_DM_CHARGE_DISPLAY=y
CONFIG_CHARGE_ANIMATION=y
CONFIG_DM_FUEL_GAUGE=y
CONFIG_POWER_FG_CW201X=y
CONFIG_CHARGER_BQ25700=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_DM_MCU=y
CONFIG_MCU_HC32fX=y
CONFIG_DM_POWER_DELIVERY=y
CONFIG_TYPEC_TCPM=y
CONFIG_TYPEC_TCPCI=y
CONFIG_TYPEC_HUSB311=y
CONFIG_MISC=y
CONFIG_LIGHT_AON_CONF=y

View File

@@ -0,0 +1,132 @@
CONFIG_RV_BOOK=y
CONFIG_RISCV=y
CONFIG_SPL_MMC_SUPPORT=y
CONFIG_ENV_SIZE=0x20000
CONFIG_ENV_OFFSET=0xe0000
CONFIG_NR_DRAM_BANKS=8
CONFIG_SPL=y
CONFIG_SMP=y
CONFIG_TARGET_LIGHT_C910=y
# CONFIG_THEAD_PLIC is not set
# CONFIG_THEAD_LIGHT_TIMER is not set
# CONFIG_THEAD_LIGHT_DIGITAL_SENSOR is not set
CONFIG_ARCH_RV64I=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_BUILD_TARGET="u-boot-with-spl.bin"
CONFIG_DISPLAY_CPUINFO=y
CONFIG_DISPLAY_BOARDINFO=y
# CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set
CONFIG_SPL_RAM_SUPPORT=y
CONFIG_SPL_RAM_DEVICE=y
CONFIG_SYS_PROMPT="C910 Light# "
CONFIG_DDR_LP4X_3733_DUALRANK=y
# CONFIG_DDR_LP4_3733_DUALRANK is not set
CONFIG_DDR_BOARD_CONFIG=y
CONFIG_FIXUP_MEMORY_REGION=y
CONFIG_CMD_BOOT_SLAVE=y
CONFIG_CMD_ERASEENV=y
CONFIG_CMD_GPT=y
CONFIG_CMD_MTD=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_SPI=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MEMTEST=y
CONFIG_DDR_SCAN=y
CONFIG_DDR_PRBS_TEST=n
# CONFIG_DOS_PARTITION is not set
# CONFIG_ISO_PARTITION is not set
CONFIG_PARTITION_TYPE_GUID=y
CONFIG_OF_EMBED=y
CONFIG_DEFAULT_DEVICE_TREE="th1520-rvbook"
CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SPL_CLK=y
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_UDP_FUNCTION_FASTBOOT=y
CONFIG_FASTBOOT_BUF_ADDR=0x10000000
CONFIG_FASTBOOT_FLASH=y
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
CONFIG_DM_GPIO=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_DW=y
CONFIG_DWAPB_GPIO=y
# CONFIG_MMC_SPI is not set
CONFIG_MMC_VERBOSE=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_IO_VOLTAGE=y
CONFIG_MMC_UHS_SUPPORT=y
CONFIG_MMC_HS400_SUPPORT=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_SNPS=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SNPS=y
CONFIG_MMC_SDHCI_SDMA=y
CONFIG_CMD_MMC=y
CONFIG_CMD_MMC_RPMB=y
CONFIG_SUPPORT_EMMC_RPMB=y
CONFIG_DM_MTD=y
CONFIG_MTD_SPI_NAND=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_ETH_DESIGNWARE=y
CONFIG_PHY_REALTEK=y
CONFIG_RTL8211E_PINE64_GIGABIT_FIX=y
CONFIG_RTL8211X_PHY_FORCE_MASTER=y
CONFIG_RTL8211F_PHY_FORCE_EEE_RXC_ON=y
CONFIG_SYS_NS16550=y
CONFIG_SPI=y
CONFIG_DESIGNWARE_SPI=y
CONFIG_DESIGNWARE_QSPI=y
CONFIG_USB=y
CONFIG_USB_DWC3=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="U-Boot-THEAD"
CONFIG_USB_GADGET_VENDOR_NUM=0x1234
CONFIG_USB_GADGET_PRODUCT_NUM=0x8888
# CONFIG_SPL_USE_TINY_PRINTF is not set
# CONFIG_EFI_LOADER is not set
CONFIG_LIGHT_SEC_BOOT_WITH_VERIFY_RVBOOK=y
CONFIG_LIGHT_SEC_UPGRADE=y
CONFIG_BOARD_LATE_INIT=y
CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
CONFIG_DM_VIDEO=y
CONFIG_PHY=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
CONFIG_CMD_BMP=y
CONFIG_VIDEO_BRIDGE=y
CONFIG_DM_PCA953X=y
CONFIG_VIDEO_VS_DPU=y
CONFIG_VIDEO_LCD_ILITEK_ILI9881C=y
CONFIG_VIDEO_LCD_CUSTOM_LOGO=y
CONFIG_VIDEO_DW_DSI_LIGHT=y
CONFIG_VIDEO_DW_DPHY=y
CONFIG_VIDEO_DW_DSI_HOST=y
CONFIG_SYS_WHITE_ON_BLACK=y
CONFIG_PMIC_VOL_INIT=y
CONFIG_DDR_REGU_0V6=600000
CONFIG_DDR_REGU_0V8=800000
CONFIG_DDR_REGU_1V1=1100000
CONFIG_TPM=y
CONFIG_TPM_V2=y
CONFIG_TPM_Z32H330TC_SPI=y
CONFIG_CMD_TPM=y
CONFIG_CMD_TPM_V2=y
CONFIG_CMD_TPM_TEST=y
CONFIG_DM_CHARGE_DISPLAY=y
CONFIG_CHARGE_ANIMATION=y
CONFIG_DM_FUEL_GAUGE=y
CONFIG_POWER_FG_CW201X=y
CONFIG_CHARGER_BQ25700=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_DM_MCU=y
CONFIG_MCU_HC32fX=y
CONFIG_DM_POWER_DELIVERY=y
CONFIG_TYPEC_TCPM=y
CONFIG_TYPEC_TCPCI=y
CONFIG_TYPEC_HUSB311=y
CONFIG_MISC=y
CONFIG_LIGHT_AON_CONF=y
CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION=y

View File

@@ -130,6 +130,8 @@ source "drivers/w1-eeprom/Kconfig"
source "drivers/watchdog/Kconfig"
source "drivers/mcu/Kconfig"
config PHYS_TO_BUS
bool "Custom physical to bus address mapping"
help

View File

@@ -85,6 +85,9 @@ obj-y += misc/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_NVME) += nvme/
obj-$(CONFIG_PCI_ENDPOINT) += pci_endpoint/
ifdef CONFIG_RV_BOOK
obj-$(CONFIG_DM_POWER_DELIVERY) += power/power_delivery/
endif
obj-y += dfu/
obj-$(CONFIG_PCH) += pch/
obj-y += phy/allwinner/

View File

@@ -135,6 +135,14 @@ config FASTBOOT_CMD_OEM_FORMAT
relies on the env variable partitions to contain the list of
partitions as required by the gpt command.
config FASTBOOT_CMD_OEM_NV_OPERATION
bool "Enable the 'oem nv get/set' command"
help
Add support for the "oem get/set" command from a client.
config FASTBOOT_ECIES_AUTH
bool "Enabled ecies fastboot auth"
endif # FASTBOOT
endmenu

View File

@@ -3,5 +3,7 @@
obj-y += fb_common.o
obj-y += fb_getvar.o
obj-y += fb_command.o
obj-$(CONFIG_FASTBOOT_ECIES_AUTH) += fb_ecies.o
obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_mmc.o
obj-$(CONFIG_FASTBOOT_FLASH_NAND) += fb_nand.o
obj-$(CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION) += fb_nv_operation.o

View File

@@ -45,6 +45,19 @@ static void oem_format(char *, char *);
static void oem_command(char *, char *);
int image_have_head(unsigned long img_src_addr);
#if CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION
void oem_nv_get_proccess(char *cmd_parameter, char *response);
void oem_nv_set_proccess(char *cmd_parameter, char *response);
void oem_nv_factory_recovery_process(char *cmd_parameter, char *response);
static void oem_nv_get(char *cmd_parameter, char *response);
static void oem_nv_set(char *cmd_parameter, char *response);
static void oem_fcty(char *cmd_parameter, char *response);
#endif
#ifdef CONFIG_FASTBOOT_ECIES_AUTH
int ecies_process_data(uint8_t * data, int data_size,char *response);
#endif
static const struct {
const char *command;
void (*dispatch)(char *cmd_parameter, char *response);
@@ -97,6 +110,20 @@ static const struct {
.command = "oem command",
.dispatch = oem_command,
},
#if CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION
[FASTBOOT_COMMAND_OEM_NV_GET] = {
.command = "oem nv get",
.dispatch = oem_nv_get,
},
[FASTBOOT_COMMAND_OEM_NV_SET] = {
.command = "oem nv set",
.dispatch = oem_nv_set,
},
[FASTBOOT_COMMAND_OEM_FCTY] = {
.command = "oem fcty",
.dispatch = oem_fcty,
},
#endif
};
/**
@@ -294,7 +321,90 @@ int check_image_board_id(uint8_t *image_data)
return 0;
}
int hibernate_image_cleaned_flag = 0;
void clean_hibernate_image_header(char *response)
{
struct blk_desc *dev_desc;
disk_partition_t info;
if(0x03 == hibernate_image_cleaned_flag) //already erased all
{
return;
}
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
fastboot_fail("invalid mmc device", response);
return;
}
char * buf = memalign(CONFIG_SYS_CACHELINE_SIZE,4096);
if(!buf) {
printf(" mem alloc for hibernate partition header failed!\n");
return;
}
/* if fastresume partition exists, earse the old image header */
if(part_get_info_by_name(dev_desc, "fastresume", &info)) {
printf(" find fastresume partition , erase the header:\n");
memset(buf,0xff,4096);
if(blk_dwrite(dev_desc, info.start, 4096/info.blksz, buf) != 4096/info.blksz)
{
printf(" fastresume header write failed!\n");
hibernate_image_cleaned_flag = 0;
}
else
{
hibernate_image_cleaned_flag |= 0x1;
}
}
/* if swap partition exists, earse the old image header */
if(part_get_info_by_name(dev_desc, "swap", &info)) {
printf(" find swap partition , erase the header:\n");
memset(buf,0xff,4096);
if(blk_dwrite(dev_desc, info.start, 4096/info.blksz, buf) != 4096/info.blksz)
{
printf(" swap header write failed!\n");
hibernate_image_cleaned_flag = 0;
}
else
{
hibernate_image_cleaned_flag |= 0x2;
}
}
free(buf);
}
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
void fasboot_uboot_write_process(void *buf, char *response)
{
char cmdbuf[32];
u32 block_cnt;
struct blk_desc *dev_desc;
int ret = 0;
disk_partition_t info;
ret = check_image_board_id(buf);
if (ret != 0) {
fastboot_fail("U-BOOT image does not match the type of BOARD", response);
return;
}
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
fastboot_fail("invalid mmc device", response);
return;
}
run_command("mmc partconf 0 1 0 1", 0);
block_cnt = image_size / BLOCK_SIZE;
if (image_size % BLOCK_SIZE) {
block_cnt = block_cnt +1;
}
sprintf(cmdbuf, "mmc write 0x%p 0 %x", buf, block_cnt);
run_command(cmdbuf, 0);
run_command("mmc partconf 0 1 0 0", 0);
}
/**
* flash() - write the downloaded image to the indicated partition.
*
@@ -308,36 +418,10 @@ static void flash(char *cmd_parameter, char *response)
{
#ifdef THEAD_LIGHT_FASTBOOT
char cmdbuf[32];
u32 block_cnt;
struct blk_desc *dev_desc;
disk_partition_t info;
int ret = 0;
if (strcmp(cmd_parameter, "uboot") == 0) {
ret = check_image_board_id(fastboot_buf_addr);
if (ret != 0) {
fastboot_fail("U-BOOT image does not match the type of BOARD", response);
return;
}
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
fastboot_fail("invalid mmc device", response);
return;
}
run_command("mmc partconf 0 1 0 1", 0);
block_cnt = image_size / BLOCK_SIZE;
if (image_size % BLOCK_SIZE) {
block_cnt = block_cnt +1;
}
sprintf(cmdbuf, "mmc write 0x%p 0 %x", fastboot_buf_addr, block_cnt);
run_command(cmdbuf, 0);
run_command("mmc partconf 0 1 0 0", 0);
fasboot_uboot_write_process(fastboot_buf_addr, response);
} else if ((strcmp(cmd_parameter, "fw") == 0)) {
memcpy((void *)LIGHT_FW_ADDR, fastboot_buf_addr, image_size);
} else if ((strcmp(cmd_parameter, "uImage") == 0)) {
@@ -352,13 +436,15 @@ static void flash(char *cmd_parameter, char *response)
memcpy((void *)LIGHT_TF_FW_ADDR, fastboot_buf_addr, image_size);
} else if ((strcmp(cmd_parameter, TEE_PART_NAME) == 0)) {
memcpy((void *)LIGHT_TEE_FW_ADDR, fastboot_buf_addr, image_size);
} else if ((strcmp(cmd_parameter, "boot") == 0)) {
}
#ifdef CONFIG_RV_BOOK
else if ((strcmp(cmd_parameter, "boot") == 0)) {
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
fastboot_fail("invalid mmc device", response);
return;
}
/* if fastresume partition exists, earse the old image header */
fastboot_fail("invalid mmc device", response);
return;
}
/* if fastresume partition exists, earse the old image header */
if(part_get_info_by_name(dev_desc, "fastresume", &info)) {
printf(" find fastresume partition , erase the header:\n");
char * buf = memalign(CONFIG_SYS_CACHELINE_SIZE,4096);
@@ -371,6 +457,22 @@ static void flash(char *cmd_parameter, char *response)
free(buf);
}
}
#endif
#ifdef CONFIG_FASTBOOT_ECIES_AUTH
else if ((strcmp(cmd_parameter, "ecies") == 0)) {
ecies_process_data(fastboot_buf_addr, image_size,response);
return;
}
#endif
//If version is updated, hibernate image may not compatible with current,erase it.
if ((strcmp(cmd_parameter, "boot") == 0)
|| (strcmp(cmd_parameter, "uboot") == 0)
|| (strcmp(cmd_parameter, "root") == 0)) {
clean_hibernate_image_header(response);
}
if(strcmp(cmd_parameter, "uboot") == 0 || (strcmp(cmd_parameter, "fw") == 0) ||
(strcmp(cmd_parameter, "uImage") == 0) || (strcmp(cmd_parameter, "dtb") == 0) ||
(strcmp(cmd_parameter, "rootfs") == 0) || (strcmp(cmd_parameter, "aon") == 0)) {
@@ -380,54 +482,7 @@ static void flash(char *cmd_parameter, char *response)
#endif
#if CONFIG_IS_ENABLED(LIGHT_SEC_UPGRADE)
if(strcmp(cmd_parameter, TF_IMG_UPD_NAME) == 0) {
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
/* tee/tf/uboot image must be written into stash partition */
sprintf(cmdbuf, "%s", STASH_PART_NAME);
fastboot_mmc_flash_write(cmdbuf, fastboot_buf_addr, image_size, response);
#endif
/* Send ACK to host */
fastboot_okay(NULL, response);
/* set secure upgrade flag to indicate it is TF image upgrade*/
sprintf(cmdbuf,"env set sec_upgrade_mode 0x%x", TF_SEC_UPGRADE_FLAG);
run_command(cmdbuf, 0);
run_command("saveenv", 0);
run_command("reset", 0);
return;
} else if (strcmp(cmd_parameter, TEE_IMG_UPD_NAME) == 0) {
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
/* tee/tf/uboot image must be written into stash partition */
sprintf(cmdbuf, "%s", STASH_PART_NAME);
fastboot_mmc_flash_write(cmdbuf, fastboot_buf_addr, image_size, response);
#endif
/* Send ACK to host */
fastboot_okay(NULL, response);
/* set secure upgrade flag to indicate it is TEE image upgrade*/
sprintf(cmdbuf,"env set sec_upgrade_mode 0x%x", TEE_SEC_UPGRADE_FLAG);
run_command(cmdbuf, 0);
run_command("saveenv", 0);
run_command("reset", 0);
return;
} else if (strcmp(cmd_parameter, SBMETA_IMG_UPD_NAME) == 0) {
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
/* tee/tf/uboot image must be written into stash partition */
sprintf(cmdbuf, "%s", STASH_PART_NAME);
fastboot_mmc_flash_write(cmdbuf, fastboot_buf_addr, image_size, response);
#endif
/* Send ACK to host */
fastboot_okay(NULL, response);
/* set secure upgrade flag to indicate it is TEE image upgrade*/
sprintf(cmdbuf,"env set sec_upgrade_mode 0x%x", SBMETA_SEC_UPGRADE_FLAG);
run_command(cmdbuf, 0);
run_command("saveenv", 0);
run_command("reset", 0);
return;
} else if (strcmp(cmd_parameter, UBOOT_IMG_UPD_NAME) == 0) {
if (strcmp(cmd_parameter, UBOOT_IMG_UPD_NAME) == 0) {
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
env_set_hex("ubootupdsize", image_size);
@@ -530,3 +585,38 @@ static void oem_command(char *cmd_parameter, char *response)
else
fastboot_okay(NULL, response);
}
#if CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION
/**
* oem_nv_get() - Execute the OEM NV GET command
*
* @cmd_parameter: Pointer to command parameter
* @response: Pointer to fastboot response buffer
*/
static void oem_nv_get(char *cmd_parameter, char *response)
{
oem_nv_get_proccess(cmd_parameter,response);
}
/**
* oem_nv_set() - Execute the OEM NV Set command
*
* @cmd_parameter: Pointer to command parameter
* @response: Pointer to fastboot response buffer
*/
static void oem_nv_set(char *cmd_parameter, char *response)
{
oem_nv_set_proccess(cmd_parameter,response);
}
/**
* oem_fcty() - Execute the OEM fcty command
*
* @cmd_parameter: Pointer to command parameter
* @response: Pointer to fastboot response buffer
*/
static void oem_fcty(char *cmd_parameter, char *response)
{
oem_nv_factory_recovery_process(cmd_parameter,response);
}
#endif

198
drivers/fastboot/fb_ecies.c Normal file
View File

@@ -0,0 +1,198 @@
#include <sec_ecies_session.h>
#include <common.h>
#include <command.h>
#include <env.h>
#include <fastboot.h>
#include <fastboot-internal.h>
#include <fb_mmc.h>
#include <fb_nand.h>
#include <part.h>
#include <stdlib.h>
#include <csi_sec_img_verify.h>
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
extern void fasboot_uboot_write_process(void *buf, char *response);
#define MAX_ECIES_IMAGE_SIZE (9*1024*1024)
#define ECIES_MALLOC_START (MAX_ECIES_IMAGE_SIZE * 2)
typedef struct {
uint32_t magic;
uint32_t file_size;
char partition_name[64];
} __attribute__((__packed__)) send_file_info_t;
static uint32_t ecies_file_pos = 0;
static int slave_init = 0;
static int current_pos = 0;
void *csi_ecies_malloc(uint32_t size)
{
void * ptr = NULL;
if (current_pos + size >= CONFIG_FASTBOOT_BUF_SIZE) {
current_pos = 0;
}
ptr = (void *)(long)(CONFIG_FASTBOOT_BUF_ADDR + ECIES_MALLOC_START + current_pos);
current_pos += size;
return ptr;
};
void csi_ecies_free(void *buffer)
{
return;
};
static int ecies_data_write(uint8_t *buf,uint8_t *data,int data_len)
{
char response[FASTBOOT_RESPONSE_LEN];
if (data_len == 0 || buf == NULL || data == NULL) {
return -1;
}
memcpy(buf + ecies_file_pos,data,data_len);
ecies_file_pos += data_len;
if (ecies_file_pos == sizeof(send_file_info_t) + ((send_file_info_t *)buf)->file_size) {
if (strcmp(((send_file_info_t *)buf)->partition_name, TEE_PART_NAME) == 0) {
memcpy((void *)LIGHT_TEE_FW_ADDR, buf + sizeof(send_file_info_t), ((send_file_info_t *)buf)->file_size);
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
fastboot_mmc_flash_write(((send_file_info_t *)buf)->partition_name, buf + sizeof(send_file_info_t), ((send_file_info_t *)buf)->file_size,
response);
#endif
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
fastboot_nand_flash_write(((send_file_info_t *)buf)->partition_name, buf + sizeof(send_file_info_t), ((send_file_info_t *)buf)->file_size,
response);
#endif
} else if (strcmp(((send_file_info_t *)buf)->partition_name, UBOOT_PART_NAME) == 0) {
fasboot_uboot_write_process(buf + sizeof(send_file_info_t),response);
} else {
printf("unknown partition name\n");
return -2;
}
ecies_file_pos = 0;
} else if(ecies_file_pos > sizeof(send_file_info_t) + ((send_file_info_t *)buf)->file_size) {
return -3;
}
return 0;
}
static void hex_to_str(char *dest, const uint8_t *src, int len)
{
char ddl = 0;
char ddh = 0;
int i = 0;
for (i = 0; i < len; i++) {
ddh = 48 + src[i] / 16;
ddl = 48 + src[i] % 16;
if (ddh > 57) {
ddh = ddh + 7;
}
if (ddl > 57) {
ddl = ddl + 7;
}
dest[i * 2] = ddh;
dest[i * 2 + 1] = ddl;
}
dest[len * 2] = '\0';
}
int ecies_process_data(uint8_t * data, int data_size,char *response)
{
static ecies_session_t ss_slave;
char apduResponse[ECIES_INIT_RESPONSE_LEN] = {0};
uint8_t *plaintext = csi_ecies_malloc(MAX_ECIES_IMAGE_SIZE);
uint32_t plaintextLen = 0;
uint32_t apduResponseLen = 0;
int ret = 0;
uint8_t cla = 0;
uint8_t errcode = 0;
if (plaintext == NULL) {
ret = -1;
goto end;
}
if (!slave_init) {
csi_sec_library_init();
ret = hal_ecies_slave_init(&ss_slave);
if (ret != 0) {
strcpy(response,"hal_ecies_slave_init ERROR");
ret = -2;
goto end;
}
}
ret = hal_ecies_slave_session_comm(&ss_slave, data, data_size, (uint8_t *)apduResponse, &apduResponseLen, plaintext, &plaintextLen);
if (ret != 0) {
ret = hal_ecies_status_get((uint8_t *)apduResponse, apduResponseLen, &cla, &errcode);
if (ret != 0) {
strcpy(response,"hal_ecies_errcode_get ERROR");
ret = -3;
goto end;
}
if (cla == ECIES_CLA_INITIALIZE_UPDATE_RESPONSE && errcode == ECIES_RESPONSE_SESSION_OPENED_ERROR) {
slave_init = 0;
ecies_file_pos = 0;
hal_ecies_slave_uninit(&ss_slave);
ret = hal_ecies_slave_init(&ss_slave);
if (ret != 0) {
strcpy(response,"hal_ecies_slave_init ERROR");
ret = -4;
goto end;
}
ret = hal_ecies_slave_session_comm(&ss_slave, data, data_size, (uint8_t*)apduResponse, &apduResponseLen, plaintext, &plaintextLen);
if (ret != 0) {
strcpy(response,"hal_ecies_slave_session_comm ERROR");
ret = -5;
goto end;
}
} else if(errcode != ECIES_RESPONSE_OK) {
if (errcode == ECIES_CLA_SDATA_SEND_RESPONSE) {
strcpy(response,"ECIES_CLA_SDATA_SEND_RESPONSE ERROR");
ret = -6;
goto end;
} else if (errcode == ECIES_CLA_SESSION_CLOSE) {
strcpy(response,"ECIES_CLA_SESSION_CLOSE ERROR");
ret = -7;
goto end;
} else if (errcode == ECIES_CLA_INITIALIZE_UPDATE) {
strcpy(response,"ECIES_CLA_INITIALIZE_UPDATE ERROR");
ret = -8;
goto end;
}
}
}
if (slave_init && plaintextLen) {
ret = ecies_data_write((uint8_t*)(long)(CONFIG_FASTBOOT_BUF_ADDR + MAX_ECIES_IMAGE_SIZE),plaintext,plaintextLen);
if (ret != 0) {
strcpy(response,"ecies_data_write ERROR");
ret = -8;
goto end;
}
}
slave_init = 1;
strcpy(response,"SUCCESS:");
hex_to_str(response + strlen(response),(uint8_t*)apduResponse,apduResponseLen);
ret = 0;
end:
if (plaintext) {
csi_ecies_free(plaintext);
plaintext = NULL;
}
return ret;
}
#endif

View File

@@ -0,0 +1,342 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <common.h>
#include <fb_mmc.h>
#include <command.h>
#include <asm/io.h>
#include <asm/types.h>
#include <configs/light-c910.h>
#include <thead/clock_config.h>
#include <linux/bitops.h>
#include <asm/arch-thead/light-iopmp.h>
#include "../lib/sec_library/include/soc.h"
#define MAX_NV_NUMBER_SIZE 32
#define MAX_NV_DATA_SIZE 128
#define NV_BLOCK_SIZE 512
extern int32_t wj_efuse_get_lc(long unsigned int, int *lc);
typedef enum {
FB_SYS_ACTION_FACTORY_RECOVER,
FB_SYS_ACTION_READ_EFUSE,
} fb_sys_action_t;
static int nv_get(uint8_t *data,int offset,int data_len)
{
struct blk_desc *dev_desc;
struct disk_partition part_info;
ulong block_start;
uint8_t data_nv[NV_BLOCK_SIZE] = {0};
int ret;
int n;
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (dev_desc == NULL) {
return -1;
}
ret = part_get_info_by_name(dev_desc, NV_PARTITION_NAME, &part_info);
if (ret < 0) {
return -2;
}
if(NV_BLOCK_SIZE != dev_desc->blksz) {
return -4;
}
block_start = part_info.start + offset / dev_desc->blksz;
n = blk_dread(dev_desc, block_start, 1, data_nv);
if (n != 1) {
return -5;
}
memcpy(data,data_nv + offset % NV_BLOCK_SIZE,data_len);
return 0;
}
static int nv_set(uint8_t *data,int offset,int data_len)
{
struct blk_desc *dev_desc;
struct disk_partition part_info;
ulong block_start;
uint8_t data_nv[NV_BLOCK_SIZE] = {0};
int ret;
int n;
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (dev_desc == NULL) {
return -1;
}
ret = part_get_info_by_name(dev_desc, NV_PARTITION_NAME, &part_info);
if (ret < 0) {
return -2;
}
if (NV_BLOCK_SIZE != dev_desc->blksz) {
return -3;
}
block_start = part_info.start + offset / dev_desc->blksz;
n = blk_dread(dev_desc, block_start, 1, data_nv);
if (n != 1) {
return -4;
}
memcpy(data_nv + offset % NV_BLOCK_SIZE,data,data_len);
n = blk_dwrite(dev_desc, block_start, 1, data_nv);
if (n != 1) {
return -5;
}
return 0;
}
static int factory_recovery(char *response)
{
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
fastboot_mmc_erase("metadata", response);
if (strcmp(response, "OKAY") != 0) {
return -1;
}
fastboot_mmc_erase("misc", response);
if (strcmp(response, "OKAY") != 0) {
return -2;
}
#endif
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
fastboot_nand_erase("metadata", response);
if (strcmp(response, "OKAY") != 0) {
return -3;
}
fastboot_nand_erase("misc", response);
if (strcmp(response, "OKAY") != 0) {
return -4;
}
#endif
strcpy(response,"OKAY");
return 0;
}
static int read_efuse_status(char *response)
{
int ret;
int lc = 0;
ret = wj_efuse_get_lc(WJ_EFUSE_BASE, &lc);
if (ret) {
return -1;
}
if(lc == 0) {
strcpy(response,"LC_INIT");
} else {
strcpy(response,"LC_BLOWNED");
}
return 0;
}
static int sys_action(int flag,char *response)
{
if (flag == FB_SYS_ACTION_FACTORY_RECOVER) {
return factory_recovery(response);
} else if (flag == FB_SYS_ACTION_READ_EFUSE) {
return read_efuse_status(response);
} else {
return -1;
}
return 0;
}
static int toupper(int c)
{
if (c >= 'a' && c <= 'z') {
return c - 32;
}
return c;
}
static void str_to_hex(uint8_t *dest, const char *src, int len)
{
char h1, h2;
unsigned char s1, s2;
for (int i = 0; i < len; i++) {
h1 = src[2 * i];
h2 = src[2 * i + 1];
s1 = toupper(h1) - 48;
s2 = toupper(h2) - 48;
if (s1 > 9) {
s1 = s1 - 7;
}
if (s2 > 9) {
s2 = s2 - 7;
}
dest[i] = s1 * 16 + s2;
}
}
static void hex_to_str(char *dest, const uint8_t *src, int len)
{
char ddl = 0;
char ddh = 0;
int i = 0;
for (i = 0; i < len; i++) {
ddh = 48 + src[i] / 16;
ddl = 48 + src[i] % 16;
if (ddh > 57) {
ddh = ddh + 7;
}
if (ddl > 57) {
ddl = ddl + 7;
}
dest[i * 2] = ddh;
dest[i * 2 + 1] = ddl;
}
dest[len * 2] = '\0';
}
static int char_to_int(char *data,int *out)
{
*out = 0;
while(*data) {
if(*data < '0' || *data > '9')
return -1;
*out = *out * 10 + (*data - '0');
++data;
}
return 0;
}
#if CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION
void oem_nv_factory_recovery_process(char *cmd_parameter, char *response)
{
int ret = 0;
int flag = 0;
ret = char_to_int(cmd_parameter,&flag);
if (ret != 0) {
strcpy(response,"ERROR FLAG INVALID");
return;
}
ret = sys_action(flag,response);
if (ret != 0) {
strcpy(response,"ERROR SYS ACTION FAILED");
return;
}
}
void oem_nv_get_proccess(char *cmd_parameter, char *response)
{
char *sep = NULL;
char offset[MAX_NV_NUMBER_SIZE] = {0};
char len[MAX_NV_NUMBER_SIZE] = {0};
int sep_pos = 0;
uint8_t nv_data[MAX_NV_DATA_SIZE + 32] = {0};
char nv_data_str[MAX_NV_DATA_SIZE * 2 + 1] = {0};
int ret;
int offset_int = 0;
int len_int = 0;
sep = strstr(cmd_parameter, ":");
if (sep == NULL) {
strcpy(response,"ERROR INVALID PARAM");
return;
}
sep_pos = sep - cmd_parameter;
memcpy(offset,cmd_parameter,sep - cmd_parameter);
memcpy(len,cmd_parameter + (sep - cmd_parameter) + 1,strlen(cmd_parameter) - sep_pos - 1);
ret = char_to_int(offset,&offset_int);
if (ret != 0) {
strcpy(response,"ERROR OFFSET INVALID");
return;
}
ret = char_to_int(len,&len_int);
if (ret != 0) {
strcpy(response,"ERROR LEN INVALID");
return;
}
if (len_int > MAX_NV_DATA_SIZE) {
strcpy(response,"ERROR NV SIZE TOO LARGE");
return;
}
ret = nv_get(nv_data, offset_int, len_int);
if (ret != 0) {
printf("nv_get failed:%d\n",ret);
strcpy(response,"ERROR NV GET FAILED");
return;
}
hex_to_str(nv_data_str,nv_data,len_int);
strcpy(response,"SUCCESS:");
strcat(response,nv_data_str);
}
void oem_nv_set_proccess(char *cmd_parameter, char *response)
{
char *sep = NULL;
char offset[MAX_NV_NUMBER_SIZE] = {0};
uint8_t nv_data[MAX_NV_DATA_SIZE + 32] = {0};
char *nv_data_str;
int data_len;
int ret;
int offset_int = 0;
sep = strstr(cmd_parameter, ":");
if (sep == NULL) {
strcpy(response,"ERROR INVALID PARAM");
return;
}
memcpy(offset,cmd_parameter,sep - cmd_parameter);
nv_data_str = cmd_parameter + (sep - cmd_parameter) + 1;
data_len = strlen(nv_data_str) / 2;
ret = char_to_int(offset,&offset_int);
if (ret != 0) {
strcpy(response,"ERROR OFFSET INVALID");
return;
}
if (data_len > MAX_NV_DATA_SIZE) {
strcpy(response,"ERROR NV SIZE TOO LARGE");
return;
}
str_to_hex(nv_data,nv_data_str,data_len);
ret = nv_set(nv_data, offset_int, data_len);
if (ret != 0) {
strcpy(response,"ERROR NV SET FAILED");
return;
}
strcpy(response,"OKAY");
}
#endif

15
drivers/mcu/Kconfig Executable file
View File

@@ -0,0 +1,15 @@
menu "MCU Support"
config DM_MCU
bool "Enable driver model for mcu device support"
depends on DM
help
This adds a simple uclass for mcu device.
config MCU_HC32fX
bool "Enable HC32fX MCU support"
depends on DM_MCU
help
This adds a driver for the HC32fX MCU support.
endmenu

9
drivers/mcu/Makefile Executable file
View File

@@ -0,0 +1,9 @@
#
# Copyright (c) 2015 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-$(CONFIG_DM_MCU) += mcu-uclass.o
obj-$(CONFIG_MCU_HC32fX) += mcu_hc32fx.o

65
drivers/mcu/mcu-uclass.c Executable file
View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <mcu/mcu-uclass.h>
#include <dm/root.h>
#include <dm/uclass-internal.h>
int _mcu_shutdown(struct udevice *dev)
{
struct mcu_ops *ops = dev_get_driver_ops(dev);
if (!ops->shutdown)
return -ENOSYS;
return ops->shutdown(dev);
}
int _mcu_poweron(struct udevice *dev)
{
struct mcu_ops *ops = dev_get_driver_ops(dev);
if (!ops->poweron)
return -ENOSYS;
return ops->poweron(dev);
}
int mcu_poweron(void)
{
struct udevice *mcu;
int ret;
ret = uclass_get_device(UCLASS_MCU, 0, &mcu);
if (ret) {
printf("Get UCLASS_MCU failed, ret=%d\n", ret);
return ret;
}
return _mcu_poweron(mcu);
}
int mcu_shutdown(void)
{
struct udevice *mcu;
int ret;
ret = uclass_get_device(UCLASS_MCU, 0, &mcu);
if (ret) {
printf("Get charge display failed, ret=%d\n", ret);
return ret;
}
return _mcu_shutdown(mcu);
}
UCLASS_DRIVER(mcu) = {
.id = UCLASS_MCU,
.name = "mcu",
};

97
drivers/mcu/mcu_hc32fx.c Executable file
View File

@@ -0,0 +1,97 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <mcu/mcu-uclass.h>
#include <dm/lists.h>
DECLARE_GLOBAL_DATA_PTR;
#define HC32FX_POWEROFF_20 0x20
#define HC32FX_POWERON_30 0x30
#define POWER_OFF 0x55
#define POWER_ON 0x01
struct hc32fx_info {
struct udevice *dev;
};
static u8 hc32fx_read(struct hc32fx_info *hc32fx, u8 reg)
{
u8 val;
int ret;
ret = dm_i2c_read(hc32fx->dev, reg, &val, 1);
if (ret) {
printf("write error to device: %p register: %#x!",
hc32fx->dev, reg);
return ret;
}
return val;
}
static int hc32fx_write(struct hc32fx_info *hc32fx, u8 reg, u8 val)
{
int ret;
ret = dm_i2c_write(hc32fx->dev, reg, &val, 1);
if (ret) {
printf("write error to device: %p register: %#x!",
hc32fx->dev, reg);
return ret;
}
return 0;
}
static int mcu_hc32fx_poweron(struct udevice *dev)
{
struct hc32fx_info *hc32fx = dev_get_priv(dev);
int ret;
ret = hc32fx_write(hc32fx, HC32FX_POWERON_30, POWER_ON);
if(ret)
printf("set mcu POWERON fail\n");
return ret;
}
static int mcu_hc32fx_shutdown(struct udevice *dev)
{
struct hc32fx_info *hc32fx = dev_get_priv(dev);
int ret;
ret = hc32fx_write(hc32fx, HC32FX_POWEROFF_20, POWER_OFF);
if(ret)
printf("set mcu POWEROFF fail\n");
return ret;
}
static int mcu_gpio_probe(struct udevice *dev)
{
struct hc32fx_info *priv = dev_get_priv(dev);
priv->dev = dev;
return 0;
}
static const struct mcu_ops mcu_hc32fx_ops = {
.poweron = mcu_hc32fx_poweron,
.shutdown = mcu_hc32fx_shutdown,
};
static const struct udevice_id hc32fx_ops_ids[] = {
{ .compatible = "mcu_hc32fx" },
{ }
};
U_BOOT_DRIVER(mcu_gpio) = {
.name = "hc32fx-mcu",
.id = UCLASS_MCU,
.of_match = hc32fx_ops_ids,
.ops = &mcu_hc32fx_ops,
.priv_auto_alloc_size = sizeof(struct hc32fx_info),
.probe = mcu_gpio_probe,
};

View File

@@ -6,6 +6,7 @@
#include <linux/delay.h>
#include <command.h>
#include "light_regu.h"
#include <dm/device.h>
#define FDT32_TO_CPU(x) (fdt32_to_cpu(x))
@@ -18,7 +19,7 @@
#endif
#ifdef AON_CONF_DEBUG
#define AON_CONF_D(fmt, args...) printf(fmt,##args)
#define AON_CONF_D(fmt, args...) printf(fmt, ##args)
#else
#define AON_CONF_D(fmt, args...)
#endif
@@ -69,7 +70,7 @@ static int misc_regu_remove(struct udevice *dev)
return 0;
}
static soc_virtual_id_t *found_base_virtual_id(char *name)
static soc_virtual_id_t *found_base_virtual_id(const char *name)
{
for (int i = 0; i < ARRAY_SIZE(soc_base_virtual_id_list); i++)
{
@@ -111,7 +112,7 @@ static int misc_regu_get_virtual_regu_config(struct udevice *dev, ofnode parent_
soc_virtual_id_t *soc_base_id;
ofnode_for_each_subnode(child_node, parent_node)
{
//printf("sub node name: %s\n", ofnode_get_name(child_node));
// printf("sub node name: %s\n", ofnode_get_name(child_node));
regu_num++;
}
@@ -134,8 +135,8 @@ static int misc_regu_get_virtual_regu_config(struct udevice *dev, ofnode parent_
ofnode_for_each_subnode(child_node, parent_node)
{
const char *virtual_id_name = ofnode_get_name(child_node);
int min_uv;
int max_uv;
uint32_t min_uv;
uint32_t max_uv;
soc_base_id = found_base_virtual_id(virtual_id_name);
if (soc_base_id)
{
@@ -173,7 +174,11 @@ static int misc_regu_get_virtual_regu_config(struct udevice *dev, ofnode parent_
{
id_list[index].max_uv = max_uv;
}
#warning "check double"
if (id_list[index].max_uv < id_list[index].min_uv)
{
printf("id:%d regulator-max-microvolt:%d is smaller than regulator-min-microvolt:%d\n", index, id_list[index].max_uv, id_list[index].min_uv);
return -1;
}
// printf("Get virtual regu_id:[%d]:%s min_uv:%dmv max_uv:%dmv\n", id_list[index].id, id_list[index].virtual_id_name,
// id_list[index].min_uv, id_list[index].max_uv);
index++;
@@ -185,12 +190,12 @@ static int misc_regu_get_virtual_regu_config(struct udevice *dev, ofnode parent_
return 0;
}
static int misc_grep_pmic_dev_name_info(char *dev_name, pmic_dev_info_t *dev)
static int misc_grep_pmic_dev_name_info(const char *dev_name, pmic_dev_info_t *dev)
{
int flag_num = 0;
int version_flag = 0;
int index = 0;
char *dev_name_orig = dev_name;
const char *dev_name_orig = dev_name;
while (*dev_name)
{
if (*dev_name == ',')
@@ -235,20 +240,117 @@ static int get_node_index(const char *name)
return strtoul(name, NULL, 10);
}
static int misc_pmic_parent_io_ctrl_config(ofnode dev_node, pmic_parent_ctrl_info_t *ctrl_info)
{
ofnode parent_ctrl_sub_node, parent_pmic_node;
int get_aon_ctrl_info_flag = 0;
int get_pmic_pin_ctrl_info_flag = 0;
uint32_t prop_size;
int prop_len;
const uint32_t *prop_val;
ofnode_for_each_subnode(parent_ctrl_sub_node, dev_node)
{
const char *node_name = ofnode_get_name(parent_ctrl_sub_node);
if (!strncmp(node_name, PMIC_PARENT_CTRL_NAME, strlen(PMIC_PARENT_CTRL_NAME)))
{
if (ofnode_read_bool(parent_ctrl_sub_node, "aon_pin_ctrl_info"))
{
prop_val = ofnode_get_property(parent_ctrl_sub_node, "aon_pin_ctrl_info", &prop_len);
if (!prop_val)
{
printf("aon_pin_ctrl_info property not found\n");
return -1;
}
prop_size = prop_len / sizeof(uint32_t);
if (prop_size != 3)
{
printf("invalid pmic-aon_pin_ctrl_info cell size %d, it should set format as aon_pin_ctrl_info = <<port> <pin> <activate_status>>\n", prop_size);
return -1;
}
ctrl_info->pmic_ctrl_type = PMIC_CTRL_BY_AON_GPIO;
ctrl_info->info.aon_io.gpio_port = FDT32_TO_CPU(prop_val[0]);
ctrl_info->info.aon_io.pin = FDT32_TO_CPU(prop_val[1]);
ctrl_info->info.aon_io.activate_status = FDT32_TO_CPU(prop_val[2]);
if (ctrl_info->info.aon_io.activate_status != HW_ID_ACTIVATE_HIGH && ctrl_info->info.aon_io.activate_status != HW_ID_ACTIVATE_LOW)
{
printf("aon io activate should set to: ACTIVATE_HIGH:0 or ACTIVATE_LOW:1");
return -1;
}
get_aon_ctrl_info_flag = 1;
}
if (ofnode_read_bool(parent_ctrl_sub_node, "pmic_pin_ctrl_info"))
{
prop_val = ofnode_get_property(parent_ctrl_sub_node, "pmic_pin_ctrl_info", &prop_len);
if (!prop_val)
{
printf("pmic_pin_ctrl_info property not found\n");
return -1;
}
prop_size = prop_len / sizeof(uint32_t);
if (prop_size != 3)
{
printf("invalid pmic-pmic_pin_ctrl_info cell size %d, it should set format as pmic_pin_ctrl_info = <<&pmic_dev> <pin> <activate_status>>\n", prop_size);
return -1;
}
parent_pmic_node = ofnode_get_by_phandle(FDT32_TO_CPU(prop_val[0]));
if (!ofnode_valid(parent_pmic_node))
{
printf("parent_pmic_node not found\n");
return -1;
}
int parent_pmic_index = get_node_index(ofnode_get_name(parent_pmic_node));
if (parent_pmic_index < 0)
{
printf("parent_pmic_node index not found\n");
return -1;
}
ctrl_info->pmic_ctrl_type = PMIC_CTRL_BY_PMIC_GPIO;
ctrl_info->info.pmic_io.pmic_id = parent_pmic_index;
ctrl_info->info.pmic_io.io_hw_id = FDT32_TO_CPU(prop_val[1]);
ctrl_info->info.pmic_io.activate_status = FDT32_TO_CPU(prop_val[2]);
if (ctrl_info->info.pmic_io.activate_status != HW_ID_ACTIVATE_HIGH && ctrl_info->info.pmic_io.activate_status != HW_ID_ACTIVATE_LOW)
{
printf("pmic io activate should set to: HW_ID_ACTIVATE_HIGH:0 or HW_ID_ACTIVATE_LOW:1");
return -1;
}
get_pmic_pin_ctrl_info_flag = 1;
}
if (get_aon_ctrl_info_flag && get_pmic_pin_ctrl_info_flag)
{
printf("aon_pin_ctrl_info or pmic_pin_ctrl_info should only support one for a pmic dev\n");
return -1;
}
if (!get_aon_ctrl_info_flag && !get_pmic_pin_ctrl_info_flag)
{
printf("aon_pin_ctrl_info or pmic_pin_ctrl_info should only support one for a pmic dev\n");
return -1;
}
return 0;
}
}
ctrl_info->pmic_ctrl_type = PMIC_CTRL_BY_NOTHINTG;
return 0;
}
static int misc_regu_get_pmic_dev_config(ofnode parent_node, pmic_dev_info_t *pmic_dev_info_list)
{
int ret = 0;
ofnode child_node, errio_node;
fdt_addr_t index;
char *pmic_name;
ofnode child_node;
int index;
const char *pmic_name;
int pmic_wdt_flag = 0;
int pmic_index = 0;
int pmic_addr_len = 0, pmic_addr_size;
int gpio_addr_len = 0, gpio_addr_size;
char err_io_str[40] = "NOT_SUPPORT";
char lpm_io_str[40] = "NOT_SUPPORT";
char parent_pmic_str[60] = "NOT_SUPPORT";
uint32_t port, pin, trigger_mode;
uint32_t phandle;
const uint32_t *prop_val;
ofnode_for_each_subnode(child_node, parent_node)
@@ -266,7 +368,7 @@ static int misc_regu_get_pmic_dev_config(ofnode parent_node, pmic_dev_info_t *pm
pmic_name = ofnode_read_string(child_node, "pmic-name");
if (!pmic_name)
{
printf("pmic_name property not set for %s%d", PMIC_DEV_DTS_NAME, index);
printf("pmic_name property not set for %s %d", PMIC_DEV_DTS_NAME, index);
return -1;
}
@@ -289,7 +391,7 @@ static int misc_regu_get_pmic_dev_config(ofnode parent_node, pmic_dev_info_t *pm
}
pmic_addr_size = pmic_addr_len / sizeof(uint32_t);
if (pmic_addr_size != 2 && pmic_addr_size!= 1)
if (pmic_addr_size != 2 && pmic_addr_size != 1)
{
printf("invalid pmic-addr cell size %d\n", pmic_addr_size);
return -1;
@@ -310,16 +412,23 @@ static int misc_regu_get_pmic_dev_config(ofnode parent_node, pmic_dev_info_t *pm
else
{
port = FDT32_TO_CPU(prop_val[0]);
pin = 1 << FDT32_TO_CPU(prop_val[1]);
pin = FDT32_TO_CPU(prop_val[1]);
trigger_mode = FDT32_TO_CPU(prop_val[2]);
dev->flag |= PMIC_DEV_ENABLE_ERR_IO;
dev->err_io_info.gpio_port = port;
dev->err_io_info.pin = pin;
dev->err_io_info.trigger_mode = trigger_mode;
if (dev->err_io_info.trigger_mode > GPIO_IRQ_MODE_HIGH_LEVEL)
{
printf("io trigger_mode support max:%d, it is set to %d\n", GPIO_IRQ_MODE_HIGH_LEVEL, dev->err_io_info.trigger_mode);
return -1;
}
sprintf(err_io_str, "port:%d pin:%d trigger:%d", port, pin, trigger_mode);
}
} else {
sprintf(err_io_str, "NOT_SUPPORT");
}
else
{
sprintf(err_io_str, "NOT_SUPPORT");
}
prop_val = ofnode_get_property(child_node, "lpm_gpio", &gpio_addr_len);
@@ -334,24 +443,57 @@ static int misc_regu_get_pmic_dev_config(ofnode parent_node, pmic_dev_info_t *pm
else
{
port = FDT32_TO_CPU(prop_val[0]);
pin = 1 << FDT32_TO_CPU(prop_val[1]);
pin = FDT32_TO_CPU(prop_val[1]);
trigger_mode = FDT32_TO_CPU(prop_val[2]);
dev->flag |= PMIC_DEV_ENABLE_LPM_IO;
dev->lpm_io_info.gpio_port = port;
dev->lpm_io_info.pin = pin;
dev->lpm_io_info.trigger_mode = trigger_mode;
if (dev->lpm_io_info.trigger_mode > GPIO_IRQ_MODE_HIGH_LEVEL)
{
printf("io trigger_mode support max:%d, it is set to %d\n", GPIO_IRQ_MODE_HIGH_LEVEL, dev->lpm_io_info.trigger_mode);
return -1;
}
sprintf(lpm_io_str, "port:%d pin:%d trigger:%d", port, pin, trigger_mode);
}
} else {
sprintf(lpm_io_str,"NOT_SUPPORT");
}
else
{
sprintf(lpm_io_str, "NOT_SUPPORT");
}
ret = misc_pmic_parent_io_ctrl_config(child_node, &dev->ctrl_info);
if (ret)
{
printf("grep pmic parent io ctrl faild %d\n", ret);
return -1;
}
else
{
if (dev->ctrl_info.pmic_ctrl_type == PMIC_CTRL_BY_AON_GPIO)
{
sprintf(parent_pmic_str, "ctrl by aon io: port:%d pin:%d activate_status:%d", dev->ctrl_info.info.aon_io.gpio_port, dev->ctrl_info.info.aon_io.pin, dev->ctrl_info.info.aon_io.activate_status);
}
else if (dev->ctrl_info.pmic_ctrl_type == PMIC_CTRL_BY_PMIC_GPIO)
{
sprintf(parent_pmic_str, "ctrl by pmic io: pmic:%d hw_id:%d activate_status:%d", dev->ctrl_info.info.pmic_io.pmic_id, dev->ctrl_info.info.pmic_io.io_hw_id, dev->ctrl_info.info.pmic_io.activate_status);
}
else
{
sprintf(parent_pmic_str, "NOT_SUPPORT");
}
}
dev->pmic_id = index;
ret = misc_grep_pmic_dev_name_info(pmic_name, dev);
pmic_index++;
AON_CONF_D("Get pmic dev:[%d]:%s|%s addr1:0x%02x addr2:0x%02x wdt:{%s} errio:{%s} lpm_io:{%s}\n", index, dev->device_name, dev->version_name, dev->addr1, dev->addr2, (dev->flag & PMIC_DEV_ENABLE_WDT ? "SUPPORT" : "NOT_SUPPORT"), err_io_str, lpm_io_str);
AON_CONF_D("Get pmic dev:[%d]:%s|%s addr1:0x%02x addr2:0x%02x wdt:{%s} errio:{%s} lpm_io:{%s} pmic_ctrl_info:{%s}\n", index, dev->device_name, dev->version_name, dev->addr1, dev->addr2, (dev->flag & PMIC_DEV_ENABLE_WDT ? "SUPPORT" : "NOT_SUPPORT"), err_io_str, lpm_io_str, parent_pmic_str);
}
}
if (!pmic_index)
{
printf("No %s node found\n", PMIC_DEV_DTS_NAME);
return -1;
}
return 0;
}
@@ -383,15 +525,10 @@ static int misc_regu_get_pmic_dev_by_name(const char *name, int pmic_dev_num, pm
static int misc_regu_get_each_regu_hw_id_config(ofnode regu_id_node, int pmic_dev_num, pmic_dev_info_t *pmic_dev_info_list, soc_virtual_id_t *virtual_id_info, pmic_hw_info_t *id)
{
uint32_t phandle;
ofnode pmic_node, pmic_parent_node;
char *pmic_name;
int prop_len, prop_size;
int on_order, on_delay_ms;
int off_order, off_delay_ms;
int pmic_index, parent_pmic_index;
int pmic_index;
const uint32_t *prop_val;
/*get pmic_dev = <&pmic_dev_0 DA9063_ID_BCORE1>*/
@@ -451,12 +588,14 @@ static int misc_regu_get_each_regu_hw_id_config(ofnode regu_id_node, int pmic_de
}
(*id).soft_power_ctrl_info.on_info.on_order = FDT32_TO_CPU(prop_val[0]);
(*id).soft_power_ctrl_info.on_info.on_delay_ms = FDT32_TO_CPU(prop_val[1]);
if(prop_size == 3) {
(*id).soft_power_ctrl_info.on_info.init_target_uv = FDT32_TO_CPU(prop_val[2]);
} else {
if (prop_size == 3)
{
(*id).soft_power_ctrl_info.on_info.init_target_uv = FDT32_TO_CPU(prop_val[2]);
}
else
{
(*id).soft_power_ctrl_info.on_info.init_target_uv = 0;
}
}
/*get auto_off_info = <1 1>*/
@@ -507,8 +646,12 @@ static int misc_regu_get_each_regu_hw_id_config(ofnode regu_id_node, int pmic_de
(*id).parent_hw_info.pmic_id = pmic_dev_info_list[pmic_index].pmic_id;
(*id).parent_hw_info.io_hw_id = FDT32_TO_CPU(prop_val[1]);
#warning "check status"
(*id).parent_hw_info.activate_status = FDT32_TO_CPU(prop_val[2]);
if (FDT32_TO_CPU(prop_val[2]) != HW_ID_ACTIVATE_HIGH && FDT32_TO_CPU(prop_val[2]) != HW_ID_ACTIVATE_LOW)
{
printf("parent hw io activate should set to: HW_ID_ACTIVATE_HIGH:0 or HW_ID_ACTIVATE_LOW:1");
return -1;
}
}
return 0;
@@ -519,13 +662,11 @@ static int misc_regu_get_each_regu_config(ofnode regu_config_node, int pmic_dev_
int ret = 0;
ofnode hw_id_node;
ofnode coupling_node;
uint32_t phandle = 0;
int index = 0;
char *regu_id_name;
const uint32_t *prop_val;
int prop_len = 0;
int prop_size = 0;
int coupling_num = 0;
int coupling_num = 0;
uint16_t hw_id_used_flag = 0x0;
ofnode_for_each_subnode(hw_id_node, regu_config_node)
@@ -540,9 +681,9 @@ static int misc_regu_get_each_regu_config(ofnode regu_config_node, int pmic_dev_
return -1;
}
if (index >= PMIC_MAX_HW_ID_NUM || index >= 8 * sizeof(uint16_t))
if (index >= PMIC_MAX_HW_ID_NUM || index >= 8 * 2)
{
printf("regu_id index should less than %d\n", MIN(PMIC_MAX_HW_ID_NUM, 8 * sizeof(uint16_t)));
printf("regu_id index should less than %d\n", MIN(PMIC_MAX_HW_ID_NUM, 8 * 2));
return -1;
}
@@ -559,11 +700,10 @@ static int misc_regu_get_each_regu_config(ofnode regu_config_node, int pmic_dev_
ret = misc_regu_get_each_regu_hw_id_config(hw_id_node, pmic_dev_num, pmic_dev_info_list, regu_info, &pmic_regu_id_info->sub.id[index]);
if (ret)
{
printf("get hw_id@%d config faild %d\n", ret);
printf("get hw_id@%d config faild %d\n", index, ret);
return -1;
}
}
}
for (int i = PMIC_MAX_HW_ID_NUM - 1; i >= 0; i--)
@@ -573,74 +713,81 @@ static int misc_regu_get_each_regu_config(ofnode regu_config_node, int pmic_dev_
(*pmic_regu_id_info).sub.id[i].pmic_id = PMIC_ID_INVALID;
}
}
ofnode_for_each_subnode(coupling_node, regu_config_node)
{
const char *node_name = ofnode_get_name(coupling_node);
if (!strncmp(node_name, COUPLING_ID_INFO_NAME, strlen(COUPLING_ID_INFO_NAME)))
{
/*get info = <0 1 -5 30>;*/
prop_val = ofnode_get_property(coupling_node, "info", &prop_len);
if (!prop_val)
{
printf("no info property set for %s", node_name);
return -1;
} else
{
prop_size = prop_len / sizeof(uint32_t);
if (prop_size != 4)
/*get info = <0 1 -5 30>;*/
prop_val = ofnode_get_property(coupling_node, "info", &prop_len);
if (!prop_val)
{
printf("coupling info property should set in format as info = <id0 id1 max_spread min_spread)>\n");
printf("no info property set for %s", node_name);
return -1;
}
else
{
prop_size = prop_len / sizeof(uint32_t);
if (prop_size != 4)
{
printf("coupling info property should set in format as info = <id0 id1 max_spread min_spread)>\n");
return -1;
}
int id0 = FDT32_TO_CPU(prop_val[0]);
int id1 = FDT32_TO_CPU(prop_val[1]);
int8_t max_spread = FDT32_TO_CPU(prop_val[2]);
int8_t min_spread = FDT32_TO_CPU(prop_val[3]);
int id0 = FDT32_TO_CPU(prop_val[0]);
int id1 = FDT32_TO_CPU(prop_val[1]);
int8_t max_spread = FDT32_TO_CPU(prop_val[2]);
int8_t min_spread = FDT32_TO_CPU(prop_val[3]);
if(ofnode_read_bool(coupling_node, "negative-min")) {
min_spread = -min_spread;
}
if(ofnode_read_bool(coupling_node, "negative-max")) {
max_spread = -max_spread;
}
if(id0 == id1) {
printf("coupling info: id0 id1 should not be equal");
return -1;
}
if(min_spread > max_spread) {
printf("coupling info: min_spread:%d is higher than max_spread:%d", min_spread, max_spread);
return -1;
}
if(id0 >= PMIC_MAX_HW_ID_NUM || id1 >= PMIC_MAX_HW_ID_NUM) {
printf("coupling info: id0:%d id1:%d is higher than max_id:%d", id0, id1, PMIC_MAX_HW_ID_NUM -1);
return -1;
}
if (ofnode_read_bool(coupling_node, "negative-min"))
{
min_spread = -min_spread;
}
if (ofnode_read_bool(coupling_node, "negative-max"))
{
max_spread = -max_spread;
}
if (id0 == id1)
{
printf("coupling info: id0 id1 should not be equal");
return -1;
}
if (min_spread > max_spread)
{
printf("coupling info: min_spread:%d is higher than max_spread:%d", min_spread, max_spread);
return -1;
}
if (id0 >= PMIC_MAX_HW_ID_NUM || id1 >= PMIC_MAX_HW_ID_NUM)
{
printf("coupling info: id0:%d id1:%d is higher than max_id:%d", id0, id1, PMIC_MAX_HW_ID_NUM - 1);
return -1;
}
if((*pmic_regu_id_info).sub.id[id0].pmic_id == PMIC_ID_INVALID || (*pmic_regu_id_info).sub.id[id1].pmic_id == PMIC_ID_INVALID) {
printf("coupling info:id0:%d id1:%d is invalid", id0, id1);
return -1;
if ((*pmic_regu_id_info).sub.id[id0].pmic_id == PMIC_ID_INVALID || (*pmic_regu_id_info).sub.id[id1].pmic_id == PMIC_ID_INVALID)
{
printf("coupling info:id0:%d id1:%d is invalid", id0, id1);
return -1;
}
(*pmic_regu_id_info).sub.coupling_list[coupling_num].id0 = id0;
(*pmic_regu_id_info).sub.coupling_list[coupling_num].id1 = id1;
(*pmic_regu_id_info).sub.coupling_list[coupling_num].max_spread = max_spread;
(*pmic_regu_id_info).sub.coupling_list[coupling_num].min_spread = min_spread;
coupling_num++;
if (coupling_num > PMIC_MAX_COUPLING_NUM)
{
printf("coupling info should no more than %d\n", coupling_num);
return -1;
}
}
(*pmic_regu_id_info).sub.coupling_list[coupling_num].id0 = id0;
(*pmic_regu_id_info).sub.coupling_list[coupling_num].id1 = id1;
(*pmic_regu_id_info).sub.coupling_list[coupling_num].max_spread = max_spread;
(*pmic_regu_id_info).sub.coupling_list[coupling_num].min_spread = min_spread;
coupling_num++;
if(coupling_num > PMIC_MAX_COUPLING_NUM) {
printf("coupling info should no more than %d\n", coupling_num);
return -1;
}
}
}
}
for(int i = PMIC_MAX_COUPLING_NUM - 1; i >= coupling_num; i--)
for (int i = PMIC_MAX_COUPLING_NUM - 1; i >= coupling_num; i--)
{
(*pmic_regu_id_info).sub.coupling_list[i].id0 = REGU_SUB_ID_INVALID;
(*pmic_regu_id_info).sub.coupling_list[i].id1 = REGU_SUB_ID_INVALID;
(*pmic_regu_id_info).sub.coupling_list[i].id0 = REGU_SUB_ID_INVALID;
(*pmic_regu_id_info).sub.coupling_list[i].id1 = REGU_SUB_ID_INVALID;
}
return 0;
@@ -649,11 +796,10 @@ static int misc_regu_get_each_regu_config(ofnode regu_config_node, int pmic_dev_
static int misc_regu_get_regu_config(ofnode parent_node, int pmic_dev_num, pmic_dev_info_t *pmic_dev_info_list, int virtual_id_num, soc_virtual_id_t *regu_list, csi_regu_id_t *pmic_regu_id_list)
{
ofnode child_node;
int index = 0;
uint32_t phandle = 0;
int ret = 0;
ofnode regu_virtual_node;
char *regu_id_name;
const char *regu_id_name;
int virtual_id_index = 0;
uint16_t virtual_id_config_flag = 0;
int regu_config_index = 0;
@@ -661,7 +807,7 @@ static int misc_regu_get_regu_config(ofnode parent_node, int pmic_dev_num, pmic_
ofnode_for_each_subnode(child_node, parent_node)
{
virtual_id_index = 0;
char *node_name = ofnode_get_name(child_node);
const char *node_name = ofnode_get_name(child_node);
if (!strncmp(node_name, REGU_ID_CONF_NAME, strlen(REGU_ID_CONF_NAME)))
{
@@ -718,7 +864,7 @@ static int misc_regu_get_regu_config(ofnode parent_node, int pmic_dev_num, pmic_
return -1;
}
AON_CONF_D("Get regu config, virtual_regu_id:[%d]:%s min_uv:%dmv max_uv:%dmv\n", virtual_id, regu_list[virtual_id_index].virtual_id_name, regu_list[virtual_id_index].min_uv,regu_list[virtual_id_index].max_uv);
AON_CONF_D("Get regu config, virtual_regu_id:[%d]:%s min_uv:%dmv max_uv:%dmv\n", virtual_id, regu_list[virtual_id_index].virtual_id_name, regu_list[virtual_id_index].min_uv, regu_list[virtual_id_index].max_uv);
for (int i = 0; i < ARRAY_SIZE(regu_conf->sub.id); i++)
{
pmic_hw_info_t *sub = &regu_conf->sub.id[i];
@@ -758,24 +904,31 @@ static int misc_regu_get_regu_config(ofnode parent_node, int pmic_dev_num, pmic_
}
}
int temp_flag = 0;
for(int i = 0; i < ARRAY_SIZE(regu_conf->sub.coupling_list); i++) {
coupling_desc_t* coupling_info = &regu_conf->sub.coupling_list[i];
if(coupling_info->id0 != REGU_SUB_ID_INVALID) {
if(!temp_flag) {
AON_CONF_D(">>>>>>");
for (int i = 0; i < ARRAY_SIZE(regu_conf->sub.coupling_list); i++)
{
coupling_desc_t *coupling_info = &regu_conf->sub.coupling_list[i];
if (coupling_info->id0 != REGU_SUB_ID_INVALID)
{
if (!temp_flag)
{
AON_CONF_D(">>>>>>");
temp_flag = 1;
}
AON_CONF_D("%s@%d:{id0:%d id1:%d max_spreed:%dmv min_spreed:%dmv} ", COUPLING_ID_INFO_NAME, i,coupling_info->id0, coupling_info->id1, coupling_info->max_spread *10 , coupling_info->min_spread * 10);
AON_CONF_D("%s@%d:{id0:%d id1:%d max_spreed:%dmv min_spreed:%dmv} ", COUPLING_ID_INFO_NAME, i, coupling_info->id0, coupling_info->id1, coupling_info->max_spread * 10, coupling_info->min_spread * 10);
}
}
if(temp_flag) {
if (temp_flag)
{
AON_CONF_D("\n");
}
regu_config_index++;
}
}
#warning "add no config check"
if (!regu_config_index)
{
printf("No %s node found\n", REGU_ID_CONF_NAME);
return -1;
}
return 0;
}
@@ -816,7 +969,7 @@ static int misc_regu_get_aon_pmic_config(struct udevice *dev, ofnode parent_node
if (ret)
{
printf("pmic dev config get faild %d", ret);
#warning "free"
free(pmic_dev_info_list);
return -1;
}
@@ -846,7 +999,8 @@ static int misc_regu_get_aon_pmic_config(struct udevice *dev, ofnode parent_node
if (ret)
{
printf("get regu config faild %d\n", ret);
#warning "free"
free(pmic_dev_info_list);
free(pmic_regu_id_list);
return -1;
}
@@ -859,15 +1013,19 @@ static int misc_regu_get_aon_pmic_config(struct udevice *dev, ofnode parent_node
return 0;
}
extern int device_bind_ofnode(struct udevice *parent, const struct driver *driver,
const char *name, const void *platdata, ofnode node,
struct udevice **devp);
static int misc_regu_bind(struct udevice *dev)
{
struct mic_regu_platdata *plat = dev_get_platdata(dev);
ofnode parent_node = dev->node;
const uint32_t *prop_val;
int prop_len = 0;
int prop_size = 0;
int ret;
ofnode child_node, node, regu_node, aon_conf_node;
const void *blob = gd->fdt_blob;
int subnode;
ofnode child_node, aon_conf_node = {0}, regu_node = {0};
struct udevice *dev_1;
/* If this is a child device, there is nothing to do here */
@@ -888,7 +1046,7 @@ static int misc_regu_bind(struct udevice *dev)
ofnode_for_each_subnode(child_node, parent_node)
{
/* Increment base_id for all subnodes, also the disabled ones */
//printf("sub node name: %s\n", ofnode_get_name(child_node));
// printf("sub node name: %s\n", ofnode_get_name(child_node));
if (!strncmp(ofnode_get_name(child_node), REGU_DTS_NAME, strlen(REGU_DTS_NAME)))
{
regu_node = child_node;
@@ -901,8 +1059,6 @@ static int misc_regu_bind(struct udevice *dev)
}
}
if (!get_regu_dts_flag)
{
printf("No %s node in dts\n", REGU_DTS_NAME);
@@ -921,18 +1077,48 @@ static int misc_regu_bind(struct udevice *dev)
return -ENOMEM;
}
plat->wakeup_flag = 0;
plat->wakeup_flag = 0;
if (ofnode_read_bool(parent_node, "wakeup-by-gpio-on")) {
if (ofnode_read_bool(parent_node, "wakeup-by-gpio-on"))
{
plat->wakeup_flag |= AON_WAKEUP_BY_GPIO;
printf("aon wakeup by gpio enabled\n");
}
if (ofnode_read_bool(parent_node, "wakeup-by-rtc-on")) {
if (ofnode_read_bool(parent_node, "wakeup-by-rtc-on"))
{
plat->wakeup_flag |= AON_WAKEUP_BY_RTC;
printf("aon wakeup by rtc enabled\n");
}
/*grep ii-config info*/
prop_val = ofnode_get_property(aon_conf_node, "iic-config", &prop_len);
if (!prop_val)
{
printf("pmic-addr property not found\n");
return -1;
}
prop_size = prop_len / sizeof(uint32_t);
if (prop_size != 3)
{
printf("invalid iic-config cell size %d,it should set in format as iic-config = <<id> <addr_mode> <speed>>\n", prop_size);
return -1;
}
plat->iic_config.iic_id = FDT32_TO_CPU(prop_val[0]);
plat->iic_config.addr_mode = FDT32_TO_CPU(prop_val[1]);
plat->iic_config.speed = FDT32_TO_CPU(prop_val[2]);
if (plat->iic_config.addr_mode > IIC_ADDRESS_10BIT)
{
printf("iic addr_mode only support IIC_ADDRESS_7BIT:0 IIC_ADDRESS_10BIT:1\n");
return -1;
}
if (plat->iic_config.speed > IIC_BUS_SPEED_HIGH)
{
printf("iic speed max support IIC_BUS_SPEED_HIGH:%d\n", IIC_BUS_SPEED_HIGH);
return -1;
}
printf("iic id:%d addr_mode:%d speed:%d\n", plat->iic_config.iic_id, plat->iic_config.addr_mode, plat->iic_config.speed);
ret = misc_regu_get_virtual_regu_config(dev, regu_node, &plat->regu_list);
if (ret)
{

View File

@@ -1,7 +1,6 @@
#ifndef __LIGHT_REGU_H__
#define __LIGHT_REGU_H__
typedef enum
{
SOC_DVDD18_AON, /*da9063: ldo-3 */
@@ -35,25 +34,23 @@ typedef enum
SOC_REGU_INVALID = 0xFF
} soc_virtual_id_en;
#define REGU_DTS_NAME "light-regu-reg"
#define AON_CONF_NAME "aon_pmic_config"
#define PMIC_DEV_DTS_NAME "pmic-dev"
#define PMIC_PARENT_CTRL_NAME "pmic_ctrl_info"
#define REGU_ID_CONF_NAME "regu_config"
#define REGU_ID_NAME "regu_id"
#define COUPLING_ID_INFO_NAME "coupling_info"
#define REGU_ID_NAME "regu_id"
#define COUPLING_ID_INFO_NAME "coupling_info"
#define PMIC_DEV_ENABLE_WDT (1U << 0)
#define PMIC_DEV_ENABLE_ERR_IO (1U << 1)
#define PMIC_DEV_ENABLE_LPM_IO (1U << 2)
#define PMIC_DEV_ENABLE_WDT (1U << 0)
#define PMIC_DEV_ENABLE_ERR_IO (1U << 1)
#define PMIC_DEV_ENABLE_LPM_IO (1U << 2)
#define HW_ID_NO_SOFT_AUTO_ON (0xff)
#define HW_ID_NO_SOFT_AUTO_OFF (0xff)
#define HW_ID_INVALID (0xff)
#define PMIC_ID_INVALID (0xff)
#define REGU_SUB_ID_INVALID (0xff)
#define HW_ID_NO_SOFT_AUTO_ON (0xff)
#define HW_ID_NO_SOFT_AUTO_OFF (0xff)
#define HW_ID_INVALID (0xff)
#define PMIC_ID_INVALID (0xff)
#define REGU_SUB_ID_INVALID (0xff)
#define REGU_EXT_ID_NAME_LEN 30
#define PMIC_DEV_NAME_LEN 20
@@ -63,108 +60,148 @@ typedef enum
#define PMIC_MAX_COUPLING_NUM 3
#define AON_WAKEUP_BY_GPIO (1 << 0)
#define AON_WAKEUP_BY_RTC (1 << 1)
#define AON_WAKEUP_BY_RTC (1 << 1)
typedef enum {
HW_ID_ACTIVATE_HIGH = 0U,
HW_ID_ACTIVATE_LOW = 1U,
#define AON_CONFIG_MAGIC "AON_CONFIG"
#define UBOOT_CONFIG_MAGIC "UBOOT_SET"
#define AON_CONFIG_VERSION "1.0.0"
typedef enum
{
HW_ID_ACTIVATE_HIGH = 0U,
HW_ID_ACTIVATE_LOW = 1U,
} hw_activate_status_en;
typedef struct __packed {
typedef struct __packed
{
uint8_t pmic_id;
uint8_t io_hw_id;
uint8_t activate_status;
uint8_t io_hw_id;
uint8_t activate_status;
} pmic_parent_hw_io_ctrl_info_t;
typedef struct __packed {
uint8_t on_order;
uint8_t on_delay_ms;
uint32_t init_target_uv;
typedef struct __packed
{
uint8_t on_order;
uint8_t on_delay_ms;
uint32_t init_target_uv;
} regu_soft_power_ctrl_on_t;
typedef struct __packed {
uint8_t off_order;
typedef struct __packed
{
uint8_t off_order;
uint8_t off_delay_ms;
} regu_soft_power_ctrl_off_t;
typedef struct __packed {
regu_soft_power_ctrl_on_t on_info;
regu_soft_power_ctrl_off_t off_info;
typedef struct __packed
{
regu_soft_power_ctrl_on_t on_info;
regu_soft_power_ctrl_off_t off_info;
} regu_soft_power_ctrl_t;
typedef struct __packed {
typedef struct __packed
{
uint8_t id0;
uint8_t id1;
int8_t max_spread; // mv/10
int8_t min_spread; // mv/10
}coupling_desc_t;
} coupling_desc_t;
typedef enum
{
GPIO_IRQ_MODE_RISING_EDGE = 0, ///< Interrupt mode for rising edge
GPIO_IRQ_MODE_FALLING_EDGE, ///< Interrupt mode for falling edge
GPIO_IRQ_MODE_BOTH_EDGE, ///< Interrupt mode for both edge
GPIO_IRQ_MODE_LOW_LEVEL, ///< Interrupt mode for low level
GPIO_IRQ_MODE_HIGH_LEVEL, ///< Interrupt mode for high level
} csi_gpio_irq_mode_t;
typedef struct __packed {
uint8_t pmic_id;
uint8_t hw_id;
uint8_t benable;
pmic_parent_hw_io_ctrl_info_t parent_hw_info;
regu_soft_power_ctrl_t soft_power_ctrl_info;
typedef enum
{
IIC_ADDRESS_7BIT = 0U, ///< 7-bit address mode
IIC_ADDRESS_10BIT ///< 10-bit address mode
} csi_iic_addr_mode_t;
typedef enum
{
IIC_BUS_SPEED_STANDARD = 0U, ///< Standard Speed (<=100kHz)
IIC_BUS_SPEED_FAST, ///< Fast Speed (<=400kHz)
IIC_BUS_SPEED_FAST_PLUS, ///< Fast plus Speed (<= 1MHz)
IIC_BUS_SPEED_HIGH ///< High Speed (<=3.4MHz)
} csi_iic_speed_t;
typedef struct __packed
{
uint8_t pmic_id;
uint8_t hw_id;
uint8_t benable;
pmic_parent_hw_io_ctrl_info_t parent_hw_info;
regu_soft_power_ctrl_t soft_power_ctrl_info;
} pmic_hw_info_t;
typedef struct __packed{
typedef struct __packed
{
coupling_desc_t coupling_list[PMIC_MAX_COUPLING_NUM];
pmic_hw_info_t id[PMIC_MAX_HW_ID_NUM]; ///< sub id1 for single-rail or first src of dual-rail
}pmic_hw_id_t;
pmic_hw_info_t id[PMIC_MAX_HW_ID_NUM]; ///< sub id1 for single-rail or first src of dual-rail
} pmic_hw_id_t;
typedef struct __packed {
uint8_t regu_ext_id; ///< virtual global regulator id
char regu_ext_id_name[REGU_EXT_ID_NAME_LEN]; ///< vitual regu-id name
pmic_hw_id_t sub; ///< sub id set for dual-rail/single-rail regulator
}csi_regu_id_t;
typedef struct __packed
{
uint8_t regu_ext_id; ///< virtual global regulator id
char regu_ext_id_name[REGU_EXT_ID_NAME_LEN]; ///< vitual regu-id name
pmic_hw_id_t sub; ///< sub id set for dual-rail/single-rail regulator
} csi_regu_id_t;
typedef enum {
PMIC_CTRL_BY_AON_GPIO = 0U,
PMIC_CTRL_BY_PMIC_GPIO = 1U,
PMIC_CTRL_BY_NOTHINTG = 0xFF,
typedef enum
{
PMIC_CTRL_BY_AON_GPIO = 0U,
PMIC_CTRL_BY_PMIC_GPIO = 1U,
PMIC_CTRL_BY_NOTHINTG = 0xFF,
} pmic_ctrl_info_en;
typedef struct __packed {
uint8_t port;
typedef struct __packed
{
uint8_t gpio_port;
uint8_t pin;
uint8_t activate_status;
uint8_t activate_status;
} pmic_ctrl_by_aon_info_t;
typedef struct __packed {
typedef struct __packed
{
uint8_t pmic_id;
uint8_t io_hw_id;
uint8_t activate_status;
uint8_t io_hw_id;
uint8_t activate_status;
} pmic_ctrl_by_pmic_info_t;
typedef struct __packed {
uint8_t pmic_ctrl_type;
union {
pmic_ctrl_by_aon_info_t aon_io_info;
pmic_ctrl_by_pmic_info_t pmic_io_info;
};
typedef struct __packed
{
uint8_t pmic_ctrl_type;
union
{
pmic_ctrl_by_aon_info_t aon_io;
pmic_ctrl_by_pmic_info_t pmic_io;
} info;
} pmic_parent_ctrl_info_t;
typedef struct __packed{
uint16_t gpio_port;
uint16_t pin;
uint8_t trigger_mode;
typedef struct __packed
{
uint8_t gpio_port;
uint8_t pin;
uint8_t trigger_mode;
} pmic_interrupt_io_info_t;
typedef struct __packed {
char device_name[PMIC_DEV_NAME_LEN];
char version_name[PMIC_DEV_VERSION_LEN];
uint8_t pmic_id;
uint8_t addr1;
uint8_t addr2;
uint8_t flag; /*support wdt|errio| lpm io*/
typedef struct __packed
{
char device_name[PMIC_DEV_NAME_LEN];
char version_name[PMIC_DEV_VERSION_LEN];
uint8_t pmic_id;
uint8_t addr1;
uint8_t addr2;
uint8_t flag; /*support wdt|errio| lpm io*/
uint8_t slew_rate;
uint32_t wdt_len;
uint32_t wdt_len;
pmic_interrupt_io_info_t err_io_info;
pmic_interrupt_io_info_t lpm_io_info;
pmic_parent_ctrl_info_t ctrl_info;
pmic_parent_ctrl_info_t ctrl_info;
} pmic_dev_info_t;
typedef struct
@@ -193,37 +230,42 @@ typedef struct
csi_regu_id_t *regu_id_list;
} regu_id_list_t;
typedef struct __packed
{
uint8_t iic_id; ///< iic id
uint8_t addr_mode; ///< iic addr_mode ---> csi_iic_addr_mode_t
uint8_t speed; ///< iic speed type ---> csi_iic_speed_t
uint8_t reserved[1];
} csi_pmic_if_config_t;
struct mic_regu_platdata
{
const char *name;
uint32_t wakeup_flag;
uint32_t wakeup_flag;
csi_pmic_if_config_t iic_config;
virtual_regu_list_t regu_list;
pmic_dev_list_t pmic_list;
regu_id_list_t regu_id_list;
};
typedef struct __packed
{
csi_pmic_if_config_t iic_config;
uint8_t pmic_dev_num;
uint8_t regu_num;
uint32_t pmic_dev_list_offset;
uint32_t regu_id_list_offset;
} aon_pmic_config_t;
#define AON_CONFIG_MAGIC "AON_CONFIG"
#define AON_CONFIG_VERSION "1.0.0"
typedef struct __packed{
uint8_t iic_id;
uint8_t pmic_dev_num;
uint8_t regu_num;
int pmic_dev_list_offset;
int regu_id_list_offset;
}aon_pmic_config_t;
typedef struct __packed{
const char magic[11];
const char version[11];
uint8_t max_hw_id_num;
uint64_t aon_config_partition_size;
uint32_t wakeup_flag;
aon_pmic_config_t aon_pmic;
typedef struct __packed
{
const char magic[11];
const char version[11];
const char uboot_set_magic[11];
uint8_t max_hw_id_num;
uint64_t aon_config_partition_size;
uint32_t wakeup_flag;
aon_pmic_config_t aon_pmic;
} aon_config_t;
#endif

View File

@@ -2,10 +2,22 @@ menu "Power"
source "drivers/power/domain/Kconfig"
source "drivers/power/fuel_gauge/Kconfig"
source "drivers/power/pmic/Kconfig"
source "drivers/power/regulator/Kconfig"
source "drivers/power/charge/Kconfig"
source "drivers/power/power_delivery/Kconfig"
config DM_CHARGE_DISPLAY
bool "Enable driver model for charge display support"
depends on DM
help
This adds a simple uclass for charge display.
choice
prompt "Select Sunxi PMIC Variant"
depends on ARCH_SUNXI
@@ -72,6 +84,13 @@ config SY8106A_POWER
endchoice
config CHARGE_ANIMATION
bool "Enable charge animation"
depends on DM_CHARGE_DISPLAY && DM_FUEL_GAUGE
select ARM_CPU_SUSPEND
help
This adds a simple function for charge animation display.
config AXP_DCDC1_VOLT
int "axp pmic dcdc1 voltage"
depends on AXP221_POWER || AXP809_POWER || AXP818_POWER

View File

@@ -3,11 +3,13 @@
# Copyright (c) 2009 Wind River Systems, Inc.
# Tom Rix <Tom.Rix at windriver.com>
obj-$(CONFIG_DM_CHARGE_DISPLAY) += charge-display-uclass.o
obj-$(CONFIG_AXP152_POWER) += axp152.o
obj-$(CONFIG_AXP209_POWER) += axp209.o
obj-$(CONFIG_AXP221_POWER) += axp221.o
obj-$(CONFIG_AXP809_POWER) += axp809.o
obj-$(CONFIG_AXP818_POWER) += axp818.o
obj-$(CONFIG_CHARGE_ANIMATION) += charge_animation.o
obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o
obj-$(CONFIG_FTPMU010_POWER) += ftpmu010.o
obj-$(CONFIG_SY8106A_POWER) += sy8106a.o

View File

@@ -0,0 +1,40 @@
/*
* (C) Copyright 2017 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <command.h>
#include <common.h>
#include <dm.h>
#include <power/charge_display.h>
int charge_display_show(struct udevice *dev)
{
const struct dm_charge_display_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->show)
return -ENOSYS;
return ops->show(dev);
}
int charge_display(void)
{
struct udevice *dev;
struct udevice *fg_dev;
int ret;
ret = uclass_get_device(UCLASS_CHARGE_DISPLAY, 0, &dev);
if (ret) {
debug("Get charge display failed, ret=%d\n", ret);
return ret;
}
return charge_display_show(dev);
}
UCLASS_DRIVER(charge_display) = {
.id = UCLASS_CHARGE_DISPLAY,
.name = "charge_display",
};

5
drivers/power/charge/Kconfig Executable file
View File

@@ -0,0 +1,5 @@
config CHARGER_BQ25700
bool "BQ25700 charger support"
depends on DM_FUEL_GAUGE
help
This adds support for BQ25700 charger support.

7
drivers/power/charge/Makefile Executable file
View File

@@ -0,0 +1,7 @@
#
# Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-$(CONFIG_CHARGER_BQ25700) += bq25700_charger.o

View File

@@ -0,0 +1,334 @@
/*
* (C) Copyright 2019 Fuzhou Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/gpio.h>
#include <dm/device.h>
#include <dm/uclass.h>
#include <power/fuel_gauge.h>
#include <power/pmic.h>
#include <power/power_delivery/power_delivery.h>
DECLARE_GLOBAL_DATA_PTR;
#define BQ25700_ID 0x25700
#define BQ25703_ID 0x25703
#define COMPAT_BQ25700 "ti,bq25700"
#define COMPAT_BQ25703 "ti,bq25703"
#define BQ25700_I2C_SPEED 100000
#define BQ25700_CHARGE_CURRENT_1500MA 0x5C0
#define BQ25700_SDP_INPUT_CURRENT_500MA 0xA00
#define BQ25700_DCP_INPUT_CURRENT_1500MA 0x1E00
#define BQ25700_DCP_INPUT_CURRENT_2000MA 0x2800
#define BQ25700_DCP_INPUT_CURRENT_3000MA 0x3C00
#define WATCHDOG_ENSABLE (0x03 << 13)
#define BQ25700_CHARGEOPTION0_REG 0x12
#define BQ25700_CHARGECURREN_REG 0x14
#define BQ25700_CHARGERSTAUS_REG 0x20
#define BQ25700_INPUTVOLTAGE_REG 0x3D
#define BQ25700_INPUTCURREN_REG 0x3F
#define BQ25703_CHARGEOPTION0_REG 0x00
#define BQ25703_CHARGECURREN_REG 0x02
#define BQ25703_CHARGERSTAUS_REG 0x20
#define BQ25703_INPUTVOLTAGE_REG 0x0A
#define BQ25703_INPUTCURREN_REG 0x0E
#define PD_MUN 2
#define TYPEC0_I2C "i2c@ffe7f20000"
#define TYPEC1_I2C "i2c@ffe7f24000"
enum bq25700_table_ids {
/* range tables */
TBL_ICHG,
TBL_CHGMAX,
TBL_INPUTVOL,
TBL_INPUTCUR,
TBL_SYSVMIN,
TBL_OTGVOL,
TBL_OTGCUR,
TBL_EXTCON,
};
struct bq25700 {
struct udevice *dev;
u32 ichg;
u32 chip_id;
struct udevice *pd[PD_MUN];
};
struct bq25700_range {
u32 min;
u32 max;
u32 step;
};
static int bq25700_read(struct bq25700 *charger, uint reg)
{
u16 val;
int ret;
ret = dm_i2c_read(charger->dev, reg, (u8 *)&val, 2);
if (ret) {
printf("write error to device: %p register: %#x!",
charger->dev, reg);
return ret;
}
return val;
}
static int bq25700_write(struct bq25700 *charger, uint reg, u16 val)
{
int ret;
ret = dm_i2c_write(charger->dev, reg, (u8 *)&val, 2);
if (ret) {
printf("write error to device: %p register: %#x!",
charger->dev, reg);
return ret;
}
return 0;
}
static const union {
struct bq25700_range rt;
} bq25700_tables[] = {
/* range tables */
[TBL_ICHG] = {.rt = {0, 8128000, 64000}},
/* uV */
[TBL_CHGMAX] = {.rt = {0, 19200000, 16000}},
/* uV max charge voltage*/
[TBL_INPUTVOL] = {.rt = {3200000, 19520000, 64000}},
/* uV input charge voltage*/
[TBL_INPUTCUR] = {.rt = {0, 6350000, 50000}},
/*uA input current*/
[TBL_SYSVMIN] = {.rt = {1024000, 16182000, 256000}},
/* uV min system voltage*/
[TBL_OTGVOL] = {.rt = {4480000, 20800000, 64000}},
/*uV OTG volage*/
[TBL_OTGCUR] = {.rt = {0, 6350000, 50000}},
};
static u32 bq25700_find_idx(u32 value, enum bq25700_table_ids id)
{
const struct bq25700_range *rtbl = &bq25700_tables[id].rt;
u32 rtbl_size;
u32 idx;
rtbl_size = (rtbl->max - rtbl->min) / rtbl->step + 1;
for (idx = 1;
idx < rtbl_size && (idx * rtbl->step + rtbl->min <= value);
idx++)
;
return idx - 1;
}
static bool bq25700_charger_status(struct bq25700 *charger)
{
int state_of_charger;
u16 value;
value = bq25700_read(charger, BQ25700_CHARGERSTAUS_REG);
state_of_charger = value >> 15;
return state_of_charger;
}
static bool bq25703_charger_status(struct bq25700 *charger)
{
int state_of_charger;
u16 value;
value = bq25700_read(charger, BQ25703_CHARGERSTAUS_REG);
state_of_charger = value >> 15;
return state_of_charger;
}
static bool bq257xx_charger_status(struct udevice *dev)
{
struct bq25700 *charger = dev_get_priv(dev);
if (charger->chip_id == BQ25700_ID)
return bq25700_charger_status(charger);
else
return bq25703_charger_status(charger);
}
static int bq25700_charger_capability(struct udevice *dev)
{
return FG_CAP_CHARGER;
}
static int bq25700_get_usb_type(void)
{
#ifdef CONFIG_PHY_ROCKCHIP_INNO_USB2
return rockchip_chg_get_type();
#else
return 0;
#endif
}
static int bq25700_get_pd_output_val(struct bq25700 *charger,
int *vol, int *cur)
{
struct power_delivery_data pd_data;
int ret;
if (!charger->pd[0] && !charger->pd[1]) {
return -EINVAL;
}
memset(&pd_data, 0, sizeof(pd_data));
int i = 0;
for (i = 0; i < PD_MUN; i++) {
if (!charger->pd[i]) {
continue;
}
ret = power_delivery_get_data(charger->pd[i], &pd_data);
if (ret) {
continue;
}
if (!pd_data.online || !pd_data.voltage || !pd_data.current) {
continue;
}
*vol = pd_data.voltage;
*cur = pd_data.current;
printf("voltage is %d current is %d\n", *vol, *cur);
goto end;
}
return -EINVAL;
end:
return 0;
}
static void bq25703_charger_current_init(struct bq25700 *charger)
{
u16 charge_current = BQ25700_CHARGE_CURRENT_1500MA;
u16 sdp_inputcurrent = BQ25700_SDP_INPUT_CURRENT_500MA;
u16 dcp_inputcurrent = BQ25700_DCP_INPUT_CURRENT_1500MA;
int pd_inputvol, pd_inputcurrent;
u16 vol_idx = 0, cur_idx;
u16 temp;
temp = bq25700_read(charger, BQ25703_CHARGEOPTION0_REG);
temp &= (~WATCHDOG_ENSABLE);
bq25700_write(charger, BQ25703_CHARGEOPTION0_REG, temp);
if (!bq25700_get_pd_output_val(charger, &pd_inputvol,
&pd_inputcurrent)) {
if (pd_inputvol > 5000000) {
vol_idx = bq25700_find_idx(pd_inputvol - 1280000 - 3200000,
TBL_INPUTVOL);
vol_idx = vol_idx << 6;
}
cur_idx = bq25700_find_idx(pd_inputcurrent,
TBL_INPUTCUR);
cur_idx = cur_idx << 8;
if (pd_inputcurrent != 0)
{
bq25700_write(charger, BQ25703_INPUTCURREN_REG,
cur_idx);
if (vol_idx)
bq25700_write(charger, BQ25703_INPUTVOLTAGE_REG,
vol_idx);
charge_current = bq25700_find_idx(pd_inputcurrent,
TBL_ICHG);
charge_current = charge_current << 6;
}
} else {
bq25700_write(charger, BQ25703_INPUTCURREN_REG,
dcp_inputcurrent);
}
if (bq25703_charger_status(charger)) {
bq25700_write(charger, BQ25703_CHARGECURREN_REG,
charge_current);
}
}
static int bq25700_ofdata_to_platdata(struct udevice *dev)
{
struct bq25700 *charger = dev_get_priv(dev);
const void *blob = gd->fdt_blob;
int node, node1;
charger->dev = dev;
node = fdt_node_offset_by_compatible(blob, 0, COMPAT_BQ25700);
node1 = fdt_node_offset_by_compatible(blob, 0, COMPAT_BQ25703);
if ((node < 0) && (node1 < 0)) {
printf("Can't find dts node for charger bq25700\n");
return -ENODEV;
}
if (node < 0) {
node = node1;
charger->chip_id = BQ25703_ID;
} else {
charger->chip_id = BQ25700_ID;
}
return 0;
}
static int bq25700_probe(struct udevice *dev)
{
struct bq25700 *charger = dev_get_priv(dev);
int ret;
struct udevice *pd_tmp;
struct udevice *dev_tmp;
for (uclass_first_device(UCLASS_PD, &pd_tmp);
pd_tmp;
uclass_next_device(&pd_tmp))
{
dev_tmp = dev_get_parent(pd_tmp);
if (!strncmp(TYPEC0_I2C, dev_tmp->name, strlen(TYPEC0_I2C))) { // Ensure that typec0 has the highest priority
charger->pd[0] = pd_tmp;
} else if (!strncmp(TYPEC1_I2C, dev_tmp->name, strlen(TYPEC1_I2C))) {
charger->pd[1] = pd_tmp;
}
}
if (charger->chip_id == BQ25703_ID) {
bq25703_charger_current_init(charger);
}
return 0;
}
static const struct udevice_id charger_ids[] = {
{.compatible = "ti,bq25700"},
{.compatible = "ti,bq25703"},
{},
{ },
};
static struct dm_fuel_gauge_ops charger_ops = {
.get_chrg_online = bq257xx_charger_status,
.capability = bq25700_charger_capability,
};
U_BOOT_DRIVER(bq25700_charger) = {
.name = "bq25700_charger",
.id = UCLASS_FG,
.probe = bq25700_probe,
.of_match = charger_ids,
.ops = &charger_ops,
.ofdata_to_platdata = bq25700_ofdata_to_platdata,
.priv_auto_alloc_size = sizeof(struct bq25700),
};

366
drivers/power/charge_animation.c Executable file
View File

@@ -0,0 +1,366 @@
/*
* (C) Copyright 2017 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <asm/io.h>
#include <asm/gpio.h>
#include <common.h>
#include <console.h>
#include <dm.h>
#include <errno.h>
#include <led.h>
#include <rtc.h>
#include <pwm.h>
#include <power/charge_display.h>
#include <power/charge_animation.h>
#include <power/fuel_gauge.h>
#include <power/pmic.h>
#include <mcu/mcu-uclass.h>
#ifdef CONFIG_IRQ
#include <irq-generic.h>
#include <rk_timer_irq.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
#define IMAGE_RECALC_IDX -1
#define IMAGE_SOC_100_IDX(n) ((n) - 2)
#define IMAGE_LOWPOWER_IDX(n) ((n) - 1)
#define SYSTEM_SUSPEND_DELAY_MS 5000
#define FUEL_GAUGE_POLL_MS 1000
#define LED_CHARGING_NAME "battery_charging"
#define LED_CHARGING_FULL_NAME "battery_full"
#define LED_CHARGING_START_NAME "battery_start"
struct charge_image {
const char *name;
int soc;
int period; /* ms */
};
struct charge_animation_priv {
struct udevice *fg;
struct udevice *charger;
struct udevice *mcu;
#ifdef CONFIG_LED
struct udevice *led_charging;
struct udevice *led_full;
struct udevice *led_start;
#endif
const struct charge_image *image;
int image_num;
int auto_wakeup_key_state;
ulong auto_screen_off_timeout; /* ms */
ulong suspend_delay_timeout; /* ms */
};
struct gpio_desc powerkey_gpio;
static int leds_switch = 0;
#ifdef CONFIG_LED
static int leds_update(struct udevice *dev, int soc)
{
struct charge_animation_priv *priv = dev_get_priv(dev);
static int old_soc = -1;
int ret, ledst;
if (old_soc == soc)
return 0;
old_soc = soc;
if (priv->led_charging) {
ledst = (soc < 100) ? LEDST_ON : LEDST_OFF;
ret = led_set_state(priv->led_charging, ledst);
if (ret) {
printf("set charging led %s failed, ret=%d\n",
(ledst == LEDST_ON) ? "ON" : "OFF", ret);
return ret;
}
}
if (priv->led_full) {
ledst = (soc == 100) ? LEDST_ON : LEDST_OFF;
ret = led_set_state(priv->led_full, ledst);
if (ret) {
printf("set charging full led %s failed, ret=%d\n",
ledst == LEDST_ON ? "ON" : "OFF", ret);
return ret;
}
}
return 0;
}
static int leds_charge_on(struct udevice *dev, int soc)
{
struct charge_animation_priv *priv = dev_get_priv(dev);
int ret, ledst;
ledst = LEDST_ON;
ret = led_set_state(priv->led_full, ledst);
if (ret) {
printf("set charging full led %s failed, ret=%d\n",
ledst == LEDST_ON ? "ON" : "OFF", ret);
return ret;
}
return 0;
}
static int leds_charge_off(struct udevice *dev, int soc)
{
struct charge_animation_priv *priv = dev_get_priv(dev);
int ret, ledst;
ledst = LEDST_OFF;
ret = led_set_state(priv->led_charging, ledst);
if (ret) {
printf("set charging full led %s failed, ret=%d\n",
ledst == LEDST_ON ? "ON" : "OFF", ret);
return ret;
}
ret = led_set_state(priv->led_full, ledst);
if (ret) {
printf("set charging full led %s failed, ret=%d\n",
ledst == LEDST_ON ? "ON" : "OFF", ret);
return ret;
}
return 0;
}
static int leds_charge_update(struct udevice *dev, int soc)
{
struct charge_animation_priv *priv = dev_get_priv(dev);
int ret, ledst;
if (leds_switch > 5){
leds_charge_on(dev, soc);
} else {
leds_charge_off(dev, soc);
}
leds_switch++;
if (leds_switch > 10)
leds_switch = 0;
return 0;
}
#else
static int leds_update(struct udevice *dev, int soc) { return 0; }
static int leds_charge_on(struct udevice *dev, int soc) { return 0; }
static int leds_charge_off(struct udevice *dev, int soc) { return 0; }
static int leds_charge_update(struct udevice *dev, int soc) { return 0; }
#endif
static int charge_animation_ofdata_to_platdata(struct udevice *dev)
{
struct charge_animation_pdata *pdata = dev_get_platdata(dev);
pdata->low_power_voltage =
dev_read_u32_default(dev, "uboot-low-power-voltage", 0);
return 0;
}
static int fg_charger_get_chrg_online(struct udevice *dev)
{
struct charge_animation_priv *priv = dev_get_priv(dev);
struct udevice *charger;
charger = priv->charger ? : priv->fg;
return fuel_gauge_get_chrg_online(charger);
}
static int get_reboot_state(void){
const char *var_name = "battery_charge";
char *value = env_get(var_name);
if (value)
if (strcmp(value, "0") == 0) {
env_set(var_name, "1");
env_save();
return 0;
}
env_set(var_name, "1");
env_save();
return 1;
}
static int charge_animation_show(struct udevice *dev)
{
int soc, voltage, ret, charging = 0;
struct charge_animation_priv *priv = dev_get_priv(dev);
struct charge_animation_pdata *pdata = dev_get_platdata(dev);
struct udevice *fg = priv->fg;
struct udevice *mcu = priv->mcu;
voltage = fuel_gauge_get_voltage(fg);
if (voltage < 0)
return -EINVAL;
while (voltage < pdata->low_power_voltage + 50) {
soc = fuel_gauge_update_get_soc(fg);
if (soc < 0 || soc > 100) {
printf("get soc failed: %d\n", soc);
continue;
} else if (soc >= 1) {
printf("soc is: %d\n", soc);
break;
}
voltage = fuel_gauge_get_voltage(fg);
if (voltage < 0) {
printf("get voltage failed: %d\n", voltage);
continue;
}
ret = leds_update(dev, soc);
if (ret)
printf("update led failed: %d\n", ret);
printf("soc is: %d voltage is :%d\n", soc, voltage);
charging = fg_charger_get_chrg_online(dev);
if (charging <= 0) {
mcu_shutdown(); // shutdown system power
}
mdelay(100);
};
leds_charge_off(dev, soc);
ret = get_reboot_state();
charging = fg_charger_get_chrg_online(dev);
if (!(charging <= 0) && ret != 0)
while(1){
ret = dm_gpio_get_value(&powerkey_gpio);
if (ret == 0){
break;
}
charging = fg_charger_get_chrg_online(dev);
if (charging <= 0) {
mcu_shutdown(); // shutdown system power
}
soc = fuel_gauge_update_get_soc(fg);
if (soc == 100){
leds_charge_on(dev, soc);
}else if (soc < 100){
leds_charge_update(dev, soc);
}
mdelay(300);
}
leds_charge_off(dev, soc);
ret = led_set_state(priv->led_start, LEDST_ON);
if (!ret)
printf("Found Charging-Start LED\n");
return 0;
}
static int fg_charger_get_device(struct udevice **fuel_gauge,
struct udevice **charger)
{
struct udevice *dev;
struct uclass *uc;
int ret, cap;
*fuel_gauge = NULL,
*charger = NULL;
ret = uclass_get(UCLASS_FG, &uc);
if (ret)
return ret;
for (uclass_first_device(UCLASS_FG, &dev);
dev;
uclass_next_device(&dev)) {
cap = fuel_gauge_capability(dev);
if (cap == (FG_CAP_CHARGER | FG_CAP_FUEL_GAUGE)) {
*fuel_gauge = dev;
*charger = NULL;
} else if (cap == FG_CAP_FUEL_GAUGE) {
*fuel_gauge = dev;
} else if (cap == FG_CAP_CHARGER) {
*charger = dev;
}
}
return (*fuel_gauge) ? 0 : -ENODEV;
}
static const struct dm_charge_display_ops charge_animation_ops = {
.show = charge_animation_show,
};
static int charge_animation_probe(struct udevice *dev)
{
struct charge_animation_priv *priv = dev_get_priv(dev);
int ret, soc;
/* Get PMIC: used for power off system */
ret = uclass_get_device(UCLASS_MCU, 0, &priv->mcu);
if (ret) {
if (ret == -ENODEV)
printf("Can't find MCU\n");
else
printf("Get UCLASS MCU failed: %d\n", ret);
}
/* Get fuel gauge and charger(If need) */
ret = fg_charger_get_device(&priv->fg, &priv->charger);
if (ret) {
if (ret == -ENODEV)
debug("Can't find FG\n");
else
debug("Get UCLASS FG failed: %d\n", ret);
// return ret;
}
#ifdef CONFIG_LED
ret = led_get_by_label(LED_CHARGING_NAME, &priv->led_charging);
if (!ret)
printf("Found Charging LED \n");
ret = led_get_by_label(LED_CHARGING_FULL_NAME, &priv->led_full);
if (!ret)
printf("Found Charging-Full LED\n");
ret = led_get_by_label(LED_CHARGING_START_NAME, &priv->led_start);
if (!ret)
printf("Found Charging-Start LED\n");
#endif
ret = gpio_request_by_name(dev, "powerkey-gpio", 0, &powerkey_gpio, 0);
if (dm_gpio_is_valid(&powerkey_gpio)) {
dm_gpio_set_dir_flags(&powerkey_gpio, GPIOD_IS_IN);
}
printf("Enable charge animation display\n");
return 0;
}
static const struct udevice_id charge_animation_ids[] = {
{ .compatible = "rockchip,uboot-charge" },
{ },
};
U_BOOT_DRIVER(charge_animation) = {
.name = "charge-animation",
.id = UCLASS_CHARGE_DISPLAY,
.probe = charge_animation_probe,
.of_match = charge_animation_ids,
.ops = &charge_animation_ops,
.ofdata_to_platdata = charge_animation_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct charge_animation_pdata),
.priv_auto_alloc_size = sizeof(struct charge_animation_priv),
};

View File

@@ -0,0 +1,11 @@
config DM_FUEL_GAUGE
bool "Enable driver model fuel gauge support"
depends on DM
help
This adds a simple uclass for fuel gauge.
config POWER_FG_CW201X
bool "CW201X Fuel gauge support"
depends on DM_FUEL_GAUGE
help
This adds support for CW201X fuel gauge support.

View File

@@ -2,5 +2,6 @@
#
# Copyright (C) 2012 Samsung Electronics
# Lukasz Majewski <l.majewski@samsung.com>
obj-$(CONFIG_$(SPL_)DM_FUEL_GAUGE) += fuel_gauge_uclass.o
obj-$(CONFIG_POWER_FG_MAX17042) += fg_max17042.o
obj-$(CONFIG_POWER_FG_CW201X) += fg_cw201x.o

View File

@@ -0,0 +1,415 @@
/*
* (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/gpio.h>
#include <dm.h>
#include <dm/device.h>
#include <errno.h>
#include <fdtdec.h>
#include <i2c.h>
// #include <linux/usb/phy-rockchip-usb2.h>
#include <malloc.h>
#include <power/battery.h>
#include <power/fuel_gauge.h>
// #include <power/pmic.h>
#include "fg_regs.h"
DECLARE_GLOBAL_DATA_PTR;
#define COMPAT_ROCKCHIP_CW201X "cw201x"
#define REG_VERSION 0x0
#define REG_VCELL 0x2
#define REG_SOC 0x4
#define REG_RRT_ALERT 0x6
#define REG_CONFIG 0x8
#define REG_MODE 0xA
#define REG_BATINFO 0x10
#define MODE_SLEEP_MASK (0x3 << 6)
#define MODE_SLEEP (0x3 << 6)
#define MODE_NORMAL (0x0 << 6)
#define MODE_QUICK_START (0x3 << 4)
#define MODE_RESTART (0xf << 0)
#define CONFIG_UPDATE_FLG (0x1 << 1)
#define ATHD (0x0 << 3)
enum charger_type {
CHARGER_TYPE_NO = 0,
CHARGER_TYPE_USB,
CHARGER_TYPE_AC,
CHARGER_TYPE_DC,
CHARGER_TYPE_UNDEF,
};
struct cw201x_info {
struct udevice *dev;
int capacity;
u32 *cw_bat_config_info;
int divider_res1;
int divider_res2;
int hw_id_check;
struct gpio_desc hw_id0;
struct gpio_desc hw_id1;
int support_dc_adp;
struct gpio_desc dc_det_gpio;
int dc_det_flag;
bool dual_cell;
};
static u8 cw201x_read(struct cw201x_info *cw201x, u8 reg)
{
u8 val;
int ret;
ret = dm_i2c_read(cw201x->dev, reg, &val, 1);
if (ret) {
printf("write error to device: %p register: %#x!",
cw201x->dev, reg);
return ret;
}
return val;
}
static int cw201x_write(struct cw201x_info *cw201x, u8 reg, u8 val)
{
int ret;
ret = dm_i2c_write(cw201x->dev, reg, &val, 1);
if (ret) {
printf("write error to device: %p register: %#x!",
cw201x->dev, reg);
return ret;
}
return 0;
}
static u16 cw201x_read_half_word(struct cw201x_info *cw201x, int reg)
{
u8 vall, valh;
u16 val;
valh = cw201x_read(cw201x, reg);
vall = cw201x_read(cw201x, reg + 1);
val = ((u16)valh << 8) | vall;
return val;
}
static int cw201x_parse_config_info(struct cw201x_info *cw201x)
{
int ret;
int i, len, size;
const u8 *info;
struct udevice *dev = cw201x->dev;
if (dev_read_prop(dev, "bat_config_info", &len)) {
len /= sizeof(u32);
size = sizeof(*cw201x->cw_bat_config_info) * len;
cw201x->cw_bat_config_info = calloc(size, 1);
if (!cw201x->cw_bat_config_info) {
printf("calloc cw_bat_config_info fail\n");
return -EINVAL;
}
ret = dev_read_u32_array(dev, "bat_config_info",
cw201x->cw_bat_config_info, len);
if (ret) {
printf("fdtdec_get cw_bat_config_info fail\n");
return -EINVAL;
}
return 0;
}
if (!dev_read_prop(dev, "cellwise,battery-profile", &len))
return -EINVAL;
size = sizeof(*cw201x->cw_bat_config_info) * len;
cw201x->cw_bat_config_info = calloc(size, 1);
if (!cw201x->cw_bat_config_info) {
printf("calloc cw_bat_config_info fail\n");
return -EINVAL;
}
info = dev_read_u8_array_ptr(dev, "cellwise,battery-profile", len);
if (!info) {
printf("fdtdec_get battery profile fail\n");
return -EINVAL;
}
for (i = 0; i < len; i++) {
cw201x->cw_bat_config_info[i] = info[i];
printf("%#x ", cw201x->cw_bat_config_info[i]);
if ((i+1) % 8 == 0)
printf("\n");
}
return 0;
}
static int cw201x_ofdata_to_platdata(struct udevice *dev)
{
struct cw201x_info *cw201x = dev_get_priv(dev);
int ret;
int hw_id0_val, hw_id1_val;
cw201x->dev = dev;
ret = cw201x_parse_config_info(cw201x);
if (ret)
return ret;
cw201x->dual_cell = dev_read_bool(dev, "cellwise,dual-cell");
ret = gpio_request_by_name_nodev(dev_ofnode(dev), "dc_det_gpio",
0, &cw201x->dc_det_gpio, GPIOD_IS_IN);
if (!ret) {
cw201x->support_dc_adp = 1;
printf("DC is valid\n");
} else {
printf("DC is invalid, ret=%d\n", ret);
}
cw201x->hw_id_check = dev_read_u32_default(dev, "hw_id_check", 0);
if (cw201x->hw_id_check) {
ret = gpio_request_by_name_nodev(dev_ofnode(dev),
"hw_id0_gpio", 0,
&cw201x->hw_id0, GPIOD_IS_IN);
if (ret)
return -EINVAL;
hw_id0_val = dm_gpio_get_value(&cw201x->hw_id0);
ret = gpio_request_by_name_nodev(dev_ofnode(dev),
"hw_id1_gpio", 0,
&cw201x->hw_id1, GPIOD_IS_IN);
if (ret)
return -EINVAL;
hw_id1_val = dm_gpio_get_value(&cw201x->hw_id1);
/* ID1 = 0, ID0 = 1 : Battery */
if (!hw_id0_val || hw_id1_val)
return -EINVAL;
}
cw201x->divider_res1 = dev_read_u32_default(dev, "divider_res1", 0);
cw201x->divider_res2 = dev_read_u32_default(dev, "divider_res2", 0);
return 0;
}
static int cw201x_get_vol(struct cw201x_info *cw201x)
{
u16 value16, value16_1, value16_2, value16_3;
int voltage;
int res1, res2;
int retry = 0;
__retry:
value16 = cw201x_read_half_word(cw201x, REG_VCELL);
if (value16 < 0)
return -1;
value16_1 = cw201x_read_half_word(cw201x, REG_VCELL);
if (value16_1 < 0)
return -1;
value16_2 = cw201x_read_half_word(cw201x, REG_VCELL);
if (value16_2 < 0)
return -1;
if (value16 > value16_1) {
value16_3 = value16;
value16 = value16_1;
value16_1 = value16_3;
}
if (value16_1 > value16_2) {
value16_3 = value16_1;
value16_1 = value16_2;
value16_2 = value16_3;
}
if (value16 > value16_1) {
value16_3 = value16;
value16 = value16_1;
value16_1 = value16_3;
}
voltage = value16_1 * 312 / 1024;
if (voltage <= 0 && retry < 10) {
retry++;
mdelay(20);
goto __retry;
}
if (cw201x->divider_res1 &&
cw201x->divider_res2) {
res1 = cw201x->divider_res1;
res2 = cw201x->divider_res2;
voltage = voltage * (res1 + res2) / res2;
}
if (cw201x->dual_cell)
voltage *= 2;
// printf("the cw201x voltage=%d\n", voltage);
return voltage;
}
static int cw201x_dwc_otg_check_dpdm(void)
{
#if defined(CONFIG_PHY_ROCKCHIP_INNO_USB2) && !defined(CONFIG_SPL_BUILD)
return rockchip_chg_get_type();
#else
printf("rockchip_chg_get_type() is not implement\n");
return CHARGER_TYPE_NO;
#endif
}
static int cw201x_get_usb_state(struct cw201x_info *cw201x)
{
int charger_type;
switch (cw201x_dwc_otg_check_dpdm()) {
case 0:
charger_type = CHARGER_TYPE_NO;
break;
case 1:
case 3:
charger_type = CHARGER_TYPE_USB;
break;
case 2:
charger_type = CHARGER_TYPE_AC;
break;
default:
charger_type = CHARGER_TYPE_NO;
break;
}
return charger_type;
}
static bool cw201x_get_dc_state(struct cw201x_info *cw201x)
{
if (dm_gpio_get_value(&cw201x->dc_det_gpio))
return true;
return false;
}
static bool cw201x_check_charge(struct cw201x_info *cw201x)
{
if (cw201x_get_usb_state(cw201x) != CHARGER_TYPE_NO)
return true;
if (cw201x_get_dc_state(cw201x))
return true;
return false;
}
static int cw201x_get_soc(struct cw201x_info *cw201x)
{
int cap, i = 0;
while (i < 10) {
mdelay(30);
cap = cw201x_read(cw201x, REG_SOC);
if ((cap < 0) || (cap > 100))
cap = cw201x->capacity;
i++;
if (cap)
break;
}
cw201x->capacity = cap;
return cw201x->capacity;
}
static int cw201x_update_get_soc(struct udevice *dev)
{
struct cw201x_info *cw201x = dev_get_priv(dev);
return cw201x_get_soc(cw201x);
}
static int cw201x_update_get_voltage(struct udevice *dev)
{
struct cw201x_info *cw201x = dev_get_priv(dev);
return cw201x_get_vol(cw201x);
}
static int cw201x_update_get_current(struct udevice *dev)
{
return 0;
}
static bool cw201x_update_get_chrg_online(struct udevice *dev)
{
struct cw201x_info *cw201x = dev_get_priv(dev);
return cw201x_check_charge(cw201x);
}
static int cw201x_capability(struct udevice *dev)
{
return FG_CAP_FUEL_GAUGE;
}
static struct dm_fuel_gauge_ops cw201x_fg_ops = {
.capability = cw201x_capability,
.get_soc = cw201x_update_get_soc,
.get_voltage = cw201x_update_get_voltage,
.get_current = cw201x_update_get_current,
.get_chrg_online = cw201x_update_get_chrg_online,
};
static int cw201x_fg_cfg(struct cw201x_info *cw201x)
{
u8 val = MODE_SLEEP;
int i;
if ((val & MODE_SLEEP_MASK) == MODE_SLEEP) {
val = MODE_NORMAL;
cw201x_write(cw201x, REG_MODE, val);
}
for (i = 0; i < 64; i++) {
cw201x_write(cw201x, REG_BATINFO + i,
(u8)cw201x->cw_bat_config_info[i]);
}
return 0;
}
static int cw201x_fg_probe(struct udevice *dev)
{
struct cw201x_info *cw201x = dev_get_priv(dev);
cw201x->dev = dev;
cw201x_fg_cfg(cw201x);
printf("vol: %d, soc: %d\n",
cw201x_get_vol(cw201x), cw201x_get_soc(cw201x));
return 0;
}
static const struct udevice_id cw201x_ids[] = {
{ .compatible = "cw201x" },
{ .compatible = "cellwise,cw2015" },
{ }
};
U_BOOT_DRIVER(cw201x_fg) = {
.name = "cw201x_fg",
.id = UCLASS_FG,
.of_match = cw201x_ids,
.probe = cw201x_fg_probe,
.ofdata_to_platdata = cw201x_ofdata_to_platdata,
.ops = &cw201x_fg_ops,
.priv_auto_alloc_size = sizeof(struct cw201x_info),
};

View File

@@ -0,0 +1,95 @@
/*
* (C) Copyright 2017 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _FG_RK8XX_H_
#define _FG_RK8XX_H_
/* register definition */
#define SECONDS_REG 0X00
#define VB_MON_REG 0x21
#define THERMAL_REG 0x22
#define SUP_STS_REG 0xA0
#define USB_CTRL_REG 0xA1
#define CHRG_CTRL_REG1 0xA3
#define CHRG_CTRL_REG2 0xA4
#define CHRG_CTRL_REG3 0xA5
#define BAT_CTRL_REG 0xA6
#define BAT_HTS_TS_REG 0xA8
#define BAT_LTS_TS_REG 0xA9
#define TS_CTRL_REG 0xAC
#define ADC_CTRL_REG 0xAD
#define GGCON_REG 0xB0
#define GGSTS_REG 0xB1
#define ZERO_CUR_ADC_REGH 0xB2
#define ZERO_CUR_ADC_REGL 0xB3
#define GASCNT_CAL_REG3 0xB4
#define GASCNT_CAL_REG2 0xB5
#define GASCNT_CAL_REG1 0xB6
#define GASCNT_CAL_REG0 0xB7
#define GASCNT_REG3 0xB8
#define GASCNT_REG2 0xB9
#define GASCNT_REG1 0xBA
#define GASCNT_REG0 0xBB
#define BAT_CUR_AVG_REGH 0xBC
#define BAT_CUR_AVG_REGL 0xBD
#define TS_ADC_REGH 0xBE
#define TS_ADC_REGL 0xBF
#define RK818_TS2_ADC_REGH 0xC0
#define RK818_TS2_ADC_REGL 0xC1
#define RK816_USB_ADC_REGH 0xC0
#define RK816_USB_ADC_REGL 0xC1
#define BAT_OCV_REGH 0xC2
#define BAT_OCV_REGL 0xC3
#define BAT_VOL_REGH 0xC4
#define BAT_VOL_REGL 0xC5
#define RELAX_ENTRY_THRES_REGH 0xC6
#define RELAX_ENTRY_THRES_REGL 0xC7
#define RELAX_EXIT_THRES_REGH 0xC8
#define RELAX_EXIT_THRES_REGL 0xC9
#define RELAX_VOL1_REGH 0xCA
#define RELAX_VOL1_REGL 0xCB
#define RELAX_VOL2_REGH 0xCC
#define RELAX_VOL2_REGL 0xCD
#define RELAX_CUR1_REGH 0xCE
#define RELAX_CUR1_REGL 0xCF
#define RELAX_CUR2_REGH 0xD0
#define RELAX_CUR2_REGL 0xD1
#define CAL_OFFSET_REGH 0xD2
#define CAL_OFFSET_REGL 0xD3
#define NON_ACT_TIMER_CNT_REG 0xD4
#define VCALIB0_REGH 0xD5
#define VCALIB0_REGL 0xD6
#define VCALIB1_REGH 0xD7
#define VCALIB1_REGL 0xD8
#define FCC_GASCNT_REG3 0xD9
#define FCC_GASCNT_REG2 0xDA
#define FCC_GASCNT_REG1 0xDB
#define FCC_GASCNT_REG0 0xDC
#define IOFFSET_REGH 0xDD
#define IOFFSET_REGL 0xDE
#define SLEEP_CON_SAMP_CUR_REG 0xDF
#define SOC_REG 0xE0
#define REMAIN_CAP_REG3 0xE1
#define REMAIN_CAP_REG2 0xE2
#define REMAIN_CAP_REG1 0xE3
#define REMAIN_CAP_REG0 0xE4
#define UPDAT_LEVE_REG 0xE5
#define NEW_FCC_REG3 0xE6
#define NEW_FCC_REG2 0xE7
#define NEW_FCC_REG1 0xE8
#define NEW_FCC_REG0 0xE9
#define NON_ACT_TIMER_CNT_SAVE_REG 0xEA
#define OCV_VOL_VALID_REG 0xEB
#define REBOOT_CNT_REG 0xEC
#define POFFSET_REG 0xED
#define MISC_MARK_REG 0xEE
#define HALT_CNT_REG 0xEF
#define DATA15_REG 0xEF
#define DATA16_REG 0xF0
#define DATA17_REG 0xF1
#define DATA18_REG 0xF2
#endif

View File

@@ -0,0 +1,136 @@
/*
* (C) Copyright 2017 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <errno.h>
#include <dm.h>
#include <power/fuel_gauge.h>
DECLARE_GLOBAL_DATA_PTR;
int fuel_gauge_capability(struct udevice *dev)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->capability)
return (FG_CAP_CHARGER | FG_CAP_FUEL_GAUGE);
return ops->capability(dev);
}
int fuel_gauge_bat_is_exist(struct udevice *dev)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->bat_is_exist)
return -ENOSYS;
return ops->bat_is_exist(dev);
}
int fuel_gauge_get_current(struct udevice *dev)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_current)
return -ENOSYS;
return ops->get_current(dev);
}
int fuel_gauge_get_voltage(struct udevice *dev)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_voltage)
return -ENOSYS;
return ops->get_voltage(dev);
}
int fuel_gauge_update_get_soc(struct udevice *dev)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_soc)
return -ENOSYS;
return ops->get_soc(dev);
}
bool fuel_gauge_get_chrg_online(struct udevice *dev)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_chrg_online)
return -ENOSYS;
return ops->get_chrg_online(dev);
}
int fuel_gauge_get_temperature(struct udevice *dev, int *temp)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_temperature)
return -ENOSYS;
return ops->get_temperature(dev, temp);
}
int charger_set_charger_voltage(struct udevice *dev, int uV)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->set_charger_voltage)
return -ENOSYS;
return ops->set_charger_voltage(dev, uV);
}
int charger_set_current(struct udevice *dev, int ichrg_uA)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->set_charger_current)
return -ENOSYS;
return ops->set_charger_current(dev, ichrg_uA);
}
int charger_set_iprechg_current(struct udevice *dev, int iprechrg_uA)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->set_iprechg_current)
return -ENOSYS;
return ops->set_iprechg_current(dev, iprechrg_uA);
}
int charger_set_enable(struct udevice *dev)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->set_charger_enable)
return -ENOSYS;
return ops->set_charger_enable(dev);
}
int charger_set_disable(struct udevice *dev)
{
const struct dm_fuel_gauge_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->set_charger_disable)
return -ENOSYS;
return ops->set_charger_disable(dev);
}
UCLASS_DRIVER(fuel_guage) = {
.id = UCLASS_FG,
.name = "fuel_gauge",
};

View File

@@ -0,0 +1,45 @@
# SPDX-License-Identifier: GPL-2.0
config DM_POWER_DELIVERY
bool "Enable driver model power delivery support"
depends on DM
help
This adds a simple uclass for power delivery.
config TYPEC_TCPM
tristate "USB Type-C Port Controller Manager"
depends on DM && DM_POWER_DELIVERY
help
The Type-C Port Controller Manager provides a USB PD and USB Type-C
state machine for use with Type-C Port Controllers.
config TYPEC_TCPCI
tristate "Type-C Port Controller Interface driver"
depends on DM && DM_POWER_DELIVERY && DM_I2C
help
Type-C Port Controller driver for TCPCI-compliant controller.
config RV_BOOK
tristate "RV Book Type-C support"
help
Enable support for rvbook device's Type-C Port Controller.
if TYPEC_TCPCI
config TYPEC_HUSB311
tristate "Hynetek HUSB311 Type-C chip driver"
depends on DM && DM_POWER_DELIVERY && DM_I2C
help
Hynetek HUSB311 Type-C chip driver that works with
Type-C Port Controller Manager to provide USB PD and USB
Type-C functionalities.
endif # TYPEC_TCPCI
config TYPEC_FUSB302
tristate "Fairchild FUSB302 Type-C chip driver"
depends on DM && DM_POWER_DELIVERY && DM_I2C
help
The Fairchild FUSB302 Type-C chip driver that works with
Type-C Port Controller Manager to provide USB PD and USB
Type-C functionalities.

View File

@@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_$(SPL_)DM_POWER_DELIVERY) += power_delivery_uclass.o
obj-$(CONFIG_TYPEC_TCPM) += tcpm.o
obj-$(CONFIG_TYPEC_FUSB302) += fusb302.o
obj-$(CONFIG_TYPEC_TCPCI) += tcpci.o
obj-$(CONFIG_TYPEC_HUSB311) += tcpci_husb311.o

View File

@@ -0,0 +1,31 @@
/*
* (C) Copyright 2022 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <errno.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <power/power_delivery/power_delivery.h>
DECLARE_GLOBAL_DATA_PTR;
int power_delivery_get_data(struct udevice *dev, struct power_delivery_data *pd_data)
{
const struct dm_power_delivery_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_current || !ops->get_voltage || !ops->get_online)
return -ENOSYS;
pd_data->voltage = ops->get_voltage(dev);
pd_data->current = ops->get_current(dev);
pd_data->online = ops->get_online(dev);
return 0;
}
UCLASS_DRIVER(power_delivery) = {
.id = UCLASS_PD,
.name = "power_delivery",
};

View File

@@ -0,0 +1,778 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2015-2017 Google, Inc
*
* USB Type-C Port Controller Interface.
*/
#include <dm.h>
#include <i2c.h>
#include <asm/gpio.h>
#include <power/power_delivery/pd.h>
#include <power/power_delivery/tcpm.h>
#include <power/power_delivery/typec.h>
#include <power/power_delivery/power_delivery.h>
#include "tcpci.h"
#define PD_RETRY_COUNT 3
#define tcpc_presenting_cc1_rd(reg) \
(!(TCPC_ROLE_CTRL_DRP & (reg)) && \
(((reg) & (TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT)) == \
(TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT)))
#define tcpc_presenting_cc2_rd(reg) \
(!(TCPC_ROLE_CTRL_DRP & (reg)) && \
(((reg) & (TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT)) == \
(TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT)))
struct tcpci {
struct udevice *dev;
struct tcpm_port *port;
bool controls_vbus;
bool gpio_cc_int_present;
struct tcpc_dev tcpc;
struct tcpci_data *data;
struct gpio_desc gpio_cc_int;
};
struct tcpci_chip {
struct udevice *udev;
struct tcpci *tcpci;
struct tcpci_data data;
};
static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc)
{
return container_of(tcpc, struct tcpci, tcpc);
}
static int tcpci_read16(struct tcpci *tcpci, unsigned int reg, u16 *val)
{
int ret = 0;
u8 buffer[2];
ret = dm_i2c_read(tcpci->dev, reg, buffer, 2);
if (ret) {
printf("%s: cannot read %02x, ret=%d\n",
__func__, reg, ret);
return ret;
}
*val = ((buffer[1] << 8) & 0xFF00) | (buffer[0] & 0xFF);
return ret;
}
static int tcpci_block_read(struct tcpci *tcpci, unsigned int reg,
u8 *data, u8 length)
{
int ret = 0;
ret = dm_i2c_read(tcpci->dev, reg, data, length);
if (ret)
printf("%s: cannot block read 0x%02x, len=%d, ret=%d\n",
__func__, reg, length, ret);
return ret;
}
static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val)
{
int ret = 0;
u8 buffer[2];
buffer[0] = val & 0xFF;
buffer[1] = (val >> 8) & 0xFF;
ret = dm_i2c_write(tcpci->dev, reg, buffer, 2);
if (ret)
printf("%s: cannot write 0x%02x, ret=%d\n",
__func__, reg, ret);
return ret;
}
static int tcpci_block_write(struct tcpci *tcpci, unsigned int reg,
u8 *data, u8 length)
{
int ret = 0;
ret = dm_i2c_write(tcpci->dev, reg, data, length);
if (ret)
printf("%s: cannot block write 0x%02x, len=%d, ret=%d\n",
__func__, reg, length, ret);
return ret;
}
static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int reg;
int ret;
switch (cc) {
case TYPEC_CC_RA:
reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) |
(TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC2_SHIFT);
break;
case TYPEC_CC_RD:
reg = (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) |
(TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT);
break;
case TYPEC_CC_RP_DEF:
reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
(TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) |
(TCPC_ROLE_CTRL_RP_VAL_DEF <<
TCPC_ROLE_CTRL_RP_VAL_SHIFT);
break;
case TYPEC_CC_RP_1_5:
reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
(TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) |
(TCPC_ROLE_CTRL_RP_VAL_1_5 <<
TCPC_ROLE_CTRL_RP_VAL_SHIFT);
break;
case TYPEC_CC_RP_3_0:
reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
(TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) |
(TCPC_ROLE_CTRL_RP_VAL_3_0 <<
TCPC_ROLE_CTRL_RP_VAL_SHIFT);
break;
case TYPEC_CC_OPEN:
default:
reg = (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT) |
(TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT);
break;
}
ret = dm_i2c_reg_write(tcpci->dev, TCPC_ROLE_CTRL, reg);
if (ret)
return ret;
return 0;
}
static int tcpci_start_toggling(struct tcpc_dev *tcpc,
enum typec_port_type port_type,
enum typec_cc_status cc)
{
int ret;
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int reg = TCPC_ROLE_CTRL_DRP;
if (port_type != TYPEC_PORT_DRP)
return -EOPNOTSUPP;
/* Handle vendor drp toggling */
if (tcpci->data->start_drp_toggling) {
ret = tcpci->data->start_drp_toggling(tcpci, tcpci->data, cc);
if (ret < 0)
return ret;
}
switch (cc) {
default:
case TYPEC_CC_RP_DEF:
reg |= (TCPC_ROLE_CTRL_RP_VAL_DEF <<
TCPC_ROLE_CTRL_RP_VAL_SHIFT);
break;
case TYPEC_CC_RP_1_5:
reg |= (TCPC_ROLE_CTRL_RP_VAL_1_5 <<
TCPC_ROLE_CTRL_RP_VAL_SHIFT);
break;
case TYPEC_CC_RP_3_0:
reg |= (TCPC_ROLE_CTRL_RP_VAL_3_0 <<
TCPC_ROLE_CTRL_RP_VAL_SHIFT);
break;
}
if (cc == TYPEC_CC_RD)
reg |= (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) |
(TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT);
else
reg |= (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
(TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT);
ret = dm_i2c_reg_write(tcpci->dev, TCPC_ROLE_CTRL, reg);
if (ret < 0)
return ret;
return dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
TCPC_CMD_LOOK4CONNECTION);
}
static enum typec_cc_status tcpci_to_typec_cc(unsigned int cc, bool sink)
{
switch (cc) {
case 0x1:
return sink ? TYPEC_CC_RP_DEF : TYPEC_CC_RA;
case 0x2:
return sink ? TYPEC_CC_RP_1_5 : TYPEC_CC_RD;
case 0x3:
if (sink)
return TYPEC_CC_RP_3_0;
/* fall through */
case 0x0:
default:
return TYPEC_CC_OPEN;
}
}
static int tcpci_get_cc(struct tcpc_dev *tcpc,
enum typec_cc_status *cc1, enum typec_cc_status *cc2)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int reg, role_control;
role_control = dm_i2c_reg_read(tcpci->dev, TCPC_ROLE_CTRL);
if (role_control < 0)
return role_control;
reg = dm_i2c_reg_read(tcpci->dev, TCPC_CC_STATUS);
if (reg < 0)
return reg;
*cc1 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC1_SHIFT) &
TCPC_CC_STATUS_CC1_MASK,
reg & TCPC_CC_STATUS_TERM ||
tcpc_presenting_cc1_rd(role_control));
*cc2 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC2_SHIFT) &
TCPC_CC_STATUS_CC2_MASK,
reg & TCPC_CC_STATUS_TERM ||
tcpc_presenting_cc2_rd(role_control));
return 0;
}
static int tcpci_set_polarity(struct tcpc_dev *tcpc,
enum typec_cc_polarity polarity)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int reg;
int ret;
enum typec_cc_status cc1, cc2;
/* Obtain Rp setting from role control */
reg = dm_i2c_reg_read(tcpci->dev, TCPC_ROLE_CTRL);
if (reg < 0)
return reg;
ret = tcpci_get_cc(tcpc, &cc1, &cc2);
if (ret < 0)
return ret;
/*
* When port has drp toggling enabled, ROLE_CONTROL would only have the initial
* terminations for the toggling and does not indicate the final cc
* terminations when ConnectionResult is 0 i.e. drp toggling stops and
* the connection is resolbed. Infer port role from TCPC_CC_STATUS based on the
* terminations seen. The port role is then used to set the cc terminations.
*/
if (reg & TCPC_ROLE_CTRL_DRP) {
/* Disable DRP for the OPEN setting to take effect */
reg = reg & ~TCPC_ROLE_CTRL_DRP;
if (polarity == TYPEC_POLARITY_CC2) {
reg &= ~(TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT);
/* Local port is source */
if (cc2 == TYPEC_CC_RD)
/* Role control would have the Rp setting when DRP was enabled */
reg |= TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT;
else
reg |= TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT;
} else {
reg &= ~(TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT);
/* Local port is source */
if (cc1 == TYPEC_CC_RD)
/* Role control would have the Rp setting when DRP was enabled */
reg |= TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT;
else
reg |= TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT;
}
}
if (polarity == TYPEC_POLARITY_CC2)
reg |= TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT;
else
reg |= TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT;
ret = dm_i2c_reg_write(tcpci->dev, TCPC_ROLE_CTRL, reg);
if (ret < 0)
return ret;
return dm_i2c_reg_write(tcpci->dev, TCPC_TCPC_CTRL,
(polarity == TYPEC_POLARITY_CC2) ?
TCPC_TCPC_CTRL_ORIENTATION : 0);
}
static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
int ret;
unsigned int reg;
/* Handle vendor set vconn */
if (tcpci->data->set_vconn) {
ret = tcpci->data->set_vconn(tcpci, tcpci->data, enable);
if (ret < 0)
return ret;
}
reg = dm_i2c_reg_read(tcpci->dev, TCPC_POWER_CTRL);
if (reg)
return reg;
reg &= ~TCPC_POWER_CTRL_VCONN_ENABLE;
reg |= enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0;
return dm_i2c_reg_write(tcpci->dev, TCPC_POWER_CTRL, reg);
}
static int tcpci_set_roles(struct tcpc_dev *tcpc, bool attached,
enum typec_role role, enum typec_data_role data)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int reg;
int ret;
reg = PD_REV20 << TCPC_MSG_HDR_INFO_REV_SHIFT;
if (role == TYPEC_SOURCE)
reg |= TCPC_MSG_HDR_INFO_PWR_ROLE;
if (data == TYPEC_HOST)
reg |= TCPC_MSG_HDR_INFO_DATA_ROLE;
ret = dm_i2c_reg_write(tcpci->dev, TCPC_MSG_HDR_INFO, reg);
if (ret < 0)
return ret;
return 0;
}
static int tcpci_set_pd_rx(struct tcpc_dev *tcpc, bool enable)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int reg = 0;
int ret;
if (enable)
reg = TCPC_RX_DETECT_SOP | TCPC_RX_DETECT_HARD_RESET;
ret = dm_i2c_reg_write(tcpci->dev, TCPC_RX_DETECT, reg);
if (ret < 0)
return ret;
return 0;
}
static int tcpci_get_vbus(struct tcpc_dev *tcpc)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int reg;
reg = dm_i2c_reg_read(tcpci->dev, TCPC_POWER_STATUS);
if (reg < 0)
return reg;
return !!(reg & TCPC_POWER_STATUS_VBUS_PRES);
}
static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
int ret;
/* Disable both source and sink first before enabling anything */
if (!source) {
ret = dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
TCPC_CMD_DISABLE_SRC_VBUS);
if (ret < 0)
return ret;
}
if (!sink) {
ret = dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
TCPC_CMD_DISABLE_SINK_VBUS);
if (ret < 0)
return ret;
}
if (source) {
ret = dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
TCPC_CMD_SRC_VBUS_DEFAULT);
if (ret < 0)
return ret;
}
if (sink) {
ret = dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
TCPC_CMD_SINK_VBUS);
if (ret < 0)
return ret;
}
return 0;
}
static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
enum tcpm_transmit_type type,
const struct pd_message *msg,
unsigned int negotiated_rev)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
u16 header = msg ? le16_to_cpu(msg->header) : 0;
unsigned int reg, cnt;
int ret;
cnt = msg ? pd_header_cnt(header) * 4 : 0;
ret = dm_i2c_reg_write(tcpci->dev, TCPC_TX_BYTE_CNT, cnt + 2);
if (ret < 0)
return ret;
ret = tcpci_write16(tcpci, TCPC_TX_HDR, header);
if (ret < 0)
return ret;
if (cnt > 0) {
ret = tcpci_block_write(tcpci, TCPC_TX_DATA,
(u8 *)&msg->payload, cnt);
if (ret < 0)
return ret;
}
reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) |
(type << TCPC_TRANSMIT_TYPE_SHIFT);
ret = dm_i2c_reg_write(tcpci->dev, TCPC_TRANSMIT, reg);
if (ret < 0)
return ret;
return 0;
}
static int tcpci_init(struct tcpc_dev *tcpc)
{
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int timeout = 0; /* XXX */
unsigned int reg;
int ret;
while (timeout < 100) {
reg = dm_i2c_reg_read(tcpci->dev, TCPC_POWER_STATUS);
if (reg < 0)
return reg;
if (!(reg & TCPC_POWER_STATUS_UNINIT))
break;
timeout++;
udelay(200);
}
if (timeout >= 100)
return -ETIMEDOUT;
/* Handle vendor init */
if (tcpci->data->init) {
ret = tcpci->data->init(tcpci, tcpci->data);
if (ret < 0)
return ret;
}
/* Clear all events */
ret = tcpci_write16(tcpci, TCPC_ALERT, 0xffff);
if (ret < 0)
return ret;
if (tcpci->controls_vbus)
reg = TCPC_POWER_STATUS_VBUS_PRES;
else
reg = 0;
ret = dm_i2c_reg_write(tcpci->dev, TCPC_POWER_STATUS_MASK, reg);
if (ret < 0)
return ret;
/* Enable Vbus detection */
ret = dm_i2c_reg_write(tcpci->dev, TCPC_COMMAND,
TCPC_CMD_ENABLE_VBUS_DETECT);
if (ret < 0)
return ret;
reg = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_FAILED |
TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_RX_STATUS |
TCPC_ALERT_RX_HARD_RST | TCPC_ALERT_CC_STATUS;
if (tcpci->controls_vbus)
reg |= TCPC_ALERT_POWER_STATUS;
return tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
}
static void tcpci_poll_event(struct tcpc_dev *tcpc)
{
u16 status;
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
tcpci_read16(tcpci, TCPC_ALERT, &status);
/*
* Clear alert status for everything except RX_STATUS, which shouldn't
* be cleared until we have successfully retrieved message.
*/
if (status & ~TCPC_ALERT_RX_STATUS)
tcpci_write16(tcpci, TCPC_ALERT,
status & ~TCPC_ALERT_RX_STATUS);
if (status & TCPC_ALERT_CC_STATUS)
tcpm_cc_change(tcpci->port);
if (status & TCPC_ALERT_POWER_STATUS) {
unsigned int reg;
reg = dm_i2c_reg_read(tcpci->dev, TCPC_POWER_STATUS_MASK);
if (reg < 0)
return;
/*
* If power status mask has been reset, then the TCPC
* has reset.
*/
if (reg == 0xff)
tcpm_tcpc_reset(tcpci->port);
else
tcpm_vbus_change(tcpci->port);
}
if (status & TCPC_ALERT_RX_STATUS) {
struct pd_message msg;
unsigned int cnt, payload_cnt;
u16 header;
cnt = dm_i2c_reg_read(tcpci->dev, TCPC_RX_BYTE_CNT);
if (cnt < 0)
return;
/*
* 'cnt' corresponds to READABLE_BYTE_COUNT in section 4.4.14
* of the TCPCI spec [Rev 2.0 Ver 1.0 October 2017] and is
* defined in table 4-36 as one greater than the number of
* bytes received. And that number includes the header. So:
*/
if (cnt > 3)
payload_cnt = cnt - (1 + sizeof(msg.header));
else
payload_cnt = 0;
tcpci_read16(tcpci, TCPC_RX_HDR, &header);
msg.header = cpu_to_le16(header);
if ((payload_cnt > sizeof(msg.payload)))
payload_cnt = sizeof(msg.payload);
if (payload_cnt > 0)
tcpci_block_read(tcpci, TCPC_RX_DATA,
(u8 *)&msg.payload, payload_cnt);
/* Read complete, clear RX status alert bit */
tcpci_write16(tcpci, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
tcpm_pd_receive(tcpci->port, &msg);
}
if (status & TCPC_ALERT_RX_HARD_RST)
tcpm_pd_hard_reset(tcpci->port);
if (status & TCPC_ALERT_TX_SUCCESS)
tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_SUCCESS);
else if (status & TCPC_ALERT_TX_DISCARDED)
tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_DISCARDED);
else if (status & TCPC_ALERT_TX_FAILED)
tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_FAILED);
}
static int tcpci_enter_low_power_mode(struct tcpc_dev *tcpc,
bool attached, bool pd_capable)
{
int ret;
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
unsigned int reg;
/* Disable chip interrupts before unregistering port */
ret = tcpci_write16(tcpci, TCPC_ALERT_MASK, 0);
if (ret < 0)
return ret;
reg = dm_i2c_reg_read(tcpci->dev, TCPC_BMCIO_CTRL);
if (reg < 0)
return reg;
/*
* For Type-C devices with PD capability, Only disable VBUS detect,
* do not diable 24M oscillator for BMC communication. Otherwise,
* data packets cannot be received.
*/
if (attached && pd_capable)
reg &= ~TCPC_BMCIO_VBUS_DETECT_MASK;
else
reg &= ~(TCPC_BMCIO_VBUS_DETECT_MASK | TCPC_BMCIO_24M_OSC_MASK);
return dm_i2c_reg_write(tcpci->dev, TCPC_BMCIO_CTRL, reg);
}
static int tcpci_parse_config(struct tcpci *tcpci)
{
tcpci->controls_vbus = true; /* XXX */
tcpci->tcpc.connector_node = dev_read_subnode(tcpci->dev, "connector");
if (!ofnode_valid(tcpci->tcpc.connector_node)) {
printf("%s: 'connector' node is not found\n", __func__);
return -EINVAL;
}
return 0;
}
struct tcpci *tcpci_register_port(struct udevice *dev, struct tcpci_data *data)
{
struct tcpci *tcpci;
int err;
tcpci = devm_kzalloc(dev, sizeof(*tcpci), GFP_KERNEL);
if (!tcpci)
return ERR_PTR(-ENOMEM);
err = gpio_request_by_name(dev, "int-n-gpios", 0, &tcpci->gpio_cc_int, GPIOD_IS_IN);
if (err) {
printf("%s: fail to get int GPIO: err=%d\n", __func__, err);
tcpci->gpio_cc_int_present = false;
} else {
printf("%s: success to get int GPIO: err=%d\n", __func__, err);
tcpci->gpio_cc_int_present = true;
}
tcpci->dev = dev;
tcpci->data = data;
tcpci->tcpc.init = tcpci_init;
tcpci->tcpc.get_vbus = tcpci_get_vbus;
tcpci->tcpc.set_vbus = tcpci_set_vbus;
tcpci->tcpc.set_cc = tcpci_set_cc;
tcpci->tcpc.get_cc = tcpci_get_cc;
tcpci->tcpc.set_polarity = tcpci_set_polarity;
tcpci->tcpc.set_vconn = tcpci_set_vconn;
tcpci->tcpc.start_toggling = tcpci_start_toggling;
tcpci->tcpc.set_pd_rx = tcpci_set_pd_rx;
tcpci->tcpc.set_roles = tcpci_set_roles;
tcpci->tcpc.pd_transmit = tcpci_pd_transmit;
tcpci->tcpc.poll_event = tcpci_poll_event;
tcpci->tcpc.enter_low_power_mode = tcpci_enter_low_power_mode;
err = tcpci_parse_config(tcpci);
if (err < 0)
return ERR_PTR(err);
tcpci->port = tcpm_port_init(tcpci->dev, &tcpci->tcpc);
if (IS_ERR(tcpci->port)) {
printf("%s: failed to tcpm port init\n", __func__);
return ERR_CAST(tcpci->port);
}
// tcpm_tcpc_reset(tcpci->port);
tcpm_poll_event(tcpci->port);
return tcpci;
}
EXPORT_SYMBOL_GPL(tcpci_register_port);
void tcpci_unregister_port(struct tcpci *tcpci)
{
tcpm_uninit_port(tcpci->port);
}
EXPORT_SYMBOL_GPL(tcpci_unregister_port);
int tcpci_get_voltage_fun(struct tcpci *tcpci)
{
return tcpm_get_voltage(tcpci->port);
}
EXPORT_SYMBOL_GPL(tcpci_get_voltage_fun);
int tcpci_get_current_fun(struct tcpci *tcpci)
{
return tcpm_get_current(tcpci->port);
}
EXPORT_SYMBOL_GPL(tcpci_get_current_fun);
int tcpci_get_online_fun(struct tcpci *tcpci)
{
return tcpm_get_online(tcpci->port);
}
EXPORT_SYMBOL_GPL(tcpci_get_online_fun);
static int tcpci_probe(struct udevice *dev)
{
struct tcpci_chip *chip = dev_get_priv(dev);
int err;
u16 val = 0;
chip->udev = dev;
/* Disable chip interrupts before requesting irq */
err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, val);
if (err < 0)
return err;
chip->tcpci = tcpci_register_port(chip->udev, &chip->data);
if (IS_ERR(chip->tcpci))
return PTR_ERR(chip->tcpci);
return 0;
}
static int tcpci_remove(struct udevice *dev)
{
struct tcpci_chip *chip = dev_get_priv(dev);
int err;
/* Disable chip interrupts before unregistering port */
err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, 0);
if (err < 0)
return err;
tcpci_unregister_port(chip->tcpci);
return 0;
}
static int tcpci_get_voltage(struct udevice *dev)
{
struct tcpci_chip *chip = dev_get_priv(dev);
return tcpm_get_voltage(chip->tcpci->port);
}
static int tcpci_get_current(struct udevice *dev)
{
struct tcpci_chip *chip = dev_get_priv(dev);
return tcpm_get_current(chip->tcpci->port);
}
static int tcpci_get_online(struct udevice *dev)
{
struct tcpci_chip *chip = dev_get_priv(dev);
return tcpm_get_online(chip->tcpci->port);
}
static struct dm_power_delivery_ops tcpci_ops = {
.get_voltage = tcpci_get_voltage,
.get_current = tcpci_get_current,
.get_online = tcpci_get_online,
};
static const struct udevice_id tcpci_ids[] = {
{ .compatible = "nxp,ptn5110", },
{},
};
U_BOOT_DRIVER(tcpci) = {
.name = "tcpci",
.id = UCLASS_PD,
.of_match = tcpci_ids,
.ops = &tcpci_ops,
.probe = tcpci_probe,
.remove = tcpci_remove,
.priv_auto_alloc_size = sizeof(struct tcpci_chip),
}
MODULE_DESCRIPTION("USB Type-C Port Controller Interface driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,150 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2015-2017 Google, Inc
*
* USB Type-C Port Controller Interface.
*/
#ifndef __LINUX_USB_TCPCI_H
#define __LINUX_USB_TCPCI_H
#define TCPC_VENDOR_ID 0x0
#define TCPC_PRODUCT_ID 0x2
#define TCPC_BCD_DEV 0x4
#define TCPC_TC_REV 0x6
#define TCPC_PD_REV 0x8
#define TCPC_PD_INT_REV 0xa
#define TCPC_ALERT 0x10
#define TCPC_ALERT_VBUS_DISCNCT BIT(11)
#define TCPC_ALERT_RX_BUF_OVF BIT(10)
#define TCPC_ALERT_FAULT BIT(9)
#define TCPC_ALERT_V_ALARM_LO BIT(8)
#define TCPC_ALERT_V_ALARM_HI BIT(7)
#define TCPC_ALERT_TX_SUCCESS BIT(6)
#define TCPC_ALERT_TX_DISCARDED BIT(5)
#define TCPC_ALERT_TX_FAILED BIT(4)
#define TCPC_ALERT_RX_HARD_RST BIT(3)
#define TCPC_ALERT_RX_STATUS BIT(2)
#define TCPC_ALERT_POWER_STATUS BIT(1)
#define TCPC_ALERT_CC_STATUS BIT(0)
#define TCPC_ALERT_MASK 0x12
#define TCPC_POWER_STATUS_MASK 0x14
#define TCPC_FAULT_STATUS_MASK 0x15
#define TCPC_CONFIG_STD_OUTPUT 0x18
#define TCPC_TCPC_CTRL 0x19
#define TCPC_TCPC_CTRL_ORIENTATION BIT(0)
#define TCPC_ROLE_CTRL 0x1a
#define TCPC_ROLE_CTRL_DRP BIT(6)
#define TCPC_ROLE_CTRL_RP_VAL_SHIFT 4
#define TCPC_ROLE_CTRL_RP_VAL_MASK 0x3
#define TCPC_ROLE_CTRL_RP_VAL_DEF 0x0
#define TCPC_ROLE_CTRL_RP_VAL_1_5 0x1
#define TCPC_ROLE_CTRL_RP_VAL_3_0 0x2
#define TCPC_ROLE_CTRL_CC2_SHIFT 2
#define TCPC_ROLE_CTRL_CC2_MASK 0x3
#define TCPC_ROLE_CTRL_CC1_SHIFT 0
#define TCPC_ROLE_CTRL_CC1_MASK 0x3
#define TCPC_ROLE_CTRL_CC_RA 0x0
#define TCPC_ROLE_CTRL_CC_RP 0x1
#define TCPC_ROLE_CTRL_CC_RD 0x2
#define TCPC_ROLE_CTRL_CC_OPEN 0x3
#define TCPC_FAULT_CTRL 0x1b
#define TCPC_POWER_CTRL 0x1c
#define TCPC_POWER_CTRL_VCONN_ENABLE BIT(0)
#define TCPC_CC_STATUS 0x1d
#define TCPC_CC_STATUS_TOGGLING BIT(5)
#define TCPC_CC_STATUS_TERM BIT(4)
#define TCPC_CC_STATUS_CC2_SHIFT 2
#define TCPC_CC_STATUS_CC2_MASK 0x3
#define TCPC_CC_STATUS_CC1_SHIFT 0
#define TCPC_CC_STATUS_CC1_MASK 0x3
#define TCPC_POWER_STATUS 0x1e
#define TCPC_POWER_STATUS_UNINIT BIT(6)
#define TCPC_POWER_STATUS_VBUS_DET BIT(3)
#define TCPC_POWER_STATUS_VBUS_PRES BIT(2)
#define TCPC_FAULT_STATUS 0x1f
#define TCPC_COMMAND 0x23
#define TCPC_CMD_WAKE_I2C 0x11
#define TCPC_CMD_DISABLE_VBUS_DETECT 0x22
#define TCPC_CMD_ENABLE_VBUS_DETECT 0x33
#define TCPC_CMD_DISABLE_SINK_VBUS 0x44
#define TCPC_CMD_SINK_VBUS 0x55
#define TCPC_CMD_DISABLE_SRC_VBUS 0x66
#define TCPC_CMD_SRC_VBUS_DEFAULT 0x77
#define TCPC_CMD_SRC_VBUS_HIGH 0x88
#define TCPC_CMD_LOOK4CONNECTION 0x99
#define TCPC_CMD_RXONEMORE 0xAA
#define TCPC_CMD_I2C_IDLE 0xFF
#define TCPC_DEV_CAP_1 0x24
#define TCPC_DEV_CAP_2 0x26
#define TCPC_STD_INPUT_CAP 0x28
#define TCPC_STD_OUTPUT_CAP 0x29
#define TCPC_MSG_HDR_INFO 0x2e
#define TCPC_MSG_HDR_INFO_DATA_ROLE BIT(3)
#define TCPC_MSG_HDR_INFO_PWR_ROLE BIT(0)
#define TCPC_MSG_HDR_INFO_REV_SHIFT 1
#define TCPC_MSG_HDR_INFO_REV_MASK 0x3
#define TCPC_RX_DETECT 0x2f
#define TCPC_RX_DETECT_HARD_RESET BIT(5)
#define TCPC_RX_DETECT_SOP BIT(0)
#define TCPC_RX_BYTE_CNT 0x30
#define TCPC_RX_BUF_FRAME_TYPE 0x31
#define TCPC_RX_HDR 0x32
#define TCPC_RX_DATA 0x34 /* through 0x4f */
#define TCPC_TRANSMIT 0x50
#define TCPC_TRANSMIT_RETRY_SHIFT 4
#define TCPC_TRANSMIT_RETRY_MASK 0x3
#define TCPC_TRANSMIT_TYPE_SHIFT 0
#define TCPC_TRANSMIT_TYPE_MASK 0x7
#define TCPC_TX_BYTE_CNT 0x51
#define TCPC_TX_HDR 0x52
#define TCPC_TX_DATA 0x54 /* through 0x6f */
#define TCPC_VBUS_VOLTAGE 0x70
#define TCPC_VBUS_SINK_DISCONNECT_THRESH 0x72
#define TCPC_VBUS_STOP_DISCHARGE_THRESH 0x74
#define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76
#define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78
#define TCPC_BMCIO_CTRL 0x90
#define TCPC_BMCIO_VBUS_DETECT_MASK BIT(1)
#define TCPC_BMCIO_VBUS_DETECT_ENABLE BIT(1)
#define TCPC_BMCIO_VBUS_DETECT_DISABLE 0
#define TCPC_BMCIO_24M_OSC_MASK BIT(0)
#define TCPC_BMCIO_ENABLE_24M_OSC BIT(0)
#define TCPC_BMCIO_DISABLE_24M_OSC 0
struct tcpci;
struct tcpci_data {
struct regmap *regmap;
int (*init)(struct tcpci *tcpci, struct tcpci_data *data);
int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data,
bool enable);
int (*start_drp_toggling)(struct tcpci *tcpci, struct tcpci_data *data,
enum typec_cc_status cc);
};
struct tcpci *tcpci_register_port(struct udevice *dev, struct tcpci_data *data);
void tcpci_unregister_port(struct tcpci *tcpci);
int tcpci_get_voltage_fun(struct tcpci *tcpci);
int tcpci_get_current_fun(struct tcpci *tcpci);
int tcpci_get_online_fun(struct tcpci *tcpci);
irqreturn_t tcpci_irq(struct tcpci *tcpci);
#endif /* __LINUX_USB_TCPCI_H */

View File

@@ -0,0 +1,229 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 Rockchip Co.,Ltd.
* Author: Wang Jie <dave.wang@rock-chips.com>
*
* Hynetek Husb311 Type-C Chip Driver
*/
#include <dm.h>
#include <i2c.h>
#include <asm/gpio.h>
#include <power/power_delivery/tcpm.h>
#include <power/power_delivery/power_delivery.h>
#include "tcpci.h"
#define HUSB311_VID 0x2E99
#define HUSB311_PID 0x0311
#define HUSB311_TCPC_I2C_RESET 0x9E
#define HUSB311_TCPC_SOFTRESET 0xA0
#define HUSB311_TCPC_FILTER 0xA1
#define HUSB311_TCPC_TDRP 0xA2
#define HUSB311_TCPC_DCSRCDRP 0xA3
#define HUSB311_I2C_RETRY_MAX_CNT 3
struct husb311_chip {
struct udevice *udev;
struct tcpci_data data;
struct tcpci *tcpci;
};
static int husb311_read16(struct husb311_chip *chip, unsigned int reg)
{
int ret = 0;
u8 buffer[2];
ret = dm_i2c_read(chip->udev, reg, buffer, 2);
if (ret < 0) {
printf("%s: cannot read %02x, ret=%d\n",
__func__, reg, ret);
return ret;
}
ret = ((buffer[1] << 8) & 0xFF00) + (buffer[0] & 0xFF);
return ret;
}
static int husb311_write8(struct husb311_chip *chip, unsigned int reg, u8 val)
{
int ret = 0;
int i;
for (i = 0; i < HUSB311_I2C_RETRY_MAX_CNT; i++) {
ret = dm_i2c_write(chip->udev, reg, &val, 1);
if (!ret)
break;
else
udelay(200);
}
if (ret)
printf("%s: cannot write 0x%02x to 0x%02x, ret=%d\n",
__func__, val, reg, ret);
return ret;
}
static int husb311_write16(struct husb311_chip *chip, unsigned int reg, u16 val)
{
int ret = 0;
u8 buffer[2];
buffer[0] = val & 0xFF;
buffer[1] = (val >> 8) & 0xFF;
ret = dm_i2c_write(chip->udev, reg, buffer, 2);
if (ret)
printf("%s: cannot write 0x%02x, len=%d, ret=%d\n",
__func__, reg, 2, ret);
return ret;
}
static struct husb311_chip *tdata_to_husb311(struct tcpci_data *tdata)
{
return container_of(tdata, struct husb311_chip, data);
}
static int husb311_sw_reset(struct husb311_chip *chip)
{
/* soft reset */
return husb311_write8(chip, HUSB311_TCPC_SOFTRESET, 0x01);
}
static int husb311_init(struct tcpci *tcpci, struct tcpci_data *tdata)
{
int ret;
struct husb311_chip *chip = tdata_to_husb311(tdata);
/* I2C reset : (val + 1) * 12.5ms */
ret = husb311_write8(chip, HUSB311_TCPC_I2C_RESET, 0x8F);
/* tTCPCfilter : (26.7 * val) us */
ret |= husb311_write8(chip, HUSB311_TCPC_FILTER, 0x0F);
/* tDRP : (51.2 + 6.4 * val) ms */
ret |= husb311_write8(chip, HUSB311_TCPC_TDRP, 0x04);
/* dcSRC.DRP : 33% */
ret |= husb311_write16(chip, HUSB311_TCPC_DCSRCDRP, 330);
if (ret)
printf("%s: fail to init registers(%d)\n", __func__, ret);
return ret;
}
static int husb311_check_revision(struct husb311_chip *chip)
{
int ret;
ret = husb311_read16(chip, TCPC_VENDOR_ID);
if (ret < 0) {
printf("%s: fail to read Vendor id(%d)\n", __func__, ret);
return ret;
}
if (ret != HUSB311_VID) {
printf("%s: vid is not correct, 0x%04x\n", __func__, ret);
return -ENODEV;
}
ret = husb311_read16(chip, TCPC_PRODUCT_ID);
if (ret < 0) {
printf("%s: fail to read Product id(%d)\n", __func__, ret);
return ret;
}
if (ret != HUSB311_PID) {
printf("%s: pid is not correct, 0x%04x\n", __func__, ret);
return -ENODEV;
}
return 0;
}
static int husb311_probe(struct udevice *dev)
{
int ret;
struct husb311_chip *chip = dev_get_priv(dev);
chip->udev = dev;
ret = husb311_check_revision(chip);
if (ret < 0) {
printf("%s: check vid/pid fail(%d)\n", __func__, ret);
return ret;
}
ret = husb311_sw_reset(chip);
if (ret) {
printf("%s: fail to soft reset, ret = %d\n", __func__, ret);
return ret;
}
chip->data.init = husb311_init;
chip->tcpci = tcpci_register_port(chip->udev, &chip->data);
if (IS_ERR(chip->tcpci))
return PTR_ERR(chip->tcpci);
return 0;
}
static int husb311_remove(struct udevice *dev)
{
struct husb311_chip *chip = dev_get_priv(dev);
int ret = 0;
printf("PD chip husb311 remove\n");
/* Disable chip interrupts before unregistering port */
ret = husb311_write16(chip, TCPC_ALERT_MASK, 0);
if (ret < 0)
return ret;
tcpci_unregister_port(chip->tcpci);
return 0;
}
static int husb311_get_voltage(struct udevice *dev)
{
struct husb311_chip *chip = dev_get_priv(dev);
return tcpci_get_voltage_fun(chip->tcpci);
}
static int husb311_get_current(struct udevice *dev)
{
struct husb311_chip *chip = dev_get_priv(dev);
return tcpci_get_current_fun(chip->tcpci);
}
static int husb311_get_online(struct udevice *dev)
{
struct husb311_chip *chip = dev_get_priv(dev);
return tcpci_get_online_fun(chip->tcpci);
}
static struct dm_power_delivery_ops husb311_ops = {
.get_voltage = husb311_get_voltage,
.get_current = husb311_get_current,
.get_online = husb311_get_online,
};
static const struct udevice_id husb311_ids[] = {
{ .compatible = "hynetek,husb311" },
{},
};
U_BOOT_DRIVER(husb311) = {
.name = "husb311",
.id = UCLASS_PD,
.of_match = husb311_ids,
.ops = &husb311_ops,
.probe = husb311_probe,
.remove = husb311_remove,
.priv_auto_alloc_size = sizeof(struct husb311_chip),
};
MODULE_AUTHOR("Wang Jie <dave.wang@rock-chips.com>");
MODULE_DESCRIPTION("Husb311 USB Type-C Port Controller Interface Driver");
MODULE_LICENSE("GPL v2");

File diff suppressed because it is too large Load Diff

View File

@@ -145,6 +145,18 @@ config TPM2_TIS_SPI
to the device using the standard TPM Interface Specification (TIS)
protocol.
config TPM_Z32H330TC_SPI
bool "STMicroelectronics Z32H330TC SPI TPM"
depends on TPM_V2 && DM_SPI
---help---
This driver supports STMicroelectronics TPM devices connected on the SPI bus.
The usual tpm operations and the 'tpm' command can be used to talk
to the device using the standard TPM Interface Specification (TIS)
protocol
config CMD_MEASURED_BOOT
bool "Enable support for measured_boot to bootcmd"
endif # TPM_V2
endmenu

View File

@@ -79,16 +79,15 @@
/* trust image name string */
#define TF_IMG_UPD_NAME "stashtf"
#define TEE_IMG_UPD_NAME "stashtee"
#define UBOOT_IMG_UPD_NAME "stashuboot"
#define SBMETA_IMG_UPD_NAME "stashsbmeta"
#define TF_PART_NAME "tf"
#define TEE_PART_NAME "tee"
#define UBOOT_PART_NAME "uboot"
#define STASH_PART_NAME "stash"
#define KERNEL_PART_NAME "kernel"
#define SBMETA_PART_NAME "sbmeta"
/* Define the NV partition name */
#define NV_PARTITION_NAME "nv"
#define UBOOT_STAGE_ADDR SRAM_BASE_ADDR
@@ -100,10 +99,10 @@
#define CONFIG_BMP_32BPP
/* security upgrade flag */
#define TF_SEC_UPGRADE_FLAG 0x5555aaaa
#define TEE_SEC_UPGRADE_FLAG 0x5a5aa5a5
#define UBOOT_SEC_UPGRADE_FLAG 0xa5a5aa55
#define SBMETA_SEC_UPGRADE_FLAG 0xaaaa5555
#define SEC_IMG_UPGRADE_FLAG 0x5a5a
#define BOOT_IMG_UPGRADE_FLAG 0xa500
#define ROOT_IMG_UPGRADE_FLAG 0xa5
/* Define secure debug log level */
#define LOG_LEVEL 1
@@ -146,7 +145,9 @@
#define ENV_STR_BOARD "board#=LB\0"
#elif defined(CONFIG_LIGHT_ANDROID_BOOT_IMAGE_VAL_LPI4A) || \
defined(CONFIG_LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A) || \
defined(CONFIG_TARGET_LIGHT_FM_C910_LPI4A)
defined(CONFIG_TARGET_LIGHT_FM_C910_LPI4A) || \
defined(CONFIG_LIGHT_SEC_BOOT_WITH_VERIFY_RVBOOK) || \
defined(CONFIG_TARGET_LIGHT_FM_C910_RVBOOK)
#define ENV_STR_BOARD "board#=LP\0"
#elif defined(CONFIG_LIGHT_ANDROID_BOOT_IMAGE_VAL_BEAGLE) || \
defined(CONFIG_TARGET_LIGHT_FM_C910_BEAGLE)
@@ -157,7 +158,6 @@
#define ENV_STR_BOARD "board#=LD\0"
#endif
#if defined (CONFIG_LIGHT_SEC_BOOT_WITH_VERIFY_VAL_A)
#define CONFIG_EXTRA_ENV_SETTINGS \
"splashimage=0x30000000\0" \
@@ -174,19 +174,24 @@
"tee_addr=0x1c000000\0" \
"sec_upgrade_mode=0\0"\
"mmcdev=0\0" \
"mmcpart=8\0" \
"mmcpart=c\0" \
"mmcbootpart=2\0" \
"mmcteepart=3\0" \
"mmcsbmetapart=5\0" \
"slot_suffix=a\0" \
"retries=5\0" \
ENV_KERNEL_LOGLEVEL \
"kdump_buf=180M\0" \
ENV_STR_BOOT_DELAY \
"sbmeta_security_level=1\0" \
"nvpart_name=" NV_PARTITION_NAME"\0" \
"uboot_version=0x0000000000000000\0"\
"tee_version=0x00000000\0"\
"tf_version=0x00000000\0"\
"sbmeta_version=0x00000000\0"\
"fdt_file=th1520-a-val-sec.dtb\0" \
"uuid_rootfs=80a5a8e9-c744-491a-93c1-4f4194fd690b\0" \
"partitions=name=table,size=2031KB;name=boot,size=200MiB,type=boot;name=tee,size=50MiB,type=boot;name=stash,size=50MiB,type=boot;name=sbmeta,size=8MiB,type=boot;name=swap,size=1536MiB,type=boot;name=fastresume,size=512MiB,type=boot;name=root,size=-,type=linux,uuid=${uuid_rootfs}\0" \
"partitions=name=table,size=2031KB;name=boot_a,size=200MiB,type=boot;name=tee_a,size=36MiB,type=boot;name=stash,size=16MiB,type=boot;name=sbmeta_a,size=8MiB,type=boot;name=swap,size=1536MiB,type=boot;name=fastresume,size=512MiB,type=boot;name=${nvpart_name},size=1MiB;name=boot_b,size=200M,type=boot;name=tee_b,size=36M,type=boot;name=sbmeta_b,size=8M,type=boot;name=root,size=-,type=linux,uuid=${uuid_rootfs}\0" \
"finduuid=part uuid mmc ${mmcdev}:${mmcpart} uuid\0" \
"gpt_partition=gpt write mmc ${mmcdev} $partitions\0" \
ENV_PUBLIC_BOOTARGS \
@@ -194,8 +199,8 @@
"load_aon=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_aon_fpga.bin;cp.b $fwaddr $aon_ram_addr $filesize;bootaon\0"\
"load_c906_audio=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_c906_audio.bin;cp.b $fwaddr $audio_ram_addr $filesize\0"\
"load_str=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr str.bin;cp.b $fwaddr $str_ram_addr $filesize\0"\
"bootcmd_load=run load_aon;run load_c906_audio;ext4load mmc 0:3 $tf_addr trust_firmware.bin; ext4load mmc 0:3 $tee_addr tee.bin;ext4load mmc ${mmcdev}:${mmcbootpart} $dtb_addr ${fdt_file}; ext4load mmc ${mmcdev}:${mmcbootpart} $kernel_addr Image\0" \
"bootcmd=run bootcmd_load; chk_hibernate; fixup_memory_region; bootslave; run finduuid; run set_bootargs; sbmetaboot;run load_str;booti $kernel_addr - $dtb_addr;\0" \
"bootcmd_load=run load_aon;run load_c906_audio;ext4load mmc ${mmcdev}:${mmcteepart} $tf_addr trust_firmware.bin; ext4load mmc ${mmcdev}:${mmcteepart} $tee_addr tee.bin;ext4load mmc ${mmcdev}:${mmcbootpart} $dtb_addr ${fdt_file}; ext4load mmc ${mmcdev}:${mmcbootpart} $kernel_addr Image\0" \
"bootcmd=light_bootab;run bootcmd_load; chk_hibernate; fixup_memory_region; bootslave; run finduuid; run set_bootargs; sbmetaboot; measureboot;run load_str;booti $kernel_addr - $dtb_addr;\0" \
"\0"
#elif defined (CONFIG_LIGHT_SEC_BOOT_WITH_VERIFY_VAL_B)
@@ -214,19 +219,24 @@
"tee_addr=0x1c000000\0" \
"sec_upgrade_mode=0\0"\
"mmcdev=0\0" \
"mmcpart=6\0" \
"mmcpart=a\0" \
"mmcbootpart=2\0" \
"mmcteepart=3\0" \
"mmcsbmetapart=5\0" \
"slot_suffix=a\0" \
"retries=5\0" \
ENV_KERNEL_LOGLEVEL \
"kdump_buf=180M\0" \
ENV_STR_BOOT_DELAY \
"sbmeta_security_level=1\0" \
"nvpart_name=" NV_PARTITION_NAME"\0" \
"uboot_version=0x0000000000000000\0"\
"tee_version=0x00000000\0"\
"tf_version=0x00000000\0"\
"sbmeta_version=0x00000000\0"\
"fdt_file=th1520-b-product-sec.dtb\0" \
"uuid_rootfs=80a5a8e9-c744-491a-93c1-4f4194fd690b\0" \
"partitions=name=table,size=2031KB;name=boot,size=200MiB,type=boot;name=tee,size=50MiB,type=boot;name=stash,size=50MiB,type=boot;name=sbmeta,size=8MiB,type=boot;name=root,size=-,type=linux,uuid=${uuid_rootfs}\0" \
"partitions=name=table,size=2031KB;name=boot_a,size=200MiB,type=boot;name=tee_a,size=36MiB,type=boot;name=stash,size=16MiB,type=boot;name=sbmeta_a,size=8MiB,type=boot;name=${nvpart_name},size=1MiB;name=boot_b,size=200M,type=boot;name=tee_b,size=36M,type=boot;name=sbmeta_b,size=8M,type=boot;name=root,size=-,type=linux,uuid=${uuid_rootfs}\0" \
"finduuid=part uuid mmc ${mmcdev}:${mmcpart} uuid\0" \
"gpt_partition=gpt write mmc ${mmcdev} $partitions\0" \
ENV_PUBLIC_BOOTARGS \
@@ -234,8 +244,8 @@
"load_aon=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_aon_fpga.bin;cp.b $fwaddr $aon_ram_addr $filesize;bootaon\0"\
"load_c906_audio=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_c906_audio.bin;cp.b $fwaddr $audio_ram_addr $filesize\0"\
"load_str=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr str.bin;cp.b $fwaddr $str_ram_addr $filesize\0"\
"bootcmd_load=run load_aon;run load_c906_audio; ext4load mmc 0:3 $tf_addr trust_firmware.bin; ext4load mmc 0:3 $tee_addr tee.bin;ext4load mmc ${mmcdev}:${mmcbootpart} $dtb_addr ${fdt_file}; ext4load mmc ${mmcdev}:${mmcbootpart} $kernel_addr Image\0" \
"bootcmd=run bootcmd_load; fixup_memory_region; bootslave; run finduuid; run set_bootargs; sbmetaboot; run load_str;booti $kernel_addr - $dtb_addr;\0" \
"bootcmd_load=run load_aon;run load_c906_audio;ext4load mmc ${mmcdev}:${mmcteepart} $tf_addr trust_firmware.bin; ext4load mmc ${mmcdev}:${mmcteepart} $tee_addr tee.bin;ext4load mmc ${mmcdev}:${mmcbootpart} $dtb_addr ${fdt_file}; ext4load mmc ${mmcdev}:${mmcbootpart} $kernel_addr Image\0" \
"bootcmd=light_bootab;run bootcmd_load; fixup_memory_region; bootslave; run finduuid; run set_bootargs; sbmetaboot; run load_str;booti $kernel_addr - $dtb_addr;\0" \
"\0"
#elif defined (CONFIG_LIGHT_SEC_BOOT_WITH_VERIFY_ANT_REF)
@@ -275,6 +285,50 @@
"bootcmd_load=run load_aon;run load_c906_audio;run load_str; ext4load mmc 0:3 $tf_addr trust_firmware.bin; ext4load mmc 0:4 $tee_addr tee.bin;ext4load mmc ${mmcdev}:${mmcbootpart} $dtb_addr ${fdt_file}; ext4load mmc ${mmcdev}:${mmcbootpart} $kernel_addr Image\0" \
"bootcmd=run bootcmd_load; fixup_memory_region; bootslave; run finduuid; run set_bootargs; secboot; booti $kernel_addr - $dtb_addr;\0" \
"\0"
#elif defined (CONFIG_LIGHT_SEC_BOOT_WITH_VERIFY_RVBOOK)
#define CONFIG_EXTRA_ENV_SETTINGS \
"splashimage=0x30000000\0" \
"splashpos=m,m\0" \
"fdt_high=0xffffffffffffffff\0" \
ENV_STR_BOARD \
"tf_addr=0x100000\0" \
"dtb_addr=0x03800000\0" \
"kernel_addr=0x00200000\0" \
"aon_ram_addr=0xffffef8000\0" \
"audio_ram_addr=0x32000000\0" \
"str_ram_addr=0xffe0000000\0" \
"fwaddr=0x10000000\0"\
"tee_addr=0x1c000000\0" \
"sec_upgrade_mode=0\0"\
"mmcdev=0\0" \
"mmcpart=c\0" \
"mmcbootpart=2\0" \
"mmcteepart=3\0" \
"mmcsbmetapart=5\0" \
"slot_suffix=a\0" \
"retries=5\0" \
ENV_KERNEL_LOGLEVEL \
"sbmeta_security_level=1\0" \
"nvpart_name=" NV_PARTITION_NAME"\0" \
"kdump_buf=180M\0" \
ENV_STR_BOOT_DELAY \
"uboot_version=0x0000000000000000\0"\
"tee_version=0x00000000\0"\
"tf_version=0x00000000\0"\
"sbmeta_version=0x00000000\0"\
"fdt_file=th1520-rvbook-product-sec.dtb\0" \
"uuid_rootfs=80a5a8e9-c744-491a-93c1-4f4194fd690b\0" \
"partitions=name=table,size=2031KB;name=boot_a,size=200MiB,type=boot;name=tee_a,size=36MiB,type=boot;name=stash,size=16MiB,type=boot;name=sbmeta_a,size=8MiB,type=boot;name=swap,size=1536MiB,type=boot;name=fastresume,size=512MiB,type=boot;name=${nvpart_name},size=1MiB;name=boot_b,size=200M,type=boot;name=tee_b,size=36M,type=boot;name=sbmeta_b,size=8M,type=boot;name=root,size=-,type=linux,uuid=${uuid_rootfs}\0" \
"finduuid=part uuid mmc ${mmcdev}:${mmcpart} uuid\0" \
"gpt_partition=gpt write mmc ${mmcdev} $partitions\0" \
ENV_PUBLIC_BOOTARGS \
"set_bootargs=setenv bootargs console=ttyS0,115200 root=PARTUUID=${uuid} ${pub_bootargs} loglevel=${kernel_loglevel} eth=$ethaddr crashkernel=${kdump_buf} ${resume_bootargs}\0" \
"load_aon=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_aon_fpga.bin;cp.b $fwaddr $aon_ram_addr $filesize;bootaon\0"\
"load_c906_audio=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_c906_audio.bin;cp.b $fwaddr $audio_ram_addr $filesize\0"\
"load_str=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr str.bin;cp.b $fwaddr $str_ram_addr $filesize\0"\
"bootcmd_load=run load_aon;run load_c906_audio;ext4load mmc ${mmcdev}:${mmcteepart} $tf_addr trust_firmware.bin; ext4load mmc ${mmcdev}:${mmcteepart} $tee_addr tee.bin;ext4load mmc ${mmcdev}:${mmcbootpart} $dtb_addr ${fdt_file}; ext4load mmc ${mmcdev}:${mmcbootpart} $kernel_addr Image\0" \
"bootcmd=light_bootab;run bootcmd_load; chk_hibernate; fixup_memory_region; bootslave; run finduuid; run set_bootargs; sbmetaboot; run load_str;booti $kernel_addr - $dtb_addr;\0" \
"\0"
#elif defined (CONFIG_LIGHT_SEC_BOOT_WITH_VERIFY_LPI4A)
#define CONFIG_EXTRA_ENV_SETTINGS \
@@ -292,10 +346,15 @@
"tee_addr=0x1c000000\0" \
"sec_upgrade_mode=0\0"\
"mmcdev=0\0" \
"mmcpart=8\0" \
"mmcpart=c\0" \
"mmcbootpart=2\0" \
"mmcteepart=3\0" \
"mmcsbmetapart=5\0" \
"slot_suffix=a\0" \
"retries=5\0" \
ENV_KERNEL_LOGLEVEL \
"sbmeta_security_level=1\0" \
"nvpart_name=" NV_PARTITION_NAME"\0" \
"kdump_buf=180M\0" \
ENV_STR_BOOT_DELAY \
"uboot_version=0x0000000000000000\0"\
@@ -304,7 +363,7 @@
"sbmeta_version=0x00000000\0"\
"fdt_file=th1520-lpi4a-product-sec.dtb\0" \
"uuid_rootfs=80a5a8e9-c744-491a-93c1-4f4194fd690b\0" \
"partitions=name=table,size=2031KB;name=boot,size=200MiB,type=boot;name=tee,size=50MiB,type=boot;name=stash,size=50MiB,type=boot;name=sbmeta,size=8MiB,type=boot;name=swap,size=1536MiB,type=boot;name=fastresume,size=512MiB,type=boot;name=root,size=-,type=linux,uuid=${uuid_rootfs}\0" \
"partitions=name=table,size=2031KB;name=boot_a,size=200MiB,type=boot;name=tee_a,size=36MiB,type=boot;name=stash,size=16MiB,type=boot;name=sbmeta_a,size=8MiB,type=boot;name=swap,size=1536MiB,type=boot;name=fastresume,size=512MiB,type=boot;name=${nvpart_name},size=1MiB;name=boot_b,size=200M,type=boot;name=tee_b,size=36M,type=boot;name=sbmeta_b,size=8M,type=boot;name=root,size=-,type=linux,uuid=${uuid_rootfs}\0" \
"finduuid=part uuid mmc ${mmcdev}:${mmcpart} uuid\0" \
"gpt_partition=gpt write mmc ${mmcdev} $partitions\0" \
ENV_PUBLIC_BOOTARGS \
@@ -312,8 +371,8 @@
"load_aon=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_aon_fpga.bin;cp.b $fwaddr $aon_ram_addr $filesize;bootaon\0"\
"load_c906_audio=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_c906_audio.bin;cp.b $fwaddr $audio_ram_addr $filesize\0"\
"load_str=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr str.bin;cp.b $fwaddr $str_ram_addr $filesize\0"\
"bootcmd_load=run load_aon;run load_c906_audio;ext4load mmc 0:3 $tf_addr trust_firmware.bin; ext4load mmc 0:3 $tee_addr tee.bin;ext4load mmc ${mmcdev}:${mmcbootpart} $dtb_addr ${fdt_file}; ext4load mmc ${mmcdev}:${mmcbootpart} $kernel_addr Image\0" \
"bootcmd=run bootcmd_load; chk_hibernate; fixup_memory_region; bootslave; run finduuid; run set_bootargs; sbmetaboot; run load_str;booti $kernel_addr - $dtb_addr;\0" \
"bootcmd_load=run load_aon;run load_c906_audio;ext4load mmc ${mmcdev}:${mmcteepart} $tf_addr trust_firmware.bin; ext4load mmc ${mmcdev}:${mmcteepart} $tee_addr tee.bin;ext4load mmc ${mmcdev}:${mmcbootpart} $dtb_addr ${fdt_file}; ext4load mmc ${mmcdev}:${mmcbootpart} $kernel_addr Image\0" \
"bootcmd=light_bootab;run bootcmd_load; chk_hibernate; fixup_memory_region; bootslave; run finduuid; run set_bootargs; sbmetaboot; run load_str;booti $kernel_addr - $dtb_addr;\0" \
"\0"
#elif defined(CONFIG_LIGHT_ANDROID_BOOT_IMAGE_VAL_A) || defined(CONFIG_LIGHT_ANDROID_BOOT_IMAGE_VAL_B) || \
@@ -575,6 +634,37 @@
"bootcmd_load=run load_aon;run load_c906_audio; run load_str; ext4load mmc ${mmcdev}:${mmcbootpart} $opensbi_addr fw_dynamic.bin; ext4load mmc ${mmcdev}:${mmcbootpart} $dtb_addr ${fdt_file}; ext4load mmc ${mmcdev}:${mmcbootpart} $kernel_addr Image\0" \
"bootcmd=run bootcmd_load; fixup_memory_region; bootslave; run finduuid; run set_bootargs; booti $kernel_addr - $dtb_addr;\0" \
"\0"
#elif defined (CONFIG_TARGET_LIGHT_FM_C910_RVBOOK)
#define CONFIG_EXTRA_ENV_SETTINGS \
"splashimage=0x30000000\0" \
"splashpos=m,m\0" \
"fdt_high=0xffffffffffffffff\0" \
"opensbi_addr=0x0\0" \
"dtb_addr=0x03800000\0" \
"kernel_addr=0x00200000\0" \
"aon_ram_addr=0xffffef8000\0" \
"audio_ram_addr=0x32000000\0" \
"str_ram_addr=0xffe0000000\0" \
"fwaddr=0x10000000\0"\
"mmcdev=0\0" \
"mmcpart=5\0" \
"mmcbootpart=2\0" \
ENV_KERNEL_LOGLEVEL \
"kdump_buf=180M\0" \
ENV_STR_BOOT_DELAY \
"fdt_file=th1520-rvbook-product.dtb\0" \
"uuid_rootfs=80a5a8e9-c744-491a-93c1-4f4194fd690b\0" \
"partitions=name=table,size=2031KB;name=boot,size=200MiB,type=boot;name=swap,size=1536MiB,type=boot;name=fastresume,size=512MiB,type=boot;name=root,size=-,type=linux,uuid=${uuid_rootfs}\0" \
"finduuid=part uuid mmc ${mmcdev}:${mmcpart} uuid\0" \
"gpt_partition=gpt write mmc ${mmcdev} $partitions\0" \
ENV_PUBLIC_BOOTARGS \
"set_bootargs=setenv bootargs console=ttyS0,115200 root=PARTUUID=${uuid} ${pub_bootargs} loglevel=${kernel_loglevel} eth=$ethaddr crashkernel=${kdump_buf} ${resume_bootargs}\0" \
"load_aon=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_aon_fpga.bin;cp.b $fwaddr $aon_ram_addr $filesize;bootaon\0"\
"load_c906_audio=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr light_c906_audio.bin;cp.b $fwaddr $audio_ram_addr $filesize\0"\
"load_str=ext4load mmc ${mmcdev}:${mmcbootpart} $fwaddr str.bin;cp.b $fwaddr $str_ram_addr $filesize\0"\
"bootcmd_load=run load_aon;run load_c906_audio; run load_str; ext4load mmc ${mmcdev}:${mmcbootpart} $opensbi_addr fw_dynamic.bin; ext4load mmc ${mmcdev}:${mmcbootpart} $dtb_addr ${fdt_file}; ext4load mmc ${mmcdev}:${mmcbootpart} $kernel_addr Image\0" \
"bootcmd=run bootcmd_load; chk_hibernate; fixup_memory_region; bootslave; run finduuid; run set_bootargs; booti $kernel_addr - $dtb_addr;\0" \
"\0"
#elif defined (CONFIG_TARGET_LIGHT_FM_C910_LPI4A)
#define CONFIG_EXTRA_ENV_SETTINGS \
"splashimage=0x30000000\0" \

View File

@@ -115,7 +115,12 @@ enum uclass_id {
UCLASS_W1, /* Dallas 1-Wire bus */
UCLASS_W1_EEPROM, /* one-wire EEPROMs */
UCLASS_WDT, /* Watchdog Timer driver */
UCLASS_FG, /* Fuel gauge */
UCLASS_CHARGE_DISPLAY, /* Charge display */
UCLASS_MCU, /* MCU device */
#ifdef CONFIG_RV_BOOK
UCLASS_PD, /* PD device */
#endif
UCLASS_COUNT,
UCLASS_INVALID = -1,
};

View File

@@ -15,8 +15,17 @@
#define FASTBOOT_VERSION "0.4"
/* The 64 defined bytes plus \0 */
#if CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION
#define FASTBOOT_COMMAND_LEN (1024 + 1)
#define FASTBOOT_RESPONSE_LEN (1024 + 1)
#else
#define FASTBOOT_COMMAND_LEN (64 + 1)
#ifdef CONFIG_FASTBOOT_ECIES_AUTH
#define FASTBOOT_RESPONSE_LEN (1024 + 1)
#else
#define FASTBOOT_RESPONSE_LEN (64 + 1)
#endif
#endif
/**
* All known commands to fastboot
@@ -49,6 +58,11 @@ enum {
FASTBOOT_COMMAND_UCMD,
#endif
FASTBOOT_COMMAND_OEM_COMMAND,
#if CONFIG_FASTBOOT_CMD_OEM_NV_OPERATION
FASTBOOT_COMMAND_OEM_NV_GET,
FASTBOOT_COMMAND_OEM_NV_SET,
FASTBOOT_COMMAND_OEM_FCTY,
#endif
FASTBOOT_COMMAND_COUNT
};

23
include/mcu/mcu-uclass.h Executable file
View File

@@ -0,0 +1,23 @@
#ifndef __MCU_H
#define __MCU_H
struct mcu_ops {
int (*shutdown)(struct udevice *dev);
int (*poweron)(struct udevice *dev);
};
/**
* mcu_shutdown() - power off supplies
*
* @return 0 on success or negative value of errno.
*/
int mcu_shutdown(void);
/**
* mcu_poweron() - power on supplies
*
* @return 0 on success or negative value of errno.
*/
int mcu_poweron(void);
#endif

View File

@@ -0,0 +1,33 @@
/*
* (C) Copyright 2017 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _CHARGE_ANIMATION_H_
#define _CHARGE_ANIMATION_H_
struct regulator_mem {
struct udevice *dev;
bool enable;
};
struct charge_animation_pdata {
int android_charge; /* android charge, 1: enable, 0: disable */
int uboot_charge; /* u-boot charge, 1: enable, 0: disable */
int auto_exit_charge; /* energy enough auto exit uboot charging*/
int exit_charge_voltage;/* lowest voltage allowed to exit charging */
int exit_charge_level; /* lowest soc level allowed to exit charging */
int low_power_voltage; /* below this voltage, force system into charge mode anyway */
int screen_on_voltage; /* lowest voltage allowed to turn on screen */
int system_suspend; /* enter ATF system suspend, 1: enable, 0: disable */
int auto_wakeup_interval;/* timeout seconds to auto wakeup system */
int auto_wakeup_screen_invert;/* auto wakeup system, 1: enable, 0: disable */
int auto_off_screen_interval;/* timeout seconds to auto turn off screen */
struct regulator_mem *regulators_mem; /* assigned regulator suspend state */
};
#endif

17
include/power/charge_display.h Executable file
View File

@@ -0,0 +1,17 @@
/*
* (C) Copyright 2017 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _CHARGE_DISPLAY_H_
#define _CHARGE_DISPLAY_H_
struct dm_charge_display_ops {
int (*show)(struct udevice *dev);
};
int charge_display(void);
int charge_display_show(struct udevice *dev);
#endif

46
include/power/fuel_gauge.h Executable file
View File

@@ -0,0 +1,46 @@
/*
* (C) Copyright 2017 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _FUEL_GAUGE_H_
#define _FUEL_GAUGE_H_
#ifndef BIT
#define BIT(nr) (1 << (nr))
#endif
/* Capability */
#define FG_CAP_FUEL_GAUGE BIT(0)
#define FG_CAP_CHARGER BIT(1)
struct dm_fuel_gauge_ops {
int (*capability)(struct udevice *dev);
int (*bat_is_exist)(struct udevice *dev);
int (*get_soc)(struct udevice *dev);
int (*get_voltage)(struct udevice *dev);
int (*get_current)(struct udevice *dev);
int (*get_temperature)(struct udevice *dev, int *temp);
bool (*get_chrg_online)(struct udevice *dev);
int (*set_charger_voltage)(struct udevice *dev, int uV);
int (*set_charger_enable)(struct udevice *dev);
int (*set_charger_disable)(struct udevice *dev);
int (*set_iprechg_current)(struct udevice *dev, int iprechrg_uA);
int (*set_charger_current)(struct udevice *dev, int ichrg_uA);
};
int fuel_gauge_capability(struct udevice *dev);
int fuel_gauge_bat_is_exist(struct udevice *dev);
int fuel_gauge_update_get_soc(struct udevice *dev);
int fuel_gauge_get_voltage(struct udevice *dev);
int fuel_gauge_get_current(struct udevice *dev);
bool fuel_gauge_get_chrg_online(struct udevice *dev);
int fuel_gauge_get_temperature(struct udevice *dev, int *temp);
int charger_set_charger_voltage(struct udevice *dev, int uV);
int charger_set_iprechg_current(struct udevice *dev, int iprechrg_uA);
int charger_set_current(struct udevice *dev, int ichrg_uA);
int charger_set_enable(struct udevice *dev);
int charger_set_disable(struct udevice *dev);
#endif

498
include/power/power_delivery/pd.h Executable file
View File

@@ -0,0 +1,498 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright 2015-2017 Google, Inc
*/
#ifndef __LINUX_USB_PD_H
#define __LINUX_USB_PD_H
#include <linux/kernel.h>
#include <linux/types.h>
#include "typec.h"
/* USB PD Messages */
enum pd_ctrl_msg_type {
/* 0 Reserved */
PD_CTRL_GOOD_CRC = 1,
PD_CTRL_GOTO_MIN = 2,
PD_CTRL_ACCEPT = 3,
PD_CTRL_REJECT = 4,
PD_CTRL_PING = 5,
PD_CTRL_PS_RDY = 6,
PD_CTRL_GET_SOURCE_CAP = 7,
PD_CTRL_GET_SINK_CAP = 8,
PD_CTRL_DR_SWAP = 9,
PD_CTRL_PR_SWAP = 10,
PD_CTRL_VCONN_SWAP = 11,
PD_CTRL_WAIT = 12,
PD_CTRL_SOFT_RESET = 13,
/* 14-15 Reserved */
PD_CTRL_NOT_SUPP = 16,
PD_CTRL_GET_SOURCE_CAP_EXT = 17,
PD_CTRL_GET_STATUS = 18,
PD_CTRL_FR_SWAP = 19,
PD_CTRL_GET_PPS_STATUS = 20,
PD_CTRL_GET_COUNTRY_CODES = 21,
/* 22-31 Reserved */
};
enum pd_data_msg_type {
/* 0 Reserved */
PD_DATA_SOURCE_CAP = 1,
PD_DATA_REQUEST = 2,
PD_DATA_BIST = 3,
PD_DATA_SINK_CAP = 4,
PD_DATA_BATT_STATUS = 5,
PD_DATA_ALERT = 6,
PD_DATA_GET_COUNTRY_INFO = 7,
PD_DATA_ENTER_USB = 8,
/* 9-14 Reserved */
PD_DATA_VENDOR_DEF = 15,
/* 16-31 Reserved */
};
enum pd_ext_msg_type {
/* 0 Reserved */
PD_EXT_SOURCE_CAP_EXT = 1,
PD_EXT_STATUS = 2,
PD_EXT_GET_BATT_CAP = 3,
PD_EXT_GET_BATT_STATUS = 4,
PD_EXT_BATT_CAP = 5,
PD_EXT_GET_MANUFACTURER_INFO = 6,
PD_EXT_MANUFACTURER_INFO = 7,
PD_EXT_SECURITY_REQUEST = 8,
PD_EXT_SECURITY_RESPONSE = 9,
PD_EXT_FW_UPDATE_REQUEST = 10,
PD_EXT_FW_UPDATE_RESPONSE = 11,
PD_EXT_PPS_STATUS = 12,
PD_EXT_COUNTRY_INFO = 13,
PD_EXT_COUNTRY_CODES = 14,
/* 15-31 Reserved */
};
#define PD_REV10 0x0
#define PD_REV20 0x1
#define PD_REV30 0x2
#define PD_MAX_REV PD_REV30
#define PD_HEADER_EXT_HDR BIT(15)
#define PD_HEADER_CNT_SHIFT 12
#define PD_HEADER_CNT_MASK 0x7
#define PD_HEADER_ID_SHIFT 9
#define PD_HEADER_ID_MASK 0x7
#define PD_HEADER_PWR_ROLE BIT(8)
#define PD_HEADER_REV_SHIFT 6
#define PD_HEADER_REV_MASK 0x3
#define PD_HEADER_DATA_ROLE BIT(5)
#define PD_HEADER_TYPE_SHIFT 0
#define PD_HEADER_TYPE_MASK 0x1f
#define PD_HEADER(type, pwr, data, rev, id, cnt, ext_hdr) \
((((type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \
((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \
((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \
(rev << PD_HEADER_REV_SHIFT) | \
(((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \
(((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT) | \
((ext_hdr) ? PD_HEADER_EXT_HDR : 0))
#define PD_HEADER_LE(type, pwr, data, rev, id, cnt) \
cpu_to_le16(PD_HEADER((type), (pwr), (data), (rev), (id), (cnt), (0)))
static inline unsigned int pd_header_cnt(u16 header)
{
return (header >> PD_HEADER_CNT_SHIFT) & PD_HEADER_CNT_MASK;
}
static inline unsigned int pd_header_cnt_le(__le16 header)
{
return pd_header_cnt(le16_to_cpu(header));
}
static inline unsigned int pd_header_type(u16 header)
{
return (header >> PD_HEADER_TYPE_SHIFT) & PD_HEADER_TYPE_MASK;
}
static inline unsigned int pd_header_type_le(__le16 header)
{
return pd_header_type(le16_to_cpu(header));
}
static inline unsigned int pd_header_msgid(u16 header)
{
return (header >> PD_HEADER_ID_SHIFT) & PD_HEADER_ID_MASK;
}
static inline unsigned int pd_header_msgid_le(__le16 header)
{
return pd_header_msgid(le16_to_cpu(header));
}
static inline unsigned int pd_header_rev(u16 header)
{
return (header >> PD_HEADER_REV_SHIFT) & PD_HEADER_REV_MASK;
}
static inline unsigned int pd_header_rev_le(__le16 header)
{
return pd_header_rev(le16_to_cpu(header));
}
#define PD_EXT_HDR_CHUNKED BIT(15)
#define PD_EXT_HDR_CHUNK_NUM_SHIFT 11
#define PD_EXT_HDR_CHUNK_NUM_MASK 0xf
#define PD_EXT_HDR_REQ_CHUNK BIT(10)
#define PD_EXT_HDR_DATA_SIZE_SHIFT 0
#define PD_EXT_HDR_DATA_SIZE_MASK 0x1ff
#define PD_EXT_HDR(data_size, req_chunk, chunk_num, chunked) \
((((data_size) & PD_EXT_HDR_DATA_SIZE_MASK) << PD_EXT_HDR_DATA_SIZE_SHIFT) | \
((req_chunk) ? PD_EXT_HDR_REQ_CHUNK : 0) | \
(((chunk_num) & PD_EXT_HDR_CHUNK_NUM_MASK) << PD_EXT_HDR_CHUNK_NUM_SHIFT) | \
((chunked) ? PD_EXT_HDR_CHUNKED : 0))
#define PD_EXT_HDR_LE(data_size, req_chunk, chunk_num, chunked) \
cpu_to_le16(PD_EXT_HDR((data_size), (req_chunk), (chunk_num), (chunked)))
static inline unsigned int pd_ext_header_chunk_num(u16 ext_header)
{
return (ext_header >> PD_EXT_HDR_CHUNK_NUM_SHIFT) &
PD_EXT_HDR_CHUNK_NUM_MASK;
}
static inline unsigned int pd_ext_header_data_size(u16 ext_header)
{
return (ext_header >> PD_EXT_HDR_DATA_SIZE_SHIFT) &
PD_EXT_HDR_DATA_SIZE_MASK;
}
static inline unsigned int pd_ext_header_data_size_le(__le16 ext_header)
{
return pd_ext_header_data_size(le16_to_cpu(ext_header));
}
#define PD_MAX_PAYLOAD 7
#define PD_EXT_MAX_CHUNK_DATA 26
/**
* struct pd_chunked_ext_message_data - PD chunked extended message data as
* seen on wire
* @header: PD extended message header
* @data: PD extended message data
*/
struct pd_chunked_ext_message_data {
__le16 header;
u8 data[PD_EXT_MAX_CHUNK_DATA];
} __packed;
/**
* struct pd_message - PD message as seen on wire
* @header: PD message header
* @payload: PD message payload
* @ext_msg: PD message chunked extended message data
*/
struct pd_message {
__le16 header;
union {
__le32 payload[PD_MAX_PAYLOAD];
struct pd_chunked_ext_message_data ext_msg;
};
} __packed;
/* PDO: Power Data Object */
#define PDO_MAX_OBJECTS 7
enum pd_pdo_type {
PDO_TYPE_FIXED = 0,
PDO_TYPE_BATT = 1,
PDO_TYPE_VAR = 2,
PDO_TYPE_APDO = 3,
};
#define PDO_TYPE_SHIFT 30
#define PDO_TYPE_MASK 0x3
#define PDO_TYPE(t) ((t) << PDO_TYPE_SHIFT)
#define PDO_VOLT_MASK 0x3ff
#define PDO_CURR_MASK 0x3ff
#define PDO_PWR_MASK 0x3ff
#define PDO_FIXED_DUAL_ROLE BIT(29) /* Power role swap supported */
#define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported (Source) */
#define PDO_FIXED_HIGHER_CAP BIT(28) /* Requires more than vSafe5V (Sink) */
#define PDO_FIXED_EXTPOWER BIT(27) /* Externally powered */
#define PDO_FIXED_USB_COMM BIT(26) /* USB communications capable */
#define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap supported */
#define PDO_FIXED_UNCHUNK_EXT BIT(24) /* Unchunked Extended Message supported (Source) */
#define PDO_FIXED_FRS_CURR_MASK (BIT(24) | BIT(23)) /* FR_Swap Current (Sink) */
#define PDO_FIXED_FRS_CURR_SHIFT 23
#define PDO_FIXED_VOLT_SHIFT 10 /* 50mV units */
#define PDO_FIXED_CURR_SHIFT 0 /* 10mA units */
#define PDO_FIXED_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_FIXED_VOLT_SHIFT)
#define PDO_FIXED_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_FIXED_CURR_SHIFT)
#define PDO_FIXED(mv, ma, flags) \
(PDO_TYPE(PDO_TYPE_FIXED) | (flags) | \
PDO_FIXED_VOLT(mv) | PDO_FIXED_CURR(ma))
#define VSAFE5V 5000 /* mv units */
#define PDO_BATT_MAX_VOLT_SHIFT 20 /* 50mV units */
#define PDO_BATT_MIN_VOLT_SHIFT 10 /* 50mV units */
#define PDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */
#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MIN_VOLT_SHIFT)
#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MAX_VOLT_SHIFT)
#define PDO_BATT_MAX_POWER(mw) ((((mw) / 250) & PDO_PWR_MASK) << PDO_BATT_MAX_PWR_SHIFT)
#define PDO_BATT(min_mv, max_mv, max_mw) \
(PDO_TYPE(PDO_TYPE_BATT) | PDO_BATT_MIN_VOLT(min_mv) | \
PDO_BATT_MAX_VOLT(max_mv) | PDO_BATT_MAX_POWER(max_mw))
#define PDO_VAR_MAX_VOLT_SHIFT 20 /* 50mV units */
#define PDO_VAR_MIN_VOLT_SHIFT 10 /* 50mV units */
#define PDO_VAR_MAX_CURR_SHIFT 0 /* 10mA units */
#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MIN_VOLT_SHIFT)
#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MAX_VOLT_SHIFT)
#define PDO_VAR_MAX_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_VAR_MAX_CURR_SHIFT)
#define PDO_VAR(min_mv, max_mv, max_ma) \
(PDO_TYPE(PDO_TYPE_VAR) | PDO_VAR_MIN_VOLT(min_mv) | \
PDO_VAR_MAX_VOLT(max_mv) | PDO_VAR_MAX_CURR(max_ma))
enum pd_apdo_type {
APDO_TYPE_PPS = 0,
};
#define PDO_APDO_TYPE_SHIFT 28 /* Only valid value currently is 0x0 - PPS */
#define PDO_APDO_TYPE_MASK 0x3
#define PDO_APDO_TYPE(t) ((t) << PDO_APDO_TYPE_SHIFT)
#define PDO_PPS_APDO_MAX_VOLT_SHIFT 17 /* 100mV units */
#define PDO_PPS_APDO_MIN_VOLT_SHIFT 8 /* 100mV units */
#define PDO_PPS_APDO_MAX_CURR_SHIFT 0 /* 50mA units */
#define PDO_PPS_APDO_VOLT_MASK 0xff
#define PDO_PPS_APDO_CURR_MASK 0x7f
#define PDO_PPS_APDO_MIN_VOLT(mv) \
((((mv) / 100) & PDO_PPS_APDO_VOLT_MASK) << PDO_PPS_APDO_MIN_VOLT_SHIFT)
#define PDO_PPS_APDO_MAX_VOLT(mv) \
((((mv) / 100) & PDO_PPS_APDO_VOLT_MASK) << PDO_PPS_APDO_MAX_VOLT_SHIFT)
#define PDO_PPS_APDO_MAX_CURR(ma) \
((((ma) / 50) & PDO_PPS_APDO_CURR_MASK) << PDO_PPS_APDO_MAX_CURR_SHIFT)
#define PDO_PPS_APDO(min_mv, max_mv, max_ma) \
(PDO_TYPE(PDO_TYPE_APDO) | PDO_APDO_TYPE(APDO_TYPE_PPS) | \
PDO_PPS_APDO_MIN_VOLT(min_mv) | PDO_PPS_APDO_MAX_VOLT(max_mv) | \
PDO_PPS_APDO_MAX_CURR(max_ma))
static inline enum pd_pdo_type pdo_type(u32 pdo)
{
return (pdo >> PDO_TYPE_SHIFT) & PDO_TYPE_MASK;
}
static inline unsigned int pdo_fixed_voltage(u32 pdo)
{
return ((pdo >> PDO_FIXED_VOLT_SHIFT) & PDO_VOLT_MASK) * 50;
}
static inline unsigned int pdo_min_voltage(u32 pdo)
{
return ((pdo >> PDO_VAR_MIN_VOLT_SHIFT) & PDO_VOLT_MASK) * 50;
}
static inline unsigned int pdo_max_voltage(u32 pdo)
{
return ((pdo >> PDO_VAR_MAX_VOLT_SHIFT) & PDO_VOLT_MASK) * 50;
}
static inline unsigned int pdo_max_current(u32 pdo)
{
return ((pdo >> PDO_VAR_MAX_CURR_SHIFT) & PDO_CURR_MASK) * 10;
}
static inline unsigned int pdo_max_power(u32 pdo)
{
return ((pdo >> PDO_BATT_MAX_PWR_SHIFT) & PDO_PWR_MASK) * 250;
}
static inline enum pd_apdo_type pdo_apdo_type(u32 pdo)
{
return (pdo >> PDO_APDO_TYPE_SHIFT) & PDO_APDO_TYPE_MASK;
}
static inline unsigned int pdo_pps_apdo_min_voltage(u32 pdo)
{
return ((pdo >> PDO_PPS_APDO_MIN_VOLT_SHIFT) &
PDO_PPS_APDO_VOLT_MASK) * 100;
}
static inline unsigned int pdo_pps_apdo_max_voltage(u32 pdo)
{
return ((pdo >> PDO_PPS_APDO_MAX_VOLT_SHIFT) &
PDO_PPS_APDO_VOLT_MASK) * 100;
}
static inline unsigned int pdo_pps_apdo_max_current(u32 pdo)
{
return ((pdo >> PDO_PPS_APDO_MAX_CURR_SHIFT) &
PDO_PPS_APDO_CURR_MASK) * 50;
}
/* RDO: Request Data Object */
#define RDO_OBJ_POS_SHIFT 28
#define RDO_OBJ_POS_MASK 0x7
#define RDO_GIVE_BACK BIT(27) /* Supports reduced operating current */
#define RDO_CAP_MISMATCH BIT(26) /* Not satisfied by source caps */
#define RDO_USB_COMM BIT(25) /* USB communications capable */
#define RDO_NO_SUSPEND BIT(24) /* USB Suspend not supported */
#define RDO_PWR_MASK 0x3ff
#define RDO_CURR_MASK 0x3ff
#define RDO_FIXED_OP_CURR_SHIFT 10
#define RDO_FIXED_MAX_CURR_SHIFT 0
#define RDO_OBJ(idx) (((idx) & RDO_OBJ_POS_MASK) << RDO_OBJ_POS_SHIFT)
#define PDO_FIXED_OP_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_OP_CURR_SHIFT)
#define PDO_FIXED_MAX_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_MAX_CURR_SHIFT)
#define RDO_FIXED(idx, op_ma, max_ma, flags) \
(RDO_OBJ(idx) | (flags) | \
PDO_FIXED_OP_CURR(op_ma) | PDO_FIXED_MAX_CURR(max_ma))
#define RDO_BATT_OP_PWR_SHIFT 10 /* 250mW units */
#define RDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */
#define RDO_BATT_OP_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_OP_PWR_SHIFT)
#define RDO_BATT_MAX_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_MAX_PWR_SHIFT)
#define RDO_BATT(idx, op_mw, max_mw, flags) \
(RDO_OBJ(idx) | (flags) | \
RDO_BATT_OP_PWR(op_mw) | RDO_BATT_MAX_PWR(max_mw))
#define RDO_PROG_VOLT_MASK 0x7ff
#define RDO_PROG_CURR_MASK 0x7f
#define RDO_PROG_VOLT_SHIFT 9
#define RDO_PROG_CURR_SHIFT 0
#define RDO_PROG_VOLT_MV_STEP 20
#define RDO_PROG_CURR_MA_STEP 50
#define PDO_PROG_OUT_VOLT(mv) \
((((mv) / RDO_PROG_VOLT_MV_STEP) & RDO_PROG_VOLT_MASK) << RDO_PROG_VOLT_SHIFT)
#define PDO_PROG_OP_CURR(ma) \
((((ma) / RDO_PROG_CURR_MA_STEP) & RDO_PROG_CURR_MASK) << RDO_PROG_CURR_SHIFT)
#define RDO_PROG(idx, out_mv, op_ma, flags) \
(RDO_OBJ(idx) | (flags) | \
PDO_PROG_OUT_VOLT(out_mv) | PDO_PROG_OP_CURR(op_ma))
static inline unsigned int rdo_index(u32 rdo)
{
return (rdo >> RDO_OBJ_POS_SHIFT) & RDO_OBJ_POS_MASK;
}
static inline unsigned int rdo_op_current(u32 rdo)
{
return ((rdo >> RDO_FIXED_OP_CURR_SHIFT) & RDO_CURR_MASK) * 10;
}
static inline unsigned int rdo_max_current(u32 rdo)
{
return ((rdo >> RDO_FIXED_MAX_CURR_SHIFT) &
RDO_CURR_MASK) * 10;
}
static inline unsigned int rdo_op_power(u32 rdo)
{
return ((rdo >> RDO_BATT_OP_PWR_SHIFT) & RDO_PWR_MASK) * 250;
}
static inline unsigned int rdo_max_power(u32 rdo)
{
return ((rdo >> RDO_BATT_MAX_PWR_SHIFT) & RDO_PWR_MASK) * 250;
}
/* Enter_USB Data Object */
#define EUDO_USB_MODE_MASK GENMASK(30, 28)
#define EUDO_USB_MODE_SHIFT 28
#define EUDO_USB_MODE_USB2 0
#define EUDO_USB_MODE_USB3 1
#define EUDO_USB_MODE_USB4 2
#define EUDO_USB4_DRD BIT(26)
#define EUDO_USB3_DRD BIT(25)
#define EUDO_CABLE_SPEED_MASK GENMASK(23, 21)
#define EUDO_CABLE_SPEED_SHIFT 21
#define EUDO_CABLE_SPEED_USB2 0
#define EUDO_CABLE_SPEED_USB3_GEN1 1
#define EUDO_CABLE_SPEED_USB4_GEN2 2
#define EUDO_CABLE_SPEED_USB4_GEN3 3
#define EUDO_CABLE_TYPE_MASK GENMASK(20, 19)
#define EUDO_CABLE_TYPE_SHIFT 19
#define EUDO_CABLE_TYPE_PASSIVE 0
#define EUDO_CABLE_TYPE_RE_TIMER 1
#define EUDO_CABLE_TYPE_RE_DRIVER 2
#define EUDO_CABLE_TYPE_OPTICAL 3
#define EUDO_CABLE_CURRENT_MASK GENMASK(18, 17)
#define EUDO_CABLE_CURRENT_SHIFT 17
#define EUDO_CABLE_CURRENT_NOTSUPP 0
#define EUDO_CABLE_CURRENT_3A 2
#define EUDO_CABLE_CURRENT_5A 3
#define EUDO_PCIE_SUPPORT BIT(16)
#define EUDO_DP_SUPPORT BIT(15)
#define EUDO_TBT_SUPPORT BIT(14)
#define EUDO_HOST_PRESENT BIT(13)
/* USB PD timers and counters */
#define PD_T_NO_RESPONSE 5000 /* 4.5 - 5.5 seconds */
#define PD_T_DB_DETECT 10000 /* 10 - 15 seconds */
#define PD_T_SEND_SOURCE_CAP 150 /* 100 - 200 ms */
#define PD_T_SENDER_RESPONSE 60 /* 24 - 30 ms, relaxed */
#define PD_T_RECEIVER_RESPONSE 15 /* 15ms max */
#define PD_T_SOURCE_ACTIVITY 45
#define PD_T_SINK_ACTIVITY 135
#define PD_T_SINK_WAIT_CAP 310 /* 310 - 620 ms */
#define PD_T_PS_TRANSITION 500
#define PD_T_SRC_TRANSITION 35
#define PD_T_DRP_SNK 40
#define PD_T_DRP_SRC 30
#define PD_T_PS_SOURCE_OFF 920
#define PD_T_PS_SOURCE_ON 480
#define PD_T_PS_SOURCE_ON_PRS 450 /* 390 - 480ms */
#define PD_T_PS_HARD_RESET 30
#define PD_T_SRC_RECOVER 760
#define PD_T_SRC_RECOVER_MAX 1000
#define PD_T_SRC_TURN_ON 275
#define PD_T_SAFE_0V 650
#define PD_T_VCONN_SOURCE_ON 100
#define PD_T_SINK_REQUEST 100 /* 100 ms minimum */
#define PD_T_ERROR_RECOVERY 100 /* minimum 25 is insufficient */
#define PD_T_SRCSWAPSTDBY 625 /* Maximum of 650ms */
#define PD_T_NEWSRC 250 /* Maximum of 275ms */
#define PD_T_SWAP_SRC_START 20 /* Minimum of 20ms */
#define PD_T_BIST_CONT_MODE 50 /* 30 - 60 ms */
#define PD_T_SINK_TX 16 /* 16 - 20 ms */
#define PD_T_CHUNK_NOT_SUPP 42 /* 40 - 50 ms */
#define PD_T_DRP_TRY 100 /* 75 - 150 ms */
#define PD_T_DRP_TRYWAIT 600 /* 400 - 800 ms */
#define PD_T_CC_DEBOUNCE 200 /* 100 - 200 ms */
#define PD_T_PD_DEBOUNCE 20 /* 10 - 20 ms */
#define PD_T_TRY_CC_DEBOUNCE 15 /* 10 - 20 ms */
#define PD_N_CAPS_COUNT (PD_T_NO_RESPONSE / PD_T_SEND_SOURCE_CAP)
#define PD_N_HARD_RESET_COUNT 1
#define PD_P_SNK_STDBY_MW 2500 /* 2500 mW */
#endif /* __LINUX_USB_PD_H */

View File

@@ -0,0 +1,518 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright 2015-2017 Google, Inc
*/
#ifndef __LINUX_USB_PD_VDO_H
#define __LINUX_USB_PD_VDO_H
#include "pd.h"
/*
* VDO : Vendor Defined Message Object
* VDM object is minimum of VDM header + 6 additional data objects.
*/
#define VDO_MAX_OBJECTS 6
#define VDO_MAX_SIZE (VDO_MAX_OBJECTS + 1)
/*
* VDM header
* ----------
* <31:16> :: SVID
* <15> :: VDM type ( 1b == structured, 0b == unstructured )
* <14:13> :: Structured VDM version
* <12:11> :: reserved
* <10:8> :: object position (1-7 valid ... used for enter/exit mode only)
* <7:6> :: command type (SVDM only?)
* <5> :: reserved (SVDM), command type (UVDM)
* <4:0> :: command
*/
#define VDO(vid, type, ver, custom) \
(((vid) << 16) | \
((type) << 15) | \
((ver) << 13) | \
((custom) & 0x7FFF))
#define VDO_SVDM_TYPE (1 << 15)
#define VDO_SVDM_VERS(x) ((x) << 13)
#define VDO_OPOS(x) ((x) << 8)
#define VDO_CMDT(x) ((x) << 6)
#define VDO_SVDM_VERS_MASK VDO_SVDM_VERS(0x3)
#define VDO_OPOS_MASK VDO_OPOS(0x7)
#define VDO_CMDT_MASK VDO_CMDT(0x3)
#define CMDT_INIT 0
#define CMDT_RSP_ACK 1
#define CMDT_RSP_NAK 2
#define CMDT_RSP_BUSY 3
/* reserved for SVDM ... for Google UVDM */
#define VDO_SRC_INITIATOR (0 << 5)
#define VDO_SRC_RESPONDER (1 << 5)
#define CMD_DISCOVER_IDENT 1
#define CMD_DISCOVER_SVID 2
#define CMD_DISCOVER_MODES 3
#define CMD_ENTER_MODE 4
#define CMD_EXIT_MODE 5
#define CMD_ATTENTION 6
#define VDO_CMD_VENDOR(x) (((0x10 + (x)) & 0x1f))
/* ChromeOS specific commands */
#define VDO_CMD_VERSION VDO_CMD_VENDOR(0)
#define VDO_CMD_SEND_INFO VDO_CMD_VENDOR(1)
#define VDO_CMD_READ_INFO VDO_CMD_VENDOR(2)
#define VDO_CMD_REBOOT VDO_CMD_VENDOR(5)
#define VDO_CMD_FLASH_ERASE VDO_CMD_VENDOR(6)
#define VDO_CMD_FLASH_WRITE VDO_CMD_VENDOR(7)
#define VDO_CMD_ERASE_SIG VDO_CMD_VENDOR(8)
#define VDO_CMD_PING_ENABLE VDO_CMD_VENDOR(10)
#define VDO_CMD_CURRENT VDO_CMD_VENDOR(11)
#define VDO_CMD_FLIP VDO_CMD_VENDOR(12)
#define VDO_CMD_GET_LOG VDO_CMD_VENDOR(13)
#define VDO_CMD_CCD_EN VDO_CMD_VENDOR(14)
#define PD_VDO_VID(vdo) ((vdo) >> 16)
#define PD_VDO_SVDM(vdo) (((vdo) >> 15) & 1)
#define PD_VDO_SVDM_VER(vdo) (((vdo) >> 13) & 0x3)
#define PD_VDO_OPOS(vdo) (((vdo) >> 8) & 0x7)
#define PD_VDO_CMD(vdo) ((vdo) & 0x1f)
#define PD_VDO_CMDT(vdo) (((vdo) >> 6) & 0x3)
/*
* SVDM Identity request -> response
*
* Request is simply properly formatted SVDM header
*
* Response is 4 data objects:
* [0] :: SVDM header
* [1] :: Identitiy header
* [2] :: Cert Stat VDO
* [3] :: (Product | Cable) VDO
* [4] :: AMA VDO
*
*/
#define VDO_INDEX_HDR 0
#define VDO_INDEX_IDH 1
#define VDO_INDEX_CSTAT 2
#define VDO_INDEX_CABLE 3
#define VDO_INDEX_PRODUCT 3
#define VDO_INDEX_AMA 4
/*
* SVDM Identity Header
* --------------------
* <31> :: data capable as a USB host
* <30> :: data capable as a USB device
* <29:27> :: product type (UFP / Cable / VPD)
* <26> :: modal operation supported (1b == yes)
* <25:23> :: product type (DFP) (SVDM version 2.0+ only; set to zero in version 1.0)
* <22:21> :: connector type (SVDM version 2.0+ only; set to zero in version 1.0)
* <20:16> :: Reserved, Shall be set to zero
* <15:0> :: USB-IF assigned VID for this cable vendor
*/
/* PD Rev2.0 definition */
#define IDH_PTYPE_UNDEF 0
/* SOP Product Type (UFP) */
#define IDH_PTYPE_NOT_UFP 0
#define IDH_PTYPE_HUB 1
#define IDH_PTYPE_PERIPH 2
#define IDH_PTYPE_PSD 3
#define IDH_PTYPE_AMA 5
/* SOP' Product Type (Cable Plug / VPD) */
#define IDH_PTYPE_NOT_CABLE 0
#define IDH_PTYPE_PCABLE 3
#define IDH_PTYPE_ACABLE 4
#define IDH_PTYPE_VPD 6
/* SOP Product Type (DFP) */
#define IDH_PTYPE_NOT_DFP 0
#define IDH_PTYPE_DFP_HUB 1
#define IDH_PTYPE_DFP_HOST 2
#define IDH_PTYPE_DFP_PB 3
/* ID Header Mask */
#define IDH_DFP_MASK GENMASK(25, 23)
#define IDH_CONN_MASK GENMASK(22, 21)
#define VDO_IDH(usbh, usbd, ufp_cable, is_modal, dfp, conn, vid) \
((usbh) << 31 | (usbd) << 30 | ((ufp_cable) & 0x7) << 27 \
| (is_modal) << 26 | ((dfp) & 0x7) << 23 | ((conn) & 0x3) << 21 \
| ((vid) & 0xffff))
#define PD_IDH_PTYPE(vdo) (((vdo) >> 27) & 0x7)
#define PD_IDH_VID(vdo) ((vdo) & 0xffff)
#define PD_IDH_MODAL_SUPP(vdo) ((vdo) & (1 << 26))
#define PD_IDH_DFP_PTYPE(vdo) (((vdo) >> 23) & 0x7)
#define PD_IDH_CONN_TYPE(vdo) (((vdo) >> 21) & 0x3)
/*
* Cert Stat VDO
* -------------
* <31:0> : USB-IF assigned XID for this cable
*/
#define PD_CSTAT_XID(vdo) (vdo)
#define VDO_CERT(xid) ((xid) & 0xffffffff)
/*
* Product VDO
* -----------
* <31:16> : USB Product ID
* <15:0> : USB bcdDevice
*/
#define VDO_PRODUCT(pid, bcd) (((pid) & 0xffff) << 16 | ((bcd) & 0xffff))
#define PD_PRODUCT_PID(vdo) (((vdo) >> 16) & 0xffff)
/*
* UFP VDO (PD Revision 3.0+ only)
* --------
* <31:29> :: UFP VDO version
* <28> :: Reserved
* <27:24> :: Device capability
* <23:22> :: Connector type (10b == receptacle, 11b == captive plug)
* <21:11> :: Reserved
* <10:8> :: Vconn power (AMA only)
* <7> :: Vconn required (AMA only, 0b == no, 1b == yes)
* <6> :: Vbus required (AMA only, 0b == yes, 1b == no)
* <5:3> :: Alternate modes
* <2:0> :: USB highest speed
*/
#define PD_VDO_UFP_DEVCAP(vdo) (((vdo) & GENMASK(27, 24)) >> 24)
/* UFP VDO Version */
#define UFP_VDO_VER1_2 2
/* Device Capability */
#define DEV_USB2_CAPABLE BIT(0)
#define DEV_USB2_BILLBOARD BIT(1)
#define DEV_USB3_CAPABLE BIT(2)
#define DEV_USB4_CAPABLE BIT(3)
/* Connector Type */
#define UFP_RECEPTACLE 2
#define UFP_CAPTIVE 3
/* Vconn Power (AMA only, set to AMA_VCONN_NOT_REQ if Vconn is not required) */
#define AMA_VCONN_PWR_1W 0
#define AMA_VCONN_PWR_1W5 1
#define AMA_VCONN_PWR_2W 2
#define AMA_VCONN_PWR_3W 3
#define AMA_VCONN_PWR_4W 4
#define AMA_VCONN_PWR_5W 5
#define AMA_VCONN_PWR_6W 6
/* Vconn Required (AMA only) */
#define AMA_VCONN_NOT_REQ 0
#define AMA_VCONN_REQ 1
/* Vbus Required (AMA only) */
#define AMA_VBUS_REQ 0
#define AMA_VBUS_NOT_REQ 1
/* Alternate Modes */
#define UFP_ALTMODE_NOT_SUPP 0
#define UFP_ALTMODE_TBT3 BIT(0)
#define UFP_ALTMODE_RECFG BIT(1)
#define UFP_ALTMODE_NO_RECFG BIT(2)
/* USB Highest Speed */
#define UFP_USB2_ONLY 0
#define UFP_USB32_GEN1 1
#define UFP_USB32_4_GEN2 2
#define UFP_USB4_GEN3 3
#define VDO_UFP(ver, cap, conn, vcpwr, vcr, vbr, alt, spd) \
(((ver) & 0x7) << 29 | ((cap) & 0xf) << 24 | ((conn) & 0x3) << 22 \
| ((vcpwr) & 0x7) << 8 | (vcr) << 7 | (vbr) << 6 | ((alt) & 0x7) << 3 \
| ((spd) & 0x7))
/*
* DFP VDO (PD Revision 3.0+ only)
* --------
* <31:29> :: DFP VDO version
* <28:27> :: Reserved
* <26:24> :: Host capability
* <23:22> :: Connector type (10b == receptacle, 11b == captive plug)
* <21:5> :: Reserved
* <4:0> :: Port number
*/
#define PD_VDO_DFP_HOSTCAP(vdo) (((vdo) & GENMASK(26, 24)) >> 24)
#define DFP_VDO_VER1_1 1
#define HOST_USB2_CAPABLE BIT(0)
#define HOST_USB3_CAPABLE BIT(1)
#define HOST_USB4_CAPABLE BIT(2)
#define DFP_RECEPTACLE 2
#define DFP_CAPTIVE 3
#define VDO_DFP(ver, cap, conn, pnum) \
(((ver) & 0x7) << 29 | ((cap) & 0x7) << 24 | ((conn) & 0x3) << 22 \
| ((pnum) & 0x1f))
/*
* Cable VDO (for both Passive and Active Cable VDO in PD Rev2.0)
* ---------
* <31:28> :: Cable HW version
* <27:24> :: Cable FW version
* <23:20> :: Reserved, Shall be set to zero
* <19:18> :: type-C to Type-A/B/C/Captive (00b == A, 01 == B, 10 == C, 11 == Captive)
* <17> :: Reserved, Shall be set to zero
* <16:13> :: cable latency (0001 == <10ns(~1m length))
* <12:11> :: cable termination type (11b == both ends active VCONN req)
* <10> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
* <9> :: SSTX2 Directionality support
* <8> :: SSRX1 Directionality support
* <7> :: SSRX2 Directionality support
* <6:5> :: Vbus current handling capability (01b == 3A, 10b == 5A)
* <4> :: Vbus through cable (0b == no, 1b == yes)
* <3> :: SOP" controller present? (0b == no, 1b == yes)
* <2:0> :: USB SS Signaling support
*
* Passive Cable VDO (PD Rev3.0+)
* ---------
* <31:28> :: Cable HW version
* <27:24> :: Cable FW version
* <23:21> :: VDO version
* <20> :: Reserved, Shall be set to zero
* <19:18> :: Type-C to Type-C/Captive (10b == C, 11b == Captive)
* <17> :: Reserved, Shall be set to zero
* <16:13> :: cable latency (0001 == <10ns(~1m length))
* <12:11> :: cable termination type (10b == Vconn not req, 01b == Vconn req)
* <10:9> :: Maximum Vbus voltage (00b == 20V, 01b == 30V, 10b == 40V, 11b == 50V)
* <8:7> :: Reserved, Shall be set to zero
* <6:5> :: Vbus current handling capability (01b == 3A, 10b == 5A)
* <4:3> :: Reserved, Shall be set to zero
* <2:0> :: USB highest speed
*
* Active Cable VDO 1 (PD Rev3.0+)
* ---------
* <31:28> :: Cable HW version
* <27:24> :: Cable FW version
* <23:21> :: VDO version
* <20> :: Reserved, Shall be set to zero
* <19:18> :: Connector type (10b == C, 11b == Captive)
* <17> :: Reserved, Shall be set to zero
* <16:13> :: cable latency (0001 == <10ns(~1m length))
* <12:11> :: cable termination type (10b == one end active, 11b == both ends active VCONN req)
* <10:9> :: Maximum Vbus voltage (00b == 20V, 01b == 30V, 10b == 40V, 11b == 50V)
* <8> :: SBU supported (0b == supported, 1b == not supported)
* <7> :: SBU type (0b == passive, 1b == active)
* <6:5> :: Vbus current handling capability (01b == 3A, 10b == 5A)
* <2:0> :: USB highest speed
*/
/* Cable VDO Version */
#define CABLE_VDO_VER1_0 0
#define CABLE_VDO_VER1_3 3
/* Connector Type (_ATYPE and _BTYPE are for PD Rev2.0 only) */
#define CABLE_ATYPE 0
#define CABLE_BTYPE 1
#define CABLE_CTYPE 2
#define CABLE_CAPTIVE 3
/* Cable Latency */
#define CABLE_LATENCY_1M 1
#define CABLE_LATENCY_2M 2
#define CABLE_LATENCY_3M 3
#define CABLE_LATENCY_4M 4
#define CABLE_LATENCY_5M 5
#define CABLE_LATENCY_6M 6
#define CABLE_LATENCY_7M 7
#define CABLE_LATENCY_7M_PLUS 8
/* Cable Termination Type */
#define PCABLE_VCONN_NOT_REQ 0
#define PCABLE_VCONN_REQ 1
#define ACABLE_ONE_END 2
#define ACABLE_BOTH_END 3
/* Maximum Vbus Voltage */
#define CABLE_MAX_VBUS_20V 0
#define CABLE_MAX_VBUS_30V 1
#define CABLE_MAX_VBUS_40V 2
#define CABLE_MAX_VBUS_50V 3
/* Active Cable SBU Supported/Type */
#define ACABLE_SBU_SUPP 0
#define ACABLE_SBU_NOT_SUPP 1
#define ACABLE_SBU_PASSIVE 0
#define ACABLE_SBU_ACTIVE 1
/* Vbus Current Handling Capability */
#define CABLE_CURR_DEF 0
#define CABLE_CURR_3A 1
#define CABLE_CURR_5A 2
/* USB SuperSpeed Signaling Support (PD Rev2.0) */
#define CABLE_USBSS_U2_ONLY 0
#define CABLE_USBSS_U31_GEN1 1
#define CABLE_USBSS_U31_GEN2 2
/* USB Highest Speed */
#define CABLE_USB2_ONLY 0
#define CABLE_USB32_GEN1 1
#define CABLE_USB32_4_GEN2 2
#define CABLE_USB4_GEN3 3
#define VDO_CABLE(hw, fw, cbl, lat, term, tx1d, tx2d, rx1d, rx2d, cur, vps, sopp, usbss) \
(((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 | ((cbl) & 0x3) << 18 \
| ((lat) & 0x7) << 13 | ((term) & 0x3) << 11 | (tx1d) << 10 \
| (tx2d) << 9 | (rx1d) << 8 | (rx2d) << 7 | ((cur) & 0x3) << 5 \
| (vps) << 4 | (sopp) << 3 | ((usbss) & 0x7))
#define VDO_PCABLE(hw, fw, ver, conn, lat, term, vbm, cur, spd) \
(((hw) & 0xf) << 28 | ((fw) & 0xf) << 24 | ((ver) & 0x7) << 21 \
| ((conn) & 0x3) << 18 | ((lat) & 0xf) << 13 | ((term) & 0x3) << 11 \
| ((vbm) & 0x3) << 9 | ((cur) & 0x3) << 5 | ((spd) & 0x7))
#define VDO_ACABLE1(hw, fw, ver, conn, lat, term, vbm, sbu, sbut, cur, vbt, sopp, spd) \
(((hw) & 0xf) << 28 | ((fw) & 0xf) << 24 | ((ver) & 0x7) << 21 \
| ((conn) & 0x3) << 18 | ((lat) & 0xf) << 13 | ((term) & 0x3) << 11 \
| ((vbm) & 0x3) << 9 | (sbu) << 8 | (sbut) << 7 | ((cur) & 0x3) << 5 \
| (vbt) << 4 | (sopp) << 3 | ((spd) & 0x7))
#define VDO_TYPEC_CABLE_TYPE(vdo) (((vdo) >> 18) & 0x3)
/*
* Active Cable VDO 2
* ---------
* <31:24> :: Maximum operating temperature
* <23:16> :: Shutdown temperature
* <15> :: Reserved, Shall be set to zero
* <14:12> :: U3/CLd power
* <11> :: U3 to U0 transition mode (0b == direct, 1b == through U3S)
* <10> :: Physical connection (0b == copper, 1b == optical)
* <9> :: Active element (0b == redriver, 1b == retimer)
* <8> :: USB4 supported (0b == yes, 1b == no)
* <7:6> :: USB2 hub hops consumed
* <5> :: USB2 supported (0b == yes, 1b == no)
* <4> :: USB3.2 supported (0b == yes, 1b == no)
* <3> :: USB lanes supported (0b == one lane, 1b == two lanes)
* <2> :: Optically isolated active cable (0b == no, 1b == yes)
* <1> :: Reserved, Shall be set to zero
* <0> :: USB gen (0b == gen1, 1b == gen2+)
*/
/* U3/CLd Power*/
#define ACAB2_U3_CLD_10MW_PLUS 0
#define ACAB2_U3_CLD_10MW 1
#define ACAB2_U3_CLD_5MW 2
#define ACAB2_U3_CLD_1MW 3
#define ACAB2_U3_CLD_500UW 4
#define ACAB2_U3_CLD_200UW 5
#define ACAB2_U3_CLD_50UW 6
/* Other Active Cable VDO 2 Fields */
#define ACAB2_U3U0_DIRECT 0
#define ACAB2_U3U0_U3S 1
#define ACAB2_PHY_COPPER 0
#define ACAB2_PHY_OPTICAL 1
#define ACAB2_REDRIVER 0
#define ACAB2_RETIMER 1
#define ACAB2_USB4_SUPP 0
#define ACAB2_USB4_NOT_SUPP 1
#define ACAB2_USB2_SUPP 0
#define ACAB2_USB2_NOT_SUPP 1
#define ACAB2_USB32_SUPP 0
#define ACAB2_USB32_NOT_SUPP 1
#define ACAB2_LANES_ONE 0
#define ACAB2_LANES_TWO 1
#define ACAB2_OPT_ISO_NO 0
#define ACAB2_OPT_ISO_YES 1
#define ACAB2_GEN_1 0
#define ACAB2_GEN_2_PLUS 1
#define VDO_ACABLE2(mtemp, stemp, u3p, trans, phy, ele, u4, hops, u2, u32, lane, iso, gen) \
(((mtemp) & 0xff) << 24 | ((stemp) & 0xff) << 16 | ((u3p) & 0x7) << 12 \
| (trans) << 11 | (phy) << 10 | (ele) << 9 | (u4) << 8 \
| ((hops) & 0x3) << 6 | (u2) << 5 | (u32) << 4 | (lane) << 3 \
| (iso) << 2 | (gen))
/*
* AMA VDO (PD Rev2.0)
* ---------
* <31:28> :: Cable HW version
* <27:24> :: Cable FW version
* <23:12> :: Reserved, Shall be set to zero
* <11> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable)
* <10> :: SSTX2 Directionality support
* <9> :: SSRX1 Directionality support
* <8> :: SSRX2 Directionality support
* <7:5> :: Vconn power
* <4> :: Vconn power required
* <3> :: Vbus power required
* <2:0> :: USB SS Signaling support
*/
#define VDO_AMA(hw, fw, tx1d, tx2d, rx1d, rx2d, vcpwr, vcr, vbr, usbss) \
(((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 \
| (tx1d) << 11 | (tx2d) << 10 | (rx1d) << 9 | (rx2d) << 8 \
| ((vcpwr) & 0x7) << 5 | (vcr) << 4 | (vbr) << 3 \
| ((usbss) & 0x7))
#define PD_VDO_AMA_VCONN_REQ(vdo) (((vdo) >> 4) & 1)
#define PD_VDO_AMA_VBUS_REQ(vdo) (((vdo) >> 3) & 1)
#define AMA_USBSS_U2_ONLY 0
#define AMA_USBSS_U31_GEN1 1
#define AMA_USBSS_U31_GEN2 2
#define AMA_USBSS_BBONLY 3
/*
* VPD VDO
* ---------
* <31:28> :: HW version
* <27:24> :: FW version
* <23:21> :: VDO version
* <20:17> :: Reserved, Shall be set to zero
* <16:15> :: Maximum Vbus voltage (00b == 20V, 01b == 30V, 10b == 40V, 11b == 50V)
* <14> :: Charge through current support (0b == 3A, 1b == 5A)
* <13> :: Reserved, Shall be set to zero
* <12:7> :: Vbus impedance
* <6:1> :: Ground impedance
* <0> :: Charge through support (0b == no, 1b == yes)
*/
#define VPD_VDO_VER1_0 0
#define VPD_MAX_VBUS_20V 0
#define VPD_MAX_VBUS_30V 1
#define VPD_MAX_VBUS_40V 2
#define VPD_MAX_VBUS_50V 3
#define VPDCT_CURR_3A 0
#define VPDCT_CURR_5A 1
#define VPDCT_NOT_SUPP 0
#define VPDCT_SUPP 1
#define VDO_VPD(hw, fw, ver, vbm, curr, vbi, gi, ct) \
(((hw) & 0xf) << 28 | ((fw) & 0xf) << 24 | ((ver) & 0x7) << 21 \
| ((vbm) & 0x3) << 15 | (curr) << 14 | ((vbi) & 0x3f) << 7 \
| ((gi) & 0x3f) << 1 | (ct))
/*
* SVDM Discover SVIDs request -> response
*
* Request is properly formatted VDM Header with discover SVIDs command.
* Response is a set of SVIDs of all supported SVIDs with all zero's to
* mark the end of SVIDs. If more than 12 SVIDs are supported command SHOULD be
* repeated.
*/
#define VDO_SVID(svid0, svid1) (((svid0) & 0xffff) << 16 | ((svid1) & 0xffff))
#define PD_VDO_SVID_SVID0(vdo) ((vdo) >> 16)
#define PD_VDO_SVID_SVID1(vdo) ((vdo) & 0xffff)
/* USB-IF SIDs */
#define USB_SID_PD 0xff00 /* power delivery */
#define USB_SID_DISPLAYPORT 0xff01
#define USB_SID_MHL 0xff02 /* Mobile High-Definition Link */
/* VDM command timeouts (in ms) */
#define PD_T_VDM_UNSTRUCTURED 500
#define PD_T_VDM_BUSY 100
#define PD_T_VDM_WAIT_MODE_E 100
#define PD_T_VDM_SNDR_RSP 30
#define PD_T_VDM_E_MODE 25
#define PD_T_VDM_RCVR_RSP 15
#endif /* __LINUX_USB_PD_VDO_H */

View File

@@ -0,0 +1,36 @@
/*
* (C) Copyright 2020 Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _power_delivery_H_
#define _power_delivery_H_
/* Capability */
#define FG_CAP_FUEL_GAUGE BIT(0)
#define FG_CAP_CHARGER BIT(1)
struct dm_power_delivery_ops {
int (*get_voltage)(struct udevice *dev);
int (*get_current)(struct udevice *dev);
int (*get_online)(struct udevice *dev);
int (*get_vbus_power)(struct udevice *dev);
};
struct power_delivery_data {
int voltage;
int current;
int online;
};
int power_delivery_get_vbus(struct udevice *dev, int *status);
#ifdef CONFIG_DM_POWER_DELIVERY
int power_delivery_get_data(struct udevice *dev, struct power_delivery_data *pd_data);
#else
inline int power_delivery_get_data(struct udevice *dev,
struct power_delivery_data *pd_data)
{
return -ENOSYS;
}
#endif
#endif

View File

@@ -0,0 +1,195 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright 2015-2017 Google, Inc
*/
#ifndef __LINUX_USB_TCPM_H
#define __LINUX_USB_TCPM_H
#include <linux/bitops.h>
#include "typec.h"
#include "pd.h"
enum typec_cc_status {
TYPEC_CC_OPEN,
TYPEC_CC_RA,
TYPEC_CC_RD,
TYPEC_CC_RP_DEF,
TYPEC_CC_RP_1_5,
TYPEC_CC_RP_3_0,
};
/* Collision Avoidance */
#define SINK_TX_NG TYPEC_CC_RP_1_5
#define SINK_TX_OK TYPEC_CC_RP_3_0
enum typec_cc_polarity {
TYPEC_POLARITY_CC1,
TYPEC_POLARITY_CC2,
};
/* Time to wait for TCPC to complete transmit */
#define PD_T_TCPC_TX_TIMEOUT 100 /* in ms */
#define PD_ROLE_SWAP_TIMEOUT (MSEC_PER_SEC * 10)
#define PD_PPS_CTRL_TIMEOUT (MSEC_PER_SEC * 10)
enum tcpm_transmit_status {
TCPC_TX_SUCCESS = 0,
TCPC_TX_DISCARDED = 1,
TCPC_TX_FAILED = 2,
};
enum tcpm_transmit_type {
TCPC_TX_SOP = 0,
TCPC_TX_SOP_PRIME = 1,
TCPC_TX_SOP_PRIME_PRIME = 2,
TCPC_TX_SOP_DEBUG_PRIME = 3,
TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4,
TCPC_TX_HARD_RESET = 5,
TCPC_TX_CABLE_RESET = 6,
TCPC_TX_BIST_MODE_2 = 7
};
/* Mux state attributes */
#define TCPC_MUX_USB_ENABLED BIT(0) /* USB enabled */
#define TCPC_MUX_DP_ENABLED BIT(1) /* DP enabled */
#define TCPC_MUX_POLARITY_INVERTED BIT(2) /* Polarity inverted */
/**
* struct tcpc_dev - Port configuration and callback functions
* @fwnode: Pointer to port fwnode
* @get_vbus: Called to read current VBUS state
* @get_current_limit:
* Optional; called by the tcpm core when configured as a snk
* and cc=Rp-def. This allows the tcpm to provide a fallback
* current-limit detection method for the cc=Rp-def case.
* For example, some tcpcs may include BC1.2 charger detection
* and use that in this case.
* @set_cc: Called to set value of CC pins
* @apply_rc: Optional; Needed to move TCPCI based chipset to APPLY_RC state
* as stated by the TCPCI specification.
* @get_cc: Called to read current CC pin values
* @set_polarity:
* Called to set polarity
* @set_vconn: Called to enable or disable VCONN
* @set_vbus: Called to enable or disable VBUS
* @set_current_limit:
* Optional; called to set current limit as negotiated
* with partner.
* @set_pd_rx: Called to enable or disable reception of PD messages
* @set_roles: Called to set power and data roles
* @start_toggling:
* Optional; if supported by hardware, called to start dual-role
* toggling or single-role connection detection. Toggling stops
* automatically if a connection is established.
* @try_role: Optional; called to set a preferred role
* @pd_transmit:Called to transmit PD message
* @set_bist_data: Turn on/off bist data mode for compliance testing
* @enable_frs:
* Optional; Called to enable/disable PD 3.0 fast role swap.
* Enabling frs is accessory dependent as not all PD3.0
* accessories support fast role swap.
* @frs_sourcing_vbus:
* Optional; Called to notify that vbus is now being sourced.
* Low level drivers can perform chip specific operations, if any.
* @enable_auto_vbus_discharge:
* Optional; TCPCI spec based TCPC implementations can optionally
* support hardware to autonomously dischrge vbus upon disconnecting
* as sink or source. TCPM signals TCPC to enable the mechanism upon
* entering connected state and signals disabling upon disconnect.
* @set_auto_vbus_discharge_threshold:
* Mandatory when enable_auto_vbus_discharge is implemented. TCPM
* calls this function to allow lower levels drivers to program the
* vbus threshold voltage below which the vbus discharge circuit
* will be turned on. requested_vbus_voltage is set to 0 when vbus
* is going to disappear knowingly i.e. during PR_SWAP and
* HARD_RESET etc.
* @is_vbus_vsafe0v:
* Optional; TCPCI spec based TCPC implementations are expected to
* detect VSAFE0V voltage level at vbus. When detection of VSAFE0V
* is supported by TCPC, set this callback for TCPM to query
* whether vbus is at VSAFE0V when needed.
* Returns true when vbus is at VSAFE0V, false otherwise.
* @set_partner_usb_comm_capable:
* Optional; The USB Communications Capable bit indicates if port
* partner is capable of communication over the USB data lines
* (e.g. D+/- or SS Tx/Rx). Called to notify the status of the bit.
* @check_contaminant:
* Optional; The callback is called when CC pins report open status
* at the end of the toggling period. Chip level drivers are
* expected to check for contaminant and re-enable toggling if
* needed. When 0 is not returned, check_contaminant is expected to
* restart toggling after checking the connector for contaminant.
* This forces the TCPM state machine to tranistion to TOGGLING state
* without calling start_toggling callback.
* @poll_event:
* After the PD chip driver is loaded, the callback function will be
* called to poll what events have been triggered.
* @enter_low_power_mode:
* Optional; the pd chip enters low power mode.
*/
struct tcpc_dev {
ofnode connector_node;
int (*init)(struct tcpc_dev *dev);
int (*get_vbus)(struct tcpc_dev *dev);
int (*get_current_limit)(struct tcpc_dev *dev);
int (*set_cc)(struct tcpc_dev *dev, enum typec_cc_status cc);
int (*apply_rc)(struct tcpc_dev *dev, enum typec_cc_status cc,
enum typec_cc_polarity polarity);
int (*get_cc)(struct tcpc_dev *dev, enum typec_cc_status *cc1,
enum typec_cc_status *cc2);
int (*set_polarity)(struct tcpc_dev *dev,
enum typec_cc_polarity polarity);
int (*set_vconn)(struct tcpc_dev *dev, bool on);
int (*set_vbus)(struct tcpc_dev *dev, bool on, bool charge);
int (*set_current_limit)(struct tcpc_dev *dev, u32 max_ma, u32 mv);
int (*set_pd_rx)(struct tcpc_dev *dev, bool on);
int (*set_roles)(struct tcpc_dev *dev, bool attached,
enum typec_role role, enum typec_data_role data);
int (*start_toggling)(struct tcpc_dev *dev,
enum typec_port_type port_type,
enum typec_cc_status cc);
int (*try_role)(struct tcpc_dev *dev, int role);
int (*pd_transmit)(struct tcpc_dev *dev, enum tcpm_transmit_type type,
const struct pd_message *msg, unsigned int negotiated_rev);
int (*set_bist_data)(struct tcpc_dev *dev, bool on);
int (*enable_frs)(struct tcpc_dev *dev, bool enable);
void (*frs_sourcing_vbus)(struct tcpc_dev *dev);
int (*enable_auto_vbus_discharge)(struct tcpc_dev *dev, bool enable);
int (*set_auto_vbus_discharge_threshold)(struct tcpc_dev *dev, enum typec_pwr_opmode mode,
bool pps_active, u32 requested_vbus_voltage);
int (*check_contaminant)(struct tcpc_dev *dev);
bool (*is_vbus_vsafe0v)(struct tcpc_dev *dev);
void (*set_partner_usb_comm_capable)(struct tcpc_dev *dev, bool enable);
void (*poll_event)(struct tcpc_dev *dev);
int (*enter_low_power_mode)(struct tcpc_dev *dev, bool attached, bool pd_capable);
};
struct tcpm_port;
struct tcpm_port *tcpm_port_init(struct udevice *dev, struct tcpc_dev *tcpc);
void tcpm_poll_event(struct tcpm_port *port);
int tcpm_get_voltage(struct tcpm_port *port);
int tcpm_get_current(struct tcpm_port *port);
int tcpm_get_online(struct tcpm_port *port);
int tcpm_get_vbus(struct tcpm_port *port);
void tcpm_uninit_port(struct tcpm_port *port);
int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo,
unsigned int nr_pdo,
unsigned int operating_snk_mw);
void tcpm_vbus_change(struct tcpm_port *port);
void tcpm_cc_change(struct tcpm_port *port);
void tcpm_sink_frs(struct tcpm_port *port);
void tcpm_sourcing_vbus(struct tcpm_port *port);
void tcpm_pd_receive(struct tcpm_port *port,
const struct pd_message *msg);
void tcpm_pd_transmit_complete(struct tcpm_port *port,
enum tcpm_transmit_status status);
void tcpm_pd_hard_reset(struct tcpm_port *port);
void tcpm_tcpc_reset(struct tcpm_port *port);
bool tcpm_is_debouncing(struct tcpm_port *tcpm);
bool tcpm_is_toggling(struct tcpm_port *port);
#endif /* __LINUX_USB_TCPM_H */

View File

@@ -0,0 +1,315 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LINUX_USB_TYPEC_H
#define __LINUX_USB_TYPEC_H
#include <linux/types.h>
/* USB Type-C Specification releases */
#define USB_TYPEC_REV_1_0 0x100 /* 1.0 */
#define USB_TYPEC_REV_1_1 0x110 /* 1.1 */
#define USB_TYPEC_REV_1_2 0x120 /* 1.2 */
#define USB_TYPEC_REV_1_3 0x130 /* 1.3 */
#define USB_TYPEC_REV_1_4 0x140 /* 1.4 */
#define USB_TYPEC_REV_2_0 0x200 /* 2.0 */
struct typec_partner;
struct typec_cable;
struct typec_plug;
struct typec_port;
struct typec_altmode_ops;
struct fwnode_handle;
struct device;
enum typec_port_type {
TYPEC_PORT_SRC,
TYPEC_PORT_SNK,
TYPEC_PORT_DRP,
};
enum typec_port_data {
TYPEC_PORT_DFP,
TYPEC_PORT_UFP,
TYPEC_PORT_DRD,
};
enum typec_plug_type {
USB_PLUG_NONE,
USB_PLUG_TYPE_A,
USB_PLUG_TYPE_B,
USB_PLUG_TYPE_C,
USB_PLUG_CAPTIVE,
};
enum typec_data_role {
TYPEC_DEVICE,
TYPEC_HOST,
};
enum typec_role {
TYPEC_SINK,
TYPEC_SOURCE,
};
enum typec_pwr_opmode {
TYPEC_PWR_MODE_USB,
TYPEC_PWR_MODE_1_5A,
TYPEC_PWR_MODE_3_0A,
TYPEC_PWR_MODE_PD,
};
enum typec_accessory {
TYPEC_ACCESSORY_NONE,
TYPEC_ACCESSORY_AUDIO,
TYPEC_ACCESSORY_DEBUG,
};
#define TYPEC_MAX_ACCESSORY 3
enum typec_orientation {
TYPEC_ORIENTATION_NONE,
TYPEC_ORIENTATION_NORMAL,
TYPEC_ORIENTATION_REVERSE,
};
/*
* struct enter_usb_data - Enter_USB Message details
* @eudo: Enter_USB Data Object
* @active_link_training: Active Cable Plug Link Training
*
* @active_link_training is a flag that should be set with uni-directional SBRX
* communication, and left 0 with passive cables and with bi-directional SBRX
* communication.
*/
struct enter_usb_data {
u32 eudo;
unsigned char active_link_training:1;
};
/*
* struct usb_pd_identity - USB Power Delivery identity data
* @id_header: ID Header VDO
* @cert_stat: Cert Stat VDO
* @product: Product VDO
* @vdo: Product Type Specific VDOs
*
* USB power delivery Discover Identity command response data.
*
* REVISIT: This is USB Power Delivery specific information, so this structure
* probable belongs to USB Power Delivery header file once we have them.
*/
struct usb_pd_identity {
u32 id_header;
u32 cert_stat;
u32 product;
u32 vdo[3];
};
int typec_partner_set_identity(struct typec_partner *partner);
int typec_cable_set_identity(struct typec_cable *cable);
/*
* struct typec_altmode_desc - USB Type-C Alternate Mode Descriptor
* @svid: Standard or Vendor ID
* @mode: Index of the Mode
* @vdo: VDO returned by Discover Modes USB PD command
* @roles: Only for ports. DRP if the mode is available in both roles
*
* Description of an Alternate Mode which a connector, cable plug or partner
* supports.
*/
struct typec_altmode_desc {
u16 svid;
u8 mode;
u32 vdo;
/* Only used with ports */
enum typec_port_data roles;
};
void typec_partner_set_pd_revision(struct typec_partner *partner, u16 pd_revision);
int typec_partner_set_num_altmodes(struct typec_partner *partner, int num_altmodes);
struct typec_altmode
*typec_partner_register_altmode(struct typec_partner *partner,
const struct typec_altmode_desc *desc);
int typec_plug_set_num_altmodes(struct typec_plug *plug, int num_altmodes);
struct typec_altmode
*typec_plug_register_altmode(struct typec_plug *plug,
const struct typec_altmode_desc *desc);
struct typec_altmode
*typec_port_register_altmode(struct typec_port *port,
const struct typec_altmode_desc *desc);
#ifdef CONFIG_NO_GKI
void typec_port_register_altmodes(struct typec_port *port,
const struct typec_altmode_ops *ops, void *drvdata,
struct typec_altmode **altmodes, size_t n);
#else
static inline void typec_port_register_altmodes(struct typec_port *port,
const struct typec_altmode_ops *ops, void *drvdata,
struct typec_altmode **altmodes, size_t n)
{
}
#endif
void typec_unregister_altmode(struct typec_altmode *altmode);
struct typec_port *typec_altmode2port(struct typec_altmode *alt);
void typec_altmode_update_active(struct typec_altmode *alt, bool active);
enum typec_plug_index {
TYPEC_PLUG_SOP_P,
TYPEC_PLUG_SOP_PP,
};
/*
* struct typec_plug_desc - USB Type-C Cable Plug Descriptor
* @index: SOP Prime for the plug connected to DFP and SOP Double Prime for the
* plug connected to UFP
*
* Represents USB Type-C Cable Plug.
*/
struct typec_plug_desc {
enum typec_plug_index index;
};
/*
* struct typec_cable_desc - USB Type-C Cable Descriptor
* @type: The plug type from USB PD Cable VDO
* @active: Is the cable active or passive
* @identity: Result of Discover Identity command
* @pd_revision: USB Power Delivery Specification revision if supported
*
* Represents USB Type-C Cable attached to USB Type-C port.
*/
struct typec_cable_desc {
enum typec_plug_type type;
unsigned int active:1;
struct usb_pd_identity *identity;
u16 pd_revision; /* 0300H = "3.0" */
};
/*
* struct typec_partner_desc - USB Type-C Partner Descriptor
* @usb_pd: USB Power Delivery support
* @accessory: Audio, Debug or none.
* @identity: Discover Identity command data
* @pd_revision: USB Power Delivery Specification Revision if supported
*
* Details about a partner that is attached to USB Type-C port. If @identity
* member exists when partner is registered, a directory named "identity" is
* created to sysfs for the partner device.
*
* @pd_revision is based on the setting of the "Specification Revision" field
* in the message header on the initial "Source Capabilities" message received
* from the partner, or a "Request" message received from the partner, depending
* on whether our port is a Sink or a Source.
*/
struct typec_partner_desc {
unsigned int usb_pd:1;
enum typec_accessory accessory;
struct usb_pd_identity *identity;
u16 pd_revision; /* 0300H = "3.0" */
};
/**
* struct typec_operations - USB Type-C Port Operations
* @try_role: Set data role preference for DRP port
* @dr_set: Set Data Role
* @pr_set: Set Power Role
* @vconn_set: Source VCONN
* @port_type_set: Set port type
*/
struct typec_operations {
int (*try_role)(struct typec_port *port, int role);
int (*dr_set)(struct typec_port *port, enum typec_data_role role);
int (*pr_set)(struct typec_port *port, enum typec_role role);
int (*vconn_set)(struct typec_port *port, enum typec_role role);
int (*port_type_set)(struct typec_port *port,
enum typec_port_type type);
};
enum usb_pd_svdm_ver {
SVDM_VER_1_0 = 0,
SVDM_VER_2_0 = 1,
SVDM_VER_MAX = SVDM_VER_2_0,
};
/*
* struct typec_capability - USB Type-C Port Capabilities
* @type: Supported power role of the port
* @data: Supported data role of the port
* @revision: USB Type-C Specification release. Binary coded decimal
* @pd_revision: USB Power Delivery Specification revision if supported
* @svdm_version: USB PD Structured VDM version if supported
* @prefer_role: Initial role preference (DRP ports).
* @accessory: Supported Accessory Modes
* @fwnode: Optional fwnode of the port
* @driver_data: Private pointer for driver specific info
* @ops: Port operations vector
*
* Static capabilities of a single USB Type-C port.
*/
struct typec_capability {
enum typec_port_type type;
enum typec_port_data data;
u16 revision; /* 0120H = "1.2" */
u16 pd_revision; /* 0300H = "3.0" */
enum usb_pd_svdm_ver svdm_version;
int prefer_role;
enum typec_accessory accessory[TYPEC_MAX_ACCESSORY];
unsigned int orientation_aware:1;
struct fwnode_handle *fwnode;
void *driver_data;
const struct typec_operations *ops;
};
/* Specific to try_role(). Indicates the user want's to clear the preference. */
#define TYPEC_NO_PREFERRED_ROLE (-1)
struct typec_port *typec_register_port(struct device *parent,
const struct typec_capability *cap);
void typec_unregister_port(struct typec_port *port);
struct typec_partner *typec_register_partner(struct typec_port *port,
struct typec_partner_desc *desc);
void typec_unregister_partner(struct typec_partner *partner);
struct typec_cable *typec_register_cable(struct typec_port *port,
struct typec_cable_desc *desc);
void typec_unregister_cable(struct typec_cable *cable);
struct typec_cable *typec_cable_get(struct typec_port *port);
void typec_cable_put(struct typec_cable *cable);
int typec_cable_is_active(struct typec_cable *cable);
struct typec_plug *typec_register_plug(struct typec_cable *cable,
struct typec_plug_desc *desc);
void typec_unregister_plug(struct typec_plug *plug);
void typec_set_data_role(struct typec_port *port, enum typec_data_role role);
void typec_set_pwr_role(struct typec_port *port, enum typec_role role);
void typec_set_vconn_role(struct typec_port *port, enum typec_role role);
void typec_set_pwr_opmode(struct typec_port *port, enum typec_pwr_opmode mode);
int typec_set_orientation(struct typec_port *port,
enum typec_orientation orientation);
enum typec_orientation typec_get_orientation(struct typec_port *port);
int typec_set_mode(struct typec_port *port, int mode);
void *typec_get_drvdata(struct typec_port *port);
int typec_find_pwr_opmode(const char *name);
int typec_find_orientation(const char *name);
int typec_find_port_power_role(const char *name);
int typec_find_power_role(const char *name);
int typec_find_port_data_role(const char *name);
void typec_partner_set_svdm_version(struct typec_partner *partner,
enum usb_pd_svdm_ver svdm_version);
int typec_get_negotiated_svdm_version(struct typec_port *port);
#endif /* __LINUX_USB_TYPEC_H */

View File

@@ -64,9 +64,11 @@ typedef enum{
AES_MODE_CBC = 0x20000020,
AES_MODE_CTR = 0x200001c0,
AES_MODE_CFB = 0x20000400,
AES_MODE_GCM = 0x20030040,
AES_MODE_CCM = 0x21D40040,
AES_MODE_GCM = 0x20020040,
AES_MODE_CCM = 0x207C0040,
AES_MODE_OFB = 0x24000000,
AES_MODE_XTS = 0x20001800,
AES_MODE_CBC_MAC = 0x2000800C,
} csi_aes_mode_t;
/**
@@ -82,10 +84,16 @@ typedef struct {
*/
typedef struct {
uint32_t key_len_byte;
uint8_t key[32]; /*Data block being processed*/
uint8_t key[32]; /*Data block being processed*/
uint32_t sca;
uint32_t is_kdf;
uint32_t is_dma;
uint64_t HH[16];
uint64_t HL[16];
uint8_t ctr[16];
uint8_t buf[16];
uint32_t origin_add_len;
uint32_t origin_len;
} csi_aes_context_t;
/**
@@ -294,7 +302,7 @@ csi_error_t csi_aes_ctr_decrypt(csi_aes_t *aes,void *in,void *out,uint32_t size,
\param[in] iv init vector
\return error code \ref csi_error_t
*/
csi_error_t csi_aes_gcm_encrypt(csi_aes_t *aes, void *in, void *out,uint32_t size, uint32_t add_len, void *iv);
csi_error_t csi_aes_gcm_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, uint32_t add_len, void *iv, void *tag);
/**
\brief Aes gcm decrypt
@@ -305,7 +313,7 @@ csi_error_t csi_aes_gcm_encrypt(csi_aes_t *aes, void *in, void *out,uint32_t siz
\param[in] iv init vecotr
\return error code \ref csi_error_t
*/
csi_error_t csi_aes_gcm_decrypt(csi_aes_t *aes, void *in, void *out,uint32_t size, uint32_t add_len, void *iv);
csi_error_t csi_aes_gcm_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, uint32_t add_len, void *iv, void *tag);
/**
\brief Aes ccm encrypt
@@ -317,7 +325,7 @@ csi_error_t csi_aes_gcm_decrypt(csi_aes_t *aes, void *in, void *out,uint32_t siz
\param[in] tag_out tag output
\return error code \ref csi_error_t
*/
csi_error_t csi_aes_ccm_encrypt(csi_aes_t *aes, void *in, void *out,uint32_t size, uint32_t add_len, void *iv, uint8_t *tag_out);
csi_error_t csi_aes_ccm_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, uint32_t add_len, void *iv, void *tag);
/**
\brief Aes ccm decrypt
@@ -329,7 +337,7 @@ csi_error_t csi_aes_ccm_encrypt(csi_aes_t *aes, void *in, void *out,uint32_t siz
\param[in] tag_out tag output
\return error code \ref csi_error_t
*/
csi_error_t csi_aes_ccm_decrypt(csi_aes_t *aes, void *in, void *out,uint32_t size, uint32_t add_len, void *iv, uint8_t *tag_out);
csi_error_t csi_aes_ccm_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, uint32_t add_len, void *iv, void *tag);
/**
\brief Enable AES power manage
@@ -347,11 +355,55 @@ void csi_aes_disable_pm(csi_aes_t *aes);
/**
\brief Config AES data transfer mode
\param[in] mode \ref csi_des_trans_mode_t
\param[in] mode \ref csi_des_trans_mode_t
\return None
*/
csi_error_t csi_aes_trans_config(csi_aes_t *aes, csi_aes_trans_mode_t mode);
/**
\brief Aes xts encrypt
\param[in] dev_aes dev_aes handle to operate
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data
\param[in] size the Source data size
\param[in] iv init vector
\param[in] key2 XTS second key
\return error code \ref csi_error_t
*/
csi_error_t csi_aes_xts_encrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv, void *key2);
/**
\brief Aes xts decrypt
\param[in] dev_aes dev_aes handle to operate
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data
\param[in] size the Source data size
\param[in] iv init vecotr
\param[in] key2 XTS second key
\return error code \ref csi_error_t
*/
csi_error_t csi_aes_xts_decrypt(csi_aes_t *aes, void *in, void *out, uint32_t size, void *iv, void *key2);
/**
\brief Aes cbc mac encrypt
\param[in] dev_aes dev_aes handle to operate
\param[in] in Pointer to the Source data
\param[in] size the Source data size
\param[out] tag tag output
\return error code \ref csi_error_t
*/
csi_error_t csi_aes_cbc_mac_encrypt(csi_aes_t *aes, void *in, uint32_t size, void *tag);
/**
\brief Aes cbc mac decrypt
\param[in] dev_aes dev_aes handle to operate
\param[in] in Pointer to the Source data
\param[in] size the Source data size
\param[in] tag tag authen
\return error code \ref csi_error_t
*/
csi_error_t csi_aes_cbc_mac_decrypt(csi_aes_t *aes, void *in, uint32_t size, void *tag);
#ifdef __cplusplus
}
#endif

View File

@@ -27,6 +27,10 @@
#include "crypto_aes.h"
#endif
#ifdef CONFIG_SEC_CRYPTO_GCM_SW
#include "crypto_gcm.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -69,6 +73,9 @@ typedef struct {
#if defined(CONFIG_SEC_CRYPTO_AES_SW)
sc_mbedtls_aes_context aes_ctx;
#endif
#if defined(CONFIG_SEC_CRYPTO_GCM_SW)
mbedtls_gcm_context gcm_ctx;
#endif
} sc_aes_t;
/*Function documentation*/
@@ -87,6 +94,14 @@ uint32_t sc_aes_init(sc_aes_t *aes, uint32_t idx);
*/
void sc_aes_uninit(sc_aes_t *aes);
/**
\brief Aes data transfer config
\param[in] aes handle to operate
\param[in] mode \ref sc_aes_trans_mode_t
\return error code \ref uint32_t
*/
uint32_t sc_aes_trans_config(sc_aes_t *aes, sc_aes_trans_mode_t mode);
/**
\brief Set encrypt key
\param[in] aes handle to operate
@@ -263,53 +278,104 @@ uint32_t sc_aes_ctr_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size,vo
/**
\brief Aes gcm encrypt
\param[in] dev_aes dev_aes handle to operate
\param[in] in Pointer to the Source data.
\param[in] in Pointer to the Source data(add + plaintext, Add can be null,
Add and plaintext must be to an integer multiple of 16Byte)
\param[out] out Pointer to the Result data
\param[in] size the Source data size
\param[in] iv init vector
\param[in] size the Source data true size
\param[in] add_len the Additional authenticated data true size
\param[in] iv Nonce(12Byte)
\param[out] tag tag output(16byte), parse null if not needed
\return error code \ref csi_error_t
*/
uint32_t sc_aes_gcm_encrypt(sc_aes_t *aes, void *in, void *out,uint32_t size, uint32_t add_len, void *iv);
uint32_t sc_aes_gcm_encrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, uint32_t add_len, void *iv, void* tag);
/**
\brief Aes gcm decrypt
\param[in] dev_aes dev_aes handle to operate
\param[in] in Pointer to the Source data.
\param[out] out Pointer to the Result data
\param[in] size the Source data size
\param[in] iv init vecotr
\param[in] in Pointer to the Source data
\param[in] in Pointer to the Source data(add + cipher, Add can be null,
Add and plaintext must be to an integer multiple of 16Byte)
\param[in] size the Source data true size
\param[in] add_len the Additional authenticated data true size
\param[in] iv Nonce(12Byte)
\param[in] tag tag authenticated(16byte), parse null if not needed
\return error code \ref csi_error_t
*/
uint32_t sc_aes_gcm_decrypt(sc_aes_t *aes, void *in, void *out,uint32_t size, uint32_t add_len, void *iv);
uint32_t sc_aes_gcm_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, uint32_t add_len, void *iv, void* tag);
/**
\brief Aes gcm encrypt
\param[in] dev_aes dev_aes handle to operate
\param[in] in Pointer to the Source data.
\param[in] in Pointer to the Source data(add + padding + plaintext + padding, Add can be null,
Add and plaintext must fill to an integer multiple of 16Byte with zero,
ignore this if the value is a multiple of 16)
\param[out] out Pointer to the Result data
\param[in] size the Source data size
\param[in] iv init vector
\param[in] tag_out tag output ,parse null if not needed
\param[in] size the Source data true size
\param[in] add_len the Additional authenticated data true size
\param[in] iv Nonce(only support 7Byte)
\param[out] tag tag authenticated(onlt support 4Byte), parse null if not needed
\return error code \ref csi_error_t
*/
uint32_t sc_aes_ccm_encrypt(sc_aes_t *aes, void *in, void *out,uint32_t size, uint32_t add_len, void *iv, uint8_t* tag_out);
uint32_t sc_aes_ccm_encrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, uint32_t add_len, void *iv, void* tag);
/**
\brief Aes gcm decrypt
\param[in] dev_aes dev_aes handle to operate
\param[in] in Pointer to the Source data.
\param[in] in Pointer to the Source data(add + padding + cipher + padding, Add can be null,
Add and cipher must fill to an integer multiple of 16 with zero,
ignore this if the value is a multiple of 16)
\param[out] out Pointer to the decrypted data
\param[in] size the Source data true size
\param[in] add_len the Additional authenticated data true size
\param[in] iv Nonce(only support 7Byte)
\param[in] tag tag authenticated(onlt support 4Byte), parse null if not needed
\return error code \ref csi_error_t
*/
uint32_t sc_aes_ccm_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, uint32_t add_len, void *iv, void* tag);
/**
\brief Aes xts encrypt
\param[in] aes handle to operate
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data
\param[in] size the Source data size
\param[in] iv init vecotr
\param[in] tag_out tag output,parse null if not needed
\return error code \ref csi_error_t
\param[in] key2 XTS Second key
\return error code \ref uint32_t
*/
uint32_t sc_aes_ccm_decrypt(sc_aes_t *aes, void *in, void *out,uint32_t size, uint32_t add_len, void *iv, uint8_t* tag_out);
uint32_t sc_aes_xts_encrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv, void *key2);
/**
\brief Aes data transfer config
\brief Aes xts decrypt
\param[in] aes handle to operate
\param[in] in Pointer to the Source data
\param[out] out Pointer to the Result data
\param[in] size the Source data size
\param[in] iv init vecotr
\param[in] key2 XTS Second key
\return error code \ref uint32_t
*/
uint32_t sc_aes_trans_config(sc_aes_t *aes, sc_aes_trans_mode_t mode) ;
uint32_t sc_aes_xts_decrypt(sc_aes_t *aes, void *in, void *out, uint32_t size, void *iv, void *key2);
/**
\brief Aes cbc mac encrypt
\param[in] aes handle to operate
\param[in] in Pointer to the Source data
\param[in] size the Source data size
\param[out] tag tag output
\return error code \ref uint32_t
*/
uint32_t sc_aes_cbc_mac_encrypt(sc_aes_t *aes, void *in, uint32_t size, void *tag);
/**
\brief Aes cbc mac decrypt
\param[in] aes handle to operate
\param[in] in Pointer to the Source data
\param[in] size the Source data size
\param[in] tag tag authen
\return error code \ref uint32_t
*/
uint32_t sc_aes_cbc_mac_decrypt(sc_aes_t *aes, void *in, uint32_t size, void *tag);
#ifdef __cplusplus
}

View File

@@ -99,7 +99,7 @@ void sc_ecc_uninit(sc_ecc_t *ecc);
\return \ref uint32_t
*/
uint32_t sc_ecc_config(sc_ecc_t *ecc, sc_ecc_cipher_order_e co,
sc_ecc_endian_mode_e endian);
sc_ecc_endian_mode_e endian);
/**
\brief Attach the callback handler to ECC
@@ -124,7 +124,7 @@ uint32_t sc_ecc_detach_callback(sc_ecc_t *ecc);
*/
uint32_t sc_ecc_get_capabilities(sc_ecc_t *ecc, sc_ecc_capabilities_t *cap);
uint32_t sc_ecc_check_keypair(sc_ecc_t *ecc, uint8_t pubkey[65],
uint32_t sc_ecc_check_keypair(sc_ecc_t *ecc, uint8_t pubkey[64],
uint8_t prikey[32]);
/**
@@ -134,7 +134,7 @@ uint32_t sc_ecc_check_keypair(sc_ecc_t *ecc, uint8_t pubkey[65],
\param[out] public Pointer to the ecc public key, alloc by caller.
\return \ref uint32_t
*/
uint32_t sc_ecc_gen_key(sc_ecc_t *ecc, uint8_t pubkey[65], uint8_t prikey[32]);
uint32_t sc_ecc_gen_key(sc_ecc_t *ecc, uint8_t pubkey[64], uint8_t prikey[32]);
/**
@@ -144,7 +144,7 @@ uint32_t sc_ecc_gen_key(sc_ecc_t *ecc, uint8_t pubkey[65], uint8_t prikey[32]);
\param[out] pubkey Pointer to the ecc public key, alloc by caller.
\return \ref uint32_t
*/
uint32_t sc_ecc_gen_pubkey(sc_ecc_t *ecc, uint8_t pubkey[65],
uint32_t sc_ecc_gen_pubkey(sc_ecc_t *ecc, uint8_t pubkey[64],
uint8_t prikey[32], sc_ecc_curve_type type);
/**
@@ -156,7 +156,7 @@ uint32_t sc_ecc_gen_pubkey(sc_ecc_t *ecc, uint8_t pubkey[65],
\return \ref uint32_t
*/
uint32_t sc_ecc_sign(sc_ecc_t *ecc, uint8_t d[32], uint8_t prikey[32],
uint8_t s[64], sc_ecc_curve_type type);
uint8_t s[64], sc_ecc_curve_type type);
/**
\brief ecc sign
@@ -167,7 +167,7 @@ uint32_t sc_ecc_sign(sc_ecc_t *ecc, uint8_t d[32], uint8_t prikey[32],
\return \ref uint32_t
*/
uint32_t sc_ecc_sign_async(sc_ecc_t *ecc, uint8_t d[32], uint8_t prikey[32],
uint8_t s[64], sc_ecc_curve_type type);
uint8_t s[64], sc_ecc_curve_type type);
/* TODO */
/**
@@ -178,8 +178,8 @@ uint32_t sc_ecc_sign_async(sc_ecc_t *ecc, uint8_t d[32], uint8_t prikey[32],
\param[out] s Pointer to the signature
\return verify result
*/
bool sc_ecc_verify(sc_ecc_t *ecc, uint8_t d[32], uint8_t pubkey[65],
uint8_t s[64], sc_ecc_curve_type type);
bool sc_ecc_verify(sc_ecc_t *ecc, uint8_t d[32], uint8_t pubkey[64],
uint8_t s[64], sc_ecc_curve_type type);
/**
\brief ecc verify
@@ -189,8 +189,8 @@ bool sc_ecc_verify(sc_ecc_t *ecc, uint8_t d[32], uint8_t pubkey[65],
\param[out] s Pointer to the signature
\return verify result
*/
bool sc_ecc_verify_async(sc_ecc_t *ecc, uint8_t d[32], uint8_t pubkey[65],
uint8_t s[64], sc_ecc_curve_type type);
bool sc_ecc_verify_async(sc_ecc_t *ecc, uint8_t d[32], uint8_t pubkey[64],
uint8_t s[64], sc_ecc_curve_type type);
/**
\brief ecc encrypto
@@ -203,7 +203,7 @@ bool sc_ecc_verify_async(sc_ecc_t *ecc, uint8_t d[32], uint8_t pubkey[65],
\return uint32_t
*/
uint32_t sc_ecc_encrypt(sc_ecc_t *ecc, uint8_t *plain, uint32_t plain_len,
uint8_t pubKey[65], uint8_t *cipher,
uint8_t pubKey[64], uint8_t *cipher,
uint32_t *cipher_len);
/**
@@ -237,7 +237,7 @@ uint32_t sc_ecc_exchangekey(sc_ecc_t *ecc, sc_ecc_exchange_role_e role,
\return uint32_t
*/
uint32_t sc_ecc_getZ(sc_ecc_t *ecc, uint8_t *id, uint32_t id_len,
uint8_t pubkey[65], uint8_t z[32]);
uint8_t pubkey[65], uint8_t z[32]);
/**
\brief ecc key exchange get E
@@ -245,7 +245,7 @@ uint32_t sc_ecc_getZ(sc_ecc_t *ecc, uint8_t *id, uint32_t id_len,
\return uint32_t
*/
uint32_t sc_ecc_getE(sc_ecc_t *ecc, uint8_t *m, uint32_t len, uint8_t z[32],
uint8_t e[32]);
uint8_t e[32]);
/**
\brief Get ECC state.

View File

@@ -1,53 +1,104 @@
/*
* Copyright (C) 2017-2022 Alibaba Group Holding Limited
* Copyright (C) 2017-2023 Alibaba Group Holding Limited
*/
/******************************************************************************
* @file sec_crypto_ecdh.h
* @brief Header File for curve25519( a state-of-the-art Diffie-Hellman function)
* @version V3.3
* @date 10. June 2022
* @file sec_crypt_ecdh.h
* @brief Header File for ECDH
* @version V1.0
* @date 12. May 2023
* @model ecdh
******************************************************************************/
#ifndef _SC_ECDH_H_
#define _SC_ECDH_H_
#include "sec_include_config.h"
#define CONFIG_SEC_CRYPTO_ECC
#include <stdint.h>
#include <sec_crypto_errcode.h>
#include <sec_crypto_ecdsa.h>
#ifdef CONFIG_SEC_CRYPTO_ECC
#ifdef CONFIG_SYSTEM_SECURE
#ifdef SEC_LIB_VERSION
#include <drv/ecc.h>
#else
#include "ecc.h"
#endif
#endif
#ifdef CONFIG_SEC_CRYPTO_ECC_SW
#include "crypto_ecc_dsa.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef SEC_LIB_VERSION
#include "drv/ecdh.h"
#include "drv/ecc.h"
#include "sec_crypto_ecc.h"
#else
#include "ecdh.h"
#include "ecc.h"
#include "sec_crypto_ecc.h"
#endif
#define EC_SECP521R1_SECRET_KEY_LEN 32
/**
\brief ecdh calc secret
\param[in] ecc ecc handle to operate.
\param[in] pubkey Pointer to the A(or B) public key.
\param[out] privkey Pointer to the B(or A) private key.
\param[out] out Pointer to the share secret.
\param[out] len length of the share secret.
\return \ref uint32_t.
\brief ECDH Ctrl Block
*/
typedef struct {
#ifdef CONFIG_SYSTEM_SECURE
#ifdef CONFIG_CSI_V1
aes_handle_t handle;
#endif
#ifdef CONFIG_CSI_V2
// csi_ecdh_t csi_ecdh;
csi_ecc_t csi_ecdh;
#endif
#endif
#if defined(CONFIG_TEE_CA)
#endif
#if defined(CONFIG_SEC_CRYPTO_ECC_SW)
uECC_Curve ecdh_ctx;
#endif
} sc_ecdh_t;
uint32_t sc_ecdh_calc_secret(sc_ecc_t *ecc, uint8_t privkey[32],
uint8_t pubkey[65], uint8_t out[32],
uint32_t *len, sc_ecc_curve_type type) ;
// Function documentation
/**
\brief Initialize ECDH interface. Initializes the resources needed for the ECDH interface
\param[in] ecdh Handle to operate
\param[in] idx Device id
\return Error code
*/
uint32_t sc_ecdh_init(sc_ecdh_t *ecdh, uint32_t idx);
/**
\brief De-initialize ECDH interface. Stops operation and releases the software resources used by the interface
\param[in] ecdh Dandle to operate
\return None
*/
void sc_ecdh_uninit(sc_ecdh_t *ecdh);
/**
\brief Load curve param to engin
\param[in] ecdh Handle to operate
\param[in] type Pointer to \ref sc_curve_type_t
\return Error code
*/
uint32_t sc_ecdh_load_curve(sc_ecdh_t *ecdh, sc_curve_type_t type);
/**
\brief ECDH generate key pairs
\param[in] ecdh Handle to operate
\param[out] privkey Pointer to the private key buf
\param[out] pubkey Pointer to the public key buf
\return Error code
*/
uint32_t sc_ecdh_gen_keypair(sc_ecdh_t *ecdh, uint8_t *prikey, uint8_t *pubkey);
/**
\brief ECDH ECDH generate secret key
\param[in] ecdh Handle to operate
\param[in] privkey Pointer to the private key buf of Alice
\param[in] pubkey Pointer to the public key buf of Bob
\param[out] sk Pointer to the secret key buf
\param[out] sk_len The secret key length
\return Error code
*/
uint32_t sc_ecdh_calc_secret(sc_ecdh_t *ecdh, const uint8_t *privkey, const uint8_t *pubkey,
uint8_t *sk, uint32_t *sk_len);
#ifdef __cplusplus
}
#endif
#endif
#endif /* _SC_CURVE15519_H_ */
#endif /* _SC_ECDH_H_ */

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2017-2023 Alibaba Group Holding Limited
*/
/******************************************************************************
* @file seccrypt_ecdsa.h
* @brief Header File for ECDSA
* @version V1.0
* @date 11. May 2023
* @model ecdsa
******************************************************************************/
#ifndef _SC_ECDSA_H_
#define _SC_ECDSA_H_
#include <stdint.h>
#include <sec_crypto_errcode.h>
#ifdef CONFIG_SYSTEM_SECURE
// #include "drv/ecdsa.h"
#endif
#ifdef CONFIG_SEC_CRYPTO_ECC_SW
#include "crypto_ecc_dsa.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
SC_CURVES_SECP256K1 = 0U, /* SECG curve over a 256 bit prime field */
SC_CURVES_SECP384R1, /* NIST/SECG curve over a 384 bit prime field */
SC_CURVES_SECP521R1, /* NIST/SECG curve over a 521 bit prime field */
SC_CURVES_BRAINPOOL256R1, /* RFC 5639 curve over a 256 prime field */
SC_CURVES_BRAINPOOL256T1, /* RFC 5639 curve over a 256 prime field */
SC_CURVES_BRAINPOOL512R1, /* RFC 5639 curve over a 512 prime field */
SC_CURVES_BRAINPOOL512T1, /* RFC 5639 curve over a 512 prime field */
} sc_curve_type_t;
#define EC_SECP521R1_PRIVATE_KEY_LEN 32
#define EC_SECP521R1_PUBLIC_KEY_LEN 64
#define EC_SECP521R1_DIGEST_LEN 32
#define EC_SECP521R1_SIGNATURE_LEN 64
/**
\brief ECDSA Ctrl Block
*/
typedef struct {
#ifdef CONFIG_SYSTEM_SECURE
#ifdef CONFIG_CSI_V1
aes_handle_t handle;
#endif
#ifdef CONFIG_CSI_V2
// csi_ecdsa_t csi_ecdsa;
#endif
#endif
#if defined(CONFIG_TEE_CA)
#endif
#if defined(CONFIG_SEC_CRYPTO_ECC_SW)
uECC_Curve ecdsa_ctx;
#endif
} sc_ecdsa_t;
// Function documentation
/**
\brief Initialize ECDSA interface. Initializes the resources needed for the ECDSA interface
\param[in] ecdsa Handle to operate
\param[in] idx Device id
\return Error code
*/
uint32_t sc_ecdsa_init(sc_ecdsa_t *ecdsa, uint32_t idx);
/**
\brief De-initialize ECDSA interface. Stops operation and releases the software resources used by the interface
\param[in] ecdsa Dandle to operate
\return None
*/
void sc_ecdsa_uninit(sc_ecdsa_t *ecdsa);
/**
\brief Load curve param to engin
\param[in] ecdsa Handle to operate
\param[in] type Pointer to \ref csi_curve_type_t
\return Error code
*/
uint32_t sc_ecdsa_load_curve(sc_ecdsa_t *ecdsa, sc_curve_type_t type);
/**
\brief Ecdsa Sign
\param[in] ecdsa Handle to operate
\param[in] prikey Pointer to the private key buf
\param[in] prikey_len The private key length
\param[in] dgst Pointer to the digest buf
\param[in] dgst_len The digest length
\param[out] sig Pointer to the signature buf
\param[out] sig_len The signature length
\return Error code
*/
uint32_t sc_ecdsa_sign(sc_ecdsa_t *ecdsa, const uint8_t *prikey, uint32_t prikey_len,
const uint8_t *dgst, uint32_t dgst_len, uint8_t *sig, uint32_t *sig_len);
/**
\brief Ecdsa Verify
\param[in] ecdsa Handle to operate
\param[in] pubkey Pointer to the public key buf
\param[in] prikey_len The public key length
\param[in] dgst Pointer to the digest buf
\param[in] dgst_len The digest length
\param[in] sig Pointer to the signature buf
\param[in] sig_len The signature length
\return Error code
*/
uint32_t sc_ecdsa_verify(sc_ecdsa_t *ecdsa, const uint8_t *pubkey, uint32_t pubkey_len,
const uint8_t *dgst, uint32_t gst_len, const uint8_t *sig, uint32_t sig_len);
#ifdef __cplusplus
}
#endif
#endif /* _SC_ECDSA_H_ */

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) 2017-2020 Alibaba Group Holding Limited
*/
/******************************************************************************
* @file seccrypt_aes.h
* @brief Header File for AES
* @version V1.0
* @date 20. Jul 2020
* @model aes
******************************************************************************/
#ifndef _SC_GCM_H_
#define _SC_GCM_H_
#include "sec_include_config.h"
#include <stdint.h>
#include "sec_crypto_errcode.h"
#ifdef CONFIG_SEC_CRYPTO_AES_SW
#include "crypto_aes.h"
#include <sec_crypto_aes.h>
#endif
#ifdef CONFIG_SEC_CRYPTO_GCM_SW
#include "crypto_gcm.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*Function documentation*/
/**
\brief Initialize AES Interface. Initializes the resources needed for the AES interface
\param[in] aes operate handle
\param[in] idx device id
\return error code \ref uint32_t
*/
uint32_t sc_gcm_init(sc_aes_t *aes, uint32_t idx);
/**
\brief De-initialize AES Interface. stops operation and releases the software resources used by the interface
\param[in] aes handle to operate
\return None
*/
void sc_gcm_uninit(sc_aes_t *aes);
/**
\brief Set encrypt key
\param[in] aes handle to operate
\param[in] key Pointer to the key buf
\param[in] key_len Pointer to \ref sc_aes_key_bits_t
\return error code \ref uint32_t
*/
uint32_t sc_gcm_set_encrypt_key(sc_aes_t *aes, void *key, sc_aes_key_bits_t key_len);
/**
\brief Set decrypt key
\param[in] aes handle to operate
\param[in] key Pointer to the key buf
\param[in] key_len Pointer to \ref sc_aes_key_bits_t
\return error code \ref uint32_t
*/
uint32_t sc_gcm_set_decrypt_key(sc_aes_t *aes, void *key, sc_aes_key_bits_t key_len);
/**
\brief gcm encrypt data
\param[in] aes aes handle to operate
\param[in] length Length of plaintext buffer
\param[in] iv_len Length of iv buffer
\param[in] add Pointer to the add buf, can be NULL
\param[in] add_len Length of add buffer, can ben zero
\param[in] input Pointer to the plaintext buf
\param[in] output Pointer to the cipher buf
\param[in] tag_len Length of tag buffer
\param[in] tag Pointer to the tag buf
\return error code \ref uint32_t
*/
uint32_t sc_gcm_encrypt_and_tag(sc_aes_t *aes, uint32_t length,
const void *iv,
uint32_t iv_len,
const void *add,
uint32_t add_len,
const void *input,
void *output,
uint32_t tag_len,
void *tag);
/**
\brief Aes gcm decrypt
\param[in] aes aes handle to operate
\param[in] length Length of cipher buffer
\param[in] iv Pointer to the iv buf
\param[in] iv_len Length of iv buffer
\param[in] add Pointer to the add buf, can be NULL
\param[in] add_len Length of add buffer, can ben zero
\param[in] input Pointer to the cipher buf
\param[in] output Pointer to the plaintext buf
\param[in] tag_len Length of tag buffer
\param[in] tag Pointer to the tag buf
\return error code \ref uint32_t
*/
uint32_t sc_gcm_auth_decrypt(sc_aes_t *aes, uint32_t length,
const void *iv,
uint32_t iv_len,
const void *add,
uint32_t add_len,
const void *tag,
uint32_t tag_len,
const void *input,
void *output);
#ifdef __cplusplus
}
#endif
#endif /* _SC_AES_H_ */

View File

@@ -0,0 +1,100 @@
#ifndef __SEC_ECIES_CRYPTO_H__
#define __SEC_ECIES_CRYPTO_H__
#ifdef _WIN32
#include "win_ctypes.h"
#else
#include <linux/types.h>
#endif
/**
\brief Ecies malloc
\param[in] size
\return error code \ref int
*/
void *csi_ecies_malloc(uint32_t size);
/**
\brief Ecies free
\param[in] buffer
\return error code \ref int
*/
void csi_ecies_free(void *buffer);
/**
\brief Ecies transmit apdu command message
\param[in] ss session handle to operate
\param[in] apdu Pointer to the apdu buf
\param[in] apduLen Length of apdu buffer
\param[out] apduResponse Pointer to the apduResponse buf
\param[out] apduResponseLen Length of apduResponse buffer
\return error code \ref int
*/
int csi_ecies_transmit_apdu(void *ss, const uint8_t *apdu,
uint32_t apduLen, uint8_t *apduResponse, uint32_t *apduResponseLen);
/**
\brief Ecies generate ec key pair
\param[in] ss session handle to operate
\param[out] privateKey Pointer to the private key buf
\param[out] privateKeyLen Length of private key
\param[out] publicKey Pointer to the public key buf
\param[out] publicKeyLen Length of public key
\return error code \ref int
*/
int csi_ecies_generate_keypair(void *ss, uint8_t *privateKey, uint32_t *privateKeyLen,
uint8_t *publicKey, uint32_t *publicKeyLen);
/**
\brief Ecies generate ec share key
\param[in] ss session handle to operate
\param[in] privateKey Pointer to the private key buf
\param[in] privateKeyLen Length of private key
\param[in] publicKey Pointer to the public key buf
\param[in] publicKeyLen Length of public key
\param[out] shareKey Pointer to the share key buf
\param[out] shareKeyLen Length of share key
\return error code \ref int
*/
int csi_ecies_generate_share_key(void *ss, const uint8_t *privateKey, uint32_t privateKeyLen,
const uint8_t *publicKey, uint32_t publicKeyLen, uint8_t *shareKey, uint32_t *shareKeyLen);
/**
\brief Ecies kdf ec share key
\param[in] ss session handle to operate
\param[in] shareKey Pointer to the share key buf
\param[in] shareKeyLen Length of share key
\param[in] encKeyLen Length of encrypt key
\param[out] encKey Pointer to the encrypt key buf
\param[in] macKeyLen Length of mac key
\param[out] macKey Pointer to the mac key buf
\return error code \ref int
*/
int csi_ecies_kdf_key(void *ss, const uint8_t *shareKey, uint32_t shareKeyLen,
uint32_t encKeyLen, uint8_t *encKey, uint32_t macKeyLen, uint8_t *macKey);
/**
\brief Ecies encrypt and generate tag
\param[in] ss session handle to operate
\param[in] length Length of input buffer
\param[in] input Pointer to the input buf
\param[out] output Pointer to the output buf
\param[in] tagLen Length of tag
\param[out] tag Pointer to the tag buf
\return error code \ref int
*/
int csi_ecies_encrypt_and_tag(void *ss, uint32_t length, const uint8_t *input, uint8_t *output,
uint32_t tagLen, uint8_t *tag);
/**
\brief Ecies auth tag and decrypt
\param[in] ss session handle to operate
\param[in] length Length of input buffer
\param[in] tag Pointer to the tag buf
\param[in] tagLen Length of tag
\param[in] input Pointer to the input buf
\param[out] output Pointer to the output buf
\return error code \ref int
*/
int csi_ecies_auth_decrypt(void *ss, uint32_t length, const uint8_t *tag, uint32_t tagLen,
const uint8_t *input, uint8_t *output);
#endif /* __SEC_ECIES_CRYPTO_H__ */

View File

@@ -0,0 +1,170 @@
#ifndef __SEC_ECIES_SESSION_H__
#define __SEC_ECIES_SESSION_H__
#ifdef _WIN32
#include "win_ctypes.h"
#else
#include <linux/types.h>
#endif
#include <stdint.h>
#define ECIES_SDATA_MAX_LEN (1024*1024*16)
#define ECIES_SDATA_RESPONSE_LEN 256
#define ECIES_INIT_COMMAND_LEN 256
#define ECIES_INIT_RESPONSE_LEN 256
#define ECIES_CLOSE_COMMAND_LEN 32
#define ECIES_CLOSE_RESPONSE_LEN 32
#define ECIES_FIXED_COMMAND_LEN 16
#define ECIES_KEY_LEN 128
#define ECIES_TAG_LEN 16
#define ECIES_TAG_LEN 16
#define ECIES_DID_LEN 16
#define ECIES_SEQ_DEFAULT 0x8000E000
#define ECIES_TIMEOUT_TIME 5 /* seconds */
#define ECIES_CLA_INITIALIZE_UPDATE 0x10
#define ECIES_CLA_INITIALIZE_UPDATE_RESPONSE 0x20
#define ECIES_CLA_SDATA_SEND 0x30
#define ECIES_CLA_SDATA_SEND_RESPONSE 0x40
#define ECIES_CLA_SESSION_CLOSE 0x50
#define ECIES_CLA_SESSION_CLOSE_RESPONSE 0x60
#define ECIES_RESPONSE_OK 0x90
#define ECIES_RESPONSE_SESSION_OPENED_ERROR 0x91
#define ECIES_RESPONSE_GEN_KEY_PAIR_ERROR 0x92
#define ECIES_RESPONSE_GEN_SHARE_KEY_ERROR 0x93
#define ECIES_RESPONSE_GEN_AUTH_DECRYPT_ERROR 0x94
#define ECIES_RESPONSE_SESSION_MEM_ERROR 0x95
#define ECIES_RESPONSE_SESSION_SEQ_ERROR 0x96
#define ECIES_RESPONSE_SESSION_SID_ERROR 0x97
#define ECIES_CLA_LEN 0x01
#define ECIES_INS_LEN 0x01
#define ECIES_P0_LEN 0x04
#define ECIES_P1_LEN 0x04
#define ECIES_P2_LEN 0x01
#define ECIES_LC_LEN 0x04
#define ECIES_LE_LEN 0x01
#define ECIES_CLA_OFFSET 0x00
#define ECIES_INS_OFFSET (ECIES_CLA_OFFSET + ECIES_CLA_LEN)
#define ECIES_P0_OFFSET (ECIES_INS_OFFSET + ECIES_INS_LEN)
#define ECIES_P1_OFFSET (ECIES_P0_OFFSET + ECIES_P0_LEN)
#define ECIES_P2_OFFSET (ECIES_P1_OFFSET + ECIES_P1_LEN)
#define ECIES_LC_OFFSET (ECIES_P2_OFFSET + ECIES_P2_LEN)
#define ECIES_DATA_OFFSET (ECIES_LC_OFFSET + ECIES_LC_LEN)
enum {
ECIES_SS_CLOSE = 0,
ECIES_SS_OPEN,
};
typedef struct _ecies_dev {
void *context;
void *transmit;
uint8_t DID[ECIES_DID_LEN];
uint8_t DIDLen;
} ecies_dev;
typedef struct _ecies_session_t {
ecies_dev dev;
uint8_t schemeType;
uint8_t shareKeyLen;
uint8_t encKeyLen;
uint8_t macKeyLen;
uint8_t shareKey[ECIES_KEY_LEN];
uint8_t encKey[ECIES_KEY_LEN];
uint8_t macKey[ECIES_KEY_LEN];
uint32_t sequenceNumber;
uint32_t SID;
uint32_t timeout;
uint32_t isOpen;
} ecies_session_t;
typedef enum {
EC_PRIME256V1_AES_GCM_256 = 0,
}scheme_type;
/**
\brief Ecies host initialization session
\param[in] session session handle to operate
\param[in] context Pointer to the user-defined context
\param[in] transmit Pointer to the user-implemented transfer
\param[in] schemeType Security scheme selection
\param[in] DID Pointer to the device ID buf
\param[in] DIDLen Length of the device ID
\return error code \ref int
*/
int hal_ecies_host_init(ecies_session_t *session, void *context, void *transmit, uint8_t schemeType, uint8_t *DID, uint32_t DIDLen);
/**
\brief Ecies host session
\param[in] session session handle to operate
\return error code \ref int
*/
int hal_ecies_host_session_open(ecies_session_t *session);
/**
\brief Ecies host comm session
\param[in] session session handle to operate
\param[in] data Pointer to the data to be encrypted
\param[in] data_len Length of the data
\return error code \ref int
*/
int hal_ecies_host_session_comm(ecies_session_t *session, uint8_t *data, uint32_t dataLen);
/**
\brief Ecies host close session
\param[in] session session handle to operate
\return error code \ref int
*/
int hal_ecies_host_session_close(ecies_session_t *session);
/**
\brief Ecies host uninitiated session
\param[in] session session handle to operate
\return error code \ref int
*/
int hal_ecies_host_uninit(ecies_session_t *session);
/**
\brief Ecies slave initialization session
\param[in] session session handle to operate
\return error code \ref int
*/
int hal_ecies_slave_init(ecies_session_t *session);
/**
\brief Ecies slave comm session
\param[in] session session handle to operate
\param[in] apdu Pointer to the apdu buf
\param[in] apduLen Length of the apdu buffer
\param[out] apduResponse Pointer to the apduResponse buf
\param[out] apduResponseLen Length of the apduResponseLen buffer
\param[out] out Pointer to the out buf to be decrypted
\param[out] outLen Length of the out buffer
\return error code \ref int
*/
int hal_ecies_slave_session_comm(ecies_session_t *session, uint8_t *apdu, uint32_t apduLen,
uint8_t *apduResponse, uint32_t *apduResponseLen, uint8_t *out, uint32_t *outLen);
/**
\brief Ecies slave uninitiated session
\param[in] session session handle to operate
\return error code \ref int
*/
int hal_ecies_slave_uninit(ecies_session_t *session);
/**
\brief Ecies host get CLA and errcode
\param[in] apduResponse Pointer to the apduResponse buf
\param[in] apduResponseLen Length of the apduResponseLen buffer
\param[out] CLA CLA one byte len
\param[out] errcode Error code one byte len
\return error code \ref int
*/
int hal_ecies_status_get(uint8_t *apduResponse, uint32_t apduResponseLen, uint8_t *CLA, uint8_t *status);
#endif /* __SEC_ECIES_SESSION_H__ */

View File

@@ -28,6 +28,8 @@
#include "sec_crypto_ecc.h"
#include "sec_crypto_ecdh.h"
#include "csi_sec_img_verify.h"
#include "sec_ecies_crypto.h"
#include "sec_ecies_session.h"
/* NOTE add more header */
#endif /* _SL_H_ */

View File

@@ -0,0 +1,320 @@
/**
* \file aes.h
*
* \brief AES block cipher
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef SC_MBEDTLS_AES_H
#define SC_MBEDTLS_AES_H
#include "crypto_config.h"
#include <stddef.h>
#include <stdint.h>
#include "sec_crypto_errcode.h"
/* padlock.c and aesni.c rely on these values! */
#define MBEDTLS_AES_ENCRYPT 1
#define MBEDTLS_AES_DECRYPT 0
#define SC_MBEDTLS_ERR_AES_INVALID_KEY_LENGTH SC_INVALID_KEY_LENGTH /**< Invalid key length. */
#define SC_MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH SC_INVALID_INPUT_LENGTH /**< Invalid data input length. */
// Regular implementation
//
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief AES context structure
*
* \note buf is able to hold 32 extra bytes, which can be used:
* - for alignment purposes if VIA padlock is used, and/or
* - to simplify key expansion in the 256-bit case by
* generating an extra round key
*/
typedef struct
{
int nr; /*!< number of rounds */
uint32_t *rk; /*!< AES round keys */
uint32_t buf[68]; /*!< unaligned data */
}
sc_mbedtls_aes_context;
/**
* \brief Initialize AES context
*
* \param ctx AES context to be initialized
*/
void sc_mbedtls_aes_init( sc_mbedtls_aes_context *ctx );
/**
* \brief Clear AES context
*
* \param ctx AES context to be cleared
*/
void sc_mbedtls_aes_free( sc_mbedtls_aes_context *ctx );
/**
* \brief AES key schedule (encryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or SC_MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int sc_mbedtls_aes_setkey_enc( sc_mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
* \brief AES key schedule (decryption)
*
* \param ctx AES context to be initialized
* \param key decryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or SC_MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int sc_mbedtls_aes_setkey_dec( sc_mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int sc_mbedtls_aes_crypt_ecb( sc_mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or SC_MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
*/
int sc_mbedtls_aes_crypt_cbc( sc_mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* sc_mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int sc_mbedtls_aes_crypt_cfb128( sc_mbedtls_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CFB8 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* sc_mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int sc_mbedtls_aes_crypt_cfb8( sc_mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* sc_mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \param ctx AES context
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
int sc_mbedtls_aes_crypt_ctr( sc_mbedtls_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*
* \return 0 if successful
*/
int sc_mbedtls_internal_aes_encrypt( sc_mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_DECRYPT_ALT)
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*
* \return 0 if successful
*/
int sc_mbedtls_internal_aes_decrypt( sc_mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_ENCRYPT_ALT)
*
* \deprecated Superseded by sc_mbedtls_aes_encrypt_ext() in 2.5.0
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
static inline void sc_mbedtls_aes_encrypt(
sc_mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
sc_mbedtls_internal_aes_encrypt( ctx, input, output );
}
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_DECRYPT_ALT)
*
* \deprecated Superseded by sc_mbedtls_aes_decrypt_ext() in 2.5.0
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*/
static inline void sc_mbedtls_aes_decrypt(
sc_mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
sc_mbedtls_internal_aes_decrypt( ctx, input, output );
}
#ifdef __cplusplus
}
#endif
#endif /* aes.h */

View File

@@ -0,0 +1,336 @@
/**
* \file asn1.h
*
* \brief Generic ASN.1 parsing
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef SC_MBEDTLS_ASN1_H
#define SC_MBEDTLS_ASN1_H
#include "crypto_config.h"
#include <stddef.h>
#include "crypto_bignum.h"
/**
* \addtogroup asn1_module
* \{
*/
/**
* \name ASN1 Error codes
* These error codes are OR'ed to X509 error codes for
* higher error granularity.
* ASN1 is a standard to specify data structures.
* \{
*/
#define SC_MBEDTLS_ERR_ASN1_OUT_OF_DATA SC_INVALID_FORMAT /**< Out of data when parsing an ASN1 data structure. */
#define SC_MBEDTLS_ERR_ASN1_UNEXPECTED_TAG SC_INVALID_FORMAT /**< ASN1 tag was of an unexpected value. */
#define SC_MBEDTLS_ERR_ASN1_INVALID_LENGTH SC_INVALID_FORMAT /**< Error when trying to determine the length or invalid length. */
#define SC_MBEDTLS_ERR_ASN1_LENGTH_MISMATCH SC_INVALID_FORMAT /**< Actual length differs from expected length. */
#define SC_MBEDTLS_ERR_ASN1_INVALID_DATA SC_INVALID_FORMAT /**< Data is invalid. (not used) */
#define SC_MBEDTLS_ERR_ASN1_ALLOC_FAILED SC_INVALID_FORMAT /**< Memory allocation failed */
#define SC_MBEDTLS_ERR_ASN1_BUF_TOO_SMALL SC_INVALID_FORMAT /**< Buffer too small when writing ASN.1 data structure. */
/* \} name */
/**
* \name DER constants
* These constants comply with DER encoded the ANS1 type tags.
* DER encoding uses hexadecimal representation.
* An example DER sequence is:\n
* - 0x02 -- tag indicating INTEGER
* - 0x01 -- length in octets
* - 0x05 -- value
* Such sequences are typically read into \c ::mbedtls_x509_buf.
* \{
*/
#define MBEDTLS_ASN1_BOOLEAN 0x01
#define MBEDTLS_ASN1_INTEGER 0x02
#define MBEDTLS_ASN1_BIT_STRING 0x03
#define MBEDTLS_ASN1_OCTET_STRING 0x04
#define MBEDTLS_ASN1_NULL 0x05
#define MBEDTLS_ASN1_OID 0x06
#define MBEDTLS_ASN1_UTF8_STRING 0x0C
#define MBEDTLS_ASN1_SEQUENCE 0x10
#define MBEDTLS_ASN1_SET 0x11
#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13
#define MBEDTLS_ASN1_T61_STRING 0x14
#define MBEDTLS_ASN1_IA5_STRING 0x16
#define MBEDTLS_ASN1_UTC_TIME 0x17
#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18
#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C
#define MBEDTLS_ASN1_BMP_STRING 0x1E
#define MBEDTLS_ASN1_PRIMITIVE 0x00
#define MBEDTLS_ASN1_CONSTRUCTED 0x20
#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80
/* \} name */
/* \} addtogroup asn1_module */
/** Returns the size of the binary string, without the trailing \\0 */
#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1)
/**
* Compares an sc_mbedtls_asn1_buf structure to a reference OID.
*
* Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a
* 'unsigned char *oid' here!
*/
#define MBEDTLS_OID_CMP(oid_str, oid_buf) \
( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \
memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 )
#ifdef __cplusplus
extern "C" {
#endif
/**
* \name Functions to parse ASN.1 data structures
* \{
*/
/**
* Type-length-value structure that allows for ASN1 using DER.
*/
typedef struct sc_mbedtls_asn1_buf
{
int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */
size_t len; /**< ASN1 length, in octets. */
unsigned char *p; /**< ASN1 data, e.g. in ASCII. */
}
sc_mbedtls_asn1_buf;
/**
* Container for ASN1 bit strings.
*/
typedef struct sc_mbedtls_asn1_bitstring
{
size_t len; /**< ASN1 length, in octets. */
unsigned char unused_bits; /**< Number of unused bits at the end of the string */
unsigned char *p; /**< Raw ASN1 data for the bit string */
}
sc_mbedtls_asn1_bitstring;
/**
* Container for a sequence of ASN.1 items
*/
typedef struct sc_mbedtls_asn1_sequence
{
sc_mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */
struct sc_mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */
}
sc_mbedtls_asn1_sequence;
/**
* Container for a sequence or list of 'named' ASN.1 data items
*/
typedef struct sc_mbedtls_asn1_named_data
{
sc_mbedtls_asn1_buf oid; /**< The object identifier. */
sc_mbedtls_asn1_buf val; /**< The named value. */
struct sc_mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */
unsigned char next_merged; /**< Merge next item into the current one? */
}
sc_mbedtls_asn1_named_data;
/**
* \brief Get the length of an ASN.1 element.
* Updates the pointer to immediately behind the length.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param len The variable that will receive the value
*
* \return 0 if successful, SC_MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching
* end of data, SC_MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is
* unparseable.
*/
int sc_mbedtls_asn1_get_len( unsigned char **p,
const unsigned char *end,
size_t *len );
/**
* \brief Get the tag and length of the tag. Check for the requested tag.
* Updates the pointer to immediately behind the tag and length.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param len The variable that will receive the length
* \param tag The expected tag
*
* \return 0 if successful, SC_MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did
* not match requested tag, or another specific ASN.1 error code.
*/
int sc_mbedtls_asn1_get_tag( unsigned char **p,
const unsigned char *end,
size_t *len, int tag );
/**
* \brief Retrieve a boolean ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param val The variable that will receive the value
*
* \return 0 if successful or a specific ASN.1 error code.
*/
int sc_mbedtls_asn1_get_bool( unsigned char **p,
const unsigned char *end,
int *val );
/**
* \brief Retrieve an integer ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param val The variable that will receive the value
*
* \return 0 if successful or a specific ASN.1 error code.
*/
int sc_mbedtls_asn1_get_int( unsigned char **p,
const unsigned char *end,
int *val );
/**
* \brief Retrieve a bitstring ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param bs The variable that will receive the value
*
* \return 0 if successful or a specific ASN.1 error code.
*/
int sc_mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
sc_mbedtls_asn1_bitstring *bs);
/**
* \brief Retrieve a bitstring ASN.1 tag without unused bits and its
* value.
* Updates the pointer to the beginning of the bit/octet string.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param len Length of the actual bit/octect string in bytes
*
* \return 0 if successful or a specific ASN.1 error code.
*/
int sc_mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
size_t *len );
/**
* \brief Parses and splits an ASN.1 "SEQUENCE OF <tag>"
* Updated the pointer to immediately behind the full sequence tag.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param cur First variable in the chain to fill
* \param tag Type of sequence
*
* \return 0 if successful or a specific ASN.1 error code.
*/
int sc_mbedtls_asn1_get_sequence_of( unsigned char **p,
const unsigned char *end,
sc_mbedtls_asn1_sequence *cur,
int tag);
#if defined(MBEDTLS_BIGNUM_C)
/**
* \brief Retrieve a MPI value from an integer ASN.1 tag.
* Updates the pointer to immediately behind the full tag.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param X The MPI that will receive the value
*
* \return 0 if successful or a specific ASN.1 or MPI error code.
*/
int sc_mbedtls_asn1_get_mpi( unsigned char **p,
const unsigned char *end,
sc_mbedtls_mpi *X );
#endif /* MBEDTLS_BIGNUM_C */
/**
* \brief Retrieve an AlgorithmIdentifier ASN.1 sequence.
* Updates the pointer to immediately behind the full
* AlgorithmIdentifier.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param alg The buffer to receive the OID
* \param params The buffer to receive the params (if any)
*
* \return 0 if successful or a specific ASN.1 or MPI error code.
*/
int sc_mbedtls_asn1_get_alg( unsigned char **p,
const unsigned char *end,
sc_mbedtls_asn1_buf *alg, sc_mbedtls_asn1_buf *params );
/**
* \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no
* params.
* Updates the pointer to immediately behind the full
* AlgorithmIdentifier.
*
* \param p The position in the ASN.1 data
* \param end End of data
* \param alg The buffer to receive the OID
*
* \return 0 if successful or a specific ASN.1 or MPI error code.
*/
int sc_mbedtls_asn1_get_alg_null( unsigned char **p,
const unsigned char *end,
sc_mbedtls_asn1_buf *alg );
/**
* \brief Find a specific named_data entry in a sequence or list based on
* the OID.
*
* \param list The list to seek through
* \param oid The OID to look for
* \param len Size of the OID
*
* \return NULL if not found, or a pointer to the existing entry.
*/
sc_mbedtls_asn1_named_data *sc_mbedtls_asn1_find_named_data( sc_mbedtls_asn1_named_data *list,
const char *oid, size_t len );
/**
* \brief Free a sc_mbedtls_asn1_named_data entry
*
* \param entry The named data entry to free
*/
void sc_mbedtls_asn1_free_named_data( sc_mbedtls_asn1_named_data *entry );
/**
* \brief Free all entries in a sc_mbedtls_asn1_named_data list
* Head will be set to NULL
*
* \param head Pointer to the head of the list of named data entries to free
*/
void sc_mbedtls_asn1_free_named_data_list( sc_mbedtls_asn1_named_data **head );
#ifdef __cplusplus
}
#endif
#endif /* asn1.h */

View File

@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2014, STMicroelectronics International N.V.
*/
#ifndef BASE64_H
#define BASE64_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
bool _base64_enc(const void *data, size_t size, char *buf, size_t *blen);
bool _base64_dec(const char *data, size_t size, void *buf, size_t *blen);
size_t _base64_enc_len(size_t size);
#endif /* BASE64_H */

View File

@@ -0,0 +1,670 @@
/**
* \file bignum.h
*
* \brief Multi-precision integer library
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef SC_MBEDTLS_BIGNUM_H
#define SC_MBEDTLS_BIGNUM_H
#include "crypto_config.h"
#include <stddef.h>
#include <stdint.h>
#include "sec_crypto_errcode.h"
#define SC_MBEDTLS_ERR_MPI_BAD_INPUT_DATA SC_PARAM_INV /**< Bad input parameters to function. */
#define SC_MBEDTLS_ERR_MPI_INVALID_CHARACTER \
SC_PARAM_INV /**< There is an invalid character in the digit string. */
#define SC_MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL SC_BUFFER_TOO_SMALL /**< The buffer is too small to write to. */
#define SC_MBEDTLS_ERR_MPI_NEGATIVE_VALUE \
SC_PARAM_INV /**< The input arguments are negative or result in illegal output. */
#define SC_MBEDTLS_ERR_MPI_DIVISION_BY_ZERO \
SC_PARAM_INV /**< The input argument for division is zero, which is not allowed. */
#define SC_MBEDTLS_ERR_MPI_NOT_ACCEPTABLE SC_PARAM_INV /**< The input arguments are not acceptable. */
#define SC_MBEDTLS_ERR_MPI_ALLOC_FAILED SC_ALLOC_FAILED /**< Memory allocation failed. */
#define SC_MBEDTLS_MPI_CHK(f) \
do { \
if ((ret = f) != 0) \
goto cleanup; \
} while (0)
/*
* Maximum size MPIs are allowed to grow to in number of limbs.
*/
#define SC_MBEDTLS_MPI_MAX_LIMBS 10000
#if !defined(SC_MBEDTLS_MPI_WINDOW_SIZE)
/*
* Maximum window size used for modular exponentiation. Default: 6
* Minimum value: 1. Maximum value: 6.
*
* Result is an array of ( 2 << SC_MBEDTLS_MPI_WINDOW_SIZE ) MPIs used
* for the sliding window calculation. (So 64 by default)
*
* Reduction in size, reduces speed.
*/
#define SC_MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
#endif /* !SC_MBEDTLS_MPI_WINDOW_SIZE */
#if !defined(SC_MBEDTLS_MPI_MAX_SIZE)
/*
* Maximum size of MPIs allowed in bits and bytes for user-MPIs.
* ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )
*
* Note: Calculations can results temporarily in larger MPIs. So the number
* of limbs required (SC_MBEDTLS_MPI_MAX_LIMBS) is higher.
*/
#define SC_MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */
#endif /* !SC_MBEDTLS_MPI_MAX_SIZE */
#define SC_MBEDTLS_MPI_MAX_BITS \
(8 * SC_MBEDTLS_MPI_MAX_SIZE) /**< Maximum number of bits for usable MPIs. */
/*
* When reading from files with sc_mbedtls_mpi_read_file() and writing to files with
* sc_mbedtls_mpi_write_file() the buffer should have space
* for a (short) label, the MPI (in the provided radix), the newline
* characters and the '\0'.
*
* By default we assume at least a 10 char label, a minimum radix of 10
* (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).
* Autosized at compile time for at least a 10 char label, a minimum radix
* of 10 (decimal) for a number of SC_MBEDTLS_MPI_MAX_BITS size.
*
* This used to be statically sized to 1250 for a maximum of 4096 bit
* numbers (1234 decimal chars).
*
* Calculate using the formula:
* SC_MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(SC_MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) +
* LabelSize + 6
*/
#define SC_SC_MBEDTLS_MPI_MAX_BITS_SCALE100 (100 * SC_MBEDTLS_MPI_MAX_BITS)
#define SC_MBEDTLS_LN_2_DIV_LN_10_SCALE100 332
#define SC_MBEDTLS_MPI_RW_BUFFER_SIZE \
(((SC_SC_MBEDTLS_MPI_MAX_BITS_SCALE100 + SC_MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / \
SC_MBEDTLS_LN_2_DIV_LN_10_SCALE100) + \
10 + 6)
/*
* Define the base integer type, architecture-wise.
*
* 32-bit integers can be forced on 64-bit arches (eg. for testing purposes)
* by defining SC_MBEDTLS_HAVE_INT32 and undefining MBEDTLS_HAVE_ASM
*/
#define SC_MBEDTLS_HAVE_INT32
typedef int32_t sc_mbedtls_mpi_sint;
typedef uint32_t sc_mbedtls_mpi_uint;
//typedef uint64_t mbedtls_t_udbl;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief MPI structure
*/
typedef struct {
int s; /*!< integer sign */
size_t n; /*!< total # of limbs */
sc_mbedtls_mpi_uint *p; /*!< pointer to limbs */
} sc_mbedtls_mpi;
/**
* \brief Initialize one MPI (make internal references valid)
* This just makes it ready to be set or freed,
* but does not define a value for the MPI.
*
* \param X One MPI to initialize.
*/
void sc_mbedtls_mpi_init(sc_mbedtls_mpi *X);
/**
* \brief Unallocate one MPI
*
* \param X One MPI to unallocate.
*/
void sc_mbedtls_mpi_free(sc_mbedtls_mpi *X);
/**
* \brief Enlarge to the specified number of limbs
*
* \param X MPI to grow
* \param nblimbs The target number of limbs
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_grow(sc_mbedtls_mpi *X, size_t nblimbs);
/**
* \brief Resize down, keeping at least the specified number of limbs
*
* \param X MPI to shrink
* \param nblimbs The minimum number of limbs to keep
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_shrink(sc_mbedtls_mpi *X, size_t nblimbs);
/**
* \brief Copy the contents of Y into X
*
* \param X Destination MPI
* \param Y Source MPI
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_copy(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *Y);
/**
* \brief Swap the contents of X and Y
*
* \param X First MPI value
* \param Y Second MPI value
*/
void sc_mbedtls_mpi_swap(sc_mbedtls_mpi *X, sc_mbedtls_mpi *Y);
/**
* \brief Safe conditional assignement X = Y if assign is 1
*
* \param X MPI to conditionally assign to
* \param Y Value to be assigned
* \param assign 1: perform the assignment, 0: keep X's original value
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
*
* \note This function is equivalent to
* if( assign ) sc_mbedtls_mpi_copy( X, Y );
* except that it avoids leaking any information about whether
* the assignment was done or not (the above code may leak
* information through branch prediction and/or memory access
* patterns analysis).
*/
int sc_mbedtls_mpi_safe_cond_assign(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *Y,
unsigned char assign);
/**
* \brief Safe conditional swap X <-> Y if swap is 1
*
* \param X First sc_mbedtls_mpi value
* \param Y Second sc_mbedtls_mpi value
* \param assign 1: perform the swap, 0: keep X and Y's original values
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
*
* \note This function is equivalent to
* if( assign ) sc_mbedtls_mpi_swap( X, Y );
* except that it avoids leaking any information about whether
* the assignment was done or not (the above code may leak
* information through branch prediction and/or memory access
* patterns analysis).
*/
int sc_mbedtls_mpi_safe_cond_swap(sc_mbedtls_mpi *X, sc_mbedtls_mpi *Y, unsigned char assign);
/**
* \brief Set value from integer
*
* \param X MPI to set
* \param z Value to use
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_lset(sc_mbedtls_mpi *X, sc_mbedtls_mpi_sint z);
/**
* \brief Get a specific bit from X
*
* \param X MPI to use
* \param pos Zero-based index of the bit in X
*
* \return Either a 0 or a 1
*/
int sc_mbedtls_mpi_get_bit(const sc_mbedtls_mpi *X, size_t pos);
/**
* \brief Set a bit of X to a specific value of 0 or 1
*
* \note Will grow X if necessary to set a bit to 1 in a not yet
* existing limb. Will not grow if bit should be set to 0
*
* \param X MPI to use
* \param pos Zero-based index of the bit in X
* \param val The value to set the bit to (0 or 1)
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* SC_MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
*/
int sc_mbedtls_mpi_set_bit(sc_mbedtls_mpi *X, size_t pos, unsigned char val);
/**
* \brief Return the number of zero-bits before the least significant
* '1' bit
*
* Note: Thus also the zero-based index of the least significant '1' bit
*
* \param X MPI to use
*/
size_t sc_mbedtls_mpi_lsb(const sc_mbedtls_mpi *X);
/**
* \brief Return the number of bits up to and including the most
* significant '1' bit'
*
* Note: Thus also the one-based index of the most significant '1' bit
*
* \param X MPI to use
*/
size_t sc_mbedtls_mpi_bitlen(const sc_mbedtls_mpi *X);
/**
* \brief Return the total size in bytes
*
* \param X MPI to use
*/
size_t sc_mbedtls_mpi_size(const sc_mbedtls_mpi *X);
/**
* \brief Import from an ASCII string
*
* \param X Destination MPI
* \param radix Input numeric base
* \param s Null-terminated string buffer
*
* \return 0 if successful, or a SC_MBEDTLS_ERR_MPI_XXX error code
*/
int sc_mbedtls_mpi_read_string(sc_mbedtls_mpi *X, int radix, const char *s);
/**
* \brief Export into an ASCII string
*
* \param X Source MPI
* \param radix Output numeric base
* \param buf Buffer to write the string to
* \param buflen Length of buf
* \param olen Length of the string written, including final NUL byte
*
* \return 0 if successful, or a SC_MBEDTLS_ERR_MPI_XXX error code.
* *olen is always updated to reflect the amount
* of data that has (or would have) been written.
*
* \note Call this function with buflen = 0 to obtain the
* minimum required buffer size in *olen.
*/
int sc_mbedtls_mpi_write_string(const sc_mbedtls_mpi *X, int radix, char *buf, size_t buflen,
size_t *olen);
/**
* \brief Import X from unsigned binary data, big endian
*
* \param X Destination MPI
* \param buf Input buffer
* \param buflen Input buffer size
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_read_binary(sc_mbedtls_mpi *X, const unsigned char *buf, size_t buflen);
/**
* \brief Export X into unsigned binary data, big endian.
* Always fills the whole buffer, which will start with zeros
* if the number is smaller.
*
* \param X Source MPI
* \param buf Output buffer
* \param buflen Output buffer size
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
*/
int sc_mbedtls_mpi_write_binary(const sc_mbedtls_mpi *X, unsigned char *buf, size_t buflen);
/**
* \brief Left-shift: X <<= count
*
* \param X MPI to shift
* \param count Amount to shift
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_shift_l(sc_mbedtls_mpi *X, size_t count);
/**
* \brief Right-shift: X >>= count
*
* \param X MPI to shift
* \param count Amount to shift
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_shift_r(sc_mbedtls_mpi *X, size_t count);
/**
* \brief Compare unsigned values
*
* \param X Left-hand MPI
* \param Y Right-hand MPI
*
* \return 1 if |X| is greater than |Y|,
* -1 if |X| is lesser than |Y| or
* 0 if |X| is equal to |Y|
*/
int sc_mbedtls_mpi_cmp_abs(const sc_mbedtls_mpi *X, const sc_mbedtls_mpi *Y);
/**
* \brief Compare signed values
*
* \param X Left-hand MPI
* \param Y Right-hand MPI
*
* \return 1 if X is greater than Y,
* -1 if X is lesser than Y or
* 0 if X is equal to Y
*/
int sc_mbedtls_mpi_cmp_mpi(const sc_mbedtls_mpi *X, const sc_mbedtls_mpi *Y);
/**
* \brief Compare signed values
*
* \param X Left-hand MPI
* \param z The integer value to compare to
*
* \return 1 if X is greater than z,
* -1 if X is lesser than z or
* 0 if X is equal to z
*/
int sc_mbedtls_mpi_cmp_int(const sc_mbedtls_mpi *X, sc_mbedtls_mpi_sint z);
/**
* \brief Unsigned addition: X = |A| + |B|
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_add_abs(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *A, const sc_mbedtls_mpi *B);
/**
* \brief Unsigned subtraction: X = |A| - |B|
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A
*/
int sc_mbedtls_mpi_sub_abs(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *A, const sc_mbedtls_mpi *B);
/**
* \brief Signed addition: X = A + B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_add_mpi(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *A, const sc_mbedtls_mpi *B);
/**
* \brief Signed subtraction: X = A - B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_sub_mpi(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *A, const sc_mbedtls_mpi *B);
/**
* \brief Signed addition: X = A + b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The integer value to add
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_add_int(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *A, sc_mbedtls_mpi_sint b);
/**
* \brief Signed subtraction: X = A - b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The integer value to subtract
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_sub_int(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *A, sc_mbedtls_mpi_sint b);
/**
* \brief Baseline multiplication: X = A * B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_mul_mpi(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *A, const sc_mbedtls_mpi *B);
/**
* \brief Baseline multiplication: X = A * b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The unsigned integer value to multiply with
*
* \note b is unsigned
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_mul_int(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *A, sc_mbedtls_mpi_uint b);
/**
* \brief Division by sc_mbedtls_mpi: A = Q * B + R
*
* \param Q Destination MPI for the quotient
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* SC_MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0
*
* \note Either Q or R can be NULL.
*/
int sc_mbedtls_mpi_div_mpi(sc_mbedtls_mpi *Q, sc_mbedtls_mpi *R, const sc_mbedtls_mpi *A,
const sc_mbedtls_mpi *B);
/**
* \brief Division by int: A = Q * b + R
*
* \param Q Destination MPI for the quotient
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param b Integer to divide by
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* SC_MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0
*
* \note Either Q or R can be NULL.
*/
int sc_mbedtls_mpi_div_int(sc_mbedtls_mpi *Q, sc_mbedtls_mpi *R, const sc_mbedtls_mpi *A,
sc_mbedtls_mpi_sint b);
/**
* \brief Modulo: R = A mod B
*
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* SC_MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0,
* SC_MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0
*/
int sc_mbedtls_mpi_mod_mpi(sc_mbedtls_mpi *R, const sc_mbedtls_mpi *A, const sc_mbedtls_mpi *B);
/**
* \brief Modulo: r = A mod b
*
* \param r Destination sc_mbedtls_mpi_uint
* \param A Left-hand MPI
* \param b Integer to divide by
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* SC_MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0,
* SC_MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0
*/
int sc_mbedtls_mpi_mod_int(sc_mbedtls_mpi_uint *r, const sc_mbedtls_mpi *A,
sc_mbedtls_mpi_sint b);
/**
* \brief Sliding-window exponentiation: X = A^E mod N
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param E Exponent MPI
* \param N Modular MPI
* \param _RR Speed-up MPI used for recalculations
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* SC_MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or
* if E is negative
*
* \note _RR is used to avoid re-computing R*R mod N across
* multiple calls, which speeds up things a bit. It can
* be set to NULL if the extra performance is unneeded.
*/
int sc_mbedtls_mpi_exp_mod(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *A, const sc_mbedtls_mpi *E,
const sc_mbedtls_mpi *N, sc_mbedtls_mpi *_RR);
/**
* \brief Fill an MPI X with size bytes of random
*
* \param X Destination MPI
* \param size Size in bytes
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_fill_random(sc_mbedtls_mpi *X, size_t size,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
/**
* \brief Greatest common divisor: G = gcd(A, B)
*
* \param G Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int sc_mbedtls_mpi_gcd(sc_mbedtls_mpi *G, const sc_mbedtls_mpi *A, const sc_mbedtls_mpi *B);
/**
* \brief Modular inverse: X = A^-1 mod N
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param N Right-hand MPI
*
* \return 0 if successful,
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* SC_MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1,
SC_MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N.
*/
int sc_mbedtls_mpi_inv_mod(sc_mbedtls_mpi *X, const sc_mbedtls_mpi *A, const sc_mbedtls_mpi *N);
/**
* \brief Miller-Rabin primality test
*
* \param X MPI to check
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful (probably prime),
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* SC_MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime
*/
int sc_mbedtls_mpi_is_prime(const sc_mbedtls_mpi *X,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
/**
* \brief Prime number generation
*
* \param X Destination MPI
* \param nbits Required size of X in bits
* ( 3 <= nbits <= SC_MBEDTLS_MPI_MAX_BITS )
* \param dh_flag If 1, then (X-1)/2 will be prime too
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful (probably prime),
* SC_MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* SC_MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
*/
int sc_mbedtls_mpi_gen_prime(sc_mbedtls_mpi *X, size_t nbits, int dh_flag,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int sc_mbedtls_mpi_self_test(int verbose);
#ifdef __cplusplus
}
#endif
#endif /* bignum.h */

View File

@@ -0,0 +1,70 @@
/**
* \file bn_mul.h
*
* \brief Multi-precision integer library
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* Multiply source vector [s] with b, add result
* to destination vector [d] and set carry c.
*
* Currently supports:
*
* . IA-32 (386+) . AMD64 / EM64T
* . IA-32 (SSE2) . Motorola 68000
* . PowerPC, 32-bit . MicroBlaze
* . PowerPC, 64-bit . TriCore
* . SPARC v8 . ARM v3+
* . Alpha . MIPS32
* . C, longlong . C, generic
*/
#ifndef SC_MBEDTLS_BN_MUL_H
#define SC_MBEDTLS_BN_MUL_H
#include "crypto_bignum.h"
#if !defined(MULADDC_CORE)
#define MULADDC_INIT \
{ \
sc_mbedtls_mpi_uint s0, s1, b0, b1; \
sc_mbedtls_mpi_uint r0, r1, rx, ry; \
b0 = ( b << biH ) >> biH; \
b1 = ( b >> biH );
#define MULADDC_CORE \
s0 = ( *s << biH ) >> biH; \
s1 = ( *s >> biH ); s++; \
rx = s0 * b1; r0 = s0 * b0; \
ry = s1 * b0; r1 = s1 * b1; \
r1 += ( rx >> biH ); \
r1 += ( ry >> biH ); \
rx <<= biH; ry <<= biH; \
r0 += rx; r1 += (r0 < rx); \
r0 += ry; r1 += (r0 < ry); \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#endif /* C (generic) */
#endif /* bn_mul.h */

View File

@@ -0,0 +1,308 @@
/**
* \file ccm.h
*
* \brief This file provides an API for the CCM authenticated encryption
* mode for block ciphers.
*
* CCM combines Counter mode encryption with CBC-MAC authentication
* for 128-bit block ciphers.
*
* Input to CCM includes the following elements:
* <ul><li>Payload - data that is both authenticated and encrypted.</li>
* <li>Associated data (Adata) - data that is authenticated but not
* encrypted, For example, a header.</li>
* <li>Nonce - A unique value that is assigned to the payload and the
* associated data.</li></ul>
*
* Definition of CCM:
* http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
* RFC 3610 "Counter with CBC-MAC (CCM)"
*
* Related:
* RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
*
* Definition of CCM*:
* IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks
* Integer representation is fixed most-significant-octet-first order and
* the representation of octets is most-significant-bit-first order. This is
* consistent with RFC 3610.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_CCM_H
#define MBEDTLS_CCM_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/cipher.h"
#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */
#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(MBEDTLS_CCM_ALT)
// Regular implementation
//
/**
* \brief The CCM context-type definition. The CCM context is passed
* to the APIs called.
*/
typedef struct mbedtls_ccm_context
{
mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
}
mbedtls_ccm_context;
#else /* MBEDTLS_CCM_ALT */
#include "ccm_alt.h"
#endif /* MBEDTLS_CCM_ALT */
/**
* \brief This function initializes the specified CCM context,
* to make references valid, and prepare the context
* for sc_mbedtls_ccm_setkey() or sc_mbedtls_ccm_free().
*
* \param ctx The CCM context to initialize. This must not be \c NULL.
*/
void sc_mbedtls_ccm_init( mbedtls_ccm_context *ctx );
/**
* \brief This function initializes the CCM context set in the
* \p ctx parameter and sets the encryption key.
*
* \param ctx The CCM context to initialize. This must be an initialized
* context.
* \param cipher The 128-bit block cipher to use.
* \param key The encryption key. This must not be \c NULL.
* \param keybits The key size in bits. This must be acceptable by the cipher.
*
* \return \c 0 on success.
* \return A CCM or cipher-specific error code on failure.
*/
int sc_mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits );
/**
* \brief This function releases and clears the specified CCM context
* and underlying cipher sub-context.
*
* \param ctx The CCM context to clear. If this is \c NULL, the function
* has no effect. Otherwise, this must be initialized.
*/
void sc_mbedtls_ccm_free( mbedtls_ccm_context *ctx );
/**
* \brief This function encrypts a buffer using CCM.
*
* \note The tag is written to a separate buffer. To concatenate
* the \p tag with the \p output, as done in <em>RFC-3610:
* Counter with CBC-MAC (CCM)</em>, use
* \p tag = \p output + \p length, and make sure that the
* output buffer is at least \p length + \p tag_len wide.
*
* \param ctx The CCM context to use for encryption. This must be
* initialized and bound to a key.
* \param length The length of the input data in Bytes.
* \param iv The initialization vector (nonce). This must be a readable
* buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field. If \p add_len is greater than
* zero, \p add must be a readable buffer of at least that
* length.
* \param add_len The length of additional data in Bytes.
* This must be less than `2^16 - 2^8`.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
* that length.
* \param output The buffer holding the output data. If \p length is greater
* than zero, \p output must be a writable buffer of at least
* that length.
* \param tag The buffer holding the authentication field. This must be a
* writable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field to generate in Bytes:
* 4, 6, 8, 10, 12, 14 or 16.
*
* \return \c 0 on success.
* \return A CCM or cipher-specific error code on failure.
*/
int sc_mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len );
/**
* \brief This function encrypts a buffer using CCM*.
*
* \note The tag is written to a separate buffer. To concatenate
* the \p tag with the \p output, as done in <em>RFC-3610:
* Counter with CBC-MAC (CCM)</em>, use
* \p tag = \p output + \p length, and make sure that the
* output buffer is at least \p length + \p tag_len wide.
*
* \note When using this function in a variable tag length context,
* the tag length has to be encoded into the \p iv passed to
* this function.
*
* \param ctx The CCM context to use for encryption. This must be
* initialized and bound to a key.
* \param length The length of the input data in Bytes.
* \param iv The initialization vector (nonce). This must be a readable
* buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field. This must be a readable buffer of
* at least \p add_len Bytes.
* \param add_len The length of additional data in Bytes.
* This must be less than 2^16 - 2^8.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
* that length.
* \param output The buffer holding the output data. If \p length is greater
* than zero, \p output must be a writable buffer of at least
* that length.
* \param tag The buffer holding the authentication field. This must be a
* writable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field to generate in Bytes:
* 0, 4, 6, 8, 10, 12, 14 or 16.
*
* \warning Passing \c 0 as \p tag_len means that the message is no
* longer authenticated.
*
* \return \c 0 on success.
* \return A CCM or cipher-specific error code on failure.
*/
int sc_mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len );
/**
* \brief This function performs a CCM authenticated decryption of a
* buffer.
*
* \param ctx The CCM context to use for decryption. This must be
* initialized and bound to a key.
* \param length The length of the input data in Bytes.
* \param iv The initialization vector (nonce). This must be a readable
* buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field. This must be a readable buffer
* of at least that \p add_len Bytes..
* \param add_len The length of additional data in Bytes.
* This must be less than 2^16 - 2^8.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
* that length.
* \param output The buffer holding the output data. If \p length is greater
* than zero, \p output must be a writable buffer of at least
* that length.
* \param tag The buffer holding the authentication field. This must be a
* readable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field to generate in Bytes:
* 4, 6, 8, 10, 12, 14 or 16.
*
* \return \c 0 on success. This indicates that the message is authentic.
* \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
* \return A cipher-specific error code on calculation failure.
*/
int sc_mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );
/**
* \brief This function performs a CCM* authenticated decryption of a
* buffer.
*
* \note When using this function in a variable tag length context,
* the tag length has to be decoded from \p iv and passed to
* this function as \p tag_len. (\p tag needs to be adjusted
* accordingly.)
*
* \param ctx The CCM context to use for decryption. This must be
* initialized and bound to a key.
* \param length The length of the input data in Bytes.
* \param iv The initialization vector (nonce). This must be a readable
* buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field. This must be a readable buffer of
* at least that \p add_len Bytes.
* \param add_len The length of additional data in Bytes.
* This must be less than 2^16 - 2^8.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
* that length.
* \param output The buffer holding the output data. If \p length is greater
* than zero, \p output must be a writable buffer of at least
* that length.
* \param tag The buffer holding the authentication field. This must be a
* readable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field in Bytes.
* 0, 4, 6, 8, 10, 12, 14 or 16.
*
* \warning Passing \c 0 as \p tag_len means that the message is nos
* longer authenticated.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
* \return A cipher-specific error code on calculation failure.
*/
int sc_mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/**
* \brief The CCM checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int sc_mbedtls_ccm_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CCM_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,125 @@
/**
* \file cipher_internal.h
*
* \brief Cipher wrappers.
*
* \author Adriaan de Jong <dejong@fox-it.com>
*/
/*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_CIPHER_WRAP_H
#define MBEDTLS_CIPHER_WRAP_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "crypto_config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "crypto_cipher.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Base cipher information. The non-mode specific functions and values.
*/
struct mbedtls_cipher_base_t
{
/** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */
mbedtls_cipher_id_t cipher;
/** Encrypt using ECB */
int (*ecb_func)( void *ctx, mbedtls_operation_t mode,
const unsigned char *input, unsigned char *output );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/** Encrypt using CBC */
int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length,
unsigned char *iv, const unsigned char *input,
unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/** Encrypt using CFB (Full length) */
int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off,
unsigned char *iv, const unsigned char *input,
unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
/** Encrypt using OFB (Full length) */
int (*ofb_func)( void *ctx, size_t length, size_t *iv_off,
unsigned char *iv,
const unsigned char *input,
unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/** Encrypt using CTR */
int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
unsigned char *nonce_counter, unsigned char *stream_block,
const unsigned char *input, unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
/** Encrypt or decrypt using XTS. */
int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length,
const unsigned char data_unit[16],
const unsigned char *input, unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
/** Encrypt using STREAM */
int (*stream_func)( void *ctx, size_t length,
const unsigned char *input, unsigned char *output );
#endif
/** Set key for encryption purposes */
int (*setkey_enc_func)( void *ctx, const unsigned char *key,
unsigned int key_bitlen );
/** Set key for decryption purposes */
int (*setkey_dec_func)( void *ctx, const unsigned char *key,
unsigned int key_bitlen);
/** Allocate a new context */
void * (*ctx_alloc_func)( void );
/** Free the given context */
void (*ctx_free_func)( void *ctx );
};
typedef struct
{
mbedtls_cipher_type_t type;
const mbedtls_cipher_info_t *info;
} mbedtls_cipher_definition_t;
extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
extern int mbedtls_cipher_supported[];
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CIPHER_WRAP_H */

View File

@@ -0,0 +1,242 @@
/**
* \file cmac.h
*
* \brief This file contains CMAC definitions and functions.
*
* The Cipher-based Message Authentication Code (CMAC) Mode for
* Authentication is defined in <em>RFC-4493: The AES-CMAC Algorithm</em>.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_CMAC_H
#define MBEDTLS_CMAC_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/cipher.h"
#ifdef __cplusplus
extern "C" {
#endif
/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */
#define MBEDTLS_AES_BLOCK_SIZE 16
#define MBEDTLS_DES3_BLOCK_SIZE 8
#if defined(MBEDTLS_AES_C)
#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */
#else
#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */
#endif
#if !defined(MBEDTLS_CMAC_ALT)
/**
* The CMAC context structure.
*/
struct mbedtls_cmac_context_t
{
/** The internal state of the CMAC algorithm. */
unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX];
/** Unprocessed data - either data that was not block aligned and is still
* pending processing, or the final block. */
unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX];
/** The length of data pending processing. */
size_t unprocessed_len;
};
#else /* !MBEDTLS_CMAC_ALT */
#include "cmac_alt.h"
#endif /* !MBEDTLS_CMAC_ALT */
/**
* \brief Initialises and allocat cmac context memory
* Must be called with an initialized cipher context.
*
* \param ctx The cipher context used for the CMAC operation, initialized
* as one of the following types: MBEDTLS_CIPHER_AES_128_ECB,
* MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB,
* or MBEDTLS_CIPHER_DES_EDE3_ECB.
* \return \c 0 on success.
* \return A cipher-specific error code on failure.
*/
int sc_mbedtls_cipher_cmac_setup(mbedtls_cipher_context_t *ctx);
/**
* \brief This function sets the CMAC key, and prepares to authenticate
* the input data.
* Must be called with an initialized cipher context.
*
* \note When the CMAC implementation is supplied by an alternate
* implementation (through #MBEDTLS_CMAC_ALT), some ciphers
* may not be supported by that implementation, and thus
* return an error. Alternate implementations must support
* AES-128 and AES-256, and may support AES-192 and 3DES.
*
* \param ctx The cipher context used for the CMAC operation, initialized
* as one of the following types: MBEDTLS_CIPHER_AES_128_ECB,
* MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB,
* or MBEDTLS_CIPHER_DES_EDE3_ECB.
* \param key The CMAC key.
* \param keybits The length of the CMAC key in bits.
* Must be supported by the cipher.
*
* \return \c 0 on success.
* \return A cipher-specific error code on failure.
*/
int sc_mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
const unsigned char *key, size_t keybits );
/**
* \brief This function feeds an input buffer into an ongoing CMAC
* computation.
*
* It is called between sc_mbedtls_cipher_cmac_starts() or
* sc_mbedtls_cipher_cmac_reset(), and sc_mbedtls_cipher_cmac_finish().
* Can be called repeatedly.
*
* \param ctx The cipher context used for the CMAC operation.
* \param input The buffer holding the input data.
* \param ilen The length of the input data.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA
* if parameter verification fails.
*/
int sc_mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
const unsigned char *input, size_t ilen );
/**
* \brief This function finishes the CMAC operation, and writes
* the result to the output buffer.
*
* It is called after sc_mbedtls_cipher_cmac_update().
* It can be followed by sc_mbedtls_cipher_cmac_reset() and
* sc_mbedtls_cipher_cmac_update(), or mbedtls_cipher_free().
*
* \param ctx The cipher context used for the CMAC operation.
* \param output The output buffer for the CMAC checksum result.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA
* if parameter verification fails.
*/
int sc_mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
unsigned char *output );
/**
* \brief This function prepares the authentication of another
* message with the same key as the previous CMAC
* operation.
*
* It is called after sc_mbedtls_cipher_cmac_finish()
* and before sc_mbedtls_cipher_cmac_update().
*
* \param ctx The cipher context used for the CMAC operation.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA
* if parameter verification fails.
*/
int sc_mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx );
/**
* \brief This function calculates the full generic CMAC
* on the input buffer with the provided key.
*
* The function allocates the context, performs the
* calculation, and frees the context.
*
* The CMAC result is calculated as
* output = generic CMAC(cmac key, input buffer).
*
* \note When the CMAC implementation is supplied by an alternate
* implementation (through #MBEDTLS_CMAC_ALT), some ciphers
* may not be supported by that implementation, and thus
* return an error. Alternate implementations must support
* AES-128 and AES-256, and may support AES-192 and 3DES.
*
* \param cipher_info The cipher information.
* \param key The CMAC key.
* \param keylen The length of the CMAC key in bits.
* \param input The buffer holding the input data.
* \param ilen The length of the input data.
* \param output The buffer for the generic CMAC result.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA
* if parameter verification fails.
*/
int sc_mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen,
unsigned char *output );
#if defined(MBEDTLS_AES_C)
/**
* \brief This function implements the AES-CMAC-PRF-128 pseudorandom
* function, as defined in
* <em>RFC-4615: The Advanced Encryption Standard-Cipher-based
* Message Authentication Code-Pseudo-Random Function-128
* (AES-CMAC-PRF-128) Algorithm for the Internet Key
* Exchange Protocol (IKE).</em>
*
* \param key The key to use.
* \param key_len The key length in Bytes.
* \param input The buffer holding the input data.
* \param in_len The length of the input data in Bytes.
* \param output The buffer holding the generated 16 Bytes of
* pseudorandom output.
*
* \return \c 0 on success.
*/
int sc_mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len,
const unsigned char *input, size_t in_len,
unsigned char output[16] );
#endif /* MBEDTLS_AES_C */
#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) )
/**
* \brief The CMAC checkup routine.
*
* \note In case the CMAC routines are provided by an alternative
* implementation (i.e. #MBEDTLS_CMAC_ALT is defined), the
* checkup routine will succeed even if the implementation does
* not support the less widely used AES-192 or 3DES primitives.
* The self-test requires at least AES-128 and AES-256 to be
* supported by the underlying implementation.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int sc_mbedtls_cmac_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CMAC_H */

View File

@@ -0,0 +1,67 @@
/*
* Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* Minimal configuration for TLS 1.2 with PSK and AES-CCM ciphersuites
* Distinguishing features:
* - no bignum, no PK, no X509
* - fully modern and secure (provided the pre-shared keys have high entropy)
* - very low record overhead with CCM-8
* - optimized for low RAM usage
*
* See README.txt for usage instructions.
*/
#ifndef SC_MBEDTLS_CONFIG_H
#define SC_MBEDTLS_CONFIG_H
/* System support */
/* mbed TLS feature support */
#define MBEDTLS_PKCS1_V15
/* mbed TLS modules */
#define MBEDTLS_AES_C
#define MBEDTLS_CIPHER_MODE_CBC
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_BIGNUM_C
#define SC_MBEDTLS_MD_C
//#define MBEDTLS_NET_C
#define MBEDTLS_OID_C
#define MBEDTLS_SHA1_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_RSA_C
#define MBEDTLS_RSA_NO_CRT
#define MBEDTLS_GCM_C
#define MBEDTLS_SELF_TEST
#if !defined (MBEDTLS_DEBUG_C)
/*reduce readonly date size*/
#define CK_REMOVE_UNUSED_FUNCTION_AND_DATA
#endif
#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO
#define MBEDTLS_PLATFORM_TIME_MACRO
#endif /* SC_MBEDTLS_CONFIG_H */

View File

@@ -0,0 +1,61 @@
/* constants.h - TinyCrypt interface to constants */
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief -- Interface to constants.
*
*/
#ifndef __TC_CONSTANTS_H__
#define __TC_CONSTANTS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#ifndef NULL
#define NULL ((void *)0)
#endif
#define TC_CRYPTO_SUCCESS 1
#define TC_CRYPTO_FAIL 0
#define TC_ZERO_BYTE 0x00
#ifdef __cplusplus
}
#endif
#endif /* __TC_CONSTANTS_H__ */

View File

@@ -0,0 +1,546 @@
/* ecc.h - TinyCrypt interface to common ECC functions */
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief -- Interface to common ECC functions.
*
* Overview: This software is an implementation of common functions
* necessary to elliptic curve cryptography. This implementation uses
* curve NIST p-256.
*
* Security: The curve NIST p-256 provides approximately 128 bits of security.
*
*/
#ifndef __TC_UECC_H__
#define __TC_UECC_H__
#include <stdint.h>
#include <linux/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Word size (4 bytes considering 32-bits architectures) */
#define uECC_WORD_SIZE 4
/* setting max number of calls to prng: */
#ifndef uECC_RNG_MAX_TRIES
#define uECC_RNG_MAX_TRIES 64
#endif
/* defining data types to store word and bit counts: */
typedef int8_t wordcount_t;
typedef int16_t bitcount_t;
/* defining data type for comparison result: */
typedef int8_t cmpresult_t;
/* defining data type to store ECC coordinate/point in 32bits words: */
typedef unsigned int uECC_word_t;
/* defining data type to store an ECC coordinate/point in 64bits words: */
typedef uint64_t uECC_dword_t;
/* defining masks useful for ecc computations: */
#define HIGH_BIT_SET 0x80000000
#define uECC_WORD_BITS 32
#define uECC_WORD_BITS_SHIFT 5
#define uECC_WORD_BITS_MASK 0x01F
/* Number of words of 32 bits to represent an element of the the curve p-256: */
#define NUM_ECC_WORDS 8
/* Number of bytes to represent an element of the the curve p-256: */
#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS)
/* structure that represents an elliptic curve (e.g. p256):*/
struct uECC_Curve_t;
typedef const struct uECC_Curve_t * uECC_Curve;
struct uECC_Curve_t {
wordcount_t num_words;
wordcount_t num_bytes;
bitcount_t num_n_bits;
uECC_word_t p[NUM_ECC_WORDS];
uECC_word_t n[NUM_ECC_WORDS];
uECC_word_t G[NUM_ECC_WORDS * 2];
uECC_word_t b[NUM_ECC_WORDS];
void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1, uECC_Curve curve);
void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
};
/*
* @brief computes doubling of point ion jacobian coordinates, in place.
* @param X1 IN/OUT -- x coordinate
* @param Y1 IN/OUT -- y coordinate
* @param Z1 IN/OUT -- z coordinate
* @param curve IN -- elliptic curve
*/
void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
uECC_word_t * Z1, uECC_Curve curve);
/*
* @brief Computes x^3 + ax + b. result must not overlap x.
* @param result OUT -- x^3 + ax + b
* @param x IN -- value of x
* @param curve IN -- elliptic curve
*/
void x_side_default(uECC_word_t *result, const uECC_word_t *x,
uECC_Curve curve);
/*
* @brief Computes result = product % curve_p
* from http://www.nsa.gov/ia/_files/nist-routines.pdf
* @param result OUT -- product % curve_p
* @param product IN -- value to be reduced mod curve_p
*/
void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product);
/* Bytes to words ordering: */
#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
#define BITS_TO_WORDS(num_bits) \
((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8))
#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8)
/* definition of curve NIST p-256: */
static const struct uECC_Curve_t curve_secp256r1 = {
NUM_ECC_WORDS,
NUM_ECC_BYTES,
256, /* num_n_bits */ {
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
}, {
BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
}, {
BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
}, {
BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
},
&double_jacobian_default,
&x_side_default,
&vli_mmod_fast_secp256r1
};
uECC_Curve uECC_secp256r1(void);
/*
* @brief Generates a random integer in the range 0 < random < top.
* Both random and top have num_words words.
* @param random OUT -- random integer in the range 0 < random < top
* @param top IN -- upper limit
* @param num_words IN -- number of words
* @return a random integer in the range 0 < random < top
*/
int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
wordcount_t num_words);
/* uECC_RNG_Function type
* The RNG function should fill 'size' random bytes into 'dest'. It should
* return 1 if 'dest' was filled with random data, or 0 if the random data could
* not be generated. The filled-in values should be either truly random, or from
* a cryptographically-secure PRNG.
*
* A correctly functioning RNG function must be set (using uECC_set_rng())
* before calling uECC_make_key() or uECC_sign().
*
* Setting a correctly functioning RNG function improves the resistance to
* side-channel attacks for uECC_shared_secret().
*
* A correct RNG function is set by default. If you are building on another
* POSIX-compliant system that supports /dev/random or /dev/urandom, you can
* define uECC_POSIX to use the predefined RNG.
*/
typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size);
/*
* @brief Set the function that will be used to generate random bytes. The RNG
* function should return 1 if the random data was generated, or 0 if the random
* data could not be generated.
*
* @note On platforms where there is no predefined RNG function, this must be
* called before uECC_make_key() or uECC_sign() are used.
*
* @param rng_function IN -- function that will be used to generate random bytes
*/
void uECC_set_rng(uECC_RNG_Function rng_function);
/*
* @brief provides current uECC_RNG_Function.
* @return Returns the function that will be used to generate random bytes.
*/
uECC_RNG_Function uECC_get_rng(void);
/*
* @brief computes the size of a private key for the curve in bytes.
* @param curve IN -- elliptic curve
* @return size of a private key for the curve in bytes.
*/
int uECC_curve_private_key_size(uECC_Curve curve);
/*
* @brief computes the size of a public key for the curve in bytes.
* @param curve IN -- elliptic curve
* @return the size of a public key for the curve in bytes.
*/
int uECC_curve_public_key_size(uECC_Curve curve);
/*
* @brief Compute the corresponding public key for a private key.
* @param private_key IN -- The private key to compute the public key for
* @param public_key OUT -- Will be filled in with the corresponding public key
* @param curve
* @return Returns 1 if key was computed successfully, 0 if an error occurred.
*/
int uECC_compute_public_key(const uint8_t *private_key,
uint8_t *public_key, uECC_Curve curve);
/*
* @brief Compute public-key.
* @return corresponding public-key.
* @param result OUT -- public-key
* @param private_key IN -- private-key
* @param curve IN -- elliptic curve
*/
uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
uECC_word_t *private_key, uECC_Curve curve);
/*
* @brief Regularize the bitcount for the private key so that attackers cannot
* use a side channel attack to learn the number of leading zeros.
* @return Regularized k
* @param k IN -- private-key
* @param k0 IN/OUT -- regularized k
* @param k1 IN/OUT -- regularized k
* @param curve IN -- elliptic curve
*/
uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
uECC_word_t *k1, uECC_Curve curve);
/*
* @brief Point multiplication algorithm using Montgomery's ladder with co-Z
* coordinates. See http://eprint.iacr.org/2011/338.pdf.
* @note Result may overlap point.
* @param result OUT -- returns scalar*point
* @param point IN -- elliptic curve point
* @param scalar IN -- scalar
* @param initial_Z IN -- initial value for z
* @param num_bits IN -- number of bits in scalar
* @param curve IN -- elliptic curve
*/
void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
const uECC_word_t * scalar, const uECC_word_t * initial_Z,
bitcount_t num_bits, uECC_Curve curve);
/*
* @brief Constant-time comparison to zero - secure way to compare long integers
* @param vli IN -- very long integer
* @param num_words IN -- number of words in the vli
* @return 1 if vli == 0, 0 otherwise.
*/
uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
/*
* @brief Check if 'point' is the point at infinity
* @param point IN -- elliptic curve point
* @param curve IN -- elliptic curve
* @return if 'point' is the point at infinity, 0 otherwise.
*/
uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve);
/*
* @brief computes the sign of left - right, in constant time.
* @param left IN -- left term to be compared
* @param right IN -- right term to be compared
* @param num_words IN -- number of words
* @return the sign of left - right
*/
cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
wordcount_t num_words);
/*
* @brief computes sign of left - right, not in constant time.
* @note should not be used if inputs are part of a secret
* @param left IN -- left term to be compared
* @param right IN -- right term to be compared
* @param num_words IN -- number of words
* @return the sign of left - right
*/
cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right,
wordcount_t num_words);
/*
* @brief Computes result = (left - right) % mod.
* @note Assumes that (left < mod) and (right < mod), and that result does not
* overlap mod.
* @param result OUT -- (left - right) % mod
* @param left IN -- leftright term in modular subtraction
* @param right IN -- right term in modular subtraction
* @param mod IN -- mod
* @param num_words IN -- number of words
*/
void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words);
/*
* @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or
* P => P', Q => P + Q
* @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z)
* @param X1 IN -- x coordinate of P
* @param Y1 IN -- y coordinate of P
* @param X2 IN -- x coordinate of Q
* @param Y2 IN -- y coordinate of Q
* @param curve IN -- elliptic curve
*/
void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2,
uECC_word_t * Y2, uECC_Curve curve);
/*
* @brief Computes (x1 * z^2, y1 * z^3)
* @param X1 IN -- previous x1 coordinate
* @param Y1 IN -- previous y1 coordinate
* @param Z IN -- z value
* @param curve IN -- elliptic curve
*/
void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
uECC_Curve curve);
/*
* @brief Check if bit is set.
* @return Returns nonzero if bit 'bit' of vli is set.
* @warning It is assumed that the value provided in 'bit' is within the
* boundaries of the word-array 'vli'.
* @note The bit ordering layout assumed for vli is: {31, 30, ..., 0},
* {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting
* of 4 uECC_word_t elements.
*/
uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
/*
* @brief Computes result = product % mod, where product is 2N words long.
* @param result OUT -- product % mod
* @param mod IN -- module
* @param num_words IN -- number of words
* @warning Currently only designed to work for curve_p or curve_n.
*/
void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
const uECC_word_t *mod, wordcount_t num_words);
/*
* @brief Computes modular product (using curve->mmod_fast)
* @param result OUT -- (left * right) mod % curve_p
* @param left IN -- left term in product
* @param right IN -- right term in product
* @param curve IN -- elliptic curve
*/
void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, uECC_Curve curve);
/*
* @brief Computes result = left - right.
* @note Can modify in place.
* @param result OUT -- left - right
* @param left IN -- left term in subtraction
* @param right IN -- right term in subtraction
* @param num_words IN -- number of words
* @return borrow
*/
uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, wordcount_t num_words);
/*
* @brief Constant-time comparison function(secure way to compare long ints)
* @param left IN -- left term in comparison
* @param right IN -- right term in comparison
* @param num_words IN -- number of words
* @return Returns 0 if left == right, 1 otherwise.
*/
uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
wordcount_t num_words);
/*
* @brief Computes (left * right) % mod
* @param result OUT -- (left * right) % mod
* @param left IN -- left term in product
* @param right IN -- right term in product
* @param mod IN -- mod
* @param num_words IN -- number of words
*/
void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words);
/*
* @brief Computes (1 / input) % mod
* @note All VLIs are the same size.
* @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide"
* @param result OUT -- (1 / input) % mod
* @param input IN -- value to be modular inverted
* @param mod IN -- mod
* @param num_words -- number of words
*/
void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
const uECC_word_t *mod, wordcount_t num_words);
/*
* @brief Sets dest = src.
* @param dest OUT -- destination buffer
* @param src IN -- origin buffer
* @param num_words IN -- number of words
*/
void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
wordcount_t num_words);
/*
* @brief Computes (left + right) % mod.
* @note Assumes that (left < mod) and right < mod), and that result does not
* overlap mod.
* @param result OUT -- (left + right) % mod.
* @param left IN -- left term in addition
* @param right IN -- right term in addition
* @param mod IN -- mod
* @param num_words IN -- number of words
*/
void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words);
/*
* @brief Counts the number of bits required to represent vli.
* @param vli IN -- very long integer
* @param max_words IN -- number of words
* @return number of bits in given vli
*/
bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
const wordcount_t max_words);
/*
* @brief Erases (set to 0) vli
* @param vli IN -- very long integer
* @param num_words IN -- number of words
*/
void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
/*
* @brief check if it is a valid point in the curve
* @param point IN -- point to be checked
* @param curve IN -- elliptic curve
* @return 0 if point is valid
* @exception returns -1 if it is a point at infinity
* @exception returns -2 if x or y is smaller than p,
* @exception returns -3 if y^2 != x^3 + ax + b.
*/
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
/*
* @brief Check if a public key is valid.
* @param public_key IN -- The public key to be checked.
* @return returns 0 if the public key is valid
* @exception returns -1 if it is a point at infinity
* @exception returns -2 if x or y is smaller than p,
* @exception returns -3 if y^2 != x^3 + ax + b.
* @exception returns -4 if public key is the group generator.
*
* @note Note that you are not required to check for a valid public key before
* using any other uECC functions. However, you may wish to avoid spending CPU
* time computing a shared secret or verifying a signature using an invalid
* public key.
*/
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
/*
* @brief Converts an integer in uECC native format to big-endian bytes.
* @param bytes OUT -- bytes representation
* @param num_bytes IN -- number of bytes
* @param native IN -- uECC native representation
*/
void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
const unsigned int *native);
/*
* @brief Converts big-endian bytes to an integer in uECC native format.
* @param native OUT -- uECC native representation
* @param bytes IN -- bytes representation
* @param num_bytes IN -- number of bytes
*/
void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
int num_bytes);
#ifdef __cplusplus
}
#endif
#endif /* __TC_UECC_H__ */

View File

@@ -0,0 +1,129 @@
/* ecc_dh.h - TinyCrypt interface to EC-DH implementation */
/*
* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief -- Interface to EC-DH implementation.
*
* Overview: This software is an implementation of EC-DH. This implementation
* uses curve NIST p-256.
*
* Security: The curve NIST p-256 provides approximately 128 bits of security.
*/
#ifndef __TC_ECC_DH_H__
#define __TC_ECC_DH_H__
#include <crypto_ecc.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Create a public/private key pair.
* @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully
* returns TC_CRYPTO_FAIL (0) if error while generating key pair
*
* @param p_public_key OUT -- Will be filled in with the public key. Must be at
* least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key
* must be 64 bytes long.
* @param p_private_key OUT -- Will be filled in with the private key. Must be as
* long as the curve order (for secp256r1, p_private_key must be 32 bytes long).
*
* @note side-channel countermeasure: algorithm strengthened against timing
* attack.
* @warning A cryptographically-secure PRNG function must be set (using
* uECC_set_rng()) before calling uECC_make_key().
*/
int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve);
/**
* @brief Create a public/private key pair given a specific d.
*
* @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to
* uECC_make_key() function for real applications.
*/
int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key,
unsigned int *d, uECC_Curve curve);
/**
* @brief Compute a shared secret given your secret key and someone else's
* public key.
* @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully
* returns TC_CRYPTO_FAIL (0) otherwise
*
* @param p_secret OUT -- Will be filled in with the shared secret value. Must be
* the same size as the curve size (for curve secp256r1, secret must be 32 bytes
* long.
* @param p_public_key IN -- The public key of the remote party.
* @param p_private_key IN -- Your private key.
*
* @warning It is recommended to use the output of uECC_shared_secret() as the
* input of a recommended Key Derivation Function (see NIST SP 800-108) in
* order to produce a cryptographically secure symmetric key.
*/
int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key,
uint8_t *p_secret, uECC_Curve curve);
#ifdef __cplusplus
}
#endif
#endif /* __TC_ECC_DH_H__ */

View File

@@ -0,0 +1,137 @@
/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */
/*
* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief -- Interface to EC-DSA implementation.
*
* Overview: This software is an implementation of EC-DSA. This implementation
* uses curve NIST p-256.
*
* Security: The curve NIST p-256 provides approximately 128 bits of security.
*
* Usage: - To sign: Compute a hash of the data you wish to sign (SHA-2 is
* recommended) and pass it in to ecdsa_sign function along with your
* private key and a random number. You must use a new non-predictable
* random number to generate each new signature.
* - To verify a signature: Compute the hash of the signed data using
* the same hash as the signer and pass it to this function along with
* the signer's public key and the signature values (r and s).
*/
#ifndef __TC_ECC_DSA_H__
#define __TC_ECC_DSA_H__
#include <crypto_ecc.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Generate an ECDSA signature for a given hash value.
* @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully
* returns TC_CRYPTO_FAIL (0) if an error occurred.
*
* @param p_private_key IN -- Your private key.
* @param p_message_hash IN -- The hash of the message to sign.
* @param p_hash_size IN -- The size of p_message_hash in bytes.
* @param p_signature OUT -- Will be filled in with the signature value. Must be
* at least 2 * curve size long (for secp256r1, signature must be 64 bytes long).
*
* @warning A cryptographically-secure PRNG function must be set (using
* uECC_set_rng()) before calling uECC_sign().
* @note Usage: Compute a hash of the data you wish to sign (SHA-2 is
* recommended) and pass it in to this function along with your private key.
* @note side-channel countermeasure: algorithm strengthened against timing
* attack.
*/
int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash,
unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve);
/*
* THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY.
* Refer to uECC_sign() function for real applications.
*/
int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
unsigned int hash_size, uECC_word_t *k, uint8_t *signature,
uECC_Curve curve);
/**
* @brief Verify an ECDSA signature.
* @return returns TC_SUCCESS (1) if the signature is valid
* returns TC_FAIL (0) if the signature is invalid.
*
* @param p_public_key IN -- The signer's public key.
* @param p_message_hash IN -- The hash of the signed data.
* @param p_hash_size IN -- The size of p_message_hash in bytes.
* @param p_signature IN -- The signature values.
*
* @note Usage: Compute the hash of the signed data using the same hash as the
* signer and pass it to this function along with the signer's public key and
* the signature values (hash_size and signature).
*/
int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash,
unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve);
#ifdef __cplusplus
}
#endif
#endif /* __TC_ECC_DSA_H__ */

View File

@@ -0,0 +1,81 @@
/* uECC_platform_specific.h - Interface to platform specific functions*/
/* Copyright (c) 2014, Kenneth MacKay
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.*/
/*
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* uECC_platform_specific.h -- Interface to platform specific functions
*/
#ifndef __UECC_PLATFORM_SPECIFIC_H_
#define __UECC_PLATFORM_SPECIFIC_H_
/*
* The RNG function should fill 'size' random bytes into 'dest'. It should
* return 1 if 'dest' was filled with random data, or 0 if the random data could
* not be generated. The filled-in values should be either truly random, or from
* a cryptographically-secure PRNG.
*
* A cryptographically-secure PRNG function must be set (using uECC_set_rng())
* before calling uECC_make_key() or uECC_sign().
*
* Setting a cryptographically-secure PRNG function improves the resistance to
* side-channel attacks for uECC_shared_secret().
*
* A correct PRNG function is set by default (default_RNG_defined = 1) and works
* for some platforms, such as Unix and Linux. For other platforms, you may need
* to provide another PRNG function.
*/
#define default_RNG_defined 1
int default_CSPRNG(uint8_t *dest, unsigned int size);
#endif /* __UECC_PLATFORM_SPECIFIC_H_ */

Some files were not shown because too many files have changed in this diff Show More