Compare commits

...

6 commits

Author SHA1 Message Date
James Deng
60297de7dc Update for v2.0 2024-10-22 19:42:58 +08:00
James Deng
8bdc7887dc Update for v2.0rc7 2024-10-08 20:22:44 +08:00
James Deng
a996a74cc1 Update for v2.0rc6 2024-09-10 17:47:09 +08:00
James Deng
ad097c0e1d Update for v2.0rc5 2024-09-02 15:34:14 +08:00
James Deng
f91a284fab Update for v2.0rc4 2024-08-29 20:58:10 +08:00
James Deng
c83b48d3b0 Update for v2.0rc3 2024-08-10 16:40:06 +08:00
109 changed files with 5390 additions and 516 deletions

View file

@ -43,5 +43,6 @@ CFLAGS_EFI += $(ARCH_FLAGS)
head-y := arch/riscv/cpu/start.o
libs-y += arch/riscv/cpu/
libs-y += arch/riscv/kernel/
libs-y += arch/riscv/cpu/$(CPU)/
libs-y += arch/riscv/lib/

View file

@ -13,6 +13,8 @@ dtb-$(CONFIG_TARGET_SPACEMIT_K1X) += k1-x_evb.dtb k1-x_deb2.dtb k1-x_deb1.dtb k1
k1-x_MUSE-Pi.dtb k1-x_spl.dtb k1-x_milkv-jupiter.dtb \
k1-x_MUSE-Book.dtb m1-x_milkv-jupiter.dtb \
k1-x_lpi3a.dtb k1-x_MUSE-Card.dtb k1-x_MUSE-Paper.dtb \
k1-x_MUSE-Paper-mini-4g.dtb k1-x_baton-camera.dtb \
k1-x_FusionOne.dtb
include $(srctree)/scripts/Makefile.dts

View file

@ -529,6 +529,16 @@
status = "disabled";
};
pwm1: pwm@d401a400 {
compatible = "spacemit,k1x-pwm";
reg = <0x0 0xd401a000 0x0 0x10>;
#pwm-cells = <2>;
clocks = <&ccu CLK_PWM0>;
resets = <&reset RESET_PWM0>;
k1x,pwm-disable-fd = <1>;
status = "disabled";
};
pwm14: pwm@d4021800 {
compatible = "spacemit,k1x-pwm";
reg = <0x0 0xd4021800 0x0 0x10>;
@ -539,6 +549,12 @@
status = "disabled";
};
backlight: backlight {
compatible = "pwm-backlight";
brightness-levels = <0 4 8 16 32 64 100 128 255>;
status = "disabled";
};
pcie0_rc: pcie@ca000000 {
compatible = "k1x,dwc-pcie";
reg = <0x0 0xca000000 0x0 0x00001000>, /* dbi */
@ -841,6 +857,10 @@
};
};
shutdown_charging: charging {
compatible = "k1,shutdown-charging";
status = "disabled";
};
};
binman: binman {

View file

@ -0,0 +1,207 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Copyright (c) 2023 Spacemit, Inc */
/dts-v1/;
#include "k1-x.dtsi"
#include "k1-x_pinctrl.dtsi"
#include "k1-x_spm8821.dtsi"
/ {
model = "spacemit k1-x FusionOne board";
aliases {
efuse_power = &ldo_31;
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x00000000 0x00000000 0x80000000>;
};
chosen {
bootargs = "earlycon=sbi console=ttyS0,115200 debug loglevel=8,initcall_debug=1 rdinit=/init.tmp";
stdout-path = "serial0:115200n8";
};
usb3hub:usb3hub {
compatible = "spacemit,usb-hub";
vbus-gpios = <&gpio 127 0>; /* gpio_97 for usb3 hub output vbus */
regulator-force-boot-off;
status = "okay";
};
};
&cpus {
timebase-frequency = <24000000>;
};
&uart0 {
status = "okay";
};
&i2c2 {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2_0>;
status = "okay";
eeprom@50{
compatible = "atmel,24c02";
reg = <0x50>;
vin-supply-names = "eeprom_1v8";
status = "okay";
};
};
&i2c4 {
clock-frequency = <400000>;
status = "okay";
};
&pinctrl {
pinctrl-single,gpio-range = <
&range GPIO_49 2 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_3V_DS4)
&range GPIO_58 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_63 2 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_65 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_66 2 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_75 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_90 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_110 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_115 2 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_125 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_127 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
>;
gpio80_pmx_func0: gpio80_pmx_func0 {
pinctrl-single,pins = <
K1X_PADCONF(GPIO_80, MUX_MODE0, (EDGE_BOTH | PULL_UP | PAD_3V_DS4)) /* mmc cd */
>;
};
};
&gpio{
gpio-ranges = <
&pinctrl 49 GPIO_49 2
&pinctrl 58 GPIO_58 1
&pinctrl 63 GPIO_63 5
&pinctrl 75 GPIO_75 1
&pinctrl 79 GPIO_79 1
&pinctrl 90 GPIO_90 1
&pinctrl 110 GPIO_110 1
&pinctrl 115 GPIO_115 2
&pinctrl 125 GPIO_125 1
&pinctrl 127 GPIO_127 1
>;
};
&udc {
status = "okay";
};
&usb2phy {
status = "okay";
};
&combphy {
status = "okay";
};
&usbdrd3 {
status = "okay";
vbus-supply = <&usb3hub>;
dwc3@c0a00000 {
dr_mode = "host";
phy_type = "utmi";
snps,dis_enblslpm_quirk;
snps,dis_u2_susphy_quirk;
snps,dis_u3_susphy_quirk;
snps,dis-del-phy-power-chg-quirk;
snps,dis-tx-ipgap-linecheck-quirk;
};
};
&sdhci0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mmc1 &gpio80_pmx_func0>;
bus-width = <4>;
cd-gpios = <&gpio 80 0>;
cd-inverted;
cap-sd-highspeed;
sdh-phy-module = <0>;
clk-src-freq = <204800000>;
status = "disabled";
};
/* eMMC */
&sdhci2 {
bus-width = <8>;
non-removable;
mmc-hs400-1_8v;
mmc-hs400-enhanced-strobe;
sdh-phy-module = <1>;
clk-src-freq = <375000000>;
status = "okay";
};
&eth0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gmac0>;
phy-reset-pin = <110>;
clk_tuning_enable;
clk-tuning-by-delayline;
tx-phase = <90>;
rx-phase = <73>;
phy-mode = "rgmii";
phy-addr = <1>;
phy-handle = <&rgmii>;
ref-clock-from-phy;
mdio {
#address-cells = <0x1>;
#size-cells = <0x0>;
rgmii: phy@0 {
compatible = "ethernet-phy-id001c.c916";
device_type = "ethernet-phy";
reg = <0x1>;
};
};
};
&pcie1_rc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pcie1_3>;
status = "disabled";
};
&pcie2_rc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pcie2_4>;
status = "disabled";
};
&qspi {
status = "disabled";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_qspi>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <26500000>;
m25p,fast-read;
broken-flash-reset;
status = "disabled";
};
};
&efuse {
status = "okay";
};

View file

@ -240,6 +240,18 @@
status = "okay";
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "disabled";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <8>;
status = "disabled";
};
&mipi_dsi {
status = "disabled";
};
@ -247,7 +259,7 @@
&panel {
dcp-gpios = <&gpio 82 0>;
dcn-gpios = <&gpio 83 0>;
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
reset-gpios = <&gpio 81 0>;
status = "disabled";
};

View file

@ -23,6 +23,13 @@
bootargs = "earlycon=sbi console=ttyS0,115200 debug loglevel=8,initcall_debug=1 rdinit=/init.tmp";
stdout-path = "serial0:115200n8";
};
usb3hub: usb3hub {
compatible = "spacemit,usb-hub";
vbus-gpios = <&gpio 123 0>;
status = "okay";
};
};
&cpus {
@ -127,10 +134,36 @@
status = "okay";
};
&usbphy1 {
status = "okay";
};
&ehci1 {
status = "okay";
};
&usb2phy {
status = "okay";
};
&combphy {
status = "okay";
};
&usbdrd3 {
status = "okay";
vbus-supply = <&usb3hub>;
dwc3@c0a00000 {
dr_mode = "host";
phy_type = "utmi";
snps,dis_enblslpm_quirk;
snps,dis_u2_susphy_quirk;
snps,dis_u3_susphy_quirk;
snps,dis-del-phy-power-chg-quirk;
snps,dis-tx-ipgap-linecheck-quirk;
};
};
&sdhci0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mmc1 &gpio80_pmx_func0>;
@ -195,6 +228,18 @@
};
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "okay";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <7>;
status = "okay";
};
&mipi_dsi {
bit-clk = <933000000>;
pix-clk = <142000000>;
@ -214,7 +259,7 @@
&panel {
force-attached = "lt8911ext_edp_1080p";
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
status = "okay";
};

14
arch/riscv/dts/k1-x_MUSE-Card.dts Executable file → Normal file
View file

@ -258,6 +258,18 @@
status = "okay";
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "disabled";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <6>;
status = "disabled";
};
&mipi_dsi {
status = "disabled";
};
@ -265,7 +277,7 @@
&panel {
dcp-gpios = <&gpio 40 0>;
dcn-gpios = <&gpio 83 0>;
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
reset-gpios = <&gpio 41 0>;
status = "disabled";
};

View file

@ -0,0 +1,271 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Copyright (c) 2023 Spacemit, Inc */
/dts-v1/;
#include "k1-x.dtsi"
#include "k1-x_pinctrl.dtsi"
#include "k1-x_spm8821.dtsi"
/ {
model = "MUSE-PAPER-MINI-4G";
aliases {
efuse_power = &ldo_31;
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x00000000 0x00000000 0x80000000>;
};
chosen {
bootargs = "earlycon=sbi console=ttyS0,115200 debug loglevel=8,initcall_debug=1 rdinit=/init.tmp";
stdout-path = "serial0:115200n8";
};
usb2hub: usb2hub {
compatible = "spacemit,usb-hub";
vbus-gpios = <&gpio 123 0>; /* for usb2 hub output vbus */
status = "disabled";
};
usb3hub: usb3hub {
compatible = "spacemit,usb-hub";
vbus-gpios = <&gpio 79 0>; /* gpio_79 for usb3 pwren */
status = "disabled";
};
};
&cpus {
timebase-frequency = <24000000>;
};
&uart0 {
status = "okay";
};
&i2c0 {
status = "disabled";
};
&i2c1 {
status = "disabled";
};
&i2c2 {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2_0>;
status = "okay";
eeprom@50{
compatible = "atmel,24c02";
reg = <0x50>;
vin-supply-names = "eeprom_1v8";
status = "okay";
};
};
&i2c3 {
status = "disabled";
};
&i2c4 {
clock-frequency = <400000>;
status = "disabled";
};
&i2c5 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c5_0>;
status = "disabled";
};
&i2c6 {
status = "disabled";
};
&i2c7 {
status = "disabled";
};
&pinctrl {
pinctrl-single,gpio-range = <
&range GPIO_49 2 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_3V_DS4)
&range GPIO_58 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_63 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_64 1 (MUX_MODE1 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_65 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_66 2 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range PRI_TDI 2 (MUX_MODE1 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range PRI_TCK 1 (MUX_MODE1 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range PRI_TDO 1 (MUX_MODE1 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_74 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_79 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_80 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_3V_DS4)
&range GPIO_81 3 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_90 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_91 2 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range DVL0 2 (MUX_MODE1 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_110 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_114 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_115 2 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_123 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_124 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_125 3 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
>;
gpio80_pmx_func0: gpio80_pmx_func0 {
pinctrl-single,pins = <
K1X_PADCONF(GPIO_80, MUX_MODE0, (EDGE_BOTH | PULL_UP | PAD_3V_DS4)) /* mmc cd */
>;
};
};
&gpio{
gpio-ranges = <
&pinctrl 49 GPIO_49 2
&pinctrl 58 GPIO_58 1
&pinctrl 63 GPIO_63 1
&pinctrl 65 GPIO_65 3
&pinctrl 70 PRI_TDI 4
&pinctrl 74 GPIO_74 1
&pinctrl 79 GPIO_79 1
&pinctrl 80 GPIO_80 4
&pinctrl 90 GPIO_90 3
&pinctrl 96 DVL0 2
&pinctrl 110 GPIO_110 1
&pinctrl 114 GPIO_114 3
&pinctrl 123 GPIO_123 5
>;
};
&udc {
status = "disabled";
};
&usbphy1 {
status = "disabled";
};
&ehci1 {
vbus-supply = <&usb2hub>;
status = "disabled";
};
&usb2phy {
status = "disabled";
};
&combphy {
status = "disabled";
};
&usbdrd3 {
status = "disabled";
vbus-supply = <&usb3hub>;
dwc3@c0a00000 {
dr_mode = "host";
phy_type = "utmi";
snps,dis_enblslpm_quirk;
snps,dis_u2_susphy_quirk;
snps,dis_u3_susphy_quirk;
snps,dis-del-phy-power-chg-quirk;
snps,dis-tx-ipgap-linecheck-quirk;
};
};
&sdhci0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mmc1 &gpio80_pmx_func0>;
bus-width = <4>;
cd-gpios = <&gpio 80 0>;
cap-sd-highspeed;
sdh-phy-module = <0>;
clk-src-freq = <204800000>;
status = "okay";
};
/* eMMC */
&sdhci2 {
bus-width = <8>;
non-removable;
mmc-hs400-1_8v;
mmc-hs400-enhanced-strobe;
sdh-phy-module = <1>;
clk-src-freq = <375000000>;
status = "okay";
};
&qspi {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_qspi>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <26500000>;
m25p,fast-read;
broken-flash-reset;
status = "okay";
};
};
&efuse {
status = "okay";
};
&ldo_27 {
regulator-init-microvolt = <1200000>;
regulator-boot-on;
regulator-state-mem {
regulator-off-in-suspend;
};
};
&ldo_33 {
regulator-init-microvolt = <1800000>;
regulator-boot-on;
regulator-state-mem {
regulator-off-in-suspend;
};
};
&dpu {
status = "okay";
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "okay";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <6>;
status = "okay";
};
&mipi_dsi {
bit-clk = <614400000>;
pix-clk = <76800000>;
status = "okay";
};
&panel {
force-attached = "jd9365dah3";
dcp-gpios = <&gpio 34 0>;
dcn-gpios = <&gpio 42 0>;
avee-gpios = <&gpio 35 0>;
avdd-gpios = <&gpio 36 0>;
backlight = <&backlight>;
enable-gpios = <&gpio 31 0>;
reset-gpios = <&gpio 30 0>;
status = "okay";
};

111
arch/riscv/dts/k1-x_MUSE-Paper.dts Executable file → Normal file
View file

@ -6,6 +6,7 @@
#include "k1-x.dtsi"
#include "k1-x_pinctrl.dtsi"
#include "k1-x_spm8821.dtsi"
#include <dt-bindings/input/input.h>
/ {
model = "M1-MUSE-PAPER";
@ -36,6 +37,26 @@
status = "disabled";
};
gpio_keys: gpio_keys {
compatible = "gpio-keys";
fastboot-key-combo = "volume-up";
fastboot-key-press-time = <2000>; /* in milliseconds */
volume-up-button {
label = "volume-up";
linux,code = <KEY_VOLUMEUP>;
gpios = <&gpio 70 1>;
debounce-interval = <10>;
};
volume-down-button {
label = "volume-down";
linux,code = <KEY_VOLUMEDOWN>;
gpios = <&gpio 71 1>;
debounce-interval = <10>;
};
};
};
&cpus {
@ -74,8 +95,27 @@
};
&i2c4 {
clock-frequency = <400000>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c4_2>;
status = "okay";
cw2015: cw2015@62 {
compatible = "spacemit,cw2015";
reg = <0x62>;
cellwise,battery-profile = /bits/ 8 <
0x17 0x67 0x73 0x69 0x68 0x65 0x64 0x55
0x75 0x60 0x4A 0x57 0x57 0x4E 0x42 0x3A
0x30 0x28 0x23 0x1E 0x23 0x35 0x46 0x4D
0x14 0x86 0x06 0x66 0x25 0x45 0x51 0x63
0x72 0x69 0x66 0x6B 0x3F 0x1B 0x78 0x39
0x0A 0x2F 0x1A 0x46 0x88 0x94 0x9B 0x12
0x3B 0x5F 0x9A 0xB6 0x80 0x57 0x7F 0xCB
0x2F 0x00 0x64 0xA5 0xB5 0xC1 0x46 0xAE
>;
status = "okay";
};
};
&i2c5 {
@ -85,13 +125,40 @@
};
&i2c6 {
status = "disabled";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c6_0>;
status = "okay";
secsgm41515: sgm41515-2 {
compatible = "spacemit,sgm41515";
reg = <0x1a>;
ch-en-gpios = <&gpio 46 0>;
nqon-gpios = <&gpio 43 0>;
sgm41515-ichrg-uA = <1000000>;
sgm41515-vchrg-uV = <4350000>;
sgm41515-cur-input-uA = <2000000>;
status = "okay";
};
};
&i2c7 {
status = "disabled";
};
&i2c8 {
sgm41515: sgm41515 {
compatible = "spacemit,sgm41515";
reg = <0x1a>;
ch-en-gpios = <&gpio 117 0>;
nqon-gpios = <&gpio 115 0>;
sgm41515-ichrg-uA = <1000000>;
sgm41515-vchrg-uV = <4350000>;
sgm41515-cur-input-uA = <2000000>;
status = "okay";
};
};
&pinctrl {
pinctrl-single,gpio-range = <
&range GPIO_49 2 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_3V_DS4)
@ -240,6 +307,18 @@
};
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "okay";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <4>;
status = "okay";
};
&mipi_dsi {
status = "okay";
};
@ -250,8 +329,32 @@
dcn-gpios = <&gpio 42 0>;
avee-gpios = <&gpio 35 0>;
avdd-gpios = <&gpio 36 0>;
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
enable-gpios = <&gpio 31 0>;
reset-gpios = <&gpio 30 0>;
status = "okay";
};
&shutdown_charging {
electricity-meter = <&cw2015>;
power-domains = <&pmu K1X_PMU_WKUP_EVENT_PWR_DOMAIN>;
wk-name = "pwr_event", "pwr_int", "rtc_ctrl", "rtc_event", "rtc_irq", "sys-shutdown";
pwr_event = <&power_event>;
pwr_int = <&power_int>;
rtc_ctrl = <&rtc_ctrl>;
rtc_event = <&rtc_event>;
rtc_irq = <&rtc_irq>;
sys-shutdown = <&power_down>;
reboot-flag = <&reboot_flag>;
charge-light = <&gpio 75 0 &gpio 76 0>;
charger-name = "charger0", "charger1";
charger0 = <&sgm41515>;
charger1 = <&secsgm41515>;
status = "okay";
};

View file

@ -273,6 +273,18 @@
status = "okay";
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "disabled";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <6>;
status = "disabled";
};
&mipi_dsi {
status = "disabled";
};
@ -280,7 +292,7 @@
&panel {
dcp-gpios = <&gpio 82 0>;
dcn-gpios = <&gpio 83 0>;
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
reset-gpios = <&gpio 81 0>;
status = "disabled";
};

View file

@ -0,0 +1,295 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Copyright (c) 2023 Spacemit, Inc */
/dts-v1/;
#include "k1-x.dtsi"
#include "k1-x_pinctrl.dtsi"
#include "k1-x_spm8821.dtsi"
/ {
model = "spacemit k1-x baton-camera board";
aliases {
efuse_power = &ldo_31;
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x00000000 0x00000000 0x80000000>;
};
chosen {
bootargs = "earlycon=sbi console=ttyS0,115200 debug loglevel=8,initcall_debug=1 rdinit=/init.tmp";
stdout-path = "serial0:115200n8";
};
usb2hub: usb2hub {
compatible = "spacemit,usb-hub";
vbus-gpios = <&gpio 123 0>; /* for usb2 hub output vbus */
status = "okay";
};
usb3hub: usb3hub {
compatible = "spacemit,usb-hub";
vbus-gpios = <&gpio 79 0>; /* gpio_79 for usb3 pwren */
status = "okay";
};
};
&cpus {
timebase-frequency = <24000000>;
};
&uart0 {
status = "okay";
};
&i2c0 {
status = "disabled";
};
&i2c1 {
status = "disabled";
};
&i2c2 {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2_0>;
status = "okay";
eeprom@50{
compatible = "atmel,24c02";
reg = <0x50>;
vin-supply-names = "eeprom_1v8";
status = "okay";
};
};
&i2c3 {
status = "disabled";
};
&i2c4 {
clock-frequency = <400000>;
status = "okay";
};
&i2c5 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c5_0>;
status = "okay";
};
&i2c6 {
status = "disabled";
};
&i2c7 {
status = "disabled";
};
&pinctrl {
pinctrl-single,gpio-range = <
&range GPIO_49 2 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_3V_DS4)
&range GPIO_58 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_63 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_64 1 (MUX_MODE1 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_65 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_66 2 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range PRI_TDI 2 (MUX_MODE1 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range PRI_TCK 1 (MUX_MODE1 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range PRI_TDO 1 (MUX_MODE1 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_74 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_79 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_80 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_3V_DS4)
&range GPIO_81 3 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_90 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_91 2 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range DVL0 2 (MUX_MODE1 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_110 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_114 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_115 2 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_123 1 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
&range GPIO_124 1 (MUX_MODE0 | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
&range GPIO_125 3 (MUX_MODE0 | EDGE_NONE | PULL_DOWN | PAD_1V8_DS2)
>;
gpio80_pmx_func0: gpio80_pmx_func0 {
pinctrl-single,pins = <
K1X_PADCONF(GPIO_80, MUX_MODE0, (EDGE_BOTH | PULL_UP | PAD_3V_DS4)) /* mmc cd */
>;
};
};
&gpio{
gpio-ranges = <
&pinctrl 49 GPIO_49 2
&pinctrl 58 GPIO_58 1
&pinctrl 63 GPIO_63 1
&pinctrl 65 GPIO_65 3
&pinctrl 70 PRI_TDI 4
&pinctrl 74 GPIO_74 1
&pinctrl 79 GPIO_79 1
&pinctrl 80 GPIO_80 4
&pinctrl 90 GPIO_90 3
&pinctrl 96 DVL0 2
&pinctrl 110 GPIO_110 1
&pinctrl 114 GPIO_114 3
&pinctrl 123 GPIO_123 5
>;
};
&udc {
status = "okay";
};
&usbphy1 {
status = "okay";
};
&ehci1 {
vbus-supply = <&usb2hub>;
status = "okay";
};
&usb2phy {
status = "okay";
};
&combphy {
status = "okay";
};
&usbdrd3 {
status = "okay";
vbus-supply = <&usb3hub>;
dwc3@c0a00000 {
dr_mode = "host";
phy_type = "utmi";
snps,dis_enblslpm_quirk;
snps,dis_u2_susphy_quirk;
snps,dis_u3_susphy_quirk;
snps,dis-del-phy-power-chg-quirk;
snps,dis-tx-ipgap-linecheck-quirk;
};
};
&sdhci0 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mmc1 &gpio80_pmx_func0>;
bus-width = <4>;
cd-gpios = <&gpio 80 0>;
cap-sd-highspeed;
sdh-phy-module = <0>;
clk-src-freq = <204800000>;
status = "disabled";
};
/* eMMC */
&sdhci2 {
bus-width = <8>;
non-removable;
mmc-hs400-1_8v;
mmc-hs400-enhanced-strobe;
sdh-phy-module = <1>;
clk-src-freq = <375000000>;
status = "okay";
};
&eth0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gmac0>;
phy-reset-pin = <110>;
clk_tuning_enable;
clk-tuning-by-delayline;
tx-phase = <90>;
rx-phase = <73>;
phy-mode = "rgmii";
phy-addr = <1>;
phy-handle = <&rgmii>;
ref-clock-from-phy;
mdio {
#address-cells = <0x1>;
#size-cells = <0x0>;
rgmii: phy@0 {
compatible = "ethernet-phy-id001c.c916";
device_type = "ethernet-phy";
reg = <0x1>;
};
};
};
&pcie0_rc {
status = "disabled";
};
&pcie1_rc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pcie1_3>;
status = "disabled";
};
&qspi {
status = "disabled";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_qspi>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <26500000>;
m25p,fast-read;
broken-flash-reset;
status = "disabled";
};
};
&efuse {
status = "okay";
};
&dpu {
status = "okay";
};
&hdmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hdmi_0>;
status = "disabled";
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "disabled";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <6>;
status = "disabled";
};
&mipi_dsi {
status = "disabled";
};
&panel {
dcp-gpios = <&gpio 40 0>;
dcn-gpios = <&gpio 83 0>;
backlight = <&backlight>;
reset-gpios = <&gpio 41 0>;
status = "disabled";
};

View file

@ -259,6 +259,18 @@
status = "okay";
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "disabled";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <6>;
status = "disabled";
};
&mipi_dsi {
status = "disabled";
};
@ -266,7 +278,7 @@
&panel {
dcp-gpios = <&gpio 82 0>;
dcn-gpios = <&gpio 83 0>;
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
reset-gpios = <&gpio 81 0>;
status = "disabled";
};

View file

@ -256,6 +256,18 @@
status = "okay";
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "disabled";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <6>;
status = "disabled";
};
&mipi_dsi {
status = "disabled";
};
@ -263,7 +275,7 @@
&panel {
dcp-gpios = <&gpio 82 0>;
dcn-gpios = <&gpio 83 0>;
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
reset-gpios = <&gpio 81 0>;
status = "disabled";
};

View file

@ -236,6 +236,18 @@
};
};
&pwm1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm1_2>;
status = "disabled";
};
&backlight {
pwms = <&pwm1 0 2000>;
default-brightness-level = <6>;
status = "disabled";
};
&mipi_dsi {
status = "disabled";
};

View file

@ -200,6 +200,18 @@
};
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "okay";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <7>;
status = "okay";
};
&mipi_dsi {
bit-clk = <933000000>;
pix-clk = <142000000>;
@ -219,7 +231,7 @@
&panel {
force-attached = "lt8911ext_edp_1080p";
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
status = "okay";
};

View file

@ -259,6 +259,18 @@
status = "okay";
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "disabled";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <6>;
status = "disabled";
};
&mipi_dsi {
status = "disabled";
};
@ -266,7 +278,7 @@
&panel {
dcp-gpios = <&gpio 82 0>;
dcn-gpios = <&gpio 83 0>;
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
reset-gpios = <&gpio 81 0>;
status = "disabled";
};

View file

@ -259,6 +259,18 @@
status = "okay";
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "disabled";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <8>;
status = "disabled";
};
&mipi_dsi {
status = "disabled";
};
@ -266,7 +278,7 @@
&panel {
dcp-gpios = <&gpio 82 0>;
dcn-gpios = <&gpio 83 0>;
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
reset-gpios = <&gpio 81 0>;
status = "disabled";
};

View file

