mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-19 13:48:06 +00:00
airoha: Introduce EN7581 SoC support
Introduce EN7581 SoC support with currently rfb board supported. This is a new 64bit SoC from Airoha that is currently almost fully supported upstream with only the DTS missing. Setting source-only waiting for the full upstream support to be completed. Link: https://github.com/openwrt/openwrt/pull/16730 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
parent
c5f38c1fd0
commit
9131cb44ff
@ -3,8 +3,8 @@ include $(TOPDIR)/rules.mk
|
||||
ARCH:=arm
|
||||
BOARD:=airoha
|
||||
BOARDNAME:=Airoha ARM
|
||||
SUBTARGETS:=en7523
|
||||
FEATURES:=dt squashfs nand ramdisk gpio source-only
|
||||
SUBTARGETS:=en7523 en7581
|
||||
FEATURES:=dt squashfs nand ramdisk gpio
|
||||
|
||||
KERNEL_PATCHVER:=6.6
|
||||
|
||||
|
210
target/linux/airoha/dts/en7581-evb-emmc.dts
Normal file
210
target/linux/airoha/dts/en7581-evb-emmc.dts
Normal file
@ -0,0 +1,210 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
/dts-v1/;
|
||||
|
||||
/* Bootloader installs ATF here */
|
||||
/memreserve/ 0x80000000 0x200000;
|
||||
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include "en7581.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Airoha EN7581 Evaluation Board";
|
||||
compatible = "airoha,en7581-evb", "airoha,en7581";
|
||||
|
||||
aliases {
|
||||
serial0 = &uart1;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,115200 earlycon";
|
||||
stdout-path = "serial0:115200n8";
|
||||
linux,usable-memory-range = <0x0 0x80200000 0x0 0x1fe00000>;
|
||||
};
|
||||
|
||||
memory@80000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x80000000 0x2 0x00000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&en7581_pinctrl {
|
||||
gpio-ranges = <&en7581_pinctrl 0 13 47>;
|
||||
|
||||
mdio_pins: mdio-pins {
|
||||
mux {
|
||||
function = "mdio";
|
||||
groups = "mdio";
|
||||
};
|
||||
|
||||
conf {
|
||||
pins = "gpio2";
|
||||
output-high;
|
||||
};
|
||||
};
|
||||
|
||||
pcie0_rst_pins: pcie0-rst-pins {
|
||||
conf {
|
||||
pins = "pcie_reset0";
|
||||
drive-open-drain = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
pcie1_rst_pins: pcie1-rst-pins {
|
||||
conf {
|
||||
pins = "pcie_reset1";
|
||||
drive-open-drain = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
gswp1_led0_pins: gswp1-led0-pins {
|
||||
mux {
|
||||
function = "phy1_led0";
|
||||
pins = "gpio33";
|
||||
};
|
||||
};
|
||||
|
||||
gswp2_led0_pins: gswp2-led0-pins {
|
||||
mux {
|
||||
function = "phy2_led0";
|
||||
pins = "gpio34";
|
||||
};
|
||||
};
|
||||
|
||||
gswp3_led0_pins: gswp3-led0-pins {
|
||||
mux {
|
||||
function = "phy3_led0";
|
||||
pins = "gpio35";
|
||||
};
|
||||
};
|
||||
|
||||
gswp4_led0_pins: gswp4-led0-pins {
|
||||
mux {
|
||||
function = "phy4_led0";
|
||||
pins = "gpio42";
|
||||
};
|
||||
};
|
||||
|
||||
pwm_gpio18_idx10_pins: pwm-gpio18-idx10-pins {
|
||||
function = "pwm";
|
||||
pins = "gpio18";
|
||||
output-enable;
|
||||
};
|
||||
|
||||
mmc_pins: mmc-pins {
|
||||
mux {
|
||||
function = "emmc";
|
||||
groups = "emmc";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&mmc0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mmc_pins>;
|
||||
status = "okay";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
card@0 {
|
||||
compatible = "mmc-card";
|
||||
reg = <0>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
bootloader@0 {
|
||||
label = "bootloader";
|
||||
reg = <0x00000000 0x00080000>;
|
||||
};
|
||||
|
||||
tclinux@80000 {
|
||||
label = "tclinux";
|
||||
reg = <0x00080000 0x02800000>;
|
||||
};
|
||||
|
||||
tclinux_slave@2880000 {
|
||||
label = "tclinux_slave";
|
||||
reg = <0x02880000 0x02800000>;
|
||||
};
|
||||
|
||||
rootfs_data@5080000 {
|
||||
label = "rootfs_data";
|
||||
reg = <0x5080000 0x00800000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pcie0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pcie0_rst_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pcie1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pcie1_rst_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ð {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gdm1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&switch {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mdio_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy1 {
|
||||
pinctrl-names = "led";
|
||||
pinctrl-0 = <&gswp1_led0_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy1_led0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy2 {
|
||||
pinctrl-names = "led";
|
||||
pinctrl-0 = <&gswp2_led0_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy2_led0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy3 {
|
||||
pinctrl-names = "led";
|
||||
pinctrl-0 = <&gswp3_led0_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy3_led0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy4 {
|
||||
pinctrl-names = "led";
|
||||
pinctrl-0 = <&gswp4_led0_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy4_led0 {
|
||||
status = "okay";
|
||||
};
|
254
target/linux/airoha/dts/en7581-evb.dts
Normal file
254
target/linux/airoha/dts/en7581-evb.dts
Normal file
@ -0,0 +1,254 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
/dts-v1/;
|
||||
|
||||
/* Bootloader installs ATF here */
|
||||
/memreserve/ 0x80000000 0x200000;
|
||||
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include "en7581.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Airoha EN7581 Evaluation Board";
|
||||
compatible = "airoha,en7581-evb", "airoha,en7581";
|
||||
|
||||
aliases {
|
||||
serial0 = &uart1;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,115200 earlycon";
|
||||
stdout-path = "serial0:115200n8";
|
||||
linux,usable-memory-range = <0x0 0x80200000 0x0 0x1fe00000>;
|
||||
};
|
||||
|
||||
memory@80000000 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x80000000 0x2 0x00000000>;
|
||||
};
|
||||
|
||||
gpio-keys-polled {
|
||||
compatible = "gpio-keys-polled";
|
||||
poll-interval = <100>;
|
||||
btn0 {
|
||||
label = "reset";
|
||||
linux,code = <KEY_RESTART>;
|
||||
gpios = <&en7581_pinctrl 0 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
pwmleds {
|
||||
compatible = "pwm-leds";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pwm_gpio18_idx10_pins>;
|
||||
lan4_green {
|
||||
label = "pon:green";
|
||||
pwms = <&en7581_pwm 10 4000000 0>;
|
||||
max-brightness = <255>;
|
||||
active-low;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
pwr_led: led-0 {
|
||||
label = "pwr";
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
function = LED_FUNCTION_POWER;
|
||||
gpios = <&en7581_pinctrl 17 GPIO_ACTIVE_LOW>;
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
los_led: led-2 {
|
||||
label = "los";
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
gpios = <&en7581_pinctrl 19 GPIO_ACTIVE_LOW>;
|
||||
default-state = "on";
|
||||
};
|
||||
|
||||
internet_led: led-3 {
|
||||
label = "internet";
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
gpios = <&en7581_pinctrl 20 GPIO_ACTIVE_LOW>;
|
||||
default-state = "on";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&en7581_pinctrl {
|
||||
gpio-ranges = <&en7581_pinctrl 0 13 47>;
|
||||
|
||||
mdio_pins: mdio-pins {
|
||||
mux {
|
||||
function = "mdio";
|
||||
groups = "mdio";
|
||||
};
|
||||
|
||||
conf {
|
||||
pins = "gpio2";
|
||||
output-high;
|
||||
};
|
||||
};
|
||||
|
||||
pcie0_rst_pins: pcie0-rst-pins {
|
||||
conf {
|
||||
pins = "pcie_reset0";
|
||||
drive-open-drain = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
pcie1_rst_pins: pcie1-rst-pins {
|
||||
conf {
|
||||
pins = "pcie_reset1";
|
||||
drive-open-drain = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
gswp1_led0_pins: gswp1-led0-pins {
|
||||
mux {
|
||||
function = "phy1_led0";
|
||||
pins = "gpio33";
|
||||
};
|
||||
};
|
||||
|
||||
gswp2_led0_pins: gswp2-led0-pins {
|
||||
mux {
|
||||
function = "phy2_led0";
|
||||
pins = "gpio34";
|
||||
};
|
||||
};
|
||||
|
||||
gswp3_led0_pins: gswp3-led0-pins {
|
||||
mux {
|
||||
function = "phy3_led0";
|
||||
pins = "gpio35";
|
||||
};
|
||||
};
|
||||
|
||||
gswp4_led0_pins: gswp4-led0-pins {
|
||||
mux {
|
||||
function = "phy4_led0";
|
||||
pins = "gpio42";
|
||||
};
|
||||
};
|
||||
|
||||
pwm_gpio18_idx10_pins: pwm-gpio18-idx10-pins {
|
||||
function = "pwm";
|
||||
pins = "gpio18";
|
||||
output-enable;
|
||||
};
|
||||
};
|
||||
|
||||
&snfi {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi_nand {
|
||||
partitions {
|
||||
compatible = "airoha,fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
bootloader@0 {
|
||||
label = "bootloader";
|
||||
reg = <0x00000000 0x00080000>;
|
||||
};
|
||||
|
||||
tclinux@80000 {
|
||||
label = "tclinux";
|
||||
compatible = "denx,fit";
|
||||
reg = <0x00080000 0x02800000>;
|
||||
};
|
||||
|
||||
tclinux_slave@2880000 {
|
||||
label = "tclinux_slave";
|
||||
reg = <0x02880000 0x02800000>;
|
||||
};
|
||||
|
||||
rootfs_data@5080000 {
|
||||
label = "rootfs_data";
|
||||
reg = <0x5080000 0x00800000>;
|
||||
};
|
||||
|
||||
art@ffffffff {
|
||||
compatible = "airoha,dynamic-art";
|
||||
label = "art";
|
||||
reg = <0xffffffff 0x00300000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pcie0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pcie0_rst_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pcie1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pcie1_rst_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ð {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gdm1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&switch {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mdio_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy1 {
|
||||
pinctrl-names = "led";
|
||||
pinctrl-0 = <&gswp1_led0_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy1_led0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy2 {
|
||||
pinctrl-names = "led";
|
||||
pinctrl-0 = <&gswp2_led0_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy2_led0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy3 {
|
||||
pinctrl-names = "led";
|
||||
pinctrl-0 = <&gswp3_led0_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy3_led0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy4 {
|
||||
pinctrl-names = "led";
|
||||
pinctrl-0 = <&gswp4_led0_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw_phy4_led0 {
|
||||
status = "okay";
|
||||
};
|
756
target/linux/airoha/dts/en7581.dtsi
Normal file
756
target/linux/airoha/dts/en7581.dtsi
Normal file
@ -0,0 +1,756 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/en7523-clk.h>
|
||||
#include <dt-bindings/reset/airoha,en7581-reset.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/thermal/thermal.h>
|
||||
|
||||
/ {
|
||||
interrupt-parent = <&gic>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
npu-binary@84000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x84000000 0x0 0xa00000>;
|
||||
};
|
||||
|
||||
npu-flag@84b0000 {
|
||||
no-map;
|
||||
reg = <0x0 0x84b00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
npu-pkt@85000000 {
|
||||
no-map;
|
||||
reg = <0x0 0x85000000 0x0 0x1a00000>;
|
||||
};
|
||||
|
||||
npu-phyaddr@86b00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x86b00000 0x0 0x100000>;
|
||||
};
|
||||
|
||||
npu-rxdesc@86d00000 {
|
||||
no-map;
|
||||
reg = <0x0 0x86d00000 0x0 0x100000>;
|
||||
};
|
||||
};
|
||||
|
||||
psci {
|
||||
compatible = "arm,psci-1.0";
|
||||
method = "smc";
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu-map {
|
||||
cluster0 {
|
||||
core0 {
|
||||
cpu = <&cpu0>;
|
||||
};
|
||||
|
||||
core1 {
|
||||
cpu = <&cpu1>;
|
||||
};
|
||||
|
||||
core2 {
|
||||
cpu = <&cpu2>;
|
||||
};
|
||||
|
||||
core3 {
|
||||
cpu = <&cpu3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
cpu0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a53";
|
||||
reg = <0x0>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
enable-method = "psci";
|
||||
clock-frequency = <80000000>;
|
||||
next-level-cache = <&l2>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
cpu1: cpu@1 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a53";
|
||||
reg = <0x1>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
enable-method = "psci";
|
||||
clock-frequency = <80000000>;
|
||||
next-level-cache = <&l2>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
cpu2: cpu@2 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a53";
|
||||
reg = <0x2>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
enable-method = "psci";
|
||||
clock-frequency = <80000000>;
|
||||
next-level-cache = <&l2>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
cpu3: cpu@3 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a53";
|
||||
reg = <0x3>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
enable-method = "psci";
|
||||
clock-frequency = <80000000>;
|
||||
next-level-cache = <&l2>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
l2: l2-cache {
|
||||
compatible = "cache";
|
||||
cache-size = <0x80000>;
|
||||
cache-line-size = <64>;
|
||||
cache-level = <2>;
|
||||
cache-unified;
|
||||
};
|
||||
};
|
||||
|
||||
cpu_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-500000000 {
|
||||
opp-hz = /bits/ 64 <500000000>;
|
||||
};
|
||||
|
||||
opp-550000000 {
|
||||
opp-hz = /bits/ 64 <550000000>;
|
||||
};
|
||||
|
||||
opp-600000000 {
|
||||
opp-hz = /bits/ 64 <600000000>;
|
||||
};
|
||||
|
||||
opp-650000000 {
|
||||
opp-hz = /bits/ 64 <650000000>;
|
||||
};
|
||||
|
||||
opp-7000000000 {
|
||||
opp-hz = /bits/ 64 <700000000>;
|
||||
};
|
||||
|
||||
opp-7500000000 {
|
||||
opp-hz = /bits/ 64 <750000000>;
|
||||
};
|
||||
|
||||
opp-8000000000 {
|
||||
opp-hz = /bits/ 64 <800000000>;
|
||||
};
|
||||
|
||||
opp-8500000000 {
|
||||
opp-hz = /bits/ 64 <850000000>;
|
||||
};
|
||||
|
||||
opp-9000000000 {
|
||||
opp-hz = /bits/ 64 <900000000>;
|
||||
};
|
||||
|
||||
opp-9500000000 {
|
||||
opp-hz = /bits/ 64 <950000000>;
|
||||
};
|
||||
|
||||
opp-10000000000 {
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
};
|
||||
|
||||
opp-10500000000 {
|
||||
opp-hz = /bits/ 64 <1050000000>;
|
||||
};
|
||||
|
||||
opp-11000000000 {
|
||||
opp-hz = /bits/ 64 <1100000000>;
|
||||
};
|
||||
|
||||
opp-11500000000 {
|
||||
opp-hz = /bits/ 64 <1150000000>;
|
||||
};
|
||||
|
||||
opp-12000000000 {
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
};
|
||||
};
|
||||
|
||||
timer {
|
||||
compatible = "arm,armv8-timer";
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
|
||||
<GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
|
||||
<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
|
||||
<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
cpu_thermal: cpu-thermal {
|
||||
polling-delay-passive = <0>;
|
||||
polling-delay = <0>;
|
||||
|
||||
thermal-sensors = <&thermal 0>;
|
||||
|
||||
trips {
|
||||
cpu_hot: cpu-hot {
|
||||
temperature = <95000>;
|
||||
hysteresis = <1000>;
|
||||
type = "hot";
|
||||
};
|
||||
|
||||
cpu-critical {
|
||||
temperature = <110000>;
|
||||
hysteresis = <1000>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map0 {
|
||||
trip = <&cpu_hot>;
|
||||
cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
||||
<&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
||||
<&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
||||
<&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
gic: interrupt-controller@9000000 {
|
||||
compatible = "arm,gic-v3";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0x0 0x09000000 0x0 0x20000>,
|
||||
<0x0 0x09080000 0x0 0x80000>,
|
||||
<0x0 0x09400000 0x0 0x2000>,
|
||||
<0x0 0x09500000 0x0 0x2000>,
|
||||
<0x0 0x09600000 0x0 0x20000>;
|
||||
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
|
||||
};
|
||||
|
||||
uart1: serial@1fbf0000 {
|
||||
compatible = "ns16550";
|
||||
reg = <0x0 0x1fbf0000 0x0 0x30>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <1843200>;
|
||||
};
|
||||
|
||||
watchdog@1fbf0100 {
|
||||
compatible = "airoha,en7581-wdt";
|
||||
reg = <0x0 0x1fbf0100 0x0 0x38>;
|
||||
|
||||
clocks = <&scuclk EN7523_CLK_BUS>;
|
||||
clock-names = "bus";
|
||||
};
|
||||
|
||||
uart2: serial@1fbf0300 {
|
||||
compatible = "airoha,en7523-uart";
|
||||
reg = <0x0 0x1fbf0300 0x0 0x30>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <7372800>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
hsuart3: serial@1fbe1000 {
|
||||
compatible = "airoha,en7523-uart";
|
||||
reg = <0x0 0x1fbe1000 0x0 0x40>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <7372800>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart4: serial@1fbf0600 {
|
||||
compatible = "airoha,en7523-uart";
|
||||
reg = <0x0 0x1fbf0600 0x0 0x30>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <7372800>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart5: serial@1fbf0700 {
|
||||
compatible = "airoha,en7523-uart";
|
||||
reg = <0x0 0x1fbf0700 0x0 0x30>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <7372800>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
chip_scu: syscon@1fa20000 {
|
||||
compatible = "airoha,en7581-chip-scu", "syscon";
|
||||
reg = <0x0 0x1fa20000 0x0 0x388>;
|
||||
};
|
||||
|
||||
syscon@1fbe3400 {
|
||||
compatible = "airoha,en7581-pbus-csr", "syscon";
|
||||
reg = <0x0 0x1fbe3400 0x0 0xff>;
|
||||
};
|
||||
|
||||
scuclk: clock-controller@1fa20000 {
|
||||
compatible = "airoha,en7581-scu";
|
||||
reg = <0x0 0x1fb00000 0x0 0x970>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
rng@1faa1000 {
|
||||
compatible = "airoha,en7581-trng";
|
||||
reg = <0x0 0x1faa1000 0x0 0xc04>;
|
||||
interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
crypto@1e004000 {
|
||||
compatible = "inside-secure,safexcel-eip93ies";
|
||||
reg = <0x0 0x1fb70000 0x0 0x1000>;
|
||||
|
||||
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
thermal: thermal-sensor@1efbd800 {
|
||||
compatible = "airoha,en7581-thermal";
|
||||
reg = <0x0 0x1efbd000 0x0 0xd5c>;
|
||||
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
airoha,chip-scu = <&chip_scu>;
|
||||
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
system-controller@1fbf0200 {
|
||||
compatible = "syscon", "simple-mfd";
|
||||
reg = <0x0 0x1fbf0200 0x0 0xc0>;
|
||||
|
||||
en7581_pinctrl: pinctrl {
|
||||
compatible = "airoha,en7581-pinctrl";
|
||||
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
en7581_pwm: pwm {
|
||||
compatible = "airoha,en7581-pwm";
|
||||
|
||||
#pwm-cells = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
i2cclock: i2cclock@0 {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
|
||||
/* 20 MHz */
|
||||
clock-frequency = <20000000>;
|
||||
};
|
||||
|
||||
i2c0: i2c0@1fbf8000 {
|
||||
compatible = "mediatek,mt7621-i2c";
|
||||
reg = <0x0 0x1fbf8000 0x0 0x100>;
|
||||
|
||||
clocks = <&i2cclock>;
|
||||
|
||||
/* 100 kHz */
|
||||
clock-frequency = <100000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
i2c1: i2c1@1fbf8100 {
|
||||
compatible = "mediatek,mt7621-i2c";
|
||||
reg = <0x0 0x1fbf8100 0x0 0x100>;
|
||||
|
||||
clocks = <&i2cclock>;
|
||||
|
||||
/* 100 kHz */
|
||||
clock-frequency = <100000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
snfi: spi@1fa10000 {
|
||||
compatible = "airoha,en7581-snand";
|
||||
reg = <0x0 0x1fa10000 0x0 0x140>,
|
||||
<0x0 0x1fa11000 0x0 0x160>;
|
||||
|
||||
clocks = <&scuclk EN7523_CLK_SPI>;
|
||||
clock-names = "spi";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
spi_nand: nand@0 {
|
||||
compatible = "spi-nand";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <50000000>;
|
||||
spi-tx-bus-width = <1>;
|
||||
spi-rx-bus-width = <2>;
|
||||
airoha,bmt;
|
||||
};
|
||||
};
|
||||
|
||||
mmc0: mmc@1fa0e000 {
|
||||
compatible = "mediatek,mt7622-mmc";
|
||||
reg = <0x0 0x1fa0e000 0x0 0x1000>,
|
||||
<0x0 0x1fa0c000 0x0 0x60>;
|
||||
interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
|
||||
bus-width = <4>;
|
||||
max-frequency = <52000000>;
|
||||
disable-wp;
|
||||
cap-mmc-highspeed;
|
||||
non-removable;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pciephy: phy@1fa5a000 {
|
||||
compatible = "airoha,en7581-pcie-phy";
|
||||
reg = <0x0 0x1fa5a000 0x0 0xfff>,
|
||||
<0x0 0x1fa5b000 0x0 0xfff>,
|
||||
<0x0 0x1fa5c000 0x0 0xfff>,
|
||||
<0x0 0x1fc10044 0x0 0x4>,
|
||||
<0x0 0x1fc30044 0x0 0x4>,
|
||||
<0x0 0x1fc15030 0x0 0x104>;
|
||||
reg-names = "csr-2l", "pma0", "pma1",
|
||||
"p0-xr-dtime", "p1-xr-dtime",
|
||||
"rx-aeq";
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
pcie0: pcie@1fc00000 {
|
||||
compatible = "airoha,en7581-pcie";
|
||||
device_type = "pci";
|
||||
linux,pci-domain = <0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
||||
reg = <0x0 0x1fc00000 0x0 0x1670>;
|
||||
reg-names = "pcie-mac";
|
||||
|
||||
clocks = <&scuclk EN7523_CLK_PCIE>;
|
||||
clock-names = "sys-ck";
|
||||
|
||||
phys = <&pciephy>;
|
||||
phy-names = "pcie-phy";
|
||||
|
||||
ranges = <0x02000000 0 0x20000000 0x0 0x20000000 0 0x4000000>;
|
||||
|
||||
resets = <&scuclk EN7581_PCIE0_RST>,
|
||||
<&scuclk EN7581_PCIE1_RST>,
|
||||
<&scuclk EN7581_PCIE2_RST>;
|
||||
reset-names = "phy-lane0", "phy-lane1", "phy-lane2";
|
||||
|
||||
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
|
||||
bus-range = <0x00 0xff>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &pcie_intc0 0>,
|
||||
<0 0 0 2 &pcie_intc0 1>,
|
||||
<0 0 0 3 &pcie_intc0 2>,
|
||||
<0 0 0 4 &pcie_intc0 3>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
pcie_intc0: interrupt-controller {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
pcie1: pcie@1fc20000 {
|
||||
compatible = "airoha,en7581-pcie";
|
||||
device_type = "pci";
|
||||
linux,pci-domain = <1>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
||||
reg = <0x0 0x1fc20000 0x0 0x1670>;
|
||||
reg-names = "pcie-mac";
|
||||
|
||||
clocks = <&scuclk EN7523_CLK_PCIE>;
|
||||
clock-names = "sys-ck";
|
||||
|
||||
phys = <&pciephy>;
|
||||
phy-names = "pcie-phy";
|
||||
|
||||
ranges = <0x02000000 0 0x24000000 0x0 0x24000000 0 0x4000000>;
|
||||
|
||||
resets = <&scuclk EN7581_PCIE0_RST>,
|
||||
<&scuclk EN7581_PCIE1_RST>,
|
||||
<&scuclk EN7581_PCIE2_RST>;
|
||||
reset-names = "phy-lane0", "phy-lane1", "phy-lane2";
|
||||
|
||||
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
|
||||
bus-range = <0x00 0xff>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &pcie_intc1 0>,
|
||||
<0 0 0 2 &pcie_intc1 1>,
|
||||
<0 0 0 3 &pcie_intc1 2>,
|
||||
<0 0 0 4 &pcie_intc1 3>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
pcie_intc1: interrupt-controller {
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
eth: ethernet@1fb50000 {
|
||||
compatible = "airoha,en7581-eth";
|
||||
reg = <0 0x1fb50000 0 0x2600>,
|
||||
<0 0x1fb54000 0 0x2000>,
|
||||
<0 0x1fb56000 0 0x2000>;
|
||||
reg-names = "fe", "qdma0", "qdma1";
|
||||
|
||||
resets = <&scuclk EN7581_FE_RST>,
|
||||
<&scuclk EN7581_FE_PDMA_RST>,
|
||||
<&scuclk EN7581_FE_QDMA_RST>,
|
||||
<&scuclk EN7581_XSI_MAC_RST>,
|
||||
<&scuclk EN7581_DUAL_HSI0_MAC_RST>,
|
||||
<&scuclk EN7581_DUAL_HSI1_MAC_RST>,
|
||||
<&scuclk EN7581_HSI_MAC_RST>,
|
||||
<&scuclk EN7581_XFP_MAC_RST>;
|
||||
reset-names = "fe", "pdma", "qdma", "xsi-mac",
|
||||
"hsi0-mac", "hsi1-mac", "hsi-mac",
|
||||
"xfp-mac";
|
||||
|
||||
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gdm1: ethernet@1 {
|
||||
compatible = "airoha,eth-mac";
|
||||
reg = <1>;
|
||||
phy-mode = "internal";
|
||||
status = "disabled";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
switch: switch@1fb58000 {
|
||||
compatible = "airoha,en7581-switch";
|
||||
reg = <0 0x1fb58000 0 0x8000>;
|
||||
resets = <&scuclk EN7581_GSW_RST>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
status = "disabled";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gsw_port1: port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&gsw_phy1>;
|
||||
};
|
||||
|
||||
gsw_port2: port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&gsw_phy2>;
|
||||
};
|
||||
|
||||
gsw_port3: port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&gsw_phy3>;
|
||||
};
|
||||
|
||||
gsw_port4: port@4 {
|
||||
reg = <4>;
|
||||
label = "lan4";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&gsw_phy4>;
|
||||
};
|
||||
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu";
|
||||
ethernet = <&gdm1>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gsw_phy1: ethernet-phy@1 {
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
reg = <9>;
|
||||
phy-mode = "internal";
|
||||
|
||||
leds {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gsw_phy1_led0: gsw-phy1-led0@0 {
|
||||
reg = <0>;
|
||||
function = "phy1_led0";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gsw_phy1_led1: gsw-phy1-led1@1 {
|
||||
reg = <1>;
|
||||
function = "phy1_led1";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gsw_phy2: ethernet-phy@2 {
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
reg = <10>;
|
||||
phy-mode = "internal";
|
||||
|
||||
leds {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gsw_phy2_led0: gsw-phy2-led0@0 {
|
||||
reg = <0>;
|
||||
function = "phy2_led0";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gsw_phy2_led1: gsw-phy2-led1@1 {
|
||||
reg = <1>;
|
||||
function = "phy1_led1";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gsw_phy3: ethernet-phy@3 {
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
reg = <11>;
|
||||
phy-mode = "internal";
|
||||
|
||||
leds {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gsw_phy3_led0: gsw-phy3-led0@0 {
|
||||
reg = <0>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gsw_phy3_led1: gsw-phy3-led1@1 {
|
||||
reg = <1>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gsw_phy4: ethernet-phy@4 {
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
reg = <12>;
|
||||
phy-mode = "internal";
|
||||
|
||||
leds {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gsw_phy4_led0: gsw-phy4-led0@0 {
|
||||
reg = <0>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gsw_phy4_led1: gsw-phy4-led1@1 {
|
||||
reg = <1>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
616
target/linux/airoha/en7581/config-6.6
Normal file
616
target/linux/airoha/en7581/config-6.6
Normal file
@ -0,0 +1,616 @@
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_AIROHA_THERMAL=y
|
||||
CONFIG_AIROHA_WATCHDOG=y
|
||||
CONFIG_AMPERE_ERRATUM_AC03_CPU_38=y
|
||||
CONFIG_ARCH_AIROHA=y
|
||||
CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y
|
||||
CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y
|
||||
CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y
|
||||
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
|
||||
CONFIG_ARCH_FORCE_MAX_ORDER=10
|
||||
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
|
||||
CONFIG_ARCH_KEEP_MEMBLOCK=y
|
||||
CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y
|
||||
CONFIG_ARCH_MMAP_RND_BITS=18
|
||||
CONFIG_ARCH_MMAP_RND_BITS_MAX=24
|
||||
CONFIG_ARCH_MMAP_RND_BITS_MIN=18
|
||||
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11
|
||||
CONFIG_ARCH_PROC_KCORE_TEXT=y
|
||||
CONFIG_ARCH_SPARSEMEM_ENABLE=y
|
||||
CONFIG_ARCH_STACKWALK=y
|
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
|
||||
CONFIG_ARCH_USES_PG_ARCH_X=y
|
||||
CONFIG_ARCH_WANTS_NO_INSTR=y
|
||||
CONFIG_ARCH_WANTS_THP_SWAP=y
|
||||
CONFIG_ARM64=y
|
||||
CONFIG_ARM64_4K_PAGES=y
|
||||
CONFIG_ARM64_AMU_EXTN=y
|
||||
CONFIG_ARM64_BTI=y
|
||||
CONFIG_ARM64_E0PD=y
|
||||
CONFIG_ARM64_EPAN=y
|
||||
CONFIG_ARM64_ERRATUM_1024718=y
|
||||
CONFIG_ARM64_ERRATUM_1165522=y
|
||||
CONFIG_ARM64_ERRATUM_1286807=y
|
||||
CONFIG_ARM64_ERRATUM_1319367=y
|
||||
CONFIG_ARM64_ERRATUM_1463225=y
|
||||
CONFIG_ARM64_ERRATUM_1508412=y
|
||||
CONFIG_ARM64_ERRATUM_1530923=y
|
||||
CONFIG_ARM64_ERRATUM_1542419=y
|
||||
CONFIG_ARM64_ERRATUM_2051678=y
|
||||
CONFIG_ARM64_ERRATUM_2054223=y
|
||||
CONFIG_ARM64_ERRATUM_2067961=y
|
||||
CONFIG_ARM64_ERRATUM_2077057=y
|
||||
CONFIG_ARM64_ERRATUM_2441007=y
|
||||
CONFIG_ARM64_ERRATUM_2441009=y
|
||||
CONFIG_ARM64_ERRATUM_2457168=y
|
||||
CONFIG_ARM64_ERRATUM_2658417=y
|
||||
CONFIG_ARM64_ERRATUM_819472=y
|
||||
CONFIG_ARM64_ERRATUM_824069=y
|
||||
CONFIG_ARM64_ERRATUM_826319=y
|
||||
CONFIG_ARM64_ERRATUM_827319=y
|
||||
CONFIG_ARM64_ERRATUM_832075=y
|
||||
CONFIG_ARM64_ERRATUM_843419=y
|
||||
CONFIG_ARM64_ERRATUM_858921=y
|
||||
CONFIG_ARM64_HW_AFDBM=y
|
||||
CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
|
||||
CONFIG_ARM64_MTE=y
|
||||
CONFIG_ARM64_PAGE_SHIFT=12
|
||||
CONFIG_ARM64_PA_BITS=48
|
||||
CONFIG_ARM64_PA_BITS_48=y
|
||||
CONFIG_ARM64_PTR_AUTH=y
|
||||
CONFIG_ARM64_PTR_AUTH_KERNEL=y
|
||||
CONFIG_ARM64_RAS_EXTN=y
|
||||
CONFIG_ARM64_SME=y
|
||||
CONFIG_ARM64_SVE=y
|
||||
# CONFIG_ARM64_SW_TTBR0_PAN is not set
|
||||
CONFIG_ARM64_TAGGED_ADDR_ABI=y
|
||||
CONFIG_ARM64_TLB_RANGE=y
|
||||
CONFIG_ARM64_VA_BITS=39
|
||||
CONFIG_ARM64_VA_BITS_39=y
|
||||
CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y
|
||||
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y
|
||||
CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y
|
||||
CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE=y
|
||||
CONFIG_ARM_AIROHA_SOC_CPUFREQ=y
|
||||
CONFIG_ARM_AMBA=y
|
||||
CONFIG_ARM_ARCH_TIMER=y
|
||||
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
|
||||
CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y
|
||||
CONFIG_ARM_GIC=y
|
||||
CONFIG_ARM_GIC_V2M=y
|
||||
CONFIG_ARM_GIC_V3=y
|
||||
CONFIG_ARM_GIC_V3_ITS=y
|
||||
CONFIG_ARM_GIC_V3_ITS_PCI=y
|
||||
CONFIG_ARM_PMU=y
|
||||
CONFIG_ARM_PMUV3=y
|
||||
CONFIG_ARM_PSCI_FW=y
|
||||
CONFIG_ARM_SMCCC_SOC_ID=y
|
||||
# CONFIG_ARM_SMMU is not set
|
||||
# CONFIG_ARM_SMMU_V3 is not set
|
||||
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
|
||||
CONFIG_BINFMT_MISC=y
|
||||
# CONFIG_BLK_CGROUP is not set
|
||||
CONFIG_BLK_DEBUG_FS=y
|
||||
# CONFIG_BLK_DEV_INITRD is not set
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_COUNT=16
|
||||
CONFIG_BLK_DEV_RAM_SIZE=4096
|
||||
CONFIG_BLK_MQ_PCI=y
|
||||
CONFIG_BLK_PM=y
|
||||
CONFIG_BLOCK_LEGACY_AUTOLOAD=y
|
||||
# CONFIG_BPF_JIT is not set
|
||||
# CONFIG_BPF_SYSCALL is not set
|
||||
# CONFIG_BRIDGE_VLAN_FILTERING is not set
|
||||
CONFIG_BUFFER_HEAD=y
|
||||
CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y
|
||||
CONFIG_CAVIUM_ERRATUM_22375=y
|
||||
CONFIG_CAVIUM_ERRATUM_23154=y
|
||||
CONFIG_CAVIUM_ERRATUM_27456=y
|
||||
CONFIG_CAVIUM_ERRATUM_30115=y
|
||||
CONFIG_CAVIUM_TX2_ERRATUM_219=y
|
||||
CONFIG_CC_HAVE_SHADOW_CALL_STACK=y
|
||||
CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y
|
||||
CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
|
||||
CONFIG_CC_NO_ARRAY_BOUNDS=y
|
||||
# CONFIG_CFS_BANDWIDTH is not set
|
||||
CONFIG_CGROUPS=y
|
||||
CONFIG_CGROUP_CPUACCT=y
|
||||
CONFIG_CGROUP_DEBUG=y
|
||||
CONFIG_CGROUP_DEVICE=y
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
# CONFIG_CGROUP_NET_CLASSID is not set
|
||||
# CONFIG_CGROUP_NET_PRIO is not set
|
||||
# CONFIG_CGROUP_PERF is not set
|
||||
# CONFIG_CGROUP_PIDS is not set
|
||||
# CONFIG_CGROUP_RDMA is not set
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_CLONE_BACKWARDS=y
|
||||
CONFIG_COMMON_CLK=y
|
||||
CONFIG_COMMON_CLK_EN7523=y
|
||||
CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
|
||||
CONFIG_COMPAT_32BIT_TIME=y
|
||||
CONFIG_CONTEXT_TRACKING=y
|
||||
CONFIG_CONTEXT_TRACKING_IDLE=y
|
||||
CONFIG_COREDUMP=y
|
||||
CONFIG_CPUSETS=y
|
||||
CONFIG_CPU_FREQ=y
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
|
||||
CONFIG_CPU_FREQ_GOV_ATTR_SET=y
|
||||
CONFIG_CPU_FREQ_GOV_COMMON=y
|
||||
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
|
||||
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
|
||||
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
||||
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
|
||||
CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
||||
CONFIG_CPU_FREQ_STAT=y
|
||||
CONFIG_CPU_IDLE=y
|
||||
CONFIG_CPU_IDLE_GOV_MENU=y
|
||||
CONFIG_CPU_ISOLATION=y
|
||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||
CONFIG_CPU_MITIGATIONS=y
|
||||
CONFIG_CPU_PM=y
|
||||
CONFIG_CPU_RMAP=y
|
||||
CONFIG_CRC16=y
|
||||
CONFIG_CRC_CCITT=y
|
||||
CONFIG_CROSS_MEMORY_ATTACH=y
|
||||
CONFIG_CRYPTO_AUTHENC=y
|
||||
CONFIG_CRYPTO_CBC=y
|
||||
CONFIG_CRYPTO_CRC32C=y
|
||||
CONFIG_CRYPTO_DEFLATE=y
|
||||
CONFIG_CRYPTO_DES=y
|
||||
CONFIG_CRYPTO_DEV_EIP93=y
|
||||
CONFIG_CRYPTO_DRBG=y
|
||||
CONFIG_CRYPTO_DRBG_HMAC=y
|
||||
CONFIG_CRYPTO_DRBG_MENU=y
|
||||
CONFIG_CRYPTO_ECB=y
|
||||
CONFIG_CRYPTO_ECHAINIV=y
|
||||
CONFIG_CRYPTO_GENIV=y
|
||||
CONFIG_CRYPTO_HASH_INFO=y
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
CONFIG_CRYPTO_HW=y
|
||||
CONFIG_CRYPTO_JITTERENTROPY=y
|
||||
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
||||
CONFIG_CRYPTO_LIB_DES=y
|
||||
CONFIG_CRYPTO_LIB_GF128MUL=y
|
||||
CONFIG_CRYPTO_LIB_SHA1=y
|
||||
CONFIG_CRYPTO_LIB_SHA256=y
|
||||
CONFIG_CRYPTO_LIB_UTILS=y
|
||||
CONFIG_CRYPTO_LZO=y
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
CONFIG_CRYPTO_MICHAEL_MIC=y
|
||||
# CONFIG_CRYPTO_PCRYPT is not set
|
||||
CONFIG_CRYPTO_RNG=y
|
||||
CONFIG_CRYPTO_RNG2=y
|
||||
CONFIG_CRYPTO_RNG_DEFAULT=y
|
||||
CONFIG_CRYPTO_SEQIV=y
|
||||
CONFIG_CRYPTO_SHA1=y
|
||||
CONFIG_CRYPTO_SHA256=y
|
||||
CONFIG_CRYPTO_SHA3=y
|
||||
CONFIG_CRYPTO_SHA512=y
|
||||
CONFIG_CRYPTO_ZSTD=y
|
||||
CONFIG_DCACHE_WORD_ACCESS=y
|
||||
CONFIG_DEBUG_BUGVERBOSE=y
|
||||
# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set
|
||||
CONFIG_DEBUG_INFO_NONE=y
|
||||
CONFIG_DEBUG_MISC=y
|
||||
CONFIG_DEVMEM=y
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y
|
||||
CONFIG_DMA_DIRECT_REMAP=y
|
||||
CONFIG_DMA_ENGINE=y
|
||||
CONFIG_DMA_OF=y
|
||||
CONFIG_DMA_OPS=y
|
||||
CONFIG_DTC=y
|
||||
CONFIG_EDAC_SUPPORT=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_POSIX_ACL=y
|
||||
CONFIG_EXT2_FS_SECURITY=y
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT3_FS_POSIX_ACL=y
|
||||
CONFIG_EXT3_FS_SECURITY=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_EXT4_FS_SECURITY=y
|
||||
CONFIG_FAIR_GROUP_SCHED=y
|
||||
CONFIG_FAT_DEFAULT_CODEPAGE=936
|
||||
CONFIG_FAT_DEFAULT_IOCHARSET="utf8"
|
||||
CONFIG_FAT_FS=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
CONFIG_FIX_EARLYCON_MEM=y
|
||||
# CONFIG_FORTIFY_SOURCE is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
CONFIG_FREEZER=y
|
||||
CONFIG_FSL_ERRATUM_A008585=y
|
||||
CONFIG_FS_IOMAP=y
|
||||
CONFIG_FS_MBCACHE=y
|
||||
CONFIG_FS_POSIX_ACL=y
|
||||
CONFIG_FUJITSU_ERRATUM_010001=y
|
||||
CONFIG_FUNCTION_ALIGNMENT=4
|
||||
CONFIG_FUNCTION_ALIGNMENT_4B=y
|
||||
CONFIG_FWNODE_MDIO=y
|
||||
CONFIG_FW_CACHE=y
|
||||
# CONFIG_FW_LOADER_USER_HELPER is not set
|
||||
CONFIG_GCC10_NO_ARRAY_BOUNDS=y
|
||||
CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y
|
||||
CONFIG_GENERIC_ALLOCATOR=y
|
||||
CONFIG_GENERIC_ARCH_TOPOLOGY=y
|
||||
CONFIG_GENERIC_BUG=y
|
||||
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
|
||||
CONFIG_GENERIC_CPU_AUTOPROBE=y
|
||||
CONFIG_GENERIC_CPU_VULNERABILITIES=y
|
||||
CONFIG_GENERIC_CSUM=y
|
||||
CONFIG_GENERIC_EARLY_IOREMAP=y
|
||||
CONFIG_GENERIC_GETTIMEOFDAY=y
|
||||
CONFIG_GENERIC_IDLE_POLL_SETUP=y
|
||||
CONFIG_GENERIC_IOREMAP=y
|
||||
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
|
||||
CONFIG_GENERIC_IRQ_MIGRATION=y
|
||||
CONFIG_GENERIC_IRQ_SHOW=y
|
||||
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
|
||||
CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y
|
||||
CONFIG_GENERIC_MSI_IRQ=y
|
||||
CONFIG_GENERIC_PCI_IOMAP=y
|
||||
CONFIG_GENERIC_PHY=y
|
||||
CONFIG_GENERIC_PINCONF=y
|
||||
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
||||
CONFIG_GENERIC_PINMUX_FUNCTIONS=y
|
||||
CONFIG_GENERIC_SCHED_CLOCK=y
|
||||
CONFIG_GENERIC_SMP_IDLE_THREAD=y
|
||||
CONFIG_GENERIC_STRNCPY_FROM_USER=y
|
||||
CONFIG_GENERIC_STRNLEN_USER=y
|
||||
CONFIG_GENERIC_TIME_VSYSCALL=y
|
||||
CONFIG_GLOB=y
|
||||
CONFIG_GPIOLIB_IRQCHIP=y
|
||||
CONFIG_GPIO_CDEV=y
|
||||
CONFIG_GPIO_EN7523=y
|
||||
CONFIG_GPIO_GENERIC=y
|
||||
CONFIG_GRO_CELLS=y
|
||||
# CONFIG_HARDENED_USERCOPY is not set
|
||||
CONFIG_HARDIRQS_SW_RESEND=y
|
||||
CONFIG_HAS_DMA=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAS_IOPORT_MAP=y
|
||||
CONFIG_HISILICON_ERRATUM_161010101=y
|
||||
CONFIG_HISILICON_ERRATUM_161600802=y
|
||||
CONFIG_HOTPLUG_CORE_SYNC=y
|
||||
CONFIG_HOTPLUG_CORE_SYNC_DEAD=y
|
||||
CONFIG_HOTPLUG_CPU=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_HW_RANDOM_AIROHA=y
|
||||
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
|
||||
CONFIG_INET_AH=y
|
||||
CONFIG_INET_ESP=y
|
||||
# CONFIG_INET_ESP_OFFLOAD is not set
|
||||
CONFIG_INET_IPCOMP=y
|
||||
CONFIG_INET_TUNNEL=y
|
||||
CONFIG_INET_XFRM_TUNNEL=y
|
||||
CONFIG_INITRAMFS_PRESERVE_MTIME=y
|
||||
CONFIG_INPUT=y
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
CONFIG_INPUT_KEYBOARD=y
|
||||
# CONFIG_INPUT_MISC is not set
|
||||
CONFIG_INTERVAL_TREE=y
|
||||
CONFIG_INTERVAL_TREE_SPAN_ITER=y
|
||||
CONFIG_IOMMUFD=y
|
||||
CONFIG_IOMMU_API=y
|
||||
# CONFIG_IOMMU_DEBUGFS is not set
|
||||
# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
|
||||
CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
|
||||
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
|
||||
CONFIG_IOMMU_DMA=y
|
||||
CONFIG_IOMMU_IOVA=y
|
||||
# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
|
||||
# CONFIG_IOMMU_IO_PGTABLE_DART is not set
|
||||
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
|
||||
CONFIG_IOMMU_SUPPORT=y
|
||||
CONFIG_IO_URING=y
|
||||
CONFIG_IPC_NS=y
|
||||
CONFIG_IPV6=y
|
||||
CONFIG_IPV6_MULTIPLE_TABLES=y
|
||||
# CONFIG_IPV6_SUBTREES is not set
|
||||
CONFIG_IP_MROUTE=y
|
||||
CONFIG_IP_MROUTE_COMMON=y
|
||||
# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
|
||||
CONFIG_IP_PNP=y
|
||||
# CONFIG_IP_PNP_BOOTP is not set
|
||||
# CONFIG_IP_PNP_DHCP is not set
|
||||
# CONFIG_IP_PNP_RARP is not set
|
||||
# CONFIG_IP_ROUTE_MULTIPATH is not set
|
||||
# CONFIG_IP_ROUTE_VERBOSE is not set
|
||||
CONFIG_IRQCHIP=y
|
||||
CONFIG_IRQ_DOMAIN=y
|
||||
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
||||
CONFIG_IRQ_FORCED_THREADING=y
|
||||
CONFIG_IRQ_MSI_IOMMU=y
|
||||
CONFIG_IRQ_WORK=y
|
||||
# CONFIG_ISDN is not set
|
||||
CONFIG_JBD2=y
|
||||
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
|
||||
# CONFIG_JFFS2_FS_XATTR is not set
|
||||
# CONFIG_JFFS2_SUMMARY is not set
|
||||
CONFIG_JFFS2_ZLIB=y
|
||||
CONFIG_KALLSYMS=y
|
||||
CONFIG_LEGACY_DIRECT_IO=y
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=8
|
||||
CONFIG_LIBCRC32C=y
|
||||
CONFIG_LIBFDT=y
|
||||
CONFIG_LOCALVERSION_AUTO=y
|
||||
CONFIG_LOCK_DEBUGGING_SUPPORT=y
|
||||
CONFIG_LOCK_SPIN_ON_OWNER=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
# CONFIG_LRU_GEN is not set
|
||||
CONFIG_LZO_COMPRESS=y
|
||||
CONFIG_LZO_DECOMPRESS=y
|
||||
CONFIG_MDIO_BUS=y
|
||||
CONFIG_MDIO_DEVICE=y
|
||||
CONFIG_MDIO_DEVRES=y
|
||||
# CONFIG_MEDIATEK_GE_SOC_PHY is not set
|
||||
# CONFIG_MEMCG is not set
|
||||
CONFIG_MFD_SYSCON=y
|
||||
CONFIG_MIGRATION=y
|
||||
CONFIG_MMU_LAZY_TLB_REFCOUNT=y
|
||||
CONFIG_MODULES_TREE_LOOKUP=y
|
||||
CONFIG_MODULES_USE_ELF_RELA=y
|
||||
CONFIG_MQ_IOSCHED_DEADLINE=y
|
||||
CONFIG_MQ_IOSCHED_KYBER=y
|
||||
CONFIG_MTD_CFI_ADV_OPTIONS=y
|
||||
# CONFIG_MTD_CFI_AMDSTD is not set
|
||||
CONFIG_MTD_CFI_GEOMETRY=y
|
||||
# CONFIG_MTD_CFI_INTELEXT is not set
|
||||
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
|
||||
CONFIG_MTD_JEDECPROBE=y
|
||||
CONFIG_MTD_NAND_CORE=y
|
||||
CONFIG_MTD_NAND_ECC=y
|
||||
CONFIG_MTD_NAND_MTK_BMT=y
|
||||
CONFIG_MTD_OF_PARTS_AIROHA=y
|
||||
CONFIG_MTD_RAW_NAND=y
|
||||
CONFIG_MTD_SPI_NAND=y
|
||||
CONFIG_MTD_SPLIT_FIRMWARE=y
|
||||
CONFIG_MTD_SPLIT_FIRMWARE_NAME="tclinux"
|
||||
CONFIG_MTD_SPLIT_FIT_FW=y
|
||||
CONFIG_MTD_SPLIT_LZMA_FW=y
|
||||
# CONFIG_MTD_SPLIT_SQUASHFS_ROOT is not set
|
||||
CONFIG_MTD_UBI=y
|
||||
CONFIG_MTD_UBI_BEB_LIMIT=20
|
||||
CONFIG_MTD_UBI_BLOCK=y
|
||||
CONFIG_MTD_UBI_WL_THRESHOLD=4096
|
||||
CONFIG_MUTEX_SPIN_ON_OWNER=y
|
||||
CONFIG_NAMESPACES=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_SG_DMA_FLAGS=y
|
||||
CONFIG_NEED_SG_DMA_LENGTH=y
|
||||
CONFIG_NET_AIROHA=y
|
||||
CONFIG_NET_DEVLINK=y
|
||||
CONFIG_NET_DSA=y
|
||||
CONFIG_NET_DSA_MT7530=y
|
||||
CONFIG_NET_DSA_MT7530_MDIO=y
|
||||
CONFIG_NET_DSA_MT7530_MMIO=y
|
||||
CONFIG_NET_DSA_TAG_MTK=y
|
||||
CONFIG_NET_FLOW_LIMIT=y
|
||||
CONFIG_NET_KEY=y
|
||||
CONFIG_NET_KEY_MIGRATE=y
|
||||
# CONFIG_NET_MEDIATEK_SOC is not set
|
||||
CONFIG_NET_NS=y
|
||||
# CONFIG_NET_SCHED is not set
|
||||
CONFIG_NET_SELFTESTS=y
|
||||
CONFIG_NET_SWITCHDEV=y
|
||||
# CONFIG_NET_VENDOR_3COM is not set
|
||||
CONFIG_NET_VENDOR_MEDIATEK=y
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS_DEFAULT="utf8"
|
||||
CONFIG_NO_HZ_COMMON=y
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_NTFS_DEBUG=y
|
||||
CONFIG_NTFS_FS=y
|
||||
CONFIG_NTFS_RW=y
|
||||
CONFIG_NVIDIA_CARMEL_CNP_ERRATUM=y
|
||||
CONFIG_OF=y
|
||||
CONFIG_OF_ADDRESS=y
|
||||
CONFIG_OF_EARLY_FLATTREE=y
|
||||
CONFIG_OF_FLATTREE=y
|
||||
CONFIG_OF_GPIO=y
|
||||
CONFIG_OF_IOMMU=y
|
||||
CONFIG_OF_IRQ=y
|
||||
CONFIG_OF_KOBJ=y
|
||||
CONFIG_OF_MDIO=y
|
||||
# CONFIG_OVERLAY_FS_XINO_AUTO is not set
|
||||
CONFIG_PAGE_POOL=y
|
||||
CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
|
||||
CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
|
||||
# CONFIG_PANIC_ON_OOPS is not set
|
||||
CONFIG_PANIC_ON_OOPS_VALUE=0
|
||||
CONFIG_PANIC_TIMEOUT=0
|
||||
CONFIG_PARTITION_PERCPU=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCIEAER=y
|
||||
CONFIG_PCIEASPM=y
|
||||
# CONFIG_PCIEASPM_DEFAULT is not set
|
||||
CONFIG_PCIEASPM_PERFORMANCE=y
|
||||
# CONFIG_PCIEASPM_POWERSAVE is not set
|
||||
# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
# CONFIG_PCIE_MEDIATEK is not set
|
||||
CONFIG_PCIE_PME=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_PCI_DOMAINS_GENERIC=y
|
||||
CONFIG_PCI_MSI=y
|
||||
CONFIG_PCPU_DEV_REFCNT=y
|
||||
CONFIG_PCS_MTK_LYNXI=y
|
||||
CONFIG_PERF_EVENTS=y
|
||||
CONFIG_PER_VMA_LOCK=y
|
||||
CONFIG_PGTABLE_LEVELS=3
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_PHYLIB_LEDS=y
|
||||
CONFIG_PHYLINK=y
|
||||
CONFIG_PHYS_ADDR_T_64BIT=y
|
||||
CONFIG_PHY_AIROHA_PCIE=y
|
||||
CONFIG_PID_NS=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PINCTRL_AIROHA=y
|
||||
# CONFIG_PINCTRL_MT2712 is not set
|
||||
# CONFIG_PINCTRL_MT6765 is not set
|
||||
# CONFIG_PINCTRL_MT6795 is not set
|
||||
# CONFIG_PINCTRL_MT6797 is not set
|
||||
# CONFIG_PINCTRL_MT7622 is not set
|
||||
# CONFIG_PINCTRL_MT7981 is not set
|
||||
# CONFIG_PINCTRL_MT7986 is not set
|
||||
# CONFIG_PINCTRL_MT8173 is not set
|
||||
# CONFIG_PINCTRL_MT8183 is not set
|
||||
# CONFIG_PINCTRL_MT8186 is not set
|
||||
# CONFIG_PINCTRL_MT8188 is not set
|
||||
# CONFIG_PINCTRL_MT8516 is not set
|
||||
CONFIG_PM=y
|
||||
CONFIG_PM_CLK=y
|
||||
CONFIG_PM_OPP=y
|
||||
CONFIG_PM_SLEEP=y
|
||||
CONFIG_PM_SLEEP_SMP=y
|
||||
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_POSIX_MQUEUE_SYSCTL=y
|
||||
CONFIG_POWER_RESET=y
|
||||
CONFIG_POWER_RESET_SYSCON=y
|
||||
CONFIG_POWER_SUPPLY=y
|
||||
CONFIG_PREEMPT_NONE_BUILD=y
|
||||
CONFIG_PROC_PAGE_MONITOR=y
|
||||
CONFIG_PROC_PID_CPUSET=y
|
||||
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
|
||||
CONFIG_QCOM_FALKOR_ERRATUM_1003=y
|
||||
CONFIG_QCOM_FALKOR_ERRATUM_1009=y
|
||||
CONFIG_QCOM_FALKOR_ERRATUM_E1041=y
|
||||
CONFIG_QCOM_QDF2400_ERRATUM_0065=y
|
||||
CONFIG_QUEUED_RWLOCKS=y
|
||||
CONFIG_QUEUED_SPINLOCKS=y
|
||||
CONFIG_RANDSTRUCT_NONE=y
|
||||
CONFIG_RAS=y
|
||||
CONFIG_RATIONAL=y
|
||||
CONFIG_RCU_CPU_STALL_TIMEOUT=21
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_REGMAP_MMIO=y
|
||||
CONFIG_RELOCATABLE=y
|
||||
CONFIG_RESET_CONTROLLER=y
|
||||
CONFIG_RFS_ACCEL=y
|
||||
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
|
||||
CONFIG_RPS=y
|
||||
CONFIG_RSEQ=y
|
||||
# CONFIG_RT_GROUP_SCHED is not set
|
||||
CONFIG_RWSEM_SPIN_ON_OWNER=y
|
||||
# CONFIG_SCHED_CORE is not set
|
||||
CONFIG_SCHED_DEBUG=y
|
||||
CONFIG_SCHED_MM_CID=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
# CONFIG_SCHED_STACK_END_CHECK is not set
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITYFS=y
|
||||
# CONFIG_SECURITY_DMESG_RESTRICT is not set
|
||||
# CONFIG_SECURITY_NETWORK is not set
|
||||
CONFIG_SERIAL_8250_EXTENDED=y
|
||||
CONFIG_SERIAL_8250_FSL=y
|
||||
CONFIG_SERIAL_8250_NR_UARTS=5
|
||||
CONFIG_SERIAL_8250_RUNTIME_UARTS=5
|
||||
CONFIG_SERIAL_8250_SHARE_IRQ=y
|
||||
CONFIG_SERIAL_MCTRL_GPIO=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
CONFIG_SERIO=y
|
||||
CONFIG_SERIO_LIBPS2=y
|
||||
CONFIG_SGETMASK_SYSCALL=y
|
||||
CONFIG_SGL_ALLOC=y
|
||||
CONFIG_SKB_EXTENSIONS=y
|
||||
# CONFIG_SLAB_FREELIST_HARDENED is not set
|
||||
# CONFIG_SLAB_FREELIST_RANDOM is not set
|
||||
CONFIG_SLUB_DEBUG=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_SOCIONEXT_SYNQUACER_PREITS=y
|
||||
CONFIG_SOCK_RX_QUEUE_MAPPING=y
|
||||
CONFIG_SOC_BUS=y
|
||||
CONFIG_SOFTIRQ_ON_OWN_STACK=y
|
||||
CONFIG_SPARSEMEM=y
|
||||
CONFIG_SPARSEMEM_EXTREME=y
|
||||
CONFIG_SPARSEMEM_VMEMMAP=y
|
||||
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
|
||||
CONFIG_SPARSE_IRQ=y
|
||||
CONFIG_SPI=y
|
||||
# CONFIG_SPI_AIROHA_EN7523 is not set
|
||||
CONFIG_SPI_AIROHA_SNFI=y
|
||||
CONFIG_SPI_MASTER=y
|
||||
CONFIG_SPI_MEM=y
|
||||
CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
|
||||
# CONFIG_SQUASHFS_EMBEDDED is not set
|
||||
CONFIG_SQUASHFS_FILE_CACHE=y
|
||||
# CONFIG_SQUASHFS_FILE_DIRECT is not set
|
||||
CONFIG_SQUASHFS_ZLIB=y
|
||||
CONFIG_STACKDEPOT=y
|
||||
CONFIG_STACKPROTECTOR=y
|
||||
CONFIG_STACKPROTECTOR_PER_TASK=y
|
||||
CONFIG_STACKPROTECTOR_STRONG=y
|
||||
CONFIG_STACKTRACE=y
|
||||
# CONFIG_STAGING is not set
|
||||
# CONFIG_STRIP_ASM_SYMS is not set
|
||||
CONFIG_SURFACE_PLATFORMS=y
|
||||
CONFIG_SUSPEND=y
|
||||
CONFIG_SUSPEND_FREEZER=y
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SWIOTLB=y
|
||||
CONFIG_SWPHY=y
|
||||
CONFIG_SYSCTL_EXCEPTION_TRACE=y
|
||||
CONFIG_SYSFS_SYSCALL=y
|
||||
# CONFIG_TCP_CONG_ADVANCED is not set
|
||||
CONFIG_TCP_MD5SIG=y
|
||||
CONFIG_TEXTSEARCH_BM=y
|
||||
CONFIG_TEXTSEARCH_FSM=y
|
||||
CONFIG_TEXTSEARCH_KMP=y
|
||||
CONFIG_THERMAL=y
|
||||
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
|
||||
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
|
||||
CONFIG_THERMAL_GOV_STEP_WISE=y
|
||||
CONFIG_THERMAL_GOV_USER_SPACE=y
|
||||
CONFIG_THERMAL_OF=y
|
||||
CONFIG_THERMAL_WRITABLE_TRIPS=y
|
||||
CONFIG_THREAD_INFO_IN_TASK=y
|
||||
CONFIG_TICK_CPU_ACCOUNTING=y
|
||||
CONFIG_TIMER_OF=y
|
||||
CONFIG_TIMER_PROBE=y
|
||||
CONFIG_TIME_NS=y
|
||||
# CONFIG_TMPFS_XATTR is not set
|
||||
CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
|
||||
CONFIG_TREE_RCU=y
|
||||
CONFIG_TREE_SRCU=y
|
||||
CONFIG_UBIFS_FS=y
|
||||
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
|
||||
CONFIG_UEVENT_HELPER_PATH=""
|
||||
CONFIG_UNMAP_KERNEL_AT_EL0=y
|
||||
CONFIG_USELIB=y
|
||||
CONFIG_USER_NS=y
|
||||
CONFIG_UTS_NS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_VMAP_STACK=y
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_WATCHDOG_CORE=y
|
||||
# CONFIG_WLAN is not set
|
||||
# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
|
||||
CONFIG_XFRM_AH=y
|
||||
CONFIG_XFRM_ALGO=y
|
||||
CONFIG_XFRM_ESP=y
|
||||
CONFIG_XFRM_IPCOMP=y
|
||||
CONFIG_XFRM_MIGRATE=y
|
||||
CONFIG_XPS=y
|
||||
CONFIG_XXHASH=y
|
||||
CONFIG_XZ_DEC_ARM=y
|
||||
CONFIG_XZ_DEC_ARMTHUMB=y
|
||||
CONFIG_XZ_DEC_BCJ=y
|
||||
CONFIG_XZ_DEC_IA64=y
|
||||
CONFIG_XZ_DEC_POWERPC=y
|
||||
CONFIG_XZ_DEC_SPARC=y
|
||||
CONFIG_XZ_DEC_X86=y
|
||||
CONFIG_ZLIB_DEFLATE=y
|
||||
CONFIG_ZLIB_INFLATE=y
|
||||
CONFIG_ZONE_DMA32=y
|
||||
CONFIG_ZSTD_COMMON=y
|
||||
CONFIG_ZSTD_COMPRESS=y
|
||||
CONFIG_ZSTD_DECOMPRESS=y
|
11
target/linux/airoha/en7581/target.mk
Normal file
11
target/linux/airoha/en7581/target.mk
Normal file
@ -0,0 +1,11 @@
|
||||
ARCH:=aarch64
|
||||
SUBTARGET:=en7581
|
||||
BOARDNAME:=EN7581
|
||||
CPU_TYPE:=cortex-a53
|
||||
KERNELNAME:=Image dtbs
|
||||
FEATURES+=pwm source-only
|
||||
|
||||
define Target/Description
|
||||
Build firmware images for Airoha en7581 ARM based boards.
|
||||
endef
|
||||
|
27
target/linux/airoha/image/en7581.mk
Normal file
27
target/linux/airoha/image/en7581.mk
Normal file
@ -0,0 +1,27 @@
|
||||
define Device/FitImageLzma
|
||||
KERNEL_SUFFIX := -uImage.itb
|
||||
KERNEL = kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(DEVICE_DTS).dtb
|
||||
KERNEL_NAME := Image
|
||||
endef
|
||||
|
||||
define Device/airoha_en7581-evb
|
||||
$(call Device/FitImageLzma)
|
||||
DEVICE_VENDOR := Airoha
|
||||
DEVICE_MODEL := EN7581 Evaluation Board (SNAND)
|
||||
DEVICE_PACKAGES := kmod-leds-pwm kmod-i2c-en7581 kmod-pwm-airoha kmod-input-gpio-keys-polled
|
||||
DEVICE_DTS := en7581-evb
|
||||
DEVICE_DTS_DIR := ../dts
|
||||
DEVICE_DTS_CONFIG := config@1
|
||||
KERNEL_LOADADDR := 0x80088000
|
||||
IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | pad-rootfs | append-metadata
|
||||
endef
|
||||
TARGET_DEVICES += airoha_en7581-evb
|
||||
|
||||
define Device/airoha_en7581-evb-emmc
|
||||
DEVICE_VENDOR := Airoha
|
||||
DEVICE_MODEL := EN7581 Evaluation Board (EMMC)
|
||||
DEVICE_DTS := en7581-evb-emmc
|
||||
DEVICE_DTS_DIR := ../dts
|
||||
DEVICE_PACKAGES := kmod-i2c-en7581
|
||||
endef
|
||||
TARGET_DEVICES += airoha_en7581-evb-emmc
|
42
target/linux/airoha/modules.mk
Normal file
42
target/linux/airoha/modules.mk
Normal file
@ -0,0 +1,42 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
OTHER_MENU:=Other modules
|
||||
|
||||
I2C_MT7621_MODULES:= \
|
||||
CONFIG_I2C_MT7621:drivers/i2c/busses/i2c-mt7621
|
||||
|
||||
define KernelPackage/i2c-en7581
|
||||
SUBMENU:=$(OTHER_MENU)
|
||||
$(call i2c_defaults,$(I2C_MT7621_MODULES),79)
|
||||
TITLE:=Airoha I2C Controller
|
||||
DEPENDS:=+kmod-i2c-core \
|
||||
@(TARGET_airoha_en7581)
|
||||
endef
|
||||
|
||||
define KernelPackage/i2c-en7581/description
|
||||
Kernel modules for enable mt7621 i2c controller.
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,i2c-en7581))
|
||||
|
||||
|
||||
define KernelPackage/pwm-en7581
|
||||
SUBMENU:=$(OTHER_MENU)
|
||||
TITLE:=Airoha EN7581 PWM
|
||||
DEPENDS:=@(TARGET_airoha_en7581)
|
||||
KCONFIG:= \
|
||||
CONFIG_PWM=y \
|
||||
CONFIG_PWM_AIROHA=y \
|
||||
CONFIG_PWM_SYSFS=y
|
||||
FILES:= \
|
||||
$(LINUX_DIR)/drivers/pwm/pwm-airoha.ko
|
||||
AUTOLOAD:=$(call AutoProbe,pwm-airoha)
|
||||
endef
|
||||
|
||||
define KernelPackage/pwm-en7581/description
|
||||
Kernel module to use the PWM channel on Airoha SoC
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,pwm-en7581))
|
||||
|
||||
|
@ -0,0 +1,34 @@
|
||||
From 428ae88ef519f2009fac37563de76ffa6f93046f Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Danzberger <dd@embedd.com>
|
||||
Date: Sat, 9 Mar 2024 10:32:16 +0100
|
||||
Subject: [PATCH] arm64: add Airoha EN7581 platform
|
||||
|
||||
Introduce the Kconfig entry for the Airoha EN7581 multicore architecture
|
||||
available in the Airoha EN7581 evaluation board.
|
||||
|
||||
Signed-off-by: Daniel Danzberger <dd@embedd.com>
|
||||
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/d52d95db313e6a58ba997ba2181faf78a1014bcc.1709975956.git.lorenzo@kernel.org
|
||||
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
|
||||
---
|
||||
arch/arm64/Kconfig.platforms | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/arch/arm64/Kconfig.platforms
|
||||
+++ b/arch/arm64/Kconfig.platforms
|
||||
@@ -8,6 +8,13 @@ config ARCH_ACTIONS
|
||||
help
|
||||
This enables support for the Actions Semiconductor S900 SoC family.
|
||||
|
||||
+config ARCH_AIROHA
|
||||
+ bool "Airoha SoC Support"
|
||||
+ select ARM_PSCI
|
||||
+ select HAVE_ARM_ARCH_TIMER
|
||||
+ help
|
||||
+ This enables support for the ARM64 based Airoha SoCs.
|
||||
+
|
||||
config ARCH_SUNXI
|
||||
bool "Allwinner sunxi 64-bit SoC Family"
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
@ -0,0 +1,27 @@
|
||||
From fd6acb0d21b8683fd8804129beeb4fe629488aff Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 9 Jul 2024 00:42:38 +0200
|
||||
Subject: [PATCH] i2c: mt7621: Add Airoha EN7581 i2c support
|
||||
|
||||
Introduce i2c support to Airoha EN7581 SoC through the i2c-mt7621
|
||||
driver.
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Tested-by: Ray Liu <ray.liu@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
|
||||
---
|
||||
drivers/i2c/busses/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/i2c/busses/Kconfig
|
||||
+++ b/drivers/i2c/busses/Kconfig
|
||||
@@ -839,7 +839,7 @@ config I2C_MT65XX
|
||||
|
||||
config I2C_MT7621
|
||||
tristate "MT7621/MT7628 I2C Controller"
|
||||
- depends on (RALINK && (SOC_MT7620 || SOC_MT7621)) || COMPILE_TEST
|
||||
+ depends on (RALINK && (SOC_MT7620 || SOC_MT7621)) || ARCH_AIROHA || COMPILE_TEST
|
||||
help
|
||||
Say Y here to include support for I2C controller in the
|
||||
MediaTek MT7621/MT7628 SoCs.
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,46 @@
|
||||
From 1f038d5897fe6b439039fc28420842abcc0d126b Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 17 Jul 2024 10:15:46 +0200
|
||||
Subject: [PATCH] net: airoha: fix error branch in airoha_dev_xmit and
|
||||
airoha_set_gdm_ports
|
||||
|
||||
Fix error case management in airoha_dev_xmit routine since we need to
|
||||
DMA unmap pending buffers starting from q->head.
|
||||
Moreover fix a typo in error case branch in airoha_set_gdm_ports
|
||||
routine.
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/b628871bc8ae4861b5e2ab4db90aaf373cbb7cee.1721203880.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -977,7 +977,7 @@ static int airoha_set_gdm_ports(struct a
|
||||
return 0;
|
||||
|
||||
error:
|
||||
- for (i--; i >= 0; i++)
|
||||
+ for (i--; i >= 0; i--)
|
||||
airoha_set_gdm_port(eth, port_list[i], false);
|
||||
|
||||
return err;
|
||||
@@ -2432,9 +2432,11 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
error_unmap:
|
||||
- for (i--; i >= 0; i++)
|
||||
- dma_unmap_single(dev->dev.parent, q->entry[i].dma_addr,
|
||||
- q->entry[i].dma_len, DMA_TO_DEVICE);
|
||||
+ for (i--; i >= 0; i--) {
|
||||
+ index = (q->head + i) % q->ndesc;
|
||||
+ dma_unmap_single(dev->dev.parent, q->entry[index].dma_addr,
|
||||
+ q->entry[index].dma_len, DMA_TO_DEVICE);
|
||||
+ }
|
||||
|
||||
spin_unlock_bh(&q->lock);
|
||||
error:
|
@ -0,0 +1,39 @@
|
||||
From 4e076ff6ad5302c015617da30d877b4cdcbdf613 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 17 Jul 2024 10:47:19 +0200
|
||||
Subject: [PATCH] net: airoha: Fix NULL pointer dereference in
|
||||
airoha_qdma_cleanup_rx_queue()
|
||||
|
||||
Move page_pool_get_dma_dir() inside the while loop of
|
||||
airoha_qdma_cleanup_rx_queue routine in order to avoid possible NULL
|
||||
pointer dereference if airoha_qdma_init_rx_queue() fails before
|
||||
properly allocating the page_pool pointer.
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/7330a41bba720c33abc039955f6172457a3a34f0.1721205981.git.lorenzo@kernel.org
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1586,7 +1586,6 @@ static int airoha_qdma_init_rx_queue(str
|
||||
|
||||
static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
- enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
struct airoha_eth *eth = q->eth;
|
||||
|
||||
while (q->queued) {
|
||||
@@ -1594,7 +1593,7 @@ static void airoha_qdma_cleanup_rx_queue
|
||||
struct page *page = virt_to_head_page(e->buf);
|
||||
|
||||
dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len,
|
||||
- dir);
|
||||
+ page_pool_get_dma_dir(q->page_pool));
|
||||
page_pool_put_full_page(q->page_pool, page, false);
|
||||
q->tail = (q->tail + 1) % q->ndesc;
|
||||
q->queued--;
|
@ -0,0 +1,27 @@
|
||||
From 39a9c25bcdfb5e88995841c47439b74cac74a527 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 19 Jul 2024 22:38:31 +0200
|
||||
Subject: [PATCH] net: airoha: Fix MBI_RX_AGE_SEL_MASK definition
|
||||
|
||||
Fix copy-paste error in MBI_RX_AGE_SEL_MASK macro definition
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/d27d0465be1bff3369e886e5f10c4d37fefc4934.1721419930.git.lorenzo@kernel.org
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -249,7 +249,7 @@
|
||||
#define REG_FE_GDM_RX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2fc)
|
||||
|
||||
#define REG_GDM2_CHN_RLS (GDM2_BASE + 0x20)
|
||||
-#define MBI_RX_AGE_SEL_MASK GENMASK(18, 17)
|
||||
+#define MBI_RX_AGE_SEL_MASK GENMASK(26, 25)
|
||||
#define MBI_TX_AGE_SEL_MASK GENMASK(18, 17)
|
||||
|
||||
#define REG_GDM3_FWD_CFG GDM3_BASE
|
@ -0,0 +1,553 @@
|
||||
From 16874d1cf3818a5804cded8eaff634122b1d6c7c Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:03 +0200
|
||||
Subject: [PATCH 1/8] net: airoha: Introduce airoha_qdma struct
|
||||
|
||||
Introduce airoha_qdma struct and move qdma IO register mapping in
|
||||
airoha_qdma. This is a preliminary patch to enable both QDMA controllers
|
||||
available on EN7581 SoC.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/7df163bdc72ee29c3d27a0cbf54522ffeeafe53c.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 197 ++++++++++++---------
|
||||
1 file changed, 112 insertions(+), 85 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <uapi/linux/ppp_defs.h>
|
||||
|
||||
#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
+#define AIROHA_MAX_NUM_QDMA 1
|
||||
#define AIROHA_MAX_NUM_RSTS 3
|
||||
#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
#define AIROHA_MAX_MTU 2000
|
||||
@@ -782,6 +783,10 @@ struct airoha_hw_stats {
|
||||
u64 rx_len[7];
|
||||
};
|
||||
|
||||
+struct airoha_qdma {
|
||||
+ void __iomem *regs;
|
||||
+};
|
||||
+
|
||||
struct airoha_gdm_port {
|
||||
struct net_device *dev;
|
||||
struct airoha_eth *eth;
|
||||
@@ -794,8 +799,6 @@ struct airoha_eth {
|
||||
struct device *dev;
|
||||
|
||||
unsigned long state;
|
||||
-
|
||||
- void __iomem *qdma_regs;
|
||||
void __iomem *fe_regs;
|
||||
|
||||
/* protect concurrent irqmask accesses */
|
||||
@@ -806,6 +809,7 @@ struct airoha_eth {
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
|
||||
+ struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
|
||||
struct net_device *napi_dev;
|
||||
@@ -850,16 +854,16 @@ static u32 airoha_rmw(void __iomem *base
|
||||
#define airoha_fe_clear(eth, offset, val) \
|
||||
airoha_rmw((eth)->fe_regs, (offset), (val), 0)
|
||||
|
||||
-#define airoha_qdma_rr(eth, offset) \
|
||||
- airoha_rr((eth)->qdma_regs, (offset))
|
||||
-#define airoha_qdma_wr(eth, offset, val) \
|
||||
- airoha_wr((eth)->qdma_regs, (offset), (val))
|
||||
-#define airoha_qdma_rmw(eth, offset, mask, val) \
|
||||
- airoha_rmw((eth)->qdma_regs, (offset), (mask), (val))
|
||||
-#define airoha_qdma_set(eth, offset, val) \
|
||||
- airoha_rmw((eth)->qdma_regs, (offset), 0, (val))
|
||||
-#define airoha_qdma_clear(eth, offset, val) \
|
||||
- airoha_rmw((eth)->qdma_regs, (offset), (val), 0)
|
||||
+#define airoha_qdma_rr(qdma, offset) \
|
||||
+ airoha_rr((qdma)->regs, (offset))
|
||||
+#define airoha_qdma_wr(qdma, offset, val) \
|
||||
+ airoha_wr((qdma)->regs, (offset), (val))
|
||||
+#define airoha_qdma_rmw(qdma, offset, mask, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), (mask), (val))
|
||||
+#define airoha_qdma_set(qdma, offset, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), 0, (val))
|
||||
+#define airoha_qdma_clear(qdma, offset, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), (val), 0)
|
||||
|
||||
static void airoha_qdma_set_irqmask(struct airoha_eth *eth, int index,
|
||||
u32 clear, u32 set)
|
||||
@@ -873,11 +877,12 @@ static void airoha_qdma_set_irqmask(stru
|
||||
|
||||
eth->irqmask[index] &= ~clear;
|
||||
eth->irqmask[index] |= set;
|
||||
- airoha_qdma_wr(eth, REG_INT_ENABLE(index), eth->irqmask[index]);
|
||||
+ airoha_qdma_wr(ð->qdma[0], REG_INT_ENABLE(index),
|
||||
+ eth->irqmask[index]);
|
||||
/* Read irq_enable register in order to guarantee the update above
|
||||
* completes in the spinlock critical section.
|
||||
*/
|
||||
- airoha_qdma_rr(eth, REG_INT_ENABLE(index));
|
||||
+ airoha_qdma_rr(ð->qdma[0], REG_INT_ENABLE(index));
|
||||
|
||||
spin_unlock_irqrestore(ð->irq_lock, flags);
|
||||
}
|
||||
@@ -1383,6 +1388,7 @@ static int airoha_fe_init(struct airoha_
|
||||
static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
+ struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
struct airoha_eth *eth = q->eth;
|
||||
int qid = q - ð->q_rx[0];
|
||||
int nframes = 0;
|
||||
@@ -1420,7 +1426,8 @@ static int airoha_qdma_fill_rx_queue(str
|
||||
WRITE_ONCE(desc->msg2, 0);
|
||||
WRITE_ONCE(desc->msg3, 0);
|
||||
|
||||
- airoha_qdma_rmw(eth, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid),
|
||||
+ RX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(RX_RING_CPU_IDX_MASK, q->head));
|
||||
}
|
||||
|
||||
@@ -1529,7 +1536,8 @@ static int airoha_qdma_rx_napi_poll(stru
|
||||
}
|
||||
|
||||
static int airoha_qdma_init_rx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q, int ndesc)
|
||||
+ struct airoha_queue *q,
|
||||
+ struct airoha_qdma *qdma, int ndesc)
|
||||
{
|
||||
const struct page_pool_params pp_params = {
|
||||
.order = 0,
|
||||
@@ -1569,14 +1577,15 @@ static int airoha_qdma_init_rx_queue(str
|
||||
|
||||
netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll);
|
||||
|
||||
- airoha_qdma_wr(eth, REG_RX_RING_BASE(qid), dma_addr);
|
||||
- airoha_qdma_rmw(eth, REG_RX_RING_SIZE(qid), RX_RING_SIZE_MASK,
|
||||
+ airoha_qdma_wr(qdma, REG_RX_RING_BASE(qid), dma_addr);
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid),
|
||||
+ RX_RING_SIZE_MASK,
|
||||
FIELD_PREP(RX_RING_SIZE_MASK, ndesc));
|
||||
|
||||
thr = clamp(ndesc >> 3, 1, 32);
|
||||
- airoha_qdma_rmw(eth, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK,
|
||||
FIELD_PREP(RX_RING_THR_MASK, thr));
|
||||
- airoha_qdma_rmw(eth, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK,
|
||||
FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head));
|
||||
|
||||
airoha_qdma_fill_rx_queue(q);
|
||||
@@ -1600,7 +1609,8 @@ static void airoha_qdma_cleanup_rx_queue
|
||||
}
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_rx(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init_rx(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1613,7 +1623,7 @@ static int airoha_qdma_init_rx(struct ai
|
||||
}
|
||||
|
||||
err = airoha_qdma_init_rx_queue(eth, ð->q_rx[i],
|
||||
- RX_DSCP_NUM(i));
|
||||
+ qdma, RX_DSCP_NUM(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1624,11 +1634,13 @@ static int airoha_qdma_init_rx(struct ai
|
||||
static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct airoha_tx_irq_queue *irq_q;
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct airoha_eth *eth;
|
||||
int id, done = 0;
|
||||
|
||||
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||||
eth = irq_q->eth;
|
||||
+ qdma = ð->qdma[0];
|
||||
id = irq_q - ð->q_tx_irq[0];
|
||||
|
||||
while (irq_q->queued > 0 && done < budget) {
|
||||
@@ -1698,9 +1710,9 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
int i, len = done >> 7;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
- airoha_qdma_rmw(eth, REG_IRQ_CLEAR_LEN(id),
|
||||
+ airoha_qdma_rmw(qdma, REG_IRQ_CLEAR_LEN(id),
|
||||
IRQ_CLEAR_LEN_MASK, 0x80);
|
||||
- airoha_qdma_rmw(eth, REG_IRQ_CLEAR_LEN(id),
|
||||
+ airoha_qdma_rmw(qdma, REG_IRQ_CLEAR_LEN(id),
|
||||
IRQ_CLEAR_LEN_MASK, (done & 0x7f));
|
||||
}
|
||||
|
||||
@@ -1712,7 +1724,8 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
}
|
||||
|
||||
static int airoha_qdma_init_tx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q, int size)
|
||||
+ struct airoha_queue *q,
|
||||
+ struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
int i, qid = q - ð->q_tx[0];
|
||||
dma_addr_t dma_addr;
|
||||
@@ -1739,10 +1752,10 @@ static int airoha_qdma_init_tx_queue(str
|
||||
WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val));
|
||||
}
|
||||
|
||||
- airoha_qdma_wr(eth, REG_TX_RING_BASE(qid), dma_addr);
|
||||
- airoha_qdma_rmw(eth, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
|
||||
+ airoha_qdma_wr(qdma, REG_TX_RING_BASE(qid), dma_addr);
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
|
||||
- airoha_qdma_rmw(eth, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_DMA_IDX_MASK, q->head));
|
||||
|
||||
return 0;
|
||||
@@ -1750,7 +1763,7 @@ static int airoha_qdma_init_tx_queue(str
|
||||
|
||||
static int airoha_qdma_tx_irq_init(struct airoha_eth *eth,
|
||||
struct airoha_tx_irq_queue *irq_q,
|
||||
- int size)
|
||||
+ struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
int id = irq_q - ð->q_tx_irq[0];
|
||||
dma_addr_t dma_addr;
|
||||
@@ -1766,29 +1779,30 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
irq_q->size = size;
|
||||
irq_q->eth = eth;
|
||||
|
||||
- airoha_qdma_wr(eth, REG_TX_IRQ_BASE(id), dma_addr);
|
||||
- airoha_qdma_rmw(eth, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK,
|
||||
+ airoha_qdma_wr(qdma, REG_TX_IRQ_BASE(id), dma_addr);
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK,
|
||||
FIELD_PREP(TX_IRQ_DEPTH_MASK, size));
|
||||
- airoha_qdma_rmw(eth, REG_TX_IRQ_CFG(id), TX_IRQ_THR_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_THR_MASK,
|
||||
FIELD_PREP(TX_IRQ_THR_MASK, 1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_tx(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init_tx(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
err = airoha_qdma_tx_irq_init(eth, ð->q_tx_irq[i],
|
||||
- IRQ_QUEUE_LEN(i));
|
||||
+ qdma, IRQ_QUEUE_LEN(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
err = airoha_qdma_init_tx_queue(eth, ð->q_tx[i],
|
||||
- TX_DSCP_NUM);
|
||||
+ qdma, TX_DSCP_NUM);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1815,7 +1829,8 @@ static void airoha_qdma_cleanup_tx_queue
|
||||
spin_unlock_bh(&q->lock);
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_hfwd_queues(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init_hfwd_queues(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
dma_addr_t dma_addr;
|
||||
u32 status;
|
||||
@@ -1827,7 +1842,7 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
if (!eth->hfwd.desc)
|
||||
return -ENOMEM;
|
||||
|
||||
- airoha_qdma_wr(eth, REG_FWD_DSCP_BASE, dma_addr);
|
||||
+ airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr);
|
||||
|
||||
size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM;
|
||||
eth->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
@@ -1835,14 +1850,14 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
if (!eth->hfwd.q)
|
||||
return -ENOMEM;
|
||||
|
||||
- airoha_qdma_wr(eth, REG_FWD_BUF_BASE, dma_addr);
|
||||
+ airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr);
|
||||
|
||||
- airoha_qdma_rmw(eth, REG_HW_FWD_DSCP_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_HW_FWD_DSCP_CFG,
|
||||
HW_FWD_DSCP_PAYLOAD_SIZE_MASK,
|
||||
FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, 0));
|
||||
- airoha_qdma_rmw(eth, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK,
|
||||
FIELD_PREP(FWD_DSCP_LOW_THR_MASK, 128));
|
||||
- airoha_qdma_rmw(eth, REG_LMGR_INIT_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_LMGR_INIT_CFG,
|
||||
LMGR_INIT_START | LMGR_SRAM_MODE_MASK |
|
||||
HW_FWD_DESC_NUM_MASK,
|
||||
FIELD_PREP(HW_FWD_DESC_NUM_MASK, HW_DSCP_NUM) |
|
||||
@@ -1850,67 +1865,69 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
|
||||
return read_poll_timeout(airoha_qdma_rr, status,
|
||||
!(status & LMGR_INIT_START), USEC_PER_MSEC,
|
||||
- 30 * USEC_PER_MSEC, true, eth,
|
||||
+ 30 * USEC_PER_MSEC, true, qdma,
|
||||
REG_LMGR_INIT_CFG);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_init_qos(struct airoha_eth *eth)
|
||||
+static void airoha_qdma_init_qos(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
- airoha_qdma_clear(eth, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK);
|
||||
- airoha_qdma_set(eth, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK);
|
||||
+ airoha_qdma_clear(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK);
|
||||
+ airoha_qdma_set(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK);
|
||||
|
||||
- airoha_qdma_clear(eth, REG_PSE_BUF_USAGE_CFG,
|
||||
+ airoha_qdma_clear(qdma, REG_PSE_BUF_USAGE_CFG,
|
||||
PSE_BUF_ESTIMATE_EN_MASK);
|
||||
|
||||
- airoha_qdma_set(eth, REG_EGRESS_RATE_METER_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_EGRESS_RATE_METER_CFG,
|
||||
EGRESS_RATE_METER_EN_MASK |
|
||||
EGRESS_RATE_METER_EQ_RATE_EN_MASK);
|
||||
/* 2047us x 31 = 63.457ms */
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_RATE_METER_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_RATE_METER_CFG,
|
||||
EGRESS_RATE_METER_WINDOW_SZ_MASK,
|
||||
FIELD_PREP(EGRESS_RATE_METER_WINDOW_SZ_MASK, 0x1f));
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_RATE_METER_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_RATE_METER_CFG,
|
||||
EGRESS_RATE_METER_TIMESLICE_MASK,
|
||||
FIELD_PREP(EGRESS_RATE_METER_TIMESLICE_MASK, 0x7ff));
|
||||
|
||||
/* ratelimit init */
|
||||
- airoha_qdma_set(eth, REG_GLB_TRTCM_CFG, GLB_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_set(qdma, REG_GLB_TRTCM_CFG, GLB_TRTCM_EN_MASK);
|
||||
/* fast-tick 25us */
|
||||
- airoha_qdma_rmw(eth, REG_GLB_TRTCM_CFG, GLB_FAST_TICK_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_GLB_TRTCM_CFG, GLB_FAST_TICK_MASK,
|
||||
FIELD_PREP(GLB_FAST_TICK_MASK, 25));
|
||||
- airoha_qdma_rmw(eth, REG_GLB_TRTCM_CFG, GLB_SLOW_TICK_RATIO_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_GLB_TRTCM_CFG, GLB_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(GLB_SLOW_TICK_RATIO_MASK, 40));
|
||||
|
||||
- airoha_qdma_set(eth, REG_EGRESS_TRTCM_CFG, EGRESS_TRTCM_EN_MASK);
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_TRTCM_CFG, EGRESS_FAST_TICK_MASK,
|
||||
+ airoha_qdma_set(qdma, REG_EGRESS_TRTCM_CFG, EGRESS_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_TRTCM_CFG, EGRESS_FAST_TICK_MASK,
|
||||
FIELD_PREP(EGRESS_FAST_TICK_MASK, 25));
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_TRTCM_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_TRTCM_CFG,
|
||||
EGRESS_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(EGRESS_SLOW_TICK_RATIO_MASK, 40));
|
||||
|
||||
- airoha_qdma_set(eth, REG_INGRESS_TRTCM_CFG, INGRESS_TRTCM_EN_MASK);
|
||||
- airoha_qdma_clear(eth, REG_INGRESS_TRTCM_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_INGRESS_TRTCM_CFG, INGRESS_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_clear(qdma, REG_INGRESS_TRTCM_CFG,
|
||||
INGRESS_TRTCM_MODE_MASK);
|
||||
- airoha_qdma_rmw(eth, REG_INGRESS_TRTCM_CFG, INGRESS_FAST_TICK_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_INGRESS_TRTCM_CFG, INGRESS_FAST_TICK_MASK,
|
||||
FIELD_PREP(INGRESS_FAST_TICK_MASK, 125));
|
||||
- airoha_qdma_rmw(eth, REG_INGRESS_TRTCM_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_INGRESS_TRTCM_CFG,
|
||||
INGRESS_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(INGRESS_SLOW_TICK_RATIO_MASK, 8));
|
||||
|
||||
- airoha_qdma_set(eth, REG_SLA_TRTCM_CFG, SLA_TRTCM_EN_MASK);
|
||||
- airoha_qdma_rmw(eth, REG_SLA_TRTCM_CFG, SLA_FAST_TICK_MASK,
|
||||
+ airoha_qdma_set(qdma, REG_SLA_TRTCM_CFG, SLA_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_rmw(qdma, REG_SLA_TRTCM_CFG, SLA_FAST_TICK_MASK,
|
||||
FIELD_PREP(SLA_FAST_TICK_MASK, 25));
|
||||
- airoha_qdma_rmw(eth, REG_SLA_TRTCM_CFG, SLA_SLOW_TICK_RATIO_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_SLA_TRTCM_CFG, SLA_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40));
|
||||
}
|
||||
|
||||
-static int airoha_qdma_hw_init(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_hw_init(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* clear pending irqs */
|
||||
for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++)
|
||||
- airoha_qdma_wr(eth, REG_INT_STATUS(i), 0xffffffff);
|
||||
+ airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff);
|
||||
|
||||
/* setup irqs */
|
||||
airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX0, INT_IDX0_MASK);
|
||||
@@ -1923,14 +1940,14 @@ static int airoha_qdma_hw_init(struct ai
|
||||
continue;
|
||||
|
||||
if (TX_RING_IRQ_BLOCKING_MAP_MASK & BIT(i))
|
||||
- airoha_qdma_set(eth, REG_TX_RING_BLOCKING(i),
|
||||
+ airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(i),
|
||||
TX_RING_IRQ_BLOCKING_CFG_MASK);
|
||||
else
|
||||
- airoha_qdma_clear(eth, REG_TX_RING_BLOCKING(i),
|
||||
+ airoha_qdma_clear(qdma, REG_TX_RING_BLOCKING(i),
|
||||
TX_RING_IRQ_BLOCKING_CFG_MASK);
|
||||
}
|
||||
|
||||
- airoha_qdma_wr(eth, REG_QDMA_GLOBAL_CFG,
|
||||
+ airoha_qdma_wr(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
GLOBAL_CFG_RX_2B_OFFSET_MASK |
|
||||
FIELD_PREP(GLOBAL_CFG_DMA_PREFERENCE_MASK, 3) |
|
||||
GLOBAL_CFG_CPU_TXR_RR_MASK |
|
||||
@@ -1941,18 +1958,18 @@ static int airoha_qdma_hw_init(struct ai
|
||||
GLOBAL_CFG_TX_WB_DONE_MASK |
|
||||
FIELD_PREP(GLOBAL_CFG_MAX_ISSUE_NUM_MASK, 2));
|
||||
|
||||
- airoha_qdma_init_qos(eth);
|
||||
+ airoha_qdma_init_qos(eth, qdma);
|
||||
|
||||
/* disable qdma rx delay interrupt */
|
||||
for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
if (!eth->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- airoha_qdma_clear(eth, REG_RX_DELAY_INT_IDX(i),
|
||||
+ airoha_qdma_clear(qdma, REG_RX_DELAY_INT_IDX(i),
|
||||
RX_DELAY_INT_MASK);
|
||||
}
|
||||
|
||||
- airoha_qdma_set(eth, REG_TXQ_CNGST_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_TXQ_CNGST_CFG,
|
||||
TXQ_CNGST_DROP_EN | TXQ_CNGST_DEI_DROP_EN);
|
||||
|
||||
return 0;
|
||||
@@ -1962,12 +1979,14 @@ static irqreturn_t airoha_irq_handler(in
|
||||
{
|
||||
struct airoha_eth *eth = dev_instance;
|
||||
u32 intr[ARRAY_SIZE(eth->irqmask)];
|
||||
+ struct airoha_qdma *qdma;
|
||||
int i;
|
||||
|
||||
+ qdma = ð->qdma[0];
|
||||
for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++) {
|
||||
- intr[i] = airoha_qdma_rr(eth, REG_INT_STATUS(i));
|
||||
+ intr[i] = airoha_qdma_rr(qdma, REG_INT_STATUS(i));
|
||||
intr[i] &= eth->irqmask[i];
|
||||
- airoha_qdma_wr(eth, REG_INT_STATUS(i), intr[i]);
|
||||
+ airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]);
|
||||
}
|
||||
|
||||
if (!test_bit(DEV_STATE_INITIALIZED, ð->state))
|
||||
@@ -1997,7 +2016,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX0,
|
||||
TX_DONE_INT_MASK(i));
|
||||
|
||||
- status = airoha_qdma_rr(eth, REG_IRQ_STATUS(i));
|
||||
+ status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i));
|
||||
head = FIELD_GET(IRQ_HEAD_IDX_MASK, status);
|
||||
irq_q->head = head % irq_q->size;
|
||||
irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||||
@@ -2011,6 +2030,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
|
||||
static int airoha_qdma_init(struct airoha_eth *eth)
|
||||
{
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int err;
|
||||
|
||||
err = devm_request_irq(eth->dev, eth->irq, airoha_irq_handler,
|
||||
@@ -2018,19 +2038,19 @@ static int airoha_qdma_init(struct airoh
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_rx(eth);
|
||||
+ err = airoha_qdma_init_rx(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_tx(eth);
|
||||
+ err = airoha_qdma_init_tx(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_hfwd_queues(eth);
|
||||
+ err = airoha_qdma_init_hfwd_queues(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_hw_init(eth);
|
||||
+ err = airoha_qdma_hw_init(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -2263,8 +2283,9 @@ static int airoha_dev_open(struct net_de
|
||||
airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
GDM_STAG_EN_MASK);
|
||||
|
||||
- airoha_qdma_set(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK);
|
||||
- airoha_qdma_set(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
+ airoha_qdma_set(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
+ GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2280,8 +2301,9 @@ static int airoha_dev_stop(struct net_de
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_qdma_clear(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK);
|
||||
- airoha_qdma_clear(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
+ airoha_qdma_clear(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
+ GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2341,6 +2363,7 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
struct airoha_eth *eth = port->eth;
|
||||
u32 nr_frags = 1 + sinfo->nr_frags;
|
||||
struct netdev_queue *txq;
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct airoha_queue *q;
|
||||
void *data = skb->data;
|
||||
u16 index;
|
||||
@@ -2368,6 +2391,7 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
|
||||
|
||||
+ qdma = ð->qdma[0];
|
||||
q = ð->q_tx[qid];
|
||||
if (WARN_ON_ONCE(!q->ndesc))
|
||||
goto error;
|
||||
@@ -2412,7 +2436,8 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
e->dma_addr = addr;
|
||||
e->dma_len = len;
|
||||
|
||||
- airoha_qdma_rmw(eth, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
+ TX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
|
||||
|
||||
data = skb_frag_address(frag);
|
||||
@@ -2614,9 +2639,11 @@ static int airoha_probe(struct platform_
|
||||
return dev_err_probe(eth->dev, PTR_ERR(eth->fe_regs),
|
||||
"failed to iomap fe regs\n");
|
||||
|
||||
- eth->qdma_regs = devm_platform_ioremap_resource_byname(pdev, "qdma0");
|
||||
- if (IS_ERR(eth->qdma_regs))
|
||||
- return dev_err_probe(eth->dev, PTR_ERR(eth->qdma_regs),
|
||||
+ eth->qdma[0].regs = devm_platform_ioremap_resource_byname(pdev,
|
||||
+ "qdma0");
|
||||
+ if (IS_ERR(eth->qdma[0].regs))
|
||||
+ return dev_err_probe(eth->dev,
|
||||
+ PTR_ERR(eth->qdma[0].regs),
|
||||
"failed to iomap qdma regs\n");
|
||||
|
||||
eth->rsts[0].id = "fe";
|
@ -0,0 +1,318 @@
|
||||
From 245c7bc86b198e5ec227eba6b582da73cb0721c8 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:04 +0200
|
||||
Subject: [PATCH 2/8] net: airoha: Move airoha_queues in airoha_qdma
|
||||
|
||||
QDMA controllers available in EN7581 SoC have independent tx/rx hw queues
|
||||
so move them in airoha_queues structure.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/795fc4797bffbf7f0a1351308aa9bf0e65b5126e.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 126 +++++++++++----------
|
||||
1 file changed, 65 insertions(+), 61 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -785,6 +785,17 @@ struct airoha_hw_stats {
|
||||
|
||||
struct airoha_qdma {
|
||||
void __iomem *regs;
|
||||
+
|
||||
+ struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
+
|
||||
+ struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
+ struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
|
||||
+
|
||||
+ /* descriptor and packet buffers for qdma hw forward */
|
||||
+ struct {
|
||||
+ void *desc;
|
||||
+ void *q;
|
||||
+ } hfwd;
|
||||
};
|
||||
|
||||
struct airoha_gdm_port {
|
||||
@@ -809,20 +820,10 @@ struct airoha_eth {
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
|
||||
- struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
- struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
-
|
||||
struct net_device *napi_dev;
|
||||
- struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
- struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
|
||||
-
|
||||
- struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
|
||||
- /* descriptor and packet buffers for qdma hw forward */
|
||||
- struct {
|
||||
- void *desc;
|
||||
- void *q;
|
||||
- } hfwd;
|
||||
+ struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
+ struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
};
|
||||
|
||||
static u32 airoha_rr(void __iomem *base, u32 offset)
|
||||
@@ -1390,7 +1391,7 @@ static int airoha_qdma_fill_rx_queue(str
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
struct airoha_eth *eth = q->eth;
|
||||
- int qid = q - ð->q_rx[0];
|
||||
+ int qid = q - &qdma->q_rx[0];
|
||||
int nframes = 0;
|
||||
|
||||
while (q->queued < q->ndesc - 1) {
|
||||
@@ -1457,8 +1458,9 @@ static int airoha_qdma_get_gdm_port(stru
|
||||
static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
+ struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
struct airoha_eth *eth = q->eth;
|
||||
- int qid = q - ð->q_rx[0];
|
||||
+ int qid = q - &qdma->q_rx[0];
|
||||
int done = 0;
|
||||
|
||||
while (done < budget) {
|
||||
@@ -1550,7 +1552,7 @@ static int airoha_qdma_init_rx_queue(str
|
||||
.dev = eth->dev,
|
||||
.napi = &q->napi,
|
||||
};
|
||||
- int qid = q - ð->q_rx[0], thr;
|
||||
+ int qid = q - &qdma->q_rx[0], thr;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
q->buf_size = PAGE_SIZE / 2;
|
||||
@@ -1614,7 +1616,7 @@ static int airoha_qdma_init_rx(struct ai
|
||||
{
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
int err;
|
||||
|
||||
if (!(RX_DONE_INT_MASK & BIT(i))) {
|
||||
@@ -1622,7 +1624,7 @@ static int airoha_qdma_init_rx(struct ai
|
||||
continue;
|
||||
}
|
||||
|
||||
- err = airoha_qdma_init_rx_queue(eth, ð->q_rx[i],
|
||||
+ err = airoha_qdma_init_rx_queue(eth, &qdma->q_rx[i],
|
||||
qdma, RX_DSCP_NUM(i));
|
||||
if (err)
|
||||
return err;
|
||||
@@ -1641,7 +1643,7 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||||
eth = irq_q->eth;
|
||||
qdma = ð->qdma[0];
|
||||
- id = irq_q - ð->q_tx_irq[0];
|
||||
+ id = irq_q - &qdma->q_tx_irq[0];
|
||||
|
||||
while (irq_q->queued > 0 && done < budget) {
|
||||
u32 qid, last, val = irq_q->q[irq_q->head];
|
||||
@@ -1658,10 +1660,10 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
last = FIELD_GET(IRQ_DESC_IDX_MASK, val);
|
||||
qid = FIELD_GET(IRQ_RING_IDX_MASK, val);
|
||||
|
||||
- if (qid >= ARRAY_SIZE(eth->q_tx))
|
||||
+ if (qid >= ARRAY_SIZE(qdma->q_tx))
|
||||
continue;
|
||||
|
||||
- q = ð->q_tx[qid];
|
||||
+ q = &qdma->q_tx[qid];
|
||||
if (!q->ndesc)
|
||||
continue;
|
||||
|
||||
@@ -1727,7 +1729,7 @@ static int airoha_qdma_init_tx_queue(str
|
||||
struct airoha_queue *q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
- int i, qid = q - ð->q_tx[0];
|
||||
+ int i, qid = q - &qdma->q_tx[0];
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
@@ -1765,7 +1767,7 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
struct airoha_tx_irq_queue *irq_q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
- int id = irq_q - ð->q_tx_irq[0];
|
||||
+ int id = irq_q - &qdma->q_tx_irq[0];
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
netif_napi_add_tx(eth->napi_dev, &irq_q->napi,
|
||||
@@ -1793,15 +1795,15 @@ static int airoha_qdma_init_tx(struct ai
|
||||
{
|
||||
int i, err;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
- err = airoha_qdma_tx_irq_init(eth, ð->q_tx_irq[i],
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
+ err = airoha_qdma_tx_irq_init(eth, &qdma->q_tx_irq[i],
|
||||
qdma, IRQ_QUEUE_LEN(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
- err = airoha_qdma_init_tx_queue(eth, ð->q_tx[i],
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ err = airoha_qdma_init_tx_queue(eth, &qdma->q_tx[i],
|
||||
qdma, TX_DSCP_NUM);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -1837,17 +1839,17 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
int size;
|
||||
|
||||
size = HW_DSCP_NUM * sizeof(struct airoha_qdma_fwd_desc);
|
||||
- eth->hfwd.desc = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
- GFP_KERNEL);
|
||||
- if (!eth->hfwd.desc)
|
||||
+ qdma->hfwd.desc = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!qdma->hfwd.desc)
|
||||
return -ENOMEM;
|
||||
|
||||
airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr);
|
||||
|
||||
size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM;
|
||||
- eth->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
- GFP_KERNEL);
|
||||
- if (!eth->hfwd.q)
|
||||
+ qdma->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!qdma->hfwd.q)
|
||||
return -ENOMEM;
|
||||
|
||||
airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr);
|
||||
@@ -1935,8 +1937,8 @@ static int airoha_qdma_hw_init(struct ai
|
||||
airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX4, INT_IDX4_MASK);
|
||||
|
||||
/* setup irq binding */
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
- if (!eth->q_tx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ if (!qdma->q_tx[i].ndesc)
|
||||
continue;
|
||||
|
||||
if (TX_RING_IRQ_BLOCKING_MAP_MASK & BIT(i))
|
||||
@@ -1961,8 +1963,8 @@ static int airoha_qdma_hw_init(struct ai
|
||||
airoha_qdma_init_qos(eth, qdma);
|
||||
|
||||
/* disable qdma rx delay interrupt */
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
airoha_qdma_clear(qdma, REG_RX_DELAY_INT_IDX(i),
|
||||
@@ -1996,18 +1998,18 @@ static irqreturn_t airoha_irq_handler(in
|
||||
airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
if (intr[1] & BIT(i))
|
||||
- napi_schedule(ð->q_rx[i].napi);
|
||||
+ napi_schedule(&qdma->q_rx[i].napi);
|
||||
}
|
||||
}
|
||||
|
||||
if (intr[0] & INT_TX_MASK) {
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
- struct airoha_tx_irq_queue *irq_q = ð->q_tx_irq[i];
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
+ struct airoha_tx_irq_queue *irq_q = &qdma->q_tx_irq[i];
|
||||
u32 status, head;
|
||||
|
||||
if (!(intr[0] & TX_DONE_INT_MASK(i)))
|
||||
@@ -2021,7 +2023,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
irq_q->head = head % irq_q->size;
|
||||
irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||||
|
||||
- napi_schedule(ð->q_tx_irq[i].napi);
|
||||
+ napi_schedule(&qdma->q_tx_irq[i].napi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2080,44 +2082,46 @@ static int airoha_hw_init(struct airoha_
|
||||
|
||||
static void airoha_hw_cleanup(struct airoha_eth *eth)
|
||||
{
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- napi_disable(ð->q_rx[i].napi);
|
||||
- netif_napi_del(ð->q_rx[i].napi);
|
||||
- airoha_qdma_cleanup_rx_queue(ð->q_rx[i]);
|
||||
- if (eth->q_rx[i].page_pool)
|
||||
- page_pool_destroy(eth->q_rx[i].page_pool);
|
||||
+ napi_disable(&qdma->q_rx[i].napi);
|
||||
+ netif_napi_del(&qdma->q_rx[i].napi);
|
||||
+ airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]);
|
||||
+ if (qdma->q_rx[i].page_pool)
|
||||
+ page_pool_destroy(qdma->q_rx[i].page_pool);
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
- napi_disable(ð->q_tx_irq[i].napi);
|
||||
- netif_napi_del(ð->q_tx_irq[i].napi);
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
+ napi_disable(&qdma->q_tx_irq[i].napi);
|
||||
+ netif_napi_del(&qdma->q_tx_irq[i].napi);
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
- if (!eth->q_tx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ if (!qdma->q_tx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- airoha_qdma_cleanup_tx_queue(ð->q_tx[i]);
|
||||
+ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void airoha_qdma_start_napi(struct airoha_eth *eth)
|
||||
{
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++)
|
||||
- napi_enable(ð->q_tx_irq[i].napi);
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
|
||||
+ napi_enable(&qdma->q_tx_irq[i].napi);
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- napi_enable(ð->q_rx[i].napi);
|
||||
+ napi_enable(&qdma->q_rx[i].napi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2392,7 +2396,7 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
|
||||
|
||||
qdma = ð->qdma[0];
|
||||
- q = ð->q_tx[qid];
|
||||
+ q = &qdma->q_tx[qid];
|
||||
if (WARN_ON_ONCE(!q->ndesc))
|
||||
goto error;
|
||||
|
@ -0,0 +1,236 @@
|
||||
From 19e47fc2aeda3a657c4f64144ffd6e65f7a66601 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:05 +0200
|
||||
Subject: [PATCH 3/8] net: airoha: Move irq_mask in airoha_qdma structure
|
||||
|
||||
QDMA controllers have independent irq lines, so move irqmask in
|
||||
airoha_qdma structure. This is a preliminary patch to support multiple
|
||||
QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/1c8a06e8be605278a7b2f3cd8ac06e74bf5ebf2b.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 84 +++++++++++-----------
|
||||
1 file changed, 42 insertions(+), 42 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -786,6 +786,11 @@ struct airoha_hw_stats {
|
||||
struct airoha_qdma {
|
||||
void __iomem *regs;
|
||||
|
||||
+ /* protect concurrent irqmask accesses */
|
||||
+ spinlock_t irq_lock;
|
||||
+ u32 irqmask[QDMA_INT_REG_MAX];
|
||||
+ int irq;
|
||||
+
|
||||
struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
|
||||
struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
@@ -812,11 +817,6 @@ struct airoha_eth {
|
||||
unsigned long state;
|
||||
void __iomem *fe_regs;
|
||||
|
||||
- /* protect concurrent irqmask accesses */
|
||||
- spinlock_t irq_lock;
|
||||
- u32 irqmask[QDMA_INT_REG_MAX];
|
||||
- int irq;
|
||||
-
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
|
||||
@@ -866,38 +866,37 @@ static u32 airoha_rmw(void __iomem *base
|
||||
#define airoha_qdma_clear(qdma, offset, val) \
|
||||
airoha_rmw((qdma)->regs, (offset), (val), 0)
|
||||
|
||||
-static void airoha_qdma_set_irqmask(struct airoha_eth *eth, int index,
|
||||
+static void airoha_qdma_set_irqmask(struct airoha_qdma *qdma, int index,
|
||||
u32 clear, u32 set)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
- if (WARN_ON_ONCE(index >= ARRAY_SIZE(eth->irqmask)))
|
||||
+ if (WARN_ON_ONCE(index >= ARRAY_SIZE(qdma->irqmask)))
|
||||
return;
|
||||
|
||||
- spin_lock_irqsave(ð->irq_lock, flags);
|
||||
+ spin_lock_irqsave(&qdma->irq_lock, flags);
|
||||
|
||||
- eth->irqmask[index] &= ~clear;
|
||||
- eth->irqmask[index] |= set;
|
||||
- airoha_qdma_wr(ð->qdma[0], REG_INT_ENABLE(index),
|
||||
- eth->irqmask[index]);
|
||||
+ qdma->irqmask[index] &= ~clear;
|
||||
+ qdma->irqmask[index] |= set;
|
||||
+ airoha_qdma_wr(qdma, REG_INT_ENABLE(index), qdma->irqmask[index]);
|
||||
/* Read irq_enable register in order to guarantee the update above
|
||||
* completes in the spinlock critical section.
|
||||
*/
|
||||
- airoha_qdma_rr(ð->qdma[0], REG_INT_ENABLE(index));
|
||||
+ airoha_qdma_rr(qdma, REG_INT_ENABLE(index));
|
||||
|
||||
- spin_unlock_irqrestore(ð->irq_lock, flags);
|
||||
+ spin_unlock_irqrestore(&qdma->irq_lock, flags);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_irq_enable(struct airoha_eth *eth, int index,
|
||||
+static void airoha_qdma_irq_enable(struct airoha_qdma *qdma, int index,
|
||||
u32 mask)
|
||||
{
|
||||
- airoha_qdma_set_irqmask(eth, index, 0, mask);
|
||||
+ airoha_qdma_set_irqmask(qdma, index, 0, mask);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_irq_disable(struct airoha_eth *eth, int index,
|
||||
+static void airoha_qdma_irq_disable(struct airoha_qdma *qdma, int index,
|
||||
u32 mask)
|
||||
{
|
||||
- airoha_qdma_set_irqmask(eth, index, mask, 0);
|
||||
+ airoha_qdma_set_irqmask(qdma, index, mask, 0);
|
||||
}
|
||||
|
||||
static void airoha_set_macaddr(struct airoha_eth *eth, const u8 *addr)
|
||||
@@ -1522,7 +1521,7 @@ static int airoha_qdma_rx_process(struct
|
||||
static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct airoha_queue *q = container_of(napi, struct airoha_queue, napi);
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
int cur, done = 0;
|
||||
|
||||
do {
|
||||
@@ -1531,7 +1530,7 @@ static int airoha_qdma_rx_napi_poll(stru
|
||||
} while (cur && done < budget);
|
||||
|
||||
if (done < budget && napi_complete(napi))
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX1,
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
return done;
|
||||
@@ -1719,7 +1718,7 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
}
|
||||
|
||||
if (done < budget && napi_complete(napi))
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX0,
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0,
|
||||
TX_DONE_INT_MASK(id));
|
||||
|
||||
return done;
|
||||
@@ -1928,13 +1927,13 @@ static int airoha_qdma_hw_init(struct ai
|
||||
int i;
|
||||
|
||||
/* clear pending irqs */
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++)
|
||||
airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff);
|
||||
|
||||
/* setup irqs */
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX0, INT_IDX0_MASK);
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX1, INT_IDX1_MASK);
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX4, INT_IDX4_MASK);
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0, INT_IDX0_MASK);
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1, INT_IDX1_MASK);
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX4, INT_IDX4_MASK);
|
||||
|
||||
/* setup irq binding */
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
@@ -1980,14 +1979,13 @@ static int airoha_qdma_hw_init(struct ai
|
||||
static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
|
||||
{
|
||||
struct airoha_eth *eth = dev_instance;
|
||||
- u32 intr[ARRAY_SIZE(eth->irqmask)];
|
||||
- struct airoha_qdma *qdma;
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
+ u32 intr[ARRAY_SIZE(qdma->irqmask)];
|
||||
int i;
|
||||
|
||||
- qdma = ð->qdma[0];
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++) {
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++) {
|
||||
intr[i] = airoha_qdma_rr(qdma, REG_INT_STATUS(i));
|
||||
- intr[i] &= eth->irqmask[i];
|
||||
+ intr[i] &= qdma->irqmask[i];
|
||||
airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]);
|
||||
}
|
||||
|
||||
@@ -1995,7 +1993,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
return IRQ_NONE;
|
||||
|
||||
if (intr[1] & RX_DONE_INT_MASK) {
|
||||
- airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX1,
|
||||
+ airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
@@ -2015,7 +2013,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
if (!(intr[0] & TX_DONE_INT_MASK(i)))
|
||||
continue;
|
||||
|
||||
- airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX0,
|
||||
+ airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0,
|
||||
TX_DONE_INT_MASK(i));
|
||||
|
||||
status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i));
|
||||
@@ -2030,12 +2028,18 @@ static irqreturn_t airoha_irq_handler(in
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init(struct platform_device *pdev,
|
||||
+ struct airoha_eth *eth)
|
||||
{
|
||||
struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int err;
|
||||
|
||||
- err = devm_request_irq(eth->dev, eth->irq, airoha_irq_handler,
|
||||
+ spin_lock_init(&qdma->irq_lock);
|
||||
+ qdma->irq = platform_get_irq(pdev, 0);
|
||||
+ if (qdma->irq < 0)
|
||||
+ return qdma->irq;
|
||||
+
|
||||
+ err = devm_request_irq(eth->dev, qdma->irq, airoha_irq_handler,
|
||||
IRQF_SHARED, KBUILD_MODNAME, eth);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -2061,7 +2065,8 @@ static int airoha_qdma_init(struct airoh
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_hw_init(struct airoha_eth *eth)
|
||||
+static int airoha_hw_init(struct platform_device *pdev,
|
||||
+ struct airoha_eth *eth)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -2077,7 +2082,7 @@ static int airoha_hw_init(struct airoha_
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- return airoha_qdma_init(eth);
|
||||
+ return airoha_qdma_init(pdev, eth);
|
||||
}
|
||||
|
||||
static void airoha_hw_cleanup(struct airoha_eth *eth)
|
||||
@@ -2674,11 +2679,6 @@ static int airoha_probe(struct platform_
|
||||
return err;
|
||||
}
|
||||
|
||||
- spin_lock_init(ð->irq_lock);
|
||||
- eth->irq = platform_get_irq(pdev, 0);
|
||||
- if (eth->irq < 0)
|
||||
- return eth->irq;
|
||||
-
|
||||
eth->napi_dev = alloc_netdev_dummy(0);
|
||||
if (!eth->napi_dev)
|
||||
return -ENOMEM;
|
||||
@@ -2688,7 +2688,7 @@ static int airoha_probe(struct platform_
|
||||
strscpy(eth->napi_dev->name, "qdma_eth", sizeof(eth->napi_dev->name));
|
||||
platform_set_drvdata(pdev, eth);
|
||||
|
||||
- err = airoha_hw_init(eth);
|
||||
+ err = airoha_hw_init(pdev, eth);
|
||||
if (err)
|
||||
goto error;
|
||||
|
@ -0,0 +1,306 @@
|
||||
From 9a2500ab22f059e596942172a8e4a60ae8243ce4 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:06 +0200
|
||||
Subject: [PATCH 4/8] net: airoha: Add airoha_qdma pointer in
|
||||
airoha_tx_irq_queue/airoha_queue structures
|
||||
|
||||
Move airoha_eth pointer in airoha_qdma structure from
|
||||
airoha_tx_irq_queue/airoha_queue ones. This is a preliminary patch to
|
||||
introduce support for multi-QDMA controllers available on EN7581.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/074565b82fd0ceefe66e186f21133d825dbd48eb.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 84 +++++++++++-----------
|
||||
1 file changed, 41 insertions(+), 43 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -728,7 +728,7 @@ struct airoha_queue_entry {
|
||||
};
|
||||
|
||||
struct airoha_queue {
|
||||
- struct airoha_eth *eth;
|
||||
+ struct airoha_qdma *qdma;
|
||||
|
||||
/* protect concurrent queue accesses */
|
||||
spinlock_t lock;
|
||||
@@ -747,7 +747,7 @@ struct airoha_queue {
|
||||
};
|
||||
|
||||
struct airoha_tx_irq_queue {
|
||||
- struct airoha_eth *eth;
|
||||
+ struct airoha_qdma *qdma;
|
||||
|
||||
struct napi_struct napi;
|
||||
u32 *q;
|
||||
@@ -784,6 +784,7 @@ struct airoha_hw_stats {
|
||||
};
|
||||
|
||||
struct airoha_qdma {
|
||||
+ struct airoha_eth *eth;
|
||||
void __iomem *regs;
|
||||
|
||||
/* protect concurrent irqmask accesses */
|
||||
@@ -1388,8 +1389,8 @@ static int airoha_fe_init(struct airoha_
|
||||
static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
- struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_qdma *qdma = q->qdma;
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int qid = q - &qdma->q_rx[0];
|
||||
int nframes = 0;
|
||||
|
||||
@@ -1457,8 +1458,8 @@ static int airoha_qdma_get_gdm_port(stru
|
||||
static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
- struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_qdma *qdma = q->qdma;
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int qid = q - &qdma->q_rx[0];
|
||||
int done = 0;
|
||||
|
||||
@@ -1521,7 +1522,6 @@ static int airoha_qdma_rx_process(struct
|
||||
static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct airoha_queue *q = container_of(napi, struct airoha_queue, napi);
|
||||
- struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
int cur, done = 0;
|
||||
|
||||
do {
|
||||
@@ -1530,14 +1530,13 @@ static int airoha_qdma_rx_napi_poll(stru
|
||||
} while (cur && done < budget);
|
||||
|
||||
if (done < budget && napi_complete(napi))
|
||||
- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1,
|
||||
+ airoha_qdma_irq_enable(q->qdma, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_rx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q,
|
||||
+static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
|
||||
struct airoha_qdma *qdma, int ndesc)
|
||||
{
|
||||
const struct page_pool_params pp_params = {
|
||||
@@ -1548,15 +1547,16 @@ static int airoha_qdma_init_rx_queue(str
|
||||
.dma_dir = DMA_FROM_DEVICE,
|
||||
.max_len = PAGE_SIZE,
|
||||
.nid = NUMA_NO_NODE,
|
||||
- .dev = eth->dev,
|
||||
+ .dev = qdma->eth->dev,
|
||||
.napi = &q->napi,
|
||||
};
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int qid = q - &qdma->q_rx[0], thr;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
q->buf_size = PAGE_SIZE / 2;
|
||||
q->ndesc = ndesc;
|
||||
- q->eth = eth;
|
||||
+ q->qdma = qdma;
|
||||
|
||||
q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry),
|
||||
GFP_KERNEL);
|
||||
@@ -1596,7 +1596,7 @@ static int airoha_qdma_init_rx_queue(str
|
||||
|
||||
static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_eth *eth = q->qdma->eth;
|
||||
|
||||
while (q->queued) {
|
||||
struct airoha_queue_entry *e = &q->entry[q->tail];
|
||||
@@ -1610,8 +1610,7 @@ static void airoha_qdma_cleanup_rx_queue
|
||||
}
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_rx(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_init_rx(struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1623,8 +1622,8 @@ static int airoha_qdma_init_rx(struct ai
|
||||
continue;
|
||||
}
|
||||
|
||||
- err = airoha_qdma_init_rx_queue(eth, &qdma->q_rx[i],
|
||||
- qdma, RX_DSCP_NUM(i));
|
||||
+ err = airoha_qdma_init_rx_queue(&qdma->q_rx[i], qdma,
|
||||
+ RX_DSCP_NUM(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1640,9 +1639,9 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
int id, done = 0;
|
||||
|
||||
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||||
- eth = irq_q->eth;
|
||||
- qdma = ð->qdma[0];
|
||||
+ qdma = irq_q->qdma;
|
||||
id = irq_q - &qdma->q_tx_irq[0];
|
||||
+ eth = qdma->eth;
|
||||
|
||||
while (irq_q->queued > 0 && done < budget) {
|
||||
u32 qid, last, val = irq_q->q[irq_q->head];
|
||||
@@ -1724,16 +1723,16 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
return done;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_tx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q,
|
||||
+static int airoha_qdma_init_tx_queue(struct airoha_queue *q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int i, qid = q - &qdma->q_tx[0];
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
q->ndesc = size;
|
||||
- q->eth = eth;
|
||||
+ q->qdma = qdma;
|
||||
q->free_thr = 1 + MAX_SKB_FRAGS;
|
||||
|
||||
q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry),
|
||||
@@ -1762,11 +1761,11 @@ static int airoha_qdma_init_tx_queue(str
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_tx_irq_init(struct airoha_eth *eth,
|
||||
- struct airoha_tx_irq_queue *irq_q,
|
||||
+static int airoha_qdma_tx_irq_init(struct airoha_tx_irq_queue *irq_q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
int id = irq_q - &qdma->q_tx_irq[0];
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
netif_napi_add_tx(eth->napi_dev, &irq_q->napi,
|
||||
@@ -1778,7 +1777,7 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
|
||||
memset(irq_q->q, 0xff, size * sizeof(u32));
|
||||
irq_q->size = size;
|
||||
- irq_q->eth = eth;
|
||||
+ irq_q->qdma = qdma;
|
||||
|
||||
airoha_qdma_wr(qdma, REG_TX_IRQ_BASE(id), dma_addr);
|
||||
airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK,
|
||||
@@ -1789,21 +1788,20 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_tx(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_init_tx(struct airoha_qdma *qdma)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
- err = airoha_qdma_tx_irq_init(eth, &qdma->q_tx_irq[i],
|
||||
- qdma, IRQ_QUEUE_LEN(i));
|
||||
+ err = airoha_qdma_tx_irq_init(&qdma->q_tx_irq[i], qdma,
|
||||
+ IRQ_QUEUE_LEN(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
- err = airoha_qdma_init_tx_queue(eth, &qdma->q_tx[i],
|
||||
- qdma, TX_DSCP_NUM);
|
||||
+ err = airoha_qdma_init_tx_queue(&qdma->q_tx[i], qdma,
|
||||
+ TX_DSCP_NUM);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1813,7 +1811,7 @@ static int airoha_qdma_init_tx(struct ai
|
||||
|
||||
static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q)
|
||||
{
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_eth *eth = q->qdma->eth;
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
while (q->queued) {
|
||||
@@ -1830,9 +1828,9 @@ static void airoha_qdma_cleanup_tx_queue
|
||||
spin_unlock_bh(&q->lock);
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_hfwd_queues(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma)
|
||||
{
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
dma_addr_t dma_addr;
|
||||
u32 status;
|
||||
int size;
|
||||
@@ -1870,8 +1868,7 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
REG_LMGR_INIT_CFG);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_init_qos(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static void airoha_qdma_init_qos(struct airoha_qdma *qdma)
|
||||
{
|
||||
airoha_qdma_clear(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK);
|
||||
airoha_qdma_set(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK);
|
||||
@@ -1921,8 +1918,7 @@ static void airoha_qdma_init_qos(struct
|
||||
FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40));
|
||||
}
|
||||
|
||||
-static int airoha_qdma_hw_init(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_hw_init(struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1959,7 +1955,7 @@ static int airoha_qdma_hw_init(struct ai
|
||||
GLOBAL_CFG_TX_WB_DONE_MASK |
|
||||
FIELD_PREP(GLOBAL_CFG_MAX_ISSUE_NUM_MASK, 2));
|
||||
|
||||
- airoha_qdma_init_qos(eth, qdma);
|
||||
+ airoha_qdma_init_qos(qdma);
|
||||
|
||||
/* disable qdma rx delay interrupt */
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
@@ -2035,6 +2031,8 @@ static int airoha_qdma_init(struct platf
|
||||
int err;
|
||||
|
||||
spin_lock_init(&qdma->irq_lock);
|
||||
+ qdma->eth = eth;
|
||||
+
|
||||
qdma->irq = platform_get_irq(pdev, 0);
|
||||
if (qdma->irq < 0)
|
||||
return qdma->irq;
|
||||
@@ -2044,19 +2042,19 @@ static int airoha_qdma_init(struct platf
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_rx(eth, qdma);
|
||||
+ err = airoha_qdma_init_rx(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_tx(eth, qdma);
|
||||
+ err = airoha_qdma_init_tx(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_hfwd_queues(eth, qdma);
|
||||
+ err = airoha_qdma_init_hfwd_queues(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_hw_init(eth, qdma);
|
||||
+ err = airoha_qdma_hw_init(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -0,0 +1,45 @@
|
||||
From e3d6bfdfc0aeb8c1d7965413b1050ec07f9761e5 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:07 +0200
|
||||
Subject: [PATCH 5/8] net: airoha: Use qdma pointer as private structure in
|
||||
airoha_irq_handler routine
|
||||
|
||||
This is a preliminary patch to support multi-QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/1e40c3cb973881c0eb3c3c247c78550da62054ab.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1974,8 +1974,7 @@ static int airoha_qdma_hw_init(struct ai
|
||||
|
||||
static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
|
||||
{
|
||||
- struct airoha_eth *eth = dev_instance;
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
+ struct airoha_qdma *qdma = dev_instance;
|
||||
u32 intr[ARRAY_SIZE(qdma->irqmask)];
|
||||
int i;
|
||||
|
||||
@@ -1985,7 +1984,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]);
|
||||
}
|
||||
|
||||
- if (!test_bit(DEV_STATE_INITIALIZED, ð->state))
|
||||
+ if (!test_bit(DEV_STATE_INITIALIZED, &qdma->eth->state))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (intr[1] & RX_DONE_INT_MASK) {
|
||||
@@ -2038,7 +2037,7 @@ static int airoha_qdma_init(struct platf
|
||||
return qdma->irq;
|
||||
|
||||
err = devm_request_irq(eth->dev, qdma->irq, airoha_irq_handler,
|
||||
- IRQF_SHARED, KBUILD_MODNAME, eth);
|
||||
+ IRQF_SHARED, KBUILD_MODNAME, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -0,0 +1,131 @@
|
||||
From e618447cf492d04415007336eec025fae6e9a2ea Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:08 +0200
|
||||
Subject: [PATCH 6/8] net: airoha: Allow mapping IO region for multiple qdma
|
||||
controllers
|
||||
|
||||
Map MMIO regions of both qdma controllers available on EN7581 SoC.
|
||||
Run airoha_hw_cleanup routine for both QDMA controllers available on
|
||||
EN7581 SoC removing airoha_eth module or in airoha_probe error path.
|
||||
This is a preliminary patch to support multi-QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/a734ae608da14b67ae749b375d880dbbc70868ea.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 56 ++++++++++++----------
|
||||
1 file changed, 32 insertions(+), 24 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2024,15 +2024,25 @@ static irqreturn_t airoha_irq_handler(in
|
||||
}
|
||||
|
||||
static int airoha_qdma_init(struct platform_device *pdev,
|
||||
- struct airoha_eth *eth)
|
||||
+ struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
- int err;
|
||||
+ int err, id = qdma - ð->qdma[0];
|
||||
+ const char *res;
|
||||
|
||||
spin_lock_init(&qdma->irq_lock);
|
||||
qdma->eth = eth;
|
||||
|
||||
- qdma->irq = platform_get_irq(pdev, 0);
|
||||
+ res = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d", id);
|
||||
+ if (!res)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ qdma->regs = devm_platform_ioremap_resource_byname(pdev, res);
|
||||
+ if (IS_ERR(qdma->regs))
|
||||
+ return dev_err_probe(eth->dev, PTR_ERR(qdma->regs),
|
||||
+ "failed to iomap qdma%d regs\n", id);
|
||||
+
|
||||
+ qdma->irq = platform_get_irq(pdev, 4 * id);
|
||||
if (qdma->irq < 0)
|
||||
return qdma->irq;
|
||||
|
||||
@@ -2053,19 +2063,13 @@ static int airoha_qdma_init(struct platf
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_hw_init(qdma);
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- set_bit(DEV_STATE_INITIALIZED, ð->state);
|
||||
-
|
||||
- return 0;
|
||||
+ return airoha_qdma_hw_init(qdma);
|
||||
}
|
||||
|
||||
static int airoha_hw_init(struct platform_device *pdev,
|
||||
struct airoha_eth *eth)
|
||||
{
|
||||
- int err;
|
||||
+ int err, i;
|
||||
|
||||
/* disable xsi */
|
||||
reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts), eth->xsi_rsts);
|
||||
@@ -2079,12 +2083,19 @@ static int airoha_hw_init(struct platfor
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- return airoha_qdma_init(pdev, eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
|
||||
+ err = airoha_qdma_init(pdev, eth, ð->qdma[i]);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ set_bit(DEV_STATE_INITIALIZED, ð->state);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-static void airoha_hw_cleanup(struct airoha_eth *eth)
|
||||
+static void airoha_hw_cleanup(struct airoha_qdma *qdma)
|
||||
{
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
@@ -2645,13 +2656,6 @@ static int airoha_probe(struct platform_
|
||||
return dev_err_probe(eth->dev, PTR_ERR(eth->fe_regs),
|
||||
"failed to iomap fe regs\n");
|
||||
|
||||
- eth->qdma[0].regs = devm_platform_ioremap_resource_byname(pdev,
|
||||
- "qdma0");
|
||||
- if (IS_ERR(eth->qdma[0].regs))
|
||||
- return dev_err_probe(eth->dev,
|
||||
- PTR_ERR(eth->qdma[0].regs),
|
||||
- "failed to iomap qdma regs\n");
|
||||
-
|
||||
eth->rsts[0].id = "fe";
|
||||
eth->rsts[1].id = "pdma";
|
||||
eth->rsts[2].id = "qdma";
|
||||
@@ -2707,7 +2711,9 @@ static int airoha_probe(struct platform_
|
||||
return 0;
|
||||
|
||||
error:
|
||||
- airoha_hw_cleanup(eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_hw_cleanup(ð->qdma[i]);
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
||||
struct airoha_gdm_port *port = eth->ports[i];
|
||||
|
||||
@@ -2725,7 +2731,9 @@ static void airoha_remove(struct platfor
|
||||
struct airoha_eth *eth = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
- airoha_hw_cleanup(eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_hw_cleanup(ð->qdma[i]);
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
||||
struct airoha_gdm_port *port = eth->ports[i];
|
||||
|
@ -0,0 +1,38 @@
|
||||
From 160231e34b8e9512ba20530f3e68fb0ac499af87 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:09 +0200
|
||||
Subject: [PATCH 7/8] net: airoha: Start all qdma NAPIs in airoha_probe()
|
||||
|
||||
This is a preliminary patch to support multi-QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/b51cf69c94d8cbc81e0a0b35587f024d01e6d9c0.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2122,9 +2122,8 @@ static void airoha_hw_cleanup(struct air
|
||||
}
|
||||
}
|
||||
|
||||
-static void airoha_qdma_start_napi(struct airoha_eth *eth)
|
||||
+static void airoha_qdma_start_napi(struct airoha_qdma *qdma)
|
||||
{
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
|
||||
@@ -2693,7 +2692,9 @@ static int airoha_probe(struct platform_
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
- airoha_qdma_start_napi(eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_qdma_start_napi(ð->qdma[i]);
|
||||
+
|
||||
for_each_child_of_node(pdev->dev.of_node, np) {
|
||||
if (!of_device_is_compatible(np, "airoha,eth-mac"))
|
||||
continue;
|
@ -0,0 +1,174 @@
|
||||
From 9304640f2f78147dddf97a5ea01502ae175e41d9 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:10 +0200
|
||||
Subject: [PATCH 8/8] net: airoha: Link the gdm port to the selected qdma
|
||||
controller
|
||||
|
||||
Link the running gdm port to the qdma controller used to connect with
|
||||
the CPU. Moreover, load all QDMA controllers available on EN7581 SoC.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/95b515df34ba4727f7ae5b14a1d0462cceec84ff.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 37 +++++++++++-----------
|
||||
1 file changed, 19 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <uapi/linux/ppp_defs.h>
|
||||
|
||||
#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
-#define AIROHA_MAX_NUM_QDMA 1
|
||||
+#define AIROHA_MAX_NUM_QDMA 2
|
||||
#define AIROHA_MAX_NUM_RSTS 3
|
||||
#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
#define AIROHA_MAX_MTU 2000
|
||||
@@ -805,8 +805,8 @@ struct airoha_qdma {
|
||||
};
|
||||
|
||||
struct airoha_gdm_port {
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct net_device *dev;
|
||||
- struct airoha_eth *eth;
|
||||
int id;
|
||||
|
||||
struct airoha_hw_stats stats;
|
||||
@@ -2139,7 +2139,7 @@ static void airoha_qdma_start_napi(struc
|
||||
|
||||
static void airoha_update_hw_stats(struct airoha_gdm_port *port)
|
||||
{
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
u32 val, i = 0;
|
||||
|
||||
spin_lock(&port->stats.lock);
|
||||
@@ -2284,22 +2284,22 @@ static void airoha_update_hw_stats(struc
|
||||
static int airoha_dev_open(struct net_device *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_qdma *qdma = port->qdma;
|
||||
int err;
|
||||
|
||||
netif_tx_start_all_queues(dev);
|
||||
- err = airoha_set_gdm_ports(eth, true);
|
||||
+ err = airoha_set_gdm_ports(qdma->eth, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (netdev_uses_dsa(dev))
|
||||
- airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
+ airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
GDM_STAG_EN_MASK);
|
||||
else
|
||||
- airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
+ airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
GDM_STAG_EN_MASK);
|
||||
|
||||
- airoha_qdma_set(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
@@ -2309,15 +2309,15 @@ static int airoha_dev_open(struct net_de
|
||||
static int airoha_dev_stop(struct net_device *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_qdma *qdma = port->qdma;
|
||||
int err;
|
||||
|
||||
netif_tx_disable(dev);
|
||||
- err = airoha_set_gdm_ports(eth, false);
|
||||
+ err = airoha_set_gdm_ports(qdma->eth, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_qdma_clear(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
@@ -2333,7 +2333,7 @@ static int airoha_dev_set_macaddr(struct
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_set_macaddr(port->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2342,7 +2342,7 @@ static int airoha_dev_init(struct net_de
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
|
||||
- airoha_set_macaddr(port->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2376,10 +2376,9 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
u32 msg0 = 0, msg1, len = skb_headlen(skb);
|
||||
int i, qid = skb_get_queue_mapping(skb);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_qdma *qdma = port->qdma;
|
||||
u32 nr_frags = 1 + sinfo->nr_frags;
|
||||
struct netdev_queue *txq;
|
||||
- struct airoha_qdma *qdma;
|
||||
struct airoha_queue *q;
|
||||
void *data = skb->data;
|
||||
u16 index;
|
||||
@@ -2407,7 +2406,6 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
|
||||
|
||||
- qdma = ð->qdma[0];
|
||||
q = &qdma->q_tx[qid];
|
||||
if (WARN_ON_ONCE(!q->ndesc))
|
||||
goto error;
|
||||
@@ -2490,7 +2488,7 @@ static void airoha_ethtool_get_drvinfo(s
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
|
||||
strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver));
|
||||
strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info));
|
||||
@@ -2571,6 +2569,7 @@ static int airoha_alloc_gdm_port(struct
|
||||
{
|
||||
const __be32 *id_ptr = of_get_property(np, "reg", NULL);
|
||||
struct airoha_gdm_port *port;
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct net_device *dev;
|
||||
int err, index;
|
||||
u32 id;
|
||||
@@ -2600,6 +2599,7 @@ static int airoha_alloc_gdm_port(struct
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
+ qdma = ð->qdma[index % AIROHA_MAX_NUM_QDMA];
|
||||
dev->netdev_ops = &airoha_netdev_ops;
|
||||
dev->ethtool_ops = &airoha_ethtool_ops;
|
||||
dev->max_mtu = AIROHA_MAX_MTU;
|
||||
@@ -2609,6 +2609,7 @@ static int airoha_alloc_gdm_port(struct
|
||||
NETIF_F_SG | NETIF_F_TSO;
|
||||
dev->features |= dev->hw_features;
|
||||
dev->dev.of_node = np;
|
||||
+ dev->irq = qdma->irq;
|
||||
SET_NETDEV_DEV(dev, eth->dev);
|
||||
|
||||
err = of_get_ethdev_address(np, dev);
|
||||
@@ -2624,8 +2625,8 @@ static int airoha_alloc_gdm_port(struct
|
||||
port = netdev_priv(dev);
|
||||
u64_stats_init(&port->stats.syncp);
|
||||
spin_lock_init(&port->stats.lock);
|
||||
+ port->qdma = qdma;
|
||||
port->dev = dev;
|
||||
- port->eth = eth;
|
||||
port->id = id;
|
||||
eth->ports[index] = port;
|
||||
|
@ -0,0 +1,44 @@
|
||||
From 63a796b4988c3dca83176a534890b510d44f105a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 3 Aug 2024 17:50:50 +0200
|
||||
Subject: [PATCH] net: airoha: honor reset return value in airoha_hw_init()
|
||||
|
||||
Take into account return value from reset_control_bulk_assert and
|
||||
reset_control_bulk_deassert routines in airoha_hw_init().
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/f49dc04a87653e0155f4fab3e3eb584785c8ad6a.1722699555.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 16 ++++++++++++----
|
||||
1 file changed, 12 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2072,13 +2072,21 @@ static int airoha_hw_init(struct platfor
|
||||
int err, i;
|
||||
|
||||
/* disable xsi */
|
||||
- reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts), eth->xsi_rsts);
|
||||
+ err = reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts),
|
||||
+ eth->xsi_rsts);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = reset_control_bulk_assert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
- reset_control_bulk_assert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
- msleep(20);
|
||||
- reset_control_bulk_deassert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
msleep(20);
|
||||
+ err = reset_control_bulk_deassert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
+ msleep(20);
|
||||
err = airoha_fe_init(eth);
|
||||
if (err)
|
||||
return err;
|
@ -0,0 +1,85 @@
|
||||
From 812a2751e827fa1eb01f3bd268b4d74c23f4226a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 21 Aug 2024 09:30:14 +0200
|
||||
Subject: [PATCH] net: airoha: configure hw mac address according to the port
|
||||
id
|
||||
|
||||
GDM1 port on EN7581 SoC is connected to the lan dsa switch.
|
||||
GDM{2,3,4} can be used as wan port connected to an external
|
||||
phy module. Configure hw mac address registers according to the port id.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240821-airoha-eth-wan-mac-addr-v2-1-8706d0cd6cd5@kernel.org
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 32 ++++++++++++++++------
|
||||
1 file changed, 23 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -67,9 +67,11 @@
|
||||
#define FE_RST_GDM3_MBI_ARB_MASK BIT(2)
|
||||
#define FE_RST_CORE_MASK BIT(0)
|
||||
|
||||
+#define REG_FE_WAN_MAC_H 0x0030
|
||||
#define REG_FE_LAN_MAC_H 0x0040
|
||||
-#define REG_FE_LAN_MAC_LMIN 0x0044
|
||||
-#define REG_FE_LAN_MAC_LMAX 0x0048
|
||||
+
|
||||
+#define REG_FE_MAC_LMIN(_n) ((_n) + 0x04)
|
||||
+#define REG_FE_MAC_LMAX(_n) ((_n) + 0x08)
|
||||
|
||||
#define REG_FE_CDM1_OQ_MAP0 0x0050
|
||||
#define REG_FE_CDM1_OQ_MAP1 0x0054
|
||||
@@ -900,16 +902,28 @@ static void airoha_qdma_irq_disable(stru
|
||||
airoha_qdma_set_irqmask(qdma, index, mask, 0);
|
||||
}
|
||||
|
||||
-static void airoha_set_macaddr(struct airoha_eth *eth, const u8 *addr)
|
||||
+static bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port)
|
||||
{
|
||||
- u32 val;
|
||||
+ /* GDM1 port on EN7581 SoC is connected to the lan dsa switch.
|
||||
+ * GDM{2,3,4} can be used as wan port connected to an external
|
||||
+ * phy module.
|
||||
+ */
|
||||
+ return port->id == 1;
|
||||
+}
|
||||
+
|
||||
+static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
|
||||
+{
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
+ u32 val, reg;
|
||||
|
||||
+ reg = airhoa_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H
|
||||
+ : REG_FE_WAN_MAC_H;
|
||||
val = (addr[0] << 16) | (addr[1] << 8) | addr[2];
|
||||
- airoha_fe_wr(eth, REG_FE_LAN_MAC_H, val);
|
||||
+ airoha_fe_wr(eth, reg, val);
|
||||
|
||||
val = (addr[3] << 16) | (addr[4] << 8) | addr[5];
|
||||
- airoha_fe_wr(eth, REG_FE_LAN_MAC_LMIN, val);
|
||||
- airoha_fe_wr(eth, REG_FE_LAN_MAC_LMAX, val);
|
||||
+ airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val);
|
||||
+ airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val);
|
||||
}
|
||||
|
||||
static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr,
|
||||
@@ -2341,7 +2355,7 @@ static int airoha_dev_set_macaddr(struct
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2350,7 +2364,7 @@ static int airoha_dev_init(struct net_de
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
|
||||
- airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
From 7d2bd8ac9d2494cf9b16c4b00df9424ad24ed18c Mon Sep 17 00:00:00 2001
|
||||
From: Liao Chen <liaochen4@huawei.com>
|
||||
Date: Mon, 26 Aug 2024 09:18:58 +0000
|
||||
Subject: [PATCH] net: airoha: fix module autoloading
|
||||
|
||||
Add MODULE_DEVICE_TABLE(), so modules could be properly autoloaded
|
||||
based on the alias from of_device_id table.
|
||||
|
||||
Signed-off-by: Liao Chen <liaochen4@huawei.com>
|
||||
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240826091858.369910-4-liaochen4@huawei.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2776,6 +2776,7 @@ static const struct of_device_id of_airo
|
||||
{ .compatible = "airoha,en7581-eth" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
+MODULE_DEVICE_TABLE(of, of_airoha_match);
|
||||
|
||||
static struct platform_driver airoha_driver = {
|
||||
.probe = airoha_probe,
|
@ -0,0 +1,40 @@
|
||||
From 8e38e08f2c560328a873c35aff1a0dbea6a7d084 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 1 Oct 2024 12:10:25 +0200
|
||||
Subject: [PATCH 2/2] net: airoha: fix PSE memory configuration in
|
||||
airoha_fe_pse_ports_init()
|
||||
|
||||
Align PSE memory configuration to vendor SDK. In particular, increase
|
||||
initial value of PSE reserved memory in airoha_fe_pse_ports_init()
|
||||
routine by the value used for the second Packet Processor Engine (PPE2)
|
||||
and do not overwrite the default value.
|
||||
|
||||
Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet support
|
||||
for EN7581 SoC")
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/20241001-airoha-eth-pse-fix-v2-2-9a56cdffd074@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1166,11 +1166,13 @@ static void airoha_fe_pse_ports_init(str
|
||||
[FE_PSE_PORT_GDM4] = 2,
|
||||
[FE_PSE_PORT_CDM5] = 2,
|
||||
};
|
||||
+ u32 all_rsv;
|
||||
int q;
|
||||
|
||||
+ all_rsv = airoha_fe_get_pse_all_rsv(eth);
|
||||
/* hw misses PPE2 oq rsv */
|
||||
- airoha_fe_set(eth, REG_FE_PSE_BUF_SET,
|
||||
- PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2]);
|
||||
+ all_rsv += PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2];
|
||||
+ airoha_fe_set(eth, REG_FE_PSE_BUF_SET, all_rsv);
|
||||
|
||||
/* CMD1 */
|
||||
for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM1]; q++)
|
@ -0,0 +1,52 @@
|
||||
From 1f3e7ff4f296af1f4350f457d5bd82bc825e645a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 1 Oct 2024 12:10:24 +0200
|
||||
Subject: [PATCH 1/2] net: airoha: read default PSE reserved pages value before
|
||||
updating
|
||||
|
||||
Store the default value for the number of PSE reserved pages in orig_val
|
||||
at the beginning of airoha_fe_set_pse_oq_rsv routine, before updating it
|
||||
with airoha_fe_set_pse_queue_rsv_pages().
|
||||
Introduce airoha_fe_get_pse_all_rsv utility routine.
|
||||
|
||||
Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet support
|
||||
for EN7581 SoC")
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/20241001-airoha-eth-pse-fix-v2-1-9a56cdffd074@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 14 ++++++++++----
|
||||
1 file changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1116,17 +1116,23 @@ static void airoha_fe_set_pse_queue_rsv_
|
||||
PSE_CFG_WR_EN_MASK | PSE_CFG_OQRSV_SEL_MASK);
|
||||
}
|
||||
|
||||
+static u32 airoha_fe_get_pse_all_rsv(struct airoha_eth *eth)
|
||||
+{
|
||||
+ u32 val = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET);
|
||||
+
|
||||
+ return FIELD_GET(PSE_ALLRSV_MASK, val);
|
||||
+}
|
||||
+
|
||||
static int airoha_fe_set_pse_oq_rsv(struct airoha_eth *eth,
|
||||
u32 port, u32 queue, u32 val)
|
||||
{
|
||||
- u32 orig_val, tmp, all_rsv, fq_limit;
|
||||
+ u32 orig_val = airoha_fe_get_pse_queue_rsv_pages(eth, port, queue);
|
||||
+ u32 tmp, all_rsv, fq_limit;
|
||||
|
||||
airoha_fe_set_pse_queue_rsv_pages(eth, port, queue, val);
|
||||
|
||||
/* modify all rsv */
|
||||
- orig_val = airoha_fe_get_pse_queue_rsv_pages(eth, port, queue);
|
||||
- tmp = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET);
|
||||
- all_rsv = FIELD_GET(PSE_ALLRSV_MASK, tmp);
|
||||
+ all_rsv = airoha_fe_get_pse_all_rsv(eth);
|
||||
all_rsv += (val - orig_val);
|
||||
airoha_fe_rmw(eth, REG_FE_PSE_BUF_SET, PSE_ALLRSV_MASK,
|
||||
FIELD_PREP(PSE_ALLRSV_MASK, all_rsv));
|
@ -0,0 +1,45 @@
|
||||
From 3dc6e998d18bfba6e0dc979d3cc68eba98dfeef7 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 4 Oct 2024 15:51:26 +0200
|
||||
Subject: [PATCH] net: airoha: Update tx cpu dma ring idx at the end of xmit
|
||||
loop
|
||||
|
||||
Move the tx cpu dma ring index update out of transmit loop of
|
||||
airoha_dev_xmit routine in order to not start transmitting the packet
|
||||
before it is fully DMA mapped (e.g. fragmented skbs).
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Reported-by: Felix Fietkau <nbd@nbd.name>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/20241004-airoha-eth-7581-mapping-fix-v1-1-8e4279ab1812@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2480,10 +2480,6 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
e->dma_addr = addr;
|
||||
e->dma_len = len;
|
||||
|
||||
- airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
- TX_RING_CPU_IDX_MASK,
|
||||
- FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
|
||||
-
|
||||
data = skb_frag_address(frag);
|
||||
len = skb_frag_size(frag);
|
||||
}
|
||||
@@ -2492,6 +2488,11 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
q->queued += i;
|
||||
|
||||
skb_tx_timestamp(skb);
|
||||
+ if (!netdev_xmit_more())
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
+ TX_RING_CPU_IDX_MASK,
|
||||
+ FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
|
||||
+
|
||||
if (q->ndesc - q->queued < q->free_thr)
|
||||
netif_tx_stop_queue(txq);
|
||||
|
@ -0,0 +1,33 @@
|
||||
From 2518b119639162251b6cc7195aec394930c1d867 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 9 Oct 2024 00:21:47 +0200
|
||||
Subject: [PATCH] net: airoha: Fix EGRESS_RATE_METER_EN_MASK definition
|
||||
|
||||
Fix typo in EGRESS_RATE_METER_EN_MASK mask definition. This bus in not
|
||||
introducing any user visible problem since, even if we are setting
|
||||
EGRESS_RATE_METER_EN_MASK bit in REG_EGRESS_RATE_METER_CFG register,
|
||||
egress QoS metering is not supported yet since we are missing some other
|
||||
hw configurations (e.g token bucket rate, token bucket size).
|
||||
|
||||
Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet support
|
||||
for EN7581 SoC")
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/20241009-airoha-fixes-v2-1-18af63ec19bf@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -554,7 +554,7 @@
|
||||
#define FWD_DSCP_LOW_THR_MASK GENMASK(17, 0)
|
||||
|
||||
#define REG_EGRESS_RATE_METER_CFG 0x100c
|
||||
-#define EGRESS_RATE_METER_EN_MASK BIT(29)
|
||||
+#define EGRESS_RATE_METER_EN_MASK BIT(31)
|
||||
#define EGRESS_RATE_METER_EQ_RATE_EN_MASK BIT(17)
|
||||
#define EGRESS_RATE_METER_WINDOW_SZ_MASK GENMASK(16, 12)
|
||||
#define EGRESS_RATE_METER_TIMESLICE_MASK GENMASK(10, 0)
|
@ -0,0 +1,42 @@
|
||||
From 1d304174106c93ce05f6088813ad7203b3eb381a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 12 Oct 2024 11:01:11 +0200
|
||||
Subject: [PATCH] net: airoha: Implement BQL support
|
||||
|
||||
Introduce BQL support in the airoha_eth driver reporting to the kernel
|
||||
info about tx hw DMA queues in order to avoid bufferbloat and keep the
|
||||
latency small.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20241012-en7581-bql-v2-1-4deb4efdb60b@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1710,9 +1710,11 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
WRITE_ONCE(desc->msg1, 0);
|
||||
|
||||
if (skb) {
|
||||
+ u16 queue = skb_get_queue_mapping(skb);
|
||||
struct netdev_queue *txq;
|
||||
|
||||
- txq = netdev_get_tx_queue(skb->dev, qid);
|
||||
+ txq = netdev_get_tx_queue(skb->dev, queue);
|
||||
+ netdev_tx_completed_queue(txq, 1, skb->len);
|
||||
if (netif_tx_queue_stopped(txq) &&
|
||||
q->ndesc - q->queued >= q->free_thr)
|
||||
netif_tx_wake_queue(txq);
|
||||
@@ -2488,7 +2490,9 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
q->queued += i;
|
||||
|
||||
skb_tx_timestamp(skb);
|
||||
- if (!netdev_xmit_more())
|
||||
+ netdev_tx_sent_queue(txq, skb->len);
|
||||
+
|
||||
+ if (netif_xmit_stopped(txq) || !netdev_xmit_more())
|
||||
airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
TX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
|
@ -0,0 +1,98 @@
|
||||
From 457e74667f452d7f071ad2b2d9313ec62ebc4b02 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 6 Apr 2024 12:43:43 +0200
|
||||
Subject: [PATCH 1/2] clk: en7523: Add en_clk_soc_data data structure
|
||||
|
||||
Introduce en_clk_soc_data data structure in order to define multiple
|
||||
clk_ops for each supported SoC. This is a preliminary patch to
|
||||
introduce EN7581 clock support.
|
||||
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/562a0da8d7874a02a324687c152c87a1549924bd.1712399981.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 34 +++++++++++++++++++++-------------
|
||||
1 file changed, 21 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -3,8 +3,8 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
-#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/property.h>
|
||||
#include <dt-bindings/clock/en7523-clk.h>
|
||||
|
||||
#define REG_PCI_CONTROL 0x88
|
||||
@@ -48,6 +48,10 @@ struct en_clk_gate {
|
||||
struct clk_hw hw;
|
||||
};
|
||||
|
||||
+struct en_clk_soc_data {
|
||||
+ const struct clk_ops pcie_ops;
|
||||
+};
|
||||
+
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
static const u32 emi_base[] = { 333000000, 400000000 };
|
||||
static const u32 bus_base[] = { 500000000, 540000000 };
|
||||
@@ -150,11 +154,6 @@ static const struct en_clk_desc en7523_b
|
||||
}
|
||||
};
|
||||
|
||||
-static const struct of_device_id of_match_clk_en7523[] = {
|
||||
- { .compatible = "airoha,en7523-scu", },
|
||||
- { /* sentinel */ }
|
||||
-};
|
||||
-
|
||||
static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
|
||||
{
|
||||
const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
@@ -252,14 +251,10 @@ static void en7523_pci_unprepare(struct
|
||||
static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
|
||||
void __iomem *np_base)
|
||||
{
|
||||
- static const struct clk_ops pcie_gate_ops = {
|
||||
- .is_enabled = en7523_pci_is_enabled,
|
||||
- .prepare = en7523_pci_prepare,
|
||||
- .unprepare = en7523_pci_unprepare,
|
||||
- };
|
||||
+ const struct en_clk_soc_data *soc_data = device_get_match_data(dev);
|
||||
struct clk_init_data init = {
|
||||
.name = "pcie",
|
||||
- .ops = &pcie_gate_ops,
|
||||
+ .ops = &soc_data->pcie_ops,
|
||||
};
|
||||
struct en_clk_gate *cg;
|
||||
|
||||
@@ -269,7 +264,7 @@ static struct clk_hw *en7523_register_pc
|
||||
|
||||
cg->base = np_base;
|
||||
cg->hw.init = &init;
|
||||
- en7523_pci_unprepare(&cg->hw);
|
||||
+ init.ops->unprepare(&cg->hw);
|
||||
|
||||
if (clk_hw_register(dev, &cg->hw))
|
||||
return NULL;
|
||||
@@ -338,6 +333,19 @@ static int en7523_clk_probe(struct platf
|
||||
return r;
|
||||
}
|
||||
|
||||
+static const struct en_clk_soc_data en7523_data = {
|
||||
+ .pcie_ops = {
|
||||
+ .is_enabled = en7523_pci_is_enabled,
|
||||
+ .prepare = en7523_pci_prepare,
|
||||
+ .unprepare = en7523_pci_unprepare,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id of_match_clk_en7523[] = {
|
||||
+ { .compatible = "airoha,en7523-scu", .data = &en7523_data },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+
|
||||
static struct platform_driver clk_en7523_drv = {
|
||||
.probe = en7523_clk_probe,
|
||||
.driver = {
|
@ -0,0 +1,248 @@
|
||||
From 66bc47326ce2a319add7e933d9340215711236ac Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 6 Apr 2024 12:43:44 +0200
|
||||
Subject: [PATCH 2/2] clk: en7523: Add EN7581 support
|
||||
|
||||
Introduce EN7581 clock support to clk-en7523 driver.
|
||||
Add hw_init callback to en_clk_soc_data data structure.
|
||||
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/57b6e53ed4d2b2e38abff6a3ea56841bad6be8a9.1712399981.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 157 +++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 152 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -10,7 +10,9 @@
|
||||
#define REG_PCI_CONTROL 0x88
|
||||
#define REG_PCI_CONTROL_PERSTOUT BIT(29)
|
||||
#define REG_PCI_CONTROL_PERSTOUT1 BIT(26)
|
||||
+#define REG_PCI_CONTROL_REFCLK_EN0 BIT(23)
|
||||
#define REG_PCI_CONTROL_REFCLK_EN1 BIT(22)
|
||||
+#define REG_PCI_CONTROL_PERSTOUT2 BIT(16)
|
||||
#define REG_GSW_CLK_DIV_SEL 0x1b4
|
||||
#define REG_EMI_CLK_DIV_SEL 0x1b8
|
||||
#define REG_BUS_CLK_DIV_SEL 0x1bc
|
||||
@@ -18,10 +20,25 @@
|
||||
#define REG_SPI_CLK_FREQ_SEL 0x1c8
|
||||
#define REG_NPU_CLK_DIV_SEL 0x1fc
|
||||
#define REG_CRYPTO_CLKSRC 0x200
|
||||
-#define REG_RESET_CONTROL 0x834
|
||||
+#define REG_RESET_CONTROL2 0x830
|
||||
+#define REG_RESET2_CONTROL_PCIE2 BIT(27)
|
||||
+#define REG_RESET_CONTROL1 0x834
|
||||
#define REG_RESET_CONTROL_PCIEHB BIT(29)
|
||||
#define REG_RESET_CONTROL_PCIE1 BIT(27)
|
||||
#define REG_RESET_CONTROL_PCIE2 BIT(26)
|
||||
+/* EN7581 */
|
||||
+#define REG_PCIE0_MEM 0x00
|
||||
+#define REG_PCIE0_MEM_MASK 0x04
|
||||
+#define REG_PCIE1_MEM 0x08
|
||||
+#define REG_PCIE1_MEM_MASK 0x0c
|
||||
+#define REG_PCIE2_MEM 0x10
|
||||
+#define REG_PCIE2_MEM_MASK 0x14
|
||||
+#define REG_PCIE_RESET_OPEN_DRAIN 0x018c
|
||||
+#define REG_PCIE_RESET_OPEN_DRAIN_MASK GENMASK(2, 0)
|
||||
+#define REG_NP_SCU_PCIC 0x88
|
||||
+#define REG_NP_SCU_SSTR 0x9c
|
||||
+#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
+#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
|
||||
struct en_clk_desc {
|
||||
int id;
|
||||
@@ -50,6 +67,8 @@ struct en_clk_gate {
|
||||
|
||||
struct en_clk_soc_data {
|
||||
const struct clk_ops pcie_ops;
|
||||
+ int (*hw_init)(struct platform_device *pdev, void __iomem *base,
|
||||
+ void __iomem *np_base);
|
||||
};
|
||||
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
@@ -216,14 +235,14 @@ static int en7523_pci_prepare(struct clk
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
/* Reset to default */
|
||||
- val = readl(np_base + REG_RESET_CONTROL);
|
||||
+ val = readl(np_base + REG_RESET_CONTROL1);
|
||||
mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
REG_RESET_CONTROL_PCIEHB;
|
||||
- writel(val & ~mask, np_base + REG_RESET_CONTROL);
|
||||
+ writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
usleep_range(1000, 2000);
|
||||
- writel(val | mask, np_base + REG_RESET_CONTROL);
|
||||
+ writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
msleep(100);
|
||||
- writel(val & ~mask, np_base + REG_RESET_CONTROL);
|
||||
+ writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
usleep_range(5000, 10000);
|
||||
|
||||
/* Release device */
|
||||
@@ -264,6 +283,9 @@ static struct clk_hw *en7523_register_pc
|
||||
|
||||
cg->base = np_base;
|
||||
cg->hw.init = &init;
|
||||
+
|
||||
+ if (init.ops->disable)
|
||||
+ init.ops->disable(&cg->hw);
|
||||
init.ops->unprepare(&cg->hw);
|
||||
|
||||
if (clk_hw_register(dev, &cg->hw))
|
||||
@@ -272,6 +294,111 @@ static struct clk_hw *en7523_register_pc
|
||||
return &cg->hw;
|
||||
}
|
||||
|
||||
+static int en7581_pci_is_enabled(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
|
||||
+ val = readl(cg->base + REG_PCI_CONTROL);
|
||||
+ return (val & mask) == mask;
|
||||
+}
|
||||
+
|
||||
+static int en7581_pci_prepare(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ void __iomem *np_base = cg->base;
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
+ REG_RESET_CONTROL_PCIEHB;
|
||||
+ val = readl(np_base + REG_RESET_CONTROL1);
|
||||
+ writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
+ val = readl(np_base + REG_RESET_CONTROL2);
|
||||
+ writel(val & ~REG_RESET2_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
+ usleep_range(5000, 10000);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int en7581_pci_enable(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ void __iomem *np_base = cg->base;
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
|
||||
+ REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
|
||||
+ REG_PCI_CONTROL_PERSTOUT;
|
||||
+ val = readl(np_base + REG_PCI_CONTROL);
|
||||
+ writel(val | mask, np_base + REG_PCI_CONTROL);
|
||||
+ msleep(250);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void en7581_pci_unprepare(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ void __iomem *np_base = cg->base;
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
+ REG_RESET_CONTROL_PCIEHB;
|
||||
+ val = readl(np_base + REG_RESET_CONTROL1);
|
||||
+ writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
+ mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2;
|
||||
+ writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
+ val = readl(np_base + REG_RESET_CONTROL2);
|
||||
+ writel(val | REG_RESET_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
+ msleep(100);
|
||||
+}
|
||||
+
|
||||
+static void en7581_pci_disable(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ void __iomem *np_base = cg->base;
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
|
||||
+ REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
|
||||
+ REG_PCI_CONTROL_PERSTOUT;
|
||||
+ val = readl(np_base + REG_PCI_CONTROL);
|
||||
+ writel(val & ~mask, np_base + REG_PCI_CONTROL);
|
||||
+ usleep_range(1000, 2000);
|
||||
+}
|
||||
+
|
||||
+static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
+ void __iomem *base,
|
||||
+ void __iomem *np_base)
|
||||
+{
|
||||
+ void __iomem *pb_base;
|
||||
+ u32 val;
|
||||
+
|
||||
+ pb_base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ if (IS_ERR(pb_base))
|
||||
+ return PTR_ERR(pb_base);
|
||||
+
|
||||
+ val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
+ writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
+ writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
+
|
||||
+ writel(0x20000000, pb_base + REG_PCIE0_MEM);
|
||||
+ writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK);
|
||||
+ writel(0x24000000, pb_base + REG_PCIE1_MEM);
|
||||
+ writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK);
|
||||
+ writel(0x28000000, pb_base + REG_PCIE2_MEM);
|
||||
+ writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
|
||||
+
|
||||
+ val = readl(base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
+ writel(val | REG_PCIE_RESET_OPEN_DRAIN_MASK,
|
||||
+ base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
|
||||
void __iomem *base, void __iomem *np_base)
|
||||
{
|
||||
@@ -304,6 +431,7 @@ static void en7523_register_clocks(struc
|
||||
static int en7523_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
+ const struct en_clk_soc_data *soc_data;
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
void __iomem *base, *np_base;
|
||||
int r;
|
||||
@@ -316,6 +444,13 @@ static int en7523_clk_probe(struct platf
|
||||
if (IS_ERR(np_base))
|
||||
return PTR_ERR(np_base);
|
||||
|
||||
+ soc_data = device_get_match_data(&pdev->dev);
|
||||
+ if (soc_data->hw_init) {
|
||||
+ r = soc_data->hw_init(pdev, base, np_base);
|
||||
+ if (r)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
clk_data = devm_kzalloc(&pdev->dev,
|
||||
struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
|
||||
GFP_KERNEL);
|
||||
@@ -341,8 +476,20 @@ static const struct en_clk_soc_data en75
|
||||
},
|
||||
};
|
||||
|
||||
+static const struct en_clk_soc_data en7581_data = {
|
||||
+ .pcie_ops = {
|
||||
+ .is_enabled = en7581_pci_is_enabled,
|
||||
+ .prepare = en7581_pci_prepare,
|
||||
+ .enable = en7581_pci_enable,
|
||||
+ .unprepare = en7581_pci_unprepare,
|
||||
+ .disable = en7581_pci_disable,
|
||||
+ },
|
||||
+ .hw_init = en7581_clk_hw_init,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id of_match_clk_en7523[] = {
|
||||
{ .compatible = "airoha,en7523-scu", .data = &en7523_data },
|
||||
+ { .compatible = "airoha,en7581-scu", .data = &en7581_data },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
@ -0,0 +1,270 @@
|
||||
From e0d8ea4ed5fa70fd085a54d0b574a044b9407c39 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:23 +0200
|
||||
Subject: [PATCH 1/4] clk: en7523: Add reset-controller support for EN7581 SoC
|
||||
|
||||
Introduce reset API support to EN7581 clock driver.
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/4f735d17e549ea53769bf5a3f50406debb879a44.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 192 ++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 187 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -5,7 +5,11 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
+#include <linux/reset-controller.h>
|
||||
#include <dt-bindings/clock/en7523-clk.h>
|
||||
+#include <dt-bindings/reset/airoha,en7581-reset.h>
|
||||
+
|
||||
+#define RST_NR_PER_BANK 32
|
||||
|
||||
#define REG_PCI_CONTROL 0x88
|
||||
#define REG_PCI_CONTROL_PERSTOUT BIT(29)
|
||||
@@ -40,6 +44,9 @@
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
|
||||
+#define REG_RST_CTRL2 0x00
|
||||
+#define REG_RST_CTRL1 0x04
|
||||
+
|
||||
struct en_clk_desc {
|
||||
int id;
|
||||
const char *name;
|
||||
@@ -65,8 +72,20 @@ struct en_clk_gate {
|
||||
struct clk_hw hw;
|
||||
};
|
||||
|
||||
+struct en_rst_data {
|
||||
+ const u16 *bank_ofs;
|
||||
+ const u16 *idx_map;
|
||||
+ void __iomem *base;
|
||||
+ struct reset_controller_dev rcdev;
|
||||
+};
|
||||
+
|
||||
struct en_clk_soc_data {
|
||||
const struct clk_ops pcie_ops;
|
||||
+ struct {
|
||||
+ const u16 *bank_ofs;
|
||||
+ const u16 *idx_map;
|
||||
+ u16 idx_map_nr;
|
||||
+ } reset;
|
||||
int (*hw_init)(struct platform_device *pdev, void __iomem *base,
|
||||
void __iomem *np_base);
|
||||
};
|
||||
@@ -173,6 +192,69 @@ static const struct en_clk_desc en7523_b
|
||||
}
|
||||
};
|
||||
|
||||
+static const u16 en7581_rst_ofs[] = {
|
||||
+ REG_RST_CTRL2,
|
||||
+ REG_RST_CTRL1,
|
||||
+};
|
||||
+
|
||||
+static const u16 en7581_rst_map[] = {
|
||||
+ /* RST_CTRL2 */
|
||||
+ [EN7581_XPON_PHY_RST] = 0,
|
||||
+ [EN7581_CPU_TIMER2_RST] = 2,
|
||||
+ [EN7581_HSUART_RST] = 3,
|
||||
+ [EN7581_UART4_RST] = 4,
|
||||
+ [EN7581_UART5_RST] = 5,
|
||||
+ [EN7581_I2C2_RST] = 6,
|
||||
+ [EN7581_XSI_MAC_RST] = 7,
|
||||
+ [EN7581_XSI_PHY_RST] = 8,
|
||||
+ [EN7581_NPU_RST] = 9,
|
||||
+ [EN7581_I2S_RST] = 10,
|
||||
+ [EN7581_TRNG_RST] = 11,
|
||||
+ [EN7581_TRNG_MSTART_RST] = 12,
|
||||
+ [EN7581_DUAL_HSI0_RST] = 13,
|
||||
+ [EN7581_DUAL_HSI1_RST] = 14,
|
||||
+ [EN7581_HSI_RST] = 15,
|
||||
+ [EN7581_DUAL_HSI0_MAC_RST] = 16,
|
||||
+ [EN7581_DUAL_HSI1_MAC_RST] = 17,
|
||||
+ [EN7581_HSI_MAC_RST] = 18,
|
||||
+ [EN7581_WDMA_RST] = 19,
|
||||
+ [EN7581_WOE0_RST] = 20,
|
||||
+ [EN7581_WOE1_RST] = 21,
|
||||
+ [EN7581_HSDMA_RST] = 22,
|
||||
+ [EN7581_TDMA_RST] = 24,
|
||||
+ [EN7581_EMMC_RST] = 25,
|
||||
+ [EN7581_SOE_RST] = 26,
|
||||
+ [EN7581_PCIE2_RST] = 27,
|
||||
+ [EN7581_XFP_MAC_RST] = 28,
|
||||
+ [EN7581_USB_HOST_P1_RST] = 29,
|
||||
+ [EN7581_USB_HOST_P1_U3_PHY_RST] = 30,
|
||||
+ /* RST_CTRL1 */
|
||||
+ [EN7581_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0,
|
||||
+ [EN7581_FE_PDMA_RST] = RST_NR_PER_BANK + 1,
|
||||
+ [EN7581_FE_QDMA_RST] = RST_NR_PER_BANK + 2,
|
||||
+ [EN7581_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4,
|
||||
+ [EN7581_CRYPTO_RST] = RST_NR_PER_BANK + 6,
|
||||
+ [EN7581_TIMER_RST] = RST_NR_PER_BANK + 8,
|
||||
+ [EN7581_PCM1_RST] = RST_NR_PER_BANK + 11,
|
||||
+ [EN7581_UART_RST] = RST_NR_PER_BANK + 12,
|
||||
+ [EN7581_GPIO_RST] = RST_NR_PER_BANK + 13,
|
||||
+ [EN7581_GDMA_RST] = RST_NR_PER_BANK + 14,
|
||||
+ [EN7581_I2C_MASTER_RST] = RST_NR_PER_BANK + 16,
|
||||
+ [EN7581_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17,
|
||||
+ [EN7581_SFC_RST] = RST_NR_PER_BANK + 18,
|
||||
+ [EN7581_UART2_RST] = RST_NR_PER_BANK + 19,
|
||||
+ [EN7581_GDMP_RST] = RST_NR_PER_BANK + 20,
|
||||
+ [EN7581_FE_RST] = RST_NR_PER_BANK + 21,
|
||||
+ [EN7581_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22,
|
||||
+ [EN7581_GSW_RST] = RST_NR_PER_BANK + 23,
|
||||
+ [EN7581_SFC2_PCM_RST] = RST_NR_PER_BANK + 25,
|
||||
+ [EN7581_PCIE0_RST] = RST_NR_PER_BANK + 26,
|
||||
+ [EN7581_PCIE1_RST] = RST_NR_PER_BANK + 27,
|
||||
+ [EN7581_CPU_TIMER_RST] = RST_NR_PER_BANK + 28,
|
||||
+ [EN7581_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
|
||||
+ [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
|
||||
+};
|
||||
+
|
||||
static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
|
||||
{
|
||||
const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
@@ -375,7 +457,7 @@ static int en7581_clk_hw_init(struct pla
|
||||
void __iomem *pb_base;
|
||||
u32 val;
|
||||
|
||||
- pb_base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ pb_base = devm_platform_ioremap_resource(pdev, 3);
|
||||
if (IS_ERR(pb_base))
|
||||
return PTR_ERR(pb_base);
|
||||
|
||||
@@ -428,6 +510,95 @@ static void en7523_register_clocks(struc
|
||||
clk_data->num = EN7523_NUM_CLOCKS;
|
||||
}
|
||||
|
||||
+static int en7523_reset_update(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id, bool assert)
|
||||
+{
|
||||
+ struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
|
||||
+ void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(addr);
|
||||
+ if (assert)
|
||||
+ val |= BIT(id % RST_NR_PER_BANK);
|
||||
+ else
|
||||
+ val &= ~BIT(id % RST_NR_PER_BANK);
|
||||
+ writel(val, addr);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_assert(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id)
|
||||
+{
|
||||
+ return en7523_reset_update(rcdev, id, true);
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id)
|
||||
+{
|
||||
+ return en7523_reset_update(rcdev, id, false);
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_status(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id)
|
||||
+{
|
||||
+ struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
|
||||
+ void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
|
||||
+
|
||||
+ return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
|
||||
+ const struct of_phandle_args *reset_spec)
|
||||
+{
|
||||
+ struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
|
||||
+
|
||||
+ if (reset_spec->args[0] >= rcdev->nr_resets)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return rst_data->idx_map[reset_spec->args[0]];
|
||||
+}
|
||||
+
|
||||
+static const struct reset_control_ops en7523_reset_ops = {
|
||||
+ .assert = en7523_reset_assert,
|
||||
+ .deassert = en7523_reset_deassert,
|
||||
+ .status = en7523_reset_status,
|
||||
+};
|
||||
+
|
||||
+static int en7523_reset_register(struct platform_device *pdev,
|
||||
+ const struct en_clk_soc_data *soc_data)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct en_rst_data *rst_data;
|
||||
+ void __iomem *base;
|
||||
+
|
||||
+ /* no reset lines available */
|
||||
+ if (!soc_data->reset.idx_map_nr)
|
||||
+ return 0;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
|
||||
+ if (!rst_data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ rst_data->bank_ofs = soc_data->reset.bank_ofs;
|
||||
+ rst_data->idx_map = soc_data->reset.idx_map;
|
||||
+ rst_data->base = base;
|
||||
+
|
||||
+ rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr;
|
||||
+ rst_data->rcdev.of_xlate = en7523_reset_xlate;
|
||||
+ rst_data->rcdev.ops = &en7523_reset_ops;
|
||||
+ rst_data->rcdev.of_node = dev->of_node;
|
||||
+ rst_data->rcdev.of_reset_n_cells = 1;
|
||||
+ rst_data->rcdev.owner = THIS_MODULE;
|
||||
+ rst_data->rcdev.dev = dev;
|
||||
+
|
||||
+ return devm_reset_controller_register(dev, &rst_data->rcdev);
|
||||
+}
|
||||
+
|
||||
static int en7523_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
@@ -461,11 +632,17 @@ static int en7523_clk_probe(struct platf
|
||||
|
||||
r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
|
||||
if (r)
|
||||
- dev_err(&pdev->dev,
|
||||
- "could not register clock provider: %s: %d\n",
|
||||
- pdev->name, r);
|
||||
+ return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n",
|
||||
+ pdev->name);
|
||||
+
|
||||
+ r = en7523_reset_register(pdev, soc_data);
|
||||
+ if (r) {
|
||||
+ of_clk_del_provider(node);
|
||||
+ return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n",
|
||||
+ pdev->name);
|
||||
+ }
|
||||
|
||||
- return r;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static const struct en_clk_soc_data en7523_data = {
|
||||
@@ -484,6 +661,11 @@ static const struct en_clk_soc_data en75
|
||||
.unprepare = en7581_pci_unprepare,
|
||||
.disable = en7581_pci_disable,
|
||||
},
|
||||
+ .reset = {
|
||||
+ .bank_ofs = en7581_rst_ofs,
|
||||
+ .idx_map = en7581_rst_map,
|
||||
+ .idx_map_nr = ARRAY_SIZE(en7581_rst_map),
|
||||
+ },
|
||||
.hw_init = en7581_clk_hw_init,
|
||||
};
|
||||
|
@ -0,0 +1,91 @@
|
||||
From db7a4a11e8be375b0a9c159f688e0cea49eacc5d Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:24 +0200
|
||||
Subject: [PATCH 2/4] clk: en7523: Remove pcie prepare/unpreare callbacks for
|
||||
EN7581 SoC
|
||||
|
||||
Get rid of prepare and unpreare callbacks for PCIe clock since they can
|
||||
be modeled as a reset line cosumed by the PCIe driver
|
||||
(pcie-mediatek-gen3)
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/16df149975514d3030499c48fc1c64f090093595.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 41 ++--------------------------------------
|
||||
1 file changed, 2 insertions(+), 39 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -366,9 +366,8 @@ static struct clk_hw *en7523_register_pc
|
||||
cg->base = np_base;
|
||||
cg->hw.init = &init;
|
||||
|
||||
- if (init.ops->disable)
|
||||
- init.ops->disable(&cg->hw);
|
||||
- init.ops->unprepare(&cg->hw);
|
||||
+ if (init.ops->unprepare)
|
||||
+ init.ops->unprepare(&cg->hw);
|
||||
|
||||
if (clk_hw_register(dev, &cg->hw))
|
||||
return NULL;
|
||||
@@ -386,23 +385,6 @@ static int en7581_pci_is_enabled(struct
|
||||
return (val & mask) == mask;
|
||||
}
|
||||
|
||||
-static int en7581_pci_prepare(struct clk_hw *hw)
|
||||
-{
|
||||
- struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
- void __iomem *np_base = cg->base;
|
||||
- u32 val, mask;
|
||||
-
|
||||
- mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
- REG_RESET_CONTROL_PCIEHB;
|
||||
- val = readl(np_base + REG_RESET_CONTROL1);
|
||||
- writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
- val = readl(np_base + REG_RESET_CONTROL2);
|
||||
- writel(val & ~REG_RESET2_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
- usleep_range(5000, 10000);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int en7581_pci_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
@@ -419,23 +401,6 @@ static int en7581_pci_enable(struct clk_
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void en7581_pci_unprepare(struct clk_hw *hw)
|
||||
-{
|
||||
- struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
- void __iomem *np_base = cg->base;
|
||||
- u32 val, mask;
|
||||
-
|
||||
- mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
- REG_RESET_CONTROL_PCIEHB;
|
||||
- val = readl(np_base + REG_RESET_CONTROL1);
|
||||
- writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
- mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2;
|
||||
- writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
- val = readl(np_base + REG_RESET_CONTROL2);
|
||||
- writel(val | REG_RESET_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
- msleep(100);
|
||||
-}
|
||||
-
|
||||
static void en7581_pci_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
@@ -656,9 +621,7 @@ static const struct en_clk_soc_data en75
|
||||
static const struct en_clk_soc_data en7581_data = {
|
||||
.pcie_ops = {
|
||||
.is_enabled = en7581_pci_is_enabled,
|
||||
- .prepare = en7581_pci_prepare,
|
||||
.enable = en7581_pci_enable,
|
||||
- .unprepare = en7581_pci_unprepare,
|
||||
.disable = en7581_pci_disable,
|
||||
},
|
||||
.reset = {
|
@ -0,0 +1,65 @@
|
||||
From bf288bd25d6232310abb81db417376ce460eb032 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:25 +0200
|
||||
Subject: [PATCH 3/4] clk: en7523: Remove PCIe reset open drain configuration
|
||||
for EN7581
|
||||
|
||||
PCIe reset open drain configuration will be managed by pinctrl driver.
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/43276af5f08a554b4ab2e52e8d437fff5c06a732.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 12 ++----------
|
||||
1 file changed, 2 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -37,8 +37,6 @@
|
||||
#define REG_PCIE1_MEM_MASK 0x0c
|
||||
#define REG_PCIE2_MEM 0x10
|
||||
#define REG_PCIE2_MEM_MASK 0x14
|
||||
-#define REG_PCIE_RESET_OPEN_DRAIN 0x018c
|
||||
-#define REG_PCIE_RESET_OPEN_DRAIN_MASK GENMASK(2, 0)
|
||||
#define REG_NP_SCU_PCIC 0x88
|
||||
#define REG_NP_SCU_SSTR 0x9c
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
@@ -86,8 +84,7 @@ struct en_clk_soc_data {
|
||||
const u16 *idx_map;
|
||||
u16 idx_map_nr;
|
||||
} reset;
|
||||
- int (*hw_init)(struct platform_device *pdev, void __iomem *base,
|
||||
- void __iomem *np_base);
|
||||
+ int (*hw_init)(struct platform_device *pdev, void __iomem *np_base);
|
||||
};
|
||||
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
@@ -416,7 +413,6 @@ static void en7581_pci_disable(struct cl
|
||||
}
|
||||
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
- void __iomem *base,
|
||||
void __iomem *np_base)
|
||||
{
|
||||
void __iomem *pb_base;
|
||||
@@ -439,10 +435,6 @@ static int en7581_clk_hw_init(struct pla
|
||||
writel(0x28000000, pb_base + REG_PCIE2_MEM);
|
||||
writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
|
||||
|
||||
- val = readl(base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
- writel(val | REG_PCIE_RESET_OPEN_DRAIN_MASK,
|
||||
- base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -582,7 +574,7 @@ static int en7523_clk_probe(struct platf
|
||||
|
||||
soc_data = device_get_match_data(&pdev->dev);
|
||||
if (soc_data->hw_init) {
|
||||
- r = soc_data->hw_init(pdev, base, np_base);
|
||||
+ r = soc_data->hw_init(pdev, np_base);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
From 7aa291962f4c3b7afb9a12fa60b406b95e5eacb4 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:22 +0200
|
||||
Subject: [PATCH] dt-bindings: clock: airoha: Add reset support to EN7581 clock
|
||||
binding
|
||||
|
||||
Introduce reset capability to EN7581 device-tree clock binding
|
||||
documentation. Add reset register mapping between misc scu and pb scu
|
||||
ones in order to follow the memory order. This change is not
|
||||
introducing any backward compatibility issue since the EN7581 dts is not
|
||||
upstream yet.
|
||||
|
||||
Fixes: 0a382be005cf ("dt-bindings: clock: airoha: add EN7581 binding")
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/28fef3e83062d5d71e7b4be4b47583f851a15bf8.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
.../bindings/clock/airoha,en7523-scu.yaml | 25 ++++++-
|
||||
.../dt-bindings/reset/airoha,en7581-reset.h | 66 +++++++++++++++++++
|
||||
2 files changed, 90 insertions(+), 1 deletion(-)
|
||||
create mode 100644 include/dt-bindings/reset/airoha,en7581-reset.h
|
||||
|
||||
--- /dev/null
|
||||
+++ b/include/dt-bindings/reset/airoha,en7581-reset.h
|
||||
@@ -0,0 +1,66 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2024 AIROHA Inc
|
||||
+ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
+ */
|
||||
+
|
||||
+#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7581_H_
|
||||
+#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7581_H_
|
||||
+
|
||||
+/* RST_CTRL2 */
|
||||
+#define EN7581_XPON_PHY_RST 0
|
||||
+#define EN7581_CPU_TIMER2_RST 1
|
||||
+#define EN7581_HSUART_RST 2
|
||||
+#define EN7581_UART4_RST 3
|
||||
+#define EN7581_UART5_RST 4
|
||||
+#define EN7581_I2C2_RST 5
|
||||
+#define EN7581_XSI_MAC_RST 6
|
||||
+#define EN7581_XSI_PHY_RST 7
|
||||
+#define EN7581_NPU_RST 8
|
||||
+#define EN7581_I2S_RST 9
|
||||
+#define EN7581_TRNG_RST 10
|
||||
+#define EN7581_TRNG_MSTART_RST 11
|
||||
+#define EN7581_DUAL_HSI0_RST 12
|
||||
+#define EN7581_DUAL_HSI1_RST 13
|
||||
+#define EN7581_HSI_RST 14
|
||||
+#define EN7581_DUAL_HSI0_MAC_RST 15
|
||||
+#define EN7581_DUAL_HSI1_MAC_RST 16
|
||||
+#define EN7581_HSI_MAC_RST 17
|
||||
+#define EN7581_WDMA_RST 18
|
||||
+#define EN7581_WOE0_RST 19
|
||||
+#define EN7581_WOE1_RST 20
|
||||
+#define EN7581_HSDMA_RST 21
|
||||
+#define EN7581_TDMA_RST 22
|
||||
+#define EN7581_EMMC_RST 23
|
||||
+#define EN7581_SOE_RST 24
|
||||
+#define EN7581_PCIE2_RST 25
|
||||
+#define EN7581_XFP_MAC_RST 26
|
||||
+#define EN7581_USB_HOST_P1_RST 27
|
||||
+#define EN7581_USB_HOST_P1_U3_PHY_RST 28
|
||||
+/* RST_CTRL1 */
|
||||
+#define EN7581_PCM1_ZSI_ISI_RST 29
|
||||
+#define EN7581_FE_PDMA_RST 30
|
||||
+#define EN7581_FE_QDMA_RST 31
|
||||
+#define EN7581_PCM_SPIWP_RST 32
|
||||
+#define EN7581_CRYPTO_RST 33
|
||||
+#define EN7581_TIMER_RST 34
|
||||
+#define EN7581_PCM1_RST 35
|
||||
+#define EN7581_UART_RST 36
|
||||
+#define EN7581_GPIO_RST 37
|
||||
+#define EN7581_GDMA_RST 38
|
||||
+#define EN7581_I2C_MASTER_RST 39
|
||||
+#define EN7581_PCM2_ZSI_ISI_RST 40
|
||||
+#define EN7581_SFC_RST 41
|
||||
+#define EN7581_UART2_RST 42
|
||||
+#define EN7581_GDMP_RST 43
|
||||
+#define EN7581_FE_RST 44
|
||||
+#define EN7581_USB_HOST_P0_RST 45
|
||||
+#define EN7581_GSW_RST 46
|
||||
+#define EN7581_SFC2_PCM_RST 47
|
||||
+#define EN7581_PCIE0_RST 48
|
||||
+#define EN7581_PCIE1_RST 49
|
||||
+#define EN7581_CPU_TIMER_RST 50
|
||||
+#define EN7581_PCIE_HB_RST 51
|
||||
+#define EN7581_XPON_MAC_RST 52
|
||||
+
|
||||
+#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7581_H_ */
|
@ -0,0 +1,100 @@
|
||||
From dc869a40d73ee6e9f47d683690ae507e30e56044 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 3 Jul 2024 18:12:42 +0200
|
||||
Subject: [PATCH 1/3] PCI: mediatek-gen3: Add mtk_gen3_pcie_pdata data
|
||||
structure
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Introduce mtk_gen3_pcie_pdata data structure in order to define
|
||||
multiple callbacks for each supported SoC.
|
||||
|
||||
This is a preliminary patch to introduce EN7581 PCIe support.
|
||||
|
||||
Link: https://lore.kernel.org/linux-pci/c193d1a87505d045e2e0ef33317bce17012ee095.1720022580.git.lorenzo@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Acked-by: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 24 ++++++++++++++++++---
|
||||
1 file changed, 21 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -100,6 +100,16 @@
|
||||
#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
|
||||
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
|
||||
|
||||
+struct mtk_gen3_pcie;
|
||||
+
|
||||
+/**
|
||||
+ * struct mtk_gen3_pcie_pdata - differentiate between host generations
|
||||
+ * @power_up: pcie power_up callback
|
||||
+ */
|
||||
+struct mtk_gen3_pcie_pdata {
|
||||
+ int (*power_up)(struct mtk_gen3_pcie *pcie);
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct mtk_msi_set - MSI information for each set
|
||||
* @base: IO mapped register base
|
||||
@@ -131,6 +141,7 @@ struct mtk_msi_set {
|
||||
* @msi_sets: MSI sets information
|
||||
* @lock: lock protecting IRQ bit map
|
||||
* @msi_irq_in_use: bit map for assigned MSI IRQ
|
||||
+ * @soc: pointer to SoC-dependent operations
|
||||
*/
|
||||
struct mtk_gen3_pcie {
|
||||
struct device *dev;
|
||||
@@ -151,6 +162,8 @@ struct mtk_gen3_pcie {
|
||||
struct mtk_msi_set msi_sets[PCIE_MSI_SET_NUM];
|
||||
struct mutex lock;
|
||||
DECLARE_BITMAP(msi_irq_in_use, PCIE_MSI_IRQS_NUM);
|
||||
+
|
||||
+ const struct mtk_gen3_pcie_pdata *soc;
|
||||
};
|
||||
|
||||
/* LTSSM state in PCIE_LTSSM_STATUS_REG bit[28:24] */
|
||||
@@ -904,7 +917,7 @@ static int mtk_pcie_setup(struct mtk_gen
|
||||
usleep_range(10, 20);
|
||||
|
||||
/* Don't touch the hardware registers before power up */
|
||||
- err = mtk_pcie_power_up(pcie);
|
||||
+ err = pcie->soc->power_up(pcie);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -939,6 +952,7 @@ static int mtk_pcie_probe(struct platfor
|
||||
pcie = pci_host_bridge_priv(host);
|
||||
|
||||
pcie->dev = dev;
|
||||
+ pcie->soc = device_get_match_data(dev);
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
err = mtk_pcie_setup(pcie);
|
||||
@@ -1054,7 +1068,7 @@ static int mtk_pcie_resume_noirq(struct
|
||||
struct mtk_gen3_pcie *pcie = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
- err = mtk_pcie_power_up(pcie);
|
||||
+ err = pcie->soc->power_up(pcie);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1074,8 +1088,12 @@ static const struct dev_pm_ops mtk_pcie_
|
||||
mtk_pcie_resume_noirq)
|
||||
};
|
||||
|
||||
+static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_mt8192 = {
|
||||
+ .power_up = mtk_pcie_power_up,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id mtk_pcie_of_match[] = {
|
||||
- { .compatible = "mediatek,mt8192-pcie" },
|
||||
+ { .compatible = "mediatek,mt8192-pcie", .data = &mtk_pcie_soc_mt8192 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_pcie_of_match);
|
@ -0,0 +1,155 @@
|
||||
From ee9eabbe3f0f0c7458d89840add97e54d4e0bccf Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 3 Jul 2024 18:12:43 +0200
|
||||
Subject: [PATCH 2/3] PCI: mediatek-gen3: Rely on reset_bulk APIs for PHY reset
|
||||
lines
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Use reset_bulk APIs to manage PHY reset lines.
|
||||
|
||||
This is a preliminary patch in order to add Airoha EN7581 PCIe support.
|
||||
|
||||
Link: https://lore.kernel.org/linux-pci/3ceb83bc0defbcf868521f8df4b9100e55ec2614.1720022580.git.lorenzo@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Acked-by: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 45 +++++++++++++++------
|
||||
1 file changed, 33 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -100,14 +100,21 @@
|
||||
#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
|
||||
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
|
||||
|
||||
+#define MAX_NUM_PHY_RESETS 1
|
||||
+
|
||||
struct mtk_gen3_pcie;
|
||||
|
||||
/**
|
||||
* struct mtk_gen3_pcie_pdata - differentiate between host generations
|
||||
* @power_up: pcie power_up callback
|
||||
+ * @phy_resets: phy reset lines SoC data.
|
||||
*/
|
||||
struct mtk_gen3_pcie_pdata {
|
||||
int (*power_up)(struct mtk_gen3_pcie *pcie);
|
||||
+ struct {
|
||||
+ const char *id[MAX_NUM_PHY_RESETS];
|
||||
+ int num_resets;
|
||||
+ } phy_resets;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -128,7 +135,7 @@ struct mtk_msi_set {
|
||||
* @base: IO mapped register base
|
||||
* @reg_base: physical register base
|
||||
* @mac_reset: MAC reset control
|
||||
- * @phy_reset: PHY reset control
|
||||
+ * @phy_resets: PHY reset controllers
|
||||
* @phy: PHY controller block
|
||||
* @clks: PCIe clocks
|
||||
* @num_clks: PCIe clocks count for this port
|
||||
@@ -148,7 +155,7 @@ struct mtk_gen3_pcie {
|
||||
void __iomem *base;
|
||||
phys_addr_t reg_base;
|
||||
struct reset_control *mac_reset;
|
||||
- struct reset_control *phy_reset;
|
||||
+ struct reset_control_bulk_data phy_resets[MAX_NUM_PHY_RESETS];
|
||||
struct phy *phy;
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
@@ -788,10 +795,10 @@ static int mtk_pcie_setup_irq(struct mtk
|
||||
|
||||
static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
|
||||
{
|
||||
+ int i, ret, num_resets = pcie->soc->phy_resets.num_resets;
|
||||
struct device *dev = pcie->dev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct resource *regs;
|
||||
- int ret;
|
||||
|
||||
regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcie-mac");
|
||||
if (!regs)
|
||||
@@ -804,12 +811,12 @@ static int mtk_pcie_parse_port(struct mt
|
||||
|
||||
pcie->reg_base = regs->start;
|
||||
|
||||
- pcie->phy_reset = devm_reset_control_get_optional_exclusive(dev, "phy");
|
||||
- if (IS_ERR(pcie->phy_reset)) {
|
||||
- ret = PTR_ERR(pcie->phy_reset);
|
||||
- if (ret != -EPROBE_DEFER)
|
||||
- dev_err(dev, "failed to get PHY reset\n");
|
||||
+ for (i = 0; i < num_resets; i++)
|
||||
+ pcie->phy_resets[i].id = pcie->soc->phy_resets.id[i];
|
||||
|
||||
+ ret = devm_reset_control_bulk_get_optional_shared(dev, num_resets, pcie->phy_resets);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to get PHY bulk reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -846,7 +853,11 @@ static int mtk_pcie_power_up(struct mtk_
|
||||
int err;
|
||||
|
||||
/* PHY power on and enable pipe clock */
|
||||
- reset_control_deassert(pcie->phy_reset);
|
||||
+ err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to deassert PHYs\n");
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
err = phy_init(pcie->phy);
|
||||
if (err) {
|
||||
@@ -882,7 +893,7 @@ err_clk_init:
|
||||
err_phy_on:
|
||||
phy_exit(pcie->phy);
|
||||
err_phy_init:
|
||||
- reset_control_assert(pcie->phy_reset);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -897,7 +908,7 @@ static void mtk_pcie_power_down(struct m
|
||||
|
||||
phy_power_off(pcie->phy);
|
||||
phy_exit(pcie->phy);
|
||||
- reset_control_assert(pcie->phy_reset);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
}
|
||||
|
||||
static int mtk_pcie_setup(struct mtk_gen3_pcie *pcie)
|
||||
@@ -909,10 +920,16 @@ static int mtk_pcie_setup(struct mtk_gen
|
||||
return err;
|
||||
|
||||
/*
|
||||
+ * Deassert the line in order to avoid unbalance in deassert_count
|
||||
+ * counter since the bulk is shared.
|
||||
+ */
|
||||
+ reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+ /*
|
||||
* The controller may have been left out of reset by the bootloader
|
||||
* so make sure that we get a clean start by asserting resets here.
|
||||
*/
|
||||
- reset_control_assert(pcie->phy_reset);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+
|
||||
reset_control_assert(pcie->mac_reset);
|
||||
usleep_range(10, 20);
|
||||
|
||||
@@ -1090,6 +1107,10 @@ static const struct dev_pm_ops mtk_pcie_
|
||||
|
||||
static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_mt8192 = {
|
||||
.power_up = mtk_pcie_power_up,
|
||||
+ .phy_resets = {
|
||||
+ .id[0] = "phy",
|
||||
+ .num_resets = 1,
|
||||
+ },
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_pcie_of_match[] = {
|
@ -0,0 +1,199 @@
|
||||
From f6ab898356dd70f267c49045a79d28ea5cf5e43e Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 3 Jul 2024 18:12:44 +0200
|
||||
Subject: [PATCH 3/3] PCI: mediatek-gen3: Add Airoha EN7581 support
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Introduce support for Airoha EN7581 PCIe controller to mediatek-gen3
|
||||
PCIe controller driver.
|
||||
|
||||
Link: https://lore.kernel.org/linux-pci/aca00bd672ee576ad96d279414fc0835ff31f637.1720022580.git.lorenzo@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Acked-by: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
---
|
||||
drivers/pci/controller/Kconfig | 2 +-
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 113 +++++++++++++++++++-
|
||||
2 files changed, 113 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/Kconfig
|
||||
+++ b/drivers/pci/controller/Kconfig
|
||||
@@ -196,7 +196,7 @@ config PCIE_MEDIATEK
|
||||
|
||||
config PCIE_MEDIATEK_GEN3
|
||||
tristate "MediaTek Gen3 PCIe controller"
|
||||
- depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
+ depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST
|
||||
depends on PCI_MSI
|
||||
help
|
||||
Adds support for PCIe Gen3 MAC controller for MediaTek SoCs.
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -6,7 +6,9 @@
|
||||
* Author: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
*/
|
||||
|
||||
+#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
+#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/irq.h>
|
||||
@@ -15,6 +17,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/msi.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/of_pci.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -29,6 +33,12 @@
|
||||
#define PCI_CLASS(class) (class << 8)
|
||||
#define PCIE_RC_MODE BIT(0)
|
||||
|
||||
+#define PCIE_EQ_PRESET_01_REG 0x100
|
||||
+#define PCIE_VAL_LN0_DOWNSTREAM GENMASK(6, 0)
|
||||
+#define PCIE_VAL_LN0_UPSTREAM GENMASK(14, 8)
|
||||
+#define PCIE_VAL_LN1_DOWNSTREAM GENMASK(22, 16)
|
||||
+#define PCIE_VAL_LN1_UPSTREAM GENMASK(30, 24)
|
||||
+
|
||||
#define PCIE_CFGNUM_REG 0x140
|
||||
#define PCIE_CFG_DEVFN(devfn) ((devfn) & GENMASK(7, 0))
|
||||
#define PCIE_CFG_BUS(bus) (((bus) << 8) & GENMASK(15, 8))
|
||||
@@ -68,6 +78,14 @@
|
||||
#define PCIE_MSI_SET_ENABLE_REG 0x190
|
||||
#define PCIE_MSI_SET_ENABLE GENMASK(PCIE_MSI_SET_NUM - 1, 0)
|
||||
|
||||
+#define PCIE_PIPE4_PIE8_REG 0x338
|
||||
+#define PCIE_K_FINETUNE_MAX GENMASK(5, 0)
|
||||
+#define PCIE_K_FINETUNE_ERR GENMASK(7, 6)
|
||||
+#define PCIE_K_PRESET_TO_USE GENMASK(18, 8)
|
||||
+#define PCIE_K_PHYPARAM_QUERY BIT(19)
|
||||
+#define PCIE_K_QUERY_TIMEOUT BIT(20)
|
||||
+#define PCIE_K_PRESET_TO_USE_16G GENMASK(31, 21)
|
||||
+
|
||||
#define PCIE_MSI_SET_BASE_REG 0xc00
|
||||
#define PCIE_MSI_SET_OFFSET 0x10
|
||||
#define PCIE_MSI_SET_STATUS_OFFSET 0x04
|
||||
@@ -100,7 +118,10 @@
|
||||
#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
|
||||
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
|
||||
|
||||
-#define MAX_NUM_PHY_RESETS 1
|
||||
+#define MAX_NUM_PHY_RESETS 3
|
||||
+
|
||||
+/* Time in ms needed to complete PCIe reset on EN7581 SoC */
|
||||
+#define PCIE_EN7581_RESET_TIME_MS 100
|
||||
|
||||
struct mtk_gen3_pcie;
|
||||
|
||||
@@ -847,6 +868,85 @@ static int mtk_pcie_parse_port(struct mt
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
|
||||
+{
|
||||
+ struct device *dev = pcie->dev;
|
||||
+ int err;
|
||||
+ u32 val;
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for the time needed to complete the bulk assert in
|
||||
+ * mtk_pcie_setup for EN7581 SoC.
|
||||
+ */
|
||||
+ mdelay(PCIE_EN7581_RESET_TIME_MS);
|
||||
+
|
||||
+ err = phy_init(pcie->phy);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to initialize PHY\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ err = phy_power_on(pcie->phy);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to power on PHY\n");
|
||||
+ goto err_phy_on;
|
||||
+ }
|
||||
+
|
||||
+ err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to deassert PHYs\n");
|
||||
+ goto err_phy_deassert;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for the time needed to complete the bulk de-assert above.
|
||||
+ * This time is specific for EN7581 SoC.
|
||||
+ */
|
||||
+ mdelay(PCIE_EN7581_RESET_TIME_MS);
|
||||
+
|
||||
+ pm_runtime_enable(dev);
|
||||
+ pm_runtime_get_sync(dev);
|
||||
+
|
||||
+ err = clk_bulk_prepare(pcie->num_clks, pcie->clks);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to prepare clock\n");
|
||||
+ goto err_clk_prepare;
|
||||
+ }
|
||||
+
|
||||
+ val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) |
|
||||
+ FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) |
|
||||
+ FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) |
|
||||
+ FIELD_PREP(PCIE_VAL_LN1_UPSTREAM, 0x41);
|
||||
+ writel_relaxed(val, pcie->base + PCIE_EQ_PRESET_01_REG);
|
||||
+
|
||||
+ val = PCIE_K_PHYPARAM_QUERY | PCIE_K_QUERY_TIMEOUT |
|
||||
+ FIELD_PREP(PCIE_K_PRESET_TO_USE_16G, 0x80) |
|
||||
+ FIELD_PREP(PCIE_K_PRESET_TO_USE, 0x2) |
|
||||
+ FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf);
|
||||
+ writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG);
|
||||
+
|
||||
+ err = clk_bulk_enable(pcie->num_clks, pcie->clks);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to prepare clock\n");
|
||||
+ goto err_clk_enable;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_clk_enable:
|
||||
+ clk_bulk_unprepare(pcie->num_clks, pcie->clks);
|
||||
+err_clk_prepare:
|
||||
+ pm_runtime_put_sync(dev);
|
||||
+ pm_runtime_disable(dev);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+err_phy_deassert:
|
||||
+ phy_power_off(pcie->phy);
|
||||
+err_phy_on:
|
||||
+ phy_exit(pcie->phy);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
static int mtk_pcie_power_up(struct mtk_gen3_pcie *pcie)
|
||||
{
|
||||
struct device *dev = pcie->dev;
|
||||
@@ -1113,7 +1213,18 @@ static const struct mtk_gen3_pcie_pdata
|
||||
},
|
||||
};
|
||||
|
||||
+static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_en7581 = {
|
||||
+ .power_up = mtk_pcie_en7581_power_up,
|
||||
+ .phy_resets = {
|
||||
+ .id[0] = "phy-lane0",
|
||||
+ .id[1] = "phy-lane1",
|
||||
+ .id[2] = "phy-lane2",
|
||||
+ .num_resets = 3,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id mtk_pcie_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-pcie", .data = &mtk_pcie_soc_en7581 },
|
||||
{ .compatible = "mediatek,mt8192-pcie", .data = &mtk_pcie_soc_mt8192 },
|
||||
{},
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,112 @@
|
||||
From 2a011c3c12e8de461fb1fdce85fa38d308c4eb8b Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 29 Jun 2024 19:51:49 +0200
|
||||
Subject: [PATCH] phy: airoha: Add dtime and Rx AEQ IO registers
|
||||
|
||||
Introduce Tx-Rx detection Time and Rx AEQ training mappings to
|
||||
phy-airoha-pcie driver. This is a preliminary patch to introduce PCIe
|
||||
support to En7581 SoC through the mediatek-gen3 PCIe driver.
|
||||
This change is not introducing any backward compatibility issue since
|
||||
the EN7581 dts is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Link: https://lore.kernel.org/r/edf3b28926177166c65256604d69f2f576cb6fb3.1719682943.git.lorenzo@kernel.org
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie-regs.h | 17 +++++++++++++
|
||||
drivers/phy/phy-airoha-pcie.c | 38 ++++++++++++++++++++++++++++++
|
||||
2 files changed, 55 insertions(+)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie-regs.h
|
||||
+++ b/drivers/phy/phy-airoha-pcie-regs.h
|
||||
@@ -474,4 +474,21 @@
|
||||
#define REG_PCIE_PMA_DIG_RESERVE_27 0x0908
|
||||
#define REG_PCIE_PMA_DIG_RESERVE_30 0x0914
|
||||
|
||||
+/* DTIME */
|
||||
+#define REG_PCIE_PEXTP_DIG_GLB44 0x00
|
||||
+#define PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL GENMASK(7, 0)
|
||||
+#define PCIE_XTP_RXDET_EN_STB_T_SEL GENMASK(15, 8)
|
||||
+#define PCIE_XTP_RXDET_FINISH_STB_T_SEL GENMASK(23, 16)
|
||||
+#define PCIE_XTP_TXPD_TX_DATA_EN_DLY GENMASK(27, 24)
|
||||
+#define PCIE_XTP_TXPD_RXDET_DONE_CDT BIT(28)
|
||||
+#define PCIE_XTP_RXDET_LATCH_STB_T_SEL GENMASK(31, 29)
|
||||
+
|
||||
+/* RX AEQ */
|
||||
+#define REG_PCIE_PEXTP_DIG_LN_RX30_P0 0x0000
|
||||
+#define PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT GENMASK(7, 0)
|
||||
+#define PCIE_XTP_LN_RX_PDOWN_T2RLB_DIG_EN BIT(8)
|
||||
+#define PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT GENMASK(31, 16)
|
||||
+
|
||||
+#define REG_PCIE_PEXTP_DIG_LN_RX30_P1 0x0100
|
||||
+
|
||||
#endif /* _PHY_AIROHA_PCIE_H */
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -31,6 +31,9 @@ enum airoha_pcie_port_gen {
|
||||
* @csr_2l: Analogic lane IO mapped register base address
|
||||
* @pma0: IO mapped register base address of PMA0-PCIe
|
||||
* @pma1: IO mapped register base address of PMA1-PCIe
|
||||
+ * @p0_xr_dtime: IO mapped register base address of port0 Tx-Rx detection time
|
||||
+ * @p1_xr_dtime: IO mapped register base address of port1 Tx-Rx detection time
|
||||
+ * @rx_aeq: IO mapped register base address of Rx AEQ training
|
||||
*/
|
||||
struct airoha_pcie_phy {
|
||||
struct device *dev;
|
||||
@@ -38,6 +41,9 @@ struct airoha_pcie_phy {
|
||||
void __iomem *csr_2l;
|
||||
void __iomem *pma0;
|
||||
void __iomem *pma1;
|
||||
+ void __iomem *p0_xr_dtime;
|
||||
+ void __iomem *p1_xr_dtime;
|
||||
+ void __iomem *rx_aeq;
|
||||
};
|
||||
|
||||
static void airoha_phy_clear_bits(void __iomem *reg, u32 mask)
|
||||
@@ -1101,6 +1107,21 @@ static void airoha_pcie_phy_load_kflow(s
|
||||
static int airoha_pcie_phy_init(struct phy *phy)
|
||||
{
|
||||
struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy);
|
||||
+ u32 val;
|
||||
+
|
||||
+ /* Setup Tx-Rx detection time */
|
||||
+ val = FIELD_PREP(PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL, 0x33) |
|
||||
+ FIELD_PREP(PCIE_XTP_RXDET_EN_STB_T_SEL, 0x1) |
|
||||
+ FIELD_PREP(PCIE_XTP_RXDET_FINISH_STB_T_SEL, 0x2) |
|
||||
+ FIELD_PREP(PCIE_XTP_TXPD_TX_DATA_EN_DLY, 0x3) |
|
||||
+ FIELD_PREP(PCIE_XTP_RXDET_LATCH_STB_T_SEL, 0x1);
|
||||
+ writel(val, pcie_phy->p0_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
|
||||
+ writel(val, pcie_phy->p1_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
|
||||
+ /* Setup Rx AEQ training time */
|
||||
+ val = FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT, 0x32) |
|
||||
+ FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT, 0x5050);
|
||||
+ writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P0);
|
||||
+ writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P1);
|
||||
|
||||
/* enable load FLL-K flow */
|
||||
airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14,
|
||||
@@ -1217,6 +1238,23 @@ static int airoha_pcie_phy_probe(struct
|
||||
return dev_err_probe(dev, PTR_ERR(pcie_phy->phy),
|
||||
"Failed to create PCIe phy\n");
|
||||
|
||||
+ pcie_phy->p0_xr_dtime =
|
||||
+ devm_platform_ioremap_resource_byname(pdev, "p0-xr-dtime");
|
||||
+ if (IS_ERR(pcie_phy->p0_xr_dtime))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->p0_xr_dtime),
|
||||
+ "Failed to map P0 Tx-Rx dtime base\n");
|
||||
+
|
||||
+ pcie_phy->p1_xr_dtime =
|
||||
+ devm_platform_ioremap_resource_byname(pdev, "p1-xr-dtime");
|
||||
+ if (IS_ERR(pcie_phy->p1_xr_dtime))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->p1_xr_dtime),
|
||||
+ "Failed to map P1 Tx-Rx dtime base\n");
|
||||
+
|
||||
+ pcie_phy->rx_aeq = devm_platform_ioremap_resource_byname(pdev, "rx-aeq");
|
||||
+ if (IS_ERR(pcie_phy->rx_aeq))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->rx_aeq),
|
||||
+ "Failed to map Rx AEQ base\n");
|
||||
+
|
||||
pcie_phy->dev = dev;
|
||||
phy_set_drvdata(pcie_phy->phy, pcie_phy);
|
||||
|
@ -0,0 +1,40 @@
|
||||
From 7f7315db3d262298ab33d198d3f0b09cabfa7b6b Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 6 Aug 2024 17:55:48 +0200
|
||||
Subject: [PATCH] phy: airoha: adjust initialization delay in
|
||||
airoha_pcie_phy_init()
|
||||
|
||||
Align phy-pcie initialization delay to the vendor sdk in
|
||||
airoha_pcie_phy_init routine and allow the hw to complete required
|
||||
configuration before proceeding
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/8af6f27857619f1e0dd227f08b8584ae8fb22fb2.1722959625.git.lorenzo@kernel.org
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -18,6 +18,9 @@
|
||||
#define LEQ_LEN_CTRL_MAX_VAL 7
|
||||
#define FREQ_LOCK_MAX_ATTEMPT 10
|
||||
|
||||
+/* PCIe-PHY initialization time in ms needed by the hw to complete */
|
||||
+#define PHY_HW_INIT_TIME_MS 30
|
||||
+
|
||||
enum airoha_pcie_port_gen {
|
||||
PCIE_PORT_GEN1 = 1,
|
||||
PCIE_PORT_GEN2,
|
||||
@@ -1181,7 +1184,8 @@ static int airoha_pcie_phy_init(struct p
|
||||
airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
|
||||
PCIE_DA_XPON_CDR_PR_PWDB);
|
||||
|
||||
- usleep_range(100, 200);
|
||||
+ /* Wait for the PCIe PHY to complete initialization before returning */
|
||||
+ msleep(PHY_HW_INIT_TIME_MS);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
From ca9afde0563a80200eab856a53d7eab28c8fdd90 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:52 +0200
|
||||
Subject: [PATCH 1/4] phy: airoha: Fix REG_CSR_2L_PLL_CMN_RESERVE0 config in
|
||||
airoha_pcie_phy_init_clk_out()
|
||||
|
||||
Fix typo configuring REG_CSR_2L_PLL_CMN_RESERVE0 register in
|
||||
airoha_pcie_phy_init_clk_out routine.
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -459,7 +459,7 @@ static void airoha_pcie_phy_init_clk_out
|
||||
airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
|
||||
CSR_2L_PXP_CLKTX1_SR);
|
||||
airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_PLL_CMN_RESERVE0,
|
||||
- CSR_2L_PXP_PLL_RESERVE_MASK, 0xdd);
|
||||
+ CSR_2L_PXP_PLL_RESERVE_MASK, 0xd0d);
|
||||
}
|
||||
|
||||
static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy)
|
@ -0,0 +1,29 @@
|
||||
From 2c2313c84ad7c0e5e39fbd98559d40f6b9ec1f83 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:53 +0200
|
||||
Subject: [PATCH 2/4] phy: airoha: Fix REG_PCIE_PMA_TX_RESET config in
|
||||
airoha_pcie_phy_init_csr_2l()
|
||||
|
||||
Fix typos configuring REG_PCIE_PMA_TX_RESET register in
|
||||
airoha_pcie_phy_init_csr_2l routine for lane0 and lane1
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -471,9 +471,9 @@ static void airoha_pcie_phy_init_csr_2l(
|
||||
PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
|
||||
PCIE_SW_RX_RST);
|
||||
airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
|
||||
- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET);
|
||||
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
|
||||
airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
|
||||
- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET);
|
||||
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
|
||||
}
|
||||
|
||||
static void airoha_pcie_phy_init_rx(struct airoha_pcie_phy *pcie_phy)
|
@ -0,0 +1,26 @@
|
||||
From 6e0c349a8a59959c3d3571b5f6776bc2d2ca62bc Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:54 +0200
|
||||
Subject: [PATCH 3/4] phy: airoha: Fix REG_CSR_2L_JCPLL_SDM_HREN config in
|
||||
airoha_pcie_phy_init_ssc_jcpll()
|
||||
|
||||
Fix typo configuring REG_CSR_2L_JCPLL_SDM_HREN register in
|
||||
airoha_pcie_phy_init_ssc_jcpll routine.
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -802,7 +802,7 @@ static void airoha_pcie_phy_init_ssc_jcp
|
||||
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_IFM,
|
||||
CSR_2L_PXP_JCPLL_SDM_IFM);
|
||||
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
|
||||
- REG_CSR_2L_JCPLL_SDM_HREN);
|
||||
+ CSR_2L_PXP_JCPLL_SDM_HREN);
|
||||
airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
|
||||
CSR_2L_PXP_JCPLL_SDM_DI_EN);
|
||||
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
|
@ -0,0 +1,32 @@
|
||||
From bc1bb265f504ea19ce611a1aec1a40dec409cd15 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:55 +0200
|
||||
Subject: [PATCH 4/4] phy: airoha: Fix REG_CSR_2L_RX{0,1}_REV0 definitions
|
||||
|
||||
Fix the following register definitions for REG_CSR_2L_RX{0,1}_REV0
|
||||
registers:
|
||||
- CSR_2L_PXP_VOS_PNINV
|
||||
- CSR_2L_PXP_FE_GAIN_NORMAL_MODE
|
||||
- CSR_2L_PXP_FE_GAIN_TRAIN_MODE
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie-regs.h | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie-regs.h
|
||||
+++ b/drivers/phy/phy-airoha-pcie-regs.h
|
||||
@@ -197,9 +197,9 @@
|
||||
#define CSR_2L_PXP_TX1_MULTLANE_EN BIT(0)
|
||||
|
||||
#define REG_CSR_2L_RX0_REV0 0x00fc
|
||||
-#define CSR_2L_PXP_VOS_PNINV GENMASK(3, 2)
|
||||
-#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(6, 4)
|
||||
-#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(10, 8)
|
||||
+#define CSR_2L_PXP_VOS_PNINV GENMASK(19, 18)
|
||||
+#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(22, 20)
|
||||
+#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(26, 24)
|
||||
|
||||
#define REG_CSR_2L_RX0_PHYCK_DIV 0x0100
|
||||
#define CSR_2L_PXP_RX0_PHYCK_SEL GENMASK(9, 8)
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@
|
||||
From 2e6bbfe7b0c0607001b784082c2685b134174fac Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 13 Sep 2024 23:07:13 +0200
|
||||
Subject: [PATCH 1/2] spi: airoha: fix dirmap_{read,write} operations
|
||||
|
||||
SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end of
|
||||
dirmap_read operation even if it is already set.
|
||||
In the same way, SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the
|
||||
end of dirmap_write operation even if it is already set.
|
||||
For this reason use regmap_write_bits() instead of regmap_set_bits().
|
||||
This patch fixes mtd_pagetest kernel module test.
|
||||
|
||||
Fixes: a403997c1201 ("spi: airoha: add SPI-NAND Flash controller driver")
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240913-airoha-spi-fixes-v1-1-de2e74ed4664@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -739,8 +739,13 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
- SPI_NFI_READ_FROM_CACHE_DONE);
|
||||
+ /*
|
||||
+ * SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end
|
||||
+ * of dirmap_read operation even if it is already set.
|
||||
+ */
|
||||
+ err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
+ SPI_NFI_READ_FROM_CACHE_DONE,
|
||||
+ SPI_NFI_READ_FROM_CACHE_DONE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -870,8 +875,13 @@ static ssize_t airoha_snand_dirmap_write
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
- SPI_NFI_LOAD_TO_CACHE_DONE);
|
||||
+ /*
|
||||
+ * SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the end
|
||||
+ * of dirmap_write operation even if it is already set.
|
||||
+ */
|
||||
+ err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
+ SPI_NFI_LOAD_TO_CACHE_DONE,
|
||||
+ SPI_NFI_LOAD_TO_CACHE_DONE);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -0,0 +1,39 @@
|
||||
From 0e58637eb968c636725dcd6c7055249b4e5326fb Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 13 Sep 2024 23:07:14 +0200
|
||||
Subject: [PATCH 2/2] spi: airoha: fix airoha_snand_{write,read}_data data_len
|
||||
estimation
|
||||
|
||||
Fix data length written and read in airoha_snand_write_data and
|
||||
airoha_snand_read_data routines respectively if it is bigger than
|
||||
SPI_MAX_TRANSFER_SIZE.
|
||||
|
||||
Fixes: a403997c1201 ("spi: airoha: add SPI-NAND Flash controller driver")
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240913-airoha-spi-fixes-v1-2-de2e74ed4664@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -405,7 +405,7 @@ static int airoha_snand_write_data(struc
|
||||
for (i = 0; i < len; i += data_len) {
|
||||
int err;
|
||||
|
||||
- data_len = min(len, SPI_MAX_TRANSFER_SIZE);
|
||||
+ data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
|
||||
err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -427,7 +427,7 @@ static int airoha_snand_read_data(struct
|
||||
for (i = 0; i < len; i += data_len) {
|
||||
int err;
|
||||
|
||||
- data_len = min(len, SPI_MAX_TRANSFER_SIZE);
|
||||
+ data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
|
||||
err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
|
||||
if (err)
|
||||
return err;
|
@ -0,0 +1,116 @@
|
||||
From fffca269e4f31c3633c6d810833ba1b184407915 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 19 Sep 2024 18:57:16 +0200
|
||||
Subject: [PATCH] spi: airoha: remove read cache in airoha_snand_dirmap_read()
|
||||
|
||||
Current upstream driver reports errors running mtd_oobtest kernel module
|
||||
test:
|
||||
|
||||
root@OpenWrt:/# insmod mtd_test.ko
|
||||
root@OpenWrt:/# insmod mtd_oobtest.ko dev=5
|
||||
[ 7023.730584] =================================================
|
||||
[ 7023.736399] mtd_oobtest: MTD device: 5
|
||||
[ 7023.740160] mtd_oobtest: MTD device size 3670016, eraseblock size 131072, page size 2048, count of eraseblocks 28, pages per eraseblock 64, OOB size 128
|
||||
[ 7023.753837] mtd_test: scanning for bad eraseblocks
|
||||
[ 7023.758636] mtd_test: scanned 28 eraseblocks, 0 are bad
|
||||
[ 7023.763861] mtd_oobtest: test 1 of 5
|
||||
[ 7024.042076] mtd_oobtest: writing OOBs of whole device
|
||||
[ 7024.682069] mtd_oobtest: written up to eraseblock 0
|
||||
[ 7041.962077] mtd_oobtest: written 28 eraseblocks
|
||||
[ 7041.966626] mtd_oobtest: verifying all eraseblocks
|
||||
[ 7041.972276] mtd_oobtest: error @addr[0x0:0x0] 0xff -> 0xe diff 0xf1
|
||||
[ 7041.978550] mtd_oobtest: error @addr[0x0:0x1] 0xff -> 0x10 diff 0xef
|
||||
[ 7041.984932] mtd_oobtest: error @addr[0x0:0x2] 0xff -> 0x82 diff 0x7d
|
||||
[ 7041.991293] mtd_oobtest: error @addr[0x0:0x3] 0xff -> 0x10 diff 0xef
|
||||
[ 7041.997659] mtd_oobtest: error @addr[0x0:0x4] 0xff -> 0x0 diff 0xff
|
||||
[ 7042.003942] mtd_oobtest: error @addr[0x0:0x5] 0xff -> 0x8a diff 0x75
|
||||
[ 7042.010294] mtd_oobtest: error @addr[0x0:0x6] 0xff -> 0x20 diff 0xdf
|
||||
[ 7042.016659] mtd_oobtest: error @addr[0x0:0x7] 0xff -> 0x1 diff 0xfe
|
||||
[ 7042.022935] mtd_oobtest: error @addr[0x0:0x8] 0xff -> 0x2e diff 0xd1
|
||||
[ 7042.029295] mtd_oobtest: error @addr[0x0:0x9] 0xff -> 0x40 diff 0xbf
|
||||
[ 7042.035661] mtd_oobtest: error @addr[0x0:0xa] 0xff -> 0x0 diff 0xff
|
||||
[ 7042.041935] mtd_oobtest: error @addr[0x0:0xb] 0xff -> 0x89 diff 0x76
|
||||
[ 7042.048300] mtd_oobtest: error @addr[0x0:0xc] 0xff -> 0x82 diff 0x7d
|
||||
[ 7042.054662] mtd_oobtest: error @addr[0x0:0xd] 0xff -> 0x15 diff 0xea
|
||||
[ 7042.061014] mtd_oobtest: error @addr[0x0:0xe] 0xff -> 0x90 diff 0x6f
|
||||
[ 7042.067380] mtd_oobtest: error @addr[0x0:0xf] 0xff -> 0x0 diff 0xff
|
||||
....
|
||||
[ 7432.421369] mtd_oobtest: error @addr[0x237800:0x36] 0xff -> 0x5f diff 0xa0
|
||||
[ 7432.428242] mtd_oobtest: error @addr[0x237800:0x37] 0xff -> 0x21 diff 0xde
|
||||
[ 7432.435118] mtd_oobtest: error: verify failed at 0x237800
|
||||
[ 7432.440510] mtd_oobtest: error: too many errors
|
||||
[ 7432.445053] mtd_oobtest: error -1 occurred
|
||||
|
||||
The above errors are due to the buggy logic in the 'read cache' available
|
||||
in airoha_snand_dirmap_read() routine since there are some corner cases
|
||||
where we are missing data updates. Since we do not get any read/write speed
|
||||
improvement using the cache (according to the mtd_speedtest kernel
|
||||
module test), in order to fix the mtd_oobtest test, remove the 'read cache'
|
||||
in airoha_snand_dirmap_read routine. Now the driver is passing all the
|
||||
tests available in mtd_test suite.
|
||||
|
||||
Fixes: a403997c1201 ("spi: airoha: add SPI-NAND Flash controller driver")
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240919-airoha-spi-fixes-v2-1-cb0f0ed9920a@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 21 ---------------------
|
||||
1 file changed, 21 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -211,9 +211,6 @@ struct airoha_snand_dev {
|
||||
|
||||
u8 *txrx_buf;
|
||||
dma_addr_t dma_addr;
|
||||
-
|
||||
- u64 cur_page_num;
|
||||
- bool data_need_update;
|
||||
};
|
||||
|
||||
struct airoha_snand_ctrl {
|
||||
@@ -644,11 +641,6 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
u32 val, rd_mode;
|
||||
int err;
|
||||
|
||||
- if (!as_dev->data_need_update)
|
||||
- return len;
|
||||
-
|
||||
- as_dev->data_need_update = false;
|
||||
-
|
||||
switch (op->cmd.opcode) {
|
||||
case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
|
||||
rd_mode = 1;
|
||||
@@ -895,23 +887,11 @@ static ssize_t airoha_snand_dirmap_write
|
||||
static int airoha_snand_exec_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(mem->spi);
|
||||
u8 data[8], cmd, opcode = op->cmd.opcode;
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
int i, err;
|
||||
|
||||
as_ctrl = spi_controller_get_devdata(mem->spi->controller);
|
||||
- if (opcode == SPI_NAND_OP_PROGRAM_EXECUTE &&
|
||||
- op->addr.val == as_dev->cur_page_num) {
|
||||
- as_dev->data_need_update = true;
|
||||
- } else if (opcode == SPI_NAND_OP_PAGE_READ) {
|
||||
- if (!as_dev->data_need_update &&
|
||||
- op->addr.val == as_dev->cur_page_num)
|
||||
- return 0;
|
||||
-
|
||||
- as_dev->data_need_update = true;
|
||||
- as_dev->cur_page_num = op->addr.val;
|
||||
- }
|
||||
|
||||
/* switch to manual mode */
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
@@ -996,7 +976,6 @@ static int airoha_snand_setup(struct spi
|
||||
if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr))
|
||||
return -ENOMEM;
|
||||
|
||||
- as_dev->data_need_update = true;
|
||||
spi_set_ctldata(spi, as_dev);
|
||||
|
||||
return 0;
|
@ -0,0 +1,435 @@
|
||||
From 7a4b3ebf1d60349587fee21872536e7bd6a4cf39 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sun, 22 Sep 2024 19:38:30 +0200
|
||||
Subject: [PATCH] spi: airoha: do not keep {tx,rx} dma buffer always mapped
|
||||
|
||||
DMA map txrx_buf on demand in airoha_snand_dirmap_read and
|
||||
airoha_snand_dirmap_write routines and do not keep it always mapped.
|
||||
This patch is not fixing any bug or introducing any functional change
|
||||
to the driver, it just simplifies the code and improve code readability
|
||||
without introducing any performance degradation according to the results
|
||||
obtained from the mtd_speedtest kernel module test.
|
||||
|
||||
root@OpenWrt:# insmod mtd_test.ko
|
||||
root@OpenWrt:# insmod mtd_speedtest.ko dev=5
|
||||
[ 49.849869] =================================================
|
||||
[ 49.855659] mtd_speedtest: MTD device: 5
|
||||
[ 49.859583] mtd_speedtest: MTD device size 8388608, eraseblock size 131072, page size 2048, count of eraseblocks 64, pages per eraseblock 64, OOB size 128
|
||||
[ 49.874622] mtd_test: scanning for bad eraseblocks
|
||||
[ 49.879433] mtd_test: scanned 64 eraseblocks, 0 are bad
|
||||
[ 50.106372] mtd_speedtest: testing eraseblock write speed
|
||||
[ 53.083380] mtd_speedtest: eraseblock write speed is 2756 KiB/s
|
||||
[ 53.089322] mtd_speedtest: testing eraseblock read speed
|
||||
[ 54.143360] mtd_speedtest: eraseblock read speed is 7811 KiB/s
|
||||
[ 54.370365] mtd_speedtest: testing page write speed
|
||||
[ 57.349480] mtd_speedtest: page write speed is 2754 KiB/s
|
||||
[ 57.354895] mtd_speedtest: testing page read speed
|
||||
[ 58.410431] mtd_speedtest: page read speed is 7796 KiB/s
|
||||
[ 58.636805] mtd_speedtest: testing 2 page write speed
|
||||
[ 61.612427] mtd_speedtest: 2 page write speed is 2757 KiB/s
|
||||
[ 61.618021] mtd_speedtest: testing 2 page read speed
|
||||
[ 62.672653] mtd_speedtest: 2 page read speed is 7804 KiB/s
|
||||
[ 62.678159] mtd_speedtest: Testing erase speed
|
||||
[ 62.903617] mtd_speedtest: erase speed is 37063 KiB/s
|
||||
[ 62.908678] mtd_speedtest: Testing 2x multi-block erase speed
|
||||
[ 63.134083] mtd_speedtest: 2x multi-block erase speed is 37292 KiB/s
|
||||
[ 63.140442] mtd_speedtest: Testing 4x multi-block erase speed
|
||||
[ 63.364262] mtd_speedtest: 4x multi-block erase speed is 37566 KiB/s
|
||||
[ 63.370632] mtd_speedtest: Testing 8x multi-block erase speed
|
||||
[ 63.595740] mtd_speedtest: 8x multi-block erase speed is 37344 KiB/s
|
||||
[ 63.602089] mtd_speedtest: Testing 16x multi-block erase speed
|
||||
[ 63.827426] mtd_speedtest: 16x multi-block erase speed is 37320 KiB/s
|
||||
[ 63.833860] mtd_speedtest: Testing 32x multi-block erase speed
|
||||
[ 64.059389] mtd_speedtest: 32x multi-block erase speed is 37288 KiB/s
|
||||
[ 64.065833] mtd_speedtest: Testing 64x multi-block erase speed
|
||||
[ 64.290609] mtd_speedtest: 64x multi-block erase speed is 37415 KiB/s
|
||||
[ 64.297063] mtd_speedtest: finished
|
||||
[ 64.300555] =================================================
|
||||
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240922-airoha-spi-fixes-v3-1-f958802b3d68@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 154 ++++++++++++++++------------------
|
||||
1 file changed, 71 insertions(+), 83 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -206,13 +206,6 @@ enum airoha_snand_cs {
|
||||
SPI_CHIP_SEL_LOW,
|
||||
};
|
||||
|
||||
-struct airoha_snand_dev {
|
||||
- size_t buf_len;
|
||||
-
|
||||
- u8 *txrx_buf;
|
||||
- dma_addr_t dma_addr;
|
||||
-};
|
||||
-
|
||||
struct airoha_snand_ctrl {
|
||||
struct device *dev;
|
||||
struct regmap *regmap_ctrl;
|
||||
@@ -617,9 +610,9 @@ static bool airoha_snand_supports_op(str
|
||||
|
||||
static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
||||
{
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(desc->mem->spi);
|
||||
+ u8 *txrx_buf = spi_get_ctldata(desc->mem->spi);
|
||||
|
||||
- if (!as_dev->txrx_buf)
|
||||
+ if (!txrx_buf)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->info.offset + desc->info.length > U32_MAX)
|
||||
@@ -634,10 +627,11 @@ static int airoha_snand_dirmap_create(st
|
||||
static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, void *buf)
|
||||
{
|
||||
- struct spi_device *spi = desc->mem->spi;
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
|
||||
struct spi_mem_op *op = &desc->info.op_tmpl;
|
||||
+ struct spi_device *spi = desc->mem->spi;
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
+ u8 *txrx_buf = spi_get_ctldata(spi);
|
||||
+ dma_addr_t dma_addr;
|
||||
u32 val, rd_mode;
|
||||
int err;
|
||||
|
||||
@@ -662,14 +656,17 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
+ dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_FROM_DEVICE);
|
||||
+ err = dma_mapping_error(as_ctrl->dev, dma_addr);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
/* set dma addr */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
|
||||
- as_dev->dma_addr);
|
||||
+ dma_addr);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* set cust sec size */
|
||||
val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
|
||||
@@ -678,58 +675,58 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
REG_SPI_NFI_SNF_MISC_CTL2,
|
||||
SPI_NFI_READ_DATA_BYTE_NUM, val);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* set read command */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2,
|
||||
op->cmd.opcode);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* set read mode */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
|
||||
FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, rd_mode));
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* set read addr */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* set nfi read */
|
||||
err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_OPMODE,
|
||||
FIELD_PREP(SPI_NFI_OPMODE, 6));
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* trigger dma start read */
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_RD_TRIG);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_RD_TRIG);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi,
|
||||
REG_SPI_NFI_SNF_STA_CTL1, val,
|
||||
(val & SPI_NFI_READ_FROM_CACHE_DONE),
|
||||
0, 1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/*
|
||||
* SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end
|
||||
@@ -739,35 +736,41 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
SPI_NFI_READ_FROM_CACHE_DONE,
|
||||
SPI_NFI_READ_FROM_CACHE_DONE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR,
|
||||
val, (val & SPI_NFI_AHB_DONE), 0,
|
||||
1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* DMA read need delay for data ready from controller to DRAM */
|
||||
udelay(1);
|
||||
|
||||
- dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_FROM_DEVICE);
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
- memcpy(buf, as_dev->txrx_buf + offs, len);
|
||||
+ memcpy(buf, txrx_buf + offs, len);
|
||||
|
||||
return len;
|
||||
+
|
||||
+error_dma_unmap:
|
||||
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_FROM_DEVICE);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, const void *buf)
|
||||
{
|
||||
- struct spi_device *spi = desc->mem->spi;
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
|
||||
struct spi_mem_op *op = &desc->info.op_tmpl;
|
||||
+ struct spi_device *spi = desc->mem->spi;
|
||||
+ u8 *txrx_buf = spi_get_ctldata(spi);
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
+ dma_addr_t dma_addr;
|
||||
u32 wr_mode, val;
|
||||
int err;
|
||||
|
||||
@@ -776,19 +779,20 @@ static ssize_t airoha_snand_dirmap_write
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
- dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
- memcpy(as_dev->txrx_buf + offs, buf, len);
|
||||
- dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
+ memcpy(txrx_buf + offs, buf, len);
|
||||
+ dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_TO_DEVICE);
|
||||
+ err = dma_mapping_error(as_ctrl->dev, dma_addr);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
|
||||
if (err < 0)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = airoha_snand_nfi_config(as_ctrl);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD ||
|
||||
op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD)
|
||||
@@ -797,9 +801,9 @@ static ssize_t airoha_snand_dirmap_write
|
||||
wr_mode = 0;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
|
||||
- as_dev->dma_addr);
|
||||
+ dma_addr);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM,
|
||||
as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
|
||||
@@ -807,65 +811,65 @@ static ssize_t airoha_snand_dirmap_write
|
||||
REG_SPI_NFI_SNF_MISC_CTL2,
|
||||
SPI_NFI_PROG_LOAD_BYTE_NUM, val);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1,
|
||||
FIELD_PREP(SPI_NFI_PG_LOAD_CMD,
|
||||
op->cmd.opcode));
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
|
||||
FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode));
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_READ_MODE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_OPMODE,
|
||||
FIELD_PREP(SPI_NFI_OPMODE, 3));
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_DMA_MODE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_WR_TRIG);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_WR_TRIG);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR,
|
||||
val, (val & SPI_NFI_AHB_DONE), 0,
|
||||
1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi,
|
||||
REG_SPI_NFI_SNF_STA_CTL1, val,
|
||||
(val & SPI_NFI_LOAD_TO_CACHE_DONE),
|
||||
0, 1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/*
|
||||
* SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the end
|
||||
@@ -875,13 +879,20 @@ static ssize_t airoha_snand_dirmap_write
|
||||
SPI_NFI_LOAD_TO_CACHE_DONE,
|
||||
SPI_NFI_LOAD_TO_CACHE_DONE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_TO_DEVICE);
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return len;
|
||||
+
|
||||
+error_dma_unmap:
|
||||
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_TO_DEVICE);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static int airoha_snand_exec_op(struct spi_mem *mem,
|
||||
@@ -956,42 +967,20 @@ static const struct spi_controller_mem_o
|
||||
static int airoha_snand_setup(struct spi_device *spi)
|
||||
{
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
- struct airoha_snand_dev *as_dev;
|
||||
-
|
||||
- as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
-
|
||||
- as_dev = devm_kzalloc(as_ctrl->dev, sizeof(*as_dev), GFP_KERNEL);
|
||||
- if (!as_dev)
|
||||
- return -ENOMEM;
|
||||
+ u8 *txrx_buf;
|
||||
|
||||
/* prepare device buffer */
|
||||
- as_dev->buf_len = SPI_NAND_CACHE_SIZE;
|
||||
- as_dev->txrx_buf = devm_kzalloc(as_ctrl->dev, as_dev->buf_len,
|
||||
- GFP_KERNEL);
|
||||
- if (!as_dev->txrx_buf)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- as_dev->dma_addr = dma_map_single(as_ctrl->dev, as_dev->txrx_buf,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
- if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr))
|
||||
+ as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
+ txrx_buf = devm_kzalloc(as_ctrl->dev, SPI_NAND_CACHE_SIZE,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!txrx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
- spi_set_ctldata(spi, as_dev);
|
||||
+ spi_set_ctldata(spi, txrx_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void airoha_snand_cleanup(struct spi_device *spi)
|
||||
-{
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
|
||||
- struct airoha_snand_ctrl *as_ctrl;
|
||||
-
|
||||
- as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
- dma_unmap_single(as_ctrl->dev, as_dev->dma_addr,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
- spi_set_ctldata(spi, NULL);
|
||||
-}
|
||||
-
|
||||
static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl)
|
||||
{
|
||||
u32 val, sec_size, sec_num;
|
||||
@@ -1093,7 +1082,6 @@ static int airoha_snand_probe(struct pla
|
||||
ctrl->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
ctrl->mode_bits = SPI_RX_DUAL;
|
||||
ctrl->setup = airoha_snand_setup;
|
||||
- ctrl->cleanup = airoha_snand_cleanup;
|
||||
device_set_node(&ctrl->dev, dev_fwnode(dev));
|
||||
|
||||
err = airoha_snand_nfi_setup(as_ctrl);
|
@ -0,0 +1,184 @@
|
||||
From 2b0229f67932e4b9e2f458bf286903582bd30740 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 09:35:12 +0200
|
||||
Subject: [PATCH] net: dsa: mt7530: Add EN7581 support
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Introduce support for the DSA built-in switch available on the EN7581
|
||||
development board. EN7581 support is similar to MT7988 one except
|
||||
it requires to set MT7530_FORCE_MODE bit in MT753X_PMCR_P register
|
||||
for on cpu port.
|
||||
|
||||
Tested-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Arınç ÜNAL <arinc.unal@arinc9.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/mt7530-mmio.c | 1 +
|
||||
drivers/net/dsa/mt7530.c | 49 ++++++++++++++++++++++++++++++-----
|
||||
drivers/net/dsa/mt7530.h | 20 ++++++++++----
|
||||
3 files changed, 59 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/net/dsa/mt7530-mmio.c
|
||||
+++ b/drivers/net/dsa/mt7530-mmio.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "mt7530.h"
|
||||
|
||||
static const struct of_device_id mt7988_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-switch", .data = &mt753x_table[ID_EN7581], },
|
||||
{ .compatible = "mediatek,mt7988-switch", .data = &mt753x_table[ID_MT7988], },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
--- a/drivers/net/dsa/mt7530.c
|
||||
+++ b/drivers/net/dsa/mt7530.c
|
||||
@@ -1152,7 +1152,8 @@ mt753x_cpu_port_enable(struct dsa_switch
|
||||
* the MT7988 SoC. Trapped frames will be forwarded to the CPU port that
|
||||
* is affine to the inbound user port.
|
||||
*/
|
||||
- if (priv->id == ID_MT7531 || priv->id == ID_MT7988)
|
||||
+ if (priv->id == ID_MT7531 || priv->id == ID_MT7988 ||
|
||||
+ priv->id == ID_EN7581)
|
||||
mt7530_set(priv, MT7531_CFC, MT7531_CPU_PMAP(BIT(port)));
|
||||
|
||||
/* CPU port gets connected to all user ports of
|
||||
@@ -2207,7 +2208,7 @@ mt7530_setup_irq(struct mt7530_priv *pri
|
||||
return priv->irq ? : -EINVAL;
|
||||
}
|
||||
|
||||
- if (priv->id == ID_MT7988)
|
||||
+ if (priv->id == ID_MT7988 || priv->id == ID_EN7581)
|
||||
priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
|
||||
&mt7988_irq_domain_ops,
|
||||
priv);
|
||||
@@ -2438,8 +2439,10 @@ mt7530_setup(struct dsa_switch *ds)
|
||||
/* Clear link settings and enable force mode to force link down
|
||||
* on all ports until they're enabled later.
|
||||
*/
|
||||
- mt7530_rmw(priv, MT753X_PMCR_P(i), PMCR_LINK_SETTINGS_MASK |
|
||||
- MT7530_FORCE_MODE, MT7530_FORCE_MODE);
|
||||
+ mt7530_rmw(priv, MT753X_PMCR_P(i),
|
||||
+ PMCR_LINK_SETTINGS_MASK |
|
||||
+ MT753X_FORCE_MODE(priv->id),
|
||||
+ MT753X_FORCE_MODE(priv->id));
|
||||
|
||||
/* Disable forwarding by default on all ports */
|
||||
mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
|
||||
@@ -2550,8 +2553,10 @@ mt7531_setup_common(struct dsa_switch *d
|
||||
/* Clear link settings and enable force mode to force link down
|
||||
* on all ports until they're enabled later.
|
||||
*/
|
||||
- mt7530_rmw(priv, MT753X_PMCR_P(i), PMCR_LINK_SETTINGS_MASK |
|
||||
- MT7531_FORCE_MODE_MASK, MT7531_FORCE_MODE_MASK);
|
||||
+ mt7530_rmw(priv, MT753X_PMCR_P(i),
|
||||
+ PMCR_LINK_SETTINGS_MASK |
|
||||
+ MT753X_FORCE_MODE(priv->id),
|
||||
+ MT753X_FORCE_MODE(priv->id));
|
||||
|
||||
/* Disable forwarding by default on all ports */
|
||||
mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
|
||||
@@ -2783,6 +2788,28 @@ static void mt7988_mac_port_get_caps(str
|
||||
}
|
||||
}
|
||||
|
||||
+static void en7581_mac_port_get_caps(struct dsa_switch *ds, int port,
|
||||
+ struct phylink_config *config)
|
||||
+{
|
||||
+ switch (port) {
|
||||
+ /* Ports which are connected to switch PHYs. There is no MII pinout. */
|
||||
+ case 0 ... 4:
|
||||
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
+ config->supported_interfaces);
|
||||
+
|
||||
+ config->mac_capabilities |= MAC_10 | MAC_100 | MAC_1000FD;
|
||||
+ break;
|
||||
+
|
||||
+ /* Port 6 is connected to SoC's XGMII MAC. There is no MII pinout. */
|
||||
+ case 6:
|
||||
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
+ config->supported_interfaces);
|
||||
+
|
||||
+ config->mac_capabilities |= MAC_10000FD;
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void
|
||||
mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
@@ -3220,6 +3247,16 @@ const struct mt753x_info mt753x_table[]
|
||||
.phy_write_c45 = mt7531_ind_c45_phy_write,
|
||||
.mac_port_get_caps = mt7988_mac_port_get_caps,
|
||||
},
|
||||
+ [ID_EN7581] = {
|
||||
+ .id = ID_EN7581,
|
||||
+ .pcs_ops = &mt7530_pcs_ops,
|
||||
+ .sw_setup = mt7988_setup,
|
||||
+ .phy_read_c22 = mt7531_ind_c22_phy_read,
|
||||
+ .phy_write_c22 = mt7531_ind_c22_phy_write,
|
||||
+ .phy_read_c45 = mt7531_ind_c45_phy_read,
|
||||
+ .phy_write_c45 = mt7531_ind_c45_phy_write,
|
||||
+ .mac_port_get_caps = en7581_mac_port_get_caps,
|
||||
+ },
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mt753x_table);
|
||||
|
||||
--- a/drivers/net/dsa/mt7530.h
|
||||
+++ b/drivers/net/dsa/mt7530.h
|
||||
@@ -19,6 +19,7 @@ enum mt753x_id {
|
||||
ID_MT7621 = 1,
|
||||
ID_MT7531 = 2,
|
||||
ID_MT7988 = 3,
|
||||
+ ID_EN7581 = 4,
|
||||
};
|
||||
|
||||
#define NUM_TRGMII_CTRL 5
|
||||
@@ -64,25 +65,30 @@ enum mt753x_id {
|
||||
#define MT7531_CPU_PMAP(x) FIELD_PREP(MT7531_CPU_PMAP_MASK, x)
|
||||
|
||||
#define MT753X_MIRROR_REG(id) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_CFC : MT753X_MFC)
|
||||
|
||||
#define MT753X_MIRROR_EN(id) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_EN : MT7530_MIRROR_EN)
|
||||
|
||||
#define MT753X_MIRROR_PORT_MASK(id) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_PORT_MASK : \
|
||||
MT7530_MIRROR_PORT_MASK)
|
||||
|
||||
#define MT753X_MIRROR_PORT_GET(id, val) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_PORT_GET(val) : \
|
||||
MT7530_MIRROR_PORT_GET(val))
|
||||
|
||||
#define MT753X_MIRROR_PORT_SET(id, val) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_PORT_SET(val) : \
|
||||
MT7530_MIRROR_PORT_SET(val))
|
||||
|
||||
@@ -355,6 +361,10 @@ enum mt7530_vlan_port_acc_frm {
|
||||
MT7531_FORCE_MODE_TX_FC | \
|
||||
MT7531_FORCE_MODE_EEE100 | \
|
||||
MT7531_FORCE_MODE_EEE1G)
|
||||
+#define MT753X_FORCE_MODE(id) ((id == ID_MT7531 || \
|
||||
+ id == ID_MT7988) ? \
|
||||
+ MT7531_FORCE_MODE_MASK : \
|
||||
+ MT7530_FORCE_MODE)
|
||||
#define PMCR_LINK_SETTINGS_MASK (PMCR_MAC_TX_EN | PMCR_MAC_RX_EN | \
|
||||
PMCR_FORCE_EEE1G | \
|
||||
PMCR_FORCE_EEE100 | \
|
@ -0,0 +1,247 @@
|
||||
From 5296da64f77ef6c809b715cdecf308977a08acb9 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Wed, 16 Oct 2024 18:00:57 +0200
|
||||
Subject: [PATCH] cpufreq: airoha: Add EN7581 Cpufreq SMC driver
|
||||
|
||||
Add simple Cpufreq driver for Airoha EN7581 SoC that control CPU
|
||||
frequency scaling with SMC APIs.
|
||||
|
||||
All CPU share the same frequency and can't be controlled independently.
|
||||
Current shared CPU frequency is returned by the related SMC command.
|
||||
|
||||
Add SoC compatible to cpufreq-dt-plat block list as a dedicated cpufreq
|
||||
driver is needed with OPP v2 nodes declared in DTS.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/cpufreq/Kconfig.arm | 8 ++
|
||||
drivers/cpufreq/Makefile | 1 +
|
||||
drivers/cpufreq/airoha-cpufreq.c | 183 +++++++++++++++++++++++++++
|
||||
drivers/cpufreq/cpufreq-dt-platdev.c | 2 +
|
||||
4 files changed, 194 insertions(+)
|
||||
create mode 100644 drivers/cpufreq/airoha-cpufreq.c
|
||||
|
||||
--- a/drivers/cpufreq/Kconfig.arm
|
||||
+++ b/drivers/cpufreq/Kconfig.arm
|
||||
@@ -41,6 +41,14 @@ config ARM_ALLWINNER_SUN50I_CPUFREQ_NVME
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called sun50i-cpufreq-nvmem.
|
||||
|
||||
+config ARM_AIROHA_SOC_CPUFREQ
|
||||
+ tristate "Airoha EN7581 SoC CPUFreq support"
|
||||
+ depends on ARCH_AIROHA || COMPILE_TEST
|
||||
+ select PM_OPP
|
||||
+ default ARCH_AIROHA
|
||||
+ help
|
||||
+ This adds the CPUFreq driver for Airoha EN7581 SoCs.
|
||||
+
|
||||
config ARM_APPLE_SOC_CPUFREQ
|
||||
tristate "Apple Silicon SoC CPUFreq support"
|
||||
depends on ARCH_APPLE || (COMPILE_TEST && 64BIT)
|
||||
--- a/drivers/cpufreq/Makefile
|
||||
+++ b/drivers/cpufreq/Makefile
|
||||
@@ -52,6 +52,7 @@ obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) +
|
||||
|
||||
##################################################################################
|
||||
# ARM SoC drivers
|
||||
+obj-$(CONFIG_ARM_AIROHA_SOC_CPUFREQ) += airoha-cpufreq.o
|
||||
obj-$(CONFIG_ARM_APPLE_SOC_CPUFREQ) += apple-soc-cpufreq.o
|
||||
obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
|
||||
obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ) += armada-8k-cpufreq.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/cpufreq/airoha-cpufreq.c
|
||||
@@ -0,0 +1,183 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/arm-smccc.h>
|
||||
+
|
||||
+#define AIROHA_SIP_AVS_HANDLE 0x82000301
|
||||
+#define AIROHA_AVS_OP_BASE 0xddddddd0
|
||||
+#define AIROHA_AVS_OP_MASK GENMASK(1, 0)
|
||||
+#define AIROHA_AVS_OP_FREQ_DYN_ADJ (AIROHA_AVS_OP_BASE | \
|
||||
+ FIELD_PREP(AIROHA_AVS_OP_MASK, 0x1))
|
||||
+#define AIROHA_AVS_OP_GET_FREQ (AIROHA_AVS_OP_BASE | \
|
||||
+ FIELD_PREP(AIROHA_AVS_OP_MASK, 0x2))
|
||||
+
|
||||
+struct airoha_cpufreq_priv {
|
||||
+ struct list_head list;
|
||||
+
|
||||
+ cpumask_var_t cpus;
|
||||
+ struct device *cpu_dev;
|
||||
+ struct cpufreq_frequency_table *freq_table;
|
||||
+};
|
||||
+
|
||||
+static LIST_HEAD(priv_list);
|
||||
+
|
||||
+static unsigned int airoha_cpufreq_get(unsigned int cpu)
|
||||
+{
|
||||
+ const struct arm_smccc_1_2_regs args = {
|
||||
+ .a0 = AIROHA_SIP_AVS_HANDLE,
|
||||
+ .a1 = AIROHA_AVS_OP_GET_FREQ,
|
||||
+ };
|
||||
+ struct arm_smccc_1_2_regs res;
|
||||
+
|
||||
+ arm_smccc_1_2_smc(&args, &res);
|
||||
+
|
||||
+ return (int)(res.a0 * 1000);
|
||||
+}
|
||||
+
|
||||
+static int airoha_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
|
||||
+{
|
||||
+ const struct arm_smccc_1_2_regs args = {
|
||||
+ .a0 = AIROHA_SIP_AVS_HANDLE,
|
||||
+ .a1 = AIROHA_AVS_OP_FREQ_DYN_ADJ,
|
||||
+ .a3 = index,
|
||||
+ };
|
||||
+ struct arm_smccc_1_2_regs res;
|
||||
+
|
||||
+ arm_smccc_1_2_smc(&args, &res);
|
||||
+
|
||||
+ /* SMC signal correct apply by unsetting BIT 0 */
|
||||
+ return res.a0 & BIT(0) ? -EINVAL : 0;
|
||||
+}
|
||||
+
|
||||
+static struct airoha_cpufreq_priv *airoha_cpufreq_find_data(int cpu)
|
||||
+{
|
||||
+ struct airoha_cpufreq_priv *priv;
|
||||
+
|
||||
+ list_for_each_entry(priv, &priv_list, list) {
|
||||
+ if (cpumask_test_cpu(cpu, priv->cpus))
|
||||
+ return priv;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int airoha_cpufreq_init(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ struct airoha_cpufreq_priv *priv;
|
||||
+ struct device *cpu_dev;
|
||||
+
|
||||
+ priv = airoha_cpufreq_find_data(policy->cpu);
|
||||
+ if (!priv)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ cpu_dev = priv->cpu_dev;
|
||||
+ cpumask_copy(policy->cpus, priv->cpus);
|
||||
+ policy->driver_data = priv;
|
||||
+ policy->freq_table = priv->freq_table;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct cpufreq_driver airoha_cpufreq_driver = {
|
||||
+ .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK |
|
||||
+ CPUFREQ_IS_COOLING_DEV,
|
||||
+ .verify = cpufreq_generic_frequency_table_verify,
|
||||
+ .target_index = airoha_cpufreq_set_target,
|
||||
+ .get = airoha_cpufreq_get,
|
||||
+ .init = airoha_cpufreq_init,
|
||||
+ .attr = cpufreq_generic_attr,
|
||||
+ .name = "airoha-cpufreq",
|
||||
+};
|
||||
+
|
||||
+static int airoha_cpufreq_driver_init_cpu(int cpu)
|
||||
+{
|
||||
+ struct airoha_cpufreq_priv *priv;
|
||||
+ struct device *cpu_dev;
|
||||
+ int ret;
|
||||
+
|
||||
+ cpu_dev = get_cpu_device(cpu);
|
||||
+ if (!cpu_dev)
|
||||
+ return -EPROBE_DEFER;
|
||||
+
|
||||
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ if (!zalloc_cpumask_var(&priv->cpus, GFP_KERNEL))
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cpumask_set_cpu(cpu, priv->cpus);
|
||||
+ priv->cpu_dev = cpu_dev;
|
||||
+
|
||||
+ ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, priv->cpus);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+
|
||||
+ ret = dev_pm_opp_of_cpumask_add_table(priv->cpus);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+
|
||||
+ ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &priv->freq_table);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+
|
||||
+ list_add(&priv->list, &priv_list);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err:
|
||||
+ dev_pm_opp_of_cpumask_remove_table(priv->cpus);
|
||||
+ free_cpumask_var(priv->cpus);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void airoha_cpufreq_release(void)
|
||||
+{
|
||||
+ struct airoha_cpufreq_priv *priv, *tmp;
|
||||
+
|
||||
+ list_for_each_entry_safe(priv, tmp, &priv_list, list) {
|
||||
+ dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &priv->freq_table);
|
||||
+ dev_pm_opp_of_cpumask_remove_table(priv->cpus);
|
||||
+ free_cpumask_var(priv->cpus);
|
||||
+ list_del(&priv->list);
|
||||
+ kfree(priv);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int __init airoha_cpufreq_driver_probe(void)
|
||||
+{
|
||||
+ int cpu, ret;
|
||||
+
|
||||
+ if (!of_machine_is_compatible("airoha,en7581"))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ for_each_possible_cpu(cpu) {
|
||||
+ ret = airoha_cpufreq_driver_init_cpu(cpu);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = cpufreq_register_driver(&airoha_cpufreq_driver);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err:
|
||||
+ airoha_cpufreq_release();
|
||||
+ return ret;
|
||||
+}
|
||||
+module_init(airoha_cpufreq_driver_probe);
|
||||
+
|
||||
+static void __exit airoha_cpufreq_driver_remove(void)
|
||||
+{
|
||||
+ cpufreq_unregister_driver(&airoha_cpufreq_driver);
|
||||
+ airoha_cpufreq_release();
|
||||
+}
|
||||
+module_exit(airoha_cpufreq_driver_remove);
|
||||
+
|
||||
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||
+MODULE_DESCRIPTION("CPUfreq driver for Airoha SoCs");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
|
||||
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
|
||||
@@ -103,6 +103,8 @@ static const struct of_device_id allowli
|
||||
* platforms using "operating-points-v2" property.
|
||||
*/
|
||||
static const struct of_device_id blocklist[] __initconst = {
|
||||
+ { .compatible = "airoha,en7581", },
|
||||
+
|
||||
{ .compatible = "allwinner,sun50i-h6", },
|
||||
|
||||
{ .compatible = "apple,arm-platform", },
|
@ -0,0 +1,210 @@
|
||||
From 1f194995c3648e20da53137d4c9110b39e779f41 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Fri, 18 Oct 2024 11:34:35 +0200
|
||||
Subject: [PATCH 2/3] thermal: of: Add
|
||||
devm_thermal_of_zone_register_with_params() variant
|
||||
|
||||
Commit b1ae92dcfa8e ("thermal: core: Make struct thermal_zone_device
|
||||
definition internal") moved the thermal_zone_device struct from global
|
||||
thermal.h to internal thermal_core.h making the internal variables of
|
||||
the struct not accessible from the user drivers (without inclusing
|
||||
thermal_core.h).
|
||||
|
||||
One case where the internal variables might be needed is for the
|
||||
thermal_zone_params in the context of OF probe.
|
||||
|
||||
In such case a thermal driver might have default params that can only be
|
||||
parsed at runtime (example present in EFUSE or derived from other values)
|
||||
and wants to update the values in the thermal_zone_params for the
|
||||
thermal device. (to use the helper like get_slope() or get_offset())
|
||||
|
||||
To account for this scenario, introduce a variant of
|
||||
devm_thermal_of_zone_register(),
|
||||
devm_thermal_of_zone_register_with_params(), that takes and additional
|
||||
variable and permits to register the thermal device with default
|
||||
thermal_zone_params.
|
||||
|
||||
To follow OF implementation, these params are only treated as default
|
||||
params and are ignored if a related one is defined in DT. (example a
|
||||
slope or offset value defined in DT have priority to the default one
|
||||
passed in a thermal_device_params struct)
|
||||
|
||||
This permits to support both implementation, use the helpers and expose
|
||||
these values in sysfs.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/thermal/thermal_of.c | 67 +++++++++++++++++++++++++++++-------
|
||||
include/linux/thermal.h | 13 +++++++
|
||||
2 files changed, 68 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/thermal/thermal_of.c
|
||||
+++ b/drivers/thermal/thermal_of.c
|
||||
@@ -249,7 +249,7 @@ static void thermal_of_parameters_init(s
|
||||
{
|
||||
int coef[2];
|
||||
int ncoef = ARRAY_SIZE(coef);
|
||||
- int prop, ret;
|
||||
+ int prop;
|
||||
|
||||
tzp->no_hwmon = true;
|
||||
|
||||
@@ -261,14 +261,11 @@ static void thermal_of_parameters_init(s
|
||||
* thermal zone. Thus, we are considering only the first two
|
||||
* values as slope and offset.
|
||||
*/
|
||||
- ret = of_property_read_u32_array(np, "coefficients", coef, ncoef);
|
||||
- if (ret) {
|
||||
- coef[0] = 1;
|
||||
- coef[1] = 0;
|
||||
+ if (!of_property_read_u32_array(np, "coefficients", coef, ncoef)) {
|
||||
+ tzp->slope = coef[0];
|
||||
+ tzp->offset = coef[1];
|
||||
}
|
||||
|
||||
- tzp->slope = coef[0];
|
||||
- tzp->offset = coef[1];
|
||||
}
|
||||
|
||||
static struct device_node *thermal_of_zone_get_by_name(struct thermal_zone_device *tz)
|
||||
@@ -462,10 +459,15 @@ static void thermal_of_zone_unregister(s
|
||||
* zone properties and registers new thermal zone with those
|
||||
* properties.
|
||||
*
|
||||
+ * The passed thermal zone params are treated as default values and ignored if
|
||||
+ * the related property is found in DT. (DT params have priority to
|
||||
+ * default values)
|
||||
+ *
|
||||
* @sensor: A device node pointer corresponding to the sensor in the device tree
|
||||
* @id: An integer as sensor identifier
|
||||
* @data: A private data to be stored in the thermal zone dedicated private area
|
||||
* @ops: A set of thermal sensor ops
|
||||
+ * @tzp: a pointer to the default thermal zone params structure associated with the sensor
|
||||
*
|
||||
* Return: a valid thermal zone structure pointer on success.
|
||||
* - EINVAL: if the device tree thermal description is malformed
|
||||
@@ -473,11 +475,11 @@ static void thermal_of_zone_unregister(s
|
||||
* - Other negative errors are returned by the underlying called functions
|
||||
*/
|
||||
static struct thermal_zone_device *thermal_of_zone_register(struct device_node *sensor, int id, void *data,
|
||||
- const struct thermal_zone_device_ops *ops)
|
||||
+ const struct thermal_zone_device_ops *ops,
|
||||
+ struct thermal_zone_params *tzp)
|
||||
{
|
||||
struct thermal_zone_device *tz;
|
||||
struct thermal_trip *trips;
|
||||
- struct thermal_zone_params tzp = {};
|
||||
struct thermal_zone_device_ops *of_ops;
|
||||
struct device_node *np;
|
||||
int delay, pdelay;
|
||||
@@ -509,7 +511,7 @@ static struct thermal_zone_device *therm
|
||||
goto out_kfree_trips;
|
||||
}
|
||||
|
||||
- thermal_of_parameters_init(np, &tzp);
|
||||
+ thermal_of_parameters_init(np, tzp);
|
||||
|
||||
of_ops->bind = thermal_of_bind;
|
||||
of_ops->unbind = thermal_of_unbind;
|
||||
@@ -517,7 +519,7 @@ static struct thermal_zone_device *therm
|
||||
mask = GENMASK_ULL((ntrips) - 1, 0);
|
||||
|
||||
tz = thermal_zone_device_register_with_trips(np->name, trips, ntrips,
|
||||
- mask, data, of_ops, &tzp,
|
||||
+ mask, data, of_ops, tzp,
|
||||
pdelay, delay);
|
||||
if (IS_ERR(tz)) {
|
||||
ret = PTR_ERR(tz);
|
||||
@@ -572,6 +574,7 @@ static int devm_thermal_of_zone_match(st
|
||||
struct thermal_zone_device *devm_thermal_of_zone_register(struct device *dev, int sensor_id, void *data,
|
||||
const struct thermal_zone_device_ops *ops)
|
||||
{
|
||||
+ struct thermal_zone_params tzp = { .slope = 1 };
|
||||
struct thermal_zone_device **ptr, *tzd;
|
||||
|
||||
ptr = devres_alloc(devm_thermal_of_zone_release, sizeof(*ptr),
|
||||
@@ -579,7 +582,7 @@ struct thermal_zone_device *devm_thermal
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
- tzd = thermal_of_zone_register(dev->of_node, sensor_id, data, ops);
|
||||
+ tzd = thermal_of_zone_register(dev->of_node, sensor_id, data, ops, &tzp);
|
||||
if (IS_ERR(tzd)) {
|
||||
devres_free(ptr);
|
||||
return tzd;
|
||||
@@ -593,6 +596,46 @@ struct thermal_zone_device *devm_thermal
|
||||
EXPORT_SYMBOL_GPL(devm_thermal_of_zone_register);
|
||||
|
||||
/**
|
||||
+ * devm_thermal_of_zone_register_with_params - register a thermal tied with the sensor life cycle
|
||||
+ * with default params
|
||||
+ *
|
||||
+ * This function is the device version of the thermal_of_zone_register() function.
|
||||
+ *
|
||||
+ * @dev: a device structure pointer to sensor to be tied with the thermal zone OF life cycle
|
||||
+ * @sensor_id: the sensor identifier
|
||||
+ * @data: a pointer to a private data to be stored in the thermal zone 'devdata' field
|
||||
+ * @ops: a pointer to the ops structure associated with the sensor
|
||||
+ * @tzp: a pointer to the default thermal zone params structure associated with the sensor
|
||||
+ *
|
||||
+ * The thermal zone params are treated as default values and ignored if the related property is
|
||||
+ * found in DT. (DT params have priority to default values)
|
||||
+ */
|
||||
+struct thermal_zone_device *devm_thermal_of_zone_register_with_params(struct device *dev, int sensor_id,
|
||||
+ void *data,
|
||||
+ const struct thermal_zone_device_ops *ops,
|
||||
+ struct thermal_zone_params *tzp)
|
||||
+{
|
||||
+ struct thermal_zone_device **ptr, *tzd;
|
||||
+
|
||||
+ ptr = devres_alloc(devm_thermal_of_zone_release, sizeof(*ptr),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!ptr)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+
|
||||
+ tzd = thermal_of_zone_register(dev->of_node, sensor_id, data, ops, tzp);
|
||||
+ if (IS_ERR(tzd)) {
|
||||
+ devres_free(ptr);
|
||||
+ return tzd;
|
||||
+ }
|
||||
+
|
||||
+ *ptr = tzd;
|
||||
+ devres_add(dev, ptr);
|
||||
+
|
||||
+ return tzd;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(devm_thermal_of_zone_register_with_params);
|
||||
+
|
||||
+/**
|
||||
* devm_thermal_of_zone_unregister - Resource managed version of
|
||||
* thermal_of_zone_unregister().
|
||||
* @dev: Device for which which resource was allocated.
|
||||
--- a/include/linux/thermal.h
|
||||
+++ b/include/linux/thermal.h
|
||||
@@ -261,6 +261,10 @@ struct thermal_zone_params {
|
||||
#ifdef CONFIG_THERMAL_OF
|
||||
struct thermal_zone_device *devm_thermal_of_zone_register(struct device *dev, int id, void *data,
|
||||
const struct thermal_zone_device_ops *ops);
|
||||
+struct thermal_zone_device *devm_thermal_of_zone_register_with_params(struct device *dev, int id,
|
||||
+ void *data,
|
||||
+ const struct thermal_zone_device_ops *ops,
|
||||
+ struct thermal_zone_params *tzp);
|
||||
|
||||
void devm_thermal_of_zone_unregister(struct device *dev, struct thermal_zone_device *tz);
|
||||
|
||||
@@ -272,6 +276,15 @@ struct thermal_zone_device *devm_thermal
|
||||
{
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
+
|
||||
+static inline
|
||||
+struct thermal_zone_device *devm_thermal_of_zone_register_with_params(struct device *dev, int id,
|
||||
+ void *data,
|
||||
+ const struct thermal_zone_device_ops *ops,
|
||||
+ struct thermal_zone_params *tzp)
|
||||
+{
|
||||
+ return ERR_PTR(-ENOTSUPP);
|
||||
+}
|
||||
|
||||
static inline void devm_thermal_of_zone_unregister(struct device *dev,
|
||||
struct thermal_zone_device *tz)
|
@ -0,0 +1,535 @@
|
||||
From bc6a6a4ec6c28467683121cc165e5681b4acdf8d Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Tue, 27 Aug 2024 23:04:53 +0200
|
||||
Subject: [PATCH 3/3] thermal: Add support for Airoha EN7581 thermal sensor
|
||||
|
||||
Add support for Airoha EN7581 thermal sensor. This provide support for
|
||||
reading the CPU or SoC Package sensor and to setup trip points for hot
|
||||
and critical condition. An interrupt is fired to react on this and
|
||||
doesn't require passive poll to read the temperature.
|
||||
|
||||
The thermal regs provide a way to read the ADC value from an external
|
||||
register placed in the Chip SCU regs. Monitor will read this value and
|
||||
fire an interrupt if the trip condition configured is reached.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/thermal/Kconfig | 9 +
|
||||
drivers/thermal/Makefile | 1 +
|
||||
drivers/thermal/airoha_thermal.c | 482 +++++++++++++++++++++++++++++++
|
||||
3 files changed, 492 insertions(+)
|
||||
create mode 100644 drivers/thermal/airoha_thermal.c
|
||||
|
||||
--- a/drivers/thermal/Kconfig
|
||||
+++ b/drivers/thermal/Kconfig
|
||||
@@ -317,6 +317,15 @@ config QORIQ_THERMAL
|
||||
cpufreq is used as the cooling device to throttle CPUs when the
|
||||
passive trip is crossed.
|
||||
|
||||
+config AIROHA_THERMAL
|
||||
+ tristate "Airoha thermal sensor driver"
|
||||
+ depends on ARCH_AIROHA || COMPILE_TEST
|
||||
+ depends on MFD_SYSCON
|
||||
+ depends on OF
|
||||
+ help
|
||||
+ Enable this to plug the Airoha thermal sensor driver into the Linux
|
||||
+ thermal framework.
|
||||
+
|
||||
config SPEAR_THERMAL
|
||||
tristate "SPEAr thermal sensor driver"
|
||||
depends on PLAT_SPEAR || COMPILE_TEST
|
||||
--- a/drivers/thermal/Makefile
|
||||
+++ b/drivers/thermal/Makefile
|
||||
@@ -34,6 +34,7 @@ obj-$(CONFIG_K3_THERMAL) += k3_bandgap.o
|
||||
# platform thermal drivers
|
||||
obj-y += broadcom/
|
||||
obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
|
||||
+obj-$(CONFIG_AIROHA_THERMAL) += airoha_thermal.o
|
||||
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
|
||||
obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
|
||||
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/thermal/airoha_thermal.c
|
||||
@@ -0,0 +1,482 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/thermal.h>
|
||||
+
|
||||
+/* SCU regs */
|
||||
+#define EN7581_PLLRG_PROTECT 0x268
|
||||
+#define EN7581_PWD_TADC 0x2ec
|
||||
+#define EN7581_MUX_TADC GENMASK(3, 1)
|
||||
+#define EN7581_DOUT_TADC 0x2f8
|
||||
+#define EN7581_DOUT_TADC_MASK GENMASK(15, 0)
|
||||
+
|
||||
+/* PTP_THERMAL regs */
|
||||
+#define EN7581_TEMPMONCTL0 0x800
|
||||
+#define EN7581_SENSE3_EN BIT(3)
|
||||
+#define EN7581_SENSE2_EN BIT(2)
|
||||
+#define EN7581_SENSE1_EN BIT(1)
|
||||
+#define EN7581_SENSE0_EN BIT(0)
|
||||
+#define EN7581_TEMPMONCTL1 0x804
|
||||
+/* period unit calculated in BUS clock * 256 scaling-up */
|
||||
+#define EN7581_PERIOD_UNIT GENMASK(9, 0)
|
||||
+#define EN7581_TEMPMONCTL2 0x808
|
||||
+#define EN7581_FILT_INTERVAL GENMASK(25, 16)
|
||||
+#define EN7581_SEN_INTERVAL GENMASK(9, 0)
|
||||
+#define EN7581_TEMPMONINT 0x80C
|
||||
+#define EN7581_STAGE3_INT_EN BIT(31)
|
||||
+#define EN7581_STAGE2_INT_EN BIT(30)
|
||||
+#define EN7581_STAGE1_INT_EN BIT(29)
|
||||
+#define EN7581_FILTER_INT_EN_3 BIT(28)
|
||||
+#define EN7581_IMMD_INT_EN3 BIT(27)
|
||||
+#define EN7581_NOHOTINTEN3 BIT(26)
|
||||
+#define EN7581_HOFSINTEN3 BIT(25)
|
||||
+#define EN7581_LOFSINTEN3 BIT(24)
|
||||
+#define EN7581_HINTEN3 BIT(23)
|
||||
+#define EN7581_CINTEN3 BIT(22)
|
||||
+#define EN7581_FILTER_INT_EN_2 BIT(21)
|
||||
+#define EN7581_FILTER_INT_EN_1 BIT(20)
|
||||
+#define EN7581_FILTER_INT_EN_0 BIT(19)
|
||||
+#define EN7581_IMMD_INT_EN2 BIT(18)
|
||||
+#define EN7581_IMMD_INT_EN1 BIT(17)
|
||||
+#define EN7581_IMMD_INT_EN0 BIT(16)
|
||||
+#define EN7581_TIME_OUT_INT_EN BIT(15)
|
||||
+#define EN7581_NOHOTINTEN2 BIT(14)
|
||||
+#define EN7581_HOFSINTEN2 BIT(13)
|
||||
+#define EN7581_LOFSINTEN2 BIT(12)
|
||||
+#define EN7581_HINTEN2 BIT(11)
|
||||
+#define EN7581_CINTEN2 BIT(10)
|
||||
+#define EN7581_NOHOTINTEN1 BIT(9)
|
||||
+#define EN7581_HOFSINTEN1 BIT(8)
|
||||
+#define EN7581_LOFSINTEN1 BIT(7)
|
||||
+#define EN7581_HINTEN1 BIT(6)
|
||||
+#define EN7581_CINTEN1 BIT(5)
|
||||
+#define EN7581_NOHOTINTEN0 BIT(4)
|
||||
+/* Similar to COLD and HOT also these seems to be swapped in documentation */
|
||||
+#define EN7581_LOFSINTEN0 BIT(3) /* In documentation: BIT(2) */
|
||||
+#define EN7581_HOFSINTEN0 BIT(2) /* In documentation: BIT(3) */
|
||||
+/* It seems documentation have these swapped as the HW
|
||||
+ * - Fire BIT(1) when lower than EN7581_COLD_THRE
|
||||
+ * - Fire BIT(0) and BIT(5) when higher than EN7581_HOT2NORMAL_THRE or
|
||||
+ * EN7581_HOT_THRE
|
||||
+ */
|
||||
+#define EN7581_CINTEN0 BIT(1) /* In documentation: BIT(0) */
|
||||
+#define EN7581_HINTEN0 BIT(0) /* In documentation: BIT(1) */
|
||||
+#define EN7581_TEMPMONINTSTS 0x810
|
||||
+#define EN7581_STAGE3_INT_STAT BIT(31)
|
||||
+#define EN7581_STAGE2_INT_STAT BIT(30)
|
||||
+#define EN7581_STAGE1_INT_STAT BIT(29)
|
||||
+#define EN7581_FILTER_INT_STAT_3 BIT(28)
|
||||
+#define EN7581_IMMD_INT_STS3 BIT(27)
|
||||
+#define EN7581_NOHOTINTSTS3 BIT(26)
|
||||
+#define EN7581_HOFSINTSTS3 BIT(25)
|
||||
+#define EN7581_LOFSINTSTS3 BIT(24)
|
||||
+#define EN7581_HINTSTS3 BIT(23)
|
||||
+#define EN7581_CINTSTS3 BIT(22)
|
||||
+#define EN7581_FILTER_INT_STAT_2 BIT(21)
|
||||
+#define EN7581_FILTER_INT_STAT_1 BIT(20)
|
||||
+#define EN7581_FILTER_INT_STAT_0 BIT(19)
|
||||
+#define EN7581_IMMD_INT_STS2 BIT(18)
|
||||
+#define EN7581_IMMD_INT_STS1 BIT(17)
|
||||
+#define EN7581_IMMD_INT_STS0 BIT(16)
|
||||
+#define EN7581_TIME_OUT_INT_STAT BIT(15)
|
||||
+#define EN7581_NOHOTINTSTS2 BIT(14)
|
||||
+#define EN7581_HOFSINTSTS2 BIT(13)
|
||||
+#define EN7581_LOFSINTSTS2 BIT(12)
|
||||
+#define EN7581_HINTSTS2 BIT(11)
|
||||
+#define EN7581_CINTSTS2 BIT(10)
|
||||
+#define EN7581_NOHOTINTSTS1 BIT(9)
|
||||
+#define EN7581_HOFSINTSTS1 BIT(8)
|
||||
+#define EN7581_LOFSINTSTS1 BIT(7)
|
||||
+#define EN7581_HINTSTS1 BIT(6)
|
||||
+#define EN7581_CINTSTS1 BIT(5)
|
||||
+#define EN7581_NOHOTINTSTS0 BIT(4)
|
||||
+/* Similar to COLD and HOT also these seems to be swapped in documentation */
|
||||
+#define EN7581_LOFSINTSTS0 BIT(3) /* In documentation: BIT(2) */
|
||||
+#define EN7581_HOFSINTSTS0 BIT(2) /* In documentation: BIT(3) */
|
||||
+/* It seems documentation have these swapped as the HW
|
||||
+ * - Fire BIT(1) when lower than EN7581_COLD_THRE
|
||||
+ * - Fire BIT(0) and BIT(5) when higher than EN7581_HOT2NORMAL_THRE or
|
||||
+ * EN7581_HOT_THRE
|
||||
+ *
|
||||
+ * To clear things, we swap the define but we keep them documented here.
|
||||
+ */
|
||||
+#define EN7581_CINTSTS0 BIT(1) /* In documentation: BIT(0) */
|
||||
+#define EN7581_HINTSTS0 BIT(0) /* In documentation: BIT(1)*/
|
||||
+/* Monitor will take the bigger threshold between HOT2NORMAL and HOT
|
||||
+ * and will fire both HOT2NORMAL and HOT interrupt when higher than the 2
|
||||
+ *
|
||||
+ * It has also been observed that not setting HOT2NORMAL makes the monitor
|
||||
+ * treat COLD threshold as HOT2NORMAL.
|
||||
+ */
|
||||
+#define EN7581_TEMPH2NTHRE 0x824
|
||||
+/* It seems HOT2NORMAL is actually NORMAL2HOT */
|
||||
+#define EN7581_HOT2NORMAL_THRE GENMASK(11, 0)
|
||||
+#define EN7581_TEMPHTHRE 0x828
|
||||
+#define EN7581_HOT_THRE GENMASK(11, 0)
|
||||
+/* Monitor will use this as HOT2NORMAL (fire interrupt when lower than...)*/
|
||||
+#define EN7581_TEMPCTHRE 0x82c
|
||||
+#define EN7581_COLD_THRE GENMASK(11, 0)
|
||||
+/* Also LOW and HIGH offset register are swapped */
|
||||
+#define EN7581_TEMPOFFSETL 0x830 /* In documentation: 0x834 */
|
||||
+#define EN7581_LOW_OFFSET GENMASK(11, 0)
|
||||
+#define EN7581_TEMPOFFSETH 0x834 /* In documentation: 0x830 */
|
||||
+#define EN7581_HIGH_OFFSET GENMASK(11, 0)
|
||||
+#define EN7581_TEMPMSRCTL0 0x838
|
||||
+#define EN7581_MSRCTL3 GENMASK(11, 9)
|
||||
+#define EN7581_MSRCTL2 GENMASK(8, 6)
|
||||
+#define EN7581_MSRCTL1 GENMASK(5, 3)
|
||||
+#define EN7581_MSRCTL0 GENMASK(2, 0)
|
||||
+#define EN7581_TEMPADCVALIDADDR 0x878
|
||||
+#define EN7581_ADC_VALID_ADDR GENMASK(31, 0)
|
||||
+#define EN7581_TEMPADCVOLTADDR 0x87c
|
||||
+#define EN7581_ADC_VOLT_ADDR GENMASK(31, 0)
|
||||
+#define EN7581_TEMPRDCTRL 0x880
|
||||
+/*
|
||||
+ * NOTICE: AHB have this set to 0 by default. Means that
|
||||
+ * the same addr is used for ADC volt and valid reading.
|
||||
+ * In such case, VALID ADDR is used and volt addr is ignored.
|
||||
+ */
|
||||
+#define EN7581_RD_CTRL_DIFF BIT(0)
|
||||
+#define EN7581_TEMPADCVALIDMASK 0x884
|
||||
+#define EN7581_ADV_RD_VALID_POLARITY BIT(5)
|
||||
+#define EN7581_ADV_RD_VALID_POS GENMASK(4, 0)
|
||||
+#define EN7581_TEMPADCVOLTAGESHIFT 0x888
|
||||
+#define EN7581_ADC_VOLTAGE_SHIFT GENMASK(4, 0)
|
||||
+/*
|
||||
+ * Same values for each CTL.
|
||||
+ * Can operate in:
|
||||
+ * - 1 sample
|
||||
+ * - 2 sample and make average of them
|
||||
+ * - 4,6,10,16 sample, drop max and min and make avgerage of them
|
||||
+ */
|
||||
+#define EN7581_MSRCTL_1SAMPLE 0x0
|
||||
+#define EN7581_MSRCTL_AVG2SAMPLE 0x1
|
||||
+#define EN7581_MSRCTL_4SAMPLE_MAX_MIX_AVG2 0x2
|
||||
+#define EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4 0x3
|
||||
+#define EN7581_MSRCTL_10SAMPLE_MAX_MIX_AVG8 0x4
|
||||
+#define EN7581_MSRCTL_18SAMPLE_MAX_MIX_AVG16 0x5
|
||||
+#define EN7581_TEMPAHBPOLL 0x840
|
||||
+#define EN7581_ADC_POLL_INTVL GENMASK(31, 0)
|
||||
+/* PTPSPARE0,2 reg are used to store efuse info for calibrated temp offset */
|
||||
+#define EN7581_EFUSE_TEMP_OFFSET_REG 0xf20 /* PTPSPARE0 */
|
||||
+#define EN7581_EFUSE_TEMP_OFFSET GENMASK(31, 16)
|
||||
+#define EN7581_PTPSPARE1 0xf24 /* PTPSPARE1 */
|
||||
+#define EN7581_EFUSE_TEMP_CPU_SENSOR_REG 0xf28 /* PTPSPARE2 */
|
||||
+
|
||||
+#define EN7581_SLOPE_X100_DIO_DEFAULT 5645
|
||||
+#define EN7581_SLOPE_X100_DIO_AVS 5645
|
||||
+
|
||||
+#define EN7581_INIT_TEMP_CPK_X10 300
|
||||
+#define EN7581_INIT_TEMP_FTK_X10 620
|
||||
+#define EN7581_INIT_TEMP_NONK_X10 550
|
||||
+
|
||||
+#define EN7581_SCU_THERMAL_PROTECT_KEY 0x12
|
||||
+#define EN7581_SCU_THERMAL_MUX_DIODE1 0x7
|
||||
+
|
||||
+/* Convert temp to raw value as read from ADC ((((temp / 100) - init) * slope) / 1000) + offset */
|
||||
+#define TEMP_TO_RAW(priv, tz, temp) ((((((temp) / 100) - (priv)->init_temp) * \
|
||||
+ thermal_zone_get_slope(tz)) / 1000) + \
|
||||
+ thermal_zone_get_offset(tz))
|
||||
+
|
||||
+/* Convert raw to temp ((((temp - offset) * 1000) / slope + init) * 100) */
|
||||
+#define RAW_TO_TEMP(priv, tz, raw) (((((raw) - thermal_zone_get_offset(tz)) * 1000) / \
|
||||
+ thermal_zone_get_slope(tz) + \
|
||||
+ (priv)->init_temp) * 100)
|
||||
+
|
||||
+struct airoha_thermal_priv {
|
||||
+ void __iomem *base;
|
||||
+ struct regmap *chip_scu;
|
||||
+ struct resource scu_adc_res;
|
||||
+
|
||||
+ struct thermal_zone_device *tz;
|
||||
+ int init_temp;
|
||||
+};
|
||||
+
|
||||
+static int airoha_get_thermal_ADC(struct airoha_thermal_priv *priv)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ regmap_read(priv->chip_scu, EN7581_DOUT_TADC, &val);
|
||||
+ return FIELD_GET(EN7581_DOUT_TADC_MASK, val);
|
||||
+}
|
||||
+
|
||||
+static void airoha_init_thermal_ADC_mode(struct airoha_thermal_priv *priv)
|
||||
+{
|
||||
+ u32 adc_mux, pllrg;
|
||||
+
|
||||
+ /* Save PLLRG current value */
|
||||
+ regmap_read(priv->chip_scu, EN7581_PLLRG_PROTECT, &pllrg);
|
||||
+
|
||||
+ /* Give access to thermal regs */
|
||||
+ regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, EN7581_SCU_THERMAL_PROTECT_KEY);
|
||||
+ adc_mux = FIELD_PREP(EN7581_MUX_TADC, EN7581_SCU_THERMAL_MUX_DIODE1);
|
||||
+ regmap_write(priv->chip_scu, EN7581_PWD_TADC, adc_mux);
|
||||
+
|
||||
+ /* Restore PLLRG value on exit */
|
||||
+ regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, pllrg);
|
||||
+}
|
||||
+
|
||||
+static int airoha_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||
+{
|
||||
+ struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz);
|
||||
+ int min, max, avg_temp, temp_adc;
|
||||
+ int i;
|
||||
+
|
||||
+ /* Get the starting temp */
|
||||
+ temp_adc = airoha_get_thermal_ADC(priv);
|
||||
+ min = temp_adc;
|
||||
+ max = temp_adc;
|
||||
+ avg_temp = temp_adc;
|
||||
+
|
||||
+ /* Make 5 more measurement and average the temp ADC difference */
|
||||
+ for (i = 0; i < 5; i++) {
|
||||
+ temp_adc = airoha_get_thermal_ADC(priv);
|
||||
+ avg_temp += temp_adc;
|
||||
+ if (temp_adc > max)
|
||||
+ max = temp_adc;
|
||||
+ if (temp_adc < min)
|
||||
+ min = temp_adc;
|
||||
+ }
|
||||
+ avg_temp = avg_temp - max - min;
|
||||
+ avg_temp /= 4;
|
||||
+
|
||||
+ *temp = RAW_TO_TEMP(priv, tz, avg_temp);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_thermal_set_trips(struct thermal_zone_device *tz, int low,
|
||||
+ int high)
|
||||
+{
|
||||
+ struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz);
|
||||
+
|
||||
+ if (high != INT_MAX) {
|
||||
+ /* Validate high and clamp them a sane value */
|
||||
+ if (high > RAW_TO_TEMP(priv, tz, FIELD_MAX(EN7581_DOUT_TADC_MASK)))
|
||||
+ high = 110000;
|
||||
+
|
||||
+ /* We offset the high temp of 1°C to trigger correct event */
|
||||
+ writel(TEMP_TO_RAW(priv, tz, high) >> 4,
|
||||
+ priv->base + EN7581_TEMPOFFSETH);
|
||||
+ }
|
||||
+
|
||||
+ if (low != -INT_MAX) {
|
||||
+ /* Validate low and clamp them to a sane value */
|
||||
+ if (low < RAW_TO_TEMP(priv, tz, 0))
|
||||
+ low = -33000;
|
||||
+
|
||||
+ /* We offset the low temp of 1°C to trigger correct event */
|
||||
+ writel(TEMP_TO_RAW(priv, tz, low) >> 4,
|
||||
+ priv->base + EN7581_TEMPOFFSETL);
|
||||
+ }
|
||||
+
|
||||
+ /* Enable sensor 0 monitor */
|
||||
+ writel(EN7581_SENSE0_EN, priv->base + EN7581_TEMPMONCTL0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct thermal_zone_device_ops thdev_ops = {
|
||||
+ .get_temp = airoha_thermal_get_temp,
|
||||
+ .set_trips = airoha_thermal_set_trips,
|
||||
+};
|
||||
+
|
||||
+static irqreturn_t airoha_thermal_irq(int irq, void *data)
|
||||
+{
|
||||
+ struct airoha_thermal_priv *priv = data;
|
||||
+ enum thermal_notify_event event;
|
||||
+ u32 status;
|
||||
+
|
||||
+ status = readl(priv->base + EN7581_TEMPMONINTSTS);
|
||||
+ switch (status & (EN7581_HOFSINTSTS0 | EN7581_LOFSINTSTS0)) {
|
||||
+ case EN7581_HOFSINTSTS0:
|
||||
+ event = THERMAL_TRIP_VIOLATED;
|
||||
+ break;
|
||||
+ case EN7581_LOFSINTSTS0:
|
||||
+ event = THERMAL_EVENT_UNSPECIFIED;
|
||||
+ break;
|
||||
+ default:
|
||||
+ goto exit;
|
||||
+ }
|
||||
+
|
||||
+ thermal_zone_device_update(priv->tz, event);
|
||||
+
|
||||
+exit:
|
||||
+ /* reset interrupt */
|
||||
+ writel(status, priv->base + EN7581_TEMPMONINTSTS);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static void airoha_thermal_setup_adc_val(struct device *dev,
|
||||
+ struct airoha_thermal_priv *priv,
|
||||
+ struct thermal_zone_params *tzp)
|
||||
+{
|
||||
+ u32 efuse_calib_info, cpu_sensor;
|
||||
+
|
||||
+ /* Setup thermal sensor to ADC mode and setup the mux to DIODE1 */
|
||||
+ airoha_init_thermal_ADC_mode(priv);
|
||||
+ /* sleep 10 ms for ADC to enable */
|
||||
+ usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC);
|
||||
+
|
||||
+ efuse_calib_info = readl(priv->base + EN7581_EFUSE_TEMP_OFFSET_REG);
|
||||
+ if (efuse_calib_info) {
|
||||
+ tzp->offset = FIELD_GET(EN7581_EFUSE_TEMP_OFFSET, efuse_calib_info);
|
||||
+ /* Different slope are applied if the sensor is used for CPU or for package */
|
||||
+ cpu_sensor = readl(priv->base + EN7581_EFUSE_TEMP_CPU_SENSOR_REG);
|
||||
+ if (cpu_sensor) {
|
||||
+ tzp->slope = EN7581_SLOPE_X100_DIO_DEFAULT;
|
||||
+ priv->init_temp = EN7581_INIT_TEMP_FTK_X10;
|
||||
+ } else {
|
||||
+ tzp->slope = EN7581_SLOPE_X100_DIO_AVS;
|
||||
+ priv->init_temp = EN7581_INIT_TEMP_CPK_X10;
|
||||
+ }
|
||||
+ } else {
|
||||
+ tzp->offset = airoha_get_thermal_ADC(priv);
|
||||
+ tzp->slope = EN7581_SLOPE_X100_DIO_DEFAULT;
|
||||
+ priv->init_temp = EN7581_INIT_TEMP_NONK_X10;
|
||||
+ dev_info(dev, "missing thermal calibrarion EFUSE, using non calibrated value\n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void airoha_thermal_setup_monitor(struct airoha_thermal_priv *priv)
|
||||
+{
|
||||
+ /* Set measure mode */
|
||||
+ writel(FIELD_PREP(EN7581_MSRCTL0, EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4),
|
||||
+ priv->base + EN7581_TEMPMSRCTL0);
|
||||
+
|
||||
+ /*
|
||||
+ * Configure ADC valid reading addr
|
||||
+ * The AHB temp monitor system doesn't have direct access to the
|
||||
+ * thermal sensor. It does instead work by providing all kind of
|
||||
+ * address to configure how to access and setup an ADC for the
|
||||
+ * sensor. EN7581 supports only one sensor hence the
|
||||
+ * implementation is greatly simplified but the AHB supports
|
||||
+ * up to 4 different sensor from the same ADC that can be
|
||||
+ * switched by tuning the ADC mux or wiriting address.
|
||||
+ *
|
||||
+ * We set valid instead of volt as we don't enable valid/volt
|
||||
+ * split reading and AHB read valid addr in such case.
|
||||
+ */
|
||||
+ writel(priv->scu_adc_res.start + EN7581_DOUT_TADC,
|
||||
+ priv->base + EN7581_TEMPADCVALIDADDR);
|
||||
+
|
||||
+ /*
|
||||
+ * Configure valid bit on a fake value of bit 16. The ADC outputs
|
||||
+ * max of 2 bytes for voltage.
|
||||
+ */
|
||||
+ writel(FIELD_PREP(EN7581_ADV_RD_VALID_POS, 16),
|
||||
+ priv->base + EN7581_TEMPADCVALIDMASK);
|
||||
+
|
||||
+ /*
|
||||
+ * AHB supports max 12 bytes for ADC voltage. Shift the read
|
||||
+ * value 4 bit to the right. Precision lost by this is minimal
|
||||
+ * in the order of half a °C and is acceptable in the context
|
||||
+ * of triggering interrupt in critical condition.
|
||||
+ */
|
||||
+ writel(FIELD_PREP(EN7581_ADC_VOLTAGE_SHIFT, 4),
|
||||
+ priv->base + EN7581_TEMPADCVOLTAGESHIFT);
|
||||
+
|
||||
+ /* BUS clock is 300MHz counting unit is 3 * 68.64 * 256 = 52.715us */
|
||||
+ writel(FIELD_PREP(EN7581_PERIOD_UNIT, 3),
|
||||
+ priv->base + EN7581_TEMPMONCTL1);
|
||||
+
|
||||
+ /*
|
||||
+ * filt interval is 1 * 52.715us = 52.715us,
|
||||
+ * sen interval is 379 * 52.715us = 19.97ms
|
||||
+ */
|
||||
+ writel(FIELD_PREP(EN7581_FILT_INTERVAL, 1) |
|
||||
+ FIELD_PREP(EN7581_FILT_INTERVAL, 379),
|
||||
+ priv->base + EN7581_TEMPMONCTL2);
|
||||
+
|
||||
+ /* AHB poll is set to 146 * 68.64 = 10.02us */
|
||||
+ writel(FIELD_PREP(EN7581_ADC_POLL_INTVL, 146),
|
||||
+ priv->base + EN7581_TEMPAHBPOLL);
|
||||
+}
|
||||
+
|
||||
+static int airoha_thermal_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct thermal_zone_params tzp = { };
|
||||
+ struct airoha_thermal_priv *priv;
|
||||
+ struct device_node *chip_scu_np;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ int irq, ret;
|
||||
+
|
||||
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(priv->base))
|
||||
+ return PTR_ERR(priv->base);
|
||||
+
|
||||
+ chip_scu_np = of_parse_phandle(dev->of_node, "airoha,chip-scu", 0);
|
||||
+ if (!chip_scu_np)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ priv->chip_scu = syscon_node_to_regmap(chip_scu_np);
|
||||
+ if (IS_ERR(priv->chip_scu))
|
||||
+ return PTR_ERR(priv->chip_scu);
|
||||
+
|
||||
+ of_address_to_resource(chip_scu_np, 0, &priv->scu_adc_res);
|
||||
+ of_node_put(chip_scu_np);
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0)
|
||||
+ return irq;
|
||||
+
|
||||
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
+ airoha_thermal_irq, IRQF_ONESHOT,
|
||||
+ pdev->name, (void *)priv);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "Can't get interrupt working.\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ airoha_thermal_setup_monitor(priv);
|
||||
+ airoha_thermal_setup_adc_val(dev, priv, &tzp);
|
||||
+
|
||||
+ /* register of thermal sensor and get info from DT */
|
||||
+ priv->tz = devm_thermal_of_zone_register_with_params(dev, 0, priv,
|
||||
+ &thdev_ops,
|
||||
+ &tzp);
|
||||
+ if (IS_ERR(priv->tz)) {
|
||||
+ dev_err(dev, "register thermal zone sensor failed\n");
|
||||
+ return PTR_ERR(priv->tz);
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(pdev, priv);
|
||||
+
|
||||
+ /* Enable LOW and HIGH interrupt */
|
||||
+ writel(EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0,
|
||||
+ priv->base + EN7581_TEMPMONINT);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id airoha_thermal_match[] = {
|
||||
+ { .compatible = "airoha,en7581-thermal" },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, airoha_thermal_match);
|
||||
+
|
||||
+static struct platform_driver airoha_thermal_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "airoha-thermal",
|
||||
+ .of_match_table = airoha_thermal_match,
|
||||
+ },
|
||||
+ .probe = airoha_thermal_probe,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(airoha_thermal_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||
+MODULE_DESCRIPTION("Airoha thermal driver");
|
||||
+MODULE_LICENSE("GPL");
|
@ -0,0 +1,304 @@
|
||||
From 9dbd16ac89e00bd8640ecac3971b0943410b5cec Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Sat, 6 Jul 2024 01:15:24 +0200
|
||||
Subject: [PATCH 2/2] hwrng: add support for Airoha EN7581 TRNG
|
||||
|
||||
Add support for Airoha TRNG. The Airoha SoC provide a True RNG module
|
||||
that can output 4 bytes of raw data at times.
|
||||
|
||||
The module makes use of various noise source to provide True Random
|
||||
Number Generation.
|
||||
|
||||
On probe the module is reset to operate Health Test and verify correct
|
||||
execution of it.
|
||||
|
||||
The module can also provide DRBG function but the execution mode is
|
||||
mutually exclusive, running as TRNG doesn't permit to also run it as
|
||||
DRBG.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/char/hw_random/Kconfig | 13 ++
|
||||
drivers/char/hw_random/Makefile | 1 +
|
||||
drivers/char/hw_random/airoha-trng.c | 243 +++++++++++++++++++++++++++
|
||||
3 files changed, 257 insertions(+)
|
||||
create mode 100644 drivers/char/hw_random/airoha-trng.c
|
||||
|
||||
--- a/drivers/char/hw_random/Kconfig
|
||||
+++ b/drivers/char/hw_random/Kconfig
|
||||
@@ -62,6 +62,19 @@ config HW_RANDOM_AMD
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
+config HW_RANDOM_AIROHA
|
||||
+ tristate "Airoha True HW Random Number Generator support"
|
||||
+ depends on ARCH_AIROHA || COMPILE_TEST
|
||||
+ default HW_RANDOM
|
||||
+ help
|
||||
+ This driver provides kernel-side support for the True Random Number
|
||||
+ Generator hardware found on Airoha SoC.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called airoha-rng.
|
||||
+
|
||||
+ If unsure, say Y.
|
||||
+
|
||||
config HW_RANDOM_ATMEL
|
||||
tristate "Atmel Random Number Generator support"
|
||||
depends on (ARCH_AT91 || COMPILE_TEST)
|
||||
--- a/drivers/char/hw_random/Makefile
|
||||
+++ b/drivers/char/hw_random/Makefile
|
||||
@@ -8,6 +8,7 @@ rng-core-y := core.o
|
||||
obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
|
||||
+obj-$(CONFIG_HW_RANDOM_AIROHA) += airoha-trng.o
|
||||
obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_BA431) += ba431-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/char/hw_random/airoha-trng.c
|
||||
@@ -0,0 +1,243 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/* Copyright (C) 2024 Christian Marangi */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mod_devicetable.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/iopoll.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/hw_random.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/delay.h>
|
||||
+
|
||||
+#define TRNG_IP_RDY 0x800
|
||||
+#define CNT_TRANS GENMASK(15, 8)
|
||||
+#define SAMPLE_RDY BIT(0)
|
||||
+#define TRNG_NS_SEK_AND_DAT_EN 0x804
|
||||
+#define RNG_EN BIT(31) /* referenced as ring_en */
|
||||
+#define RAW_DATA_EN BIT(16)
|
||||
+#define TRNG_HEALTH_TEST_SW_RST 0x808
|
||||
+#define SW_RST BIT(0) /* Active High */
|
||||
+#define TRNG_INTR_EN 0x818
|
||||
+#define INTR_MASK BIT(16)
|
||||
+#define CONTINUOUS_HEALTH_INITR_EN BIT(2)
|
||||
+#define SW_STARTUP_INITR_EN BIT(1)
|
||||
+#define RST_STARTUP_INITR_EN BIT(0)
|
||||
+/* Notice that Health Test are done only out of Reset and with RNG_EN */
|
||||
+#define TRNG_HEALTH_TEST_STATUS 0x824
|
||||
+#define CONTINUOUS_HEALTH_AP_TEST_FAIL BIT(23)
|
||||
+#define CONTINUOUS_HEALTH_RC_TEST_FAIL BIT(22)
|
||||
+#define SW_STARTUP_TEST_DONE BIT(21)
|
||||
+#define SW_STARTUP_AP_TEST_FAIL BIT(20)
|
||||
+#define SW_STARTUP_RC_TEST_FAIL BIT(19)
|
||||
+#define RST_STARTUP_TEST_DONE BIT(18)
|
||||
+#define RST_STARTUP_AP_TEST_FAIL BIT(17)
|
||||
+#define RST_STARTUP_RC_TEST_FAIL BIT(16)
|
||||
+#define RAW_DATA_VALID BIT(7)
|
||||
+
|
||||
+#define TRNG_RAW_DATA_OUT 0x828
|
||||
+
|
||||
+#define TRNG_CNT_TRANS_VALID 0x80
|
||||
+#define BUSY_LOOP_SLEEP 10
|
||||
+#define BUSY_LOOP_TIMEOUT (BUSY_LOOP_SLEEP * 10000)
|
||||
+
|
||||
+struct airoha_trng {
|
||||
+ void __iomem *base;
|
||||
+ struct hwrng rng;
|
||||
+ struct device *dev;
|
||||
+
|
||||
+ struct completion rng_op_done;
|
||||
+};
|
||||
+
|
||||
+static int airoha_trng_irq_mask(struct airoha_trng *trng)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(trng->base + TRNG_INTR_EN);
|
||||
+ val |= INTR_MASK;
|
||||
+ writel(val, trng->base + TRNG_INTR_EN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_trng_irq_unmask(struct airoha_trng *trng)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(trng->base + TRNG_INTR_EN);
|
||||
+ val &= ~INTR_MASK;
|
||||
+ writel(val, trng->base + TRNG_INTR_EN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_trng_init(struct hwrng *rng)
|
||||
+{
|
||||
+ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng);
|
||||
+ int ret;
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+ val |= RNG_EN;
|
||||
+ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+
|
||||
+ /* Set out of SW Reset */
|
||||
+ airoha_trng_irq_unmask(trng);
|
||||
+ writel(0, trng->base + TRNG_HEALTH_TEST_SW_RST);
|
||||
+
|
||||
+ ret = wait_for_completion_timeout(&trng->rng_op_done, BUSY_LOOP_TIMEOUT);
|
||||
+ if (ret <= 0) {
|
||||
+ dev_err(trng->dev, "Timeout waiting for Health Check\n");
|
||||
+ airoha_trng_irq_mask(trng);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /* Check if Health Test Failed */
|
||||
+ val = readl(trng->base + TRNG_HEALTH_TEST_STATUS);
|
||||
+ if (val & (RST_STARTUP_AP_TEST_FAIL | RST_STARTUP_RC_TEST_FAIL)) {
|
||||
+ dev_err(trng->dev, "Health Check fail: %s test fail\n",
|
||||
+ val & RST_STARTUP_AP_TEST_FAIL ? "AP" : "RC");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /* Check if IP is ready */
|
||||
+ ret = readl_poll_timeout(trng->base + TRNG_IP_RDY, val,
|
||||
+ val & SAMPLE_RDY, 10, 1000);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(trng->dev, "Timeout waiting for IP ready");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /* CNT_TRANS must be 0x80 for IP to be considered ready */
|
||||
+ ret = readl_poll_timeout(trng->base + TRNG_IP_RDY, val,
|
||||
+ FIELD_GET(CNT_TRANS, val) == TRNG_CNT_TRANS_VALID,
|
||||
+ 10, 1000);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(trng->dev, "Timeout waiting for IP ready");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void airoha_trng_cleanup(struct hwrng *rng)
|
||||
+{
|
||||
+ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+ val &= ~RNG_EN;
|
||||
+ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+
|
||||
+ /* Put it in SW Reset */
|
||||
+ writel(SW_RST, trng->base + TRNG_HEALTH_TEST_SW_RST);
|
||||
+}
|
||||
+
|
||||
+static int airoha_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
|
||||
+{
|
||||
+ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng);
|
||||
+ u32 *data = buf;
|
||||
+ u32 status;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = readl_poll_timeout(trng->base + TRNG_HEALTH_TEST_STATUS, status,
|
||||
+ status & RAW_DATA_VALID, 10, 1000);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(trng->dev, "Timeout waiting for TRNG RAW Data valid\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ *data = readl(trng->base + TRNG_RAW_DATA_OUT);
|
||||
+
|
||||
+ return 4;
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t airoha_trng_irq(int irq, void *priv)
|
||||
+{
|
||||
+ struct airoha_trng *trng = (struct airoha_trng *)priv;
|
||||
+
|
||||
+ airoha_trng_irq_mask(trng);
|
||||
+ /* Just complete the task, we will read the value later */
|
||||
+ complete(&trng->rng_op_done);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int airoha_trng_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct airoha_trng *trng;
|
||||
+ int irq, ret;
|
||||
+ u32 val;
|
||||
+
|
||||
+ trng = devm_kzalloc(dev, sizeof(*trng), GFP_KERNEL);
|
||||
+ if (!trng)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ trng->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(trng->base))
|
||||
+ return PTR_ERR(trng->base);
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0)
|
||||
+ return irq;
|
||||
+
|
||||
+ airoha_trng_irq_mask(trng);
|
||||
+ ret = devm_request_irq(&pdev->dev, irq, airoha_trng_irq, 0,
|
||||
+ pdev->name, (void *)trng);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "Can't get interrupt working.\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ init_completion(&trng->rng_op_done);
|
||||
+
|
||||
+ /* Enable interrupt for SW reset Health Check */
|
||||
+ val = readl(trng->base + TRNG_INTR_EN);
|
||||
+ val |= RST_STARTUP_INITR_EN;
|
||||
+ writel(val, trng->base + TRNG_INTR_EN);
|
||||
+
|
||||
+ /* Set output to raw data */
|
||||
+ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+ val |= RAW_DATA_EN;
|
||||
+ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+
|
||||
+ /* Put it in SW Reset */
|
||||
+ writel(SW_RST, trng->base + TRNG_HEALTH_TEST_SW_RST);
|
||||
+
|
||||
+ trng->dev = dev;
|
||||
+ trng->rng.name = pdev->name;
|
||||
+ trng->rng.init = airoha_trng_init;
|
||||
+ trng->rng.cleanup = airoha_trng_cleanup;
|
||||
+ trng->rng.read = airoha_trng_read;
|
||||
+
|
||||
+ ret = devm_hwrng_register(dev, &trng->rng);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to register rng device: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id airoha_trng_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-trng", },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, airoha_trng_of_match);
|
||||
+
|
||||
+static struct platform_driver airoha_trng_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "airoha-trng",
|
||||
+ .of_match_table = airoha_trng_of_match,
|
||||
+ },
|
||||
+ .probe = airoha_trng_probe,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(airoha_trng_driver);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||
+MODULE_DESCRIPTION("Airoha True Random Number Generator driver");
|
@ -0,0 +1,268 @@
|
||||
From 4019d58ca5b249e4cf79169cc0c6a4ff5275c155 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Fri, 5 Jul 2024 19:12:12 +0200
|
||||
Subject: [PATCH v2 2/2] watchdog: Add support for Airoha EN7851 watchdog
|
||||
|
||||
Add support for Airoha EN7851 watchdog. This is a very basic watchdog
|
||||
with no pretimeout support, max timeout is 28 seconds and it ticks based
|
||||
on half the SoC BUS clock.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
Changes v2:
|
||||
- Drop clock-frequency implementation
|
||||
- Add missing bitfield.h header
|
||||
- Attach BUS clock
|
||||
|
||||
drivers/watchdog/Kconfig | 8 ++
|
||||
drivers/watchdog/Makefile | 1 +
|
||||
drivers/watchdog/airoha_wdt.c | 216 ++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 225 insertions(+)
|
||||
create mode 100644 drivers/watchdog/airoha_wdt.c
|
||||
|
||||
--- a/drivers/watchdog/Kconfig
|
||||
+++ b/drivers/watchdog/Kconfig
|
||||
@@ -372,6 +372,14 @@ config SL28CPLD_WATCHDOG
|
||||
|
||||
# ARM Architecture
|
||||
|
||||
+config AIROHA_WATCHDOG
|
||||
+ tristate "Airoha EN7581 Watchdog"
|
||||
+ depends on ARCH_AIROHA || COMPILE_TEST
|
||||
+ select WATCHDOG_CORE
|
||||
+ help
|
||||
+ Watchdog timer embedded into Airoha SoC. This will reboot your
|
||||
+ system when the timeout is reached.
|
||||
+
|
||||
config ARM_SP805_WATCHDOG
|
||||
tristate "ARM SP805 Watchdog"
|
||||
depends on (ARM || ARM64 || COMPILE_TEST) && ARM_AMBA
|
||||
--- a/drivers/watchdog/Makefile
|
||||
+++ b/drivers/watchdog/Makefile
|
||||
@@ -40,6 +40,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.
|
||||
obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
|
||||
obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
|
||||
obj-$(CONFIG_ARMADA_37XX_WATCHDOG) += armada_37xx_wdt.o
|
||||
+obj-$(CONFIG_AIROHA_WATCHDOG) += airoha_wdt.o
|
||||
obj-$(CONFIG_ASM9260_WATCHDOG) += asm9260_wdt.o
|
||||
obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
|
||||
obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/watchdog/airoha_wdt.c
|
||||
@@ -0,0 +1,216 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Airoha Watchdog Driver
|
||||
+ *
|
||||
+ * Copyright (c) 2024, AIROHA All rights reserved.
|
||||
+ *
|
||||
+ * Mayur Kumar <mayur.kumar@airoha.com>
|
||||
+ * Christian Marangi <ansuelsmth@gmail.com>
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/moduleparam.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/math.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/watchdog.h>
|
||||
+
|
||||
+/* Base address of timer and watchdog registers */
|
||||
+#define TIMER_CTRL 0x0
|
||||
+#define WDT_ENABLE BIT(25)
|
||||
+#define WDT_TIMER_INTERRUPT BIT(21)
|
||||
+/* Timer3 is used as Watchdog Timer */
|
||||
+#define WDT_TIMER_ENABLE BIT(5)
|
||||
+#define WDT_TIMER_LOAD_VALUE 0x2c
|
||||
+#define WDT_TIMER_CUR_VALUE 0x30
|
||||
+#define WDT_TIMER_VAL GENMASK(31, 0)
|
||||
+#define WDT_RELOAD 0x38
|
||||
+#define WDT_RLD BIT(0)
|
||||
+
|
||||
+/* Airoha watchdog structure description */
|
||||
+struct airoha_wdt_desc {
|
||||
+ struct watchdog_device wdog_dev;
|
||||
+ unsigned int wdt_freq;
|
||||
+ void __iomem *base;
|
||||
+};
|
||||
+
|
||||
+#define WDT_HEARTBEAT 24
|
||||
+static int heartbeat = WDT_HEARTBEAT;
|
||||
+module_param(heartbeat, int, 0);
|
||||
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. (default="
|
||||
+ __MODULE_STRING(WDT_HEARTBEAT) ")");
|
||||
+
|
||||
+static bool nowayout = WATCHDOG_NOWAYOUT;
|
||||
+module_param(nowayout, bool, 0);
|
||||
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
|
||||
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
+
|
||||
+static int airoha_wdt_start(struct watchdog_device *wdog_dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(airoha_wdt->base + TIMER_CTRL);
|
||||
+ val |= (WDT_TIMER_ENABLE | WDT_ENABLE | WDT_TIMER_INTERRUPT);
|
||||
+ writel(val, airoha_wdt->base + TIMER_CTRL);
|
||||
+ val = wdog_dev->timeout * airoha_wdt->wdt_freq;
|
||||
+ writel(val, airoha_wdt->base + WDT_TIMER_LOAD_VALUE);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_wdt_stop(struct watchdog_device *wdog_dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(airoha_wdt->base + TIMER_CTRL);
|
||||
+ val &= (~WDT_ENABLE & ~WDT_TIMER_ENABLE);
|
||||
+ writel(val, airoha_wdt->base + TIMER_CTRL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_wdt_ping(struct watchdog_device *wdog_dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(airoha_wdt->base + WDT_RELOAD);
|
||||
+ val |= WDT_RLD;
|
||||
+ writel(val, airoha_wdt->base + WDT_RELOAD);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_wdt_set_timeout(struct watchdog_device *wdog_dev, unsigned int timeout)
|
||||
+{
|
||||
+ wdog_dev->timeout = timeout;
|
||||
+
|
||||
+ if (watchdog_active(wdog_dev)) {
|
||||
+ airoha_wdt_stop(wdog_dev);
|
||||
+ return airoha_wdt_start(wdog_dev);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static unsigned int airoha_wdt_get_timeleft(struct watchdog_device *wdog_dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(airoha_wdt->base + WDT_TIMER_CUR_VALUE);
|
||||
+ return DIV_ROUND_UP(val, airoha_wdt->wdt_freq);
|
||||
+}
|
||||
+
|
||||
+static const struct watchdog_info airoha_wdt_info = {
|
||||
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
|
||||
+ .identity = "Airoha Watchdog",
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_ops airoha_wdt_ops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .start = airoha_wdt_start,
|
||||
+ .stop = airoha_wdt_stop,
|
||||
+ .ping = airoha_wdt_ping,
|
||||
+ .set_timeout = airoha_wdt_set_timeout,
|
||||
+ .get_timeleft = airoha_wdt_get_timeleft,
|
||||
+};
|
||||
+
|
||||
+static int airoha_wdt_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt;
|
||||
+ struct watchdog_device *wdog_dev;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct clk *bus_clk;
|
||||
+ int ret;
|
||||
+
|
||||
+ airoha_wdt = devm_kzalloc(dev, sizeof(*airoha_wdt), GFP_KERNEL);
|
||||
+ if (!airoha_wdt)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ airoha_wdt->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(airoha_wdt->base))
|
||||
+ return PTR_ERR(airoha_wdt->base);
|
||||
+
|
||||
+ bus_clk = devm_clk_get_enabled(dev, "bus");
|
||||
+ if (IS_ERR(bus_clk))
|
||||
+ return dev_err_probe(dev, PTR_ERR(bus_clk),
|
||||
+ "failed to enable bus clock\n");
|
||||
+
|
||||
+ /* Watchdog ticks at half the bus rate */
|
||||
+ airoha_wdt->wdt_freq = clk_get_rate(bus_clk) / 2;
|
||||
+
|
||||
+ /* Initialize struct watchdog device */
|
||||
+ wdog_dev = &airoha_wdt->wdog_dev;
|
||||
+ wdog_dev->timeout = heartbeat;
|
||||
+ wdog_dev->info = &airoha_wdt_info;
|
||||
+ wdog_dev->ops = &airoha_wdt_ops;
|
||||
+ /* Bus 300MHz, watchdog 150MHz, 28 seconds */
|
||||
+ wdog_dev->max_timeout = FIELD_MAX(WDT_TIMER_VAL) / airoha_wdt->wdt_freq;
|
||||
+ wdog_dev->parent = dev;
|
||||
+
|
||||
+ watchdog_set_drvdata(wdog_dev, airoha_wdt);
|
||||
+ watchdog_set_nowayout(wdog_dev, nowayout);
|
||||
+ watchdog_stop_on_unregister(wdog_dev);
|
||||
+
|
||||
+ ret = devm_watchdog_register_device(dev, wdog_dev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, airoha_wdt);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_wdt_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = dev_get_drvdata(dev);
|
||||
+
|
||||
+ if (watchdog_active(&airoha_wdt->wdog_dev))
|
||||
+ airoha_wdt_stop(&airoha_wdt->wdog_dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_wdt_resume(struct device *dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = dev_get_drvdata(dev);
|
||||
+
|
||||
+ if (watchdog_active(&airoha_wdt->wdog_dev)) {
|
||||
+ airoha_wdt_start(&airoha_wdt->wdog_dev);
|
||||
+ airoha_wdt_ping(&airoha_wdt->wdog_dev);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id airoha_wdt_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-wdt", },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+MODULE_DEVICE_TABLE(of, airoha_wdt_of_match);
|
||||
+
|
||||
+static DEFINE_SIMPLE_DEV_PM_OPS(airoha_wdt_pm_ops, airoha_wdt_suspend, airoha_wdt_resume);
|
||||
+
|
||||
+static struct platform_driver airoha_wdt_driver = {
|
||||
+ .probe = airoha_wdt_probe,
|
||||
+ .driver = {
|
||||
+ .name = "airoha-wdt",
|
||||
+ .pm = pm_sleep_ptr(&airoha_wdt_pm_ops),
|
||||
+ .of_match_table = airoha_wdt_of_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(airoha_wdt_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Mayur Kumar <mayur.kumar@airoha.com>");
|
||||
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||
+MODULE_DESCRIPTION("Airoha EN7581 Watchdog Driver");
|
||||
+MODULE_LICENSE("GPL");
|
@ -0,0 +1,11 @@
|
||||
--- a/drivers/i2c/busses/i2c-mt7621.c
|
||||
+++ b/drivers/i2c/busses/i2c-mt7621.c
|
||||
@@ -85,7 +85,7 @@ static void mtk_i2c_reset(struct mtk_i2c
|
||||
{
|
||||
int ret;
|
||||
|
||||
- ret = device_reset(i2c->adap.dev.parent);
|
||||
+ ret = device_reset_optional(i2c->adap.dev.parent);
|
||||
if (ret)
|
||||
dev_err(i2c->dev, "I2C reset failed!\n");
|
||||
|
@ -0,0 +1,187 @@
|
||||
--- /dev/null
|
||||
+++ b/drivers/tty/serial/8250/8250_en7523.c
|
||||
@@ -0,0 +1,94 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * Airoha EN7523 driver.
|
||||
+ *
|
||||
+ * Copyright (c) 2022 Genexis Sweden AB
|
||||
+ * Author: Benjamin Larsson <benjamin.larsson@genexis.eu>
|
||||
+ */
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_irq.h>
|
||||
+#include <linux/of_platform.h>
|
||||
+#include <linux/pinctrl/consumer.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pm_runtime.h>
|
||||
+#include <linux/serial_8250.h>
|
||||
+#include <linux/serial_reg.h>
|
||||
+#include <linux/console.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/tty.h>
|
||||
+#include <linux/tty_flip.h>
|
||||
+
|
||||
+#include "8250.h"
|
||||
+
|
||||
+
|
||||
+/* The Airoha UART is 16550-compatible except for the baud rate calculation.
|
||||
+ *
|
||||
+ * crystal_clock = 20 MHz
|
||||
+ * xindiv_clock = crystal_clock / clock_div
|
||||
+ * (x/y) = XYD, 32 bit register with 16 bits of x and and then 16 bits of y
|
||||
+ * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)),
|
||||
+ * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ]
|
||||
+ *
|
||||
+ * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16)
|
||||
+ *
|
||||
+ * XYD_y seems to need to be larger then XYD_x for things to work.
|
||||
+ * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values
|
||||
+ * for usual baud rates.
|
||||
+ *
|
||||
+ * Selecting divider needs to fulfill
|
||||
+ * 1.8432 MHz <= xindiv_clk <= APB clock / 2
|
||||
+ * The clocks are unknown but a divider of value 1 did not work.
|
||||
+ *
|
||||
+ * Optimally the XYD, BRD and XINCLK_DIVCNT registers could be searched to
|
||||
+ * find values that gives the least error for every baud rate. But searching
|
||||
+ * the space takes time and in practise only a few rates are of interest.
|
||||
+ * With some value combinations not working a tested subset is used giving
|
||||
+ * a usable range from 110 to 460800 baud.
|
||||
+ */
|
||||
+
|
||||
+#define CLOCK_DIV_TAB_ELEMS 3
|
||||
+#define XYD_Y 65000
|
||||
+#define XINDIV_CLOCK 20000000
|
||||
+#define UART_BRDL_20M 0x01
|
||||
+#define UART_BRDH_20M 0x00
|
||||
+
|
||||
+static int clock_div_tab[] = { 10, 4, 2};
|
||||
+static int clock_div_reg[] = { 4, 2, 1};
|
||||
+
|
||||
+
|
||||
+int en7523_set_uart_baud_rate (struct uart_port *port, unsigned int baud)
|
||||
+{
|
||||
+ struct uart_8250_port *up = up_to_u8250p(port);
|
||||
+ unsigned int xyd_x, nom, denom;
|
||||
+ int i;
|
||||
+
|
||||
+ /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */
|
||||
+ serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
|
||||
+
|
||||
+ /* set baud rate calculation defaults */
|
||||
+
|
||||
+ /* set BRDIV ([BRDH,BRDL]) to 1 */
|
||||
+ serial_port_out(port, UART_BRDL, UART_BRDL_20M);
|
||||
+ serial_port_out(port, UART_BRDH, UART_BRDH_20M);
|
||||
+
|
||||
+ /* calculate XYD_x and XINCLKDR register */
|
||||
+
|
||||
+ for (i = 0 ; i < CLOCK_DIV_TAB_ELEMS ; i++) {
|
||||
+ denom = (XINDIV_CLOCK/40) / clock_div_tab[i];
|
||||
+ nom = (baud * (XYD_Y/40));
|
||||
+ xyd_x = ((nom/denom) << 4);
|
||||
+ if (xyd_x < XYD_Y) break;
|
||||
+ }
|
||||
+
|
||||
+ serial_port_out(port, UART_XINCLKDR, clock_div_reg[i]);
|
||||
+ serial_port_out(port, UART_XYD, (xyd_x<<16) | XYD_Y);
|
||||
+
|
||||
+ /* unset DLAB */
|
||||
+ serial_port_out(port, UART_LCR, up->lcr);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+EXPORT_SYMBOL_GPL(en7523_set_uart_baud_rate);
|
||||
--- a/drivers/tty/serial/8250/8250_of.c
|
||||
+++ b/drivers/tty/serial/8250/8250_of.c
|
||||
@@ -338,6 +338,7 @@ static const struct of_device_id of_plat
|
||||
{ .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
|
||||
{ .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, },
|
||||
{ .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, },
|
||||
+ { .compatible = "airoha,en7523-uart", .data = (void *)PORT_AIROHA, },
|
||||
{ /* end of list */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_platform_serial_table);
|
||||
--- a/drivers/tty/serial/8250/8250_port.c
|
||||
+++ b/drivers/tty/serial/8250/8250_port.c
|
||||
@@ -330,6 +330,14 @@ static const struct serial8250_config ua
|
||||
.rxtrig_bytes = {1, 8, 16, 30},
|
||||
.flags = UART_CAP_FIFO | UART_CAP_AFE,
|
||||
},
|
||||
+ [PORT_AIROHA] = {
|
||||
+ .name = "Airoha 16550",
|
||||
+ .fifo_size = 8,
|
||||
+ .tx_loadsz = 1,
|
||||
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01,
|
||||
+ .rxtrig_bytes = {1, 4},
|
||||
+ .flags = UART_CAP_FIFO,
|
||||
+ },
|
||||
};
|
||||
|
||||
/* Uart divisor latch read */
|
||||
@@ -2880,6 +2888,12 @@ serial8250_do_set_termios(struct uart_po
|
||||
|
||||
serial8250_set_divisor(port, baud, quot, frac);
|
||||
|
||||
+#ifdef CONFIG_SERIAL_8250_AIROHA
|
||||
+ /* Airoha SoCs have custom registers for baud rate settings */
|
||||
+ if (port->type == PORT_AIROHA)
|
||||
+ en7523_set_uart_baud_rate(port, baud);
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
|
||||
* is written without DLAB set, this mode will be disabled.
|
||||
--- a/drivers/tty/serial/8250/Makefile
|
||||
+++ b/drivers/tty/serial/8250/Makefile
|
||||
@@ -46,6 +46,7 @@ obj-$(CONFIG_SERIAL_8250_PERICOM) += 825
|
||||
obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o
|
||||
obj-$(CONFIG_SERIAL_8250_TEGRA) += 8250_tegra.o
|
||||
obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o
|
||||
+obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_en7523.o
|
||||
obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o
|
||||
|
||||
CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
|
||||
--- a/include/uapi/linux/serial_reg.h
|
||||
+++ b/include/uapi/linux/serial_reg.h
|
||||
@@ -382,5 +382,17 @@
|
||||
#define UART_ALTR_EN_TXFIFO_LW 0x01 /* Enable the TX FIFO Low Watermark */
|
||||
#define UART_ALTR_TX_LOW 0x41 /* Tx FIFO Low Watermark */
|
||||
|
||||
+/*
|
||||
+ * These are definitions for the Airoha EN75XX uart registers
|
||||
+ * Normalized because of 32 bits registers.
|
||||
+ */
|
||||
+#define UART_BRDL 0
|
||||
+#define UART_BRDH 1
|
||||
+#define UART_XINCLKDR 10
|
||||
+#define UART_XYD 11
|
||||
+#define UART_TXLVLCNT 12
|
||||
+#define UART_RXLVLCNT 13
|
||||
+#define UART_FINTLVL 14
|
||||
+
|
||||
#endif /* _LINUX_SERIAL_REG_H */
|
||||
|
||||
--- a/include/uapi/linux/serial_core.h
|
||||
+++ b/include/uapi/linux/serial_core.h
|
||||
@@ -45,6 +45,7 @@
|
||||
#define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */
|
||||
#define PORT_RT2880 29 /* Ralink RT2880 internal UART */
|
||||
#define PORT_16550A_FSL64 30 /* Freescale 16550 UART with 64 FIFOs */
|
||||
+#define PORT_AIROHA 31 /* Airoha 16550 UART */
|
||||
|
||||
/*
|
||||
* ARM specific type numbers. These are not currently guaranteed
|
||||
--- a/include/linux/serial_8250.h
|
||||
+++ b/include/linux/serial_8250.h
|
||||
@@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart
|
||||
void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
|
||||
unsigned int quot, unsigned int quot_frac);
|
||||
int fsl8250_handle_irq(struct uart_port *port);
|
||||
+int en7523_set_uart_baud_rate(struct uart_port *port, unsigned int baud);
|
||||
int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
|
||||
u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr);
|
||||
void serial8250_read_char(struct uart_8250_port *up, u16 lsr);
|
@ -0,0 +1,60 @@
|
||||
From 64e497f372dfca3e6be9fe05a0f9b874ea8604d2 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 3 Sep 2024 23:39:46 +0200
|
||||
Subject: [PATCH 1/6] clk: en7523: remove REG_PCIE*_{MEM,MEM_MASK}
|
||||
configuration
|
||||
|
||||
REG_PCIE*_MEM and REG_PCIE*_MEM_MASK regs (PBUS_CSR memory region) are not
|
||||
part of the scu block on the EN7581 SoC and they are used to select the
|
||||
PCIE ports on the PBUS, so remove this configuration from the clock driver
|
||||
and set these registers in the PCIE host driver instead.
|
||||
This patch does not introduce any backward incompatibility since the dts
|
||||
for EN7581 SoC is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 18 ------------------
|
||||
1 file changed, 18 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -31,12 +31,6 @@
|
||||
#define REG_RESET_CONTROL_PCIE1 BIT(27)
|
||||
#define REG_RESET_CONTROL_PCIE2 BIT(26)
|
||||
/* EN7581 */
|
||||
-#define REG_PCIE0_MEM 0x00
|
||||
-#define REG_PCIE0_MEM_MASK 0x04
|
||||
-#define REG_PCIE1_MEM 0x08
|
||||
-#define REG_PCIE1_MEM_MASK 0x0c
|
||||
-#define REG_PCIE2_MEM 0x10
|
||||
-#define REG_PCIE2_MEM_MASK 0x14
|
||||
#define REG_NP_SCU_PCIC 0x88
|
||||
#define REG_NP_SCU_SSTR 0x9c
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
@@ -415,26 +409,14 @@ static void en7581_pci_disable(struct cl
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
void __iomem *np_base)
|
||||
{
|
||||
- void __iomem *pb_base;
|
||||
u32 val;
|
||||
|
||||
- pb_base = devm_platform_ioremap_resource(pdev, 3);
|
||||
- if (IS_ERR(pb_base))
|
||||
- return PTR_ERR(pb_base);
|
||||
-
|
||||
val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
|
||||
- writel(0x20000000, pb_base + REG_PCIE0_MEM);
|
||||
- writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK);
|
||||
- writel(0x24000000, pb_base + REG_PCIE1_MEM);
|
||||
- writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK);
|
||||
- writel(0x28000000, pb_base + REG_PCIE2_MEM);
|
||||
- writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,144 @@
|
||||
From 0dd8a6df58a4a8cf1f341249e7358b3bb51f52ad Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 3 Sep 2024 23:39:47 +0200
|
||||
Subject: [PATCH 2/6] clk: en7523: move clock_register in hw_init callback
|
||||
|
||||
Move en7523_register_clocks routine in hw_init callback.
|
||||
Introduce en7523_clk_hw_init callback for EN7523 SoC.
|
||||
This is a preliminary patch to differentiate IO mapped region between
|
||||
EN7523 and EN7581 SoCs in order to access chip-scu IO region
|
||||
<0x1fa20000 0x384> on EN7581 SoC as syscon device since it contains
|
||||
miscellaneous registers needed by multiple devices (clock, pinctrl ..).
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 82 ++++++++++++++++++++++++----------------
|
||||
1 file changed, 50 insertions(+), 32 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -78,7 +78,8 @@ struct en_clk_soc_data {
|
||||
const u16 *idx_map;
|
||||
u16 idx_map_nr;
|
||||
} reset;
|
||||
- int (*hw_init)(struct platform_device *pdev, void __iomem *np_base);
|
||||
+ int (*hw_init)(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data);
|
||||
};
|
||||
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
@@ -406,20 +407,6 @@ static void en7581_pci_disable(struct cl
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
|
||||
-static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
- void __iomem *np_base)
|
||||
-{
|
||||
- u32 val;
|
||||
-
|
||||
- val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
- writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
- val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
- writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
|
||||
void __iomem *base, void __iomem *np_base)
|
||||
{
|
||||
@@ -449,6 +436,49 @@ static void en7523_register_clocks(struc
|
||||
clk_data->num = EN7523_NUM_CLOCKS;
|
||||
}
|
||||
|
||||
+static int en7523_clk_hw_init(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data)
|
||||
+{
|
||||
+ void __iomem *base, *np_base;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ np_base = devm_platform_ioremap_resource(pdev, 1);
|
||||
+ if (IS_ERR(np_base))
|
||||
+ return PTR_ERR(np_base);
|
||||
+
|
||||
+ en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data)
|
||||
+{
|
||||
+ void __iomem *base, *np_base;
|
||||
+ u32 val;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ np_base = devm_platform_ioremap_resource(pdev, 1);
|
||||
+ if (IS_ERR(np_base))
|
||||
+ return PTR_ERR(np_base);
|
||||
+
|
||||
+ en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
|
||||
+
|
||||
+ val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
+ writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
+ writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int en7523_reset_update(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
@@ -543,31 +573,18 @@ static int en7523_clk_probe(struct platf
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
const struct en_clk_soc_data *soc_data;
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
- void __iomem *base, *np_base;
|
||||
int r;
|
||||
|
||||
- base = devm_platform_ioremap_resource(pdev, 0);
|
||||
- if (IS_ERR(base))
|
||||
- return PTR_ERR(base);
|
||||
-
|
||||
- np_base = devm_platform_ioremap_resource(pdev, 1);
|
||||
- if (IS_ERR(np_base))
|
||||
- return PTR_ERR(np_base);
|
||||
-
|
||||
- soc_data = device_get_match_data(&pdev->dev);
|
||||
- if (soc_data->hw_init) {
|
||||
- r = soc_data->hw_init(pdev, np_base);
|
||||
- if (r)
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
clk_data = devm_kzalloc(&pdev->dev,
|
||||
struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
|
||||
GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
- en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
|
||||
+ soc_data = device_get_match_data(&pdev->dev);
|
||||
+ r = soc_data->hw_init(pdev, clk_data);
|
||||
+ if (r)
|
||||
+ return r;
|
||||
|
||||
r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
|
||||
if (r)
|
||||
@@ -590,6 +607,7 @@ static const struct en_clk_soc_data en75
|
||||
.prepare = en7523_pci_prepare,
|
||||
.unprepare = en7523_pci_unprepare,
|
||||
},
|
||||
+ .hw_init = en7523_clk_hw_init,
|
||||
};
|
||||
|
||||
static const struct en_clk_soc_data en7581_data = {
|
@ -0,0 +1,160 @@
|
||||
From f849bcb746abeaafa63b4f02f1d8bb22703fc645 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 3 Sep 2024 23:39:48 +0200
|
||||
Subject: [PATCH 3/6] clk: en7523: introduce chip_scu regmap
|
||||
|
||||
Introduce chip_scu regmap pointer since EN7581 SoC will access chip-scu
|
||||
memory area via a syscon node. Remove first memory region mapping
|
||||
for EN7581 SoC. This patch does not introduce any backward incompatibility
|
||||
since the dts for EN7581 SoC is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 81 ++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 61 insertions(+), 20 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -3,8 +3,10 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
+#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <dt-bindings/clock/en7523-clk.h>
|
||||
#include <dt-bindings/reset/airoha,en7581-reset.h>
|
||||
@@ -247,15 +249,11 @@ static const u16 en7581_rst_map[] = {
|
||||
[EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
|
||||
};
|
||||
|
||||
-static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
|
||||
+static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
|
||||
{
|
||||
- const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
- u32 val;
|
||||
-
|
||||
if (!desc->base_bits)
|
||||
return desc->base_value;
|
||||
|
||||
- val = readl(base + desc->base_reg);
|
||||
val >>= desc->base_shift;
|
||||
val &= (1 << desc->base_bits) - 1;
|
||||
|
||||
@@ -265,16 +263,11 @@ static unsigned int en7523_get_base_rate
|
||||
return desc->base_values[val];
|
||||
}
|
||||
|
||||
-static u32 en7523_get_div(void __iomem *base, int i)
|
||||
+static u32 en7523_get_div(const struct en_clk_desc *desc, u32 val)
|
||||
{
|
||||
- const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
- u32 reg, val;
|
||||
-
|
||||
if (!desc->div_bits)
|
||||
return 1;
|
||||
|
||||
- reg = desc->div_reg ? desc->div_reg : desc->base_reg;
|
||||
- val = readl(base + reg);
|
||||
val >>= desc->div_shift;
|
||||
val &= (1 << desc->div_bits) - 1;
|
||||
|
||||
@@ -416,9 +409,12 @@ static void en7523_register_clocks(struc
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
|
||||
const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
+ u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
|
||||
+ u32 val = readl(base + desc->base_reg);
|
||||
|
||||
- rate = en7523_get_base_rate(base, i);
|
||||
- rate /= en7523_get_div(base, i);
|
||||
+ rate = en7523_get_base_rate(desc, val);
|
||||
+ val = readl(base + reg);
|
||||
+ rate /= en7523_get_div(desc, val);
|
||||
|
||||
hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
|
||||
if (IS_ERR(hw)) {
|
||||
@@ -454,21 +450,66 @@ static int en7523_clk_hw_init(struct pla
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
|
||||
+ struct regmap *map, void __iomem *base)
|
||||
+{
|
||||
+ struct clk_hw *hw;
|
||||
+ u32 rate;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
|
||||
+ const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
+ u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
|
||||
+ int err;
|
||||
+
|
||||
+ err = regmap_read(map, desc->base_reg, &val);
|
||||
+ if (err) {
|
||||
+ pr_err("Failed reading fixed clk rate %s: %d\n",
|
||||
+ desc->name, err);
|
||||
+ continue;
|
||||
+ }
|
||||
+ rate = en7523_get_base_rate(desc, val);
|
||||
+
|
||||
+ err = regmap_read(map, reg, &val);
|
||||
+ if (err) {
|
||||
+ pr_err("Failed reading fixed clk div %s: %d\n",
|
||||
+ desc->name, err);
|
||||
+ continue;
|
||||
+ }
|
||||
+ rate /= en7523_get_div(desc, val);
|
||||
+
|
||||
+ hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
|
||||
+ if (IS_ERR(hw)) {
|
||||
+ pr_err("Failed to register clk %s: %ld\n",
|
||||
+ desc->name, PTR_ERR(hw));
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ clk_data->hws[desc->id] = hw;
|
||||
+ }
|
||||
+
|
||||
+ hw = en7523_register_pcie_clk(dev, base);
|
||||
+ clk_data->hws[EN7523_CLK_PCIE] = hw;
|
||||
+
|
||||
+ clk_data->num = EN7523_NUM_CLOCKS;
|
||||
+}
|
||||
+
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
struct clk_hw_onecell_data *clk_data)
|
||||
{
|
||||
- void __iomem *base, *np_base;
|
||||
+ void __iomem *np_base;
|
||||
+ struct regmap *map;
|
||||
u32 val;
|
||||
|
||||
- base = devm_platform_ioremap_resource(pdev, 0);
|
||||
- if (IS_ERR(base))
|
||||
- return PTR_ERR(base);
|
||||
+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
|
||||
+ if (IS_ERR(map))
|
||||
+ return PTR_ERR(map);
|
||||
|
||||
- np_base = devm_platform_ioremap_resource(pdev, 1);
|
||||
+ np_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(np_base))
|
||||
return PTR_ERR(np_base);
|
||||
|
||||
- en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
|
||||
+ en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
|
||||
|
||||
val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
@@ -545,7 +586,7 @@ static int en7523_reset_register(struct
|
||||
if (!soc_data->reset.idx_map_nr)
|
||||
return 0;
|
||||
|
||||
- base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ base = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
@ -0,0 +1,150 @@
|
||||
From b9ea4918216ca0c2511446c531d3f8163ac1466d Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 3 Sep 2024 23:39:49 +0200
|
||||
Subject: [PATCH 4/6] clk: en7523: fix estimation of fixed rate for EN7581
|
||||
|
||||
Introduce en7581_base_clks array in order to define per-SoC fixed-rate
|
||||
clock parameters and fix wrong parameters for emi, npu and crypto EN7581
|
||||
clocks
|
||||
|
||||
Fixes: 66bc47326ce2 ("clk: en7523: Add EN7581 support")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 105 ++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 103 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -37,6 +37,7 @@
|
||||
#define REG_NP_SCU_SSTR 0x9c
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
+#define REG_CRYPTO_CLKSRC2 0x20c
|
||||
|
||||
#define REG_RST_CTRL2 0x00
|
||||
#define REG_RST_CTRL1 0x04
|
||||
@@ -89,6 +90,10 @@ static const u32 emi_base[] = { 33300000
|
||||
static const u32 bus_base[] = { 500000000, 540000000 };
|
||||
static const u32 slic_base[] = { 100000000, 3125000 };
|
||||
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
|
||||
+/* EN7581 */
|
||||
+static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
|
||||
+static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
|
||||
+static const u32 crypto_base[] = { 540000000, 480000000 };
|
||||
|
||||
static const struct en_clk_desc en7523_base_clks[] = {
|
||||
{
|
||||
@@ -186,6 +191,102 @@ static const struct en_clk_desc en7523_b
|
||||
}
|
||||
};
|
||||
|
||||
+static const struct en_clk_desc en7581_base_clks[] = {
|
||||
+ {
|
||||
+ .id = EN7523_CLK_GSW,
|
||||
+ .name = "gsw",
|
||||
+
|
||||
+ .base_reg = REG_GSW_CLK_DIV_SEL,
|
||||
+ .base_bits = 1,
|
||||
+ .base_shift = 8,
|
||||
+ .base_values = gsw_base,
|
||||
+ .n_base_values = ARRAY_SIZE(gsw_base),
|
||||
+
|
||||
+ .div_bits = 3,
|
||||
+ .div_shift = 0,
|
||||
+ .div_step = 1,
|
||||
+ .div_offset = 1,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_EMI,
|
||||
+ .name = "emi",
|
||||
+
|
||||
+ .base_reg = REG_EMI_CLK_DIV_SEL,
|
||||
+ .base_bits = 2,
|
||||
+ .base_shift = 8,
|
||||
+ .base_values = emi7581_base,
|
||||
+ .n_base_values = ARRAY_SIZE(emi7581_base),
|
||||
+
|
||||
+ .div_bits = 3,
|
||||
+ .div_shift = 0,
|
||||
+ .div_step = 1,
|
||||
+ .div_offset = 1,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_BUS,
|
||||
+ .name = "bus",
|
||||
+
|
||||
+ .base_reg = REG_BUS_CLK_DIV_SEL,
|
||||
+ .base_bits = 1,
|
||||
+ .base_shift = 8,
|
||||
+ .base_values = bus_base,
|
||||
+ .n_base_values = ARRAY_SIZE(bus_base),
|
||||
+
|
||||
+ .div_bits = 3,
|
||||
+ .div_shift = 0,
|
||||
+ .div_step = 1,
|
||||
+ .div_offset = 1,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_SLIC,
|
||||
+ .name = "slic",
|
||||
+
|
||||
+ .base_reg = REG_SPI_CLK_FREQ_SEL,
|
||||
+ .base_bits = 1,
|
||||
+ .base_shift = 0,
|
||||
+ .base_values = slic_base,
|
||||
+ .n_base_values = ARRAY_SIZE(slic_base),
|
||||
+
|
||||
+ .div_reg = REG_SPI_CLK_DIV_SEL,
|
||||
+ .div_bits = 5,
|
||||
+ .div_shift = 24,
|
||||
+ .div_val0 = 20,
|
||||
+ .div_step = 2,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_SPI,
|
||||
+ .name = "spi",
|
||||
+
|
||||
+ .base_reg = REG_SPI_CLK_DIV_SEL,
|
||||
+
|
||||
+ .base_value = 400000000,
|
||||
+
|
||||
+ .div_bits = 5,
|
||||
+ .div_shift = 8,
|
||||
+ .div_val0 = 40,
|
||||
+ .div_step = 2,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_NPU,
|
||||
+ .name = "npu",
|
||||
+
|
||||
+ .base_reg = REG_NPU_CLK_DIV_SEL,
|
||||
+ .base_bits = 2,
|
||||
+ .base_shift = 8,
|
||||
+ .base_values = npu7581_base,
|
||||
+ .n_base_values = ARRAY_SIZE(npu7581_base),
|
||||
+
|
||||
+ .div_bits = 3,
|
||||
+ .div_shift = 0,
|
||||
+ .div_step = 1,
|
||||
+ .div_offset = 1,
|
||||
+ }, {
|
||||
+ .id = EN7523_CLK_CRYPTO,
|
||||
+ .name = "crypto",
|
||||
+
|
||||
+ .base_reg = REG_CRYPTO_CLKSRC2,
|
||||
+ .base_bits = 1,
|
||||
+ .base_shift = 0,
|
||||
+ .base_values = crypto_base,
|
||||
+ .n_base_values = ARRAY_SIZE(crypto_base),
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
static const u16 en7581_rst_ofs[] = {
|
||||
REG_RST_CTRL2,
|
||||
REG_RST_CTRL1,
|
||||
@@ -457,8 +558,8 @@ static void en7581_register_clocks(struc
|
||||
u32 rate;
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
|
||||
- const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
+ for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) {
|
||||
+ const struct en_clk_desc *desc = &en7581_base_clks[i];
|
||||
u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
|
||||
int err;
|
||||
|
@ -0,0 +1,172 @@
|
||||
From 2c5b1a5b68973947a6919d9c951f9b3e0d84f347 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 3 Sep 2024 23:39:50 +0200
|
||||
Subject: [PATCH 5/6] clk: en7523: move en7581_reset_register() in
|
||||
en7581_clk_hw_init()
|
||||
|
||||
Move en7581_reset_register routine in en7581_clk_hw_init() since reset
|
||||
feature is supported just by EN7581 SoC.
|
||||
Get rid of reset struct in en_clk_soc_data data struct.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 93 ++++++++++++++--------------------------
|
||||
1 file changed, 33 insertions(+), 60 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -76,11 +76,6 @@ struct en_rst_data {
|
||||
|
||||
struct en_clk_soc_data {
|
||||
const struct clk_ops pcie_ops;
|
||||
- struct {
|
||||
- const u16 *bank_ofs;
|
||||
- const u16 *idx_map;
|
||||
- u16 idx_map_nr;
|
||||
- } reset;
|
||||
int (*hw_init)(struct platform_device *pdev,
|
||||
struct clk_hw_onecell_data *clk_data);
|
||||
};
|
||||
@@ -595,32 +590,6 @@ static void en7581_register_clocks(struc
|
||||
clk_data->num = EN7523_NUM_CLOCKS;
|
||||
}
|
||||
|
||||
-static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
- struct clk_hw_onecell_data *clk_data)
|
||||
-{
|
||||
- void __iomem *np_base;
|
||||
- struct regmap *map;
|
||||
- u32 val;
|
||||
-
|
||||
- map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
|
||||
- if (IS_ERR(map))
|
||||
- return PTR_ERR(map);
|
||||
-
|
||||
- np_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
- if (IS_ERR(np_base))
|
||||
- return PTR_ERR(np_base);
|
||||
-
|
||||
- en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
|
||||
-
|
||||
- val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
- writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
- val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
- writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int en7523_reset_update(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
@@ -670,23 +639,18 @@ static int en7523_reset_xlate(struct res
|
||||
return rst_data->idx_map[reset_spec->args[0]];
|
||||
}
|
||||
|
||||
-static const struct reset_control_ops en7523_reset_ops = {
|
||||
+static const struct reset_control_ops en7581_reset_ops = {
|
||||
.assert = en7523_reset_assert,
|
||||
.deassert = en7523_reset_deassert,
|
||||
.status = en7523_reset_status,
|
||||
};
|
||||
|
||||
-static int en7523_reset_register(struct platform_device *pdev,
|
||||
- const struct en_clk_soc_data *soc_data)
|
||||
+static int en7581_reset_register(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct en_rst_data *rst_data;
|
||||
void __iomem *base;
|
||||
|
||||
- /* no reset lines available */
|
||||
- if (!soc_data->reset.idx_map_nr)
|
||||
- return 0;
|
||||
-
|
||||
base = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
@@ -695,13 +659,13 @@ static int en7523_reset_register(struct
|
||||
if (!rst_data)
|
||||
return -ENOMEM;
|
||||
|
||||
- rst_data->bank_ofs = soc_data->reset.bank_ofs;
|
||||
- rst_data->idx_map = soc_data->reset.idx_map;
|
||||
+ rst_data->bank_ofs = en7581_rst_ofs;
|
||||
+ rst_data->idx_map = en7581_rst_map;
|
||||
rst_data->base = base;
|
||||
|
||||
- rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr;
|
||||
+ rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
|
||||
rst_data->rcdev.of_xlate = en7523_reset_xlate;
|
||||
- rst_data->rcdev.ops = &en7523_reset_ops;
|
||||
+ rst_data->rcdev.ops = &en7581_reset_ops;
|
||||
rst_data->rcdev.of_node = dev->of_node;
|
||||
rst_data->rcdev.of_reset_n_cells = 1;
|
||||
rst_data->rcdev.owner = THIS_MODULE;
|
||||
@@ -710,6 +674,32 @@ static int en7523_reset_register(struct
|
||||
return devm_reset_controller_register(dev, &rst_data->rcdev);
|
||||
}
|
||||
|
||||
+static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data)
|
||||
+{
|
||||
+ void __iomem *np_base;
|
||||
+ struct regmap *map;
|
||||
+ u32 val;
|
||||
+
|
||||
+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
|
||||
+ if (IS_ERR(map))
|
||||
+ return PTR_ERR(map);
|
||||
+
|
||||
+ np_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(np_base))
|
||||
+ return PTR_ERR(np_base);
|
||||
+
|
||||
+ en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
|
||||
+
|
||||
+ val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
+ writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
+ writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
+
|
||||
+ return en7581_reset_register(pdev);
|
||||
+}
|
||||
+
|
||||
static int en7523_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
@@ -728,19 +718,7 @@ static int en7523_clk_probe(struct platf
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
|
||||
- if (r)
|
||||
- return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n",
|
||||
- pdev->name);
|
||||
-
|
||||
- r = en7523_reset_register(pdev, soc_data);
|
||||
- if (r) {
|
||||
- of_clk_del_provider(node);
|
||||
- return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n",
|
||||
- pdev->name);
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
+ return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
|
||||
}
|
||||
|
||||
static const struct en_clk_soc_data en7523_data = {
|
||||
@@ -758,11 +736,6 @@ static const struct en_clk_soc_data en75
|
||||
.enable = en7581_pci_enable,
|
||||
.disable = en7581_pci_disable,
|
||||
},
|
||||
- .reset = {
|
||||
- .bank_ofs = en7581_rst_ofs,
|
||||
- .idx_map = en7581_rst_map,
|
||||
- .idx_map_nr = ARRAY_SIZE(en7581_rst_map),
|
||||
- },
|
||||
.hw_init = en7581_clk_hw_init,
|
||||
};
|
||||
|
@ -0,0 +1,82 @@
|
||||
From 665a59f4836c3d7813a9d8bfb9680d93adb4626e Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 3 Sep 2024 23:39:51 +0200
|
||||
Subject: [PATCH 6/6] clk: en7523: map io region in a single block
|
||||
|
||||
Map all clock-controller memory region in a single block.
|
||||
This patch does not introduce any backward incompatibility since the dts
|
||||
for EN7581 SoC is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 32 +++++++++++++-------------------
|
||||
1 file changed, 13 insertions(+), 19 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -39,8 +39,8 @@
|
||||
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
#define REG_CRYPTO_CLKSRC2 0x20c
|
||||
|
||||
-#define REG_RST_CTRL2 0x00
|
||||
-#define REG_RST_CTRL1 0x04
|
||||
+#define REG_RST_CTRL2 0x830
|
||||
+#define REG_RST_CTRL1 0x834
|
||||
|
||||
struct en_clk_desc {
|
||||
int id;
|
||||
@@ -645,15 +645,9 @@ static const struct reset_control_ops en
|
||||
.status = en7523_reset_status,
|
||||
};
|
||||
|
||||
-static int en7581_reset_register(struct platform_device *pdev)
|
||||
+static int en7581_reset_register(struct device *dev, void __iomem *base)
|
||||
{
|
||||
- struct device *dev = &pdev->dev;
|
||||
struct en_rst_data *rst_data;
|
||||
- void __iomem *base;
|
||||
-
|
||||
- base = devm_platform_ioremap_resource(pdev, 1);
|
||||
- if (IS_ERR(base))
|
||||
- return PTR_ERR(base);
|
||||
|
||||
rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
|
||||
if (!rst_data)
|
||||
@@ -677,27 +671,27 @@ static int en7581_reset_register(struct
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
struct clk_hw_onecell_data *clk_data)
|
||||
{
|
||||
- void __iomem *np_base;
|
||||
struct regmap *map;
|
||||
+ void __iomem *base;
|
||||
u32 val;
|
||||
|
||||
map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
|
||||
if (IS_ERR(map))
|
||||
return PTR_ERR(map);
|
||||
|
||||
- np_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
- if (IS_ERR(np_base))
|
||||
- return PTR_ERR(np_base);
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
|
||||
- en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
|
||||
+ en7581_register_clocks(&pdev->dev, clk_data, map, base);
|
||||
|
||||
- val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(base + REG_NP_SCU_SSTR);
|
||||
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
- writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
- val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
- writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
+ writel(val, base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(base + REG_NP_SCU_PCIC);
|
||||
+ writel(val | 3, base + REG_NP_SCU_PCIC);
|
||||
|
||||
- return en7581_reset_register(pdev);
|
||||
+ return en7581_reset_register(&pdev->dev, base);
|
||||
}
|
||||
|
||||
static int en7523_clk_probe(struct platform_device *pdev)
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,474 @@
|
||||
From b235c45e83c8c2a24746652982d569896b142de9 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Larsson <benjamin.larsson@genexis.eu>
|
||||
Date: Wed, 16 Oct 2024 12:07:34 +0200
|
||||
Subject: [PATCH 2/2] pwm: airoha: Add support for EN7581 SoC
|
||||
|
||||
Introduce driver for PWM module available on EN7581 SoC.
|
||||
|
||||
Signed-off-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
|
||||
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/pwm/Kconfig | 11 +
|
||||
drivers/pwm/Makefile | 1 +
|
||||
drivers/pwm/pwm-airoha.c | 424 +++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 436 insertions(+)
|
||||
create mode 100644 drivers/pwm/pwm-airoha.c
|
||||
|
||||
--- a/drivers/pwm/Kconfig
|
||||
+++ b/drivers/pwm/Kconfig
|
||||
@@ -51,6 +51,17 @@ config PWM_AB8500
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called pwm-ab8500.
|
||||
|
||||
+config PWM_AIROHA
|
||||
+ tristate "Airoha PWM support"
|
||||
+ depends on ARCH_AIROHA || COMPILE_TEST
|
||||
+ depends on OF
|
||||
+ select REGMAP_MMIO
|
||||
+ help
|
||||
+ Generic PWM framework driver for Airoha SoC.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the module
|
||||
+ will be called pwm-airoha.
|
||||
+
|
||||
config PWM_APPLE
|
||||
tristate "Apple SoC PWM support"
|
||||
depends on ARCH_APPLE || COMPILE_TEST
|
||||
--- a/drivers/pwm/Makefile
|
||||
+++ b/drivers/pwm/Makefile
|
||||
@@ -2,6 +2,7 @@
|
||||
obj-$(CONFIG_PWM) += core.o
|
||||
obj-$(CONFIG_PWM_SYSFS) += sysfs.o
|
||||
obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
|
||||
+obj-$(CONFIG_PWM_AIROHA) += pwm-airoha.o
|
||||
obj-$(CONFIG_PWM_APPLE) += pwm-apple.o
|
||||
obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o
|
||||
obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pwm/pwm-airoha.c
|
||||
@@ -0,0 +1,424 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright 2022 Markus Gothe <markus.gothe@genexis.eu>
|
||||
+ *
|
||||
+ * Limitations:
|
||||
+ * - No disable bit, so a disabled PWM is simulated by setting duty_cycle to 0
|
||||
+ * - Only 8 concurrent waveform generators are available for 8 combinations of
|
||||
+ * duty_cycle and period. Waveform generators are shared between 16 GPIO
|
||||
+ * pins and 17 SIPO GPIO pins.
|
||||
+ * - Supports only normal polarity.
|
||||
+ * - On configuration the currently running period is completed.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/iopoll.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pwm.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <asm/div64.h>
|
||||
+
|
||||
+#define REG_SGPIO_LED_DATA 0x0024
|
||||
+#define SGPIO_LED_DATA_SHIFT_FLAG BIT(31)
|
||||
+#define SGPIO_LED_DATA_DATA GENMASK(16, 0)
|
||||
+
|
||||
+#define REG_SGPIO_CLK_DIVR 0x0028
|
||||
+#define REG_SGPIO_CLK_DLY 0x002c
|
||||
+
|
||||
+#define REG_SIPO_FLASH_MODE_CFG 0x0030
|
||||
+#define SERIAL_GPIO_FLASH_MODE BIT(1)
|
||||
+#define SERIAL_GPIO_MODE BIT(0)
|
||||
+
|
||||
+#define REG_GPIO_FLASH_PRD_SET(_n) (0x003c + ((_n) << 2))
|
||||
+#define GPIO_FLASH_PRD_MASK(_n) GENMASK(15 + ((_n) << 4), ((_n) << 4))
|
||||
+
|
||||
+#define REG_GPIO_FLASH_MAP(_n) (0x004c + ((_n) << 2))
|
||||
+#define GPIO_FLASH_SETID_MASK(_n) GENMASK(2 + ((_n) << 2), ((_n) << 2))
|
||||
+#define GPIO_FLASH_EN(_n) BIT(3 + ((_n) << 2))
|
||||
+
|
||||
+#define REG_SIPO_FLASH_MAP(_n) (0x0054 + ((_n) << 2))
|
||||
+
|
||||
+#define REG_CYCLE_CFG_VALUE(_n) (0x0098 + ((_n) << 2))
|
||||
+#define WAVE_GEN_CYCLE_MASK(_n) GENMASK(7 + ((_n) << 3), ((_n) << 3))
|
||||
+
|
||||
+#define EN7581_NUM_BUCKETS 8
|
||||
+
|
||||
+struct airoha_pwm_bucket {
|
||||
+ /* Bitmask of PWM channels using this bucket */
|
||||
+ u64 used;
|
||||
+ u64 period_ns;
|
||||
+ u64 duty_ns;
|
||||
+};
|
||||
+
|
||||
+struct airoha_pwm {
|
||||
+ struct pwm_chip chip;
|
||||
+
|
||||
+ struct regmap *regmap;
|
||||
+
|
||||
+ struct device_node *np;
|
||||
+ u64 initialized;
|
||||
+
|
||||
+ struct airoha_pwm_bucket bucket[EN7581_NUM_BUCKETS];
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * The first 16 GPIO pins, GPIO0-GPIO15, are mapped into 16 PWM channels, 0-15.
|
||||
+ * The SIPO GPIO pins are 17 pins which are mapped into 17 PWM channels, 16-32.
|
||||
+ * However, we've only got 8 concurrent waveform generators and can therefore
|
||||
+ * only use up to 8 different combinations of duty cycle and period at a time.
|
||||
+ */
|
||||
+#define PWM_NUM_GPIO 16
|
||||
+#define PWM_NUM_SIPO 17
|
||||
+
|
||||
+/* The PWM hardware supports periods between 4 ms and 1 s */
|
||||
+#define PERIOD_MIN_NS (4 * NSEC_PER_MSEC)
|
||||
+#define PERIOD_MAX_NS (1 * NSEC_PER_SEC)
|
||||
+/* It is represented internally as 1/250 s between 1 and 250 */
|
||||
+#define PERIOD_MIN 1
|
||||
+#define PERIOD_MAX 250
|
||||
+/* Duty cycle is relative with 255 corresponding to 100% */
|
||||
+#define DUTY_FULL 255
|
||||
+
|
||||
+static int airoha_pwm_get_generator(struct airoha_pwm *pc, u64 duty_ns,
|
||||
+ u64 period_ns)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(pc->bucket); i++) {
|
||||
+ if (!pc->bucket[i].used)
|
||||
+ continue;
|
||||
+
|
||||
+ if (duty_ns == pc->bucket[i].duty_ns &&
|
||||
+ period_ns == pc->bucket[i].period_ns)
|
||||
+ return i;
|
||||
+
|
||||
+ /*
|
||||
+ * Unlike duty cycle zero, which can be handled by
|
||||
+ * disabling PWM, a generator is needed for full duty
|
||||
+ * cycle but it can be reused regardless of period
|
||||
+ */
|
||||
+ if (duty_ns == DUTY_FULL && pc->bucket[i].duty_ns == DUTY_FULL)
|
||||
+ return i;
|
||||
+ }
|
||||
+
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static void airoha_pwm_release_bucket_config(struct airoha_pwm *pc,
|
||||
+ unsigned int hwpwm)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(pc->bucket); i++)
|
||||
+ pc->bucket[i].used &= ~BIT_ULL(hwpwm);
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_consume_generator(struct airoha_pwm *pc,
|
||||
+ u64 duty_ns, u64 period_ns,
|
||||
+ unsigned int hwpwm)
|
||||
+{
|
||||
+ int id = airoha_pwm_get_generator(pc, duty_ns, period_ns);
|
||||
+
|
||||
+ if (id < 0) {
|
||||
+ int i;
|
||||
+
|
||||
+ /* find an unused waveform generator */
|
||||
+ for (i = 0; i < ARRAY_SIZE(pc->bucket); i++) {
|
||||
+ if (!(pc->bucket[i].used & ~BIT_ULL(hwpwm))) {
|
||||
+ id = i;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (id >= 0) {
|
||||
+ airoha_pwm_release_bucket_config(pc, hwpwm);
|
||||
+ pc->bucket[id].used |= BIT_ULL(hwpwm);
|
||||
+ pc->bucket[id].period_ns = period_ns;
|
||||
+ pc->bucket[id].duty_ns = duty_ns;
|
||||
+ }
|
||||
+
|
||||
+ return id;
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_sipo_init(struct airoha_pwm *pc)
|
||||
+{
|
||||
+ u32 clk_divr_val, sipo_clock_delay, sipo_clock_divisor;
|
||||
+ u32 val;
|
||||
+
|
||||
+ if (!(pc->initialized >> PWM_NUM_GPIO))
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Select the right shift register chip.
|
||||
+ * By default 74HC164 is assumed. With this enabled
|
||||
+ * 74HC595 chip is used that requires the latch pin
|
||||
+ * to be triggered to apply the configuration.
|
||||
+ */
|
||||
+ if (of_property_read_bool(pc->np, "airoha,74hc595-mode"))
|
||||
+ regmap_set_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG,
|
||||
+ SERIAL_GPIO_MODE);
|
||||
+ else
|
||||
+ regmap_clear_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG,
|
||||
+ SERIAL_GPIO_MODE);
|
||||
+
|
||||
+ if (of_property_read_u32(pc->np, "airoha,sipo-clock-divisor",
|
||||
+ &sipo_clock_divisor))
|
||||
+ sipo_clock_divisor = 32;
|
||||
+
|
||||
+ switch (sipo_clock_divisor) {
|
||||
+ case 4:
|
||||
+ clk_divr_val = 0;
|
||||
+ break;
|
||||
+ case 8:
|
||||
+ clk_divr_val = 1;
|
||||
+ break;
|
||||
+ case 16:
|
||||
+ clk_divr_val = 2;
|
||||
+ break;
|
||||
+ case 32:
|
||||
+ clk_divr_val = 3;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* Configure shift register timings */
|
||||
+ regmap_write(pc->regmap, REG_SGPIO_CLK_DIVR, clk_divr_val);
|
||||
+
|
||||
+ if (of_property_read_u32(pc->np, "airoha,sipo-clock-delay",
|
||||
+ &sipo_clock_delay))
|
||||
+ sipo_clock_delay = 1;
|
||||
+
|
||||
+ if (sipo_clock_delay < 1 || sipo_clock_delay > sipo_clock_divisor / 2)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /*
|
||||
+ * The actual delay is sclkdly + 1 so subtract 1 from
|
||||
+ * sipo-clock-delay to calculate the register value
|
||||
+ */
|
||||
+ sipo_clock_delay--;
|
||||
+ regmap_write(pc->regmap, REG_SGPIO_CLK_DLY, sipo_clock_delay);
|
||||
+
|
||||
+ /*
|
||||
+ * It it necessary to after muxing explicitly shift out all
|
||||
+ * zeroes to initialize the shift register before enabling PWM
|
||||
+ * mode because in PWM mode SIPO will not start shifting until
|
||||
+ * it needs to output a non-zero value (bit 31 of led_data
|
||||
+ * indicates shifting in progress and it must return to zero
|
||||
+ * before led_data can be written or PWM mode can be set)
|
||||
+ */
|
||||
+ if (regmap_read_poll_timeout(pc->regmap, REG_SGPIO_LED_DATA, val,
|
||||
+ !(val & SGPIO_LED_DATA_SHIFT_FLAG), 10,
|
||||
+ 200 * USEC_PER_MSEC))
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ regmap_clear_bits(pc->regmap, REG_SGPIO_LED_DATA, SGPIO_LED_DATA_DATA);
|
||||
+ if (regmap_read_poll_timeout(pc->regmap, REG_SGPIO_LED_DATA, val,
|
||||
+ !(val & SGPIO_LED_DATA_SHIFT_FLAG), 10,
|
||||
+ 200 * USEC_PER_MSEC))
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ /* Set SIPO in PWM mode */
|
||||
+ regmap_set_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG,
|
||||
+ SERIAL_GPIO_FLASH_MODE);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void airoha_pwm_calc_bucket_config(struct airoha_pwm *pc, int index,
|
||||
+ u64 duty_ns, u64 period_ns)
|
||||
+{
|
||||
+ u32 period, duty, mask, val;
|
||||
+ u64 tmp;
|
||||
+
|
||||
+ tmp = duty_ns * DUTY_FULL;
|
||||
+ duty = clamp_val(div64_u64(tmp, period_ns), 0, DUTY_FULL);
|
||||
+ tmp = period_ns * 25;
|
||||
+ period = clamp_val(div64_u64(tmp, 100000000), PERIOD_MIN, PERIOD_MAX);
|
||||
+
|
||||
+ /* Configure frequency divisor */
|
||||
+ mask = WAVE_GEN_CYCLE_MASK(index % 4);
|
||||
+ val = (period << __ffs(mask)) & mask;
|
||||
+ regmap_update_bits(pc->regmap, REG_CYCLE_CFG_VALUE(index / 4),
|
||||
+ mask, val);
|
||||
+
|
||||
+ /* Configure duty cycle */
|
||||
+ duty = ((DUTY_FULL - duty) << 8) | duty;
|
||||
+ mask = GPIO_FLASH_PRD_MASK(index % 2);
|
||||
+ val = (duty << __ffs(mask)) & mask;
|
||||
+ regmap_update_bits(pc->regmap, REG_GPIO_FLASH_PRD_SET(index / 2),
|
||||
+ mask, val);
|
||||
+}
|
||||
+
|
||||
+static void airoha_pwm_config_flash_map(struct airoha_pwm *pc,
|
||||
+ unsigned int hwpwm, int index)
|
||||
+{
|
||||
+ u32 addr, mask, val;
|
||||
+
|
||||
+ if (hwpwm < PWM_NUM_GPIO) {
|
||||
+ addr = REG_GPIO_FLASH_MAP(hwpwm / 8);
|
||||
+ } else {
|
||||
+ addr = REG_SIPO_FLASH_MAP(hwpwm / 8);
|
||||
+ hwpwm -= PWM_NUM_GPIO;
|
||||
+ }
|
||||
+
|
||||
+ if (index < 0) {
|
||||
+ /*
|
||||
+ * Change of waveform takes effect immediately but
|
||||
+ * disabling has some delay so to prevent glitching
|
||||
+ * only the enable bit is touched when disabling
|
||||
+ */
|
||||
+ regmap_clear_bits(pc->regmap, addr, GPIO_FLASH_EN(hwpwm % 8));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ mask = GPIO_FLASH_SETID_MASK(hwpwm % 8);
|
||||
+ val = ((index & 7) << __ffs(mask)) & mask;
|
||||
+ regmap_update_bits(pc->regmap, addr, mask, val);
|
||||
+ regmap_set_bits(pc->regmap, addr, GPIO_FLASH_EN(hwpwm % 8));
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_config(struct airoha_pwm *pc, struct pwm_device *pwm,
|
||||
+ u64 duty_ns, u64 period_ns)
|
||||
+{
|
||||
+ int index = -1;
|
||||
+
|
||||
+ index = airoha_pwm_consume_generator(pc, duty_ns, period_ns,
|
||||
+ pwm->hwpwm);
|
||||
+ if (index < 0)
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ if (!(pc->initialized & BIT_ULL(pwm->hwpwm)) &&
|
||||
+ pwm->hwpwm >= PWM_NUM_GPIO)
|
||||
+ airoha_pwm_sipo_init(pc);
|
||||
+
|
||||
+ if (index >= 0) {
|
||||
+ airoha_pwm_calc_bucket_config(pc, index, duty_ns, period_ns);
|
||||
+ airoha_pwm_config_flash_map(pc, pwm->hwpwm, index);
|
||||
+ } else {
|
||||
+ airoha_pwm_config_flash_map(pc, pwm->hwpwm, index);
|
||||
+ airoha_pwm_release_bucket_config(pc, pwm->hwpwm);
|
||||
+ }
|
||||
+
|
||||
+ pc->initialized |= BIT_ULL(pwm->hwpwm);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void airoha_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
+{
|
||||
+ struct airoha_pwm *pc = pwmchip_get_drvdata(chip);
|
||||
+
|
||||
+ /* Disable PWM and release the waveform */
|
||||
+ airoha_pwm_config_flash_map(pc, pwm->hwpwm, -1);
|
||||
+ airoha_pwm_release_bucket_config(pc, pwm->hwpwm);
|
||||
+
|
||||
+ pc->initialized &= ~BIT_ULL(pwm->hwpwm);
|
||||
+ if (!(pc->initialized >> PWM_NUM_GPIO))
|
||||
+ regmap_clear_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG,
|
||||
+ SERIAL_GPIO_FLASH_MODE);
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
+ const struct pwm_state *state)
|
||||
+{
|
||||
+ struct airoha_pwm *pc = pwmchip_get_drvdata(chip);
|
||||
+ u64 duty = state->enabled ? state->duty_cycle : 0;
|
||||
+ u64 period = state->period;
|
||||
+
|
||||
+ /* Only normal polarity is supported */
|
||||
+ if (state->polarity == PWM_POLARITY_INVERSED)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!state->enabled) {
|
||||
+ airoha_pwm_disable(chip, pwm);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (period < PERIOD_MIN_NS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (period > PERIOD_MAX_NS)
|
||||
+ period = PERIOD_MAX_NS;
|
||||
+
|
||||
+ return airoha_pwm_config(pc, pwm, duty, period);
|
||||
+}
|
||||
+
|
||||
+static int airoha_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
+ struct pwm_state *state)
|
||||
+{
|
||||
+ struct airoha_pwm *pc = pwmchip_get_drvdata(chip);
|
||||
+ int i;
|
||||
+
|
||||
+ /* find hwpwm in waveform generator bucket */
|
||||
+ for (i = 0; i < ARRAY_SIZE(pc->bucket); i++) {
|
||||
+ if (pc->bucket[i].used & BIT_ULL(pwm->hwpwm)) {
|
||||
+ state->enabled = pc->initialized & BIT_ULL(pwm->hwpwm);
|
||||
+ state->polarity = PWM_POLARITY_NORMAL;
|
||||
+ state->period = pc->bucket[i].period_ns;
|
||||
+ state->duty_cycle = pc->bucket[i].duty_ns;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (i == ARRAY_SIZE(pc->bucket))
|
||||
+ state->enabled = false;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct pwm_ops airoha_pwm_ops = {
|
||||
+ .get_state = airoha_pwm_get_state,
|
||||
+ .apply = airoha_pwm_apply,
|
||||
+};
|
||||
+
|
||||
+static int airoha_pwm_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct airoha_pwm *pc;
|
||||
+ struct pwm_chip *chip;
|
||||
+
|
||||
+ chip = devm_pwmchip_alloc(dev, PWM_NUM_GPIO + PWM_NUM_SIPO,
|
||||
+ sizeof(*pc));
|
||||
+ if (IS_ERR(chip))
|
||||
+ return PTR_ERR(chip);
|
||||
+
|
||||
+ chip->ops = &airoha_pwm_ops;
|
||||
+ pc = pwmchip_get_drvdata(chip);
|
||||
+ pc->np = dev->of_node;
|
||||
+
|
||||
+ pc->regmap = device_node_to_regmap(dev->parent->of_node);
|
||||
+ if (IS_ERR(pc->regmap))
|
||||
+ return PTR_ERR(pc->regmap);
|
||||
+
|
||||
+ return devm_pwmchip_add(&pdev->dev, chip);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id airoha_pwm_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-pwm" },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, airoha_pwm_of_match);
|
||||
+
|
||||
+static struct platform_driver airoha_pwm_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "pwm-airoha",
|
||||
+ .of_match_table = airoha_pwm_of_match,
|
||||
+ },
|
||||
+ .probe = airoha_pwm_probe,
|
||||
+};
|
||||
+module_platform_driver(airoha_pwm_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
|
||||
+MODULE_AUTHOR("Markus Gothe <markus.gothe@genexis.eu>");
|
||||
+MODULE_AUTHOR("Benjamin Larsson <benjamin.larsson@genexis.eu>");
|
||||
+MODULE_DESCRIPTION("Airoha EN7581 PWM driver");
|
||||
+MODULE_LICENSE("GPL");
|
@ -0,0 +1,45 @@
|
||||
From 6d74b9e6d3bb07f50b22b9ea047b84a83aba185c Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Thu, 17 Oct 2024 19:26:24 +0200
|
||||
Subject: [PATCH] clk: en7523: Fix wrong BUS clock for EN7581
|
||||
|
||||
The Documentation for EN7581 had a typo and still referenced the EN7523
|
||||
BUS base source frequency. This was in conflict with a different page in
|
||||
the Documentration that state that the BUS runs at 300MHz (600MHz source with
|
||||
divisor set to 2) and the actual watchdog that tick at half the BUS
|
||||
clock (150MHz). This was verified with the watchdog by timing the
|
||||
seconds that the system takes to reboot (due too watchdog) and by
|
||||
operating on different values of the BUS divisor.
|
||||
|
||||
The correct values for source of BUS clock are 600MHz and 540MHz.
|
||||
|
||||
This was also confirmed by Airoha.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 66bc47326ce2 ("clk: en7523: Add EN7581 support")
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -87,6 +87,7 @@ static const u32 slic_base[] = { 1000000
|
||||
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
|
||||
/* EN7581 */
|
||||
static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
|
||||
+static const u32 bus7581_base[] = { 600000000, 540000000 };
|
||||
static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
|
||||
static const u32 crypto_base[] = { 540000000, 480000000 };
|
||||
|
||||
@@ -222,8 +223,8 @@ static const struct en_clk_desc en7581_b
|
||||
.base_reg = REG_BUS_CLK_DIV_SEL,
|
||||
.base_bits = 1,
|
||||
.base_shift = 8,
|
||||
- .base_values = bus_base,
|
||||
- .n_base_values = ARRAY_SIZE(bus_base),
|
||||
+ .base_values = bus7581_base,
|
||||
+ .n_base_values = ARRAY_SIZE(bus7581_base),
|
||||
|
||||
.div_bits = 3,
|
||||
.div_shift = 0,
|
@ -0,0 +1,36 @@
|
||||
From 38d2c6aafc5bbcad3ec36f6d3356b3debd40f6fd Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Wed, 16 Oct 2024 20:26:05 +0200
|
||||
Subject: [RFC PATCH v2 1/3] spinlock: extend guard with spinlock_bh variants
|
||||
|
||||
Extend guard APIs with missing raw/spinlock_bh variants.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
include/linux/spinlock.h | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
--- a/include/linux/spinlock.h
|
||||
+++ b/include/linux/spinlock.h
|
||||
@@ -515,6 +515,10 @@ DEFINE_LOCK_GUARD_1(raw_spinlock_irq, ra
|
||||
raw_spin_lock_irq(_T->lock),
|
||||
raw_spin_unlock_irq(_T->lock))
|
||||
|
||||
+DEFINE_LOCK_GUARD_1(raw_spinlock_bh, raw_spinlock_t,
|
||||
+ raw_spin_lock_bh(_T->lock),
|
||||
+ raw_spin_unlock_bh(_T->lock))
|
||||
+
|
||||
DEFINE_LOCK_GUARD_1(raw_spinlock_irqsave, raw_spinlock_t,
|
||||
raw_spin_lock_irqsave(_T->lock, _T->flags),
|
||||
raw_spin_unlock_irqrestore(_T->lock, _T->flags),
|
||||
@@ -528,6 +532,10 @@ DEFINE_LOCK_GUARD_1(spinlock_irq, spinlo
|
||||
spin_lock_irq(_T->lock),
|
||||
spin_unlock_irq(_T->lock))
|
||||
|
||||
+DEFINE_LOCK_GUARD_1(spinlock_bh, spinlock_t,
|
||||
+ spin_lock_bh(_T->lock),
|
||||
+ spin_unlock_bh(_T->lock))
|
||||
+
|
||||
DEFINE_LOCK_GUARD_1(spinlock_irqsave, spinlock_t,
|
||||
spin_lock_irqsave(_T->lock, _T->flags),
|
||||
spin_unlock_irqrestore(_T->lock, _T->flags),
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
--- a/drivers/spi/Kconfig
|
||||
+++ b/drivers/spi/Kconfig
|
||||
@@ -353,6 +353,12 @@ config SPI_DLN2
|
||||
@@ -363,6 +363,12 @@ config SPI_DLN2
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called spi-dln2.
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
depends on ARCH_EP93XX || COMPILE_TEST
|
||||
--- a/drivers/spi/Makefile
|
||||
+++ b/drivers/spi/Makefile
|
||||
@@ -50,6 +50,7 @@ obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1.
|
||||
@@ -51,6 +51,7 @@ obj-$(CONFIG_SPI_DW_BT1) += spi-dw-bt1.
|
||||
obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o
|
||||
obj-$(CONFIG_SPI_DW_PCI) += spi-dw-pci.o
|
||||
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
|
||||
|
578
target/linux/airoha/patches-6.6/900-airoha-bmt-support.patch
Normal file
578
target/linux/airoha/patches-6.6/900-airoha-bmt-support.patch
Normal file
@ -0,0 +1,578 @@
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/nand/airoha_bmt.c
|
||||
@@ -0,0 +1,575 @@
|
||||
+
|
||||
+/*
|
||||
+ * Airoha BMT algorithm
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/moduleparam.h>
|
||||
+#include "mtk_bmt.h"
|
||||
+
|
||||
+#define MAX_BMT_SIZE (250)
|
||||
+#define MAX_RAW_BAD_BLOCK_SIZE (250)
|
||||
+#define POOL_GOOD_BLOCK_PERCENT 8/100
|
||||
+#define MAX_BMT_PERCENT 1/8
|
||||
+
|
||||
+typedef struct {
|
||||
+ char signature[3];
|
||||
+ u8 version;
|
||||
+ u8 bad_count; // this field is useless
|
||||
+ u8 size;
|
||||
+ u8 checksum;
|
||||
+ u8 reseverd[13];
|
||||
+} bmt_table_header;
|
||||
+
|
||||
+typedef struct {
|
||||
+ u16 from;
|
||||
+ u16 to;
|
||||
+} bmt_entry;
|
||||
+
|
||||
+typedef struct {
|
||||
+ bmt_table_header header;
|
||||
+ bmt_entry table[MAX_BMT_SIZE];
|
||||
+} bmt_table;
|
||||
+
|
||||
+typedef struct {
|
||||
+ char signature[4];
|
||||
+ u32 checksum;
|
||||
+ u8 version;
|
||||
+ u8 size;
|
||||
+ u8 reserved[2];
|
||||
+} bbt_table_header;
|
||||
+
|
||||
+typedef struct {
|
||||
+ bbt_table_header header;
|
||||
+ u16 table[MAX_RAW_BAD_BLOCK_SIZE];
|
||||
+} bbt_table;
|
||||
+
|
||||
+bbt_table bbt;
|
||||
+bmt_table bmt;
|
||||
+
|
||||
+int bmt_index=0xffff;
|
||||
+int bbt_index=0xffff;
|
||||
+unsigned int total_blks , system_blks , bmt_blks, _to, _to2, val;
|
||||
+
|
||||
+module_param(bmt_index, int, S_IRUSR | S_IWUSR);
|
||||
+module_param(bbt_index, int, S_IRUSR | S_IWUSR);
|
||||
+module_param(total_blks, int, S_IRUSR | S_IWUSR);
|
||||
+module_param(system_blks, int, S_IRUSR | S_IWUSR);
|
||||
+module_param(bmt_blks, int, S_IRUSR | S_IWUSR);
|
||||
+module_param(_to, int, S_IRUSR | S_IWUSR);
|
||||
+module_param(_to2, int, S_IRUSR | S_IWUSR);
|
||||
+module_param(val, int, S_IRUSR | S_IWUSR);
|
||||
+
|
||||
+
|
||||
+static bool is_bad_raw(int block) {
|
||||
+ u8 fdm[4];
|
||||
+ int ret;
|
||||
+ ret = bbt_nand_read(blk_pg(block), bmtd.data_buf, bmtd.pg_size,
|
||||
+ fdm, sizeof(fdm));
|
||||
+ if (ret || fdm[0] != 0xff ){
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static bool is_bad( int block) {
|
||||
+ u8 fdm[4];
|
||||
+ int ret;
|
||||
+ ret = bbt_nand_read(blk_pg(block), bmtd.data_buf, bmtd.pg_size,
|
||||
+ fdm, sizeof(fdm));
|
||||
+ //printk("%x %x %x %x\n", fdm[0], fdm[1], fdm[2], fdm[3]);
|
||||
+ if (ret || fdm[0] != 0xff || fdm[1] != 0xff ){
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static bool is_mapped( int block) {
|
||||
+ u16 mapped_block;
|
||||
+ u8 fdm[4];
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = bbt_nand_read(blk_pg(block), bmtd.data_buf, bmtd.pg_size,
|
||||
+ fdm, sizeof(fdm));
|
||||
+ mapped_block = (fdm[2] << 8) | fdm[3];
|
||||
+ //printk("%u is mapped to %d\n", mapped_block);
|
||||
+ if (mapped_block == 0xffff)
|
||||
+ return false;
|
||||
+ else return true;
|
||||
+}
|
||||
+
|
||||
+static void mark_bad(int block) {
|
||||
+ u8 fdm[4] = {0xff, 0xff, 0xff, 0xff};
|
||||
+ struct mtd_oob_ops ops = {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = 0,
|
||||
+ .ooblen = 4,
|
||||
+ .oobbuf = fdm,
|
||||
+ .datbuf = NULL,
|
||||
+ .len = 0,
|
||||
+ };
|
||||
+ int retlen;
|
||||
+
|
||||
+ printk("marking bad :%d\n", block);
|
||||
+ if (block < system_blks)
|
||||
+ fdm[0] = 0x00;
|
||||
+ else fdm[1] = 0x00;
|
||||
+
|
||||
+ retlen = bmtd._write_oob(bmtd.mtd, block << bmtd.blk_shift , &ops) ;
|
||||
+ if (retlen < 0) {
|
||||
+ printk("marking bad block failed \n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void mark_good(int block) {
|
||||
+ u8 fdm[4] = {0xff, 0xff, 0xff, 0xff};
|
||||
+ struct mtd_oob_ops ops = {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = 0,
|
||||
+ .ooblen = 4,
|
||||
+ .oobbuf = fdm,
|
||||
+ .datbuf = NULL,
|
||||
+ .len = 0,
|
||||
+ };
|
||||
+ int retlen;
|
||||
+ retlen = bmtd._write_oob(bmtd.mtd, block << bmtd.blk_shift , &ops) ;
|
||||
+ if (retlen < 0) {
|
||||
+ printk("marking bad block failed \n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void make_mapping(u16 from , u16 to) {
|
||||
+ u8 fdm[4] = {0xff, 0xff, 0xff , 0xff};
|
||||
+ struct mtd_oob_ops ops = {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = 0,
|
||||
+ .ooblen = 4,
|
||||
+ .oobbuf = fdm,
|
||||
+ .datbuf = NULL,
|
||||
+ .len = 0,
|
||||
+ };
|
||||
+ int retlen;
|
||||
+
|
||||
+ memcpy(fdm + 2, &to, sizeof(to)); // this has to be exactly like this .
|
||||
+ retlen = bmtd._write_oob(bmtd.mtd, from << bmtd.blk_shift , &ops) ;
|
||||
+ if (retlen < 0) {
|
||||
+ printk("marking bad block failed \n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static u16 bbt_checksum(void) {
|
||||
+ int i=0;
|
||||
+ u16 checksum =0;
|
||||
+ u8 *data = (u8*) &bbt;
|
||||
+ checksum += bbt.header.version;
|
||||
+ checksum += bbt.header.size;
|
||||
+ data += sizeof(bbt_table_header);
|
||||
+ for (; i < sizeof(bbt.table); i++)
|
||||
+ checksum += data[i];
|
||||
+ return checksum;
|
||||
+}
|
||||
+
|
||||
+static bool parse_bbt(void) {
|
||||
+ int i = system_blks;
|
||||
+ u8 fdm[4];
|
||||
+ for (; i < total_blks; i++) {
|
||||
+ if( !is_bad(i)
|
||||
+ && !bbt_nand_read(blk_pg(i),(unsigned char *)&bbt, sizeof(bbt), fdm, sizeof(fdm))
|
||||
+ && (strncmp(bbt.header.signature , "RAWB", 4)==0)
|
||||
+ && (bbt.header.checksum == bbt_checksum())
|
||||
+ ) {
|
||||
+ bbt_index = i;
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static u8 bmt_checksum(void) {
|
||||
+ int i;
|
||||
+ u8 checksum = 0;
|
||||
+ u8* data = (u8*)&bmt;
|
||||
+ checksum += bmt.header.version;
|
||||
+ checksum += bmt.header.size;
|
||||
+ data += sizeof(bmt_table_header);
|
||||
+ for (i=0;i<bmt_blks*sizeof(bmt_entry);i++)
|
||||
+ checksum += data[i];
|
||||
+ return checksum;
|
||||
+}
|
||||
+
|
||||
+static bool parse_bmt(void) {
|
||||
+ int i = total_blks-1 ;
|
||||
+ u8 fdm[4];
|
||||
+ for (; i> system_blks;i--) {
|
||||
+ if ( !is_bad(i)
|
||||
+ && !bbt_nand_read(blk_pg(i),(unsigned char *)&bmt, sizeof(bmt), fdm, sizeof(fdm))
|
||||
+ && (strncmp(bmt.header.signature , "BMT", 3)==0)
|
||||
+ && (bmt.header.checksum == bmt_checksum())
|
||||
+ ) {
|
||||
+ bmt_index = i ;
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static void variable_setup(void) {
|
||||
+ unsigned int need_valid_block_num;
|
||||
+ int valid_blks = 0;
|
||||
+ int last_blk;
|
||||
+
|
||||
+ total_blks = bmtd.total_blks;
|
||||
+ last_blk = total_blks - 1;
|
||||
+ need_valid_block_num = total_blks * POOL_GOOD_BLOCK_PERCENT;
|
||||
+
|
||||
+ for (; last_blk > 0 ;last_blk--) {
|
||||
+ if (is_bad_raw(last_blk)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ valid_blks++;
|
||||
+ if (valid_blks == need_valid_block_num) {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ bmt_blks = total_blks - last_blk;
|
||||
+ system_blks = total_blks - bmt_blks;
|
||||
+ bmtd.mtd->size = (total_blks - total_blks * MAX_BMT_PERCENT) * bmtd.mtd->erasesize;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int find_available_block(bool start_from_end) {
|
||||
+ int i=system_blks,d=1;
|
||||
+ int count = 0;
|
||||
+ if (start_from_end)
|
||||
+ i=total_blks-1,d=-1;
|
||||
+ for (; count < (total_blks - system_blks); count++, i+=d) {
|
||||
+ if(bmt_index == i || bbt_index == i || is_bad(i) || is_mapped(i))
|
||||
+ continue;
|
||||
+ return i ;
|
||||
+ }
|
||||
+ //TODO: handle OOM
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static void update_bmt_bbt( void ) {
|
||||
+ int retlen = 0;
|
||||
+ struct mtd_oob_ops ops , ops1;
|
||||
+
|
||||
+ bbt.header.checksum = bbt_checksum();
|
||||
+ bmt.header.checksum = bmt_checksum();
|
||||
+
|
||||
+ if(bbt_index ==0xffff) bbt_index = find_available_block(false);
|
||||
+ if(bmt_index ==0xffff) bmt_index = find_available_block(true);
|
||||
+
|
||||
+ bbt_nand_erase(bmt_index);
|
||||
+ bbt_nand_erase(bbt_index);
|
||||
+ printk("putting back in bbt_index: %d, bmt_index: %d\n" , bbt_index, bmt_index);
|
||||
+
|
||||
+ ops = (struct mtd_oob_ops) {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = 0,
|
||||
+ .ooblen = 0,
|
||||
+ .oobbuf = NULL,
|
||||
+ .len = sizeof(bmt),
|
||||
+ .datbuf = (u8 *)&bmt,
|
||||
+ };
|
||||
+
|
||||
+retry_bmt:
|
||||
+ retlen = bmtd._write_oob(bmtd.mtd, bmt_index << bmtd.blk_shift, &ops);
|
||||
+ if (retlen) {
|
||||
+ printk("error while write");
|
||||
+ mark_bad(bmt_index);
|
||||
+ if (bmt_index > system_blks) {
|
||||
+ bmt_index--;
|
||||
+ goto retry_bmt;
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+ ops1 = (struct mtd_oob_ops) {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = 0,
|
||||
+ .ooblen = 0,
|
||||
+ .oobbuf = NULL,
|
||||
+ .len = sizeof(bbt),
|
||||
+ .datbuf = (u8 *)&bbt,
|
||||
+ };
|
||||
+
|
||||
+retry_bbt:
|
||||
+ retlen = bmtd._write_oob(bmtd.mtd, bbt_index << bmtd.blk_shift, &ops1);
|
||||
+ if (retlen) {
|
||||
+ printk("error while write");
|
||||
+ mark_bad(bbt_index);
|
||||
+ if (bbt_index < total_blks) {
|
||||
+ bbt_index++;
|
||||
+ goto retry_bbt;
|
||||
+ }
|
||||
+ return;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool is_in_bmt(int block) {
|
||||
+ int i;
|
||||
+ for (i=0;i<bmt.header.size;i++)
|
||||
+ if (bmt.table[i].from == block)
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static void reconstruct_from_oob(void) {
|
||||
+ int i;
|
||||
+
|
||||
+ memset(&bmt,0x00,sizeof(bmt));
|
||||
+ memcpy(&bmt.header.signature, "BMT",3);
|
||||
+ bmt.header.version = 1;
|
||||
+ bmt.header.size = 0;
|
||||
+ for ( i = total_blks -1 ; i >= system_blks ;i--) {
|
||||
+ unsigned short mapped_block;
|
||||
+ u8 fdm[4];
|
||||
+ int ret;
|
||||
+
|
||||
+ if (is_bad(i)) continue;
|
||||
+ ret = bbt_nand_read(blk_pg(i), bmtd.data_buf, bmtd.pg_size,
|
||||
+ fdm, sizeof(fdm));
|
||||
+ if (ret < 0)
|
||||
+ mark_bad(i);
|
||||
+
|
||||
+ memcpy(&mapped_block,fdm+2,2); // need to be this way
|
||||
+ if (mapped_block >= system_blks) continue;
|
||||
+ printk("block %X was mapped to :%X\n", mapped_block, i);
|
||||
+ bmt.table[bmt.header.size++] = (bmt_entry){.from = mapped_block , .to = i};
|
||||
+ }
|
||||
+ memset(&bbt,0x00,sizeof(bbt));
|
||||
+ memcpy(&bbt.header.signature , "RAWB", 4);
|
||||
+ bbt.header.version = 1;
|
||||
+ bbt.header.size = 0;
|
||||
+ for ( i = 0 ; i < system_blks; i++) {
|
||||
+ if (is_bad_raw(i) && !is_in_bmt(i))
|
||||
+ bbt.table[bbt.header.size++] = (u16)i;
|
||||
+ }
|
||||
+ bmt.header.checksum = bmt_checksum();
|
||||
+ bbt.header.checksum = bbt_checksum();
|
||||
+ update_bmt_bbt();
|
||||
+ printk("bbt and bmt reconstructed successfully\n");
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static bool remap_block(u16 block , u16 mapped_block, int copy_len) {
|
||||
+ bool mapped_already_in_bbt = false;
|
||||
+ bool mapped_already_in_bmt = false;
|
||||
+ bool block_already_in_bbt = false;
|
||||
+ u16 new_block = find_available_block(false);
|
||||
+ int i;
|
||||
+ // TODO check for -1
|
||||
+
|
||||
+ bbt_nand_erase(new_block);
|
||||
+ if (copy_len)
|
||||
+ bbt_nand_copy(new_block , mapped_block , copy_len);
|
||||
+
|
||||
+ for (i=0; i < bmt.header.size; i++)
|
||||
+ if (bmt.table[i].from == block) {
|
||||
+ bmt.table[i].to = new_block;
|
||||
+ mapped_already_in_bmt = true;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!mapped_already_in_bmt)
|
||||
+ bmt.table[bmt.header.size++] = (bmt_entry){ .from = block, .to = new_block};
|
||||
+
|
||||
+ for (i=0;i<bbt.header.size;i++)
|
||||
+ if (bbt.table[i] == mapped_block) {
|
||||
+ mapped_already_in_bbt = true;
|
||||
+ break;
|
||||
+ } else if (bbt.table[i] == block) {
|
||||
+ block_already_in_bbt = true;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!mapped_already_in_bbt)
|
||||
+ bbt.table[bbt.header.size++] = mapped_block;
|
||||
+ if (mapped_block != block && !block_already_in_bbt)
|
||||
+ bbt.table[bbt.header.size++] = block;
|
||||
+
|
||||
+ if (mapped_block != block) mark_bad(mapped_block);
|
||||
+ mark_bad(block);
|
||||
+ make_mapping(new_block, block);
|
||||
+
|
||||
+ update_bmt_bbt();
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static int init(struct device_node *np) {
|
||||
+ variable_setup();
|
||||
+ if (!(parse_bbt() && parse_bmt())) {
|
||||
+ reconstruct_from_oob();
|
||||
+ } else {
|
||||
+ printk("bmt/bbt found\n");
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int get_mapping_block( int block) {
|
||||
+ int i;
|
||||
+
|
||||
+ if (block > system_blks)
|
||||
+ return block;
|
||||
+ for (i = 0; i < bmt.header.size; i++)
|
||||
+ if (bmt.table[i].from == block)
|
||||
+ return bmt.table[i].to;
|
||||
+ return block;
|
||||
+}
|
||||
+
|
||||
+static void unmap_block( u16 block) { // not required
|
||||
+ printk("unmapping is called on block : %d\n", block);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int debug( void* data , u64 cmd) {
|
||||
+ int i;
|
||||
+ printk("val: %d\n", val);
|
||||
+ printk("_to: %d\n", _to);
|
||||
+ if (val == 0 ) {
|
||||
+ printk("fixing all\n");
|
||||
+ for (i=0;i<total_blks;i++) {
|
||||
+ mark_good(i);
|
||||
+ }
|
||||
+ } else if(val ==1 ) {
|
||||
+ int mapped_block;
|
||||
+ printk("remapping: %d\n", _to);
|
||||
+ mapped_block = get_mapping_block(_to);
|
||||
+ printk("before mapped to: %d\n", mapped_block);
|
||||
+ remap_block(_to , mapped_block, bmtd.mtd->erasesize);
|
||||
+ mapped_block = get_mapping_block(_to);
|
||||
+ printk("after mapped to: %d\n", mapped_block);
|
||||
+ } else if(val ==2 ) {
|
||||
+ printk("bmt table: \n");
|
||||
+ for (i = 0 ; i < bmt.header.size;i++) {
|
||||
+ printk("%d->%d\n", bmt.table[i].from , bmt.table[i].to);
|
||||
+ }
|
||||
+ printk("bbt table\n");
|
||||
+ for (i =0;i< bbt.header.size;i++) {
|
||||
+ printk("%d ", bbt.table[i]);
|
||||
+ }
|
||||
+ printk("\n");
|
||||
+ } else if(val == 3) {
|
||||
+ printk("reconstruct from oob\n");
|
||||
+ reconstruct_from_oob();
|
||||
+ } else if (val == 4) {
|
||||
+ printk("showing the oobreconstruct_from_oob of %d\n", _to);
|
||||
+ printk("%d\n",is_bad(_to));
|
||||
+ } else if (val == 5 ) {
|
||||
+ printk("trying to parse_bmt again %d\n", parse_bmt());
|
||||
+ } else if (val == 6 ) {
|
||||
+ printk("marking bad : %d", _to);
|
||||
+ mark_bad(_to);
|
||||
+ } else if ( val == 7) {
|
||||
+ struct mtd_oob_ops opsk = {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = 0,
|
||||
+ .ooblen = 0,
|
||||
+ .oobbuf = NULL,
|
||||
+ .len = sizeof(bmt),
|
||||
+ .datbuf = (u8 *)&bmt,
|
||||
+ };
|
||||
+ int retlen;
|
||||
+ printk("parse bmt from the %d block \n", _to);
|
||||
+ retlen = bmtd._read_oob(bmtd.mtd, _to << bmtd.blk_shift , &opsk);
|
||||
+
|
||||
+ printk("status : %d\n", retlen);
|
||||
+ } else if (val == 8) {
|
||||
+ u8 *data;
|
||||
+ int j;
|
||||
+ printk("dump bmt hex\n");
|
||||
+ data = (u8 *)&bmt;
|
||||
+ for (j =0;j < 50;j++) {
|
||||
+ if(j%20==0) printk("\n");
|
||||
+ printk("%X ", data[j]);
|
||||
+ }
|
||||
+ printk("bbt table\n");
|
||||
+ data = (u8 *)&bbt;
|
||||
+ for (j =0;j < 50;j++) {
|
||||
+ if(j%20==0) printk("\n");
|
||||
+ printk("%X ", data[j]);
|
||||
+ }
|
||||
+ } else if (val == 9) {
|
||||
+ struct mtd_oob_ops ops = {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = 0,
|
||||
+ .ooblen = 0,
|
||||
+ .oobbuf = NULL,
|
||||
+ .len = sizeof(bmt),
|
||||
+ .datbuf = (u8 *)&bmt,
|
||||
+ };
|
||||
+ int retlen;
|
||||
+ printk("put bmt at index\n");
|
||||
+ retlen = bmtd._write_oob(bmtd.mtd, _to << bmtd.blk_shift, &ops);
|
||||
+ bmt.header.checksum = bmt_checksum();
|
||||
+ if (retlen < 0) {
|
||||
+ printk("error while write");
|
||||
+ }
|
||||
+ } else if (val == 10) {
|
||||
+ printk("erase block %d\n", _to);
|
||||
+ bbt_nand_erase(_to);
|
||||
+ } else if (val == 11) {
|
||||
+ char *buf1, *buf2;
|
||||
+ struct mtd_oob_ops ops = {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = 0,
|
||||
+ .ooblen = 0,
|
||||
+ .oobbuf = NULL,
|
||||
+ };
|
||||
+ struct mtd_oob_ops ops1 = {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = 0,
|
||||
+ .ooblen = 0,
|
||||
+ .oobbuf = NULL,
|
||||
+ };
|
||||
+ int retlen;
|
||||
+ int j;
|
||||
+
|
||||
+ printk("tranfering content from block :%d to %d\n", _to , _to2);
|
||||
+ bbt_nand_copy(_to2, _to, bmtd.mtd->erasesize);
|
||||
+ printk("now we check size\n");
|
||||
+
|
||||
+ buf1 = (char*) kzalloc(sizeof(char) * bmtd.mtd->erasesize , GFP_KERNEL);
|
||||
+ buf2 = (char*) kzalloc(sizeof(char) * bmtd.mtd->erasesize , GFP_KERNEL);
|
||||
+
|
||||
+ ops.len = sizeof(char) * bmtd.mtd->erasesize;
|
||||
+ ops.datbuf = buf1;
|
||||
+ retlen = bmtd._read_oob(bmtd.mtd, _to << bmtd.blk_shift, &ops);
|
||||
+ if (retlen < 0) {
|
||||
+ printk("error while write\n");
|
||||
+ }
|
||||
+
|
||||
+ ops1.len = sizeof(char) * bmtd.mtd->erasesize;
|
||||
+ ops1.datbuf = buf2;
|
||||
+ retlen = bmtd._read_oob(bmtd.mtd, _to << bmtd.blk_shift, &ops1);
|
||||
+ if (retlen < 0) {
|
||||
+ printk("error while write");
|
||||
+ }
|
||||
+ for (j = 0 ; j < bmtd.mtd->erasesize ;j++) {
|
||||
+ if (j%20==0) {
|
||||
+ printk("\n");
|
||||
+ }
|
||||
+ printk("%X %X ", buf1[j], buf2[j]);
|
||||
+ }
|
||||
+ printk("\n");
|
||||
+
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+const struct mtk_bmt_ops airoha_bmt_ops = {
|
||||
+ .sig = "bmt",
|
||||
+ .sig_len = 3,
|
||||
+ .init = init,
|
||||
+ .remap_block = remap_block,
|
||||
+ .unmap_block = unmap_block,
|
||||
+ .get_mapping_block = get_mapping_block,
|
||||
+ .debug = debug,
|
||||
+};
|
@ -0,0 +1,34 @@
|
||||
--- a/drivers/mtd/nand/spi/core.c
|
||||
+++ b/drivers/mtd/nand/spi/core.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi-mem.h>
|
||||
+#include <linux/mtd/mtk_bmt.h>
|
||||
|
||||
static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val)
|
||||
{
|
||||
@@ -1346,6 +1347,7 @@ static int spinand_probe(struct spi_mem
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ mtk_bmt_attach(mtd);
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret)
|
||||
goto err_spinand_cleanup;
|
||||
@@ -1353,6 +1355,7 @@ static int spinand_probe(struct spi_mem
|
||||
return 0;
|
||||
|
||||
err_spinand_cleanup:
|
||||
+ mtk_bmt_detach(mtd);
|
||||
spinand_cleanup(spinand);
|
||||
|
||||
return ret;
|
||||
@@ -1371,6 +1374,7 @@ static int spinand_remove(struct spi_mem
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ mtk_bmt_detach(mtd);
|
||||
spinand_cleanup(spinand);
|
||||
|
||||
return 0;
|
@ -0,0 +1,170 @@
|
||||
From ca46c5834ba3a74595a93d7a491fa9c943be7c30 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Sun, 28 Jul 2024 12:15:53 +0200
|
||||
Subject: [PATCH 3/3] mtd: parser: add support for Airoha parser
|
||||
|
||||
Add support for Airoha parser based on a post parse ofpart function.
|
||||
|
||||
Airoha partition table follow normal fixed-partition implementation
|
||||
with a special implementation for the ART partition. This is always the
|
||||
past partition and is placed from the end of the flash - the partition
|
||||
size.
|
||||
|
||||
To enable this special implementation for ART partition, the relevant
|
||||
node require the "airoha,dynamic-art" compatible. With that declared,
|
||||
offset value is ignored and real offset is updated with the calculated
|
||||
value.
|
||||
|
||||
Due to usage of specific bad block management driver, the MTD size might
|
||||
vary hence the ART partition offset needs to be dynamically parsed and
|
||||
can't be declared statically.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/mtd/parsers/Kconfig | 10 ++++++
|
||||
drivers/mtd/parsers/Makefile | 1 +
|
||||
drivers/mtd/parsers/ofpart_airoha.c | 56 +++++++++++++++++++++++++++++
|
||||
drivers/mtd/parsers/ofpart_airoha.h | 18 ++++++++++
|
||||
drivers/mtd/parsers/ofpart_core.c | 6 ++++
|
||||
5 files changed, 91 insertions(+)
|
||||
create mode 100644 drivers/mtd/parsers/ofpart_airoha.c
|
||||
create mode 100644 drivers/mtd/parsers/ofpart_airoha.h
|
||||
|
||||
--- a/drivers/mtd/parsers/Kconfig
|
||||
+++ b/drivers/mtd/parsers/Kconfig
|
||||
@@ -93,6 +93,16 @@ config MTD_OF_PARTS
|
||||
flash memory node, as described in
|
||||
Documentation/devicetree/bindings/mtd/mtd.yaml.
|
||||
|
||||
+config MTD_OF_PARTS_AIROHA
|
||||
+ bool "Airoha EN7815 partitioning support"
|
||||
+ depends on MTD_OF_PARTS && (ARCH_AIROHA || COMPILE_TEST)
|
||||
+ default ARCH_AIROHA
|
||||
+ help
|
||||
+ This provides partitions parser for Airoha EN7815 family devices
|
||||
+ that can have dynamic "ART" partition at the end of the flash.
|
||||
+ It takes care of finding the correct offset and update property
|
||||
+ with it.
|
||||
+
|
||||
config MTD_OF_PARTS_BCM4908
|
||||
bool "BCM4908 partitioning support"
|
||||
depends on MTD_OF_PARTS && (ARCH_BCMBCA || COMPILE_TEST)
|
||||
--- a/drivers/mtd/parsers/Makefile
|
||||
+++ b/drivers/mtd/parsers/Makefile
|
||||
@@ -7,6 +7,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdl
|
||||
obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
|
||||
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||
ofpart-y += ofpart_core.o
|
||||
+ofpart-$(CONFIG_MTD_OF_PARTS_AIROHA) += ofpart_airoha.o
|
||||
ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o
|
||||
ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o
|
||||
obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/parsers/ofpart_airoha.c
|
||||
@@ -0,0 +1,56 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Copyright (C) 2024 Christian Marangi <ansuelsmth@gmail.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+
|
||||
+#include "ofpart_airoha.h"
|
||||
+
|
||||
+int airoha_partitions_post_parse(struct mtd_info *mtd,
|
||||
+ struct mtd_partition *parts,
|
||||
+ int nr_parts)
|
||||
+{
|
||||
+ struct mtd_partition *part;
|
||||
+ int len, a_cells, s_cells;
|
||||
+ struct device_node *pp;
|
||||
+ struct property *prop;
|
||||
+ const __be32 *reg;
|
||||
+ __be32 *new_reg;
|
||||
+
|
||||
+ part = &parts[nr_parts - 1];
|
||||
+ pp = part->of_node;
|
||||
+
|
||||
+ /* Skip if ART partition have a valid offset instead of a dynamic one */
|
||||
+ if (!of_device_is_compatible(pp, "airoha,dynamic-art"))
|
||||
+ return 0;
|
||||
+
|
||||
+ /* ART partition is set at the end of flash - size */
|
||||
+ part->offset = mtd->size - part->size;
|
||||
+
|
||||
+ /* Update the offset with the new calculate value in DT */
|
||||
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
|
||||
+ if (!prop)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* Reg already validated by fixed-partition parser */
|
||||
+ reg = of_get_property(pp, "reg", &len);
|
||||
+
|
||||
+ /* Fixed partition */
|
||||
+ a_cells = of_n_addr_cells(pp);
|
||||
+ s_cells = of_n_size_cells(pp);
|
||||
+
|
||||
+ prop->name = "reg";
|
||||
+ prop->length = (a_cells + s_cells) * sizeof(__be32);
|
||||
+ prop->value = kmemdup(reg, (a_cells + s_cells) * sizeof(__be32),
|
||||
+ GFP_KERNEL);
|
||||
+ new_reg = prop->value;
|
||||
+ memset(new_reg, 0, a_cells * sizeof(__be32));
|
||||
+ new_reg[a_cells - 1] = cpu_to_be32(part->offset);
|
||||
+ if (a_cells > 1)
|
||||
+ new_reg[0] = cpu_to_be32(part->offset >> 32);
|
||||
+ of_update_property(pp, prop);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/parsers/ofpart_airoha.h
|
||||
@@ -0,0 +1,18 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 */
|
||||
+#ifndef __OFPART_AIROHA_H
|
||||
+#define __OFPART_AIROHA_H
|
||||
+
|
||||
+#ifdef CONFIG_MTD_OF_PARTS_AIROHA
|
||||
+int airoha_partitions_post_parse(struct mtd_info *mtd,
|
||||
+ struct mtd_partition *parts,
|
||||
+ int nr_parts);
|
||||
+#else
|
||||
+static inline int airoha_partitions_post_parse(struct mtd_info *mtd,
|
||||
+ struct mtd_partition *parts,
|
||||
+ int nr_parts)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
||||
--- a/drivers/mtd/parsers/ofpart_core.c
|
||||
+++ b/drivers/mtd/parsers/ofpart_core.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
+#include "ofpart_airoha.h"
|
||||
#include "ofpart_bcm4908.h"
|
||||
#include "ofpart_linksys_ns.h"
|
||||
|
||||
@@ -23,6 +24,10 @@ struct fixed_partitions_quirks {
|
||||
int (*post_parse)(struct mtd_info *mtd, struct mtd_partition *parts, int nr_parts);
|
||||
};
|
||||
|
||||
+static struct fixed_partitions_quirks airoha_partitions_quirks = {
|
||||
+ .post_parse = airoha_partitions_post_parse,
|
||||
+};
|
||||
+
|
||||
static struct fixed_partitions_quirks bcm4908_partitions_quirks = {
|
||||
.post_parse = bcm4908_partitions_post_parse,
|
||||
};
|
||||
@@ -192,6 +197,7 @@ static const struct of_device_id parse_o
|
||||
/* Generic */
|
||||
{ .compatible = "fixed-partitions" },
|
||||
/* Customized */
|
||||
+ { .compatible = "airoha,fixed-partitions", .data = &airoha_partitions_quirks, },
|
||||
{ .compatible = "brcm,bcm4908-partitions", .data = &bcm4908_partitions_quirks, },
|
||||
{ .compatible = "linksys,ns-partitions", .data = &linksys_ns_partitions_quirks, },
|
||||
{},
|
Loading…
Reference in New Issue
Block a user