Nothing really major here, some rework of the SPL PMIC drivers, adding
support for the AXP717 on the way, which is showing up on newer boards
now, most prominently some Anbernic handheld gaming devices.  The rest
is enabling Ethernet and SPI boot on the Allwinner V3s SoC, plus two
fixes.  This also updates the "traditional U-Boot" DTs to that of kernel
v6.9.  I will look into upgrading some SoCs to dts/upstream in the
coming cycle, though this will not cover all SoCs for now, as we carry
some non-mainline fix to improve compatibility with older kernels. Will
see how it goes, but for now we stick with the "old way".

The branch survived the gitlab CI run, and Linux boot testing on some
selected boards.
This commit is contained in:
Tom Rini
2024-07-16 10:20:14 -06:00
28 changed files with 1026 additions and 246 deletions

View File

@@ -291,6 +291,8 @@
};
&spdif {
pinctrl-names = "default";
pinctrl-0 = <&spdif_tx_pin>;
status = "okay";
};

View File

@@ -166,6 +166,8 @@
};
&spdif {
pinctrl-names = "default";
pinctrl-0 = <&spdif_tx_pin>;
status = "okay";
};

View File

@@ -405,6 +405,7 @@
function = "spi1";
};
/omit-if-no-ref/
spdif_tx_pin: spdif-tx-pin {
pins = "PH7";
function = "spdif";
@@ -654,10 +655,8 @@
clocks = <&ccu CLK_BUS_SPDIF>, <&ccu CLK_SPDIF>;
clock-names = "apb", "spdif";
resets = <&ccu RST_BUS_SPDIF>;
dmas = <&dma 2>;
dma-names = "tx";
pinctrl-names = "default";
pinctrl-0 = <&spdif_tx_pin>;
dmas = <&dma 2>, <&dma 2>;
dma-names = "rx", "tx";
status = "disabled";
};

View File

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: (GPL-2.0+ or MIT)
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2023 Martin Botka <martin.botka@somainline.org>.
*/

View File

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: (GPL-2.0+ or MIT)
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2023 Martin Botka <martin.botka@somainline.org>.
*/
@@ -93,7 +93,7 @@
interrupt-controller;
#interrupt-cells = <1>;
regulators{
regulators {
reg_dcdc1: dcdc1 {
regulator-name = "vdd-gpu-sys";
regulator-min-microvolt = <810000>;

View File

@@ -1,4 +1,4 @@
// SPDX-License-Identifier: (GPL-2.0+ or MIT)
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2023 Martin Botka <martin@biqu3d.com>.
*/

View File

@@ -9,6 +9,7 @@
#include <dt-bindings/clock/sun6i-rtc.h>
#include <dt-bindings/reset/sun50i-h616-ccu.h>
#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
#include <dt-bindings/thermal/thermal.h>
/ {
interrupt-parent = <&gic>;
@@ -133,11 +134,28 @@
#reset-cells = <1>;
};
dma: dma-controller@3002000 {
compatible = "allwinner,sun50i-h616-dma",
"allwinner,sun50i-a100-dma";
reg = <0x03002000 0x1000>;
interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
clock-names = "bus", "mbus";
dma-channels = <16>;
dma-requests = <49>;
resets = <&ccu RST_BUS_DMA>;
#dma-cells = <1>;
};
sid: efuse@3006000 {
compatible = "allwinner,sun50i-h616-sid", "allwinner,sun50i-a64-sid";
reg = <0x03006000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
ths_calibration: thermal-sensor-calibration@14 {
reg = <0x14 0x8>;
};
};
watchdog: watchdog@30090a0 {
@@ -240,6 +258,11 @@
function = "spi1";
};
spdif_tx_pin: spdif-tx-pin {
pins = "PH4";
function = "spdif";
};
uart0_ph_pins: uart0-ph-pins {
pins = "PH0", "PH1";
function = "uart0";
@@ -256,6 +279,12 @@
pins = "PG8", "PG9";
function = "uart1";
};
/omit-if-no-ref/
x32clk_fanout_pin: x32clk-fanout-pin {
pins = "PG10";
function = "clock";
};
};
gic: interrupt-controller@3021000 {
@@ -339,6 +368,8 @@
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&ccu CLK_BUS_UART0>;
dmas = <&dma 14>, <&dma 14>;
dma-names = "tx", "rx";
resets = <&ccu RST_BUS_UART0>;
status = "disabled";
};
@@ -350,6 +381,8 @@
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&ccu CLK_BUS_UART1>;
dmas = <&dma 15>, <&dma 15>;
dma-names = "tx", "rx";
resets = <&ccu RST_BUS_UART1>;
status = "disabled";
};
@@ -361,6 +394,8 @@
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&ccu CLK_BUS_UART2>;
dmas = <&dma 16>, <&dma 16>;
dma-names = "tx", "rx";
resets = <&ccu RST_BUS_UART2>;
status = "disabled";
};
@@ -372,6 +407,8 @@
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&ccu CLK_BUS_UART3>;
dmas = <&dma 17>, <&dma 17>;
dma-names = "tx", "rx";
resets = <&ccu RST_BUS_UART3>;
status = "disabled";
};
@@ -383,6 +420,8 @@
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&ccu CLK_BUS_UART4>;
dmas = <&dma 18>, <&dma 18>;
dma-names = "tx", "rx";
resets = <&ccu RST_BUS_UART4>;
status = "disabled";
};
@@ -394,6 +433,8 @@
reg-shift = <2>;
reg-io-width = <4>;
clocks = <&ccu CLK_BUS_UART5>;
dmas = <&dma 19>, <&dma 19>;
dma-names = "tx", "rx";
resets = <&ccu RST_BUS_UART5>;
status = "disabled";
};
@@ -405,6 +446,8 @@
reg = <0x05002000 0x400>;
interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_I2C0>;
dmas = <&dma 43>, <&dma 43>;
dma-names = "rx", "tx";
resets = <&ccu RST_BUS_I2C0>;
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
@@ -420,6 +463,8 @@
reg = <0x05002400 0x400>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_I2C1>;
dmas = <&dma 44>, <&dma 44>;
dma-names = "rx", "tx";
resets = <&ccu RST_BUS_I2C1>;
status = "disabled";
#address-cells = <1>;
@@ -433,6 +478,8 @@
reg = <0x05002800 0x400>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_I2C2>;
dmas = <&dma 45>, <&dma 45>;
dma-names = "rx", "tx";
resets = <&ccu RST_BUS_I2C2>;
status = "disabled";
#address-cells = <1>;
@@ -446,6 +493,8 @@
reg = <0x05002c00 0x400>;
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_I2C3>;
dmas = <&dma 46>, <&dma 46>;
dma-names = "rx", "tx";
resets = <&ccu RST_BUS_I2C3>;
status = "disabled";
#address-cells = <1>;
@@ -459,6 +508,8 @@
reg = <0x05003000 0x400>;
interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_I2C4>;
dmas = <&dma 47>, <&dma 47>;
dma-names = "rx", "tx";
resets = <&ccu RST_BUS_I2C4>;
status = "disabled";
#address-cells = <1>;
@@ -472,6 +523,8 @@
interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
clock-names = "ahb", "mod";
dmas = <&dma 22>, <&dma 22>;
dma-names = "rx", "tx";
resets = <&ccu RST_BUS_SPI0>;
status = "disabled";
#address-cells = <1>;
@@ -485,6 +538,8 @@
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
clock-names = "ahb", "mod";
dmas = <&dma 23>, <&dma 23>;
dma-names = "rx", "tx";
resets = <&ccu RST_BUS_SPI1>;
status = "disabled";
#address-cells = <1>;
@@ -511,6 +566,34 @@
};
};
spdif: spdif@5093000 {
compatible = "allwinner,sun50i-h616-spdif";
reg = <0x05093000 0x400>;
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_SPDIF>, <&ccu CLK_SPDIF>;
clock-names = "apb", "spdif";
resets = <&ccu RST_BUS_SPDIF>;
dmas = <&dma 2>;
dma-names = "tx";
pinctrl-names = "default";
pinctrl-0 = <&spdif_tx_pin>;
#sound-dai-cells = <0>;
status = "disabled";
};
ths: thermal-sensor@5070400 {
compatible = "allwinner,sun50i-h616-ths";
reg = <0x05070400 0x400>;
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_THS>;
clock-names = "bus";
resets = <&ccu RST_BUS_THS>;
nvmem-cells = <&ths_calibration>;
nvmem-cell-names = "calibration";
allwinner,sram = <&syscon>;
#thermal-sensor-cells = <1>;
};
usbotg: usb@5100000 {
compatible = "allwinner,sun50i-h616-musb",
"allwinner,sun8i-h3-musb";
@@ -734,6 +817,8 @@
reg = <0x07081400 0x400>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&r_ccu CLK_R_APB2_I2C>;
dmas = <&dma 48>, <&dma 48>;
dma-names = "rx", "tx";
resets = <&r_ccu RST_R_APB2_I2C>;
status = "disabled";
#address-cells = <1>;
@@ -755,4 +840,74 @@
#size-cells = <0>;
};
};
thermal-zones {
cpu-thermal {
polling-delay-passive = <500>;
polling-delay = <1000>;
thermal-sensors = <&ths 2>;
sustainable-power = <1000>;
trips {
cpu_threshold: cpu-trip-0 {
temperature = <60000>;
type = "passive";
hysteresis = <0>;
};
cpu_target: cpu-trip-1 {
temperature = <70000>;
type = "passive";
hysteresis = <0>;
};
cpu_critical: cpu-trip-2 {
temperature = <110000>;
type = "critical";
hysteresis = <0>;
};
};
};
gpu-thermal {
polling-delay-passive = <500>;
polling-delay = <1000>;
thermal-sensors = <&ths 0>;
sustainable-power = <1100>;
trips {
gpu_temp_critical: gpu-trip-0 {
temperature = <110000>;
type = "critical";
hysteresis = <0>;
};
};
};
ve-thermal {
polling-delay-passive = <0>;
polling-delay = <0>;
thermal-sensors = <&ths 1>;
trips {
ve_temp_critical: ve-trip-0 {
temperature = <110000>;
type = "critical";
hysteresis = <0>;
};
};
};
ddr-thermal {
polling-delay-passive = <0>;
polling-delay = <0>;
thermal-sensors = <&ths 3>;
trips {
ddr_temp_critical: ddr-trip-0 {
temperature = <110000>;
type = "critical";
hysteresis = <0>;
};
};
};
};
};

View File

@@ -0,0 +1,75 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) Jisheng Zhang <jszhang@kernel.org>
*/
#include "sun50i-h616.dtsi"
&mmc2 {
pinctrl-names = "default";
pinctrl-0 = <&mmc2_pins>;
vmmc-supply = <&reg_dldo1>;
vqmmc-supply = <&reg_aldo1>;
bus-width = <8>;
non-removable;
cap-mmc-hw-reset;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
status = "okay";
};
&r_i2c {
status = "okay";
axp313: pmic@36 {
compatible = "x-powers,axp313a";
reg = <0x36>;
#interrupt-cells = <1>;
interrupt-controller;
regulators {
reg_aldo1: aldo1 {
regulator-always-on;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-name = "vcc-1v8-pll";
};
reg_dldo1: dldo1 {
regulator-always-on;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "vcc-3v3-io";
};
reg_dcdc1: dcdc1 {
regulator-always-on;
regulator-min-microvolt = <810000>;
regulator-max-microvolt = <990000>;
regulator-name = "vdd-gpu-sys";
};
reg_dcdc2: dcdc2 {
regulator-always-on;
regulator-min-microvolt = <810000>;
regulator-max-microvolt = <1100000>;
regulator-name = "vdd-cpu";
};
reg_dcdc3: dcdc3 {
regulator-always-on;
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1100000>;
regulator-name = "vdd-dram";
};
};
};
};
&pio {
vcc-pc-supply = <&reg_dldo1>;
vcc-pf-supply = <&reg_dldo1>;
vcc-pg-supply = <&reg_aldo1>;
vcc-ph-supply = <&reg_dldo1>;
vcc-pi-supply = <&reg_dldo1>;
};

View File

@@ -0,0 +1,144 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) Jisheng Zhang <jszhang@kernel.org>
*/
/dts-v1/;
#include "sun50i-h618-longan-module-3h.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/leds/common.h>
/ {
model = "Sipeed Longan Pi 3H";
compatible = "sipeed,longan-pi-3h", "sipeed,longan-module-3h", "allwinner,sun50i-h618";
aliases {
ethernet0 = &emac0;
serial0 = &uart0;
};
chosen {
stdout-path = "serial0:115200n8";
};
leds {
compatible = "gpio-leds";
led-0 {
color = <LED_COLOR_ID_ORANGE>;
function = LED_FUNCTION_INDICATOR;
function-enumerator = <0>;
gpios = <&pio 6 2 GPIO_ACTIVE_LOW>; /* PG2 */
};
led-1 {
color = <LED_COLOR_ID_ORANGE>;
function = LED_FUNCTION_INDICATOR;
function-enumerator = <1>;
gpios = <&pio 6 4 GPIO_ACTIVE_LOW>; /* PG4 */
};
};
reg_vcc5v: regulator-vcc5v {
/* board wide 5V supply directly from the USB-C socket */
compatible = "regulator-fixed";
regulator-name = "vcc-5v";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
reg_vcc3v3: regulator-vcc3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc-3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
vin-supply = <&reg_vcc5v>;
};
};
&axp313 {
vin1-supply = <&reg_vcc5v>;
vin2-supply = <&reg_vcc5v>;
vin3-supply = <&reg_vcc5v>;
};
&ehci1 {
status = "okay";
};
&ohci1 {
status = "okay";
};
&ehci2 {
status = "okay";
};
&ohci2 {
status = "okay";
};
/* WiFi & BT combo module is connected to this Host */
&ehci3 {
status = "okay";
};
&ohci3 {
status = "okay";
};
&emac0 {
pinctrl-names = "default";
pinctrl-0 = <&ext_rgmii_pins>;
phy-mode = "rgmii";
phy-handle = <&ext_rgmii_phy>;
allwinner,rx-delay-ps = <3100>;
allwinner,tx-delay-ps = <700>;
phy-supply = <&reg_vcc3v3>;
status = "okay";
};
&mdio0 {
ext_rgmii_phy: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
};
};
&mmc0 {
bus-width = <4>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
vmmc-supply = <&reg_vcc3v3>;
status = "okay";
};
&uart0 {
status = "okay";
};
&usbotg {
/*
* PHY0 pins are connected to a USB-C socket, but a role switch
* is not implemented: both CC pins are pulled to GND.
* The VBUS pins power the device, so a fixed peripheral mode
* is the best choice.
* The board can be powered via GPIOs, in this case port0 *can*
* act as a host (with a cable/adapter ignoring CC), as VBUS is
* then provided by the GPIOs. Any user of this setup would
* need to adjust the DT accordingly: dr_mode set to "host",
* enabling OHCI0 and EHCI0.
*/
dr_mode = "peripheral";
status = "okay";
};
&usbphy {
usb1_vbus-supply = <&reg_vcc5v>;
usb2_vbus-supply = <&reg_vcc5v>;
status = "okay";
};

View File

@@ -15,6 +15,7 @@
compatible = "transpeed,8k618-t", "allwinner,sun50i-h618";
aliases {
ethernet1 = &sdio_wifi;
serial0 = &uart0;
};
@@ -39,6 +40,15 @@
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
clocks = <&rtc CLK_OSC32K_FANOUT>;
clock-names = "ext_clock";
pinctrl-0 = <&x32clk_fanout_pin>;
pinctrl-names = "default";
reset-gpios = <&pio 6 18 GPIO_ACTIVE_LOW>; /* PG18 */
};
};
&ehci0 {
@@ -60,6 +70,19 @@
status = "okay";
};
&mmc1 {
vmmc-supply = <&reg_dldo1>;
vqmmc-supply = <&reg_aldo1>;
mmc-pwrseq = <&wifi_pwrseq>;
bus-width = <4>;
non-removable;
status = "okay";
sdio_wifi: wifi@1 {
reg = <1>;
};
};
&mmc2 {
vmmc-supply = <&reg_dldo1>;
vqmmc-supply = <&reg_aldo1>;

View File

@@ -0,0 +1,356 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
// Copyright (c) 2023 ARM Ltd.
/dts-v1/;
#include "sun50i-a64.dtsi"
#include "sun50i-a64-cpu-opp.dtsi"
#include <dt-bindings/gpio/gpio.h>
/ {
model = "Remix Mini PC";
compatible = "jide,remix-mini-pc", "allwinner,sun50i-h64",
"allwinner,sun50i-a64";
aliases {
ethernet1 = &rtl8723bs;
serial0 = &uart0;
};
chosen {
stdout-path = "serial0:115200n8";
};
hdmi-connector {
compatible = "hdmi-connector";
type = "a";
port {
hdmi_con_in: endpoint {
remote-endpoint = <&hdmi_out_con>;
};
};
};
reg_vcc5v: regulator-5v {
/* board wide 5V supply directly from the DC input */
compatible = "regulator-fixed";
regulator-name = "vcc-5v";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
post-power-on-delay-ms = <200>;
};
};
&codec {
status = "okay";
};
&codec_analog {
cpvdd-supply = <&reg_eldo1>;
status = "okay";
};
&cpu0 {
cpu-supply = <&reg_dcdc2>;
};
&cpu1 {
cpu-supply = <&reg_dcdc2>;
};
&cpu2 {
cpu-supply = <&reg_dcdc2>;
};
&cpu3 {
cpu-supply = <&reg_dcdc2>;
};
&dai {
status = "okay";
};
&de {
status = "okay";
};
&ehci0 {
status = "okay";
};
&ehci1 {
status = "okay";
};
&hdmi {
hvcc-supply = <&reg_dldo1>;
status = "okay";
};
&hdmi_out {
hdmi_out_con: endpoint {
remote-endpoint = <&hdmi_con_in>;
};
};
/* Connects to the AC200 chip */
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
status = "okay";
};
&i2c0_pins {
bias-pull-up;
};
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
vmmc-supply = <&reg_dcdc1>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
disable-wp;
bus-width = <4>;
status = "okay";
};
&mmc1 {
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
vmmc-supply = <&reg_aldo1>;
vqmmc-supply = <&reg_dldo4>;
mmc-pwrseq = <&wifi_pwrseq>;
bus-width = <4>;
non-removable;
status = "okay";
rtl8723bs: wifi@1 {
reg = <1>;
interrupt-parent = <&r_pio>;
interrupts = <0 3 IRQ_TYPE_LEVEL_LOW>; /* PL3 */
interrupt-names = "host-wake";
};
};
&mmc2 {
pinctrl-names = "default";
pinctrl-0 = <&mmc2_pins>, <&mmc2_ds_pin>;
vmmc-supply = <&reg_dcdc1>;
vqmmc-supply = <&reg_eldo1>;
bus-width = <8>;
non-removable;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
cap-mmc-hw-reset;
status = "okay";
};
&ohci0 {
status = "okay";
};
&ohci1 {
status = "okay";
};
&pio {
vcc-pb-supply = <&reg_dcdc1>;
vcc-pc-supply = <&reg_dcdc1>;
vcc-pd-supply = <&reg_dcdc1>;
vcc-pe-supply = <&reg_dcdc1>;
vcc-pf-supply = <&reg_dcdc1>;
vcc-pg-supply = <&reg_dldo4>;
vcc-ph-supply = <&reg_dcdc1>;
};
&r_ir {
status = "okay";
};
&r_pio {
/*
* We cannot add that supply for now since it would create a circular
* dependency between pinctrl, the regulator and the RSB Bus.
*
* vcc-pl-supply = <&reg_aldo2>;
*/
};
&r_rsb {
status = "okay";
axp803: pmic@3a3 {
compatible = "x-powers,axp803";
reg = <0x3a3>;
interrupt-parent = <&r_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
x-powers,drive-vbus-en;
vin1-supply = <&reg_vcc5v>;
vin2-supply = <&reg_vcc5v>;
vin3-supply = <&reg_vcc5v>;
vin5-supply = <&reg_vcc5v>;
vin6-supply = <&reg_vcc5v>;
aldoin-supply = <&reg_vcc5v>;
dldoin-supply = <&reg_vcc5v>;
eldoin-supply = <&reg_vcc5v>;
fldoin-supply = <&reg_vcc5v>;
drivevbus-supply = <&reg_vcc5v>;
ips-supply = <&reg_vcc5v>;
status = "okay";
};
};
#include "axp803.dtsi"
&ac_power_supply {
status = "okay";
};
&reg_dcdc1 {
regulator-always-on;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "vcc-3v3";
};
&reg_dcdc2 {
regulator-always-on;
regulator-min-microvolt = <1040000>;
regulator-max-microvolt = <1300000>;
regulator-name = "vdd-cpux";
};
/* DCDC3 is polyphased with DCDC2 */
&reg_dcdc5 {
regulator-always-on;
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <1500000>;
regulator-name = "vcc-dram";
};
/* Deviates from the reset default of 1.1V. */
&reg_dcdc6 {
regulator-always-on;
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-name = "vdd-sys";
};
&reg_aldo1 {
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "vcc-wifi";
};
&reg_aldo2 {
/* Specifying R_PIO consumer would create circular dependency. */
regulator-always-on;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "vcc-pl";
};
&reg_aldo3 {
regulator-always-on;
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-name = "vcc-pll-avcc";
};
/* AC200 power supply */
&reg_dldo1 {
regulator-always-on;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "vcc-ave-33";
};
&reg_dldo4 {
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "vcc-wifi-io";
};
&reg_drivevbus {
regulator-name = "usb0-vbus";
status = "okay";
};
&reg_eldo1 {
regulator-always-on;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-name = "vcc-cpvdd-dram-emmc";
};
/* Supplies the arisc management core, needed by TF-A to power off cores. */
&reg_fldo2 {
regulator-always-on;
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1100000>;
regulator-name = "vdd-cpus";
};
&reg_rtc_ldo {
regulator-name = "vcc-rtc";
};
&simplefb_hdmi {
vcc-hdmi-supply = <&reg_dcdc1>;
};
&sound {
simple-audio-card,aux-devs = <&codec_analog>;
simple-audio-card,widgets = "Microphone", "Microphone Jack",
"Headphone", "Headphone Jack";
simple-audio-card,routing =
"Left DAC", "DACL",
"Right DAC", "DACR",
"Headphone Jack", "HP",
"ADCL", "Left ADC",
"ADCR", "Right ADC",
"MIC2", "Microphone Jack";
status = "okay";
};
/* On the (unpopulated) UART pads. */
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pb_pins>;
status = "okay";
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
uart-has-rtscts;
status = "okay";
bluetooth {
compatible = "realtek,rtl8723bs-bt";
enable-gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */
max-speed = <1500000>;
};
};
&usb_otg {
dr_mode = "host";
status = "okay";
};
&usbphy {
usb0_vbus-supply = <&reg_drivevbus>;
usb1_vbus-supply = <&reg_drivevbus>;
status = "okay";
};

View File

@@ -42,6 +42,13 @@
vcc-pg-supply = <&reg_dldo1>;
};
&reg_aldo1 {
regulator-always-on;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "vcc-3v3-tv-usb";
};
&reg_aldo2 {
regulator-always-on;
regulator-min-microvolt = <1800000>;

View File

@@ -1078,7 +1078,7 @@ config SPL_STACK_R_ADDR
config SPL_SPI_SUNXI
bool "Support for SPI Flash on Allwinner SoCs in SPL"
depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6 || MACH_SUNIV || SUNXI_GEN_NCAT2
depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN8I_V3S || SUN50I_GEN_H6 || MACH_SUNIV || SUNXI_GEN_NCAT2
help
Enable support for SPI Flash. This option allows SPL to read from
sunxi SPI Flash. It uses the same method as the boot ROM, so does

View File

@@ -333,7 +333,8 @@ uint32_t sunxi_get_spl_size(void)
* The eGON SPL image can be located at 8KB or at 128KB into an SD card or
* an eMMC device. The boot source has bit 4 set in the latter case.
* By adding 120KB to the normal offset when booting from a "high" location
* we can support both cases.
* we can support both cases. The H616 has the alternative location
* moved up to 256 KB instead of 128KB, so cater for that, too.
* Also U-Boot proper is located at least 32KB after the SPL, but will
* immediately follow the SPL if that is bigger than that.
*/
@@ -349,6 +350,8 @@ unsigned long board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
case SUNXI_BOOTED_FROM_MMC0_HIGH:
case SUNXI_BOOTED_FROM_MMC2_HIGH:
sector += (128 - 8) * 2;
if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
sector += 128 * 2;
break;
}

View File

@@ -19,6 +19,7 @@
#define AXP152_I2C_ADDR 0x30
#define AXP209_I2C_ADDR 0x34
#define AXP717_I2C_ADDR 0x34
#define AXP305_I2C_ADDR 0x36
#define AXP313_I2C_ADDR 0x36
@@ -36,6 +37,8 @@ static int pmic_i2c_address(void)
return AXP305_I2C_ADDR;
if (IS_ENABLED(CONFIG_AXP313_POWER))
return AXP313_I2C_ADDR;
if (IS_ENABLED(CONFIG_AXP717_POWER))
return AXP717_I2C_ADDR;
/* Other AXP2xx and AXP8xx variants */
return AXP209_I2C_ADDR;

View File

@@ -140,7 +140,8 @@ static bool is_sun6i_gen_spi(void)
{
return IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ||
IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2);
IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2) ||
IS_ENABLED(CONFIG_MACH_SUN8I_V3S);
}
static uintptr_t spi0_base_address(void)

View File

@@ -562,7 +562,7 @@ void sunxi_board_init(void)
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER || \
defined CONFIG_AXP313_POWER
defined CONFIG_AXP313_POWER || defined CONFIG_AXP717_POWER
power_failed = axp_init();
if (IS_ENABLED(CONFIG_AXP_DISABLE_BOOT_ON_POWERON) && !power_failed) {

View File

@@ -16,6 +16,7 @@ static struct ccu_clk_gate v3s_gates[] = {
[CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
[CLK_BUS_EMAC] = GATE(0x060, BIT(17)),
[CLK_BUS_SPI0] = GATE(0x060, BIT(20)),
[CLK_BUS_OTG] = GATE(0x060, BIT(24)),
@@ -30,6 +31,8 @@ static struct ccu_clk_gate v3s_gates[] = {
[CLK_BUS_UART1] = GATE(0x06c, BIT(17)),
[CLK_BUS_UART2] = GATE(0x06c, BIT(18)),
[CLK_BUS_EPHY] = GATE(0x070, BIT(0)),
[CLK_SPI0] = GATE(0x0a0, BIT(31)),
[CLK_USB_PHY0] = GATE(0x0cc, BIT(8)),
@@ -44,12 +47,15 @@ static struct ccu_reset v3s_resets[] = {
[RST_BUS_MMC0] = RESET(0x2c0, BIT(8)),
[RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
[RST_BUS_MMC2] = RESET(0x2c0, BIT(10)),
[RST_BUS_EMAC] = RESET(0x2c0, BIT(17)),
[RST_BUS_SPI0] = RESET(0x2c0, BIT(20)),
[RST_BUS_OTG] = RESET(0x2c0, BIT(24)),
[RST_BUS_TCON0] = RESET(0x2c4, BIT(4)),
[RST_BUS_DE] = RESET(0x2c4, BIT(12)),
[RST_BUS_EPHY] = RESET(0x2c8, BIT(2)),
[RST_BUS_I2C0] = RESET(0x2d8, BIT(0)),
[RST_BUS_I2C1] = RESET(0x2d8, BIT(1)),
[RST_BUS_UART0] = RESET(0x2d8, BIT(16)),

View File

@@ -892,6 +892,11 @@ static const struct emac_variant emac_variant_r40 = {
.syscon_offset = 0x164,
};
static const struct emac_variant emac_variant_v3s = {
.syscon_offset = 0x30,
.soc_has_internal_phy = true,
};
static const struct emac_variant emac_variant_a64 = {
.syscon_offset = 0x30,
.support_rmii = true,
@@ -909,6 +914,8 @@ static const struct udevice_id sun8i_emac_eth_ids[] = {
.data = (ulong)&emac_variant_h3 },
{ .compatible = "allwinner,sun8i-r40-gmac",
.data = (ulong)&emac_variant_r40 },
{ .compatible = "allwinner,sun8i-v3s-emac",
.data = (ulong)&emac_variant_v3s },
{ .compatible = "allwinner,sun50i-a64-emac",
.data = (ulong)&emac_variant_a64 },
{ .compatible = "allwinner,sun50i-h6-emac",

View File

@@ -109,6 +109,13 @@ config AXP313_POWER
Select this to enable support for the AXP313 PMIC found on some
H616 boards.
config AXP717_POWER
bool "axp717 pmic support"
select AXP_PMIC_BUS
select CMD_POWEROFF
---help---
Select this to enable support for the AXP717 PMIC found on some boards.
config AXP809_POWER
bool "axp809 pmic support"
depends on MACH_SUN9I
@@ -151,10 +158,11 @@ config AXP_DCDC1_VOLT
config AXP_DCDC2_VOLT
int "axp pmic dcdc2 voltage"
depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313_POWER
depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313_POWER || AXP717_POWER
default 900 if AXP818_POWER
default 1400 if AXP152_POWER || AXP209_POWER
default 1000 if AXP313_POWER
default 1000 if AXP717_POWER
default 1200 if MACH_SUN6I
default 1100 if MACH_SUN8I
default 0 if MACH_SUN9I
@@ -167,11 +175,11 @@ config AXP_DCDC2_VOLT
On A80 boards dcdc2 powers the GPU and can be left off.
On A83T boards dcdc2 is used for VDD-CPUA(cluster 0) and should be 0.9V.
On R40 boards dcdc2 is VDD-CPU and should be 1.1V
On boards using the AXP313 it's often VDD-CPU.
On boards using the AXP313 or AXP717 it's often VDD-CPU.
config AXP_DCDC3_VOLT
int "axp pmic dcdc3 voltage"
depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313_POWER
depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313_POWER || AXP717_POWER
default 900 if AXP809_POWER || AXP818_POWER
default 1500 if AXP152_POWER
default 1250 if AXP209_POWER
@@ -188,7 +196,8 @@ config AXP_DCDC3_VOLT
On A80 boards dcdc3 is used for VDD-CPUA(cluster 0) and should be 0.9V.
On A83T boards dcdc3 is used for VDD-CPUB(cluster 1) and should be 0.9V.
On R40 boards dcdc3 is VDD-SYS and VDD-GPU and should be 1.1V.
On boards using the AXP313 it's often VDD-DRAM and should be 1.1V for LPDDR4.
On boards using the AXP313 or AXP717 it's often VDD-DRAM and should
be 1.1V for LPDDR4.
config AXP_DCDC4_VOLT
int "axp pmic dcdc4 voltage"

View File

@@ -8,13 +8,16 @@ obj-$(CONFIG_$(SPL_TPL_)POWER_DOMAIN) += domain/
obj-y += pmic/
obj-y += regulator/
obj-$(CONFIG_AXP221_POWER) += axp221.o
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_AXP152_POWER) += axp152.o
obj-$(CONFIG_AXP209_POWER) += axp209.o
obj-$(CONFIG_AXP221_POWER) += axp221.o
obj-$(CONFIG_AXP305_POWER) += axp305.o
obj-$(CONFIG_AXP313_POWER) += axp313.o
obj-$(CONFIG_AXP305_POWER) += axp_spl.o
obj-$(CONFIG_AXP313_POWER) += axp_spl.o
obj-$(CONFIG_AXP717_POWER) += axp_spl.o
obj-$(CONFIG_AXP809_POWER) += axp809.o
obj-$(CONFIG_AXP818_POWER) += axp818.o
endif
obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o
obj-$(CONFIG_SY8106A_POWER) += sy8106a.o
obj-$(CONFIG_TPS6586X_POWER) += tps6586x.o

View File

@@ -1,82 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* AXP305 driver
*
* (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
*
* Based on axp221.c
* (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
* (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
*/
#include <command.h>
#include <errno.h>
#include <asm/arch/pmic_bus.h>
#include <axp_pmic.h>
#define AXP305_DCDC4_1600MV_OFFSET 46
static u8 axp305_mvolt_to_cfg(int mvolt, int min, int max, int div)
{
if (mvolt < min)
mvolt = min;
else if (mvolt > max)
mvolt = max;
return (mvolt - min) / div;
}
int axp_set_dcdc4(unsigned int mvolt)
{
int ret;
u8 cfg;
if (mvolt >= 1600)
cfg = AXP305_DCDC4_1600MV_OFFSET +
axp305_mvolt_to_cfg(mvolt, 1600, 3300, 100);
else
cfg = axp305_mvolt_to_cfg(mvolt, 600, 1500, 20);
if (mvolt == 0)
return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
AXP305_OUTPUT_CTRL1_DCDCD_EN);
ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
if (ret)
return ret;
return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
AXP305_OUTPUT_CTRL1_DCDCD_EN);
}
int axp_init(void)
{
u8 axp_chip_id;
int ret;
ret = pmic_bus_init();
if (ret)
return ret;
ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
if (ret)
return ret;
if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x40)
return -ENODEV;
return ret;
}
#if !CONFIG_IS_ENABLED(ARM_PSCI_FW) && !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF)
int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
pmic_bus_write(AXP305_SHUTDOWN, AXP305_POWEROFF);
/* infinite loop during shutdown */
while (1) {}
/* not reached */
return 0;
}
#endif

View File

@@ -1,133 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* AXP313(a) driver
*
* (C) Copyright 2023 Arm Ltd.
*
* Based on axp305.c
* (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
* (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
* (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
*/
#include <command.h>
#include <errno.h>
#include <asm/arch/pmic_bus.h>
#include <axp_pmic.h>
enum axp313_reg {
AXP313_CHIP_VERSION = 0x03,
AXP313_OUTPUT_CTRL = 0x10,
AXP313_DCDC1_CTRL = 0x13,
AXP313_SHUTDOWN = 0x1a,
};
#define AXP313_CHIP_VERSION_MASK 0xcf
#define AXP313_CHIP_VERSION_AXP1530 0x48
#define AXP313_CHIP_VERSION_AXP313A 0x4b
#define AXP313_CHIP_VERSION_AXP313B 0x4c
#define AXP313_DCDC_SPLIT_OFFSET 71
#define AXP313_DCDC_SPLIT_MVOLT 1200
#define AXP313_POWEROFF BIT(7)
static u8 mvolt_to_cfg(int mvolt, int min, int max, int div)
{
if (mvolt < min)
mvolt = min;
else if (mvolt > max)
mvolt = max;
return (mvolt - min) / div;
}
static int axp_set_dcdc(int dcdc_num, unsigned int mvolt)
{
int ret;
u8 cfg, enable_mask = 1U << (dcdc_num - 1);
int volt_reg = AXP313_DCDC1_CTRL + dcdc_num - 1;
int max_mV;
switch (dcdc_num) {
case 1:
case 2:
max_mV = 1540;
break;
case 3:
/*
* The manual defines a different split point, but tests
* show that it's the same 1200mV as for DCDC1/2.
*/
max_mV = 1840;
break;
default:
return -EINVAL;
}
if (mvolt > AXP313_DCDC_SPLIT_MVOLT)
cfg = AXP313_DCDC_SPLIT_OFFSET + mvolt_to_cfg(mvolt,
AXP313_DCDC_SPLIT_MVOLT + 20, max_mV, 20);
else
cfg = mvolt_to_cfg(mvolt, 500, AXP313_DCDC_SPLIT_MVOLT, 10);
if (mvolt == 0)
return pmic_bus_clrbits(AXP313_OUTPUT_CTRL, enable_mask);
debug("DCDC%d: writing 0x%x to reg 0x%x\n", dcdc_num, cfg, volt_reg);
ret = pmic_bus_write(volt_reg, cfg);
if (ret)
return ret;
return pmic_bus_setbits(AXP313_OUTPUT_CTRL, enable_mask);
}
int axp_set_dcdc2(unsigned int mvolt)
{
return axp_set_dcdc(2, mvolt);
}
int axp_set_dcdc3(unsigned int mvolt)
{
return axp_set_dcdc(3, mvolt);
}
int axp_init(void)
{
u8 axp_chip_id;
int ret;
ret = pmic_bus_init();
if (ret)
return ret;
ret = pmic_bus_read(AXP313_CHIP_VERSION, &axp_chip_id);
if (ret)
return ret;
axp_chip_id &= AXP313_CHIP_VERSION_MASK;
switch (axp_chip_id) {
case AXP313_CHIP_VERSION_AXP1530:
case AXP313_CHIP_VERSION_AXP313A:
case AXP313_CHIP_VERSION_AXP313B:
break;
default:
debug("unknown PMIC: 0x%x\n", axp_chip_id);
return -EINVAL;
}
return ret;
}
#if !CONFIG_IS_ENABLED(ARM_PSCI_FW) && !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF)
int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
pmic_bus_write(AXP313_SHUTDOWN, AXP313_POWEROFF);
/* infinite loop during shutdown */
while (1) {}
/* not reached */
return 0;
}
#endif

173
drivers/power/axp_spl.c Normal file
View File

@@ -0,0 +1,173 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* AXP PMIC SPL driver
* (C) Copyright 2024 Arm Ltd.
*/
#include <errno.h>
#include <linux/types.h>
#include <asm/arch/pmic_bus.h>
#include <axp_pmic.h>
struct axp_reg_desc_spl {
u8 enable_reg;
u8 enable_mask;
u8 volt_reg;
u8 volt_mask;
u16 min_mV;
u16 max_mV;
u8 step_mV;
u8 split;
};
#define NA 0xff
#if defined(CONFIG_AXP717_POWER) /* AXP717 */
static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
{ 0x80, BIT(0), 0x83, 0x7f, 500, 1540, 10, 70 },
{ 0x80, BIT(1), 0x84, 0x7f, 500, 1540, 10, 70 },
{ 0x80, BIT(2), 0x85, 0x7f, 500, 1840, 10, 70 },
};
#define AXP_CHIP_VERSION 0x0
#define AXP_CHIP_VERSION_MASK 0x0
#define AXP_CHIP_ID 0x0
#define AXP_SHUTDOWN_REG 0x27
#define AXP_SHUTDOWN_MASK BIT(0)
#elif defined(CONFIG_AXP313_POWER) /* AXP313 */
static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
{ 0x10, BIT(0), 0x13, 0x7f, 500, 1540, 10, 70 },
{ 0x10, BIT(1), 0x14, 0x7f, 500, 1540, 10, 70 },
{ 0x10, BIT(2), 0x15, 0x7f, 500, 1840, 10, 70 },
};
#define AXP_CHIP_VERSION 0x3
#define AXP_CHIP_VERSION_MASK 0xc8
#define AXP_CHIP_ID 0x48
#define AXP_SHUTDOWN_REG 0x1a
#define AXP_SHUTDOWN_MASK BIT(7)
#elif defined(CONFIG_AXP305_POWER) /* AXP305 */
static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
{ 0x10, BIT(0), 0x12, 0x7f, 600, 1520, 10, 50 },
{ 0x10, BIT(1), 0x13, 0x1f, 1000, 2550, 50, NA },
{ 0x10, BIT(2), 0x14, 0x7f, 600, 1520, 10, 50 },
{ 0x10, BIT(3), 0x15, 0x3f, 600, 1500, 20, NA },
{ 0x10, BIT(4), 0x16, 0x1f, 1100, 3400, 100, NA },
};
#define AXP_CHIP_VERSION 0x3
#define AXP_CHIP_VERSION_MASK 0xcf
#define AXP_CHIP_ID 0x40
#define AXP_SHUTDOWN_REG 0x32
#define AXP_SHUTDOWN_MASK BIT(7)
#else
#error "Please define the regulator registers in axp_spl_regulators[]."
#endif
static u8 axp_mvolt_to_cfg(int mvolt, const struct axp_reg_desc_spl *reg)
{
if (mvolt < reg->min_mV)
mvolt = reg->min_mV;
else if (mvolt > reg->max_mV)
mvolt = reg->max_mV;
mvolt -= reg->min_mV;
/* voltage in the first range ? */
if (mvolt <= reg->split * reg->step_mV)
return mvolt / reg->step_mV;
mvolt -= reg->split * reg->step_mV;
return reg->split + mvolt / (reg->step_mV * 2);
}
static int axp_set_dcdc(int dcdc_num, unsigned int mvolt)
{
const struct axp_reg_desc_spl *reg;
int ret;
if (dcdc_num < 1 || dcdc_num > ARRAY_SIZE(axp_spl_dcdc_regulators))
return -EINVAL;
reg = &axp_spl_dcdc_regulators[dcdc_num - 1];
if (mvolt == 0)
return pmic_bus_clrbits(reg->enable_reg, reg->enable_mask);
ret = pmic_bus_write(reg->volt_reg, axp_mvolt_to_cfg(mvolt, reg));
if (ret)
return ret;
return pmic_bus_setbits(reg->enable_reg, reg->enable_mask);
}
int axp_set_dcdc1(unsigned int mvolt)
{
return axp_set_dcdc(1, mvolt);
}
int axp_set_dcdc2(unsigned int mvolt)
{
return axp_set_dcdc(2, mvolt);
}
int axp_set_dcdc3(unsigned int mvolt)
{
return axp_set_dcdc(3, mvolt);
}
int axp_set_dcdc4(unsigned int mvolt)
{
return axp_set_dcdc(4, mvolt);
}
int axp_set_dcdc5(unsigned int mvolt)
{
return axp_set_dcdc(5, mvolt);
}
int axp_init(void)
{
int ret = pmic_bus_init();
if (ret)
return ret;
if (AXP_CHIP_VERSION_MASK) {
u8 axp_chip_id;
ret = pmic_bus_read(AXP_CHIP_VERSION, &axp_chip_id);
if (ret)
return ret;
if ((axp_chip_id & AXP_CHIP_VERSION_MASK) != AXP_CHIP_ID) {
debug("unknown PMIC: 0x%x\n", axp_chip_id);
return -EINVAL;
}
}
return 0;
}
#if !CONFIG_IS_ENABLED(ARM_PSCI_FW) && !IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF)
int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
pmic_bus_setbits(AXP_SHUTDOWN_REG, AXP_SHUTDOWN_MASK);
/* infinite loop during shutdown */
while (1)
;
/* not reached */
return 0;
}
#endif

View File

@@ -88,6 +88,7 @@ static const struct udevice_id axp_pmic_ids[] = {
{ .compatible = "x-powers,axp221", .data = AXP221_ID },
{ .compatible = "x-powers,axp223", .data = AXP223_ID },
{ .compatible = "x-powers,axp313a", .data = AXP313_ID },
{ .compatible = "x-powers,axp717", .data = AXP717_ID },
{ .compatible = "x-powers,axp803", .data = AXP803_ID },
{ .compatible = "x-powers,axp806", .data = AXP806_ID },
{ .compatible = "x-powers,axp809", .data = AXP809_ID },

View File

@@ -189,6 +189,33 @@ static const struct axp_regulator_plat axp313_regulators[] = {
{ }
};
/*
* The "dcdc2" regulator has another range, beyond 1.54V up to 3.4V, in
* steps of 100mV. We cannot model this easily, but also don't need that,
* since it's typically only used for lower voltages anyway, so just ignore it.
*/
static const struct axp_regulator_plat axp717_regulators[] = {
{ "dcdc1", 0x80, BIT(0), 0x83, 0x7f, 500, 1540, 10, 70 },
{ "dcdc2", 0x80, BIT(1), 0x84, 0x7f, 500, 1540, 10, 70 },
{ "dcdc3", 0x80, BIT(2), 0x85, 0x7f, 500, 1840, 10, 70 },
{ "dcdc4", 0x80, BIT(3), 0x86, 0x7f, 1000, 3700, 100, NA },
{ "aldo1", 0x90, BIT(0), 0x93, 0x1f, 500, 3500, 100, NA },
{ "aldo2", 0x90, BIT(1), 0x94, 0x1f, 500, 3500, 100, NA },
{ "aldo3", 0x90, BIT(2), 0x95, 0x1f, 500, 3500, 100, NA },
{ "aldo4", 0x90, BIT(3), 0x96, 0x1f, 500, 3500, 100, NA },
{ "bldo1", 0x90, BIT(4), 0x97, 0x1f, 500, 3500, 100, NA },
{ "bldo2", 0x90, BIT(5), 0x98, 0x1f, 500, 3500, 100, NA },
{ "bldo3", 0x90, BIT(6), 0x99, 0x1f, 500, 3500, 100, NA },
{ "bldo4", 0x90, BIT(7), 0x9a, 0x1f, 500, 3500, 100, NA },
{ "cldo1", 0x91, BIT(0), 0x9b, 0x1f, 500, 3500, 100, NA },
{ "cldo2", 0x91, BIT(1), 0x9c, 0x1f, 500, 3500, 100, NA },
{ "cldo3", 0x91, BIT(2), 0x9d, 0x1f, 500, 3500, 100, NA },
{ "cldo4", 0x91, BIT(3), 0x9e, 0x1f, 500, 3500, 100, NA },
{"cpusldo",0x91, BIT(4), 0x9f, 0x1f, 500, 1400, 50, NA },
{" boost", 0x19, BIT(4), 0x1e, 0xf0, 4550, 5510, 64, NA },
{ }
};
static const struct axp_regulator_plat axp803_regulators[] = {
{ "dcdc1", 0x10, BIT(0), 0x20, 0x1f, 1600, 3400, 100, NA },
{ "dcdc2", 0x10, BIT(1), 0x21, 0x7f, 500, 1300, 10, 70 },
@@ -291,6 +318,7 @@ static const struct axp_regulator_plat *const axp_regulators[] = {
[AXP221_ID] = axp22x_regulators,
[AXP223_ID] = axp22x_regulators,
[AXP313_ID] = axp313_regulators,
[AXP717_ID] = axp717_regulators,
[AXP803_ID] = axp803_regulators,
[AXP806_ID] = axp806_regulators,
[AXP809_ID] = axp809_regulators,

View File

@@ -135,7 +135,6 @@ struct sun4i_spi_variant {
struct sun4i_spi_plat {
struct sun4i_spi_variant *variant;
u32 base;
u32 max_hz;
};
struct sun4i_spi_priv {
@@ -237,6 +236,13 @@ static void sun4i_spi_set_speed_mode(struct udevice *dev)
unsigned int div;
u32 reg;
/*
* The uclass should take care that this won't happen. But anyway,
* avoid a div-by-zero exception.
*/
if (!priv->freq)
return;
/*
* Setup clock divider.
*
@@ -401,11 +407,10 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
{
struct sun4i_spi_plat *plat = dev_get_plat(dev);
struct sun4i_spi_priv *priv = dev_get_priv(dev);
if (speed > plat->max_hz)
speed = plat->max_hz;
if (speed > SUN4I_SPI_MAX_RATE)
speed = SUN4I_SPI_MAX_RATE;
if (speed < SUN4I_SPI_MIN_RATE)
speed = SUN4I_SPI_MIN_RATE;
@@ -458,7 +463,6 @@ static int sun4i_spi_probe(struct udevice *bus)
priv->variant = plat->variant;
priv->base = plat->base;
priv->freq = plat->max_hz;
return 0;
}
@@ -466,16 +470,9 @@ static int sun4i_spi_probe(struct udevice *bus)
static int sun4i_spi_of_to_plat(struct udevice *bus)
{
struct sun4i_spi_plat *plat = dev_get_plat(bus);
int node = dev_of_offset(bus);
plat->base = dev_read_addr(bus);
plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
"spi-max-frequency",
SUN4I_SPI_DEFAULT_RATE);
if (plat->max_hz > SUN4I_SPI_MAX_RATE)
plat->max_hz = SUN4I_SPI_MAX_RATE;
return 0;
}

View File

@@ -33,6 +33,7 @@ enum {
AXP221_ID,
AXP223_ID,
AXP313_ID,
AXP717_ID,
AXP803_ID,
AXP806_ID,
AXP809_ID,