@ -22,7 +22,7 @@
regulator-boot-on;
u-boot,dm-spl;
regulator-state-mem {
regulator-off-in-suspend;
regulator-suspend-microvolt = <650000>;
};
};
@ -30,6 +30,9 @@
regulator-name = "dcdc2";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3450000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
dcdc_8: DCDC_REG3 {
@ -38,24 +41,36 @@
regulator-max-microvolt = <3450000>;
regulator-boot-on;
u-boot,dm-spl;
regulator-state-mem {
regulator-off-in-suspend;
};
};
dcdc_9: DCDC_REG4 {
regulator-name = "dcdc4";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3450000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
dcdc_10: DCDC_REG5 {
regulator-name = "dcdc5";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3450000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
dcdc_11: DCDC_REG6 {
regulator-name = "dcdc6";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3450000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
/* aldo */
@ -66,24 +81,36 @@
regulator-init-microvolt = <3300000>;
regulator-boot-on;
u-boot,dm-spl;
regulator-state-mem {
regulator-off-in-suspend;
};
};
ldo_24: LDO_REG2 {
regulator-name = "ldo2";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
ldo_25: LDO_REG3 {
regulator-name = "ldo3";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
ldo_26: LDO_REG4 {
regulator-name = "ldo4";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
/* dldo */
@ -91,48 +118,97 @@
regulator-name = "ldo5";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
ldo_28: LDO_REG6 {
regulator-name = "ldo6";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
ldo_29: LDO_REG7 {
regulator-name = "ldo7";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
ldo_30: LDO_REG8 {
regulator-name = "ldo8";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
ldo_31: LDO_REG9 {
regulator-name = "ldo9";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
ldo_32: LDO_REG10 {
regulator-name = "ldo10";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
ldo_33: LDO_REG11 {
regulator-name = "ldo11";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <3400000>;
regulator-state-mem {
regulator-off-in-suspend;
};
};
sw_2: SWITCH_REG1 {
regulator-name = "switch1";
};
power_event: SWITCH_REG2 {
regulator-name = "pwr-event";
};
power_int: SWITCH_REG3 {
regulator-name = "pwr-int";
};
rtc_ctrl: SWITCH_REG4 {
regulator-name = "rtc-ctrl";
};
rtc_event: SWITCH_REG5 {
regulator-name = "rtc-event";
};
rtc_irq: SWITCH_REG6 {
regulator-name = "rtc-irq";
};
power_down: SWITCH_REG7 {
regulator-name = "power-down";
};
reboot_flag: SWITCH_REG8 {
regulator-name = "reboot-flag";
};
wdt_pm8821: PMIC_WDT {
wdt-name = "wdt_pm8821";
};

View file

@ -259,6 +259,18 @@
status = "okay";
};
&pwm14 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm14_1>;
status = "disabled";
};
&backlight {
pwms = <&pwm14 0 2000>;
default-brightness-level = <8>;
status = "disabled";
};
&mipi_dsi {
status = "disabled";
};
@ -266,7 +278,7 @@
&panel {
dcp-gpios = <&gpio 82 0>;
dcn-gpios = <&gpio 83 0>;
bl-gpios = <&gpio 44 0>;
backlight = <&backlight>;
reset-gpios = <&gpio 81 0>;
status = "disabled";
};

View file

@ -0,0 +1,42 @@
#ifndef __SLEEP__H_
#define __SLEEP__H_
#define PT_EPC 0 /* offsetof(struct pt_regs, epc) */
#define PT_RA 8 /* offsetof(struct pt_regs, ra) */
#define PT_S0 64 /* offsetof(struct pt_regs, s0) */
#define PT_S1 72 /* offsetof(struct pt_regs, s1) */
#define PT_S2 144 /* offsetof(struct pt_regs, s2) */
#define PT_S3 152 /* offsetof(struct pt_regs, s3) */
#define PT_S4 160 /* offsetof(struct pt_regs, s4) */
#define PT_S5 168 /* offsetof(struct pt_regs, s5) */
#define PT_S6 176 /* offsetof(struct pt_regs, s6) */
#define PT_S7 184 /* offsetof(struct pt_regs, s7) */
#define PT_S8 192 /* offsetof(struct pt_regs, s8) */
#define PT_S9 200 /* offsetof(struct pt_regs, s9) */
#define PT_S10 208 /* offsetof(struct pt_regs, s10) */
#define PT_S11 216 /* offsetof(struct pt_regs, s11) */
#define PT_SP 16 /* offsetof(struct pt_regs, sp) */
#define PT_TP 32 /* offsetof(struct pt_regs, tp) */
#define PT_A0 80 /* offsetof(struct pt_regs, a0) */
#define PT_A1 88 /* offsetof(struct pt_regs, a1) */
#define PT_A2 96 /* offsetof(struct pt_regs, a2) */
#define PT_A3 104 /* offsetof(struct pt_regs, a3) */
#define PT_A4 112 /* offsetof(struct pt_regs, a4) */
#define PT_A5 120 /* offsetof(struct pt_regs, a5) */
#define PT_A6 128 /* offsetof(struct pt_regs, a6) */
#define PT_A7 136 /* offsetof(struct pt_regs, a7) */
#define PT_T0 40 /* offsetof(struct pt_regs, t0) */
#define PT_T1 48 /* offsetof(struct pt_regs, t1) */
#define PT_T2 56 /* offsetof(struct pt_regs, t2) */
#define PT_T3 224 /* offsetof(struct pt_regs, t3) */
#define PT_T4 232 /* offsetof(struct pt_regs, t4) */
#define PT_T5 240 /* offsetof(struct pt_regs, t5) */
#define PT_T6 248 /* offsetof(struct pt_regs, t6) */
#define PT_GP 24 /* offsetof(struct pt_regs, gp) */
#define PT_ORIG_A0 280 /* offsetof(struct pt_regs, orig_a0) */
#define PT_STATUS 256 /* offsetof(struct pt_regs, status) */
#define PT_BADADDR 264 /* offsetof(struct pt_regs, badaddr) */
#define PT_CAUSE 272 /* offsetof(struct pt_regs, cause) */
#define SUSPEND_CONTEXT_REGS 0 /* offsetof(struct suspend_context, regs) */
#endif

View file

@ -0,0 +1 @@
obj-y += suspend_entry.o

View file

@ -0,0 +1,112 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021 Western Digital Corporation or its affiliates.
* Copyright (c) 2022 Ventana Micro Systems Inc.
*/
#include <linux/linkage.h>
#include <asm/asm.h>
#include <asm/csr.h>
#include <asm/sleep.h>
#define LREG ld
#define SREG sd
.text
.altmacro
.option norelax
ENTRY(__cpu_suspend_enter)
/* Save registers (except A0 and T0-T6) */
SREG ra, (SUSPEND_CONTEXT_REGS + PT_RA)(a0)
SREG sp, (SUSPEND_CONTEXT_REGS + PT_SP)(a0)
SREG gp, (SUSPEND_CONTEXT_REGS + PT_GP)(a0)
SREG tp, (SUSPEND_CONTEXT_REGS + PT_TP)(a0)
SREG s0, (SUSPEND_CONTEXT_REGS + PT_S0)(a0)
SREG s1, (SUSPEND_CONTEXT_REGS + PT_S1)(a0)
SREG a1, (SUSPEND_CONTEXT_REGS + PT_A1)(a0)
SREG a2, (SUSPEND_CONTEXT_REGS + PT_A2)(a0)
SREG a3, (SUSPEND_CONTEXT_REGS + PT_A3)(a0)
SREG a4, (SUSPEND_CONTEXT_REGS + PT_A4)(a0)
SREG a5, (SUSPEND_CONTEXT_REGS + PT_A5)(a0)
SREG a6, (SUSPEND_CONTEXT_REGS + PT_A6)(a0)
SREG a7, (SUSPEND_CONTEXT_REGS + PT_A7)(a0)
SREG s2, (SUSPEND_CONTEXT_REGS + PT_S2)(a0)
SREG s3, (SUSPEND_CONTEXT_REGS + PT_S3)(a0)
SREG s4, (SUSPEND_CONTEXT_REGS + PT_S4)(a0)
SREG s5, (SUSPEND_CONTEXT_REGS + PT_S5)(a0)
SREG s6, (SUSPEND_CONTEXT_REGS + PT_S6)(a0)
SREG s7, (SUSPEND_CONTEXT_REGS + PT_S7)(a0)
SREG s8, (SUSPEND_CONTEXT_REGS + PT_S8)(a0)
SREG s9, (SUSPEND_CONTEXT_REGS + PT_S9)(a0)
SREG s10, (SUSPEND_CONTEXT_REGS + PT_S10)(a0)
SREG s11, (SUSPEND_CONTEXT_REGS + PT_S11)(a0)
/* Save CSRs */
csrr t0, CSR_SEPC
SREG t0, (SUSPEND_CONTEXT_REGS + PT_EPC)(a0)
csrr t0, CSR_SSTATUS
SREG t0, (SUSPEND_CONTEXT_REGS + PT_STATUS)(a0)
csrr t0, CSR_STVAL
SREG t0, (SUSPEND_CONTEXT_REGS + PT_BADADDR)(a0)
csrr t0, CSR_SCAUSE
SREG t0, (SUSPEND_CONTEXT_REGS + PT_CAUSE)(a0)
/* Return non-zero value */
li a0, 1
/* Return to C code */
ret
END(__cpu_suspend_enter)
ENTRY(__cpu_resume_enter)
/* Load the global pointer */
# .option push
# .option norelax
# la gp, gd
# .option pop
/* Make A0 point to suspend context */
add a0, a1, zero
/* Restore CSRs */
LREG t0, (SUSPEND_CONTEXT_REGS + PT_EPC)(a0)
csrw CSR_SEPC, t0
LREG t0, (SUSPEND_CONTEXT_REGS + PT_STATUS)(a0)
csrw CSR_SSTATUS, t0
LREG t0, (SUSPEND_CONTEXT_REGS + PT_BADADDR)(a0)
csrw CSR_STVAL, t0
LREG t0, (SUSPEND_CONTEXT_REGS + PT_CAUSE)(a0)
csrw CSR_SCAUSE, t0
/* Restore registers (except A0 and T0-T6) */
LREG ra, (SUSPEND_CONTEXT_REGS + PT_RA)(a0)
LREG sp, (SUSPEND_CONTEXT_REGS + PT_SP)(a0)
LREG gp, (SUSPEND_CONTEXT_REGS + PT_GP)(a0)
LREG tp, (SUSPEND_CONTEXT_REGS + PT_TP)(a0)
LREG s0, (SUSPEND_CONTEXT_REGS + PT_S0)(a0)
LREG s1, (SUSPEND_CONTEXT_REGS + PT_S1)(a0)
LREG a1, (SUSPEND_CONTEXT_REGS + PT_A1)(a0)
LREG a2, (SUSPEND_CONTEXT_REGS + PT_A2)(a0)
LREG a3, (SUSPEND_CONTEXT_REGS + PT_A3)(a0)
LREG a4, (SUSPEND_CONTEXT_REGS + PT_A4)(a0)
LREG a5, (SUSPEND_CONTEXT_REGS + PT_A5)(a0)
LREG a6, (SUSPEND_CONTEXT_REGS + PT_A6)(a0)
LREG a7, (SUSPEND_CONTEXT_REGS + PT_A7)(a0)
LREG s2, (SUSPEND_CONTEXT_REGS + PT_S2)(a0)
LREG s3, (SUSPEND_CONTEXT_REGS + PT_S3)(a0)
LREG s4, (SUSPEND_CONTEXT_REGS + PT_S4)(a0)
LREG s5, (SUSPEND_CONTEXT_REGS + PT_S5)(a0)
LREG s6, (SUSPEND_CONTEXT_REGS + PT_S6)(a0)
LREG s7, (SUSPEND_CONTEXT_REGS + PT_S7)(a0)
LREG s8, (SUSPEND_CONTEXT_REGS + PT_S8)(a0)
LREG s9, (SUSPEND_CONTEXT_REGS + PT_S9)(a0)
LREG s10, (SUSPEND_CONTEXT_REGS + PT_S10)(a0)
LREG s11, (SUSPEND_CONTEXT_REGS + PT_S11)(a0)
/* Return zero value */
add a0, zero, zero
/* Return to C code */
ret
END(__cpu_resume_enter)

View file

@ -5,3 +5,4 @@
obj-y += k1x.o
obj-$(CONFIG_SPL_BUILD) += spl.o k1x-i2c-eeprom.o k1x-tlvinfo.o
obj-$(CONFIG_SPLASH_SOURCE) +=splash.o
obj-$(CONFIG_ENV_IS_IN_NFS) +=nfs_env.o

View file

@ -154,6 +154,33 @@
algo = "crc32";
};
};
fdt_16 {
description = "k1-x_MUSE-Paper-mini-4g";
type = "flat_dt";
compression = "none";
data = /incbin/("../dtb/k1-x_MUSE-Paper-mini-4g.dtb");
hash-1 {
algo = "crc32";
};
};
fdt_17 {
description = "k1-x_baton-camera";
type = "flat_dt";
compression = "none";
data = /incbin/("../dtb/k1-x_baton-camera.dtb");
hash-1 {
algo = "crc32";
};
};
fdt_18 {
description = "k1-x_FusionOne";
type = "flat_dt";
compression = "none";
data = /incbin/("../dtb/k1-x_FusionOne.dtb");
hash-1 {
algo = "crc32";
};
};
};
configurations {
@ -233,5 +260,20 @@
loadables = "uboot";
fdt = "fdt_15";
};
conf_16 {
description = "k1-x_MUSE-Paper-mini-4g";
loadables = "uboot";
fdt = "fdt_16";
};
conf_17 {
description = "k1-x_baton-camera";
loadables = "uboot";
fdt = "fdt_17";
};
conf_18 {
description = "k1-x_FusionOne";
loadables = "uboot";
fdt = "fdt_18";
};
};
};

View file

@ -6,7 +6,7 @@ bootdelay=0
baudrate=115200
loglevel=8
stderr=serial
stdin=serial,usbkbd
stdin=serial,usbkbd,usbkbd1
stdout=serial
workqueue.default_affinity_scope=system
@ -45,11 +45,12 @@ set_nor_root=run get_rootfs_env; run set_rootfs_env;
//ethaddr=fe:fe:fe:22:22:01
//eth1addr=fe:fe:fe:22:22:02
ipaddr=10.0.92.100
ipaddr=
netmask=255.255.255.0
serverip=10.0.92.134
serverip=10.0.92.148
gatewayip=10.0.92.1
net_data_path=net_flash_file/net_flash_file/
mac_mapping_file=/home/it/nfs/bianbu/mac_mapping.txt
preboot=
ramdisk_size=-
@ -65,7 +66,7 @@ phy_link_time=10000
netdev=eth0
// Common boot args
commonargs=setenv bootargs earlycon=${earlycon} earlyprintk console=tty1 console=${console} loglevel=${loglevel} clk_ignore_unused swiotlb=65536 rdinit=${init} workqueue.default_affinity_scope=${workqueue.default_affinity_scope}
commonargs=setenv bootargs earlycon=${earlycon} earlyprintk quiet splash plymouth.ignore-serial-consoles plymouth.prefer-fbcon console=${console} loglevel=${loglevel} clk_ignore_unused swiotlb=65536 rdinit=${init} workqueue.default_affinity_scope=${workqueue.default_affinity_scope}
//detect product_name from env and select dtb file to load
dtb_env=if test -n "${product_name}"; then \
@ -112,7 +113,7 @@ loaddtb=echo "Loading dtb..."; \
fi;
// Nor+ssd boot combo
set_nor_args=setenv bootargs ${bootargs} mtdparts=${mtdparts} root=${blk_root} rootfstype=ext4
set_nor_args=setenv bootargs "${bootargs}" mtdparts=${mtdparts} root=${blk_root} rootfstype=ext4
nor_boot=echo "Try to boot from ${bootfs_devname}${boot_devnum} ..."; \
run commonargs; \
run set_nor_root; \
@ -140,6 +141,26 @@ mmc_boot=echo "Try to boot from ${bootfs_devname}${boot_devnum} ..."; \
bootm ${kernel_addr_r} ${ramdisk_combo} ${dtb_addr}; \
echo "########### boot kernel failed by default config, check your boot config #############"
nfs_boot=echo "Try to boot from NFS ..."; \
run commonargs; \
setenv bootargs "${bootargs}" root=/dev/nfs nfsroot=${serverip}:${rootfs_path} bootfs=${serverip}:${bootfs_path}; \
echo "bootargs: ${bootargs}"; \
run detect_dtb; \
echo "Loading kernel from NFS..."; \
nfs ${kernel_addr_r} ${serverip}:${bootfs_path}/${knl_name}; \
echo "Loading dtb from NFS..."; \
nfs ${dtb_addr} ${serverip}:${bootfs_path}/${dtb_name}; \
if test -n "${ramdisk_name}"; then \
echo "Loading ramdisk from NFS..."; \
nfs ${ramdisk_addr} ${serverip}:${bootfs_path}/${ramdisk_name}; \
setenv ramdisk_size ${filesize}; \
setenv ramdisk_combo ${ramdisk_addr}:${ramdisk_size}; \
else \
setenv ramdisk_combo -; \
fi; \
bootm ${kernel_addr_r} ${ramdisk_combo} ${dtb_addr}; \
echo "########### boot kernel failed from NFS, check your boot config #############"
// Variable "boot_device" is set during board_late_init()
autoboot=if test ${boot_device} = nand; then \
run nand_boot; \
@ -147,6 +168,8 @@ autoboot=if test ${boot_device} = nand; then \
run nor_boot; \
elif test ${boot_device} = mmc; then \
run mmc_boot; \
elif test ${boot_device} = nfs; then \
run nfs_boot; \
fi;
bootcmd=run autoboot; echo "run autoboot"

View file

@ -7,6 +7,7 @@
#include <asm/global_data.h>
#include <stdlib.h>
#include <linux/delay.h>
#include <tlv_eeprom.h>
DECLARE_GLOBAL_DATA_PTR;
@ -23,6 +24,11 @@ DECLARE_GLOBAL_DATA_PTR;
#define I2C_PIN_CONFIG(x) ((x) | EDGE_NONE | PULL_UP | PAD_1V8_DS2)
#define READ_I2C_LINE_LEN (16)
int _read_from_i2c(int chip, u32 addr, u32 size, uchar *buf);
bool _is_valid_tlvinfo_header(struct tlvinfo_header *hdr);
static __section(".data") uint8_t tlv_data[256];
char *spacemit_i2c_eeprom[] = {
"atmel,24c02",
};
@ -47,24 +53,33 @@ const struct eeprom_config eeprom_info[] = {
{6, 0x50, MUX_MODE2, 0xd401e228, 0xd401e22c},
};
int spacemit_eeprom_read(uint8_t chip, uint8_t *buffer, uint8_t id)
static void init_tlv_data(uint8_t chip, uint8_t *buffer, uint32_t size)
{
uint32_t offset;
struct tlvinfo_header *hdr = (struct tlvinfo_header*)buffer;
offset = sizeof(struct tlvinfo_header);
_read_from_i2c(chip, 0, offset, buffer);
if (!_is_valid_tlvinfo_header(hdr) || ((be16_to_cpu(hdr->totallen) + offset) > size)) {
memset(buffer, 0, size);
return;
}
_read_from_i2c(chip, offset, be16_to_cpu(hdr->totallen), buffer + offset);
}
int spacemit_eeprom_read(uint8_t *buffer, uint8_t id)
{
struct tlv_eeprom tlv;
int ret;
uint8_t buf[1] = {0};
uint8_t len[1] = {0};
uint16_t i = 0;
uint8_t j;
uint32_t i;
tlv.type = 0;
tlv.length = 0;
for (i = 11; i <= 256; i = i + tlv.length + 2) {
ret = i2c_read(chip, i, 1, buf, 1);
tlv.type = *buf;
ret = i2c_read(chip, i + 1, 1, len, 1);
tlv.length = *len;
for (i = sizeof(struct tlvinfo_header); i < sizeof(tlv_data);
i = i + tlv.length + 2) {
tlv.type = tlv_data[i];
tlv.length = tlv_data[i + 1];
if (tlv.length == 0) {
pr_err("Error: wrong tlv length\n");
@ -72,10 +87,7 @@ int spacemit_eeprom_read(uint8_t chip, uint8_t *buffer, uint8_t id)
}
if (tlv.type == id) {
for(j = 0; j < tlv.length; j++) {
ret = i2c_read(chip, i + 2 + j, 1, (char *)buffer, 1);
buffer++;
}
memcpy(buffer, &tlv_data[i + 2], tlv.length);
return 0;
}
}
@ -119,6 +131,7 @@ int k1x_eeprom_init(void)
}
else {
pr_info("find eeprom in bus %d, address %d\n", bus, saddr);
init_tlv_data(saddr, tlv_data, sizeof(tlv_data));
return saddr;
}
}

View file

@ -38,7 +38,7 @@ static bool had_read_tlvinfo = false;
* to the allowed maximum (2048-11)
*
*/
static bool _is_valid_tlvinfo_header(struct tlvinfo_header *hdr)
bool _is_valid_tlvinfo_header(struct tlvinfo_header *hdr)
{
return ((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) &&
(hdr->version == TLV_INFO_VERSION) &&

View file

@ -39,6 +39,17 @@
#include <fdt_simplefb.h>
#include <mtd_node.h>
#include <misc.h>
#ifdef CONFIG_ENV_IS_IN_NFS
#include "nfs_env.h"
#endif
#ifdef CONFIG_BUTTON
#include <button.h>
struct fastboot_key_config {
const char **key_names;
int key_count;
u32 press_time;
};
#endif
DECLARE_GLOBAL_DATA_PTR;
static char found_partition[64] = {0};
@ -46,6 +57,7 @@ extern u32 ddr_cs_num;
bool is_video_connected = false;
uint32_t reboot_config;
void refresh_config_info(u8 *eeprom_data);
void read_from_eeprom(struct tlvinfo_tlv **tlv_data, u8 tcode);
int mac_read_from_buffer(u8 *eeprom_data);
void set_boot_mode(enum board_boot_mode boot_mode)
@ -279,11 +291,126 @@ u32 get_reboot_config(void)
return reboot_config;
}
#ifdef CONFIG_BUTTON
static int button_get_state_by_label(struct udevice *dev, const char *label)
{
struct udevice *child;
struct button_uc_plat *plat;
int state;
bool invert_state = false;
pr_debug("Searching for button with label '%s'\n", label);
for (device_find_first_child(dev, &child);
child;
device_find_next_child(&child)) {
plat = dev_get_uclass_plat(child);
if (plat->label && !strcmp(plat->label, label)) {
invert_state = ofnode_read_bool(dev_ofnode(child), "invert-state");
state = button_get_state(child);
pr_debug("Button '%s' found, raw state: %d, invert: %d\n", label, state, invert_state);
if (invert_state) {
state = (state == BUTTON_ON) ? BUTTON_OFF : BUTTON_ON;
}
pr_debug("Button '%s' final state: %d\n", label, state);
return state;
}
}
pr_err("Button '%s' not found\n", label);
return -ENOENT;
}
static int get_fastboot_key_config(struct fastboot_key_config *config)
{
ofnode node;
int ret;
node = ofnode_path("/gpio_keys");
if (!ofnode_valid(node))
return -ENODEV;
ret = ofnode_read_string_list(node, "fastboot-key-combo", &config->key_names);
if (ret < 0)
return ret;
config->key_count = ret;
ret = ofnode_read_u32(node, "fastboot-key-press-time", &config->press_time);
if (ret < 0)
return ret;
return 0;
}
static bool check_fastboot_keys(void)
{
struct udevice *dev;
struct fastboot_key_config config;
int *key_states;
ulong press_start = 0;
int i, ret;
bool all_pressed = true;
ret = get_fastboot_key_config(&config);
if (ret < 0) {
pr_err("Failed to get fastboot key config: %d\n", ret);
return false;
}
pr_debug("Fastboot key config: count=%d, press_time=%u\n", config.key_count, config.press_time);
ret = uclass_get_device_by_name(UCLASS_BUTTON, "gpio_keys", &dev);
if (ret) {
pr_err("Failed to get device for gpio_keys\n");
return false;
}
key_states = calloc(config.key_count, sizeof(int));
if (!key_states) {
pr_err("Failed to allocate memory for key_states\n");
return false;
}
press_start = get_timer(0);
while (get_timer(press_start) < config.press_time) {
all_pressed = true;
for (i = 0; i < config.key_count; i++) {
key_states[i] = button_get_state_by_label(dev, config.key_names[i]);
if (key_states[i] < 0 || key_states[i] != BUTTON_ON) {
all_pressed = false;
break;
}
}
if (!all_pressed) {
/* Key released within the specified time, normal boot */
free(key_states);
return false;
}
mdelay(10);
}
/* Keys held down longer than specified time, enter Fastboot mode */
free(key_states);
pr_info("Fastboot key combination detected! Duration: %u ms\n", config.press_time);
return true;
}
#endif
void run_fastboot_command(void)
{
u32 boot_mode = get_boot_mode();
if (boot_mode == BOOT_MODE_USB || BOOT_MODE_USB == get_reboot_config()) {
if (boot_mode == BOOT_MODE_USB || BOOT_MODE_USB == get_reboot_config()
#ifdef CONFIG_BUTTON
|| check_fastboot_keys()
#endif
) {
/* show flash log*/
env_set("stdout", env_get("stdout_flash"));
@ -295,6 +422,7 @@ void run_fastboot_command(void)
}
}
int run_uboot_shell(void)
{
u32 boot_mode = get_boot_mode();
@ -381,6 +509,20 @@ char* parse_mtdparts_and_find_bootfs(void) {
void import_env_from_bootfs(void)
{
u32 boot_mode = get_boot_mode();
#ifdef CONFIG_ENV_IS_IN_NFS
// Check if local bootfs exists
if (check_bootfs_exists() != 0) {
#ifdef CONFIG_CMD_NET
eth_initialize();
#endif
// Local bootfs not found, try to load from NFS
if (load_env_from_nfs() == 0) {
return;
}
}
#endif
switch (boot_mode) {
case BOOT_MODE_NAND:
#if CONFIG_IS_ENABLED(ENV_IS_IN_MTD)
@ -499,6 +641,16 @@ void run_cardfirmware_flash_command(void)
void setenv_boot_mode(void)
{
#ifdef CONFIG_ENV_IS_IN_NFS
const char *boot_override = env_get("boot_override");
if (boot_override) {
env_set("boot_device", boot_override);
env_set("boot_override", NULL);
return;
}
#endif
u32 boot_mode = get_boot_mode();
switch (boot_mode) {
case BOOT_MODE_NAND:
@ -789,6 +941,13 @@ int board_init(void)
ret = regulators_enable_boot_on(true);
if (ret)
pr_debug("%s: Cannot enable boot on regulator\n", __func__);
#endif
#ifdef CONFIG_SPACEMIT_SHUTDOWN_CHARGE
struct udevice *udev;
if (get_boot_mode() != BOOT_MODE_USB) {
ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(shutdown_charge), &udev);
}
#endif
return 0;
}
@ -840,6 +999,15 @@ int board_late_init(void)
}
#endif
#ifdef CONFIG_BUTTON
ret = uclass_probe_all(UCLASS_BUTTON);
if (ret) {
pr_err("Failed to probe all buttons: %d\n", ret);
} else {
pr_info("All buttons probed successfully\n");
}
#endif
run_fastboot_command();
run_cardfirmware_flash_command();

View file

@ -0,0 +1,382 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2023 Spacemit, Inc
*/
#include <common.h>
#include <env.h>
#include <log.h>
#include <asm/global_data.h>
#include <net.h>
#include <tlv_eeprom.h>
#include <vsprintf.h>
#include <ctype.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <u-boot/crc.h>
#include <command.h>
#include <mmc.h>
#include <part.h>
#include <net.h>
#include <env_flags.h>
#include <mtd.h>
#include <jffs2/load_kernel.h>
#include <mtd.h>
#include <jffs2/load_kernel.h>
#include <vsprintf.h>
#include <ctype.h>
#include <dm.h>
#include <fb_spacemit.h>
#include "nfs_env.h"
#define NFS_LOAD_ADDR CONFIG_FASTBOOT_BUF_ADDR
int eth_parse_enetaddr(const char *addr, uint8_t *enetaddr)
{
char *end;
int i;
if (strlen(addr) != 17) {
pr_err("Invalid MAC address length\n");
return -1;
}
for (i = 0; i < 6; i++) {
enetaddr[i] = simple_strtoul(addr, &end, 16);
if (i < 5 && *end != ':') {
pr_err("Invalid MAC address format\n");
return -1;
}
addr = end + 1;
}
pr_info("Successfully parsed MAC address\n");
return 0;
}
static int get_mac_address(uint8_t *mac_addr)
{
const char *mac_str = env_get("ethaddr");
if (mac_str) {
if (eth_validate_ethaddr_str(mac_str) == 0) {
if (eth_parse_enetaddr(mac_str, mac_addr) == 0) {
pr_info("Successfully obtained MAC address from environment\n");
return 0;
} else {
pr_err("Failed to parse MAC address from environment\n");
}
} else {
pr_err("Invalid MAC address in environment\n");
}
} else {
pr_debug("MAC address not found in environment\n");
}
return -1;
}
static int read_mac_from_eeprom(uint8_t *mac_addr)
{
struct tlvinfo_tlv *mac_base_tlv = NULL;
read_from_eeprom(&mac_base_tlv, TLV_CODE_MAC_BASE);
if (mac_base_tlv && mac_base_tlv->length == 6) {
memcpy(mac_addr, mac_base_tlv->value, 6);
pr_info("Successfully read MAC address from EEPROM: %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
return 0;
}
pr_err("Failed to read valid MAC address from EEPROM\n");
return -1;
}
static int get_device_mac_address(uint8_t *mac_addr)
{
// Try to get MAC address from environment first
if (get_mac_address(mac_addr) == 0) {
return 0;
}
// If not found in environment, try to read from EEPROM
if (read_mac_from_eeprom(mac_addr) == 0) {
char mac_str[18];
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5]);
env_set("ethaddr", mac_str);
return 0;
}
pr_err("Failed to get MAC address\n");
return -1;
}
static int strcasecmp_colon(const char *s1, const char *s2, size_t n) {
for (size_t i = 0; i < n; i++) {
char c1 = tolower((unsigned char)s1[i]);
char c2 = tolower((unsigned char)s2[i]);
if (c1 != c2) {
return c1 - c2;
}
if (c1 == '\0') {
return 0;
}
if (c1 == ':') {
continue;
}
}
return 0;
}
static int load_mac_mapping(struct mac_mapping *mapping, const char *mac_mapping_file)
{
char cmd[128] = {"\0"};
char *buf = (char *)NFS_LOAD_ADDR;
char *line, *next_line;
int ret = -1;
uint8_t mac_addr[6];
char mac_str[18];
size_t mac_str_len;
const char *server_ip;
bool found_match = false;
// Run DHCP
sprintf(cmd, "dhcp");
ret = run_command(cmd, 0);
if (ret != 0) {
pr_err("DHCP failed, return value: %d\n", ret);
return -1;
}
// Get server IP address
server_ip = env_get("serverip");
if (!server_ip) {
pr_err("serverip not set in environment\n");
return -1;
}
// Get device MAC address
if (get_device_mac_address(mac_addr) != 0) {
pr_err("Failed to get device MAC address\n");
return -1;
}
// Convert MAC address to string format
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5]);
mac_str_len = strlen(mac_str);
// Construct NFS command
sprintf(cmd, "nfs %lx %s:%s", (ulong)buf, server_ip, mac_mapping_file);
// Execute NFS command
ret = run_command(cmd, 0);
if (ret != 0) {
pr_err("Failed to load %s from NFS\n", mac_mapping_file);
return -1;
}
// Parse file content
line = buf;
while (line && *line) {
next_line = strchr(line, '\n');
if (next_line) {
*next_line = '\0';
}
if (strcasecmp_colon(line, mac_str, mac_str_len) == 0) {
char *bootfs_start = strchr(line, ',');
if (bootfs_start) {
bootfs_start++;
char *rootfs_start = strchr(bootfs_start, ',');
if (rootfs_start) {
*rootfs_start = '\0';
rootfs_start++;
// Copy bootfs path
strncpy(mapping->bootfs_path, bootfs_start, sizeof(mapping->bootfs_path) - 1);
mapping->bootfs_path[sizeof(mapping->bootfs_path) - 1] = '\0';
// Copy rootfs path
strncpy(mapping->rootfs_path, rootfs_start, sizeof(mapping->rootfs_path) - 1);
mapping->rootfs_path[sizeof(mapping->rootfs_path) - 1] = '\0';
found_match = true;
ret = 0;
break;
}
}
}
if (next_line) {
line = next_line + 1;
} else {
break;
}
}
if (!found_match) {
pr_err("Failed to find matching MAC address in %s\n", mac_mapping_file);
ret = -1;
}
return ret;
}
static int check_nand_bootfs(void)
{
char cmd[128];
const char *bootfs_name = BOOTFS_NAME;
if (!bootfs_name) {
return -1;
}
snprintf(cmd, sizeof(cmd), "ubi part %s", parse_mtdparts_and_find_bootfs());
if (run_command(cmd, 0) != 0) {
return -1;
}
snprintf(cmd, sizeof(cmd), "ubifsmount %s", bootfs_name);
if (run_command(cmd, 0) != 0) {
return -1;
}
return 0;
}
static int check_nor_bootfs(void)
{
int part, blk_index;
char *blk_name;
char devpart_str[16];
if (get_available_boot_blk_dev(&blk_name, &blk_index)) {
pr_err("Cannot get available block device\n");
return -1;
}
part = detect_blk_dev_or_partition_exist(blk_name, blk_index, BOOTFS_NAME);
if (part < 0) {
pr_err("Failed to detect partition %s on %s:%d\n", BOOTFS_NAME, blk_name, blk_index);
return -1;
}
snprintf(devpart_str, sizeof(devpart_str), "%d:%d", blk_index, part);
if (!strcmp("mmc", blk_name)) {
pr_info("Found bootfs partition on eMMC device %s\n", devpart_str);
} else if (!strcmp("nvme", blk_name)) {
pr_info("Found bootfs partition on NVMe device %s\n", devpart_str);
} else {
pr_info("Not found bootfs partition on %s\n", blk_name);
return -1;
}
return 0;
}
static int check_mmc_bootfs(int dev)
{
struct mmc *mmc;
struct blk_desc *desc;
struct disk_partition info;
int part;
mmc = find_mmc_device(dev);
if (!mmc) {
return -1;
}
if (mmc_init(mmc)) {
return -1;
}
desc = mmc_get_blk_desc(mmc);
for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
if (part_get_info(desc, part, &info) != 0) {
continue;
}
if (strcmp(info.name, BOOTFS_NAME) == 0) {
return 0;
}
}
return -1;
}
int check_bootfs_exists(void)
{
int ret;
u32 boot_mode = get_boot_mode();
switch (boot_mode) {
case BOOT_MODE_NAND:
ret = check_nand_bootfs();
break;
case BOOT_MODE_NOR:
ret = check_nor_bootfs();
break;
case BOOT_MODE_EMMC:
ret = check_mmc_bootfs(MMC_DEV_EMMC);
break;
case BOOT_MODE_SD:
ret = check_mmc_bootfs(MMC_DEV_SD);
break;
default:
pr_info("Unsupported boot mode for checking bootfs\n");
return -1;
}
return ret;
}
int load_env_from_nfs(void)
{
const char *mac_mapping_file;
struct mac_mapping mapping;
char cmd[128] = {"\0"};
int ret;
if (env_get("boot_override")) {
env_set("boot_override", NULL);
}
mac_mapping_file = env_get("mac_mapping_file");
if (!mac_mapping_file) {
pr_err("MAC mapping file path not set in environment\n");
return -1;
}
ret = load_mac_mapping(&mapping, mac_mapping_file);
if (ret == 0) {
env_set("bootfs_path", mapping.bootfs_path);
env_set("rootfs_path", mapping.rootfs_path);
env_set("boot_override", "nfs");
printf("bootfs_path: %s\n", env_get("bootfs_path"));
printf("rootfs_path: %s\n", env_get("rootfs_path"));
printf("boot_override: %s\n", env_get("boot_override"));
sprintf(cmd, "nfs %x %s/env_%s.txt",
NFS_LOAD_ADDR,
mapping.bootfs_path,
CONFIG_SYS_CONFIG_NAME);
if (run_command(cmd, 0) == 0) {
sprintf(cmd, "env import -t %x", NFS_LOAD_ADDR);
if (run_command(cmd, 0) == 0) {
pr_info("Successfully loaded environment from NFS\n");
return 0;
} else {
pr_err("Failed to import environment\n");
}
} else {
pr_err("Failed to load environment file from NFS\n");
}
} else {
pr_err("Failed to load MAC mapping from NFS. Return code: %d\n", ret);
}
return -1;
}

View file

@ -0,0 +1,24 @@
#ifndef __NFS_ENV_H__
#define __NFS_ENV_H__
#ifdef CONFIG_ENV_IS_IN_NFS
#define NFS_LOAD_ADDR CONFIG_FASTBOOT_BUF_ADDR
struct mac_mapping {
char mac_addr[18];
char bootfs_path[256];
char rootfs_path[256];
};
int eth_parse_enetaddr(const char *addr, uint8_t *enetaddr);
int check_bootfs_exists(void);
int load_env_from_nfs(void);
char* parse_mtdparts_and_find_bootfs(void);
enum board_boot_mode get_boot_mode(void);
void read_from_eeprom(struct tlvinfo_tlv **tlv_data, u8 tcode);
#endif // CONFIG_ENV_IS_IN_NFS
#endif // __NFS_ENV_H__

View file

@ -80,13 +80,13 @@
extern int __data_start[], __data_end[];
extern int k1x_eeprom_init(void);
extern int spacemit_eeprom_read(uint8_t chip, uint8_t *buffer, uint8_t id);
extern int spacemit_eeprom_read(uint8_t *buffer, uint8_t id);
extern bool get_mac_address(uint64_t *mac_addr);
extern void update_ddr_info(void);
extern enum board_boot_mode get_boot_storage(void);
extern int spl_mtd_read(struct mtd_info *mtd, ulong sector, ulong count, void *buf);
char *product_name;
extern u32 ddr_cs_num;
extern u32 ddr_cs_num, ddr_datarate;;
extern const char *ddr_type;
int timer_init(void)
@ -140,7 +140,7 @@ static uint32_t adjust_cpu_freq(uint64_t cluster, uint32_t freq)
val &= ~(0x07 | BIT(13));
switch(freq) {
case 1600000:
val |= 0x07 | BIT(13); //set cpu freq to PLL3_DIV1
val |= 0x07;
break;
case 1228000:
@ -180,16 +180,13 @@ void raise_cpu_frequency(void)
val |= BIT(16) | BIT(15) | BIT(14) | BIT(13);
writel(val, (void __iomem *)(K1X_MPMU_BASE + 0x1024));
/* set the frequency of pll3 to 1.6G */
writel(0x0050cd61, (void __iomem *)(K1X_APB_SPARE_BASE + 0x124));
/* enable PLL3 */
/* enable PLL3(3200Mhz) */
val = readl((void __iomem *)(K1X_APB_SPARE_BASE + 0x12C));
val |= BIT(31);
writel(val, (void __iomem *)(K1X_APB_SPARE_BASE + 0x12C));
/* enable PLL3_DIV2 and PLL3_DIV1*/
/* enable PLL3_DIV2 */
val = readl((void __iomem *)(K1X_APB_SPARE_BASE + 0x128));
val |= BIT(1) | BIT(0);
val |= BIT(1);
writel(val, (void __iomem *)(K1X_APB_SPARE_BASE + 0x128));
cpu = cpu_get_current_dev();
@ -639,11 +636,8 @@ static void spl_load_env(void)
bool get_mac_address(uint64_t *mac_addr)
{
int eeprom_addr;
eeprom_addr = k1x_eeprom_init();
if ((eeprom_addr >= 0) && (NULL != mac_addr) && (0 == spacemit_eeprom_read(
eeprom_addr, (uint8_t*)mac_addr, TLV_CODE_MAC_BASE))) {
if ((k1x_eeprom_init() >= 0) && (NULL != mac_addr) &&
(0 == spacemit_eeprom_read((uint8_t*)mac_addr, TLV_CODE_MAC_BASE))) {
pr_info("Get mac address %llx from eeprom\n", *mac_addr);
return true;
}
@ -654,12 +648,10 @@ bool get_mac_address(uint64_t *mac_addr)
char *get_product_name(void)
{
char *name = NULL;
int eeprom_addr;
eeprom_addr = k1x_eeprom_init();
name = calloc(1, 64);
if ((eeprom_addr >= 0) && (NULL != name) && (0 == spacemit_eeprom_read(
eeprom_addr, name, TLV_CODE_PRODUCT_NAME))) {
if ((k1x_eeprom_init() >= 0) && (NULL != name) &&
(0 == spacemit_eeprom_read(name, TLV_CODE_PRODUCT_NAME))) {
pr_info("Get product name from eeprom %s\n", name);
return name;
}
@ -673,26 +665,33 @@ char *get_product_name(void)
void update_ddr_info(void)
{
int eeprom_addr;
uint8_t *info;
eeprom_addr = k1x_eeprom_init();
if (eeprom_addr < 0)
if (k1x_eeprom_init() < 0)
return;
// read ddr type from eeprom
info = malloc(32);
memset(info, 0, 32);
if (0 == spacemit_eeprom_read(eeprom_addr, info, TLV_CODE_DDR_TYPE))
if (0 == spacemit_eeprom_read(info, TLV_CODE_DDR_TYPE))
ddr_type = info;
else
free(info);
// if fail to get ddr cs number from eeprom, update it from dts node
if (0 == spacemit_eeprom_read(eeprom_addr, (uint8_t*)&ddr_cs_num, TLV_CODE_DDR_CSNUM))
if (0 == spacemit_eeprom_read((uint8_t*)&ddr_cs_num, TLV_CODE_DDR_CSNUM))
pr_info("Get ddr cs num %d from eeprom\n", ddr_cs_num);
else
ddr_cs_num = 0;
// if fail to get ddr cs number from eeprom, update it from dts node
if (0 == spacemit_eeprom_read((uint8_t*)&ddr_datarate, TLV_CODE_DDR_DATARATE)) {
// convert it from big endian to little endian
ddr_datarate = be16_to_cpu(ddr_datarate);
pr_info("Get ddr datarate %d from eeprom\n", ddr_datarate);
}
else
ddr_datarate = 0;
}
void spl_board_init(void)

View file

@ -56,26 +56,33 @@ int set_nor_splash_location(struct splash_location *locations) {
char *blk_name;
char devpart_str[16];
if (get_available_boot_blk_dev(&blk_name, &blk_index)){
printf("can not get available blk dev\n");
if (get_available_boot_blk_dev(&blk_name, &blk_index)) {
pr_err("Error: Cannot get available block device\n");
return -1;
}
part = detect_blk_dev_or_partition_exist(blk_name, blk_index, BOOTFS_NAME);
if (part < 0)
if (part < 0) {
pr_err("Error: Failed to detect partition %s on %s:%d\n", BOOTFS_NAME, blk_name, blk_index);
return -1;
}
snprintf(devpart_str, sizeof(devpart_str), "%d:%d", blk_index, part);
if (!strcmp("mmc", blk_name))
if (!strcmp("mmc", blk_name)) {
locations[0].name = "emmc_fs";
else if (!strcmp("nvme", blk_name))
locations[0].storage = SPLASH_STORAGE_MMC;
} else if (!strcmp("nvme", blk_name)) {
locations[0].name = "nvme_fs";
else
locations[0].storage = SPLASH_STORAGE_NVME;
} else {
pr_err("Error: Unsupported block device type: %s\n", blk_name);
return -1;
}
locations[0].storage = SPLASH_STORAGE_NVME;
locations[0].flags = SPLASH_STORAGE_FS;
locations[0].devpart = strdup(devpart_str);
return 0;
}

View file

@ -618,7 +618,7 @@ int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len,
flush_cache((unsigned long)*initrd_start,
ALIGN(rd_len, ARCH_DMA_MINALIGN));
}
puts("OK\n");
printf("OK\n");
}
} else {
*initrd_start = 0;

View file

@ -1339,7 +1339,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
if (fit_image_check_hash(fit, noffset, data, size,
&err_msg))
goto error;
puts("+ ");
printf("+ ");
} else if (FIT_IMAGE_ENABLE_VERIFY && verify_all &&
!strncmp(name, FIT_SIG_NODENAME,
strlen(FIT_SIG_NODENAME))) {
@ -1353,9 +1353,9 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
* fit_image_verify_required_sigs() above.
*/
if (ret)
puts("- ");
printf("- ");
else
puts("+ ");
printf("+ ");
}
}
@ -1958,12 +1958,12 @@ static int fit_image_select(const void *fit, int rd_noffset, int verify)
fit_image_print(fit, rd_noffset, " ");
if (verify) {
puts(" Verifying Hash Integrity ... ");
printf(" Verifying Hash Integrity ... ");
if (!fit_image_verify(fit, rd_noffset)) {
puts("Bad Data Hash\n");
printf("Bad Data Hash\n");
return -EACCES;
}
puts("OK\n");
printf("OK\n");
}
return 0;
@ -2085,7 +2085,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
fit_uname_config);
}
if (cfg_noffset < 0) {
puts("Could not find configuration node\n");
printf("Could not find configuration node\n");
bootstage_error(bootstage_id +
BOOTSTAGE_SUB_NO_UNIT_NAME);
return -ENOENT;
@ -2098,14 +2098,14 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
images->fit_uname_cfg = fit_base_uname_config;
if (FIT_IMAGE_ENABLE_VERIFY && images->verify) {
puts(" Verifying Hash Integrity ... ");
printf(" Verifying Hash Integrity ... ");
if (fit_config_verify(fit, cfg_noffset)) {
puts("Bad Data Hash\n");
printf("Bad Data Hash\n");
bootstage_error(bootstage_id +
BOOTSTAGE_SUB_HASH);
return -EACCES;
}
puts("OK\n");
printf("OK\n");
}
bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
@ -2131,7 +2131,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
if (!tools_build() && IS_ENABLED(CONFIG_SANDBOX)) {
if (!fit_image_check_target_arch(fit, noffset)) {
puts("Unsupported Architecture\n");
printf("Unsupported Architecture\n");
bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
return -ENOEXEC;
}
@ -2189,12 +2189,12 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
/* Decrypt data before uncompress/move */
if (IS_ENABLED(CONFIG_FIT_CIPHER) && IMAGE_ENABLE_DECRYPT) {
puts(" Decrypting Data ... ");
printf(" Decrypting Data ... ");
if (fit_image_uncipher(fit, noffset, &buf, &size)) {
puts("Error\n");
printf("Error\n");
return -EACCES;
}
puts("OK\n");
printf("OK\n");
}
/* perform any post-processing on the image data */
@ -2267,12 +2267,12 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
}
if (image_type == IH_TYPE_RAMDISK && comp != IH_COMP_NONE)
puts("WARNING: 'compression' nodes for ramdisks are deprecated,"
printf("WARNING: 'compression' nodes for ramdisks are deprecated,"
" please fix your .its file!\n");
/* verify that image data is a proper FDT blob */
if (image_type == IH_TYPE_FLATDT && fdt_check_header(loadbuf)) {
puts("Subimage data is not a FDT");
printf("Subimage data is not a FDT");
return -ENOEXEC;
}

View file

@ -943,6 +943,13 @@ config CMD_BCB
https://android.googlesource.com/platform/bootable/recovery
- Inspect/dump the contents of the BCB fields
config CMD_BATTERY
bool "battery - information about batteries"
depends on DM_BATTERY
default y
help
Provides access to information regarding batteries present on the system.
config CMD_BIND
bool "bind/unbind - Bind or unbind a device to/from a driver"
depends on DM

View file

@ -23,6 +23,7 @@ obj-$(CONFIG_CMD_BOOTDEV) += bootdev.o
obj-$(CONFIG_CMD_BOOTFLOW) += bootflow.o
obj-$(CONFIG_CMD_BOOTMETH) += bootmeth.o
obj-$(CONFIG_CMD_SOURCE) += source.o
obj-$(CONFIG_CMD_BATTERY) += battery.o
obj-$(CONFIG_CMD_BCB) += bcb.o
obj-$(CONFIG_CMD_BDI) += bdinfo.o
obj-$(CONFIG_CMD_BIND) += bind.o

119
cmd/battery.c Normal file
View file

@ -0,0 +1,119 @@
/*
* Copyright (C) 2018 Simon Shields <simon@lineageos.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <command.h>
#include <errno.h>
#include <dm.h>
#include <dm/uclass-internal.h>
#include <power/battery.h>
static struct udevice *currdev;
#define LIMIT_DEV 32
#define LIMIT_PARENT 20
static const char *bat_states[] = {
[BAT_STATE_UNUSED] = "Unknown",
[BAT_STATE_NOT_PRESENT] = "Not present",
[BAT_STATE_NEED_CHARGING] = "Need charging",
[BAT_STATE_NORMAL] = "Present",
};
static int failure(int ret)
{
printf("Error: %d (%s)\n", ret, errno_str(ret));
return CMD_RET_FAILURE;
}
static int do_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
int ret = -ENODEV;
char *name;
unsigned int uV = 0;
switch (argc) {
case 2:
name = argv[1];
ret = battery_get(name, &currdev);
if (ret) {
printf("Can't get battery: %s!\n", name);
return failure(ret);
}
case 1:
if (!currdev) {
printf("Battery device is not set!\n\n");
return CMD_RET_USAGE;
}
printf("dev: %d @ %s\n", currdev->seq_, currdev->name);
ret = battery_get_voltage(currdev, &uV);
if (ret)
printf("failed to get voltage: %d\n", ret);
printf("voltage: %u uV, charge state: %d%%\n", uV, battery_get_soc(currdev));
ret = battery_get_status(currdev);
if (ret < 0)
printf("failed to get battery status: %d\n", ret);
else
printf("battery status: %s\n", bat_states[ret]);
}
return CMD_RET_SUCCESS;
}
static int do_list(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
{
struct udevice *dev;
int ret;
printf("| %-*.*s| %-*.*s| %s @ %s\n",
LIMIT_DEV, LIMIT_DEV, "Name",
LIMIT_PARENT, LIMIT_PARENT, "Parent name",
"Parent uclass", "seq");
for (ret = uclass_first_device(UCLASS_BATTERY, &dev); dev;
ret = uclass_next_device(&dev)) {
if (ret)
continue;
printf("| %-*.*s| %-*.*s| %s @ %d\n",
LIMIT_DEV, LIMIT_DEV, dev->name,
LIMIT_PARENT, LIMIT_PARENT, dev->parent->name,
dev_get_uclass_name(dev->parent), dev->parent->seq_);
}
if (ret)
return CMD_RET_FAILURE;
return CMD_RET_SUCCESS;
}
static struct cmd_tbl subcmd[] = {
U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""),
U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""),
};
static int do_battery(struct cmd_tbl *cmdtp, int flag, int argc,
char * const argv[])
{
struct cmd_tbl *cmd;
argc--;
argv++;
cmd = find_cmd_tbl(argv[0], subcmd, ARRAY_SIZE(subcmd));
if (cmd == NULL || argc > cmd->maxargs)
return CMD_RET_USAGE;
return cmd->cmd(cmdtp, flag, argc, argv);
}
U_BOOT_CMD(battery, CONFIG_SYS_MAXARGS, 1, do_battery,
"Battery subsystem",
"list - list battery devices\n"
"dev [name] - show or [set] operating battery device\n"
);

View file

@ -23,14 +23,14 @@ static int do_echo(struct cmd_tbl *cmdtp, int flag, int argc,
for (; i < argc; ++i) {
if (space) {
putc(' ');
printf(" ");
}
puts(argv[i]);
printf("%s", argv[i]);
space = true;
}
if (newline)
putc('\n');
printf("\n");
return 0;
}

View file

@ -660,25 +660,15 @@ static void print_memory_attributes(u64 attributes)
static int do_efi_show_memmap(struct cmd_tbl *cmdtp, int flag,
int argc, char *const argv[])
{
struct efi_mem_desc *memmap = NULL, *map;
efi_uintn_t map_size = 0;
struct efi_mem_desc *memmap, *map;
efi_uintn_t map_size;
const char *type;
int i;
efi_status_t ret;
ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
if (ret == EFI_BUFFER_TOO_SMALL) {
map_size += sizeof(struct efi_mem_desc); /* for my own */
ret = efi_allocate_pool(EFI_LOADER_DATA, map_size,
(void *)&memmap);
if (ret != EFI_SUCCESS)
return CMD_RET_FAILURE;
ret = efi_get_memory_map(&map_size, memmap, NULL, NULL, NULL);
}
if (ret != EFI_SUCCESS) {
efi_free_pool(memmap);
ret = efi_get_memory_map_alloc(&map_size, &memmap);
if (ret != EFI_SUCCESS)
return CMD_RET_FAILURE;
}
printf("Type Start%.*s End%.*s Attributes\n",
EFI_PHYS_ADDR_WIDTH - 5, spc, EFI_PHYS_ADDR_WIDTH - 3, spc);

View file

@ -321,6 +321,7 @@ static void decode_tlv(struct tlvinfo_tlv *tlv)
sprintf(value, "%u", tlv->value[0]);
break;
case TLV_CODE_MAC_SIZE:
case TLV_CODE_DDR_DATARATE:
sprintf(value, "%u", (tlv->value[0] << 8) | tlv->value[1]);
break;
case TLV_CODE_VENDOR_EXT:
@ -645,6 +646,7 @@ static bool tlvinfo_add_tlv(u8 *eeprom, int tcode, char *strval)
new_tlv_len = 1;
break;
case TLV_CODE_MAC_SIZE:
case TLV_CODE_DDR_DATARATE:
value = simple_strtoul(strval, NULL, 0);
if (value >= 65536) {
printf("ERROR: MAC Size must be 65535 or less. Value supplied: %u",

View file

@ -211,7 +211,7 @@ static int print_cpuinfo(void)
static int announce_dram_init(void)
{
puts("DRAM: ");
printf("DRAM: ");
return 0;
}
@ -233,7 +233,7 @@ static int show_dram_config(void)
print_size(size, "");
board_add_ram_info(0);
putc('\n');
printf("\n");
return 0;
}

View file

@ -329,7 +329,7 @@ static int initr_flash(void)
if (!is_flash_available())
return 0;
puts("Flash: ");
printf("Flash: ");
if (board_flash_wp_on())
printf("Uninitialized - Write Protect On\n");
@ -379,7 +379,7 @@ static int initr_flash(void)
/* go init the NAND */
static int initr_nand(void)
{
puts("NAND: ");
printf("NAND: ");
nand_init();
printf("%lu MiB\n", nand_size() / 1024);
return 0;
@ -390,7 +390,7 @@ static int initr_nand(void)
/* go init the NAND */
static int initr_onenand(void)
{
puts("NAND: ");
printf("NAND: ");
onenand_init();
return 0;
}
@ -399,7 +399,7 @@ static int initr_onenand(void)
#ifdef CONFIG_MMC
static int initr_mmc(void)
{
puts("MMC: ");
printf("MMC: ");
mmc_initialize(gd->bd);
return 0;
}
@ -408,7 +408,7 @@ static int initr_mmc(void)
#ifdef CONFIG_PVBLOCK
static int initr_pvblock(void)
{
puts("PVBLOCK: ");
printf("PVBLOCK: ");
pvblock_init();
return 0;
}
@ -466,7 +466,7 @@ static int initr_malloc_bootparams(void)
{
gd->bd->bi_boot_params = (ulong)malloc(CONFIG_SYS_BOOTPARAMS_LEN);
if (!gd->bd->bi_boot_params) {
puts("WARNING: Cannot allocate space for boot parameters\n");
printf("WARNING: Cannot allocate space for boot parameters\n");
return -ENOMEM;
}
return 0;
@ -488,9 +488,9 @@ static int initr_status_led(void)
#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI)
static int initr_scsi(void)
{
puts("SCSI: ");
printf("SCSI: ");
scsi_init();
puts("\n");
printf("\n");
return 0;
}
@ -499,7 +499,7 @@ static int initr_scsi(void)
#ifdef CONFIG_CMD_NET
static int initr_net(void)
{
puts("Net: ");
printf("Net: ");
eth_initialize();
#if defined(CONFIG_RESET_PHY_R)
debug("Reset Ethernet PHY\n");
@ -520,7 +520,7 @@ static int initr_post(void)
#if defined(CONFIG_IDE) && !defined(CONFIG_BLK)
static int initr_ide(void)
{
puts("IDE: ");
printf("IDE: ");
#if defined(CONFIG_START_IDE)
if (board_start_ide())
ide_init();

View file

@ -977,23 +977,23 @@ int console_init_f(void)
void stdio_print_current_devices(void)
{
/* Print information */
puts("In: ");
printf("In: ");
if (stdio_devices[stdin] == NULL) {
puts("No input devices available!\n");
printf("No input devices available!\n");
} else {
printf ("%s\n", stdio_devices[stdin]->name);
}
puts("Out: ");
printf("Out: ");
if (stdio_devices[stdout] == NULL) {
puts("No output devices available!\n");
printf("No output devices available!\n");
} else {
printf ("%s\n", stdio_devices[stdout]->name);
}
puts("Err: ");
printf("Err: ");
if (stdio_devices[stderr] == NULL) {
puts("No error devices available!\n");
printf("No error devices available!\n");
} else {
printf ("%s\n", stdio_devices[stderr]->name);
}

View file

@ -257,7 +257,7 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
if (IS_ENABLED(CONFIG_SPL_FPGA) ||
(IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP))) {
if (fit_image_get_type(fit, node, &type))
puts("Cannot get image type.\n");
printf("Cannot get image type.\n");
else
pr_debug("%s ", genimg_get_type_name(type));
}
@ -314,7 +314,7 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
} else {
/* Embedded data */
if (fit_image_get_data(fit, node, &data, &length)) {
puts("Cannot get image data/size\n");
printf("Cannot get image data/size\n");
return -ENOENT;
}
pr_debug("Embedded data: dst=%lx, size=%lx\n", load_addr,
@ -328,7 +328,7 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
if (!fit_image_verify_with_data(fit, node, gd_fdt_blob(), src,
length))
return -EPERM;
puts("OK\n");
printf("OK\n");
}
if (CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS))
@ -338,7 +338,7 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
if (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) {
size = length;
if (gunzip(load_ptr, CONFIG_SYS_BOOTM_LEN, src, &size)) {
puts("Uncompressing error\n");
printf("Uncompressing error\n");
return -EIO;
}
length = size;
@ -613,7 +613,7 @@ static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node,
return ret;
}
puts("FPGA image loaded from FIT\n");
printf("FPGA image loaded from FIT\n");
return 0;
}
@ -690,7 +690,7 @@ static int spl_simple_fit_parse(struct spl_fit_info *ctx)
fit_get_name(ctx->fit, ctx->conf_node, NULL));
if (fit_config_verify(ctx->fit, ctx->conf_node))
return -EPERM;
puts("OK\n");
printf("OK\n");
}
/* find the node holding the images information */

View file

@ -23,6 +23,14 @@
#include <usb.h>
/*
* USB vendor and product IDs used for quirks.
*/
#define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 0x029a
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f
/*
* If overwrite_console returns 1, the stdin, stderr and stdout
* are switched to the serial port, else the settings in the
@ -41,6 +49,9 @@ int overwrite_console(void)
#define REPEAT_RATE 40 /* 40msec -> 25cps */
#define REPEAT_DELAY 10 /* 10 x REPEAT_RATE = 400msec */
/* Timeout for SETLED control transfer */
#define SETLED_TIMEOUT 500
#define NUM_LOCK 0x53
#define CAPS_LOCK 0x39
#define SCROLL_LOCK 0x47
@ -60,6 +71,7 @@ int overwrite_console(void)
/* Device name */
#define DEVNAME "usbkbd"
static unsigned int usbkbd_count;
/* Keyboard maps */
static const unsigned char usb_kbd_numkey[] = {
@ -100,12 +112,19 @@ static const u8 usb_special_keys[] = {
(USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK)
struct usb_kbd_pdata {
struct stdio_dev* sdev;
unsigned long intpipe;
int intpktsize;
int intinterval;
unsigned long last_report;
/* The period of time between two calls of usb_kbd_testc(). */
unsigned long kbd_testc_tms;
struct int_queue *intq;
uint32_t ifnum;
uint32_t repeat_delay;
uint32_t usb_in_pointer;
@ -116,12 +135,11 @@ struct usb_kbd_pdata {
uint8_t old[USB_KBD_BOOT_REPORT_SIZE];
uint8_t flags;
bool gone;
};
extern int __maybe_unused net_busy_flag;
/* The period of time between two calls of usb_kbd_testc(). */
static unsigned long kbd_testc_tms;
/* Puts character in the queue and sets up the in and out pointer. */
static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c)
@ -150,14 +168,18 @@ static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c)
*/
static void usb_kbd_setled(struct usb_device *dev)
{
struct usb_interface *iface = &dev->config.if_desc[0];
struct usb_kbd_pdata *data = dev->privptr;
struct usb_interface *iface = &dev->config.if_desc[data->ifnum];
int ret;
ALLOC_ALIGN_BUFFER(uint32_t, leds, 1, USB_DMA_MINALIGN);
*leds = data->flags & USB_KBD_LEDMASK;
usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0x200, iface->desc.bInterfaceNumber, leds, 1, 0);
0x200, iface->desc.bInterfaceNumber, leds, 1, SETLED_TIMEOUT);
if (ret < 0) {
debug("WARN: usb_kbd_setled failed: %d\n", ret);
}
}
#define CAPITAL_MASK 0x20
@ -361,15 +383,44 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev)
data->intpktsize, data->intinterval, true) >= 0)
usb_kbd_irq_worker(dev);
#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) || \
defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE)
defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE) || \
defined(CONFIG_SYS_USB_EVENT_POLL_COMPATIBLE)
#if defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP)
struct usb_interface *iface;
struct usb_kbd_pdata *data = dev->privptr;
iface = &dev->config.if_desc[0];
iface = &dev->config.if_desc[data->ifnum];
usb_get_report(dev, iface->desc.bInterfaceNumber,
1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE);
if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) {
usb_kbd_irq_worker(dev);
#elif defined(CONFIG_SYS_USB_EVENT_POLL_COMPATIBLE)
struct usb_kbd_pdata *data = dev->privptr;
struct udevice *bus = dev->controller_dev;
bool use_int_queue = !!usb_get_ops(bus)->create_int_queue;
int data_pending = 0;
/* If keyboard is gone and cannot recover, we stop polling it,
* so xhci won't spam a lots of EP reset messages.
*/
if (data->gone)
return;
if (use_int_queue) {
data_pending = !!poll_int_queue(dev, data->intq);
} else {
data_pending = usb_int_msg(dev, data->intpipe, &data->new[0],
data->intpktsize, data->intinterval, true);
if (data_pending == -EINVAL)
data->gone = true;
data_pending = data_pending >= 0;
}
if (data_pending) {
usb_kbd_irq_worker(dev);
if (use_int_queue) {
/* We've consumed all queued int packets, create new */
destroy_int_queue(dev, data->intq);
data->intq = create_int_queue(dev, data->intpipe, 1,
USB_KBD_BOOT_REPORT_SIZE, data->new,
data->intinterval);
}
#else
struct usb_kbd_pdata *data = dev->privptr;
if (poll_int_queue(dev, data->intq)) {
@ -426,9 +477,9 @@ static int usb_kbd_testc(struct stdio_dev *sdev)
usb_kbd_dev = (struct usb_device *)dev->priv;
data = usb_kbd_dev->privptr;
if (get_timer(kbd_testc_tms) >= poll_delay) {
if (get_timer(data->kbd_testc_tms) >= poll_delay) {
usb_kbd_poll_for_event(usb_kbd_dev);
kbd_testc_tms = get_timer(0);
data->kbd_testc_tms = get_timer(0);
}
return !(data->usb_in_pointer == data->usb_out_pointer);
@ -464,6 +515,11 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum)
struct usb_interface *iface;
struct usb_endpoint_descriptor *ep;
struct usb_kbd_pdata *data;
#if defined(CONFIG_SYS_USB_EVENT_POLL_COMPATIBLE)
struct udevice *bus = dev->controller_dev;
struct dm_usb_ops *ops = usb_get_ops(bus);
bool use_int_queue = !!ops->create_int_queue;
#endif
int epNum;
if (dev->descriptor.bNumConfigurations != 1)
@ -509,6 +565,8 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum)
data->new = memalign(USB_DMA_MINALIGN,
roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN));
data->ifnum = ifnum;
/* Insert private data into USB device structure */
dev->privptr = data;
@ -526,9 +584,16 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum)
usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0);
#if !defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) && \
!defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE)
!defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE) && \
!defined(CONFIG_SYS_USB_EVENT_POLL_COMPATIBLE)
debug("USB KBD: set idle interval...\n");
usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE / 4, 0);
#elif defined(CONFIG_SYS_USB_EVENT_POLL_COMPATIBLE)
debug("USB KBD: set idle interval=0...\n");
if (use_int_queue)
usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0);
else
usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE / 4, 0);
#else
debug("USB KBD: set idle interval=0...\n");
usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0);
@ -540,6 +605,12 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum)
USB_KBD_BOOT_REPORT_SIZE, data->new,
data->intinterval);
if (!data->intq) {
#elif defined(CONFIG_SYS_USB_EVENT_POLL_COMPATIBLE)
data->intq = create_int_queue(dev, data->intpipe, 1,
USB_KBD_BOOT_REPORT_SIZE, data->new,
data->intinterval);
// Only abort when we do support int queue, else we will fallback
if (!data->intq && use_int_queue) {
#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP)
if (usb_get_report(dev, iface->desc.bInterfaceNumber,
1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE) < 0) {
@ -561,39 +632,51 @@ static int probe_usb_keyboard(struct usb_device *dev)
{
char *stdinname;
struct stdio_dev usb_kbd_dev;
unsigned int ifnum;
unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES,
(unsigned int)dev->config.no_of_if);
int error;
struct usb_kbd_pdata *data;
/* Try probing the keyboard */
if (usb_kbd_probe_dev(dev, 0) != 1)
for (ifnum = 0; ifnum < max_ifnum; ifnum++) {
if (usb_kbd_probe_dev(dev, ifnum) == 1)
break;
}
if (ifnum >= max_ifnum)
return -ENOENT;
/* Register the keyboard */
debug("USB KBD: register.\n");
memset(&usb_kbd_dev, 0, sizeof(struct stdio_dev));
strcpy(usb_kbd_dev.name, DEVNAME);
if (usbkbd_count)
sprintf(usb_kbd_dev.name, DEVNAME"%d", usbkbd_count);
else
strcpy(usb_kbd_dev.name, DEVNAME);
usbkbd_count++;
usb_kbd_dev.flags = DEV_FLAGS_INPUT;
usb_kbd_dev.getc = usb_kbd_getc;
usb_kbd_dev.tstc = usb_kbd_testc;
usb_kbd_dev.priv = (void *)dev;
error = stdio_register(&usb_kbd_dev);
data = dev->privptr;
error = stdio_register_dev(&usb_kbd_dev, &data->sdev);
if (error)
return error;
stdinname = env_get("stdin");
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
if (strstr(stdinname, DEVNAME) != NULL) {
if (strstr(stdinname, usb_kbd_dev.name) != NULL) {
error = iomux_doenv(stdin, stdinname);
if (error)
return error;
}
#else
/* Check if this is the standard input device. */
if (!strcmp(stdinname, DEVNAME)) {
if (!strcmp(stdinname, usb_kbd_dev.name)) {
/* Reassign the console */
if (overwrite_console())
return 1;
error = console_assign(stdin, DEVNAME);
error = console_assign(stdin, usb_kbd_dev.name);
if (error)
return error;
}
@ -681,14 +764,14 @@ static int usb_kbd_remove(struct udevice *dev)
struct stdio_dev *sdev;
int ret;
sdev = stdio_get_by_name(DEVNAME);
data = udev->privptr;
sdev = data->sdev;
if (!sdev) {
ret = -ENXIO;
goto err;
}
data = udev->privptr;
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
if (iomux_replace_device(stdin, DEVNAME, "nulldev")) {
if (iomux_replace_device(stdin, data->sdev->name, "nulldev")) {
ret = -ENOLINK;
goto err;
}
@ -700,6 +783,7 @@ static int usb_kbd_remove(struct udevice *dev)
#ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
destroy_int_queue(udev, data->intq);
#endif
usbkbd_count--;
free(data->new);
free(data);
@ -731,6 +815,18 @@ static const struct usb_device_id kbd_id_table[] = {
.bInterfaceSubClass = USB_SUB_HID_BOOT,
.bInterfaceProtocol = USB_PROT_HID_KEYBOARD,
},
{
USB_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021),
},
{
USB_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021),
},
{
USB_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021),
},
{ } /* Terminating entry */
};

View file

@ -118,8 +118,8 @@ CONFIG_JFFS2_PART_SIZE=0x100000
CONFIG_CMD_MTDPARTS=y
CONFIG_CMD_MTDPARTS_SPREAD=y
CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES=y
CONFIG_MTDIDS_DEFAULT="nor0=spi-nor"
CONFIG_MTDPARTS_DEFAULT="spi-nor:64K@0(bootinfo),64K@64K(private),256K@128K(fsbl),64K@384K(env),192K@448K(opensbi),-@640K(uboot)"
CONFIG_MTDIDS_DEFAULT="nor0=d420c000.spi-0"
CONFIG_MTDPARTS_DEFAULT="d420c000.spi-0:64K@0(bootinfo),64K@64K(private),256K@128K(fsbl),64K@384K(env),192K@448K(opensbi),-@640K(uboot)"
CONFIG_CMD_UBI=y
CONFIG_SPACEMIT_FLASH=y
CONFIG_SPL_FASTBOOT=y
@ -129,17 +129,23 @@ CONFIG_MULTI_DTB_FIT=y
CONFIG_ENV_OVERWRITE=y
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_MMC=y
CONFIG_ENV_IS_IN_NFS=y
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_SYS_MMC_ENV_DEV=1
# CONFIG_SPL_ENV_IS_NOWHERE is not set
CONFIG_ARP_TIMEOUT=200
CONFIG_NET_RETRY_COUNT=50
CONFIG_PROT_UDP=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_IP_DEFRAG=y
CONFIG_NET_MAXDEFRAG=65535
CONFIG_KEEP_SERVERADDR=y
CONFIG_BOOTP_SERVERIP=y
CONFIG_REGMAP=y
CONFIG_DEVRES=y
# CONFIG_SCSI_AHCI is not set
CONFIG_BUTTON=y
CONFIG_BUTTON_GPIO=y
CONFIG_SPL_CLK=y
CONFIG_SPL_CLK_CCF=y
CONFIG_SPACEMIT_K1X_CCU=y
@ -176,6 +182,7 @@ CONFIG_MISC=y
CONFIG_I2C_EEPROM=y
CONFIG_SPACEMIT_K1X_EFUSE=y
CONFIG_SPL_SPACEMIT_K1X_EFUSE=y
CONFIG_SPACEMIT_SHUTDOWN_CHARGE=y
CONFIG_MMC=y
CONFIG_SUPPORT_EMMC_BOOT=y
CONFIG_MMC_HS400_ES_SUPPORT=y
@ -211,6 +218,10 @@ CONFIG_PMIC_SPM8XX=y
CONFIG_DM_REGULATOR=y
CONFIG_DM_REGULATOR_SPM8XX=y
CONFIG_DM_REGULATOR_SPACEMIT_HUB=y
CONFIG_DM_BATTERY=y
CONFIG_CW2015_BATTERY=y
CONFIG_DM_CHARGER=y
CONFIG_SGM41515_CHARGER=y
CONFIG_SPL_SPACEMIT_POWER=y
CONFIG_DM_PWM=y
CONFIG_PWM_PXA=y
@ -237,7 +248,7 @@ CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GENERIC=y
CONFIG_USB_STORAGE=y
CONFIG_USB_KEYBOARD=y
CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP=y
CONFIG_SYS_USB_EVENT_POLL_COMPATIBLE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VENDOR_NUM=0x361C
CONFIG_USB_GADGET_PRODUCT_NUM=0x1001
@ -265,9 +276,9 @@ CONFIG_JFFS2_NOR=y
CONFIG_JFFS2_USE_MTD_READ=y
CONFIG_UBIFS_SILENCE_MSG=y
CONFIG_IMAGE_SPARSE_TRANSFER_BLK_NUM=0x3000
CONFIG_PRINT_TIMESTAMP=y
# CONFIG_SPL_USE_TINY_PRINTF is not set
# CONFIG_RSA is not set
# CONFIG_SPL_SHA1 is not set
# CONFIG_SPL_SHA256 is not set
CONFIG_ZSTD=y
CONFIG_FDT_FIXUP_PARTITIONS=y

View file

@ -46,15 +46,27 @@ configure)
fi
;;
"/dev/nvme0n1"*)
BOOTINFO_FILE=bootinfo_spinor.bin
BOOTINFO=/dev/mtdblock0
FSBL=/dev/mtdblock0
FSBL_SEEK=$((128 * 1024))
ENV=/dev/mtdblock0
ENV_SEEK=$((384 * 1024))
UBOOT=/dev/mtdblock0
# 以KB为单位
UBOOT_SEEK=640
if [ ! -e "/dev/mtdblock5" ]; then
BOOTINFO_FILE=bootinfo_spinor.bin
BOOTINFO=/dev/mtdblock0
FSBL=/dev/mtdblock0
FSBL_SEEK=$((128 * 1024))
ENV=/dev/mtdblock0
ENV_SEEK=$((384 * 1024))
UBOOT=/dev/mtdblock0
# 以KB为单位
UBOOT_SEEK=640
else
BOOTINFO_FILE=bootinfo_spinor.bin
BOOTINFO=/dev/mtdblock0
FSBL=/dev/mtdblock2
FSBL_SEEK=0
ENV=/dev/mtdblock3
ENV_SEEK=0
UBOOT=/dev/mtdblock5
# 以KB为单位
UBOOT_SEEK=0
fi
;;
*)
echo "Unsupported root=$ROOT"
@ -78,11 +90,12 @@ configure)
done
# 此前已经做了所有检查
set -x
dd if=/usr/lib/u-boot/$target/$BOOTINFO_FILE of=$BOOTINFO && sync
dd if=/usr/lib/u-boot/$target/FSBL.bin of=$FSBL seek=$FSBL_SEEK bs=1 && sync
dd if=/usr/lib/u-boot/$target/env.bin of=$ENV seek=$ENV_SEEK bs=1 && sync
dd if=/usr/lib/u-boot/$target/u-boot.itb of=$UBOOT seek=$UBOOT_SEEK bs=1K && sync
set +x
;;
esac

