mirror of
https://gitee.com/bianbu-linux/uboot-2022.10
synced 2025-04-24 14:57:15 -04:00
Compare commits
6 commits
Author | SHA1 | Date | |
---|---|---|---|
|
60297de7dc | ||
|
8bdc7887dc | ||
|
a996a74cc1 | ||
|
ad097c0e1d | ||
|
f91a284fab | ||
|
c83b48d3b0 |
40 changed files with 2849 additions and 286 deletions
|
@ -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/
|
||||
|
|
|
@ -13,7 +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_MUSE-Paper-mini-4g.dtb k1-x_baton-camera.dtb \
|
||||
k1-x_FusionOne.dtb
|
||||
|
||||
include $(srctree)/scripts/Makefile.dts
|
||||
|
||||
|
|
|
@ -857,6 +857,10 @@
|
|||
};
|
||||
};
|
||||
|
||||
shutdown_charging: charging {
|
||||
compatible = "k1,shutdown-charging";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
binman: binman {
|
||||
|
|
207
arch/riscv/dts/k1-x_FusionOne.dts
Normal file
207
arch/riscv/dts/k1-x_FusionOne.dts
Normal 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";
|
||||
};
|
||||
|
||||
ð0 {
|
||||
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";
|
||||
};
|
|
@ -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>;
|
||||
|
|
|
@ -6,15 +6,13 @@
|
|||
#include "k1-x.dtsi"
|
||||
#include "k1-x_pinctrl.dtsi"
|
||||
#include "k1-x_spm8821.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
/ {
|
||||
model = "M1-MUSE-PAPER";
|
||||
|
||||
aliases {
|
||||
efuse_power = &ldo_31;
|
||||
battery = &cw2015;
|
||||
charger = &sgm41515;
|
||||
charger-2 = &secsgm41515;
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
|
@ -38,6 +36,27 @@
|
|||
vbus-gpios = <&gpio 79 0>; /* gpio_79 for usb3 pwren */
|
||||
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 {
|
||||
|
@ -315,3 +334,27 @@
|
|||
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";
|
||||
};
|
||||
|
|
295
arch/riscv/dts/k1-x_baton-camera.dts
Normal file
295
arch/riscv/dts/k1-x_baton-camera.dts
Normal 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";
|
||||
};
|
||||
|
||||
|
||||
ð0 {
|
||||
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";
|
||||
};
|
|
@ -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";
|
||||
};
|
||||
|
|
42
arch/riscv/include/asm/sleep.h
Normal file
42
arch/riscv/include/asm/sleep.h
Normal 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
|
1
arch/riscv/kernel/Makefile
Normal file
1
arch/riscv/kernel/Makefile
Normal file
|
@ -0,0 +1 @@
|
|||
obj-y += suspend_entry.o
|
112
arch/riscv/kernel/suspend_entry.S
Normal file
112
arch/riscv/kernel/suspend_entry.S
Normal 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)
|
|
@ -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
|
||||
|
|
|
@ -163,6 +163,24 @@
|
|||
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 {
|
||||
|
@ -247,5 +265,15 @@
|
|||
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";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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,8 +66,7 @@ phy_link_time=10000
|
|||
netdev=eth0
|
||||
|
||||
// Common boot args
|
||||
set_bootargs=setenv bootargs earlycon=${earlycon} earlyprintk quiet splash console=${console} loglevel=${loglevel} clk_ignore_unused swiotlb=65536 rdinit=${init} product_name=${product_name}
|
||||
commonargs=run set_bootargs; setenv bootargs "${bootargs}" plymouth.ignore-serial-consoles plymouth.prefer-fbcon 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 \
|
||||
|
@ -141,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; \
|
||||
|
@ -148,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"
|
||||
|
|
|
@ -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();
|
||||
|
|
382
board/spacemit/k1-x/nfs_env.c
Normal file
382
board/spacemit/k1-x/nfs_env.c
Normal 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;
|
||||
}
|
24
board/spacemit/k1-x/nfs_env.h
Normal file
24
board/spacemit/k1-x/nfs_env.h
Normal 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__
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
136
common/usb_kbd.c
136
common/usb_kbd.c
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -241,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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ int _parse_flash_config(struct flash_dev *fdev, void *load_flash_addr)
|
|||
if (!parse_mtd_partition){
|
||||
if (strlen(node_part) > 0 && !strncmp("bootinfo", node_part, 8)){
|
||||
pr_info("bootinfo would not add as partition\n");
|
||||
fdev->parts_info[part_index].hidden = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -818,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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
519
drivers/misc/spacemit_shutdown_charging.c
Normal file
519
drivers/misc/spacemit_shutdown_charging.c
Normal 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),
|
||||
};
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
7
env/Kconfig
vendored
|
@ -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
|
||||
|
|
|
@ -174,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" \
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -83,10 +83,17 @@
|
|||
#define SPM8821_SWITCH_CTRL_REG 0x59
|
||||
#define SPM8821_SWTICH_EN_MASK 0x1
|
||||
|
||||
#define SPM8821_SWITCH_PWRKEY_EVENT_CTRL_REG 0x97
|
||||
#define SPM8821_SWITCH_PWRKEY_EVENT_EN_MSK 0xf
|
||||
|
||||
#define SPM8821_SWITCH_PWRKEY_INIT_CTRL_REG 0x9e
|
||||
#define SPM8821_SWITCH_PWRKEY_INT_EN_MSK 0xf
|
||||
|
||||
/* Watchdog Timer Registers */
|
||||
#define SPM8821_WDT_CTRL 0x44
|
||||
#define SPM8821_PWR_CTRL0 0x7C
|
||||
#define SPM8821_PWR_CTRL2 0x7E
|
||||
#define SPM8821_PWR_CTRL2_MSK 0xff
|
||||
|
||||
/* Watchdog Timer Control Bits */
|
||||
#define SPM8821_WDT_CLEAR_STATUS 0x1
|
||||
|
@ -98,6 +105,19 @@
|
|||
#define SPM8821_WDT_TIMEOUT_8S 0x2
|
||||
#define SPM8821_WDT_TIMEOUT_16S 0x3
|
||||
|
||||
#define SPM8821_RTC_TICK_CTRL 0x1d
|
||||
#define SPM8821_RTC_TICK_CTRL_MSK 0x7f
|
||||
|
||||
#define SPM8821_RTC_TICK_EVENT 0x92
|
||||
#define SPM8821_RTC_TICK_EVENT_MSK 0x3f
|
||||
|
||||
#define SPM8821_RTC_TICK_IRQ 0x99
|
||||
#define SPM8821_RTC_TICK_IRQ_MSK 0x3f
|
||||
|
||||
#define SPM8821_ALIVE_REGISTER 0xab
|
||||
#define SPM8821_ALIVE_REGISTER_MSK 0x7
|
||||
#define SYS_REBOOT_FLAG_BIT 0x2
|
||||
|
||||
enum SPM8821_buck_reg {
|
||||
SPM8821_ID_DCDC1,
|
||||
SPM8821_ID_DCDC2,
|
||||
|
@ -123,6 +143,20 @@ enum SPM8821_ldo_reg {
|
|||
|
||||
enum SPM8821_switch_reg {
|
||||
SPM8821_ID_SWITCH1,
|
||||
SPM8821_ID_SWITCH1_PWRKEY_EVENT,
|
||||
SPM8821_ID_SWITCH1_PWRKEY_INT,
|
||||
SPM8821_ID_SWITCH_RTC_TICK_CTRL,
|
||||
SPM8821_ID_SWITCH_RTC_TICK_EVENT,
|
||||
SPM8821_ID_SWITCH_RTC_TCK_IRQ,
|
||||
SPM8821_ID_SWITCH_POWER_DOWN,
|
||||
SPM8821_ID_SWITCH_CHARGING_FLAG,
|
||||
};
|
||||
|
||||
enum SPM8821_pwrkey_event {
|
||||
PWRKEY_RISING_EVENT = 1,
|
||||
PWRKEY_FAILING_EVENT = 2,
|
||||
PWRKEY_SHORT_PRESS_EVENT = 4,
|
||||
PWRKEY_LONG_PRESS_EVENT = 8,
|
||||
};
|
||||
|
||||
#define SPM8821_BUCK_LINER_RANGE \
|
||||
|
@ -255,8 +289,22 @@ static const struct pm8xx_buck_desc spm8821_ldo_desc[] = { \
|
|||
#define SPM8821_REGULATOR_SWITCH_DESC \
|
||||
static const struct pm8xx_buck_desc spm8821_switch_desc[] = { \
|
||||
/* PWR SWITCH */ \
|
||||
PM8XX_DESC_COMMON(SPM8821_ID_SWITCH1, "SWITCH_REG", 0, SPM8821_SWITCH_CTRL_REG, SPM8821_SWTICH_EN_MASK, \
|
||||
0, 0, 0, 0, spm8821_switch_ranges), \
|
||||
PM8XX_DESC_COMMON(SPM8821_ID_SWITCH1, "SWITCH_REG1", 0, 0, 0, SPM8821_SWITCH_CTRL_REG, SPM8821_SWTICH_EN_MASK, \
|
||||
0, 0, spm8821_switch_ranges), \
|
||||
PM8XX_DESC_COMMON(SPM8821_ID_SWITCH1_PWRKEY_EVENT, "SWITCH_REG2", 0, 0, 0, SPM8821_SWITCH_PWRKEY_EVENT_CTRL_REG, SPM8821_SWITCH_PWRKEY_EVENT_EN_MSK, \
|
||||
0, 0, spm8821_switch_ranges), \
|
||||
PM8XX_DESC_COMMON(SPM8821_ID_SWITCH1_PWRKEY_INT, "SWITCH_REG3", 0, 0, 0, SPM8821_SWITCH_PWRKEY_INIT_CTRL_REG, SPM8821_SWITCH_PWRKEY_INT_EN_MSK, \
|
||||
0, 0, spm8821_switch_ranges), \
|
||||
PM8XX_DESC_COMMON(SPM8821_ID_SWITCH_RTC_TICK_CTRL, "SWITCH_REG4", 0, 0, 0, SPM8821_RTC_TICK_CTRL, SPM8821_RTC_TICK_CTRL_MSK, \
|
||||
0, 0, spm8821_switch_ranges), \
|
||||
PM8XX_DESC_COMMON(SPM8821_ID_SWITCH_RTC_TICK_EVENT, "SWITCH_REG5", 0, 0, 0, SPM8821_RTC_TICK_EVENT, SPM8821_RTC_TICK_EVENT_MSK, \
|
||||
0, 0, spm8821_switch_ranges), \
|
||||
PM8XX_DESC_COMMON(SPM8821_ID_SWITCH_RTC_TCK_IRQ, "SWITCH_REG6", 0, 0, 0, SPM8821_RTC_TICK_IRQ, SPM8821_RTC_TICK_IRQ_MSK, \
|
||||
0, 0, spm8821_switch_ranges), \
|
||||
PM8XX_DESC_COMMON(SPM8821_ID_SWITCH_POWER_DOWN, "SWITCH_REG7", 0, 0, 0, SPM8821_PWR_CTRL2, SPM8821_PWR_CTRL2_MSK, \
|
||||
0, 0, spm8821_switch_ranges), \
|
||||
PM8XX_DESC_COMMON(SPM8821_ID_SWITCH_CHARGING_FLAG, "SWITCH_REG8", 0, 0, 0, SPM8821_ALIVE_REGISTER, SPM8821_ALIVE_REGISTER_MSK, \
|
||||
0, 0, spm8821_switch_ranges), \
|
||||
};
|
||||
|
||||
#define SPM8821_REGULATOR_MATCH_DATA \
|
||||
|
|
|
@ -46,6 +46,12 @@
|
|||
*/
|
||||
#define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000)
|
||||
|
||||
/*
|
||||
* The xhcd hcd driver prepares only a limited number interfaces / endpoints.
|
||||
* Define this limit so that drivers do not exceed it.
|
||||
*/
|
||||
#define USB_MAX_ACTIVE_INTERFACES 2
|
||||
|
||||
/* device request (setup) */
|
||||
struct devrequest {
|
||||
__u8 requesttype;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#ifndef HOST_XHCI_H_
|
||||
#define HOST_XHCI_H_
|
||||
|
||||
#include <iommu.h>
|
||||
#include <phys2bus.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/cache.h>
|
||||
|
@ -25,6 +26,13 @@
|
|||
|
||||
#define MAX_EP_CTX_NUM 31
|
||||
#define XHCI_ALIGNMENT 64
|
||||
|
||||
/* Non-blocking INTR transfer timeout
|
||||
* Keyboard idle timeout is 40ms, double it to make sure key is captured,
|
||||
* meanwhile prevent misbehaved keyboard block too long
|
||||
*/
|
||||
#define XHCI_NONBLOCK_INTR_TIMEOUT 80
|
||||
|
||||
/* Generic timeout for XHCI events */
|
||||
#define XHCI_TIMEOUT 5000
|
||||
/* Max number of USB devices for any host controller - limit in section 6.1 */
|
||||
|
@ -490,6 +498,7 @@ struct xhci_container_ctx {
|
|||
|
||||
int size;
|
||||
u8 *bytes;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -688,6 +697,8 @@ struct xhci_input_control_ctx {
|
|||
struct xhci_device_context_array {
|
||||
/* 64-bit device addresses; we only write 32-bit addresses */
|
||||
__le64 dev_context_ptrs[MAX_HC_SLOTS];
|
||||
/* private xHCD pointers */
|
||||
dma_addr_t dma;
|
||||
};
|
||||
/* TODO: write function to set the 64-bit device DMA address */
|
||||
/*
|
||||
|
@ -870,6 +881,9 @@ struct xhci_event_cmd {
|
|||
/* Block Event Interrupt */
|
||||
#define TRB_BEI (1<<9)
|
||||
|
||||
/* Address device - disable SetAddress */
|
||||
#define TRB_BSR (1<<9)
|
||||
|
||||
/* Control transfer TRB specific fields */
|
||||
#define TRB_DIR_IN (1<<16)
|
||||
#define TRB_TX_TYPE(p) ((p) << 16)
|
||||
|
@ -897,6 +911,8 @@ union xhci_trb {
|
|||
|
||||
/* TRB type IDs */
|
||||
typedef enum {
|
||||
/* reserved, used as a software sentinel */
|
||||
TRB_NONE = 0,
|
||||
/* bulk, interrupt, isoc scatter/gather, and control data stage */
|
||||
TRB_NORMAL = 1,
|
||||
/* setup stage for control transfers */
|
||||
|
@ -997,6 +1013,7 @@ struct xhci_segment {
|
|||
union xhci_trb *trbs;
|
||||
/* private to HCD */
|
||||
struct xhci_segment *next;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
struct xhci_ring {
|
||||
|
@ -1025,11 +1042,14 @@ struct xhci_erst_entry {
|
|||
struct xhci_erst {
|
||||
struct xhci_erst_entry *entries;
|
||||
unsigned int num_entries;
|
||||
/* xhci->event_ring keeps track of segment dma addresses */
|
||||
dma_addr_t erst_dma_addr;
|
||||
/* Num entries the ERST can contain */
|
||||
unsigned int erst_size;
|
||||
};
|
||||
|
||||
struct xhci_scratchpad {
|
||||
void *scratchpad;
|
||||
u64 *sp_array;
|
||||
};
|
||||
|
||||
|
@ -1216,6 +1236,7 @@ struct xhci_ctrl {
|
|||
struct xhci_virt_device *devs[MAX_HC_SLOTS];
|
||||
int rootdev;
|
||||
u16 hci_version;
|
||||
int page_size;
|
||||
u32 quirks;
|
||||
#define XHCI_MTK_HOST BIT(0)
|
||||
};
|
||||
|
@ -1226,7 +1247,7 @@ struct xhci_ctrl {
|
|||
#define xhci_to_dev(_ctrl) NULL
|
||||
#endif
|
||||
|
||||
unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb);
|
||||
dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb);
|
||||
struct xhci_input_control_ctx
|
||||
*xhci_get_input_control_ctx(struct xhci_container_ctx *ctx);
|
||||
struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_ctrl *ctrl,
|
||||
|
@ -1243,12 +1264,18 @@ void xhci_slot_copy(struct xhci_ctrl *ctrl,
|
|||
struct xhci_container_ctx *out_ctx);
|
||||
void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
|
||||
struct usb_device *udev, int hop_portnr);
|
||||
void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr,
|
||||
void xhci_queue_command(struct xhci_ctrl *ctrl, dma_addr_t addr,
|
||||
u32 slot_id, u32 ep_index, trb_type cmd);
|
||||
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);
|
||||
void xhci_acknowledge_event(struct xhci_ctrl *ctrl);
|
||||
union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected);
|
||||
union xhci_trb *xhci_wait_for_event_timeout(struct xhci_ctrl *ctrl, trb_type expected,
|
||||
unsigned long timeout);
|
||||
int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
|
||||
int length, void *buffer);
|
||||
int xhci_intr_tx(struct usb_device *udev, unsigned long pipe,
|
||||
int length, void *buffer, bool nonblock);
|
||||
int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
||||
struct devrequest *req, int length, void *buffer);
|
||||
int xhci_check_maxpacket(struct usb_device *udev);
|
||||
|
@ -1258,6 +1285,8 @@ void xhci_cleanup(struct xhci_ctrl *ctrl);
|
|||
struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs,
|
||||
bool link_trbs);
|
||||
int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id);
|
||||
void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_ctrl *ctrl,
|
||||
struct usb_device *udev);
|
||||
int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
|
||||
struct xhci_hcor *hcor);
|
||||
|
||||
|
@ -1284,14 +1313,22 @@ extern struct dm_usb_ops xhci_usb_ops;
|
|||
|
||||
struct xhci_ctrl *xhci_get_ctrl(struct usb_device *udev);
|
||||
|
||||
static inline dma_addr_t xhci_virt_to_bus(struct xhci_ctrl *ctrl, void *addr)
|
||||
static inline dma_addr_t xhci_dma_map(struct xhci_ctrl *ctrl, void *addr,
|
||||
size_t size)
|
||||
{
|
||||
#if CONFIG_IS_ENABLED(IOMMU)
|
||||
return dev_iommu_dma_map(xhci_to_dev(ctrl), addr, size);
|
||||
#else
|
||||
return dev_phys_to_bus(xhci_to_dev(ctrl), virt_to_phys(addr));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void *xhci_bus_to_virt(struct xhci_ctrl *ctrl, dma_addr_t addr)
|
||||
static inline void xhci_dma_unmap(struct xhci_ctrl *ctrl, dma_addr_t addr,
|
||||
size_t size)
|
||||
{
|
||||
return phys_to_virt(dev_bus_to_phys(xhci_to_dev(ctrl), addr));
|
||||
#if CONFIG_IS_ENABLED(IOMMU)
|
||||
dev_iommu_dma_unmap(xhci_to_dev(ctrl), addr, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* HOST_XHCI_H_ */
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
* However, if CONFIG_IP_DEFRAG is set, a bigger value could be used. In any
|
||||
* case, most NFS servers are optimized for a power of 2.
|
||||
*/
|
||||
#define NFS_READ_SIZE 1024 /* biggest power of two that fits Ether frame */
|
||||
#define NFS_READ_SIZE (32*1024) /* biggest power of two that fits Ether frame */
|
||||
#define NFS_MAX_ATTRS 26
|
||||
|
||||
/* Values for Accept State flag on RPC answers (See: rfc1831) */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue