Compare commits

..

6 commits

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

View file

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

View file

@ -13,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

View file

@ -857,6 +857,10 @@
};
};
shutdown_charging: charging {
compatible = "k1,shutdown-charging";
status = "disabled";
};
};
binman: binman {

View file

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

View file

@ -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>;

View file

@ -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";
};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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";
};
};
};

View file

@ -6,7 +6,7 @@ bootdelay=0
baudrate=115200
loglevel=8
stderr=serial
stdin=serial,usbkbd
stdin=serial,usbkbd,usbkbd1
stdout=serial
workqueue.default_affinity_scope=system
@ -45,11 +45,12 @@ set_nor_root=run get_rootfs_env; run set_rootfs_env;
//ethaddr=fe:fe:fe:22:22:01
//eth1addr=fe:fe:fe:22:22:02
ipaddr=10.0.92.100
ipaddr=
netmask=255.255.255.0
serverip=10.0.92.134
serverip=10.0.92.148
gatewayip=10.0.92.1
net_data_path=net_flash_file/net_flash_file/
mac_mapping_file=/home/it/nfs/bianbu/mac_mapping.txt
preboot=
ramdisk_size=-
@ -65,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"

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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

View file

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

View file

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

View file

@ -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)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

7
env/Kconfig vendored
View file

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

View file

@ -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" \

View file

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

View file

@ -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 \

View file

@ -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;

View file

@ -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_ */

View file

@ -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) */