View file

@ -35,5 +35,13 @@ config SYS_SPD_BUS_NUM
depends on DDR_SPD || SYS_I2C_LEGACY || SPL_SYS_I2C_LEGACY
default 0
config DDR_QOS
bool "DDR Quality of Service (QoS) support"
help
For memory controllers that support QoS, set different priority for
different master, that ensure all on-chip data flows can concurrently
meet latency and bandwidth requirements while sharing the finite
bandwidth of DDR memory.
source "drivers/ddr/altera/Kconfig"
source "drivers/ddr/imx/Kconfig"

View file

@ -5,6 +5,7 @@
ifdef CONFIG_SPL_BUILD
obj-y += ddr_init.o lpddr4_silicon_init.o ddr_freq.o
obj-$(CONFIG_DDR_QOS) += ddr_qos.o
else
obj-$(CONFIG_DYNAMIC_DDR_CLK_FREQ) += ddr_freq.o
endif

View file

@ -116,7 +116,7 @@ static u32 mode_register_read(u32 MR, u32 CH, u32 CS)
read_data = readl((void __iomem*)DDR_MR_DATA);
}
UI3 = readl((void __iomem*)(DDR_BASE + 0x234)) & 0xFF;
UI3 = readl((void __iomem*)(DDR_BASE + 0x370)) & 0xFF;
return UI3;
}
@ -271,6 +271,12 @@ static struct dfc_level_config freq_levels[MAX_FREQ_LV] =
{7, 3, DPLL_PLL2, DPLL_DIV1, DPLL_DIV1, 3200, 1, 3},
};
#define KHZ 1000
#define FREQ_MAX ~(0U)
static int ddr_vmin_table[] = {
0, 400000, 600000, FREQ_MAX
};
static int get_cur_freq_level(void)
{
@ -385,6 +391,25 @@ static int ddr_vftbl_cfg(void)
return 0;
}
static void set_vol_level(void)
{
int freq_lv, vmin_lv, cur_vol_lv = 0;
u32 rate;
for (freq_lv = 0; freq_lv < MAX_FREQ_LV; freq_lv++) {
rate = freq_levels[freq_lv].data_rate / DDR_CONS * KHZ;
for (vmin_lv = cur_vol_lv; vmin_lv < ARRAY_SIZE(ddr_vmin_table); vmin_lv++) {
if (rate <= ddr_vmin_table[vmin_lv]) {
freq_levels[freq_lv].vol_lv = vmin_lv;
cur_vol_lv = vmin_lv;
break;
}
}
pr_info("%d KHZ: %d; ", rate, vmin_lv);
}
pr_info("\n");
}
static int config_core(void)
{
u32 val;
@ -489,19 +514,20 @@ static int wait_freq_change_done(void)
static int ddr_freq_init(void)
{
int ret;
static bool ddr_freq_init_flag = false;
static bool ddr_freq_init_flag = false;
if(ddr_freq_init_flag == true) {
return 0;
}
#ifdef CONFIG_K1_X_BOARD_ASIC
#ifdef CONFIG_K1_X_BOARD_ASIC
set_vol_level();
ret = ddr_vftbl_cfg();
if (ret < 0) {
pr_err("%s failed!\n", __func__);
return ret;
}
#endif
#endif
ddr_freq_init_flag = true;

View file

@ -29,6 +29,9 @@
extern u32 ddr_cs_num;
extern const char *ddr_type;
extern int ddr_freq_change(u32 data_rate);
extern void qos_set_default(void);
u32 ddr_datarate;
static int test_pattern(fdt_addr_t base, fdt_size_t size)
{
@ -126,7 +129,6 @@ static int spacemit_ddr_probe(struct udevice *dev)
#ifdef CONFIG_K1_X_BOARD_FPGA
void (*ddr_init)(void);
#else
uint32_t ddr_datarate;
fdt_addr_t ddrc_base;
ddrc_base = dev_read_addr(dev);
@ -137,16 +139,16 @@ static int spacemit_ddr_probe(struct udevice *dev)
ddr_init();
#else
/* check if dram data-rate is configued in dts */
if(dev_read_u32u(dev, "datarate", &ddr_datarate)) {
/* if dram data-rate is NOT configued in eeprom or in dts, use default value */
if ((0 == ddr_datarate) && (dev_read_u32u(dev, "datarate", &ddr_datarate))) {
pr_info("ddr data rate not configed in dts, use 1200 as default!\n");
ddr_datarate = 1200;
} else {
pr_info("ddr data rate is %u configured in dts\n", ddr_datarate);
pr_info("ddr data rate is configured as %dMT/s\n", ddr_datarate);
}
/* if DDR cs number is NOT configued in eeprom or in dts, use default value */
if((0 == ddr_cs_num) && dev_read_u32u(dev, "cs-num", &ddr_cs_num)) {
if ((0 == ddr_cs_num) && dev_read_u32u(dev, "cs-num", &ddr_cs_num)) {
pr_info("ddr cs number not configed in dts!\n");
ddr_cs_num = DDR_CS_NUM;
}
@ -169,6 +171,9 @@ static int spacemit_ddr_probe(struct udevice *dev)
pr_err("dram init failed!\n");
return -EIO;
}
#ifdef CONFIG_DDR_QOS
qos_set_default();
#endif
pr_info("dram init done\n");
return 0;

View file

@ -0,0 +1,157 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2022-2024 Spacemit
*/
#include <stdio.h>
#include <common.h>
#include <dt-bindings/soc/spacemit-k1x.h>
#define DEBUG_QOS_DUMP
#define K1_DDRC_ADDR(base, offset) ((uintptr_t)(base) + (offset))
#define MC_QOS_CTRL1 K1_DDRC_ADDR(K1X_CIU_BASE, 0x118)
#define MC_QOS_CTRL2 K1_DDRC_ADDR(K1X_CIU_BASE, 0x11c)
#define MC_QOS_CTRL3 K1_DDRC_ADDR(K1X_CIU_BASE, 0x120)
#define MC_QOS_CTRL4 K1_DDRC_ADDR(K1X_CIU_BASE, 0x124)
#define CCI_QOS_CTRL K1_DDRC_ADDR(K1X_PLAT_CIU_BASE, 0x98)
#define ISP_QOS_CTRL K1_DDRC_ADDR(K1X_CIU_BASE, 0x1e0)
#define GPU_QOS_CTRL K1_DDRC_ADDR(K1X_CIU_BASE, 0x100)
#define GNSS_QOS_CTRL K1_DDRC_ADDR(K1X_CIU_BASE, 0x1c)
#define REG32(x) (*((volatile uint32_t *)((uintptr_t)(x))))
/* DDR QoS master id */
enum {
/* port0 */
DDR_MASTER_CORE = 0,
DDR_MASTER_GPU,
DDR_MASTER_GPU_H,
/* port1 */
DDR_MASTER_PDMA,
DDR_MASTER_SDH,
DDR_MASTER_USB_OTG,
DDR_MASTER_USB2,
DDR_MASTER_USB3,
DDR_MASTER_EMAC0,
DDR_MASTER_EMAC1,
/* port2 */
DDR_MASTER_VPU,
DDR_MASTER_PCIE_A,
DDR_MASTER_PCIE_B,
DDR_MASTER_PCIE_C,
/* port3 */
DDR_MASTER_V2D,
DDR_MASTER_CCIC,
DDR_MASTER_JPEG,
DDR_MASTER_CPP,
DDR_MASTER_ISP,
};
/* defined in ciu reg, bit width = 4 by default */
struct ciu_qos_conf {
const char *name;
uint32_t qos_id;
uint32_t reg;
uint32_t aw_qos;
uint32_t aw_offset;
uint32_t ar_qos;
uint32_t ar_offset;
uint32_t mask;
};
/* QoS on DDR port
* lcd hdmi qos and v2d qos are in their drvier
*/
static struct ciu_qos_conf qos_conf[] = {
/*name id reg wqos woffset rqos roffset mask */
{"CORE", DDR_MASTER_CORE, CCI_QOS_CTRL, 0, 0, 0, 4, 0xff},
{"GPU", DDR_MASTER_GPU, GPU_QOS_CTRL, 1, 8, 1, 12, 0xff},
{"GPU_H", DDR_MASTER_GPU_H, GPU_QOS_CTRL, 1, 16, 1, 20, 0xff},
{"PDMA", DDR_MASTER_PDMA, MC_QOS_CTRL1, 0, 16, 0, 20, 0xff},
{"USB3", DDR_MASTER_USB3, MC_QOS_CTRL1, 1, 8, 1, 12, 0xff},
{"SDH", DDR_MASTER_SDH, MC_QOS_CTRL2, 1, 0, 1, 4, 0xff},
{"USB_OTG", DDR_MASTER_USB_OTG, MC_QOS_CTRL2, 1, 8, 1, 12, 0xff},
{"USB2", DDR_MASTER_USB2, MC_QOS_CTRL2, 1, 16, 1, 20, 0xff},
{"EMAC0", DDR_MASTER_EMAC0, MC_QOS_CTRL3, 1, 0, 1, 0, 0xf},
{"EMAC1", DDR_MASTER_EMAC1, MC_QOS_CTRL3, 1, 0, 1, 0, 0xf},
{"PCIE_A", DDR_MASTER_PCIE_A, MC_QOS_CTRL3, 2, 8, 2, 12, 0xff},
{"PCIE_B", DDR_MASTER_PCIE_B, MC_QOS_CTRL3, 2, 16, 2, 20, 0xff},
{"PCIE_C", DDR_MASTER_PCIE_C, MC_QOS_CTRL3, 2, 24, 2, 28, 0xff},
{"VPU", DDR_MASTER_VPU, MC_QOS_CTRL4, 1, 24, 1, 28, 0xff},
{"CCIC", DDR_MASTER_CCIC, ISP_QOS_CTRL, 3, 24, 3, 28, 0xff},
{"JPEG", DDR_MASTER_JPEG, ISP_QOS_CTRL, 2, 16, 2, 20, 0xff},
{"CPP", DDR_MASTER_CPP, ISP_QOS_CTRL, 2, 8, 2, 12, 0xff},
{"ISP", DDR_MASTER_ISP, ISP_QOS_CTRL, 3, 0, 2, 4, 0xff},
};
static void qos_setup_one(struct ciu_qos_conf *qos_conf)
{
uint32_t reg, val, mask, shift, qos_val;
reg = qos_conf->reg;
mask = qos_conf->mask;
/* qos val = (aw_val<<aw_offset)|(ar_val<<(aw_offset+ar_offset)) */
shift = qos_conf->ar_offset;
qos_val = qos_conf->ar_qos << shift;
shift = qos_conf->aw_offset;
qos_val |= (qos_conf->aw_qos << shift);
val = REG32(reg);
shift = min(qos_conf->ar_offset, qos_conf->aw_offset);
val &= ~(mask << shift);
val |= qos_val;
REG32(reg) = val;
}
static void qos_setup(void)
{
int i;
REG32(MC_QOS_CTRL2) &= ~(1 << 26);
REG32(MC_QOS_CTRL2) |= (1 << 25);
REG32(MC_QOS_CTRL2) |= (1 << 24);
for (i = 0; i < ARRAY_SIZE(qos_conf); i++)
qos_setup_one(&qos_conf[i]);
}
#ifdef DEBUG_QOS_DUMP
static void qos_dump_one(struct ciu_qos_conf *qos_conf)
{
uint32_t reg, val, mask, shift;
uint32_t rqos;
uint32_t wqos;
reg = qos_conf->reg;
mask = qos_conf->mask;
shift = min(qos_conf->ar_offset, qos_conf->aw_offset);
val = REG32(reg);
val &= (mask << shift);
shift = qos_conf->aw_offset;
wqos = (val >> shift) & 0xf;
shift = qos_conf->ar_offset;
rqos = (val >> shift) & 0xf;
printf("%s: rd = %d wr = %d\n", qos_conf->name, rqos, wqos);
}
#endif
static void qos_dump(void)
{
#ifdef DEBUG_QOS_DUMP
int i;
for (i = 0; i < ARRAY_SIZE(qos_conf); i++)
qos_dump_one(&qos_conf[i]);
#endif
}
void qos_set_default(void)
{
qos_setup();
qos_dump();
}

View file

@ -22,6 +22,7 @@
#include <mapmem.h>
#include <u-boot/crc.h>
#include "ddr_freq.h"
#include <linux/delay.h>
#define BOOT_PP 0
#define PMUA_REG_BASE 0xd4282800
@ -44,7 +45,7 @@ extern u32 ddr_cs_num;
extern u32 ddr_get_mr8(void);
extern uint32_t get_manufacture_id(void);
extern uint32_t get_ddr_rev_id(void);
static uint32_t byte_mode_tag = 0;
struct addrmap_info {
u32 io_width_per_channel;
u32 density_per_channel;
@ -88,7 +89,7 @@ struct io_para_info {
};
const struct io_para_info ddr_io_para_table[] = {
{SK_HYNIX, LPDDR4X, 0x9D, R_40, R_40, R_60, 0x19, R_60, VOH_0P6, R_60, R_60, 0x55},
{SK_HYNIX, LPDDR4X, 0x9D, R_40, R_40, R_80, 0x19, R_60, VOH_0P6, R_60, R_60, 0x55},
{SK_HYNIX, LPDDR4, 0xB2, R_40, R_40, R_120, 0xA7, R_60, VOH_0P6, R_80, R_80, 0x33},
// {SK_HYNIX, LPDDR4, 0xB2, R_40, R_40, R_60, 0xA7, R_48, VOH_0P6, R_48, R_48, 0x00},
};
@ -779,6 +780,25 @@ void ddr_dfc_table_init(unsigned int DDRC_BASE, unsigned int ddr_size_mb)
REG32(DDRC_BASE + 0x70) = idx;
}
void set_byte_mode_parameter(u32 DDRC_BASE)
{
REG32(DDRC_BASE + MC_CH0_BASE + 0x0104) = 0xF0800400;
REG32(DDRC_BASE + MC_CH0_PHY_BASE + 0x03e4) = 0x19000A02;
REG32(DDRC_BASE + MC_CH0_BASE + 0x01b4) = 0x08001400;
REG32(DDRC_BASE + MC_CH0_BASE + 0x0104) = 0xA0800400;
REG32(DDRC_BASE + MC_CH0_PHY_BASE + 0x03e4) = 0x15000802;
REG32(DDRC_BASE + MC_CH0_BASE + 0x01b4) = 0x08001000;
REG32(DDRC_BASE + MC_CH0_BASE + 0x0104) = 0x50800400;
REG32(DDRC_BASE + MC_CH0_PHY_BASE + 0x03e4) = 0x0c000402;
REG32(DDRC_BASE + MC_CH0_BASE + 0x01b4) = 0x08000A00;
REG32(DDRC_BASE + MC_CH0_BASE + 0x0104) = 0x00800400;
REG32(DDRC_BASE + MC_CH0_PHY_BASE + 0x03e4) = 0x0c000402;
REG32(DDRC_BASE + MC_CH0_BASE + 0x01b4) = 0x08000A00;
}
void top_DDR_MC_init(unsigned DDRC_BASE, unsigned int fp)
{
u32 temp_data;
@ -810,7 +830,12 @@ void top_DDR_MC_init(unsigned DDRC_BASE, unsigned int fp)
REG32(DDRC_BASE + MC_CH0_BASE + 0xcc) = 0x200;
fp_timing_init(DDRC_BASE);
if(byte_mode_tag)
set_byte_mode_parameter(DDRC_BASE);
fp_sel(DDRC_BASE, fp);
REG32(DDRC_BASE + MC_CH0_BASE + 0x0180) = 0x30D400;
REG32(DDRC_BASE + MC_CH0_BASE + 0x0184) = 0x4E200;
REG32(DDRC_BASE + MC_CH0_BASE + 0x0188) = 0xC800000;
@ -857,7 +882,7 @@ void top_DDR_rx_ds_odt_vref(unsigned DPHY0_BASE,unsigned combination)
case 2:
data = REG32(DPHY0_BASE + COMMON_OFFSET + 0xc);
data &= 0xFFC0FFFF;
// d_reg3 = 0xE4;
//d_reg3 = 0xE4;
d_reg3 = (io_para_update->rx_odt << 3) | io_para_update->rx_odt;
data |= (d_reg3 << 16);
REG32(DPHY0_BASE + COMMON_OFFSET + 0xc) = data;
@ -1217,8 +1242,22 @@ void lpddr4_silicon_init(u32 ddr_base, const char *ddr_type, u32 data_rate)
top_DDR_MC_Phy_Device_Init(ddr_base, cs_num, 0);
top_training_fp_all(ddr_base, cs_num, 0, info->para);
size_mb = ddr_get_density();
mr8_value = ddr_get_mr8();
byte_mode_tag = (mr8_value >> 6);
if (0 != byte_mode_tag) {
//reset mc
REG32(0xd4282800 + 0xb0) &= ~(0x1 << 21);
udelay(100);
REG32(0xd4282800 + 0xb0) |= (0x1 << 21);
udelay(100);
top_DDR_MC_Phy_Device_Init(ddr_base, cs_num, 0);
}
adjust_mapping(ddr_base, cs_num, size_mb, mr8_value);
LogMsg(0,"ddr density: %u MB \n", size_mb);

View file

@ -119,7 +119,7 @@ static void write_raw_image(struct blk_desc *dev_desc,
return;
}
puts("Flashing Raw Image\n");
printf("Flashing Raw Image\n");
blks = fb_blk_write(dev_desc, info->start, blkcnt, buffer);
@ -186,6 +186,8 @@ void fastboot_blk_flash_write(const char *cmd, void *download_buffer,
static char __maybe_unused part_name_t[20] = "";
unsigned long __maybe_unused src_len = ~0UL;
bool gzip_image = false;
bool is_hidden_part = false;
int part_index = 0;
if (fdev == NULL){
fdev = malloc(sizeof(struct flash_dev));
@ -213,9 +215,42 @@ void fastboot_blk_flash_write(const char *cmd, void *download_buffer,
response, fdev);
return;
}
for (part_index = 0; part_index < MAX_PARTITION_NUM; part_index++){
if (fdev->parts_info[part_index].part_name != NULL
&& strcmp(cmd, fdev->parts_info[part_index].part_name) == 0){
if (fdev->parts_info[part_index].hidden)
is_hidden_part = true;
break;
}
}
if (is_hidden_part){
/*find available blk dev*/
/* do_get_part_info(&dev_desc, cmd, &info); */
char *blk_dev;
int blk_index = -1;
if (get_available_blk_dev(&blk_dev, &blk_index) == 0) {
dev_desc = blk_get_dev(blk_dev, blk_index);
if (dev_desc == NULL){
fastboot_fail("can not get available blk dev", response);
return;
}
}else{
fastboot_fail("can not get available blk dev", response);
return;
}
strlcpy((char *)&info.name, cmd, sizeof(info.name));
info.size = fdev->parts_info[part_index].part_size / dev_desc->blksz;
info.start = fdev->parts_info[part_index].part_offset / dev_desc->blksz;
info.blksz = dev_desc->blksz;
printf("!!! flash image to hidden partition !!!\n");
}
#endif
if (fastboot_blk_get_part_info(cmd, &dev_desc, &info, response) < 0)
if (!is_hidden_part && fastboot_blk_get_part_info(cmd, &dev_desc, &info, response) < 0)
return;
if (check_gzip_format((uchar *)download_buffer, src_len) >= 0) {

View file

@ -368,9 +368,9 @@ void fastboot_data_download(const void *fastboot_data,
now_dot_num = fastboot_bytes_received / BYTES_PER_DOT;
if (pre_dot_num != now_dot_num) {
putc('.');
printf(".");
if (!(now_dot_num % 74))
putc('\n');
printf("\n");
}
*response = '\0';
}
@ -411,9 +411,9 @@ void fastboot_data_upload(const void *fastboot_data,
now_dot_num = fastboot_bytes_received / BYTES_PER_DOT;
if (pre_dot_num != now_dot_num) {
putc('.');
printf(".");
if (!(now_dot_num % 74))
putc('\n');
printf("\n");
}
*response = '\0';
}
@ -430,7 +430,8 @@ void fastboot_data_complete(char *response)
{
/* Download complete. Respond with "OKAY" */
fastboot_okay(NULL, response);
pr_info("\ndownloading/uploading of %d bytes finished\n", fastboot_bytes_received);
pr_info("\n");
pr_info("downloading/uploading of %d bytes finished\n", fastboot_bytes_received);
image_size = fastboot_bytes_received;
env_set_hex("filesize", image_size);
fastboot_bytes_expected = 0;

View file

@ -194,7 +194,7 @@ static void write_raw_image(struct blk_desc *dev_desc,
return;
}
puts("Flashing Raw Image\n");
printf("Flashing Raw Image\n");
blks = fb_mmc_blk_write(dev_desc, info->start, blkcnt, buffer);
@ -359,7 +359,7 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
struct disk_partition info;
int res;
puts("Flashing zImage\n");
printf("Flashing zImage\n");
/* Get boot partition info */
res = part_get_info_by_name(dev_desc, BOOT_PARTITION_NAME, &info);
@ -441,7 +441,7 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
return -1;
}
puts("........ zImage was updated in boot partition\n");
printf("........ zImage was updated in boot partition\n");
fastboot_okay(NULL, response);
return 0;
}
@ -528,6 +528,8 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
static char __maybe_unused part_name_t[20] = "";
unsigned long __maybe_unused src_len = ~0UL;
bool gzip_image = false;
bool is_hidden_part = false;
int part_index = 0;
if (fdev == NULL){
fdev = malloc(sizeof(struct flash_dev));
@ -659,6 +661,30 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer,
}
#endif
#ifdef CONFIG_SPACEMIT_FLASH
for (part_index = 0; part_index < MAX_PARTITION_NUM; part_index++){
if (fdev->parts_info[part_index].part_name != NULL
&& strcmp(cmd, fdev->parts_info[part_index].part_name) == 0){
if (fdev->parts_info[part_index].hidden)
is_hidden_part = true;
break;
}
}
if (is_hidden_part){
/*find available blk dev*/
dev_desc = fastboot_mmc_get_dev(response);
if (!dev_desc)
return;
strlcpy((char *)&info.name, cmd, sizeof(info.name));
info.size = fdev->parts_info[part_index].part_size / dev_desc->blksz;
info.start = fdev->parts_info[part_index].part_offset / dev_desc->blksz;
info.blksz = dev_desc->blksz;
printf("!!! flash image to hidden partition !!!\n");
}
#endif
if (!info.name[0] &&
fastboot_mmc_get_part_info(cmd, &dev_desc, &info, response) < 0)
return;

View file

@ -110,12 +110,6 @@ int _clear_env_part(void *download_buffer, u32 download_bytes,
{
u32 boot_mode = get_boot_pin_select();
/* char cmdbuf[64] = {"\0"}; */
/* sprintf(cmdbuf, "env export -c -s 0x%lx 0x%lx", (ulong)CONFIG_ENV_SIZE, (ulong)download_buffer); */
/* if (run_command(cmdbuf, 0)){ */
/* return -1; */
/* } */
switch(boot_mode){
#ifdef CONFIG_ENV_IS_IN_MMC
case BOOT_MODE_EMMC:
@ -147,12 +141,6 @@ int _clear_env_part(void *download_buffer, u32 download_bytes,
ret = _fb_mtd_erase(mtd, CONFIG_ENV_SIZE);
if (ret)
return -1;
/*should not write env to env part*/
/* ret = _fb_mtd_write(mtd, download_buffer, 0, CONFIG_ENV_SIZE, NULL); */
/* if (ret){ */
/* pr_err("can not write env to mtd flash\n"); */
/* } */
}
break;
#endif
@ -208,7 +196,7 @@ int _write_mtd_partition(struct flash_dev *fdev)
* @brief transfer the string of size 'K' or 'M' to u32 type.
*
* @param reserve_size , the string of size
* @return int , return the transfer result.
* @return int , return the transfer result of KB.
*/
int transfer_string_to_ul(const char *reserve_size)
{
@ -303,6 +291,7 @@ int _parse_flash_config(struct flash_dev *fdev, void *load_flash_addr)
const char *node_file = NULL;
const char *node_offset = NULL;
const char *node_size = NULL;
fdev->parts_info[part_index].hidden = false;
cJSON *arraypart = cJSON_GetArrayItem(cj_parts, i);
cJSON *cj_name = cJSON_GetObjectItem(arraypart, "name");
@ -311,7 +300,7 @@ int _parse_flash_config(struct flash_dev *fdev, void *load_flash_addr)
else
node_part = "";
/*only blk dev would not add bootinfo partition*/
/*bootinfo should be hidden as default in gpt partition*/
if (!parse_mtd_partition){
if (strlen(node_part) > 0 && !strncmp("bootinfo", node_part, 8)){
pr_info("bootinfo would not add as partition\n");
@ -319,6 +308,15 @@ int _parse_flash_config(struct flash_dev *fdev, void *load_flash_addr)
}
}
cJSON *cj_hidden = cJSON_GetObjectItem(arraypart, "hidden");
if (cj_hidden){
if ((cj_hidden->type == cJSON_String && strcmp("true", cj_hidden->valuestring) == 0)
|| cj_hidden->type == cJSON_True){
printf("!!!! patr name:%s would set to hidden part !!!!\n", node_part);
fdev->parts_info[part_index].hidden = true;
}
}
cJSON *cj_filename = cJSON_GetObjectItem(arraypart, "image");
if (cj_filename && cj_filename->type == cJSON_String)
node_file = cj_filename->valuestring;
@ -374,19 +372,26 @@ int _parse_flash_config(struct flash_dev *fdev, void *load_flash_addr)
if (off > 0)
combine_size = off;
/*TODO: support hidden partition for mtd dev*/
if (parse_mtd_partition){
/*parse mtd partition*/
if (strlen(combine_str) == 0)
sprintf(combine_str, "%s%s@%dK(%s)", combine_str, node_size, combine_size, node_part);
else
sprintf(combine_str, "%s,%s@%dK(%s)", combine_str, node_size, combine_size, node_part);
}else if (fdev->gptinfo.fastboot_flash_gpt){
}else if (!fdev->parts_info[part_index].hidden && fdev->gptinfo.fastboot_flash_gpt){
/*parse gpt partition*/
if (strlen(node_offset) == 0)
sprintf(combine_str, "%sname=%s,size=%s;", combine_str, node_part, node_size);
else
sprintf(combine_str, "%sname=%s,start=%s,size=%s;", combine_str, node_part, node_offset, node_size);
}
/*save part offset and size to byte*/
fdev->parts_info[part_index].part_offset = combine_size * 1024;
fdev->parts_info[part_index].part_size = transfer_string_to_ul(node_size) * 1024;
/*save as the next part offset*/
combine_size += transfer_string_to_ul(node_size);
/*after finish recovery, it would free the malloc paramenter at func recovery_show_result*/
@ -742,7 +747,7 @@ int compare_blk_image_val(struct blk_desc *dev_desc, u64 compare_val, lbaint_t p
}
for (int i = 0; i < div_times; i++) {
pr_info("\ndownload and flash div %d\n", i);
pr_info("download and flash div %d\n", i);
download_bytes = byte_remain > RECOVERY_LOAD_IMG_SIZE ? RECOVERY_LOAD_IMG_SIZE : byte_remain;
blk_size = (download_bytes + (blksz - 1)) / blksz;
@ -760,7 +765,7 @@ int compare_blk_image_val(struct blk_desc *dev_desc, u64 compare_val, lbaint_t p
pr_info("get calculate value:%llx, compare calculate:%llx\n", calculate, compare_val);
time_start_flash = get_timer(time_start_flash);
pr_info("\ncompare over, use time:%lu ms\n\n", time_start_flash);
pr_info("compare over, use time:%lu ms\n", time_start_flash);
return (calculate == compare_val) ? 0 : -1;
}
@ -799,7 +804,7 @@ int compare_mtd_image_val(struct mtd_info *mtd, u64 compare_val, uint64_t image_
pr_info("get calculate value:%llx, compare calculate:%llx\n", calculate, compare_val);
time_start_flash = get_timer(time_start_flash);
pr_info("compare over, use time:%lu ms\n\n", time_start_flash);
pr_info("compare over, use time:%lu ms\n", time_start_flash);
return (calculate == compare_val) ? 0 : -1;
}
@ -813,7 +818,7 @@ int compare_mtd_image_val(struct mtd_info *mtd, u64 compare_val, uint64_t image_
* @param response
* @param fdev
*/
void fastboot_oem_flash_bootinfo(const char *cmd, void *download_buffer,
void fastboot_oem_flash_bootinfo(const char *cmd, void *download_buffer,
u32 download_bytes, char *response, struct flash_dev *fdev)
{
#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC) || CONFIG_IS_ENABLED(FASTBOOT_MULTI_FLASH_OPTION_MMC)
@ -885,6 +890,7 @@ const struct oem_config_info config_info[] = {
{ "manufacturer", TLV_CODE_MANUF_NAME, 32, NULL },
{ "sdk_version", TLV_CODE_SDK_VERSION, 3, NULL},
{ "ddr_cs_num", TLV_CODE_DDR_CSNUM, 3, NULL},
{ "ddr_datarate", TLV_CODE_DDR_DATARATE, 5, NULL},
{ "ddr_type", TLV_CODE_DDR_TYPE, 32, NULL},
{ "pmic_type", TLV_CODE_PMIC_TYPE, 3, NULL},
{ "eeprom_i2c_index", TLV_CODE_EEPROM_I2C_INDEX, 3, NULL},

View file

@ -664,4 +664,15 @@ config SPL_SPACEMIT_K1X_EFUSE
help
This enable efuse read support in SPL, on Spacemit K1x SoCs.
config SPACEMIT_SHUTDOWN_CHARGE
bool "Support charge battery in shutdown mode for k1x soc"
depends on MISC
help
This enable the charge battery in system shutdown mode, on Spacemit K1x SoCs.
config SPL_SPACEMIT_SHUTDOWN_CHARGE
bool "Support charge battery in shutdown mode for k1x soc in spl"
depends on MISC
help
This enable the charge battery in system shutdown mode, on Spacemit K1x SoCs, in spl.
endmenu

View file

@ -91,3 +91,4 @@ obj-$(CONFIG_ESM_PMIC) += esm_pmic.o
obj-$(CONFIG_SL28CPLD) += sl28cpld.o
obj-$(CONFIG_MCP4725) += mcp4725.o
obj-$(CONFIG_$(SPL_)SPACEMIT_K1X_EFUSE) += spacemit_k1x_efuse.o
obj-$(CONFIG_$(SPL_)SPACEMIT_SHUTDOWN_CHARGE) += spacemit_shutdown_charging.o

View file

@ -0,0 +1,519 @@
#include <common.h>
#include <fdt_support.h>
#include <log.h>
#include <irq.h>
#include <dm.h>
#include <dm/lists.h>
#include <power-domain.h>
#include <power/regulator.h>
#include <asm/sbi.h>
#include <power/battery.h>
#include <asm/csr.h>
#include <asm/io.h>
#include <led.h>
#include <asm-generic/gpio.h>
#include <power/charger.h>
#include <power/spacemit/spacemit_pmic.h>
#define SBI_HSM_SUSP_TOP_BIT 0x92000000
#define PLIC_PMIC_PRIO_REG 0xe0000100
#define PLIC_PMIC_THRESH_REG 0xe0201000
#define PLIC_PMIC_EN_REG 0xe0002088
#define PLIC_PMIC_PENDING_REG 0xe0001008
#define RTC_CLK_SEL_EXTERNAL_OSC 0x8
#define RTC_EN 0x4
#define RTC_TICK_TYPE_1S 0x0
#define RTC_TICK_TYPE_1MIN 0x1
#define RTC_TICK_EN 0x40
#define RTC_CRYSTAL_EN 0x1
#define RTC_OUT_32K_EN 0x2
#define RTC_TICK_IRQ 0x20
#define WAKEUP_SOURCE_POWER_KEY_EVENT 0x0
#define WAKEUP_SOURCE_POWER_KEY_INTER 0x1
#define WAKEUP_SOURCE_RTC_WAKEUP_CTRL 0x2
#define WAKEUP_SOURCE_RTC_WAKEUP_EVENT 0x3
#define WAKEUP_SOURCE_RTC_WAKEUP_IRQ 0x4
#define SYS_SHUTDOWN 0x5
#define SYS_REBOOT_FLAG 0x6
#define SYS_SHUTDOWN_BIT 0x4
#define BATTERY_RED_LIGHT_INDEX 0x0
#define BATTERY_GREEN_LIGHT_INDEX 0x1
#define DISABLE_BATTERY_LED 0x1
#define MAX_GPIO_COUNT 3
#define MAX_REGULATOR_COUNT 7
#define MAX_CHARGER_COUNT 2
#define CHARGER_LIGHT_FLASHES_CNT 10
#define VTHRESHOLD0 3000000
#define VTHRESHOLD1 3500000
#define VTHRESHOLD2 4350000
struct pt_regs {
unsigned long long sepc;
unsigned long long ra;
unsigned long long sp;
unsigned long long gp;
unsigned long long tp;
unsigned long long t0;
unsigned long long t1;
unsigned long long t2;
unsigned long long s0;
unsigned long long s1;
unsigned long long a0;
unsigned long long a1;
unsigned long long a2;
unsigned long long a3;
unsigned long long a4;
unsigned long long a5;
unsigned long long a6;
unsigned long long a7;
unsigned long long s2;
unsigned long long s3;
unsigned long long s4;
unsigned long long s5;
unsigned long long s6;
unsigned long long s7;
unsigned long long s8;
unsigned long long s9;
unsigned long long s10;
unsigned long long s11;
unsigned long long t3;
unsigned long long t4;
unsigned long long t5;
unsigned long long t6;
/* Supervisor */
unsigned long long sstatus;
unsigned long long sbadaddr;
unsigned long long scause;
};
struct shutdown_charge {
/* electricity meter */
struct udevice *ele_meter;
/* wakeup-source set
* 0: wk_event
* 1: wk_int
* 2: rtc_tick_ctrl
* 3: rtc_tick_event
* 4: rtc_tick_irq
* */
struct udevice *wkup_set[MAX_REGULATOR_COUNT];
const char **wkup_name;
/* led charging indicator */
struct gpio_desc led_indicators[MAX_GPIO_COUNT];
int gpio_cnt;
/* charget */
struct udevice *charger[MAX_CHARGER_COUNT];
const char **charger_name;
int charger_cnt;
/* power domain */
struct power_domain pm_domain;
};
struct suspend_context {
/* Saved and restored by low-level functions */
struct pt_regs regs;
/* Saved and restored by high-level functions */
unsigned long scratch;
unsigned long tvec;
unsigned long ie;
} __aligned(64);
extern int __cpu_suspend_enter(void *context);
extern int __cpu_resume_enter(void *context);
static struct suspend_context context = { 0 };
extern void flush_dcache_range(unsigned long start, unsigned long end);
static int sbi_suspend_finisher(unsigned long suspend_type,
unsigned long resume_addr,
unsigned long opaque)
{
struct sbiret ret;
flush_dcache_range((unsigned long)&context, (unsigned long)(&context) + sizeof(struct suspend_context));
ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_SUSPEND,
suspend_type, resume_addr, opaque, 0, 0, 0);
return (ret.error) ? ret.error : 0;
}
static void suspend_save_csrs(struct suspend_context *context)
{
context->scratch = csr_read(CSR_SSCRATCH);
context->tvec = csr_read(CSR_STVEC);
context->ie = csr_read(CSR_SIE);
}
static void suspend_restore_csrs(struct suspend_context *context)
{
csr_write(CSR_SSCRATCH, context->scratch);
csr_write(CSR_STVEC, context->tvec);
csr_write(CSR_SIE, context->ie);
}
int cpu_suspend(unsigned long arg,
int (*finish)(unsigned long arg,
unsigned long entry,
unsigned long context))
{
int rc = 0;
/* Finisher should be non-NULL */
if (!finish)
return -EINVAL;
/* Save additional CSRs*/
suspend_save_csrs(&context);
/* Save context on stack */
if (__cpu_suspend_enter(&context)) {
/* Call the finisher */
rc = finish(arg, (unsigned long)__cpu_resume_enter,
(ulong)&context);
/*
* Should never reach here, unless the suspend finisher
* fails. Successful cpu_suspend() should return from
* __cpu_resume_entry()
*/
if (!rc)
rc = -EOPNOTSUPP;
}
/* Restore additional CSRs */
suspend_restore_csrs(&context);
return rc;
}
static int shutdown_charge_probe(struct udevice *dev)
{
int ret, status;
unsigned int pwr_key_status = 0, reboot_flag;
unsigned long long plugin_count = 0, plugout_count = 0, plugin_and_pwr_key_flag = 0;
unsigned int uV, prio, thresh;
struct shutdown_charge *priv = dev_get_priv(dev);
ret = uclass_get_device_by_phandle(UCLASS_BATTERY, dev,
"electricity-meter", &priv->ele_meter);
if (ret) {
printf("%s:%d, get electrycity meter failed\n", __func__, __LINE__);
return ret;
}
ret = power_domain_get(dev, &priv->pm_domain);
if (ret) {
printf("get pm domain failed\n");
return ret;
}
ret = dev_read_string_list(dev, "wk-name", &priv->wkup_name);
if (ret < 0) {
printf("get wk source name failed\n");
return ret;
}
for (int i = 0; i < dev_read_string_count(dev, "wk-name"); ++i) {
ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, priv->wkup_name[i],
&priv->wkup_set[i]);
if (ret) {
printf("get wk source: %s faild\n", priv->wkup_name[i]);
return ret;
}
}
priv->charger_cnt = dev_read_string_count(dev, "charger-name");
if (priv->charger_cnt < 0) {
printf("get charger count failed\n");
return ret;
}
ret = dev_read_string_list(dev, "charger-name", &priv->charger_name);
if (ret < 0) {
printf("get charger name failed\n");
return ret;
}
for (int i = 0; i < priv->charger_cnt; ++i) {
ret = uclass_get_device_by_phandle(UCLASS_CHARGER, dev, priv->charger_name[i],
&priv->charger[i]);
if (ret) {
printf("get charger: %s faild\n", priv->charger_name[i]);
return ret;
}
}
priv->gpio_cnt = gpio_request_list_by_name(dev, "charge-light", priv->led_indicators,
MAX_GPIO_COUNT,
GPIOD_IS_OUT);
if (priv->gpio_cnt < 0) {
printf("get charge-light failed\n");
return priv->gpio_cnt;
}
/* disable the battery led */
for (int i = 0; i < priv->gpio_cnt; ++i) {
dm_gpio_set_value(&priv->led_indicators[i], DISABLE_BATTERY_LED);
}
pwr_key_status = regulator_get_value(priv->wkup_set[WAKEUP_SOURCE_POWER_KEY_EVENT]);
ret = battery_get_voltage(priv->ele_meter, &uV);
if (ret) {
printf("%s:%d, get battery volatge failed\n", __func__, __LINE__);
return ret;
}
status = 0;
for (int i = 0; i < priv->charger_cnt; ++i) {
status |= charger_get_status(priv->charger[i]);
}
/* reboot ??? */
reboot_flag = regulator_get_value(priv->wkup_set[SYS_REBOOT_FLAG]);
/* clear the reboot flag */
reboot_flag &= ~(1 << SYS_REBOOT_FLAG_BIT);
regulator_set_value_force(priv->wkup_set[SYS_REBOOT_FLAG], reboot_flag);
if ((reboot_flag & SYS_REBOOT_FLAG_BIT) && (uV >= VTHRESHOLD1)) {
goto out;
}
/* power-up system */
if ((pwr_key_status & PWRKEY_RISING_EVENT) && !status && (uV >= VTHRESHOLD1)) {
goto out;
}
/* clear the power key pending */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_POWER_KEY_EVENT],
PWRKEY_RISING_EVENT |
PWRKEY_FAILING_EVENT |
PWRKEY_LONG_PRESS_EVENT |
PWRKEY_SHORT_PRESS_EVENT);
/* enable the rtc base function */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_CTRL],
RTC_CLK_SEL_EXTERNAL_OSC |
RTC_EN |
RTC_OUT_32K_EN |
RTC_CRYSTAL_EN);
/* clear the rtc tick event */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_EVENT], 0xff);
/* set the priority */
prio = readl((void __iomem *)PLIC_PMIC_PRIO_REG);
writel(8, (void __iomem *)PLIC_PMIC_PRIO_REG);
/* set the priority */
thresh = readl((void __iomem *)PLIC_PMIC_THRESH_REG);
writel(7, (void __iomem *)PLIC_PMIC_THRESH_REG);
/* enable the IE: the interrupt number of pmic is 64 */
writel(1, (void __iomem *)PLIC_PMIC_EN_REG);
/* clear pending first */
writel(0, (void __iomem *)PLIC_PMIC_PENDING_REG);
while (1) {
ret = battery_get_voltage(priv->ele_meter, &uV);
if (ret) {
printf("%s:%d, get battery volatge failed\n", __func__, __LINE__);
return ret;
}
status = 0;
for (int i = 0; i < priv->charger_cnt; ++i) {
status |= charger_get_status(priv->charger[i]);
}
/* dp is not plugged */
if (!status) {
++plugout_count;
plugin_count = 0;
plugin_and_pwr_key_flag = 0;
/* let the system power-down */
if (plugout_count == CHARGER_LIGHT_FLASHES_CNT) {
regulator_set_value_force(priv->wkup_set[SYS_SHUTDOWN], SYS_SHUTDOWN);
}
if (uV >= VTHRESHOLD2) {
dm_gpio_set_value(&priv->led_indicators[BATTERY_RED_LIGHT_INDEX], DISABLE_BATTERY_LED);
dm_gpio_set_value(&priv->led_indicators[BATTERY_GREEN_LIGHT_INDEX], !DISABLE_BATTERY_LED);
} else {
dm_gpio_set_value(&priv->led_indicators[BATTERY_RED_LIGHT_INDEX], !!(plugout_count % 2));
dm_gpio_set_value(&priv->led_indicators[BATTERY_GREEN_LIGHT_INDEX], DISABLE_BATTERY_LED);
}
/* enable rtc tick modeule & 1s */
ret = regulator_get_value(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_CTRL]);
ret |= (RTC_TICK_EN | RTC_EN);
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_CTRL], ret);
/* enable rtc tick irq */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_IRQ], RTC_TICK_IRQ);
if (uV >= VTHRESHOLD0 && uV < VTHRESHOLD1) {
/* the screen lights up to indicate low battery level */
}
} else {
/* the dp is plugged, we are charging now, so we can let the system enter low power mode */
plugout_count = 0;
++plugin_count;
/* enable rtc tick modeule & 1s */
ret = regulator_get_value(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_CTRL]);
ret |= (RTC_TICK_EN | RTC_EN);
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_CTRL], ret);
/* enable rtc tick irq */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_IRQ], RTC_TICK_IRQ);
if (uV < VTHRESHOLD2) {
/* have the power-key event */
if (pwr_key_status & PWRKEY_FAILING_EVENT || plugin_and_pwr_key_flag == 1) {
/* bring up the system */
if (uV >= VTHRESHOLD1) {
dm_gpio_set_value(&priv->led_indicators[BATTERY_RED_LIGHT_INDEX], !DISABLE_BATTERY_LED);
dm_gpio_set_value(&priv->led_indicators[BATTERY_GREEN_LIGHT_INDEX], DISABLE_BATTERY_LED);
plugin_and_pwr_key_flag = 0;
goto out;
}
if (plugin_count < CHARGER_LIGHT_FLASHES_CNT) {
plugin_and_pwr_key_flag = 1;
dm_gpio_set_value(&priv->led_indicators[BATTERY_RED_LIGHT_INDEX], !!(plugin_count % 2));
dm_gpio_set_value(&priv->led_indicators[BATTERY_GREEN_LIGHT_INDEX], DISABLE_BATTERY_LED);
if (uV >= VTHRESHOLD0) {
/* screen displays chargin ircron and battery level */
}
} else {
plugin_and_pwr_key_flag = 0;
dm_gpio_set_value(&priv->led_indicators[BATTERY_RED_LIGHT_INDEX], !DISABLE_BATTERY_LED);
dm_gpio_set_value(&priv->led_indicators[BATTERY_GREEN_LIGHT_INDEX], DISABLE_BATTERY_LED);
}
} else {
plugin_and_pwr_key_flag = 0;
/* the led is alway on */
dm_gpio_set_value(&priv->led_indicators[BATTERY_RED_LIGHT_INDEX], !DISABLE_BATTERY_LED);
dm_gpio_set_value(&priv->led_indicators[BATTERY_GREEN_LIGHT_INDEX], DISABLE_BATTERY_LED);
if (uV >= VTHRESHOLD0) {
if (plugin_count < CHARGER_LIGHT_FLASHES_CNT) {
/* screen displays chargin ircron and battery level */
}
}
}
} else {
/* the led is alway on */
dm_gpio_set_value(&priv->led_indicators[BATTERY_RED_LIGHT_INDEX], DISABLE_BATTERY_LED);
dm_gpio_set_value(&priv->led_indicators[BATTERY_GREEN_LIGHT_INDEX], !DISABLE_BATTERY_LED);
/* bringup the system */
if (pwr_key_status & PWRKEY_FAILING_EVENT)
goto out;
}
}
/* enable the power-key */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_POWER_KEY_INTER], PWRKEY_FAILING_EVENT);
power_domain_on(&priv->pm_domain);
cpu_suspend(SBI_HSM_SUSP_TOP_BIT, sbi_suspend_finisher);
power_domain_off(&priv->pm_domain);
/* if we have the power-key event, so we reset the plugin counter */
pwr_key_status = regulator_get_value(priv->wkup_set[WAKEUP_SOURCE_POWER_KEY_EVENT]);
if (pwr_key_status & PWRKEY_FAILING_EVENT) {
plugin_count = 0;
plugin_and_pwr_key_flag = 0;
plugout_count = 0;
printf("%s:%d, pwr_key_status:%x\n", __func__, __LINE__, pwr_key_status);
}
/* clean the event pending */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_POWER_KEY_EVENT],
PWRKEY_RISING_EVENT |
PWRKEY_FAILING_EVENT |
PWRKEY_LONG_PRESS_EVENT |
PWRKEY_SHORT_PRESS_EVENT);
/* disable the irq of power-key */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_POWER_KEY_INTER], 0);
/* disable rtc tick first */
ret = regulator_get_value(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_CTRL]);
ret &= ~(RTC_TICK_EN | RTC_EN);
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_CTRL], ret);
/* clear the rtc tick event */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_EVENT], 0xff);
/* disable rtc tick irq */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_IRQ], 0);
/* clear pending */
writel(0, (void __iomem *)PLIC_PMIC_PENDING_REG);
}
out:
/* disable PLIC */
writel(0, (void __iomem *)PLIC_PMIC_PENDING_REG);
writel(thresh, (void __iomem *)PLIC_PMIC_THRESH_REG);
writel(prio, (void __iomem *)PLIC_PMIC_PRIO_REG);
writel(0, (void __iomem *)PLIC_PMIC_EN_REG);
/* disable the event of power-key & clean the event pending */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_POWER_KEY_INTER], 0);
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_POWER_KEY_EVENT],
PWRKEY_RISING_EVENT |
PWRKEY_FAILING_EVENT |
PWRKEY_LONG_PRESS_EVENT |
PWRKEY_SHORT_PRESS_EVENT);
/* disable rtc tick first */
ret = regulator_get_value(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_CTRL]);
ret &= ~(RTC_TICK_EN | RTC_EN);
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_CTRL], ret);
/* clear the rtc tick event */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_EVENT], 0xff);
/* disable rtc module */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_CTRL], 0);
/* disable rtc tick irq */
regulator_set_value_force(priv->wkup_set[WAKEUP_SOURCE_RTC_WAKEUP_IRQ], 0);
return 0;
}
static const struct udevice_id shutdown_charging_ids[] = {
{ .compatible = "k1,shutdown-charging" },
{}
};
U_BOOT_DRIVER(shutdown_charge) = {
.name = "shutdown-charge",
.of_match = shutdown_charging_ids,
.id = UCLASS_MISC,
.probe = shutdown_charge_probe,
.priv_auto = sizeof(struct shutdown_charge),
};

View file

@ -14,6 +14,7 @@
#include <asm/global_data.h>
#include <dm/device-internal.h>
#include "sf_internal.h"
#include <blk.h>
DECLARE_GLOBAL_DATA_PTR;
@ -104,9 +105,44 @@ static int spi_flash_post_bind(struct udevice *dev)
return 0;
}
#ifdef CONFIG_SPINOR_BLOCK_SUPPORT
int spacemit_spinor_post_probe(struct udevice *dev)
{
struct blk_desc *bdesc;
struct udevice *bdev;
int ret;
struct udevice *parent_dev = dev->parent;
// Create the block device interface for the SPI NOR device with the same parent as dev
ret = blk_create_devicef(parent_dev, "nor_blk", "blk", IF_TYPE_NOR,
dev_seq(dev), SPI_NOR_BLOCK_SIZE, 0, &bdev);
if (ret) {
pr_err("Cannot create block device\n");
return ret;
}
// Obtain the block device descriptor
bdesc = dev_get_uclass_plat(bdev);
if (!bdesc) {
pr_err("Failed to get block device descriptor\n");
return -ENODEV;
}
// Initialize block device descriptor
bdesc->if_type = IF_TYPE_NOR;
bdesc->removable = 0;
dev_set_priv(bdev, dev);
return 0;
}
#endif /* CONFIG_SPINOR_BLOCK_SUPPORT */
UCLASS_DRIVER(spi_flash) = {
.id = UCLASS_SPI_FLASH,
.name = "spi_flash",
.post_bind = spi_flash_post_bind,
#ifdef CONFIG_SPINOR_BLOCK_SUPPORT
.post_probe = spacemit_spinor_post_probe,
#endif /* CONFIG_SPINOR_BLOCK_SUPPORT */
.per_device_auto = sizeof(struct spi_nor),
};

View file

@ -14,8 +14,6 @@
#include <malloc.h>
#include <spi.h>
#include <spi_flash.h>
#include <blk.h>
#include <dm/device-internal.h>
#include "sf_internal.h"
@ -165,38 +163,6 @@ static int spi_flash_std_remove(struct udevice *dev)
return 0;
}
#ifdef CONFIG_SPINOR_BLOCK_SUPPORT
int spacemit_spinor_bind(struct udevice *dev)
{
struct blk_desc *bdesc;
struct udevice *bdev;
int ret;
struct udevice *parent_dev = dev->parent;
// Create the block device interface for the SPI NOR device with the same parent as dev
ret = blk_create_devicef(parent_dev, "nor_blk", "blk", IF_TYPE_NOR,
dev_seq(dev), SPI_NOR_BLOCK_SIZE, 0, &bdev);
if (ret) {
pr_err("Cannot create block device\n");
return ret;
}
// Obtain the block device descriptor
bdesc = dev_get_uclass_plat(bdev);
if (!bdesc) {
pr_err("Failed to get block device descriptor\n");
return -ENODEV;
}
// Initialize block device descriptor
bdesc->if_type = IF_TYPE_NOR;
bdesc->removable = 0;
dev_set_priv(bdev, dev);
return 0;
}
#endif /* CONFIG_SPINOR_BLOCK_SUPPORT */
static const struct dm_spi_flash_ops spi_flash_std_ops = {
.read = spi_flash_std_read,
.write = spi_flash_std_write,
@ -217,9 +183,6 @@ U_BOOT_DRIVER(jedec_spi_nor) = {
.remove = spi_flash_std_remove,
.priv_auto = sizeof(struct spi_nor),
.ops = &spi_flash_std_ops,
#ifdef CONFIG_SPINOR_BLOCK_SUPPORT
.bind = spacemit_spinor_bind,
#endif /* CONFIG_SPINOR_BLOCK_SUPPORT */
.flags = DM_FLAG_OS_PREPARE,
};

View file

@ -1125,7 +1125,7 @@ static int emac_probe(struct udevice *dev)
ret = emac_probe_resources_core(dev);
if (ret < 0) {
pr_err("emac_probe_resources_core() failed: %d", ret);
pr_err("emac_probe_resources_core() failed: %d\n", ret);
return ret;
}
@ -1145,7 +1145,7 @@ static int emac_probe(struct udevice *dev)
priv->mii = mdio_alloc();
if (!priv->mii) {
pr_err("mdio_alloc() failed");
pr_err("mdio_alloc() failed\n");
ret = -ENOMEM;
goto err_remove_resources_core;
}
@ -1156,7 +1156,7 @@ static int emac_probe(struct udevice *dev)
ret = mdio_register(priv->mii);
if (ret < 0) {
pr_err("mdio_register() failed: %d", ret);
pr_err("mdio_register() failed: %d\n", ret);
goto err_free_mdio;
}
@ -1167,14 +1167,14 @@ static int emac_probe(struct udevice *dev)
#ifdef CONFIG_GPIO /* gpio driver is not ready for fpga platform! */
ret = gpio_request(priv->phy_reset_gpio, "phy-reset-pin");
if (ret < 0) {
pr_err("gpio_request_by_name(phy reset) failed: %d", ret);
pr_err("gpio_request_by_name(phy reset) failed: %d\n", ret);
goto err_free_mdio;
}
if (priv->ldo_gpio >= 0) {
ret = gpio_request(priv->ldo_gpio, "ldo-pwr-pin");
if (ret < 0) {
pr_err("gpio_request_by_name(ldo pwr) failed: %d", ret);
pr_err("gpio_request_by_name(ldo pwr) failed: %d\n", ret);
goto err_free_gpio;
}
gpio_direction_output(priv->ldo_gpio, 1);

View file

@ -894,6 +894,14 @@ int pci_bind_bus_devices(struct udevice *bus)
PCI_SIZE_16);
pci_bus_read_config(bus, bdf, PCI_CLASS_REVISION, &class,
PCI_SIZE_32);
#if defined(CONFIG_TARGET_SPACEMIT_K1X)
if(vendor == 0x144d && device == 0xa808) {
debug("delay 2s for device 144d:a808\n");
mdelay(2000);
}
#endif
class >>= 8;
/* Find this device in the device tree */

View file

@ -29,6 +29,8 @@ DECLARE_GLOBAL_DATA_PTR;
#define PCIE_VENDORID_MASK GENMASK(15, 0)
#define PCIE_DEVICEID_SHIFT 16
#define K1X_PCIE_VENDOR_ID 0x201F
#define k1X_PCIE_DEVICE_ID 0x0001
#define PCIE_LINK_CAPABILITY 0x7c
#define PCIE_LINK_CTL_2 0xa0
@ -629,6 +631,16 @@ static int init_phy(struct pcie_dw_k1x *k1x)
return 0;
}
static int pcie_dw_init_id(struct pcie_dw_k1x *pci)
{
dw_pcie_dbi_write_enable(&pci->dw, true);
writew(K1X_PCIE_VENDOR_ID, pci->dw.dbi_base + PCI_VENDOR_ID);
writew(k1X_PCIE_DEVICE_ID, pci->dw.dbi_base + PCI_DEVICE_ID);
dw_pcie_dbi_write_enable(&pci->dw, false);
return 0;
}
/**
* pcie_dw_k1x_probe() - Probe the PCIe bus for active link
*
@ -648,8 +660,6 @@ static int pcie_dw_k1x_probe(struct udevice *dev)
int ret;
u32 reg;
printf("%s, %d\n", __FUNCTION__, __LINE__);
/* enable pcie clk */
clk_enable(&pci->clock);
reset_deassert(&pci->reset);
@ -667,7 +677,7 @@ static int pcie_dw_k1x_probe(struct udevice *dev)
ret = generic_phy_get_by_name(dev, "pcie-phy0", &phy0);
if (ret) {
dev_err(dev, "Unable to get phy0");
dev_err(dev, "Unable to get phy0\n");
} else {
generic_phy_reset(&phy0);
generic_phy_init(&phy0);
@ -676,7 +686,7 @@ static int pcie_dw_k1x_probe(struct udevice *dev)
ret = generic_phy_get_by_name(dev, "pcie-phy1", &phy1);
if (ret) {
dev_err(dev, "Unable to get phy1");
dev_err(dev, "Unable to get phy1\n");
} else {
generic_phy_reset(&phy1);
generic_phy_init(&phy1);
@ -690,6 +700,7 @@ static int pcie_dw_k1x_probe(struct udevice *dev)
k1x_pcie_host_init(pci);
pcie_dw_setup_host(&pci->dw);
pcie_dw_init_id(pci);
if (!pcie_dw_k1x_pcie_link_up(pci, LINK_SPEED_GEN_2)) {
printf("PCIE-%d: Link down\n", dev_seq(dev));

View file

@ -51,6 +51,10 @@ source "drivers/power/pmic/Kconfig"
source "drivers/power/regulator/Kconfig"
source "drivers/power/battery/Kconfig"
source "drivers/power/charger/Kconfig"
choice
prompt "Select Sunxi PMIC Variant"
depends on ARCH_SUNXI

View file

@ -5,6 +5,7 @@
obj-$(CONFIG_$(SPL_TPL_)ACPI_PMC) += acpi_pmc/
obj-y += battery/
obj-y += charger/
obj-$(CONFIG_$(SPL_TPL_)POWER_DOMAIN) += domain/
obj-y += fuel_gauge/
obj-y += mfd/

View file

@ -0,0 +1,11 @@
config DM_BATTERY
bool "Enable Driver Model for BATTERY drivers (UCLASS_BATTERY)"
depends on DM
---help---
This config enables driver model battery support.
config CW2015_BATTERY
bool "Enable Driver Model for SPACEMIT CW2015 battery"
depends on DM_BATTERY
help
This config enables driver model for cw2015 battery

View file

@ -5,3 +5,5 @@
obj-$(CONFIG_POWER_BATTERY_TRATS) += bat_trats.o
obj-$(CONFIG_POWER_BATTERY_TRATS2) += bat_trats2.o
obj-$(CONFIG_DM_BATTERY) += battery-uclass.o
obj-$(CONFIG_$(SPL_)CW2015_BATTERY) += spacemit_cw2015.o

View file

@ -0,0 +1,53 @@
/*
* Copyright (C) 2018 Simon Shields <simon@lineageos.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <dm.h>
#include <dm/uclass-internal.h>
#include <power/battery.h>
DECLARE_GLOBAL_DATA_PTR;
int battery_get(const char *devname, struct udevice **devp)
{
return uclass_get_device_by_name(UCLASS_BATTERY, devname, devp);
}
int battery_get_voltage(struct udevice *dev, unsigned int *uV)
{
const struct dm_battery_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_voltage)
return -ENOSYS;
return ops->get_voltage(dev, uV);
}
int battery_get_status(struct udevice *dev)
{
const struct dm_battery_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_status)
return -ENOSYS;
return ops->get_status(dev);
}
int battery_get_soc(struct udevice *dev)
{
const struct dm_battery_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_soc)
return -ENOSYS;
return ops->get_soc(dev);
}
UCLASS_DRIVER(battery) = {
.id = UCLASS_BATTERY,
.name = "battery",
};

View file

@ -0,0 +1,324 @@
/*
* Copyright (C) 2024 Spacemit
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <dm.h>
#include <dm/uclass-internal.h>
#include <power/battery.h>
#include <power/pmic.h>
#include <linux/delay.h>
#include <dm/lists.h>
#include <log.h>
#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_VTEMPL 0xC
#define REG_VTEMPH 0xD
#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) // ATHD = 0%
#define MASK_ATHD GENMASK(7, 3)
#define MASK_SOC GENMASK(12, 0)
#define BATTERY_CAPACITY_ERROR 40*1000
#define BATTERY_CHARGING_ZERO 1800*1000
#define UI_FULL 100
#define DECIMAL_MAX 80
#define DECIMAL_MIN 20
#define CHARGING_ON 1
#define NO_CHARGING 0
#define SIZE_BATINFO 64
static unsigned char config_info[SIZE_BATINFO] = {};
/*struct cw_battery {
struct udevice *dev;
int charger_mode;
int capacity;
int voltage;
int status;
int change;
int raw_soc;
int time_to_empty;
};*/
static int cw2015_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
{
int ret;
ret = dm_i2c_read(dev, reg, buff, len);
if(ret) {
debug("read error from device: %p register: %#x!\n", dev, reg);
return ret;
}
return 0;
}
static int cw2015_write(struct udevice *dev, uint reg, uint8_t *buff, int len)
{
int ret;
ret = dm_i2c_write(dev, reg, buff, len);
if(ret) {
debug("write error to device: %p register: %#x!\n", dev, reg);
return ret;
}
return 0;
}
static int cw_get_voltage(struct udevice *dev, unsigned int *uV)
{
int ret;
unsigned char reg_val[2];
u16 value16, value16_1, value16_2, value16_3;
ret = cw2015_read(dev, REG_VCELL, reg_val, 2);
if(ret < 0) {
return ret;
}
value16 = (reg_val[0] << 8) + reg_val[1];
ret = cw2015_read(dev, REG_VCELL, reg_val, 2);
if(ret < 0) {
return ret;
}
value16_1 = (reg_val[0] << 8) + reg_val[1];
ret = cw2015_read(dev, REG_VCELL, reg_val, 2);
if(ret < 0) {
return ret;
}
value16_2 = (reg_val[0] << 8) + reg_val[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;
}
*uV = value16_1 * 625 / 2048 * 1000;
return 0;
}
int cw_update_config_info(struct udevice *dev)
{
int ret;
unsigned char reg_val;
int i;
unsigned char reset_val;
// make sure no in sleep mode
ret = cw2015_read(dev, REG_MODE, &reg_val, 1);
if(ret < 0) {
return ret;
}
reset_val = reg_val;
if((reg_val & MODE_SLEEP_MASK) == MODE_SLEEP) {
return -1;
}
// update new battery info
for (i = 0; i < SIZE_BATINFO; i++) {
ret = cw2015_write(dev, REG_BATINFO + i, &config_info[i], 1);
if(ret < 0)
return ret;
}
reg_val = 0x00;
reg_val |= CONFIG_UPDATE_FLG; // set UPDATE_FLAG
reg_val &= 0x07; // clear ATHD
reg_val |= ATHD; // set ATHD
ret = cw2015_write(dev, REG_CONFIG, &reg_val, 1);
if(ret < 0)
return ret;
mdelay(50);
// reset
reg_val = 0x00;
reset_val &= ~(MODE_RESTART);
reg_val = reset_val | MODE_RESTART;
ret = cw2015_write(dev, REG_MODE, &reg_val, 1);
if(ret < 0)
return ret;
mdelay(10);
ret = cw2015_write(dev, REG_MODE, &reset_val, 1);
if(ret < 0)
return ret;
mdelay(100);
printf("cw2015 update config success!\n");
return 0;
}
static int cw_init(struct udevice *dev)
{
int ret;
int i;
unsigned char reg_val = MODE_NORMAL;
ret = cw2015_write(dev, REG_MODE, &reg_val, 1);
if (ret < 0)
return ret;
ret = cw2015_read(dev, REG_CONFIG, &reg_val, 1);
if(ret < 0)
return ret;
if (!(reg_val & CONFIG_UPDATE_FLG)) {
debug("update config flg is true, need update config\n");
ret = cw_update_config_info(dev);
if (ret < 0) {
printf("%s : update config fail\n", __func__);
return ret;
}
} else {
for(i = 0; i < SIZE_BATINFO; i++) {
ret = cw2015_read(dev, (REG_BATINFO + i), &reg_val, 1);
if (ret < 0)
return ret;
debug("%X\n", reg_val);
if (config_info[i] != reg_val)
break;
}
if (i != SIZE_BATINFO) {
reg_val = MODE_SLEEP;
ret = cw2015_write(dev, REG_MODE, &reg_val, 1);
if (ret < 0)
return ret;
mdelay(30);
reg_val = MODE_NORMAL;
ret = cw2015_write(dev, REG_MODE, &reg_val, 1);
if (ret < 0)
return ret;
printf("config didn't match, need update config\n");
ret = cw_update_config_info(dev);
if (ret < 0){
return ret;
}
}
}
mdelay(10);
for (i = 0; i < 30; i++) {
ret = cw2015_read(dev, REG_SOC, &reg_val, 1);
if (ret < 0)
return ret;
else if (reg_val <= 0x64)
break;
mdelay(120);
}
if (i >= 30 ){
reg_val = MODE_SLEEP;
ret = cw2015_write(dev, REG_MODE, &reg_val, 1);
printf("cw2015 input unvalid power error, cw2015 join sleep mode\n");
return -1;
}
printf("cw2015 init success!\n");
return 0;
}
static int cw_get_capacity(struct udevice *dev)
{
int ret;
unsigned char reg_val[2];
ret = cw2015_read(dev, REG_SOC, reg_val, 1);
if (ret < 0)
return ret;
return reg_val[0];
}
static int cw_get_status(struct udevice *dev)
{
int voltage;
int ret = cw_get_voltage(dev, &voltage);
if(ret)
return ret;
if(voltage <= 3400000)
ret = BAT_STATE_NEED_CHARGING;
else if(voltage > 3400000 && voltage <= 4350000)
ret = BAT_STATE_NORMAL;
else
ret = BAT_STATE_NOT_PRESENT;
return ret;
}
static struct dm_battery_ops cw2015_battery_ops = {
.get_voltage = cw_get_voltage,
.get_status = cw_get_status,
.get_soc = cw_get_capacity,
};
static int cw2015_probe(struct udevice *dev)
{
int ret, i;
int loop = 0;
const char *data;
data = dev_read_u8_array_ptr(dev, "cellwise,battery-profile", SIZE_BATINFO);
if (!data)
return -1;
for(i = 0; i < SIZE_BATINFO; i++)
config_info[i] = *(data + i);
ret = cw_init(dev);
while ((loop++ < 3) && (ret != 0)) {
mdelay(200);
ret = cw_init(dev);
}
if (ret) {
printf("%s : cw2015 init fail!\n", __func__);
return ret;
}
return 0;
}
static const struct udevice_id cw2015_ids[] = {
{ .compatible = "spacemit,cw2015", .data = 0 },
{ }
};
U_BOOT_DRIVER(cw_battery) = {
.name = "cw-bat",
.id = UCLASS_BATTERY,
.of_match = cw2015_ids,
.ops = &cw2015_battery_ops,
.probe = cw2015_probe,
//.priv_auto = sizeof(struct cw_battery),
};

View file

@ -0,0 +1,11 @@
config DM_CHARGER
bool "Enable Driver Model for charger drivers (UCLASS_CHARGER)"
depends on DM
---help---
This config enables driver model charger support.
config SGM41515_CHARGER
bool "Enable Driver Model for SPACEMIT sgm41515 charger"
depends on DM_CHARGER
help
This config enables driver model for sgm41515 charger.

View file

@ -0,0 +1,2 @@
obj-$(CONFIG_DM_CHARGER) += charger-uclass.o
obj-$(CONFIG_$(SPL_)SGM41515_CHARGER) += sgm41515.o

View file

@ -0,0 +1,54 @@
/*
* Copyright (C) 2018 Simon Shields <simon@lineageos.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <dm.h>
#include <dm/uclass-internal.h>
#include <power/charger.h>
DECLARE_GLOBAL_DATA_PTR;
int charger_get(const char *devname, struct udevice **devp)
{
return uclass_get_device_by_name(UCLASS_CHARGER, devname, devp);
}
int charger_set_current(struct udevice *dev, unsigned int microamps)
{
const struct dm_charger_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->set_current)
return -ENOSYS;
return ops->set_current(dev, microamps);
}
int charger_get_current(struct udevice *dev)
{
const struct dm_charger_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_current)
return -ENOSYS;
return ops->get_current(dev);
}
int charger_get_status(struct udevice *dev)
{
const struct dm_charger_ops *ops = dev_get_driver_ops(dev);
if (!ops || !ops->get_status)
return -ENOSYS;
return ops->get_status(dev);
}
UCLASS_DRIVER(charger) = {
.id = UCLASS_CHARGER,
.name = "charger",
};

View file

@ -0,0 +1,395 @@
/*
* Copyright (C) 2024 Spacemit
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <errno.h>
#include <dm.h>
#include <dm/uclass-internal.h>
#include <power/charger.h>
#include <power/pmic.h>
#include <linux/delay.h>
#include <dm/lists.h>
#include <log.h>
#include <asm-generic/gpio.h>
#define SGM41515_CHRG_CTRL_0 0x00
#define SGM41515_CHRG_CTRL_1 0x01
#define SGM41515_CHRG_CTRL_2 0x02
#define SGM41515_CHRG_CTRL_3 0x03
#define SGM41515_CHRG_CTRL_4 0x04
#define SGM41515_CHRG_CTRL_5 0x05
#define SGM41515_CHRG_CTRL_6 0x06
#define SGM41515_CHRG_CTRL_7 0x07
#define SGM41515_CHRG_STAT 0x08
#define SGM41515_CHRG_FAULT 0x09
#define SGM41515_CHRG_CTRL_a 0x0a
#define SGM41515_CHRG_CTRL_b 0x0b
#define SGM41515_CHRG_CTRL_c 0x0c
#define SGM41515_CHRG_CTRL_d 0x0d
#define SGM41515_INPUT_DET 0x0e
#define SGM41515_CHRG_CTRL_f 0x0f
#define SGM41515_CHRG_EN BIT(4)
#define SGM41515_HIZ_EN BIT(7)
#define SGM41515_TERM_EN BIT(7)
#define SGM41515_VAC_OVP_MASK GENMASK(7, 6)
#define SGM41515_DPDM_ONGOING BIT(7)
#define SGM41515_VBUS_GOOD BIT(7)
#define SGM41515_VREG_V_MASK GENMASK(7, 3)
#define SGM41515_VREG_V_MAX_uV 4624000
#define SGM41515_VREG_V_MIN_uV 3856000
#define SGM41515_VREG_V_DEF_uV 4208000
#define SGM41515_VREG_V_STEP_uV 32000
#define SGM41515_IINDPM_I_MASK GENMASK(4, 0)
#define SGM41515_IINDPM_I_MIN_uA 100000
#define SGM41515_IINDPM_I_MAX_uA 3200000
#define SGM41515_IINDPM_STEP_uA 100000
#define SGM41515_IINDPM_DEF_uA 2400000
#define SGM41515_ICHRG_CUR_MASK GENMASK(5, 0)
#define SGM41515_PG_STAT BIT(2)
/* WDT TIMER SET */
#define SGM41515_WDT_TIMER_MASK GENMASK(5, 4)
#define SGM41515_WDT_TIMER_DISABLE 0
#define SGM41515_WDT_TIMER_40S BIT(4)
#define SGM41515_WDT_TIMER_80S BIT(5)
#define SGM41515_WDT_TIMER_160S (BIT(4)| BIT(5))
#define SGM41515_BOOSTV (BIT(4)| BIT(5))
#define SGM41515_BOOST_LIM BIT(7)
#define SGM41515_OTG_EN BIT(5)
#define SGM41515_PRECHRG_CUR_MASK GENMASK(7, 4)
#define SGM41515_TERMCHRG_CUR_MASK GENMASK(3, 0)
#define SGM41515_PRECHRG_I_DEF_uA 120000
#define SGM41515_TERMCHRG_I_DEF_uA 120000
static const unsigned int IPRECHG_CURRENT_STABLE[] = {
5000, 10000, 15000, 20000, 30000, 40000, 50000, 60000,
80000, 100000, 120000, 140000, 160000, 180000, 200000, 240000
};
static const unsigned int ITERM_CURRENT_STABLE[] = {
5000, 10000, 15000, 20000, 30000, 40000, 50000, 60000,
80000, 100000, 120000, 140000, 160000, 180000, 200000, 240000
};
static const unsigned int BOOST_VOLT_LIMIT[] = {
4850000, 5000000, 5150000, 5300000
};
struct sgm41515_charger {
struct gpio_desc nqon;
struct gpio_desc charge_en;
u32 ichg; /* charge current */
u32 ilim; /* input current */
u32 vreg; /* regulation voltage */
u32 iterm; /* termination current */
u32 iprechg; /* precharge current */
u32 vlim; /* minimum system voltage limit */
u32 max_ichg;
u32 max_vreg;
};
static int sgm41515_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
{
int ret;
ret = dm_i2c_read(dev, reg, buff, len);
if(ret) {
debug("read error from device: %p register: %#x!\n", dev, reg);
return ret;
}
return 0;
}
static int sgm41515_write(struct udevice *dev, uint reg, uint8_t *buff, int len)
{
int ret;
ret = dm_i2c_write(dev, reg, buff, len);
if(ret) {
debug("write error to device: %p register: %#x!\n", dev, reg);
return ret;
}
return 0;
}
static int sgm41515_set_input_curr_lim(struct udevice *dev, int iindpm)
{
int ret;
unsigned char reg, reg_val;
if (iindpm < SGM41515_IINDPM_I_MIN_uA ||
iindpm > SGM41515_IINDPM_I_MAX_uA)
return -EINVAL;
reg_val = (iindpm-SGM41515_IINDPM_I_MIN_uA) / SGM41515_IINDPM_STEP_uA;
ret = sgm41515_read(dev, SGM41515_CHRG_CTRL_0, &reg, 1);
reg &= ~SGM41515_IINDPM_I_MASK;
reg_val |= reg;
ret = sgm41515_write(dev, SGM41515_CHRG_CTRL_0, &reg_val, 1);
return ret;
}
static int sgm41515_set_chrg_curr(struct udevice *dev, int uA)
{
int ret;
unsigned char reg, reg_val;
if (uA <= 40000)
reg_val = uA / 5000;
else if (uA <= 110000)
reg_val = 0x08 + (uA -40000) / 10000;
else if (uA <= 270000)
reg_val = 0x0F + (uA -110000) / 20000;
else if (uA <= 540000)
reg_val = 0x17 + (uA -270000) / 30000;
else if (uA <= 1500000)
reg_val = 0x20 + (uA -540000) / 60000;
else if (uA <= 2940000)
reg_val = 0x30 + (uA -1500000) / 120000;
else
reg_val = 0x3d;
ret = sgm41515_read(dev, SGM41515_CHRG_CTRL_2, &reg, 1);
reg &= ~SGM41515_ICHRG_CUR_MASK;
reg_val |= reg;
ret = sgm41515_write(dev, SGM41515_CHRG_CTRL_2, &reg_val, 1);
return ret;
}
static int sgm41515_set_chrg_volt(struct udevice *dev, int chrg_volt)
{
int ret;
unsigned char reg, reg_val;
struct sgm41515_charger *priv = dev_get_priv(dev);
if (chrg_volt < SGM41515_VREG_V_MIN_uV)
chrg_volt = SGM41515_VREG_V_MIN_uV;
else if (chrg_volt > priv->max_vreg)
chrg_volt = priv->max_vreg;
reg_val = (chrg_volt-SGM41515_VREG_V_MIN_uV) / SGM41515_VREG_V_STEP_uV;
reg_val = reg_val<<3;
ret = sgm41515_read(dev, SGM41515_CHRG_CTRL_4, &reg, 1);
reg &= ~SGM41515_VREG_V_MASK;
reg_val |= reg;
ret = sgm41515_write(dev, SGM41515_CHRG_CTRL_4, &reg_val, 1);
return ret;
}
static int sgm41515_set_watchdog_timer(struct udevice *dev, int time)
{
int ret;
unsigned char reg, reg_val;
if (time == 0)
reg_val = SGM41515_WDT_TIMER_DISABLE;
else if (time == 40)
reg_val = SGM41515_WDT_TIMER_40S;
else if (time == 80)
reg_val = SGM41515_WDT_TIMER_80S;
else
reg_val = SGM41515_WDT_TIMER_160S;
ret = sgm41515_read(dev, SGM41515_CHRG_CTRL_5, &reg, 1);
reg &= ~SGM41515_WDT_TIMER_MASK;
reg_val |= reg;
ret = sgm41515_write(dev, SGM41515_CHRG_CTRL_5, &reg_val, 1);
return ret;
}
static int sgm41515_set_output_volt(struct udevice *dev, int uV)
{
int ret = 0;
int i = 0;
unsigned char reg, reg_val;
while(i < 4){
if (uV == BOOST_VOLT_LIMIT[i]){
reg_val = (unsigned char)i;
break;
}
i++;
}
if (reg_val < 0)
return reg_val;
reg_val = reg_val << 4;
ret = sgm41515_read(dev, SGM41515_CHRG_CTRL_6, &reg, 1);
reg &= ~SGM41515_BOOSTV;
reg_val |= reg;
ret = sgm41515_write(dev, SGM41515_CHRG_CTRL_6, &reg_val, 1);
return ret;
}
static int sgm41515_set_term_curr(struct udevice *dev, int uA)
{
unsigned char reg, reg_val;
for(reg_val = 1; reg_val < 16 && uA >= ITERM_CURRENT_STABLE[reg_val]; reg_val++)
;
reg_val--;
sgm41515_read(dev, SGM41515_CHRG_CTRL_3, &reg, 1);
reg &= ~SGM41515_TERMCHRG_CUR_MASK;
reg_val |= reg;
return sgm41515_write(dev, SGM41515_CHRG_CTRL_3, &reg_val, 1);
}
static int sgm41515_set_prechrg_curr(struct udevice *dev, int uA)
{
unsigned char reg, reg_val;
for(reg_val = 1; reg_val < 16 && uA >= IPRECHG_CURRENT_STABLE[reg_val]; reg_val++)
;
reg_val--;
reg_val = reg_val << 4;
sgm41515_read(dev, SGM41515_CHRG_CTRL_3, &reg, 1);
reg &= ~SGM41515_PRECHRG_CUR_MASK;
reg_val |= reg;
return sgm41515_write(dev, SGM41515_CHRG_CTRL_3, &reg_val, 1);
}
static int sgm41515_hw_init(struct udevice *dev)
{
int ret, val;
struct sgm41515_charger *priv = dev_get_priv(dev);
/* set input current limit */
ret = sgm41515_set_input_curr_lim(dev, priv->ilim);
if(ret) {
printf("set input current failed\n");
return ret;
}
/* set charge current and voltage limit */
ret = sgm41515_set_chrg_curr(dev, priv->ichg);
if(ret) {
printf("set charge current failed\n");
return ret;
}
ret = sgm41515_set_chrg_volt(dev, priv->max_vreg);
if(ret) {
printf("set charge voltage failed\n");
return ret;
}
sgm41515_set_watchdog_timer(dev, 0);
sgm41515_set_output_volt(dev, 5000000);
val = dev_read_u32_default(dev, "sgm41515-prechrg-uA", SGM41515_PRECHRG_I_DEF_uA);
sgm41515_set_prechrg_curr(dev, val);
val = dev_read_u32_default(dev, "sgm41515-termchrg-uA", SGM41515_TERMCHRG_I_DEF_uA);
sgm41515_set_term_curr(dev, val);
return 0;
}
static int sgm41515_enable_charge(struct udevice *dev)
{
int ret;
unsigned char reg, reg_val;
struct sgm41515_charger *priv = dev_get_priv(dev);
ret = gpio_request_by_name(dev, "ch-en-gpios", 0, &priv->charge_en,
GPIOD_IS_OUT);
if (ret) {
printf("%s: Warning: cannot get enable GPIO: ret=%d\n",
__func__, ret);
return ret;
}
/* enable charge */
dm_gpio_set_value(&priv->charge_en, 0);
ret = gpio_request_by_name(dev, "nqon-gpios", 0, &priv->nqon,
GPIOD_IS_OUT);
if (ret) {
printf("%s: Warning: cannot get enable GPIO: ret=%d\n",
__func__, ret);
return ret;
}
/* enable charge */
dm_gpio_set_value(&priv->nqon, 1);
reg_val = SGM41515_CHRG_EN;
ret = sgm41515_read(dev, SGM41515_CHRG_CTRL_1, &reg, 1);
reg &= ~SGM41515_CHRG_EN;
reg_val |= reg;
ret = sgm41515_write(dev, SGM41515_CHRG_CTRL_1, &reg_val, 1);
if(ret)
return ret;
return 0;
}
static int sgm41515_get_status(struct udevice *dev)
{
unsigned char reg;
int ret;
bool online;
struct sgm41515_charger *priv = dev_get_priv(dev);
ret = sgm41515_read(dev, SGM41515_CHRG_STAT, &reg, 1);
if(ret) {
printf("failed to get charger status\n");
return ret;
}
online = !!(reg & SGM41515_PG_STAT);
if(online) {
printf("vbus is attached\n");
ret = sgm41515_set_input_curr_lim(dev, priv->ilim);
if(ret) {
printf("set input current failed\n");
return ret;
}
return 1;
} else {
printf("vbus is not attached\n");
return 0;
}
return 0;
}
static int sgm41515_probe(struct udevice *dev)
{
int ret;
int input_current, ichrg_limit, vchrg_limit;
struct sgm41515_charger *priv = dev_get_priv(dev);
input_current = dev_read_u32_default(dev, "sgm41515-cur-input-uA", 2000000);
ichrg_limit = dev_read_u32_default(dev, "sgm41515-ichrg-uA", 2000000);
vchrg_limit = dev_read_u32_default(dev, "sgm41515-vchrg-uV", 4350000);
priv->max_vreg = vchrg_limit;
priv->ichg = ichrg_limit;
priv->ilim = input_current;
ret = sgm41515_hw_init(dev);
if(ret)
return ret;
/* enable charger */
sgm41515_enable_charge(dev);
printf("sgm41515 charger register successfully!\n");
return 0;
}
static const struct udevice_id sgm41515_ids[] = {
{ .compatible = "spacemit,sgm41515", .data = 0 },
{ }
};
static struct dm_charger_ops sgm41515_chg_ops = {
.get_status = sgm41515_get_status,
};
U_BOOT_DRIVER(sgm41515_charger) = {
.name = "sgm41515-charger",
.id = UCLASS_CHARGER,
.of_match = sgm41515_ids,
.ops = &sgm41515_chg_ops,
.probe = sgm41515_probe,
.priv_auto = sizeof(struct sgm41515_charger),
};

View file

@ -12,6 +12,20 @@
#define APMU_REGMAP_INDEX 1
#define APMU_POWER_STATUS_REG 0xf0
#define MPMU_APCR_PER_REG 0x1098
#define MPMU_AWUCRM_REG 0x104c
#define PM_QOS_AXISDD_OFFSET 31
#define PM_QOS_DDRCORSD_OFFSET 27
#define PM_QOS_APBSD_OFFSET 26
#define PM_QOS_VCTCXOSD_OFFSET 19
#define PM_QOS_STBYEN_OFFSET 13
#define PM_QOS_PE_VOTE_AP_SLPEN_OFFSET 3
/* pmic */
#define WAKEUP_SOURCE_WAKEUP_7 7
static unsigned int g_acpr_per;
enum pm_domain_id {
K1X_PMU_VPU_PWR_DOMAIN,
@ -21,6 +35,7 @@ enum pm_domain_id {
K1X_PMU_AUD_PWR_DOMAIN,
K1X_PMU_GNSS_PWR_DOMAIN,
K1X_PMU_HDMI_PWR_DOMAIN,
K1X_PMU_WKUP_EVENT_PWR_DOMAIN,
};
struct pm_domain_desc {
@ -131,6 +146,10 @@ static struct pm_domain_desc k1x_pm_domain_desc[] = {
.use_hw = 1,
.pm_index = K1X_PMU_HDMI_PWR_DOMAIN,
},
[K1X_PMU_WKUP_EVENT_PWR_DOMAIN] = {
.pm_index = K1X_PMU_WKUP_EVENT_PWR_DOMAIN,
},
};
static const struct udevice_id spacemit_power_domain_of_match[] = {
@ -159,6 +178,17 @@ static int k1x_pd_power_off(struct spacemit_k1x_pd_platdata *skp, struct pm_doma
{
unsigned int val;
int loop;
unsigned int apcr_per;
if (desc->pm_index == K1X_PMU_WKUP_EVENT_PWR_DOMAIN) {
regmap_write(skp->regmap[MPMU_REGMAP_INDEX], MPMU_APCR_PER_REG, g_acpr_per);
/* disable pmic wakeup */
regmap_read(skp->regmap[MPMU_REGMAP_INDEX], MPMU_AWUCRM_REG, &apcr_per);
apcr_per &= ~(1 << WAKEUP_SOURCE_WAKEUP_7);
regmap_write(skp->regmap[MPMU_REGMAP_INDEX], MPMU_AWUCRM_REG, apcr_per);
return 0;
}
if (!desc->use_hw) {
/* this is the sw type */
@ -210,6 +240,29 @@ static int k1x_pd_power_on(struct spacemit_k1x_pd_platdata *skp, struct pm_domai
{
int loop;
unsigned int val;
unsigned int apcr_per;
unsigned int apcr_clear = 0, apcr_set = (1 << PM_QOS_PE_VOTE_AP_SLPEN_OFFSET);
if (desc->pm_index == K1X_PMU_WKUP_EVENT_PWR_DOMAIN) {
/* vote the per, and enable some wakeup source */
apcr_set |= (1 << PM_QOS_AXISDD_OFFSET);
apcr_set |= (1 << PM_QOS_DDRCORSD_OFFSET);
apcr_set |= (1 << PM_QOS_APBSD_OFFSET);
apcr_set |= (1 << PM_QOS_VCTCXOSD_OFFSET);
apcr_set |= (1 << PM_QOS_STBYEN_OFFSET);
regmap_read(skp->regmap[MPMU_REGMAP_INDEX], MPMU_APCR_PER_REG, &apcr_per);
g_acpr_per = apcr_per;
apcr_per &= ~(apcr_clear);
apcr_per |= apcr_set;
regmap_write(skp->regmap[MPMU_REGMAP_INDEX], MPMU_APCR_PER_REG, apcr_per);
/* enable pmic wakeup */
regmap_read(skp->regmap[MPMU_REGMAP_INDEX], MPMU_AWUCRM_REG, &apcr_per);
apcr_per |= (1 << WAKEUP_SOURCE_WAKEUP_7);
regmap_write(skp->regmap[MPMU_REGMAP_INDEX], MPMU_AWUCRM_REG, apcr_per);
return 0;
}
regmap_read(skp->regmap[APMU_REGMAP_INDEX], APMU_POWER_STATUS_REG, &val);
if (val & (1 << desc->bit_pwr_stat))

View file

@ -330,12 +330,12 @@ static void regulator_show(struct udevice *dev, int ret)
uc_pdata = dev_get_uclass_plat(dev);
pr_info("%s@%s: ", dev->name, uc_pdata->name);
pr_info("%s@%s:", dev->name, uc_pdata->name);
if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UV)
pr_info("set %d uV", uc_pdata->min_uV);
pr_info(" set %d uV;", uc_pdata->min_uV);
if (uc_pdata->flags & REGULATOR_FLAG_AUTOSET_UA)
pr_info("; set %d uA", uc_pdata->min_uA);
pr_info("; enabling");
pr_info(" set %d uA;", uc_pdata->min_uA);
pr_info(" enabling");
if (ret)
pr_info(" (ret: %d)", ret);
pr_info("\n");

View file

@ -248,49 +248,43 @@ static int buck_set_value(struct udevice *dev, int uvolt)
static int buck_set_suspend_value(struct udevice *dev, int uvolt)
{
/* the hardware has already support the function */
/**
* int sel, ret = -EINVAL;
* int buck = dev->driver_data - 1;
* const struct pm8xx_buck_desc *info = get_buck_reg(dev->parent, buck);
*
* if (info == NULL)
* return -ENOSYS;
*
* sel = regulator_map_voltage_linear_range(info, uvolt, uvolt);
* if (sel >=0) {
* // has get the selctor
* sel <<= ffs(info->vsel_sleep_msk) - 1;
* ret = pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, info->vsel_sleep_msk, sel);
* }
*
* return ret;
*/
return 0;
int sel, ret = -EINVAL;
int buck = dev->driver_data - 1;
const struct pm8xx_buck_desc *info = get_buck_reg(dev->parent, buck);
if (info == NULL)
return -ENOSYS;
sel = regulator_map_voltage_linear_range(info, uvolt, uvolt);
if (sel >=0) {
// has get the selctor
sel <<= ffs(info->vsel_sleep_msk) - 1;
ret = pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, info->vsel_sleep_msk, sel);
}
return 1;
}
static int buck_get_suspend_value(struct udevice *dev)
{
/* the hardware has already support the function */
/**
* int buck = dev->driver_data - 1;
* const struct pm8xx_buck_desc *info = get_buck_reg(dev->parent, buck);
* int mask = info->vsel_sleep_msk;
* int ret;
* unsigned int val;
*
* if (info == NULL)
* return -ENOSYS;
*
* ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
* if (ret < 0)
* return ret;
* val = ret & mask;
*
* val >>= ffs(mask) - 1;
*
* return regulator_desc_list_voltage_linear_range(info, val);
*/
return 0;
int buck = dev->driver_data - 1;
const struct pm8xx_buck_desc *info = get_buck_reg(dev->parent, buck);
int mask = info->vsel_sleep_msk;
int ret;
unsigned int val;
if (info == NULL)
return -ENOSYS;
ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
if (ret < 0)
return ret;
val = ret & mask;
val >>= ffs(mask) - 1;
return regulator_desc_list_voltage_linear_range(info, val);
}
static int buck_get_enable(struct udevice *dev)
@ -437,48 +431,42 @@ static int ldo_set_value(struct udevice *dev, int uvolt)
static int ldo_set_suspend_value(struct udevice *dev, int uvolt)
{
/**
* int sel, ret = -EINVAL;
* int buck = dev->driver_data - 1;
* const struct pm8xx_buck_desc *info = get_ldo_reg(dev->parent, buck);
*
* if (info == NULL)
* return -ENOSYS;
*
* sel = regulator_map_voltage_linear_range(info, uvolt, uvolt);
* if (sel >=0) {
*
* sel <<= ffs(info->vsel_sleep_msk) - 1;
* ret = pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, info->vsel_sleep_msk, sel);
* }
*
* return ret;
*/
return 0;
int sel, ret = -EINVAL;
int buck = dev->driver_data - 1;
const struct pm8xx_buck_desc *info = get_ldo_reg(dev->parent, buck);
if (info == NULL)
return -ENOSYS;
sel = regulator_map_voltage_linear_range(info, uvolt, uvolt);
if (sel >=0) {
sel <<= ffs(info->vsel_sleep_msk) - 1;
ret = pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, info->vsel_sleep_msk, sel);
}
return 1;
}
static int ldo_get_suspend_value(struct udevice *dev)
{
/**
* int buck = dev->driver_data - 1;
* const struct pm8xx_buck_desc *info = get_ldo_reg(dev->parent, buck);
* int mask = info->vsel_sleep_msk;
* int ret;
* unsigned int val;
*
* if (info == NULL)
* return -ENOSYS;
*
* ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
* if (ret < 0)
* return ret;
* val = ret & mask;
*
* val >>= ffs(mask) - 1;
*
* return regulator_desc_list_voltage_linear_range(info, val);
*/
return 0;
int buck = dev->driver_data - 1;
const struct pm8xx_buck_desc *info = get_ldo_reg(dev->parent, buck);
int mask = info->vsel_sleep_msk;
int ret;
unsigned int val;
if (info == NULL)
return -ENOSYS;
ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg);
if (ret < 0)
return ret;
val = ret & mask;
val >>= ffs(mask) - 1;
return regulator_desc_list_voltage_linear_range(info, val);
}
static int ldo_get_enable(struct udevice *dev)
@ -585,11 +573,51 @@ static const struct pm8xx_buck_desc *get_switch_reg(struct udevice *pmic, int nu
static int switch_get_value(struct udevice *dev)
{
return 0;
int ret;
unsigned int val;
int buck = dev->driver_data - 1;
const struct pm8xx_buck_desc *info = get_switch_reg(dev->parent, buck);
int mask = info->enable_msk;
if (info == NULL)
return -ENOSYS;
ret = pmic_reg_read(dev->parent, info->enable_reg);
if (ret < 0)
return ret;
val = ret & mask;
val >>= ffs(mask) - 1;
return val;
}
static int switch_set_value(struct udevice *dev, int uvolt)
{
int ret;
unsigned int val = 0;
int buck = dev->driver_data - 1;
const struct pm8xx_buck_desc *info = get_switch_reg(dev->parent, buck);
int mask = info->enable_msk;
ret = pmic_reg_read(dev->parent, info->enable_reg);
if (ret < 0)
return ret;
val = (unsigned int)ret;
val &= mask;
val >>= ffs(mask) - 1;
if (uvolt == val)
return 0;
val = uvolt << (ffs(mask) - 1);
ret = pmic_clrsetbits(dev->parent, info->enable_reg, info->enable_msk, val);
if (ret < 0)
return ret;
return 0;
}

View file

@ -96,7 +96,6 @@ static int pxa_pwm_set_enable(struct udevice *dev, uint channel, bool enable)
struct pxa_pwm_priv *priv = dev_get_priv(dev);
if (enable) {
printf("!!!!!!!!!!!!!!!!!!\n");
return clk_enable(&priv->clk);
}
else
@ -146,7 +145,7 @@ static const struct udevice_id pxa_pwm_ids[] = {
{ }
};
U_BOOT_DRIVER(mtk_pwm) = {
U_BOOT_DRIVER(spacemit_pwm) = {
.name = "pxa_pwm",
.id = UCLASS_PWM,
.of_match = pxa_pwm_ids,

View file

@ -458,7 +458,7 @@ static int spacemit_reset_deassert(struct reset_ctl *rst)
static int spacemit_k1x_reset_probe(struct udevice *dev)
{
struct spacemit_reset *reset = dev_get_priv(dev);
pr_info("[RESET]probe start \r\n");
pr_info("reset driver probe start \n");
reset->mpmu_base = (void __iomem *)dev_remap_addr_index(dev, 0);
if (!reset->mpmu_base) {
@ -508,7 +508,7 @@ static int spacemit_k1x_reset_probe(struct udevice *dev)
goto out;
}
reset->signals = k1x_reset_signals;
pr_info("[RESET]probe finish \r\n");
pr_info("reset driver probe finish \n");
out:
return 0;
}

View file

@ -127,6 +127,12 @@ config SYS_USB_EVENT_POLL
config SYS_USB_EVENT_POLL_VIA_INT_QUEUE
bool "Poll via interrupt queue"
config SYS_USB_EVENT_POLL_COMPATIBLE
bool "Interrupt polling compatible mode"
---help---
Select to poll via interrupt queue if controller supported,
this allow using different mechanisms for different controllers.
config SYS_USB_EVENT_POLL_VIA_CONTROL_EP
bool "Poll via control EP"

View file

@ -64,8 +64,9 @@ void xhci_inval_cache(uintptr_t addr, u32 len)
* @param ptr pointer to "segement" to be freed
* Return: none
*/
static void xhci_segment_free(struct xhci_segment *seg)
static void xhci_segment_free(struct xhci_ctrl *ctrl, struct xhci_segment *seg)
{
xhci_dma_unmap(ctrl, seg->dma, SEGMENT_SIZE);
free(seg->trbs);
seg->trbs = NULL;
@ -78,7 +79,7 @@ static void xhci_segment_free(struct xhci_segment *seg)
* @param ptr pointer to "ring" to be freed
* Return: none
*/
static void xhci_ring_free(struct xhci_ring *ring)
static void xhci_ring_free(struct xhci_ctrl *ctrl, struct xhci_ring *ring)
{
struct xhci_segment *seg;
struct xhci_segment *first_seg;
@ -89,10 +90,10 @@ static void xhci_ring_free(struct xhci_ring *ring)
seg = first_seg->next;
while (seg != first_seg) {
struct xhci_segment *next = seg->next;
xhci_segment_free(seg);
xhci_segment_free(ctrl, seg);
seg = next;
}
xhci_segment_free(first_seg);
xhci_segment_free(ctrl, first_seg);
free(ring);
}
@ -105,12 +106,20 @@ static void xhci_ring_free(struct xhci_ring *ring)
*/
static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
{
struct xhci_hccr *hccr = ctrl->hccr;
int num_sp;
if (!ctrl->scratchpad)
return;
num_sp = HCS_MAX_SCRATCHPAD(xhci_readl(&hccr->cr_hcsparams2));
xhci_dma_unmap(ctrl, ctrl->scratchpad->sp_array[0],
num_sp * ctrl->page_size);
xhci_dma_unmap(ctrl, ctrl->dcbaa->dev_context_ptrs[0],
num_sp * sizeof(u64));
ctrl->dcbaa->dev_context_ptrs[0] = 0;
free(xhci_bus_to_virt(ctrl, le64_to_cpu(ctrl->scratchpad->sp_array[0])));
free(ctrl->scratchpad->scratchpad);
free(ctrl->scratchpad->sp_array);
free(ctrl->scratchpad);
ctrl->scratchpad = NULL;
@ -122,8 +131,10 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
* @param ptr pointer to "xhci_container_ctx" to be freed
* Return: none
*/
static void xhci_free_container_ctx(struct xhci_container_ctx *ctx)
static void xhci_free_container_ctx(struct xhci_ctrl *ctrl,
struct xhci_container_ctx *ctx)
{
xhci_dma_unmap(ctrl, ctx->dma, ctx->size);
free(ctx->bytes);
free(ctx);
}
@ -153,12 +164,12 @@ static void xhci_free_virt_devices(struct xhci_ctrl *ctrl)
for (i = 0; i < 31; ++i)
if (virt_dev->eps[i].ring)
xhci_ring_free(virt_dev->eps[i].ring);
xhci_ring_free(ctrl, virt_dev->eps[i].ring);
if (virt_dev->in_ctx)
xhci_free_container_ctx(virt_dev->in_ctx);
xhci_free_container_ctx(ctrl, virt_dev->in_ctx);
if (virt_dev->out_ctx)
xhci_free_container_ctx(virt_dev->out_ctx);
xhci_free_container_ctx(ctrl, virt_dev->out_ctx);
free(virt_dev);
/* make sure we are pointing to NULL */
@ -174,11 +185,15 @@ static void xhci_free_virt_devices(struct xhci_ctrl *ctrl)
*/
void xhci_cleanup(struct xhci_ctrl *ctrl)
{
xhci_ring_free(ctrl->event_ring);
xhci_ring_free(ctrl->cmd_ring);
xhci_ring_free(ctrl, ctrl->event_ring);
xhci_ring_free(ctrl, ctrl->cmd_ring);
xhci_scratchpad_free(ctrl);
xhci_free_virt_devices(ctrl);
xhci_dma_unmap(ctrl, ctrl->erst.erst_dma_addr,
sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS);
free(ctrl->erst.entries);
xhci_dma_unmap(ctrl, ctrl->dcbaa->dma,
sizeof(struct xhci_device_context_array));
free(ctrl->dcbaa);
memset(ctrl, '\0', sizeof(struct xhci_ctrl));
}
@ -218,15 +233,13 @@ static void xhci_link_segments(struct xhci_ctrl *ctrl, struct xhci_segment *prev
struct xhci_segment *next, bool link_trbs)
{
u32 val;
u64 val_64 = 0;
if (!prev || !next)
return;
prev->next = next;
if (link_trbs) {
val_64 = xhci_virt_to_bus(ctrl, next->trbs);
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
cpu_to_le64(val_64);
cpu_to_le64(next->dma);
/*
* Set the last TRB in the segment to
@ -273,7 +286,7 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring)
* @param none
* Return: pointer to the newly allocated SEGMENT
*/
static struct xhci_segment *xhci_segment_alloc(void)
static struct xhci_segment *xhci_segment_alloc(struct xhci_ctrl *ctrl)
{
struct xhci_segment *seg;
@ -281,6 +294,7 @@ static struct xhci_segment *xhci_segment_alloc(void)
BUG_ON(!seg);
seg->trbs = xhci_malloc(SEGMENT_SIZE);
seg->dma = xhci_dma_map(ctrl, seg->trbs, SEGMENT_SIZE);
seg->next = NULL;
@ -314,7 +328,7 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs,
if (num_segs == 0)
return ring;
ring->first_seg = xhci_segment_alloc();
ring->first_seg = xhci_segment_alloc(ctrl);
BUG_ON(!ring->first_seg);
num_segs--;
@ -323,7 +337,7 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs,
while (num_segs > 0) {
struct xhci_segment *next;
next = xhci_segment_alloc();
next = xhci_segment_alloc(ctrl);
BUG_ON(!next);
xhci_link_segments(ctrl, prev, next, link_trbs);
@ -372,7 +386,8 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
if (!scratchpad->sp_array)
goto fail_sp2;
val_64 = xhci_virt_to_bus(ctrl, scratchpad->sp_array);
val_64 = xhci_dma_map(ctrl, scratchpad->sp_array,
num_sp * sizeof(u64));
ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64);
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0],
@ -386,16 +401,18 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
}
BUG_ON(i == 16);
page_size = 1 << (i + 12);
buf = memalign(page_size, num_sp * page_size);
ctrl->page_size = 1 << (i + 12);
buf = memalign(ctrl->page_size, num_sp * ctrl->page_size);
if (!buf)
goto fail_sp3;
memset(buf, '\0', num_sp * page_size);
xhci_flush_cache((uintptr_t)buf, num_sp * page_size);
memset(buf, '\0', num_sp * ctrl->page_size);
xhci_flush_cache((uintptr_t)buf, num_sp * ctrl->page_size);
scratchpad->scratchpad = buf;
val_64 = xhci_dma_map(ctrl, buf, num_sp * ctrl->page_size);
for (i = 0; i < num_sp; i++) {
val_64 = xhci_virt_to_bus(ctrl, buf + i * page_size);
scratchpad->sp_array[i] = cpu_to_le64(val_64);
val_64 += ctrl->page_size;
}
xhci_flush_cache((uintptr_t)scratchpad->sp_array,
@ -437,6 +454,7 @@ static struct xhci_container_ctx
ctx->size += CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams));
ctx->bytes = xhci_malloc(ctx->size);
ctx->dma = xhci_dma_map(ctrl, ctx->bytes, ctx->size);
return ctx;
}
@ -487,7 +505,7 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id)
/* Allocate endpoint 0 ring */
virt_dev->eps[0].ring = xhci_ring_alloc(ctrl, 1, true);
byte_64 = xhci_virt_to_bus(ctrl, virt_dev->out_ctx->bytes);
byte_64 = virt_dev->out_ctx->dma;
/* Point to output device context in dcbaa. */
ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64);
@ -497,6 +515,30 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id)
return 0;
}
void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_ctrl *ctrl,
struct usb_device *udev)
{
struct xhci_virt_device *virt_dev;
struct xhci_ep_ctx *ep0_ctx;
struct xhci_ring *ep_ring;
virt_dev = ctrl->devs[udev->slot_id];
ep0_ctx = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, 0);
ep_ring = virt_dev->eps[0].ring;
/*
* FIXME we don't keep track of the dequeue pointer very well after a
* Set TR dequeue pointer, so we're setting the dequeue pointer of the
* host to our enqueue pointer. This should only be called after a
* configured device has reset, so all control transfers should have
* been completed or cancelled before the reset.
*/
ep0_ctx->deq = cpu_to_le64(xhci_trb_virt_to_dma(ep_ring->enq_seg,
ep_ring->enqueue)
| ep_ring->cycle_state);
/* uboot should flush the cache here while kernel do elsewhere */
xhci_flush_cache((uintptr_t)ep0_ctx, sizeof(struct xhci_ep_ctx));
}
/**
* Allocates the necessary data structures
* for XHCI host controller
@ -523,15 +565,16 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
return -ENOMEM;
}
val_64 = xhci_virt_to_bus(ctrl, ctrl->dcbaa);
ctrl->dcbaa->dma = xhci_dma_map(ctrl, ctrl->dcbaa,
sizeof(struct xhci_device_context_array));
/* Set the pointer in DCBAA register */
xhci_writeq(&hcor->or_dcbaap, val_64);
xhci_writeq(&hcor->or_dcbaap, ctrl->dcbaa->dma);
/* Command ring control pointer register initialization */
ctrl->cmd_ring = xhci_ring_alloc(ctrl, 1, true);
/* Set the address in the Command Ring Control register */
trb_64 = xhci_virt_to_bus(ctrl, ctrl->cmd_ring->first_seg->trbs);
trb_64 = ctrl->cmd_ring->first_seg->dma;
val_64 = xhci_readq(&hcor->or_crcr);
val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
(trb_64 & (u64) ~CMD_RING_RSVD_BITS) |
@ -555,6 +598,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
ctrl->event_ring = xhci_ring_alloc(ctrl, ERST_NUM_SEGS, false);
ctrl->erst.entries = xhci_malloc(sizeof(struct xhci_erst_entry) *
ERST_NUM_SEGS);
ctrl->erst.erst_dma_addr = xhci_dma_map(ctrl, ctrl->erst.entries,
sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS);
ctrl->erst.num_entries = ERST_NUM_SEGS;
@ -562,7 +607,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
val < ERST_NUM_SEGS;
val++) {
struct xhci_erst_entry *entry = &ctrl->erst.entries[val];
trb_64 = xhci_virt_to_bus(ctrl, seg->trbs);
trb_64 = seg->dma;
entry->seg_addr = cpu_to_le64(trb_64);
entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
entry->rsvd = 0;
@ -571,7 +616,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
xhci_flush_cache((uintptr_t)ctrl->erst.entries,
ERST_NUM_SEGS * sizeof(struct xhci_erst_entry));
deq = xhci_virt_to_bus(ctrl, ctrl->event_ring->dequeue);
deq = xhci_trb_virt_to_dma(ctrl->event_ring->deq_seg,
ctrl->event_ring->dequeue);
/* Update HC event ring dequeue pointer */
xhci_writeq(&ctrl->ir_set->erst_dequeue,
@ -586,7 +632,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
/* this is the event ring segment table pointer */
val_64 = xhci_readq(&ctrl->ir_set->erst_base);
val_64 &= ERST_PTR_MASK;
val_64 |= xhci_virt_to_bus(ctrl, ctrl->erst.entries) & ~ERST_PTR_MASK;
val_64 |= ctrl->erst.erst_dma_addr & ~ERST_PTR_MASK;
xhci_writeq(&ctrl->ir_set->erst_base, val_64);
@ -849,7 +895,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
/* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */
ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3));
trb_64 = xhci_virt_to_bus(ctrl, virt_dev->eps[0].ring->first_seg->trbs);
trb_64 = virt_dev->eps[0].ring->first_seg->dma;
ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state);
/*

View file

@ -24,6 +24,24 @@
#include <usb/xhci.h>
/*
* Returns zero if the TRB isn't in this segment, otherwise it returns the DMA
* address of the TRB.
*/
dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg,
union xhci_trb *trb)
{
unsigned long segment_offset;
if (!seg || !trb || trb < seg->trbs)
return 0;
/* offset in TRBs */
segment_offset = trb - seg->trbs;
if (segment_offset >= TRBS_PER_SEGMENT)
return 0;
return seg->dma + (segment_offset * sizeof(*trb));
}
/**
* Is this TRB a link TRB or was the last TRB the last TRB in this event ring
* segment? I.e. would the updated event TRB pointer step off the end of the
@ -180,12 +198,11 @@ static void inc_deq(struct xhci_ctrl *ctrl, struct xhci_ring *ring)
* @param trb_fields pointer to trb field array containing TRB contents
* Return: pointer to the enqueued trb
*/
static struct xhci_generic_trb *queue_trb(struct xhci_ctrl *ctrl,
struct xhci_ring *ring,
bool more_trbs_coming,
unsigned int *trb_fields)
static dma_addr_t queue_trb(struct xhci_ctrl *ctrl, struct xhci_ring *ring,
bool more_trbs_coming, unsigned int *trb_fields)
{
struct xhci_generic_trb *trb;
dma_addr_t addr;
int i;
trb = &ring->enqueue->generic;
@ -195,9 +212,11 @@ static struct xhci_generic_trb *queue_trb(struct xhci_ctrl *ctrl,
xhci_flush_cache((uintptr_t)trb, sizeof(struct xhci_generic_trb));
addr = xhci_trb_virt_to_dma(ring->enq_seg, (union xhci_trb *)trb);
inc_enq(ctrl, ring, more_trbs_coming);
return trb;
return addr;
}
/**
@ -227,7 +246,8 @@ static int prepare_ring(struct xhci_ctrl *ctrl, struct xhci_ring *ep_ring,
puts("WARN waiting for error on ep to be cleared\n");
return -EINVAL;
case EP_STATE_HALTED:
puts("WARN halted endpoint, queueing URB anyway.\n");
puts("WARN endpoint is halted\n");
return -EINVAL;
case EP_STATE_STOPPED:
case EP_STATE_RUNNING:
debug("EP STATE RUNNING.\n");
@ -271,22 +291,24 @@ static int prepare_ring(struct xhci_ctrl *ctrl, struct xhci_ring *ep_ring,
* @param cmd Command type to enqueue
* Return: none
*/
void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id,
void xhci_queue_command(struct xhci_ctrl *ctrl, dma_addr_t addr, u32 slot_id,
u32 ep_index, trb_type cmd)
{
return xhci_queue_command_extra_flags(ctrl, addr, slot_id, ep_index, cmd, 0);
}
void xhci_queue_command_extra_flags(struct xhci_ctrl *ctrl, dma_addr_t addr, u32 slot_id,
u32 ep_index, trb_type cmd, u32 extra_flags)
{
u32 fields[4];
u64 val_64 = 0;
BUG_ON(prepare_ring(ctrl, ctrl->cmd_ring, EP_STATE_RUNNING));
if (ptr)
val_64 = xhci_virt_to_bus(ctrl, ptr);
fields[0] = lower_32_bits(val_64);
fields[1] = upper_32_bits(val_64);
fields[0] = lower_32_bits(addr);
fields[1] = upper_32_bits(addr);
fields[2] = 0;
fields[3] = TRB_TYPE(cmd) | SLOT_ID_FOR_TRB(slot_id) |
ctrl->cmd_ring->cycle_state;
ctrl->cmd_ring->cycle_state | extra_flags;
/*
* Only 'reset endpoint', 'stop endpoint' and 'set TR dequeue pointer'
@ -399,12 +421,15 @@ static void giveback_first_trb(struct usb_device *udev, int ep_index,
*/
void xhci_acknowledge_event(struct xhci_ctrl *ctrl)
{
dma_addr_t deq;
/* Advance our dequeue pointer to the next event */
inc_deq(ctrl, ctrl->event_ring);
/* Inform the hardware */
xhci_writeq(&ctrl->ir_set->erst_dequeue,
xhci_virt_to_bus(ctrl, ctrl->event_ring->dequeue) | ERST_EHB);
deq = xhci_trb_virt_to_dma(ctrl->event_ring->deq_seg,
ctrl->event_ring->dequeue);
xhci_writeq(&ctrl->ir_set->erst_dequeue, deq | ERST_EHB);
}
/**
@ -440,6 +465,12 @@ static int event_ready(struct xhci_ctrl *ctrl)
* Return: pointer to event trb
*/
union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected)
{
return xhci_wait_for_event_timeout(ctrl, expected, XHCI_TIMEOUT);
}
union xhci_trb *xhci_wait_for_event_timeout(struct xhci_ctrl *ctrl, trb_type expected,
unsigned long timeout)
{
trb_type type;
unsigned long ts = get_timer(0);
@ -451,7 +482,8 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected)
continue;
type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags));
if (type == expected)
if (type == expected ||
(expected == TRB_NONE && type != TRB_PORT_STATUS))
return event;
if (type == TRB_PORT_STATUS)
@ -472,13 +504,15 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected)
le32_to_cpu(event->generic.field[3]));
xhci_acknowledge_event(ctrl);
} while (get_timer(ts) < XHCI_TIMEOUT);
} while (get_timer(ts) < timeout);
if (expected == TRB_TRANSFER)
return NULL;
printf("XHCI timeout on event type %d... cannot recover.\n", expected);
BUG();
/* Don't spam msgs for some keyboards who always timeout when no inputs */
debug("XHCI timeout on event type %d...\n", expected);
return NULL;
}
/*
@ -490,18 +524,26 @@ static void reset_ep(struct usb_device *udev, int ep_index)
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring;
union xhci_trb *event;
u64 addr;
u32 field;
printf("Resetting EP %d...\n", ep_index);
xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_RESET_EP);
xhci_queue_command(ctrl, 0, udev->slot_id, ep_index, TRB_RESET_EP);
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
if (!event)
return;
field = le32_to_cpu(event->trans_event.flags);
BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id);
xhci_acknowledge_event(ctrl);
xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue |
ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ);
addr = xhci_trb_virt_to_dma(ring->enq_seg,
(void *)((uintptr_t)ring->enqueue | ring->cycle_state));
xhci_queue_command(ctrl, addr, udev->slot_id, ep_index, TRB_SET_DEQ);
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
if (!event)
return;
BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
!= udev->slot_id || GET_COMP_CODE(le32_to_cpu(
event->event_cmd.status)) != COMP_SUCCESS);
@ -521,27 +563,49 @@ static void abort_td(struct usb_device *udev, int ep_index)
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring;
union xhci_trb *event;
xhci_comp_code comp;
trb_type type;
u64 addr;
u32 field;
xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_STOP_RING);
xhci_queue_command(ctrl, 0, udev->slot_id, ep_index, TRB_STOP_RING);
event = xhci_wait_for_event(ctrl, TRB_TRANSFER);
field = le32_to_cpu(event->trans_event.flags);
BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id);
BUG_ON(TRB_TO_EP_INDEX(field) != ep_index);
BUG_ON(GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len
!= COMP_STOP)));
event = xhci_wait_for_event(ctrl, TRB_NONE);
if (!event)
return;
type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags));
if (type == TRB_TRANSFER) {
field = le32_to_cpu(event->trans_event.flags);
BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id);
BUG_ON(TRB_TO_EP_INDEX(field) != ep_index);
BUG_ON(GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len
!= COMP_STOP)));
xhci_acknowledge_event(ctrl);
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
if (!event)
return;
type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags));
} else {
printf("abort_td: Expected a TRB_TRANSFER TRB first\n");
}
comp = GET_COMP_CODE(le32_to_cpu(event->event_cmd.status));
BUG_ON(type != TRB_COMPLETION ||
TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
!= udev->slot_id || (comp != COMP_SUCCESS && comp
!= COMP_CTX_STATE));
xhci_acknowledge_event(ctrl);
addr = xhci_trb_virt_to_dma(ring->enq_seg,
(void *)((uintptr_t)ring->enqueue | ring->cycle_state));
xhci_queue_command(ctrl, addr, udev->slot_id, ep_index, TRB_SET_DEQ);
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
!= udev->slot_id || GET_COMP_CODE(le32_to_cpu(
event->event_cmd.status)) != COMP_SUCCESS);
xhci_acknowledge_event(ctrl);
if (!event)
return;
xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue |
ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ);
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
!= udev->slot_id || GET_COMP_CODE(le32_to_cpu(
event->event_cmd.status)) != COMP_SUCCESS);
@ -576,18 +640,8 @@ static void record_transfer_result(struct usb_device *udev,
}
}
/**** Bulk and Control transfer methods ****/
/**
* Queues up the BULK Request
*
* @param udev pointer to the USB device structure
* @param pipe contains the DIR_IN or OUT , devnum
* @param length length of the buffer
* @param buffer buffer to be read/written based on the request
* Return: returns 0 if successful else -1 on failure
*/
int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
int length, void *buffer)
static int xhci_normal_tx_internal(struct usb_device *udev, unsigned long pipe,
int length, void *buffer, unsigned long timeout)
{
int num_trbs = 0;
struct xhci_generic_trb *start_trb;
@ -609,8 +663,8 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
u64 addr;
int ret;
u32 trb_fields[4];
u64 val_64 = xhci_virt_to_bus(ctrl, buffer);
void *last_transfer_trb_addr;
u64 buf_64 = xhci_dma_map(ctrl, buffer, length);
dma_addr_t last_transfer_trb_addr;
int available_length;
debug("dev=%p, pipe=%lx, buffer=%p, length=%d\n",
@ -625,7 +679,18 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index);
/*
* If the endpoint was halted due to a prior error, resume it before
* the next transfer. It is the responsibility of the upper layer to
* have dealt with whatever caused the error.
*/
if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == EP_STATE_HALTED)
reset_ep(udev, ep_index);
ring = virt_dev->eps[ep_index].ring;
if (!ring)
return -EINVAL;
/*
* How much data is (potentially) left before the 64KB boundary?
* XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec)
@ -633,7 +698,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
* we send request in more than 1 TRB by chaining them.
*/
running_total = TRB_MAX_BUFF_SIZE -
(lower_32_bits(val_64) & (TRB_MAX_BUFF_SIZE - 1));
(lower_32_bits(buf_64) & (TRB_MAX_BUFF_SIZE - 1));
trb_buff_len = running_total;
running_total &= TRB_MAX_BUFF_SIZE - 1;
@ -678,7 +743,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
* that the buffer should not span 64KB boundary. if so
* we send request in more than 1 TRB by chaining them.
*/
addr = val_64;
addr = buf_64;
if (trb_buff_len > length)
trb_buff_len = length;
@ -744,7 +809,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
giveback_first_trb(udev, ep_index, start_cycle, start_trb);
again:
event = xhci_wait_for_event(ctrl, TRB_TRANSFER);
event = xhci_wait_for_event_timeout(ctrl, TRB_TRANSFER, timeout);
if (!event) {
debug("XHCI bulk transfer timed out, aborting...\n");
abort_td(udev, ep_index);
@ -754,7 +819,7 @@ again:
}
if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer)) !=
(uintptr_t)xhci_virt_to_bus(ctrl, last_transfer_trb_addr)) {
(uintptr_t)last_transfer_trb_addr) {
available_length -=
(int)EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len));
xhci_acknowledge_event(ctrl);
@ -768,10 +833,45 @@ again:
record_transfer_result(udev, event, available_length);
xhci_acknowledge_event(ctrl);
xhci_inval_cache((uintptr_t)buffer, length);
xhci_dma_unmap(ctrl, buf_64, length);
return (udev->status != USB_ST_NOT_PROC) ? 0 : -1;
}
/**** Bulk, Interrupt and Control transfer methods ****/
/**
* Queues up the BULK Request
*
* @param udev pointer to the USB device structure
* @param pipe contains the DIR_IN or OUT , devnum
* @param length length of the buffer
* @param buffer buffer to be read/written based on the request
* Return: returns 0 if successful else -1 on failure
*/
int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
int length, void *buffer)
{
return xhci_normal_tx_internal(udev, pipe, length, buffer, XHCI_TIMEOUT);
}
/**
* Queues up the INTR Request
*
* @param udev pointer to the USB device structure
* @param pipe contains the DIR_IN or OUT , devnum
* @param length length of the buffer
* @param buffer buffer to be read/written based on the request
* @param nonblock non-blocking flag, useful for keyboard intrupt
* Return: returns 0 if successful else -1 on failure
*/
int xhci_intr_tx(struct usb_device *udev, unsigned long pipe,
int length, void *buffer, bool nonblock)
{
unsigned long timeout;
timeout = nonblock ? XHCI_NONBLOCK_INTR_TIMEOUT : USB_TIMEOUT_MS(pipe);
return xhci_normal_tx_internal(udev, pipe, length, buffer, timeout);
}
/**
* Queues up the Control Transfer Request
*
@ -811,6 +911,8 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
ep_index = usb_pipe_ep_index(pipe);
ep_ring = virt_dev->eps[ep_index].ring;
if (!ep_ring)
return -EINVAL;
/*
* Check to see if the max packet size for the default control
@ -911,7 +1013,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
if (length > 0) {
if (req->requesttype & USB_DIR_IN)
field |= TRB_DIR_IN;
buf_64 = xhci_virt_to_bus(ctrl, buffer);
buf_64 = xhci_dma_map(ctrl, buffer, length);
trb_fields[0] = lower_32_bits(buf_64);
trb_fields[1] = upper_32_bits(buf_64);
@ -961,8 +1063,10 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
}
/* Invalidate buffer to make it available to usb-core */
if (length > 0)
if (length > 0) {
xhci_inval_cache((uintptr_t)buffer, length);
xhci_dma_unmap(ctrl, buf_64, length);
}
if (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len))
== COMP_SHORT_TX) {

View file

@ -448,9 +448,12 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change)
in_ctx = virt_dev->in_ctx;
xhci_flush_cache((uintptr_t)in_ctx->bytes, in_ctx->size);
xhci_queue_command(ctrl, in_ctx->bytes, udev->slot_id, 0,
xhci_queue_command(ctrl, in_ctx->dma, udev->slot_id, 0,
ctx_change ? TRB_EVAL_CONTEXT : TRB_CONFIG_EP);
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
if (!event)
return -ETIMEDOUT;
BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
!= udev->slot_id);
@ -472,67 +475,34 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change)
}
/**
* Configure the endpoint, programming the device contexts.
* Fill endpoint contexts for interface descriptor ifdesc.
*
* @param udev pointer to the USB device structure
* Return: returns the status of the xhci_configure_endpoints
* @param udev pointer to the USB device structure
* @param ctrl pointer to the xhci pravte device structure
* @param virt_dev pointer to the xhci virtual device structure
* @param ifdesc pointer to the USB interface config descriptor
* Return: returns the status of xhci_init_ep_contexts_if
*/
static int xhci_set_configuration(struct usb_device *udev)
static int xhci_init_ep_contexts_if(struct usb_device *udev,
struct xhci_ctrl *ctrl,
struct xhci_virt_device *virt_dev,
struct usb_interface *ifdesc
)
{
struct xhci_container_ctx *in_ctx;
struct xhci_container_ctx *out_ctx;
struct xhci_input_control_ctx *ctrl_ctx;
struct xhci_slot_ctx *slot_ctx;
struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM];
int cur_ep;
int max_ep_flag = 0;
int ep_index;
unsigned int dir;
unsigned int ep_type;
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
int num_of_ep;
int ep_flag = 0;
u64 trb_64 = 0;
int slot_id = udev->slot_id;
struct xhci_virt_device *virt_dev = ctrl->devs[slot_id];
struct usb_interface *ifdesc;
u32 max_esit_payload;
unsigned int interval;
unsigned int mult;
unsigned int max_burst;
unsigned int avg_trb_len;
unsigned int err_count = 0;
int num_of_ep = ifdesc->no_of_ep;
out_ctx = virt_dev->out_ctx;
in_ctx = virt_dev->in_ctx;
num_of_ep = udev->config.if_desc[0].no_of_ep;
ifdesc = &udev->config.if_desc[0];
ctrl_ctx = xhci_get_input_control_ctx(in_ctx);
/* Initialize the input context control */
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
ctrl_ctx->drop_flags = 0;
/* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */
for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
ep_flag = xhci_get_ep_index(&ifdesc->ep_desc[cur_ep]);
ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1));
if (max_ep_flag < ep_flag)
max_ep_flag = ep_flag;
}
xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size);
/* slot context */
xhci_slot_copy(ctrl, in_ctx, out_ctx);
slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx);
slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK));
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0);
xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0);
/* filling up ep contexts */
for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
struct usb_endpoint_descriptor *endpt_desc = NULL;
struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc = NULL;
@ -558,7 +528,8 @@ static int xhci_set_configuration(struct usb_device *udev)
avg_trb_len = max_esit_payload;
ep_index = xhci_get_ep_index(endpt_desc);
ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index);
ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx,
ep_index);
/* Allocate the ep rings */
virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true);
@ -585,7 +556,8 @@ static int xhci_set_configuration(struct usb_device *udev)
cpu_to_le32(MAX_BURST(max_burst) |
ERROR_COUNT(err_count));
trb_64 = xhci_virt_to_bus(ctrl, virt_dev->eps[ep_index].ring->enqueue);
trb_64 = xhci_trb_virt_to_dma(virt_dev->eps[ep_index].ring->enq_seg,
virt_dev->eps[ep_index].ring->enqueue);
ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 |
virt_dev->eps[ep_index].ring->cycle_state);
@ -610,6 +582,72 @@ static int xhci_set_configuration(struct usb_device *udev)
}
}
return 0;
}
/**
* Configure the endpoint, programming the device contexts.
*
* @param udev pointer to the USB device structure
* Return: returns the status of the xhci_configure_endpoints
*/
static int xhci_set_configuration(struct usb_device *udev)
{
struct xhci_container_ctx *out_ctx;
struct xhci_container_ctx *in_ctx;
struct xhci_input_control_ctx *ctrl_ctx;
struct xhci_slot_ctx *slot_ctx;
int err;
int cur_ep;
int max_ep_flag = 0;
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
int num_of_ep;
int ep_flag = 0;
int slot_id = udev->slot_id;
struct xhci_virt_device *virt_dev = ctrl->devs[slot_id];
struct usb_interface *ifdesc;
unsigned int ifnum;
unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES,
(unsigned int)udev->config.no_of_if);
out_ctx = virt_dev->out_ctx;
in_ctx = virt_dev->in_ctx;
ctrl_ctx = xhci_get_input_control_ctx(in_ctx);
/* Initialize the input context control */
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
ctrl_ctx->drop_flags = 0;
for (ifnum = 0; ifnum < max_ifnum; ifnum++) {
ifdesc = &udev->config.if_desc[ifnum];
num_of_ep = ifdesc->no_of_ep;
/* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */
for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
ep_flag = xhci_get_ep_index(&ifdesc->ep_desc[cur_ep]);
ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1));
if (max_ep_flag < ep_flag)
max_ep_flag = ep_flag;
}
}
xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size);
/* slot context */
xhci_slot_copy(ctrl, in_ctx, out_ctx);
slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx);
slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK));
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0);
xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0);
/* filling up ep contexts */
for (ifnum = 0; ifnum < max_ifnum; ifnum++) {
ifdesc = &udev->config.if_desc[ifnum];
err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc);
if (err < 0)
return err;
}
return xhci_configure_endpoints(udev, false);
}
@ -620,7 +658,7 @@ static int xhci_set_configuration(struct usb_device *udev)
* @param udev pointer to the Device Data Structure
* Return: 0 if successful else error code on failure
*/
static int xhci_address_device(struct usb_device *udev, int root_portnr)
static int xhci_address_device(struct usb_device *udev, int root_portnr, bool do_address)
{
int ret = 0;
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
@ -636,15 +674,32 @@ static int xhci_address_device(struct usb_device *udev, int root_portnr)
* This is the first Set Address since device plug-in
* so setting up the slot context.
*/
debug("Setting up addressable devices %p\n", ctrl->dcbaa);
xhci_setup_addressable_virt_dev(ctrl, udev, root_portnr);
debug("Setting up addressable devices %p, BSR: %d\n", ctrl->dcbaa, !do_address);
slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->in_ctx);
/*
* If this is the first Set Address since device plug-in or
* virt_device realloaction after a resume with an xHCI power loss,
* then set up the slot context.
*/
if (!slot_ctx->dev_info)
xhci_setup_addressable_virt_dev(ctrl, udev, root_portnr);
/* Otherwise, update the control endpoint ring enqueue pointer. */
else
xhci_copy_ep0_dequeue_into_input_ctx(ctrl, udev);
ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx);
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
ctrl_ctx->drop_flags = 0;
xhci_queue_command(ctrl, (void *)ctrl_ctx, slot_id, 0, TRB_ADDR_DEV);
if (!do_address)
xhci_queue_command_extra_flags(ctrl, virt_dev->in_ctx->dma,
slot_id, 0, TRB_ADDR_DEV, TRB_BSR);
else
xhci_queue_command(ctrl, virt_dev->in_ctx->dma,
slot_id, 0, TRB_ADDR_DEV);
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
if (!event)
return -ETIMEDOUT;
BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != slot_id);
switch (GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))) {
@ -707,6 +762,9 @@ static int _xhci_alloc_device(struct usb_device *udev)
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
union xhci_trb *event;
int ret;
struct usb_device *uhop;
struct udevice *hub;
int root_portnr = 0;
/*
* Root hub will be first device to be initailized.
@ -718,8 +776,11 @@ static int _xhci_alloc_device(struct usb_device *udev)
return 0;
}
xhci_queue_command(ctrl, NULL, 0, 0, TRB_ENABLE_SLOT);
xhci_queue_command(ctrl, 0, 0, 0, TRB_ENABLE_SLOT);
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
if (!event)
return -ETIMEDOUT;
BUG_ON(GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))
!= COMP_SUCCESS);
@ -737,6 +798,21 @@ static int _xhci_alloc_device(struct usb_device *udev)
return ret;
}
hub = udev->dev;
if (device_get_uclass_id(hub) == UCLASS_USB_HUB) {
/* Figure out our port number on the root hub */
if (usb_hub_is_root_hub(hub)) {
root_portnr = udev->portnr;
} else {
while (!usb_hub_is_root_hub(hub->parent))
hub = hub->parent;
uhop = dev_get_parent_priv(hub);
root_portnr = uhop->portnr;
}
}
xhci_address_device(udev, root_portnr, false);
return 0;
}
@ -1114,7 +1190,7 @@ static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe,
* (at most) one TD. A TD (comprised of sg list entries) can
* take several service intervals to transmit.
*/
return xhci_bulk_tx(udev, pipe, length, buffer);
return xhci_intr_tx(udev, pipe, length, buffer, nonblock);
}
/**
@ -1165,7 +1241,7 @@ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe,
if (setup->request == USB_REQ_SET_ADDRESS &&
(setup->requesttype & USB_TYPE_MASK) == USB_TYPE_STANDARD)
return xhci_address_device(udev, root_portnr);
return xhci_address_device(udev, root_portnr, true);
if (setup->request == USB_REQ_SET_CONFIGURATION &&
(setup->requesttype & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
@ -1396,12 +1472,12 @@ int xhci_register(struct udevice *dev, struct xhci_hccr *hccr,
ctrl->dev = dev;
/*
* XHCI needs to issue a Address device command to setup
* proper device context structures, before it can interact
* with the device. So a get_descriptor will fail before any
* of that is done for XHCI unlike EHCI.
* XHCI support get_descriptor before Address device command after
* we support send Address device command with BSR to setup proper
* device context structures without actually sending Set Address to
* device, so enable it.
*/
priv->desc_before_addr = false;
priv->desc_before_addr = true;
ret = xhci_reset(hcor);
if (ret)

View file

@ -8,6 +8,7 @@ obj-y += video/spacemit_video_tx.o \
obj-y += video/lcd/lcd_icnl9911c.o
obj-y += video/lcd/lcd_icnl9951r.o
obj-y += video/lcd/lcd_jd9365dah3.o
obj-y += video/lcd/lcd_gx09inx101.o
obj-y += video/lcd/lcd_lt8911ext_edp_1080p.o

View file

@ -141,6 +141,7 @@ int lcd_mipi_probe(void);
int lcd_icnl9911c_init(void);
int lcd_icnl9951r_init(void);
int lcd_gx09inx101_init(void);
int lcd_jd9365dah3_init(void);
int lcd_lt8911ext_edp_1080p_init(void);
#endif /*_SPACEMIT_DSI_COMMON_H_*/

View file

@ -160,6 +160,7 @@ struct spacemit_panel_priv {
struct gpio_desc bl;
struct gpio_desc enable;
struct gpio_desc reset;
struct udevice *backlight;
bool dcp_valid;
bool dcn_valid;
bool avee_valid;

View file

@ -0,0 +1,341 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2023 Spacemit Co., Ltd.
*
*/
#include <linux/kernel.h>
#include "../../include/spacemit_dsi_common.h"
#include "../../include/spacemit_video_tx.h"
#include <linux/delay.h>
#define UNLOCK_DELAY 0
struct spacemit_mode_modeinfo jd9365dah3_spacemit_modelist[] = {
{
.name = "800x1280-60",
.refresh = 60,
.xres = 800,
.yres = 1280,
.real_xres = 800,
.real_yres = 1280,
.left_margin = 20,
.right_margin = 40,
.hsync_len = 20,
.upper_margin = 8,
.lower_margin = 20,
.vsync_len = 4,
.hsync_invert = 0,
.vsync_invert = 0,
.invert_pixclock = 0,
.pixclock_freq = 87*1000,
.pix_fmt_out = OUTFMT_RGB888,
.width = 108,
.height = 172,
},
};
struct spacemit_mipi_info jd9365dah3_mipi_info = {
.height = 1280,
.width = 800,
.hfp = 40, /* unit: pixel */
.hbp = 20,
.hsync = 20,
.vfp = 20, /* unit: line */
.vbp = 8,
.vsync = 4,
.fps = 60,
.work_mode = SPACEMIT_DSI_MODE_VIDEO, /*command_mode, video_mode*/
.rgb_mode = DSI_INPUT_DATA_RGB_MODE_888,
.lane_number = 4,
.phy_bit_clock = 614400000,
.phy_esc_clock = 51200000,
.split_enable = 0,
.eotp_enable = 0,
.burst_mode = DSI_BURST_MODE_BURST,
};
static struct spacemit_dsi_cmd_desc jd9365dah3_set_id_cmds[] = {
{SPACEMIT_DSI_SET_MAX_PKT_SIZE, SPACEMIT_DSI_LP_MODE, UNLOCK_DELAY, 1, {0x01}},
};
static struct spacemit_dsi_cmd_desc jd9365dah3_read_id_cmds[] = {
{SPACEMIT_DSI_GENERIC_READ1, SPACEMIT_DSI_LP_MODE, UNLOCK_DELAY, 1, {0x04}},
};
static struct spacemit_dsi_cmd_desc jd9365dah3_set_power_cmds[] = {
{SPACEMIT_DSI_SET_MAX_PKT_SIZE, SPACEMIT_DSI_HS_MODE, UNLOCK_DELAY, 1, {0x1}},
};
static struct spacemit_dsi_cmd_desc jd9365dah3_read_power_cmds[] = {
{SPACEMIT_DSI_GENERIC_READ1, SPACEMIT_DSI_HS_MODE, UNLOCK_DELAY, 1, {0xA}},
};
static struct spacemit_dsi_cmd_desc jd9365dah3_init_cmds[] = {
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE0, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE1, 0x93}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE2, 0x65}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE3, 0xF8}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x80, 0x03}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE0, 0x01}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x00, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x01, 0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x03, 0x10}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x04, 0x47}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x0C, 0x74}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x17, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x18, 0xD7}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x19, 0x01}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x1A, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x1B, 0xD7}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x1C, 0x01}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x24, 0xFE}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x25, 0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x35, 0x28}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x37, 0x69}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x38, 0x05}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x39, 0x08}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3A, 0x0A}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3C, 0x78}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3D, 0xFF}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3E, 0xFF}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3F, 0xFF}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x40, 0x06}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x41, 0xA0}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x43, 0x14}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x44, 0x08}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x45, 0x20}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x4B, 0x04}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x55, 0x02}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x57, 0xA9}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x59, 0x0A}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5A, 0x2D}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5B, 0x19}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5C, 0x15}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5D, 0x7C}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5E, 0x6C}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5F, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x60, 0x54}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x61, 0x50}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x62, 0x43}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x63, 0x46}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x64, 0x2F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x65, 0x48}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x66, 0x46}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x67, 0x44}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x68, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x69, 0x49}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6A, 0x4C}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6B, 0x3D}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6C, 0x36}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6D, 0x29}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6E, 0x18}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6F, 0x0C}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x70, 0x7C}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x71, 0x6C}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x72, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x73, 0x54}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x74, 0x50}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x75, 0x43}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x76, 0x46}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x77, 0x2F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x78, 0x48}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x79, 0x46}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7A, 0x44}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7B, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7C, 0x49}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7D, 0x4C}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7E, 0x3D}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7F, 0x36}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x80, 0x29}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x81, 0x18}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x82, 0x0C}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE0, 0x02}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x00, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x01, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x02, 0x52}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x03, 0x51}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x04, 0x50}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x05, 0x4B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x06, 0x4A}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x07, 0x49}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x08, 0x48}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x09, 0x47}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x0A, 0x46}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x0B, 0x45}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x0C, 0x44}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x0D, 0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x0E, 0x41}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x0F, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x10, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x11, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x12, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x13, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x14, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x15, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x16, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x17, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x18, 0x52}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x19, 0x51}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x1A, 0x50}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x1B, 0x4B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x1C, 0x4A}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x1D, 0x49}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x1E, 0x48}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x1F, 0x47}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x20, 0x46}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x21, 0x45}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x22, 0x44}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x23, 0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x24, 0x41}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x25, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x26, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x27, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x28, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x29, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x2A, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x2B, 0x5F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x2C, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x2D, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x2E, 0x12}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x2F, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x30, 0x01}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x31, 0x08}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x32, 0x09}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x33, 0x0A}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x34, 0x0B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x35, 0x04}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x36, 0x05}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x37, 0x06}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x38, 0x07}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x39, 0x11}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3A, 0x10}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3B, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3C, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3D, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3E, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x3F, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x40, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x41, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x42, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x43, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x44, 0x12}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x45, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x46, 0x01}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x47, 0x08}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x48, 0x09}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x49, 0x0A}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x4A, 0x0B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x4B, 0x04}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x4C, 0x05}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x4D, 0x06}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x4E, 0x07}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x4F, 0x11}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x50, 0x10}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x51, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x52, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x53, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x54, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x55, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x56, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x57, 0x1F}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x58, 0x40}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x59, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5A, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5B, 0x10}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5C, 0x02}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5D, 0x50}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5E, 0x01}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x5F, 0x02}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x60, 0x50}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x61, 0x05}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x62, 0x02}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x63, 0x04}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x64, 0x64}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x65, 0x65}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x66, 0x08}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x67, 0x73}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x68, 0x04}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x69, 0x04}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6A, 0x64}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6B, 0x08}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6C, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6D, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6E, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x6F, 0x88}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x70, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x71, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x72, 0x06}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x73, 0x7B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x74, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x75, 0x0C}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x76, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x77, 0x5D}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x78, 0x17}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x79, 0x10}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7A, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7B, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7C, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7D, 0x03}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x7E, 0x7B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE0, 0x04}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x2C, 0x6B}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x35, 0x0A}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0xE0, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 120, 2, {0x11, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 5, 2, {0x29, 0x00}},
{SPACEMIT_DSI_DCS_LWRITE, SPACEMIT_DSI_LP_MODE, 0, 2, {0x35, 0x00}},
};
static struct spacemit_dsi_cmd_desc jd9365dah3_sleep_out_cmds[] = {
{SPACEMIT_DSI_DCS_SWRITE,SPACEMIT_DSI_LP_MODE,120,2,{0x11, 0x00}},
{SPACEMIT_DSI_DCS_SWRITE,SPACEMIT_DSI_LP_MODE,50,2,{0x29, 0x00}},
};
static struct spacemit_dsi_cmd_desc jd9365dah3_sleep_in_cmds[] = {
{SPACEMIT_DSI_DCS_SWRITE,SPACEMIT_DSI_LP_MODE,50,2,{0x28, 0x00}},
{SPACEMIT_DSI_DCS_SWRITE,SPACEMIT_DSI_LP_MODE,120,2,{0x10, 0x00}},
};
struct lcd_mipi_panel_info lcd_jd9365dah3 = {
.lcd_name = "jd9365dah3",
.lcd_id = 0x9365,
.panel_id0 = 0x93,
.power_value = 0x18,
.panel_type = LCD_MIPI,
.width_mm = 108,
.height_mm = 172,
.dft_pwm_bl = 128,
.set_id_cmds_num = ARRAY_SIZE(jd9365dah3_set_id_cmds),
.read_id_cmds_num = ARRAY_SIZE(jd9365dah3_read_id_cmds),
.init_cmds_num = ARRAY_SIZE(jd9365dah3_init_cmds),
.set_power_cmds_num = ARRAY_SIZE(jd9365dah3_set_power_cmds),
.read_power_cmds_num = ARRAY_SIZE(jd9365dah3_read_power_cmds),
.sleep_out_cmds_num = ARRAY_SIZE(jd9365dah3_sleep_out_cmds),
.sleep_in_cmds_num = ARRAY_SIZE(jd9365dah3_sleep_in_cmds),
//.drm_modeinfo = jd9365dah3_modelist,
.spacemit_modeinfo = jd9365dah3_spacemit_modelist,
.mipi_info = &jd9365dah3_mipi_info,
.set_id_cmds = jd9365dah3_set_id_cmds,
.read_id_cmds = jd9365dah3_read_id_cmds,
.set_power_cmds = jd9365dah3_set_power_cmds,
.read_power_cmds = jd9365dah3_read_power_cmds,
.init_cmds = jd9365dah3_init_cmds,
.sleep_out_cmds = jd9365dah3_sleep_out_cmds,
.sleep_in_cmds = jd9365dah3_sleep_in_cmds,
.bitclk_sel = 3,
.bitclk_div = 1,
.pxclk_sel = 2,
.pxclk_div = 6,
};
int lcd_jd9365dah3_init(void)
{
int ret;
ret = lcd_mipi_register_panel(&lcd_jd9365dah3);
return ret;
}

View file

@ -17,7 +17,7 @@
#include <asm/global_data.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <backlight.h>
#define PANEL_NUM_MAX 5
@ -354,13 +354,24 @@ static int lcd_bl_enable(struct video_tx_device *dev, bool enable)
struct lcd_mipi_tx_data *video_tx_client =
video_tx_get_drvdata(dev);
struct spacemit_panel_priv *priv = video_tx_client->priv;
int ret;
if (priv->bl_valid) {
if (enable)
dm_gpio_set_value(&priv->bl, 1);
else
dm_gpio_set_value(&priv->bl, 0);
if (enable) {
ret = backlight_set_brightness(priv->backlight, BACKLIGHT_DEFAULT);
pr_debug("%s: set brightness done, ret = %d\n", __func__, ret);
if (ret)
return ret;
ret = backlight_enable(priv->backlight);
pr_debug("%s: enable backlight done, ret = %d\n", __func__, ret);
if (ret)
return ret;
} else {
ret = backlight_set_brightness(priv->backlight, BACKLIGHT_OFF);
pr_debug("%s: shutdown backlight done, ret = %d\n", __func__, ret);
if (ret)
return ret;
}
}
return 0;
@ -444,6 +455,10 @@ int lcd_mipi_probe(void)
tx_device_client.panel_type = LCD_MIPI;
tx_device.panel_type = tx_device_client.panel_type;
lcd_icnl9951r_init();
} else if(strcmp("jd9365dah3", priv->panel_name) == 0) {
tx_device_client.panel_type = LCD_MIPI;
tx_device.panel_type = tx_device_client.panel_type;
lcd_jd9365dah3_init();
} else {
// lcd_icnl9911c_init();
lcd_gx09inx101_init();
@ -513,13 +528,14 @@ static int spacemit_panel_of_to_plat(struct udevice *dev)
}
ret = gpio_request_by_name(dev, "bl-gpios", 0, &priv->bl,
GPIOD_IS_OUT);
ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
"backlight", &priv->backlight);
if (ret) {
pr_debug("%s: Warning: cannot get bl GPIO: ret=%d\n",
__func__, ret);
pr_debug("%s: Warning: cannot get backlight pwm: ret = %d\n",
__func__, ret);
priv->bl_valid = false;
} else {
pr_debug("apply for pwm successfully\n");
priv->bl_valid = true;
}

View file

@ -6,6 +6,7 @@
#include <common.h>
#include <display.h>
#include <cpu_func.h>
#include <dm.h>
#include <dm/uclass.h>
#include <dm/device.h>
@ -306,12 +307,15 @@ static int spacemit_display_init(struct udevice *dev, ulong fbbase, ofnode ep_no
return ret;
}
hdmi_dpu_init(&hdmi_1080p_modeinfo, fbbase);
uc_priv->xsize = 1920;
uc_priv->ysize = 1080;
pr_info("fb=%lx, size=%d %d\n", fbbase, uc_priv->xsize, uc_priv->ysize);
pr_info("fb=%lx, size=%dx%d\n", fbbase, uc_priv->xsize, uc_priv->ysize);
memset((void *)fbbase, 0, uc_priv->xsize * uc_priv->ysize * VNBYTES(uc_priv->bpix));
flush_cache(fbbase, uc_priv->xsize * uc_priv->ysize * VNBYTES(uc_priv->bpix));
hdmi_dpu_init(&hdmi_1080p_modeinfo, fbbase);
return 0;
} else if (dpu_id == DPU_MODE_MIPI) {
@ -356,6 +360,11 @@ static int spacemit_display_init(struct udevice *dev, ulong fbbase, ofnode ep_no
uc_priv->xsize = spacemit_mode->xres;
uc_priv->ysize = spacemit_mode->yres;
pr_info("fb=%lx, size=%dx%d\n", fbbase, uc_priv->xsize, uc_priv->ysize);
memset((void *)fbbase, 0, uc_priv->xsize * uc_priv->ysize * VNBYTES(uc_priv->bpix));
flush_cache(fbbase, uc_priv->xsize * uc_priv->ysize * VNBYTES(uc_priv->bpix));
pr_debug("%s: panel type %d\n", __func__, fbi.tx->panel_type);
if (fbi.tx->panel_type == LCD_MIPI) {
@ -393,8 +402,6 @@ static int spacemit_display_init(struct udevice *dev, ulong fbbase, ofnode ep_no
pr_info("%s: Failed to find panel\n", __func__);
}
pr_info("fb=%lx, size=%d %d\n", fbbase, uc_priv->xsize, uc_priv->ysize);
return 0;
}

View file

@ -20,6 +20,7 @@ struct pmic_wdt_priv {
fdt_addr_t base;
fdt_addr_t pwr_ctrl0;
fdt_addr_t pwr_ctrl2;
fdt_addr_t alive_reg;
enum pmic_model model;
};
@ -199,6 +200,14 @@ static int pmic_wdt_expire_now(struct udevice *dev, ulong flags)
switch (priv->model) {
case PMIC_MODEL_SPM8821:
/* set the reset flag for shutdown charging or not */
ret = pmic_reg_read(priv->pmic_dev, priv->alive_reg);
if (ret < 0) return ret;
reg_val = ret | (1 << SYS_REBOOT_FLAG_BIT);
ret = pmic_reg_write(priv->pmic_dev, priv->alive_reg, reg_val);
if (ret) return ret;
/* Set SW_RST bit of PWR_CTRL2 */
ret = pmic_reg_read(priv->pmic_dev, priv->pwr_ctrl2);
if (ret < 0) return ret;
@ -234,6 +243,7 @@ static int pmic_wdt_probe(struct udevice *dev)
priv->base = SPM8821_WDT_CTRL;
priv->pwr_ctrl0 = SPM8821_PWR_CTRL0;
priv->pwr_ctrl2 = SPM8821_PWR_CTRL2;
priv->alive_reg = SPM8821_ALIVE_REGISTER;
} else {
priv->model = PMIC_MODEL_UNKNOWN;
pr_err("Device is not compatible: %s\n", wdt_name);

7
env/Kconfig vendored
View file

@ -272,6 +272,13 @@ config ENV_IS_IN_NAND
Currently, CONFIG_ENV_OFFSET_REDUND is not supported when
using CONFIG_ENV_OFFSET_OOB.
config ENV_IS_IN_NFS
bool "Environment is in NFS"
depends on NET
help
This option allows loading the environment from an NFS server
when local bootfs is not available.
config ENV_RANGE
hex "Length of the region in which the environment can be written"
depends on ENV_IS_IN_NAND

View file

@ -812,11 +812,11 @@ int do_load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[],
printf("%llu bytes read in %lu ms", len_read, time);
if (time > 0) {
puts(" (");
printf(" (");
print_size(div_u64(len_read, time) * 1000, "/s");
puts(")");
printf(")");
}
puts("\n");
printf("\n");
env_set_hex("fileaddr", addr);
env_set_hex("filesize", len_read);

View file

@ -18,6 +18,7 @@
#define RISCV_MMODE_TIMER_FREQ 24000000
#define RISCV_SMODE_TIMER_FREQ 24000000
#define RISCV_TIMER_FREQ (RISCV_SMODE_TIMER_FREQ)
#define CONFIG_IPADDR 10.0.92.253
#define CONFIG_SERVERIP 10.0.92.134
@ -77,6 +78,7 @@
#define TLV_CODE_SDK_VERSION 0x40
#define TLV_CODE_DDR_CSNUM 0x41
#define TLV_CODE_DDR_TYPE 0x42
#define TLV_CODE_DDR_DATARATE 0x43
#define TLV_CODE_PMIC_TYPE 0x80
#define TLV_CODE_EEPROM_I2C_INDEX 0x81
@ -172,11 +174,6 @@ struct boot_storage_op
"dtb_addr=" __stringify(DTB_LOAD_ADDR) "\0" \
"scriptaddr=0x2c100000\0" \
"pxefile_addr_r=0x0c200000\0" \
"ipaddr=192.168.1.15\0" \
"netmask=255.255.255.0\0" \
"serverip=10.0.92.134\0" \
"gatewayip=192.168.1.1\0" \
"net_data_path=spacemit_flash_file/net_flash_file/\0" \
"splashimage=" __stringify(CONFIG_FASTBOOT_BUF_ADDR) "\0" \
"splashpos=m,m\0" \
"splashfile=bianbu.bmp\0" \

View file

@ -37,6 +37,8 @@ enum uclass_id {
UCLASS_AUDIO_CODEC, /* Audio codec with control and data path */
UCLASS_AXI, /* AXI bus */
UCLASS_BLK, /* Block device */
UCLASS_BATTERY, /* Battery */
UCLASS_CHARGER, /* Charger */
UCLASS_BOOTCOUNT, /* Bootcount backing store */
UCLASS_BOOTDEV, /* Boot device for locating an OS to boot */
UCLASS_BOOTMETH, /* Bootmethod for booting an OS */

View file

@ -10,5 +10,6 @@
#define K1X_PMU_AUD_PWR_DOMAIN 4
#define K1X_PMU_GNSS_PWR_DOMAIN 5
#define K1X_PMU_HDMI_PWR_DOMAIN 6
#define K1X_PMU_WKUP_EVENT_PWR_DOMAIN 7
#endif /* __DT_BINDINGS_POWER_DOMAIN_K1X_H */

View file

@ -721,6 +721,9 @@ efi_status_t efi_allocate_pool(enum efi_memory_type pool_type,
efi_uintn_t size, void **buffer);
/* EFI pool memory free function. */
efi_status_t efi_free_pool(void *buffer);
/* Allocate and retrieve EFI memory map */
efi_status_t efi_get_memory_map_alloc(efi_uintn_t *map_size,
struct efi_mem_desc **memory_map);
/* Returns the EFI memory map */
efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
struct efi_mem_desc *memory_map,

View file

@ -58,8 +58,16 @@ struct flash_volume_image {
struct flash_parts_info {
char *part_name;
char *file_name;
/*partition size info, such as 128MiB*/
/*partition offset info*/
u64 part_offset;
/*partition size info*/
u64 part_size;
/*save partition size to string*/
char *size;
/*use for fsbl, if hidden that gpt would reserve a raw memeory
for fsbl and the partition is not available.
*/

View file

@ -7,6 +7,8 @@
#ifndef __POWER_BATTERY_H_
#define __POWER_BATTERY_H_
#ifndef CONFIG_DM_BATTERY
/* TODO: remove this once all users have been moved over to DM */
struct battery {
unsigned int version;
unsigned int state_of_chrg;
@ -18,4 +20,41 @@ struct battery {
};
int power_bat_init(unsigned char bus);
#else
enum dm_battery_state {
BAT_STATE_UNUSED = 0, /* never used */
BAT_STATE_NOT_PRESENT, /* battery is not present */
BAT_STATE_NEED_CHARGING, /* battery needs charging (i.e. low SOC or voltage) */
BAT_STATE_NORMAL, /* battery is OK */
};
/* Battery device operations */
struct dm_battery_ops {
/**
* Get the current voltage of the battery.
* @dev - battery device
* @uV - pointer to place to store voltage, in microvolts
* @return 0 if success, -errno otherwise.
*/
int (*get_voltage)(struct udevice *dev, unsigned int *uV);
/**
* Get the current battery status
* @dev - battery device
* @return -errno on error, enum dm_battery_state otherwise
*/
int (*get_status)(struct udevice *dev);
/**
* Get the battery's State Of Charge (SOC)
* @dev - battery device
* @return 0-100 value representing current battery charge percentage, -errno on error
*/
int (*get_soc)(struct udevice *dev);
};
int battery_get(const char *devname, struct udevice **devp);
int battery_get_voltage(struct udevice *dev, unsigned int *uV);
int battery_get_status(struct udevice *dev);
int battery_get_soc(struct udevice *dev);
#endif /* CONFIG_DM_BATTERY */
#endif /* __POWER_BATTERY_H_ */

40
include/power/charger.h Normal file
View file

@ -0,0 +1,40 @@
/*
* Copyright (C) 2018 Simon Shields <simon@lineageos.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
enum charger_state {
CHARGE_STATE_UNKNOWN = 0,
CHARGE_STATE_CHARGING = 1, /* charging normally */
CHARGE_STATE_FULL = 2, /* not charging - battery full */
CHARGE_STATE_NOT_CHARGING = 3, /* not charging - some other reason */
CHARGE_STATE_DISCHARGING = 4, /* discharging */
};
struct dm_charger_ops {
/**
* Get the charge current of the charger.
* Some devices may return the maximum charge current rather than the current charge current.
* @dev - charger device.
* @return -errno on error, charge current in uA.
*/
int (*get_current)(struct udevice *dev);
/**
* Set the maximum charge current for the charger. A current of zero will disable charging.
* @dev - charger device
* @return -errno on error, 0 otherwise.
*/
int (*set_current)(struct udevice *dev, unsigned int microamps);
/**
* Get current charging state.
* @dev - charger device
* @return -errno on error, enum charger_state otherwise.
*/
int (*get_status)(struct udevice *dev);
};
int charger_get(const char *devname, struct udevice **devp);
int charger_get_current(struct udevice *dev);
int charger_set_current(struct udevice *dev, unsigned int microamps);
int charger_get_status(struct udevice *dev);

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