realtek: copy dts/files/patches/configs for 5.15
Copy dts/files/patches/configs from 5.10 to 5.15. Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com> [refresh with updated DGS-1210 dts files] Signed-off-by: Sander Vanheule <sander@svanheule.net>
This commit is contained in:
parent
fef55d5ffd
commit
8fb15ea52a
139 changed files with 39485 additions and 0 deletions
|
@ -0,0 +1,88 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_common.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_gpio.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "d-link,dgs-1210-10mp-f", "realtek,rtl8382-soc", "realtek,rtl838x-soc";
|
||||
|
||||
model = "D-Link DGS-1210-10MP F";
|
||||
};
|
||||
|
||||
&leds {
|
||||
link_act {
|
||||
label = "green:link_act";
|
||||
gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
poe {
|
||||
label = "green:poe";
|
||||
gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
poe_max {
|
||||
label = "yellow:poe_max";
|
||||
gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
&keys {
|
||||
mode {
|
||||
label = "mode";
|
||||
gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_LIGHTS_TOGGLE>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
INTERNAL_PHY(24)
|
||||
INTERNAL_PHY(26)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
SWITCH_SFP_PORT(24, 9, rgmii-id)
|
||||
SWITCH_SFP_PORT(26, 10, rgmii-id)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
229
target/linux/realtek/dts-5.15/rtl8380_engenius_ews2910p.dts
Normal file
229
target/linux/realtek/dts-5.15/rtl8380_engenius_ews2910p.dts
Normal file
|
@ -0,0 +1,229 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
compatible = "engenius,ews2910p", "realtek,rtl838x-soc";
|
||||
model = "EnGenius EWS2910P";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_power;
|
||||
led-failsafe = &led_fault;
|
||||
led-running = &led_power;
|
||||
led-upgrade = &led_power;
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x10000000>;
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
|
||||
led_mode {
|
||||
label = "led-mode";
|
||||
gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <BTN_0>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio1: rtl8231-gpio {
|
||||
compatible = "realtek,rtl8231-gpio";
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
indirect-access-bus-id = <0>;
|
||||
|
||||
poe_enable {
|
||||
gpio-hog;
|
||||
gpios = <1 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "poe-enable";
|
||||
};
|
||||
|
||||
sff_p9_gpios {
|
||||
gpio-hog;
|
||||
gpios = < 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>,
|
||||
< 11 GPIO_ACTIVE_HIGH>, /* los-gpio */
|
||||
< 12 GPIO_ACTIVE_LOW>; /* mod-def0-gpio */
|
||||
input;
|
||||
line-name = "sff-p9-gpios";
|
||||
};
|
||||
};
|
||||
|
||||
gpio-export {
|
||||
compatible = "gpio-export";
|
||||
|
||||
sff-p9-tx-disable {
|
||||
gpio-export,name = "sff-p9-tx-disable";
|
||||
gpio-export,output = <1>;
|
||||
gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio-restart {
|
||||
compatible = "gpio-restart";
|
||||
gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_power: led-0 {
|
||||
label = "green:power";
|
||||
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
led_lan_mode: led-1 {
|
||||
label = "green:lan-mode";
|
||||
gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
led_fault: led-2 {
|
||||
label = "amber:fault";
|
||||
gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
led_poe_max: led-3 {
|
||||
label = "amber:poe-max";
|
||||
gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
sfp1: sfp-p10 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
tx-disable-gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
|
||||
los-gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 21 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0x80000>;
|
||||
read-only;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x80000 0x10000>;
|
||||
read-only;
|
||||
};
|
||||
partition@90000 {
|
||||
label = "u-boot-env2";
|
||||
reg = <0x90000 0x10000>;
|
||||
};
|
||||
partition@a0000 {
|
||||
label = "rootfs_data";
|
||||
reg = <0xa0000 0xd60000>;
|
||||
};
|
||||
partition@e00000 {
|
||||
label = "jffs2-log";
|
||||
reg = <0xe00000 0x200000>;
|
||||
};
|
||||
partition@1000000 {
|
||||
compatible = "openwrt,uimage";
|
||||
label = "firmware";
|
||||
reg = <0x1000000 0x800000>;
|
||||
openwrt,ih-magic = <0x03802910>;
|
||||
};
|
||||
partition@1800000 {
|
||||
label = "firmware2";
|
||||
reg = <0x1800000 0x800000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
INTERNAL_PHY(24)
|
||||
INTERNAL_PHY(26)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
|
||||
SWITCH_SFP_PORT(24, 9, 1000base-x)
|
||||
|
||||
port@26 {
|
||||
reg = <26>;
|
||||
label = "lan10";
|
||||
phy-mode = "1000base-x";
|
||||
phy-handle = <&phy26>;
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp1>;
|
||||
};
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
113
target/linux/realtek/dts-5.15/rtl8380_hpe_1920-8g.dts
Normal file
113
target/linux/realtek/dts-5.15/rtl8380_hpe_1920-8g.dts
Normal file
|
@ -0,0 +1,113 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl838x_hpe_1920.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "hpe,1920-8g", "realtek,rtl838x-soc";
|
||||
model = "HPE 1920-8G (JG920A)";
|
||||
|
||||
gpio1: rtl8231-gpio {
|
||||
compatible = "realtek,rtl8231-gpio";
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
indirect-access-bus-id = <0>;
|
||||
};
|
||||
|
||||
i2c0: i2c-gpio-0 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 23 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp0: sfp-0 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
los-gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 25 GPIO_ACTIVE_LOW>;
|
||||
// tx-fault and tx-disable unconnected
|
||||
};
|
||||
|
||||
i2c1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp1: sfp-1 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
los-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 21 GPIO_ACTIVE_LOW>;
|
||||
// tx-fault and tx-disable unconnected
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
INTERNAL_PHY(24)
|
||||
INTERNAL_PHY(26)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
|
||||
port@24 {
|
||||
reg = <24>;
|
||||
label = "lan9";
|
||||
phy-mode = "1000base-x";
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp0>;
|
||||
};
|
||||
|
||||
port@26 {
|
||||
reg = <26>;
|
||||
label = "lan10";
|
||||
phy-mode = "1000base-x";
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp1>;
|
||||
};
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
85
target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit.dtsi
Normal file
85
target/linux/realtek/dts-5.15/rtl8380_netgear_gigabit.dtsi
Normal file
|
@ -0,0 +1,85 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
compatible = "realtek,rtl838x-soc";
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
keys {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_disable_sys_led>;
|
||||
|
||||
compatible = "gpio-keys";
|
||||
|
||||
mode {
|
||||
label = "reset";
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio-restart {
|
||||
compatible = "gpio-restart";
|
||||
gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
||||
open-source;
|
||||
};
|
||||
|
||||
gpio1: rtl8231-gpio {
|
||||
compatible = "realtek,rtl8231-gpio";
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
indirect-access-bus-id = <31>;
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_netgear_gigabit.dtsi"
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <50000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0000000 0x00e0000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@e0000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x00e0000 0x0010000>;
|
||||
};
|
||||
|
||||
partition@f0000 {
|
||||
label = "u-boot-env2";
|
||||
reg = <0x00f0000 0x0010000>;
|
||||
};
|
||||
|
||||
partition@100000 {
|
||||
label = "jffs";
|
||||
reg = <0x0100000 0x0100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@200000 {
|
||||
label = "jffs2";
|
||||
reg = <0x0200000 0x0100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@300000 {
|
||||
label = "firmware";
|
||||
compatible = "openwrt,uimage", "denx,uimage";
|
||||
openwrt,ih-magic = <0x4e474520>;
|
||||
reg = <0x0300000 0x0e80000>;
|
||||
};
|
||||
|
||||
partition@1180000 {
|
||||
label = "runtime2";
|
||||
reg = <0x1180000 0x0e80000>;
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_netgear_gigabit.dtsi"
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <50000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0000000 0x00e0000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@e0000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x00e0000 0x0010000>;
|
||||
};
|
||||
|
||||
partition@f0000 {
|
||||
label = "u-boot-env2";
|
||||
reg = <0x00f0000 0x0010000>;
|
||||
};
|
||||
|
||||
partition@100000 {
|
||||
label = "jffs";
|
||||
reg = <0x0100000 0x0100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@200000 {
|
||||
label = "jffs2";
|
||||
reg = <0x0200000 0x0100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@300000 {
|
||||
label = "firmware";
|
||||
compatible = "openwrt,uimage", "denx,uimage";
|
||||
openwrt,ih-magic = <0x4e474335>;
|
||||
reg = <0x0300000 0x0e80000>;
|
||||
};
|
||||
|
||||
partition@1180000 {
|
||||
label = "runtime2";
|
||||
reg = <0x1180000 0x0e80000>;
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
35
target/linux/realtek/dts-5.15/rtl8380_netgear_gs108t-v3.dts
Normal file
35
target/linux/realtek/dts-5.15/rtl8380_netgear_gs108t-v3.dts
Normal file
|
@ -0,0 +1,35 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_netgear_gigabit_1xx.dtsi"
|
||||
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/ {
|
||||
compatible = "netgear,gs108t-v3", "realtek,rtl838x-soc";
|
||||
model = "Netgear GS108T v3";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_power_green;
|
||||
led-failsafe = &led_power_amber;
|
||||
led-running = &led_power_green;
|
||||
led-upgrade = &led_power_amber;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_power_amber: led-0 {
|
||||
label = "amber:power";
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
function = LED_FUNCTION_POWER;
|
||||
gpios = <&gpio1 32 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
led_power_green: led-1 {
|
||||
label = "green:power";
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_POWER;
|
||||
gpios = <&gpio1 31 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,57 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_netgear_gigabit_1xx.dtsi"
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/ {
|
||||
compatible = "netgear,gs110tpp-v1", "realtek,rtl838x-soc";
|
||||
model = "Netgear GS110TPP v1";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_status_green;
|
||||
led-failsafe = &led_status_red;
|
||||
led-running = &led_status_green;
|
||||
led-upgrade = &led_status_blue;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_status_red: led-0 {
|
||||
label = "red:status";
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
gpios = <&gpio1 31 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
led_status_green: led-1 {
|
||||
label = "green:status";
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
gpios = <&gpio1 32 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
led_status_blue: led-2 {
|
||||
label = "blue:status";
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
gpios = <&gpio1 34 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdio {
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
SWITCH_PORT(16, 9, qsgmii)
|
||||
SWITCH_PORT(17, 10, qsgmii)
|
||||
};
|
||||
};
|
35
target/linux/realtek/dts-5.15/rtl8380_netgear_gs308t-v1.dts
Normal file
35
target/linux/realtek/dts-5.15/rtl8380_netgear_gs308t-v1.dts
Normal file
|
@ -0,0 +1,35 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_netgear_gigabit_3xx.dtsi"
|
||||
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/ {
|
||||
compatible = "netgear,gs308t-v1", "realtek,rtl838x-soc";
|
||||
model = "Netgear GS308T v1";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_power_green;
|
||||
led-failsafe = &led_power_amber;
|
||||
led-running = &led_power_green;
|
||||
led-upgrade = &led_power_amber;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_power_amber: led-0 {
|
||||
label = "amber:power";
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
function = LED_FUNCTION_POWER;
|
||||
gpios = <&gpio1 32 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
led_power_green: led-1 {
|
||||
label = "green:power";
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_POWER;
|
||||
gpios = <&gpio1 31 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
};
|
25
target/linux/realtek/dts-5.15/rtl8380_netgear_gs310tp-v1.dts
Normal file
25
target/linux/realtek/dts-5.15/rtl8380_netgear_gs310tp-v1.dts
Normal file
|
@ -0,0 +1,25 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_netgear_gigabit_3xx.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "netgear,gs310tp-v1", "realtek,rtl838x-soc";
|
||||
model = "Netgear GS310TP v1";
|
||||
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdio {
|
||||
INTERNAL_PHY(24)
|
||||
INTERNAL_PHY(26)
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
SWITCH_SFP_PORT(24, 9, rgmii-id)
|
||||
SWITCH_SFP_PORT(26, 10, rgmii-id)
|
||||
};
|
||||
};
|
|
@ -0,0 +1,133 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl83xx_panasonic_mxxeg-pn28xx0k.dtsi"
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
/ {
|
||||
compatible = "panasonic,m8eg-pn28080k", "realtek,rtl8380-soc";
|
||||
model = "Panasonic Switch-M8eG PN28080K";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_status_eco_green;
|
||||
led-failsafe = &led_status_eco_amber;
|
||||
led-running = &led_status_eco_green;
|
||||
led-upgrade = &led_status_eco_green;
|
||||
};
|
||||
|
||||
sfp0: sfp-p9 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
tx-fault-gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>;
|
||||
tx-disable-gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
|
||||
los-gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&leds {
|
||||
led_status_eco_amber: led-5 {
|
||||
label = "amber:status_eco";
|
||||
gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
function-enumerator = <1>;
|
||||
};
|
||||
|
||||
led_status_eco_green: led-6 {
|
||||
label = "green:status_eco";
|
||||
gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
function-enumerator = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_gpio_0 {
|
||||
scl-gpios = <&gpio0 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio0 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
};
|
||||
|
||||
&i2c_gpio_1 {
|
||||
scl-gpios = <&gpio0 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio0 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
||||
};
|
||||
|
||||
&gpio2 {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
||||
};
|
||||
|
||||
&i2c_switch {
|
||||
i2c0: i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
INTERNAL_PHY(24)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
|
||||
port@24 {
|
||||
reg = <24>;
|
||||
label = "lan9";
|
||||
phy-mode = "1000base-x";
|
||||
phy-handle = <&phy24>;
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp0>;
|
||||
};
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
28
target/linux/realtek/dts-5.15/rtl8380_tplink_sg2008p-v1.dts
Normal file
28
target/linux/realtek/dts-5.15/rtl8380_tplink_sg2008p-v1.dts
Normal file
|
@ -0,0 +1,28 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_tplink_sg2xxx.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "tplink,sg2008p-v1", "realtek,rtl838x-soc";
|
||||
model = "TP-Link SG2008P v1";
|
||||
};
|
||||
|
||||
&tps23861_20 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&phy24 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&phy26 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&port24 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&port26 {
|
||||
status = "disabled";
|
||||
};
|
16
target/linux/realtek/dts-5.15/rtl8380_tplink_sg2210p-v3.dts
Normal file
16
target/linux/realtek/dts-5.15/rtl8380_tplink_sg2210p-v3.dts
Normal file
|
@ -0,0 +1,16 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_tplink_sg2xxx.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "tplink,sg2210p-v3", "realtek,rtl838x-soc";
|
||||
model = "TP-Link SG2210P v3";
|
||||
};
|
||||
|
||||
&port24 {
|
||||
label = "lan-sfp2";
|
||||
};
|
||||
|
||||
&port26 {
|
||||
label = "lan-sfp1";
|
||||
};
|
183
target/linux/realtek/dts-5.15/rtl8380_tplink_sg2xxx.dtsi
Normal file
183
target/linux/realtek/dts-5.15/rtl8380_tplink_sg2xxx.dtsi
Normal file
|
@ -0,0 +1,183 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
led-boot = &led_power;
|
||||
led-failsafe = &led_power;
|
||||
led-running = &led_power;
|
||||
led-upgrade = &led_power;
|
||||
label-mac-device = ðernet0;
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x10000000>;
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio-restart {
|
||||
compatible = "gpio-restart";
|
||||
gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_power: led-0 {
|
||||
label = "green:power";
|
||||
gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
scl-gpios = <&gpio0 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio0 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
tps23861_20: tps23861@20 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x20>;
|
||||
shunt-resistor-micro-ohms = <255000>;
|
||||
};
|
||||
|
||||
tps23861_28: tps23861@28 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x28>;
|
||||
shunt-resistor-micro-ohms = <255000>;
|
||||
};
|
||||
};
|
||||
|
||||
watchdog {
|
||||
compatible = "linux,wdt-gpio";
|
||||
gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>;
|
||||
hw_algo = "toggle";
|
||||
/* SGM706 specs: typical 1.6s, but minimum 1.0s. */
|
||||
hw_margin_ms = <1000>;
|
||||
};
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
watchdog-enable {
|
||||
gpio-hog;
|
||||
gpios = <14 GPIO_ACTIVE_LOW>;
|
||||
output-low;
|
||||
line-name = "watchdog-enable";
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0xe0000>;
|
||||
read-only;
|
||||
};
|
||||
partition@e0000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0xe0000 0x20000>;
|
||||
};
|
||||
partition@100000 {
|
||||
compatible = "denx,uimage";
|
||||
label = "firmware";
|
||||
reg = <0x100000 0x1a00000>;
|
||||
};
|
||||
partition@1b00000 {
|
||||
label = "usrappfs";
|
||||
reg = <0x1b00000 0x400000>;
|
||||
};
|
||||
partition@1f00000 {
|
||||
compatible = "nvmem-cells";
|
||||
label = "para";
|
||||
reg = <0x1f00000 0x100000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
read-only;
|
||||
|
||||
factory_macaddr: macaddr@fdff4 {
|
||||
reg = <0xfdff4 0x6>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
nvmem-cells = <&factory_macaddr>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
INTERNAL_PHY(24)
|
||||
INTERNAL_PHY(26)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(15, 1, internal)
|
||||
SWITCH_PORT(14, 2, internal)
|
||||
SWITCH_PORT(13, 3, internal)
|
||||
SWITCH_PORT(12, 4, internal)
|
||||
SWITCH_PORT(11, 5, internal)
|
||||
SWITCH_PORT(10, 6, internal)
|
||||
SWITCH_PORT(9, 7, internal)
|
||||
SWITCH_PORT(8, 8, internal)
|
||||
|
||||
SWITCH_SFP_PORT(24, 9, 1000base-x)
|
||||
SWITCH_SFP_PORT(26, 10, 1000base-x)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
75
target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900-10hp.dts
Normal file
75
target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900-10hp.dts
Normal file
|
@ -0,0 +1,75 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_zyxel_gs1900.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,gs1900-10hp", "realtek,rtl838x-soc";
|
||||
model = "ZyXEL GS1900-10HP Switch";
|
||||
|
||||
/* i2c of the left SFP cage: port 9 */
|
||||
i2c0: i2c-gpio-0 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp0: sfp-p9 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
los-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 26 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
/* i2c of the right SFP cage: port 10 */
|
||||
i2c1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp1: sfp-p10 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
los-gpio = <&gpio1 33 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 32 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdio {
|
||||
INTERNAL_PHY(24)
|
||||
INTERNAL_PHY(26)
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
port@24 {
|
||||
reg = <24>;
|
||||
label = "lan9";
|
||||
phy-mode = "1000base-x";
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp0>;
|
||||
};
|
||||
|
||||
port@26 {
|
||||
reg = <26>;
|
||||
label = "lan10";
|
||||
phy-mode = "1000base-x";
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp1>;
|
||||
};
|
||||
};
|
||||
};
|
12
target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900-8.dts
Normal file
12
target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900-8.dts
Normal file
|
@ -0,0 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_zyxel_gs1900.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,gs1900-8", "realtek,rtl838x-soc";
|
||||
model = "ZyXEL GS1900-8 Switch";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
/delete-node/ poe_enable;
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_zyxel_gs1900.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,gs1900-8hp-v1", "realtek,rtl838x-soc";
|
||||
model = "ZyXEL GS1900-8HP v1 Switch";
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_zyxel_gs1900.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,gs1900-8hp-v2", "realtek,rtl838x-soc";
|
||||
model = "ZyXEL GS1900-8HP v2 Switch";
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
149
target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900.dtsi
Normal file
149
target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900.dtsi
Normal file
|
@ -0,0 +1,149 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
led-boot = &led_sys;
|
||||
led-failsafe = &led_sys;
|
||||
led-running = &led_sys;
|
||||
led-upgrade = &led_sys;
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys-polled";
|
||||
poll-interval = <20>;
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_disable_sys_led>;
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_sys: sys {
|
||||
label = "green:sys";
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio1: rtl8231-gpio {
|
||||
compatible = "realtek,rtl8231-gpio";
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
indirect-access-bus-id = <0>;
|
||||
|
||||
poe_enable {
|
||||
gpio-hog;
|
||||
gpios = <13 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
partition@40000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x40000 0x10000>;
|
||||
read-only;
|
||||
};
|
||||
partition@50000 {
|
||||
label = "u-boot-env2";
|
||||
reg = <0x50000 0x10000>;
|
||||
};
|
||||
partition@60000 {
|
||||
label = "jffs";
|
||||
reg = <0x60000 0x100000>;
|
||||
};
|
||||
partition@160000 {
|
||||
label = "jffs2";
|
||||
reg = <0x160000 0x100000>;
|
||||
};
|
||||
partition@b260000 {
|
||||
label = "firmware";
|
||||
reg = <0x260000 0x6d0000>;
|
||||
compatible = "openwrt,uimage", "denx,uimage";
|
||||
openwrt,ih-magic = <0x83800000>;
|
||||
};
|
||||
partition@930000 {
|
||||
label = "runtime2";
|
||||
reg = <0x930000 0x6d0000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
141
target/linux/realtek/dts-5.15/rtl8382_allnet_all-sg8208m.dts
Normal file
141
target/linux/realtek/dts-5.15/rtl8382_allnet_all-sg8208m.dts
Normal file
|
@ -0,0 +1,141 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
compatible = "allnet,all-sg8208m", "realtek,rtl838x-soc";
|
||||
model = "ALLNET ALL-SG8208M";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_sys;
|
||||
led-failsafe = &led_sys;
|
||||
led-running = &led_sys;
|
||||
led-upgrade = &led_sys;
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys-polled";
|
||||
poll-interval = <20>;
|
||||
|
||||
/* is this pin 3 on the external RTL8231 (&gpio1)? */
|
||||
/*reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio0 67 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};*/
|
||||
};
|
||||
|
||||
leds {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_disable_sys_led>;
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_sys: sys {
|
||||
label = "green:sys";
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
// GPIO 25: power on/off all port leds
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0x80000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@80000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x80000 0x10000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@90000 {
|
||||
label = "u-boot-env2";
|
||||
reg = <0x90000 0x10000>;
|
||||
};
|
||||
|
||||
partition@a0000 {
|
||||
label = "jffs";
|
||||
reg = <0xa0000 0x100000>;
|
||||
};
|
||||
|
||||
partition@1a0000 {
|
||||
label = "jffs2";
|
||||
reg = <0x1a0000 0x100000>;
|
||||
};
|
||||
|
||||
partition@2a0000 {
|
||||
label = "firmware";
|
||||
reg = <0x2a0000 0xd60000>;
|
||||
compatible = "openwrt,uimage", "denx,uimage";
|
||||
openwrt,ih-magic = <0x00000006>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
102
target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-10p.dts
Normal file
102
target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-10p.dts
Normal file
|
@ -0,0 +1,102 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_common.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "d-link,dgs-1210-10p", "realtek,rtl838x-soc";
|
||||
model = "D-Link DGS-1210-10P";
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys-polled";
|
||||
poll-interval = <20>;
|
||||
|
||||
mode {
|
||||
label = "mode";
|
||||
gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_LIGHTS_TOGGLE>;
|
||||
};
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio1 33 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
link_act {
|
||||
label = "green:link_act";
|
||||
gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
poe {
|
||||
label = "green:poe";
|
||||
gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
poe_max {
|
||||
label = "yellow:poe_max";
|
||||
gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio1: rtl8231-gpio {
|
||||
compatible = "realtek,rtl8231-gpio";
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
indirect-access-bus-id = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
INTERNAL_PHY(24)
|
||||
INTERNAL_PHY(26)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
SWITCH_SFP_PORT(24, 9, rgmii-id)
|
||||
SWITCH_SFP_PORT(26, 10, rgmii-id)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
81
target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-16.dts
Normal file
81
target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-16.dts
Normal file
|
@ -0,0 +1,81 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_common.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "d-link,dgs-1210-16", "realtek,rtl838x-soc";
|
||||
model = "D-Link DGS-1210-16";
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
EXTERNAL_SFP_PHY(24)
|
||||
EXTERNAL_SFP_PHY(25)
|
||||
EXTERNAL_SFP_PHY(26)
|
||||
EXTERNAL_SFP_PHY(27)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, internal)
|
||||
SWITCH_PORT(9, 10, internal)
|
||||
SWITCH_PORT(10, 11, internal)
|
||||
SWITCH_PORT(11, 12, internal)
|
||||
SWITCH_PORT(12, 13, internal)
|
||||
SWITCH_PORT(13, 14, internal)
|
||||
SWITCH_PORT(14, 15, internal)
|
||||
SWITCH_PORT(15, 16, internal)
|
||||
|
||||
SWITCH_PORT(24, 17, qsgmii)
|
||||
SWITCH_PORT(25, 18, qsgmii)
|
||||
SWITCH_PORT(26, 19, qsgmii)
|
||||
SWITCH_PORT(27, 20, qsgmii)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
82
target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-20.dts
Normal file
82
target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-20.dts
Normal file
|
@ -0,0 +1,82 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_common.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_gpio.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "d-link,dgs-1210-20", "realtek,rtl838x-soc";
|
||||
model = "D-Link DGS-1210-20";
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
EXTERNAL_SFP_PHY(24)
|
||||
EXTERNAL_SFP_PHY(25)
|
||||
EXTERNAL_SFP_PHY(26)
|
||||
EXTERNAL_SFP_PHY(27)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, internal)
|
||||
SWITCH_PORT(9, 10, internal)
|
||||
SWITCH_PORT(10, 11, internal)
|
||||
SWITCH_PORT(11, 12, internal)
|
||||
SWITCH_PORT(12, 13, internal)
|
||||
SWITCH_PORT(13, 14, internal)
|
||||
SWITCH_PORT(14, 15, internal)
|
||||
SWITCH_PORT(15, 16, internal)
|
||||
|
||||
SWITCH_PORT(24, 17, qsgmii)
|
||||
SWITCH_PORT(25, 18, qsgmii)
|
||||
SWITCH_PORT(26, 19, qsgmii)
|
||||
SWITCH_PORT(27, 20, qsgmii)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
11
target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-28.dts
Normal file
11
target/linux/realtek/dts-5.15/rtl8382_d-link_dgs-1210-28.dts
Normal file
|
@ -0,0 +1,11 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_common.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_gpio.dtsi"
|
||||
#include "rtl8382_d-link_dgs-1210-28_common.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "d-link,dgs-1210-28", "realtek,rtl838x-soc";
|
||||
model = "D-Link DGS-1210-28";
|
||||
};
|
|
@ -0,0 +1,91 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
|
||||
EXTERNAL_SFP_PHY(24)
|
||||
EXTERNAL_SFP_PHY(25)
|
||||
EXTERNAL_SFP_PHY(26)
|
||||
EXTERNAL_SFP_PHY(27)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, internal)
|
||||
SWITCH_PORT(9, 10, internal)
|
||||
SWITCH_PORT(10, 11, internal)
|
||||
SWITCH_PORT(11, 12, internal)
|
||||
SWITCH_PORT(12, 13, internal)
|
||||
SWITCH_PORT(13, 14, internal)
|
||||
SWITCH_PORT(14, 15, internal)
|
||||
SWITCH_PORT(15, 16, internal)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
SWITCH_PORT(24, 25, qsgmii)
|
||||
SWITCH_PORT(25, 26, qsgmii)
|
||||
SWITCH_PORT(26, 27, qsgmii)
|
||||
SWITCH_PORT(27, 28, qsgmii)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,40 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_common.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_gpio.dtsi"
|
||||
#include "rtl8382_d-link_dgs-1210-28_common.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "d-link,dgs-1210-28mp-f", "realtek,rtl8382-soc", "realtek,rtl838x-soc";
|
||||
model = "D-Link DGS-1210-28MP F";
|
||||
};
|
||||
|
||||
&leds {
|
||||
link_act {
|
||||
label = "green:link_act";
|
||||
gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
poe {
|
||||
label = "green:poe";
|
||||
gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
poe_max {
|
||||
label = "yellow:poe_max";
|
||||
gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
&keys {
|
||||
mode {
|
||||
label = "mode";
|
||||
gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <BTN_0>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
48
target/linux/realtek/dts-5.15/rtl8382_hpe_1920-16g.dts
Normal file
48
target/linux/realtek/dts-5.15/rtl8382_hpe_1920-16g.dts
Normal file
|
@ -0,0 +1,48 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl8382_hpe_1920.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "hpe,1920-16g", "realtek,rtl838x-soc";
|
||||
model = "HPE 1920-16G (JG923A)";
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
|
||||
SWITCH_PORT(16, 9, qsgmii)
|
||||
SWITCH_PORT(17, 10, qsgmii)
|
||||
SWITCH_PORT(18, 11, qsgmii)
|
||||
SWITCH_PORT(19, 12, qsgmii)
|
||||
SWITCH_PORT(20, 13, qsgmii)
|
||||
SWITCH_PORT(21, 14, qsgmii)
|
||||
SWITCH_PORT(22, 15, qsgmii)
|
||||
SWITCH_PORT(23, 16, qsgmii)
|
||||
|
||||
SWITCH_PORT(24, 17, qsgmii)
|
||||
SWITCH_PORT(25, 18, qsgmii)
|
||||
SWITCH_PORT(26, 19, qsgmii)
|
||||
SWITCH_PORT(27, 20, qsgmii)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
68
target/linux/realtek/dts-5.15/rtl8382_hpe_1920-24g.dts
Normal file
68
target/linux/realtek/dts-5.15/rtl8382_hpe_1920-24g.dts
Normal file
|
@ -0,0 +1,68 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl8382_hpe_1920.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "hpe,1920-24g", "realtek,rtl838x-soc";
|
||||
model = "HPE 1920-24G (JG924A)";
|
||||
};
|
||||
|
||||
&mdio {
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, internal)
|
||||
SWITCH_PORT(9, 10, internal)
|
||||
SWITCH_PORT(10, 11, internal)
|
||||
SWITCH_PORT(11, 12, internal)
|
||||
SWITCH_PORT(12, 13, internal)
|
||||
SWITCH_PORT(13, 14, internal)
|
||||
SWITCH_PORT(14, 15, internal)
|
||||
SWITCH_PORT(15, 16, internal)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
SWITCH_PORT(24, 25, qsgmii)
|
||||
SWITCH_PORT(25, 26, qsgmii)
|
||||
SWITCH_PORT(26, 27, qsgmii)
|
||||
SWITCH_PORT(27, 28, qsgmii)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
117
target/linux/realtek/dts-5.15/rtl8382_hpe_1920.dtsi
Normal file
117
target/linux/realtek/dts-5.15/rtl8382_hpe_1920.dtsi
Normal file
|
@ -0,0 +1,117 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl838x_hpe_1920.dtsi"
|
||||
|
||||
/ {
|
||||
gpio1: rtl8231-gpio {
|
||||
compatible = "realtek,rtl8231-gpio";
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
indirect-access-bus-id = <0>;
|
||||
};
|
||||
|
||||
i2c0: i2c-gpio-0 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp0: sfp-0 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
los-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 21 GPIO_ACTIVE_LOW>;
|
||||
// tx-fault unconnected
|
||||
// tx-disable connected to RTL8214FC
|
||||
};
|
||||
|
||||
i2c1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 23 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp1: sfp-1 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
los-gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 25 GPIO_ACTIVE_LOW>;
|
||||
// tx-fault unconnected
|
||||
// tx-disable connected to RTL8214FC
|
||||
};
|
||||
|
||||
i2c2: i2c-gpio-2 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 27 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp2: sfp-2 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c2>;
|
||||
los-gpio = <&gpio1 30 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 29 GPIO_ACTIVE_LOW>;
|
||||
// tx-fault unconnected
|
||||
// tx-disable connected to RTL8214FC
|
||||
};
|
||||
|
||||
i2c3: i2c-gpio-3 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 32 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp3: sfp-3 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c3>;
|
||||
los-gpio = <&gpio1 34 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 33 GPIO_ACTIVE_LOW>;
|
||||
// tx-fault unconnected
|
||||
// tx-disable connected to RTL8214FC
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
|
||||
EXTERNAL_SFP_PHY_FULL(24, 0)
|
||||
EXTERNAL_SFP_PHY_FULL(25, 1)
|
||||
EXTERNAL_SFP_PHY_FULL(26, 2)
|
||||
EXTERNAL_SFP_PHY_FULL(27, 3)
|
||||
};
|
||||
};
|
158
target/linux/realtek/dts-5.15/rtl8382_inaba_aml2-17gp.dts
Normal file
158
target/linux/realtek/dts-5.15/rtl8382_inaba_aml2-17gp.dts
Normal file
|
@ -0,0 +1,158 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
compatible = "inaba,aml2-17gp", "realtek,rtl838x-soc";
|
||||
model = "INABA Abaniact AML2-17GP";
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
keys {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_disable_sys_led>;
|
||||
|
||||
compatible = "gpio-keys";
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0x80000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@80000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x80000 0x10000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@90000 {
|
||||
label = "u-boot-env2";
|
||||
reg = <0x90000 0x10000>;
|
||||
};
|
||||
|
||||
partition@a0000 {
|
||||
label = "jffs2_cfg";
|
||||
reg = <0xa0000 0x400000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@4a0000 {
|
||||
label = "jffs2_log";
|
||||
reg = <0x4a0000 0x100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@5a0000 {
|
||||
compatible = "openwrt,uimage", "denx,uimage";
|
||||
label = "firmware";
|
||||
reg = <0x5a0000 0xd30000>;
|
||||
openwrt,ih-magic = <0x83800000>;
|
||||
};
|
||||
|
||||
partition@12d0000 {
|
||||
label = "runtime2";
|
||||
reg = <0x12d0000 0xd30000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
|
||||
EXTERNAL_PHY(24)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
|
||||
SWITCH_PORT(16, 9, qsgmii)
|
||||
SWITCH_PORT(17, 10, qsgmii)
|
||||
SWITCH_PORT(18, 11, qsgmii)
|
||||
SWITCH_PORT(19, 12, qsgmii)
|
||||
SWITCH_PORT(20, 13, qsgmii)
|
||||
SWITCH_PORT(21, 14, qsgmii)
|
||||
SWITCH_PORT(22, 15, qsgmii)
|
||||
SWITCH_PORT(23, 16, qsgmii)
|
||||
|
||||
port@24 {
|
||||
reg = <24>;
|
||||
label = "wan";
|
||||
phy-handle = <&phy24>;
|
||||
phy-mode = "qsgmii";
|
||||
};
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
197
target/linux/realtek/dts-5.15/rtl8382_iodata_bsh-g24mb.dts
Normal file
197
target/linux/realtek/dts-5.15/rtl8382_iodata_bsh-g24mb.dts
Normal file
|
@ -0,0 +1,197 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/ {
|
||||
compatible = "iodata,bsh-g24mb", "realtek,rtl838x-soc";
|
||||
model = "I-O DATA BSH-G24MB";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_sys_loop;
|
||||
led-failsafe = &led_sys_loop;
|
||||
led-upgrade = &led_sys_loop;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,115200";
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
leds {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_disable_sys_led>;
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_sys_loop: led {
|
||||
label = "red:sys_loop";
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
};
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys-polled";
|
||||
poll-interval = <20>;
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio1: rtl8231-gpio {
|
||||
compatible = "realtek,rtl8231-gpio";
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
indirect-access-bus-id = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0x80000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@80000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x80000 0x10000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@90000 {
|
||||
label = "u-boot-env2";
|
||||
reg = <0x90000 0x10000>;
|
||||
};
|
||||
|
||||
partition@a0000 {
|
||||
label = "jffs2_cfg";
|
||||
reg = <0xa0000 0x100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@1a0000 {
|
||||
label = "jffs2_log";
|
||||
reg = <0x1a0000 0x100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
/*
|
||||
* use 2x OS partitions in OpenWrt
|
||||
*
|
||||
* 0x2A0000-0x94FFFF: RUNTIME
|
||||
* 0x950000-0xFFFFFF: RUNTIME2 (not used in stock)
|
||||
*/
|
||||
partition@2a0000 {
|
||||
compatible = "openwrt,uimage", "denx,uimage";
|
||||
label = "firmware";
|
||||
reg = <0x2a0000 0xd60000>;
|
||||
openwrt,ih-magic = <0x83800013>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, internal)
|
||||
SWITCH_PORT(9, 10, internal)
|
||||
SWITCH_PORT(10, 11, internal)
|
||||
SWITCH_PORT(11, 12, internal)
|
||||
SWITCH_PORT(12, 13, internal)
|
||||
SWITCH_PORT(13, 14, internal)
|
||||
SWITCH_PORT(14, 15, internal)
|
||||
SWITCH_PORT(15, 16, internal)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,171 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl83xx_panasonic_mxxeg-pn28xx0k.dtsi"
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
/ {
|
||||
compatible = "panasonic,m16eg-pn28160k", "realtek,rtl8382-soc";
|
||||
model = "Panasonic Switch-M16eG PN28160K";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_status_eco_green;
|
||||
led-failsafe = &led_status_eco_amber;
|
||||
led-running = &led_status_eco_green;
|
||||
led-upgrade = &led_status_eco_green;
|
||||
};
|
||||
|
||||
/*
|
||||
* sfp0/1 are "combo" port with each TP port (23/24), and they are
|
||||
* connected to the RTL8218FB. Currently, there is no support for
|
||||
* the chip and only TP ports work by the RTL8218D support.
|
||||
*/
|
||||
sfp0: sfp-p23 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
tx-fault-gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>;
|
||||
tx-disable-gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
|
||||
los-gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
sfp1: sfp-p24 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
tx-fault-gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
|
||||
tx-disable-gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 6 GPIO_ACTIVE_LOW>;
|
||||
los-gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&leds {
|
||||
led_status_eco_amber: led-5 {
|
||||
label = "amber:status_eco";
|
||||
gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
function-enumerator = <1>;
|
||||
};
|
||||
|
||||
led_status_eco_green: led-6 {
|
||||
label = "green:status_eco";
|
||||
gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
function-enumerator = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_gpio_0 {
|
||||
scl-gpios = <&gpio0 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio0 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
};
|
||||
|
||||
&i2c_gpio_1 {
|
||||
scl-gpios = <&gpio0 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio0 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
};
|
||||
|
||||
&gpio2 {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
/*
|
||||
* GPIO12 (IO1_4): RTL8218FB
|
||||
*
|
||||
* This GPIO pin should be specified as "reset-gpio" in mdio node, but
|
||||
* RTL8218FB phy won't be configured on RTL8218D support in the current
|
||||
* phy driver. So, ethernet ports on the phy will be broken after hard-
|
||||
* resetting.
|
||||
* (RTL8218FB phy will be detected as RTL8218D by the phy driver)
|
||||
* At the moment, configure this GPIO pin as gpio-hog to avoid breaking
|
||||
* by resetting.
|
||||
*/
|
||||
ext_switch_reset {
|
||||
gpio-hog;
|
||||
gpios = <12 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "ext-switch-reset";
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_switch {
|
||||
i2c0: i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
i2c1: i2c@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
/* RTL8218FB */
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(8, 1, internal)
|
||||
SWITCH_PORT(9, 2, internal)
|
||||
SWITCH_PORT(10, 3, internal)
|
||||
SWITCH_PORT(11, 4, internal)
|
||||
SWITCH_PORT(12, 5, internal)
|
||||
SWITCH_PORT(13, 6, internal)
|
||||
SWITCH_PORT(14, 7, internal)
|
||||
SWITCH_PORT(15, 8, internal)
|
||||
|
||||
SWITCH_PORT(16, 9, qsgmii)
|
||||
SWITCH_PORT(17, 10, qsgmii)
|
||||
SWITCH_PORT(18, 11, qsgmii)
|
||||
SWITCH_PORT(19, 12, qsgmii)
|
||||
SWITCH_PORT(20, 13, qsgmii)
|
||||
SWITCH_PORT(21, 14, qsgmii)
|
||||
SWITCH_PORT(22, 15, qsgmii)
|
||||
SWITCH_PORT(23, 16, qsgmii)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,190 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl838x.dtsi"
|
||||
#include "rtl83xx_panasonic_mxxeg-pn28xx0k.dtsi"
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
/ {
|
||||
compatible = "panasonic,m24eg-pn28240k", "realtek,rtl8382-soc";
|
||||
model = "Panasonic Switch-M24eG PN28240K";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_status_eco_green;
|
||||
led-failsafe = &led_status_eco_amber;
|
||||
led-running = &led_status_eco_green;
|
||||
led-upgrade = &led_status_eco_green;
|
||||
};
|
||||
|
||||
/*
|
||||
* sfp0/1 are "combo" port with each TP port (23/24), and they are
|
||||
* connected to the RTL8218FB. Currently, there is no support for
|
||||
* the chip and only TP ports work by the RTL8218D support.
|
||||
*/
|
||||
sfp0: sfp-p23 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
tx-fault-gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>;
|
||||
tx-disable-gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
|
||||
los-gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
sfp1: sfp-p24 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
tx-fault-gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
|
||||
tx-disable-gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 6 GPIO_ACTIVE_LOW>;
|
||||
los-gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&leds {
|
||||
led_status_eco_amber: led-5 {
|
||||
label = "amber:status_eco";
|
||||
gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
function-enumerator = <1>;
|
||||
};
|
||||
|
||||
led_status_eco_green: led-6 {
|
||||
label = "green:status_eco";
|
||||
gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
function-enumerator = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_gpio_0 {
|
||||
scl-gpios = <&gpio0 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio0 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
};
|
||||
|
||||
&i2c_gpio_1 {
|
||||
scl-gpios = <&gpio0 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio0 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
};
|
||||
|
||||
&gpio2 {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
/*
|
||||
* GPIO12 (IO1_4): RTL8218B + RTL8218FB
|
||||
*
|
||||
* This GPIO pin should be specified as "reset-gpio" in mdio node,
|
||||
* but the current configuration of RTL8218B phy in the phy driver
|
||||
* seems to be incomplete and RTL8218FB phy won't be configured on
|
||||
* RTL8218D support. So, ethernet ports on these phys will be broken
|
||||
* after hard-resetting.
|
||||
* (RTL8218FB phy will be detected as RTL8218D by the phy driver)
|
||||
* At the moment, configure this GPIO pin as gpio-hog to avoid breaking
|
||||
* by resetting.
|
||||
*/
|
||||
ext_switch_reset {
|
||||
gpio-hog;
|
||||
gpios = <12 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "ext-switch-reset";
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_switch {
|
||||
i2c0: i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
i2c1: i2c@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
INTERNAL_PHY(8)
|
||||
INTERNAL_PHY(9)
|
||||
INTERNAL_PHY(10)
|
||||
INTERNAL_PHY(11)
|
||||
INTERNAL_PHY(12)
|
||||
INTERNAL_PHY(13)
|
||||
INTERNAL_PHY(14)
|
||||
INTERNAL_PHY(15)
|
||||
|
||||
/* RTL8218FB */
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, internal)
|
||||
SWITCH_PORT(9, 10, internal)
|
||||
SWITCH_PORT(10, 11, internal)
|
||||
SWITCH_PORT(11, 12, internal)
|
||||
SWITCH_PORT(12, 13, internal)
|
||||
SWITCH_PORT(13, 14, internal)
|
||||
SWITCH_PORT(14, 15, internal)
|
||||
SWITCH_PORT(15, 16, internal)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
36
target/linux/realtek/dts-5.15/rtl8382_zyxel_gs1900-16.dts
Normal file
36
target/linux/realtek/dts-5.15/rtl8382_zyxel_gs1900-16.dts
Normal file
|
@ -0,0 +1,36 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_zyxel_gs1900.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,gs1900-16", "realtek,rtl838x-soc";
|
||||
model = "ZyXEL GS1900-16";
|
||||
};
|
||||
|
||||
&mdio {
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
SWITCH_PORT(16, 9, qsgmii)
|
||||
SWITCH_PORT(17, 10, qsgmii)
|
||||
SWITCH_PORT(18, 11, qsgmii)
|
||||
SWITCH_PORT(19, 12, qsgmii)
|
||||
SWITCH_PORT(20, 13, qsgmii)
|
||||
SWITCH_PORT(21, 14, qsgmii)
|
||||
SWITCH_PORT(22, 15, qsgmii)
|
||||
SWITCH_PORT(23, 16, qsgmii)
|
||||
};
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
/delete-node/ poe_enable;
|
||||
};
|
128
target/linux/realtek/dts-5.15/rtl8382_zyxel_gs1900-24-v1.dts
Normal file
128
target/linux/realtek/dts-5.15/rtl8382_zyxel_gs1900-24-v1.dts
Normal file
|
@ -0,0 +1,128 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_zyxel_gs1900.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,gs1900-24-v1", "realtek,rtl838x-soc";
|
||||
model = "ZyXEL GS1900-24 v1";
|
||||
|
||||
memory@0 {
|
||||
reg = <0x0 0x4000000>;
|
||||
};
|
||||
|
||||
/* i2c of the left SFP cage: port 25 */
|
||||
i2c0: i2c-gpio-0 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp0: sfp-p25 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
los-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 26 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
/* i2c of the right SFP cage: port 26 */
|
||||
i2c1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp1: sfp-p26 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
los-gpio = <&gpio1 33 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 32 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdio {
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
|
||||
INTERNAL_PHY(24)
|
||||
INTERNAL_PHY(26)
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, internal)
|
||||
SWITCH_PORT(9, 10, internal)
|
||||
SWITCH_PORT(10, 11, internal)
|
||||
SWITCH_PORT(11, 12, internal)
|
||||
SWITCH_PORT(12, 13, internal)
|
||||
SWITCH_PORT(13, 14, internal)
|
||||
SWITCH_PORT(14, 15, internal)
|
||||
SWITCH_PORT(15, 16, internal)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
port@24 {
|
||||
reg = <24>;
|
||||
label = "lan25";
|
||||
phy-mode = "1000base-x";
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp0>;
|
||||
};
|
||||
|
||||
port@26 {
|
||||
reg = <26>;
|
||||
label = "lan26";
|
||||
phy-mode = "1000base-x";
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
/delete-node/ poe_enable;
|
||||
};
|
63
target/linux/realtek/dts-5.15/rtl8382_zyxel_gs1900-24e.dts
Normal file
63
target/linux/realtek/dts-5.15/rtl8382_zyxel_gs1900-24e.dts
Normal file
|
@ -0,0 +1,63 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_zyxel_gs1900.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,gs1900-24e", "realtek,rtl838x-soc";
|
||||
model = "ZyXEL GS1900-24E";
|
||||
};
|
||||
|
||||
&mdio {
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
SWITCH_PORT(1, 1, qsgmii)
|
||||
SWITCH_PORT(0, 2, qsgmii)
|
||||
SWITCH_PORT(3, 3, qsgmii)
|
||||
SWITCH_PORT(2, 4, qsgmii)
|
||||
SWITCH_PORT(5, 5, qsgmii)
|
||||
SWITCH_PORT(4, 6, qsgmii)
|
||||
SWITCH_PORT(7, 7, qsgmii)
|
||||
SWITCH_PORT(6, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(9, 9, internal)
|
||||
SWITCH_PORT(8, 10, internal)
|
||||
SWITCH_PORT(11, 11, internal)
|
||||
SWITCH_PORT(10, 12, internal)
|
||||
SWITCH_PORT(13, 13, internal)
|
||||
SWITCH_PORT(12, 14, internal)
|
||||
SWITCH_PORT(15, 15, internal)
|
||||
SWITCH_PORT(14, 16, internal)
|
||||
|
||||
SWITCH_PORT(17, 17, qsgmii)
|
||||
SWITCH_PORT(16, 18, qsgmii)
|
||||
SWITCH_PORT(19, 19, qsgmii)
|
||||
SWITCH_PORT(18, 20, qsgmii)
|
||||
SWITCH_PORT(21, 21, qsgmii)
|
||||
SWITCH_PORT(20, 22, qsgmii)
|
||||
SWITCH_PORT(23, 23, qsgmii)
|
||||
SWITCH_PORT(22, 24, qsgmii)
|
||||
};
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
/delete-node/ poe_enable;
|
||||
};
|
125
target/linux/realtek/dts-5.15/rtl8382_zyxel_gs1900-24hp-v1.dts
Normal file
125
target/linux/realtek/dts-5.15/rtl8382_zyxel_gs1900-24hp-v1.dts
Normal file
|
@ -0,0 +1,125 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_zyxel_gs1900.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,gs1900-24hp-v1", "realtek,rtl838x-soc";
|
||||
model = "ZyXEL GS1900-24HP v1";
|
||||
|
||||
memory@0 {
|
||||
reg = <0x0 0x4000000>;
|
||||
};
|
||||
|
||||
/* i2c of the left SFP cage: port 25 */
|
||||
i2c0: i2c-gpio-0 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp0: sfp-p25 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
los-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 26 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
/* i2c of the right SFP cage: port 26 */
|
||||
i2c1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp1: sfp-p26 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
los-gpio = <&gpio1 33 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 32 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdio {
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
|
||||
INTERNAL_PHY(24)
|
||||
INTERNAL_PHY(26)
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, internal)
|
||||
SWITCH_PORT(9, 10, internal)
|
||||
SWITCH_PORT(10, 11, internal)
|
||||
SWITCH_PORT(11, 12, internal)
|
||||
SWITCH_PORT(12, 13, internal)
|
||||
SWITCH_PORT(13, 14, internal)
|
||||
SWITCH_PORT(14, 15, internal)
|
||||
SWITCH_PORT(15, 16, internal)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
port@24 {
|
||||
reg = <24>;
|
||||
label = "lan25";
|
||||
phy-mode = "1000base-x";
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp0>;
|
||||
};
|
||||
|
||||
port@26 {
|
||||
reg = <26>;
|
||||
label = "lan26";
|
||||
phy-mode = "1000base-x";
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
121
target/linux/realtek/dts-5.15/rtl8382_zyxel_gs1900-24hp-v2.dts
Normal file
121
target/linux/realtek/dts-5.15/rtl8382_zyxel_gs1900-24hp-v2.dts
Normal file
|
@ -0,0 +1,121 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "rtl8380_zyxel_gs1900.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,gs1900-24hp-v2", "realtek,rtl838x-soc";
|
||||
model = "ZyXEL GS1900-24HP v2 Switch";
|
||||
|
||||
/* i2c of the left SFP cage: port 25 */
|
||||
i2c0: i2c-gpio-0 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp0: sfp-p25 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
los-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 26 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
/* i2c of the right SFP cage: port 26 */
|
||||
i2c1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp1: sfp-p26 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
los-gpio = <&gpio1 33 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 32 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mdio {
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
|
||||
INTERNAL_PHY(24)
|
||||
INTERNAL_PHY(26)
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, internal)
|
||||
SWITCH_PORT(9, 10, internal)
|
||||
SWITCH_PORT(10, 11, internal)
|
||||
SWITCH_PORT(11, 12, internal)
|
||||
SWITCH_PORT(12, 13, internal)
|
||||
SWITCH_PORT(13, 14, internal)
|
||||
SWITCH_PORT(14, 15, internal)
|
||||
SWITCH_PORT(15, 16, internal)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
|
||||
port@24 {
|
||||
reg = <24>;
|
||||
label = "lan25";
|
||||
phy-mode = "1000base-x";
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp0>;
|
||||
};
|
||||
|
||||
port@26 {
|
||||
reg = <26>;
|
||||
label = "lan26";
|
||||
phy-mode = "1000base-x";
|
||||
managed = "in-band-status";
|
||||
sfp = <&sfp1>;
|
||||
};
|
||||
};
|
||||
};
|
287
target/linux/realtek/dts-5.15/rtl838x.dtsi
Normal file
287
target/linux/realtek/dts-5.15/rtl838x.dtsi
Normal file
|
@ -0,0 +1,287 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include <dt-bindings/clock/rtl83xx-clk.h>
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#define STRINGIZE(s) #s
|
||||
#define LAN_LABEL(p, s) STRINGIZE(p ## s)
|
||||
#define SWITCH_PORT_LABEL(n) LAN_LABEL(lan, n)
|
||||
|
||||
#define INTERNAL_PHY(n) \
|
||||
phy##n: ethernet-phy@##n { \
|
||||
reg = <##n>; \
|
||||
compatible = "ethernet-phy-ieee802.3-c22"; \
|
||||
phy-is-integrated; \
|
||||
};
|
||||
|
||||
#define EXTERNAL_PHY(n) \
|
||||
phy##n: ethernet-phy@##n { \
|
||||
reg = <##n>; \
|
||||
compatible = "ethernet-phy-ieee802.3-c22"; \
|
||||
};
|
||||
|
||||
#define EXTERNAL_SFP_PHY(n) \
|
||||
phy##n: ethernet-phy@##n { \
|
||||
compatible = "ethernet-phy-ieee802.3-c22"; \
|
||||
sfp; \
|
||||
media = "fibre"; \
|
||||
reg = <##n>; \
|
||||
};
|
||||
|
||||
#define EXTERNAL_SFP_PHY_FULL(n, s) \
|
||||
phy##n: ethernet-phy@##n { \
|
||||
compatible = "ethernet-phy-ieee802.3-c22"; \
|
||||
sfp = <&sfp##s>; \
|
||||
reg = <##n>; \
|
||||
};
|
||||
|
||||
#define SWITCH_PORT(n, s, m) \
|
||||
port##n: port@##n { \
|
||||
reg = <##n>; \
|
||||
label = SWITCH_PORT_LABEL(s) ; \
|
||||
phy-handle = <&phy##n>; \
|
||||
phy-mode = #m ; \
|
||||
};
|
||||
|
||||
#define SWITCH_SFP_PORT(n, s, m) \
|
||||
port##n: port@##n { \
|
||||
reg = <##n>; \
|
||||
label = SWITCH_PORT_LABEL(s) ; \
|
||||
phy-handle = <&phy##n>; \
|
||||
phy-mode = #m ; \
|
||||
fixed-link { \
|
||||
speed = <1000>; \
|
||||
full-duplex; \
|
||||
}; \
|
||||
};
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
compatible = "realtek,rtl838x-soc";
|
||||
|
||||
osc: oscillator {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
|
||||
ccu: clock-controller {
|
||||
compatible = "realtek,rtl8380-clock";
|
||||
#clock-cells = <1>;
|
||||
clocks = <&osc>;
|
||||
clock-names = "ref_clk";
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "mips,mips4KEc";
|
||||
reg = <0>;
|
||||
clocks = <&ccu CLK_CPU>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu_opp_table: opp-table-0 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = /bits/ 64 <325000000>;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = /bits/ 64 <350000000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = /bits/ 64 <375000000>;
|
||||
};
|
||||
opp03 {
|
||||
opp-hz = /bits/ 64 <400000000>;
|
||||
};
|
||||
opp04 {
|
||||
opp-hz = /bits/ 64 <425000000>;
|
||||
};
|
||||
opp05 {
|
||||
opp-hz = /bits/ 64 <450000000>;
|
||||
};
|
||||
opp06 {
|
||||
opp-hz = /bits/ 64 <475000000>;
|
||||
};
|
||||
opp07 {
|
||||
opp-hz = /bits/ 64 <500000000>;
|
||||
};
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,115200";
|
||||
};
|
||||
|
||||
cpuintc: cpuintc {
|
||||
compatible = "mti,cpu-interrupt-controller";
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
soc: soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x18000000 0x10000>;
|
||||
|
||||
intc: interrupt-controller@3000 {
|
||||
compatible = "realtek,rtl8380-intc", "realtek,rtl-intc";
|
||||
reg = <0x3000 0x18>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
interrupt-parent = <&cpuintc>;
|
||||
interrupts = <2>, <3>, <4>, <5>, <6>;
|
||||
};
|
||||
|
||||
spi0: spi@1200 {
|
||||
compatible = "realtek,rtl8380-spi";
|
||||
reg = <0x1200 0x100>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
timer0: timer@3100 {
|
||||
compatible = "realtek,rtl8380-timer", "realtek,otto-timer";
|
||||
reg = <0x3100 0x10>, <0x3110 0x10>, <0x3120 0x10>,
|
||||
<0x3130 0x10>, <0x3140 0x10>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <29 4>, <28 4>, <17 4>, <16 4>, <15 4>;
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
};
|
||||
|
||||
uart0: uart@2000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x2000 0x100>;
|
||||
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <31 1>;
|
||||
|
||||
reg-io-width = <1>;
|
||||
reg-shift = <2>;
|
||||
fifo-size = <1>;
|
||||
no-loopback-test;
|
||||
};
|
||||
|
||||
uart1: uart@2100 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&enable_uart1>;
|
||||
|
||||
compatible = "ns16550a";
|
||||
reg = <0x2100 0x100>;
|
||||
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <30 0>;
|
||||
|
||||
reg-io-width = <1>;
|
||||
reg-shift = <2>;
|
||||
fifo-size = <1>;
|
||||
no-loopback-test;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
watchdog0: watchdog@3150 {
|
||||
compatible = "realtek,rtl8380-wdt";
|
||||
reg = <0x3150 0xc>;
|
||||
|
||||
realtek,reset-mode = "soc";
|
||||
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
timeout-sec = <30>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupt-names = "phase1", "phase2";
|
||||
interrupts = <19 3>, <18 4>;
|
||||
};
|
||||
|
||||
gpio0: gpio-controller@3500 {
|
||||
compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio";
|
||||
reg = <0x3500 0x20>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <24>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <23 3>;
|
||||
};
|
||||
};
|
||||
|
||||
pinmux: pinmux@1b001000 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x1b001000 0x4>;
|
||||
|
||||
pinctrl-single,bit-per-mux;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0x1>;
|
||||
#pinctrl-cells = <2>;
|
||||
|
||||
enable_uart1: pinmux_enable_uart1 {
|
||||
pinctrl-single,bits = <0x0 0x10 0x10>;
|
||||
};
|
||||
};
|
||||
|
||||
/* LED_GLB_CTRL */
|
||||
pinmux_led: pinmux@1b00a000 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x1b00a000 0x4>;
|
||||
|
||||
pinctrl-single,bit-per-mux;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0x1>;
|
||||
#pinctrl-cells = <2>;
|
||||
|
||||
/* enable GPIO 0 */
|
||||
pinmux_disable_sys_led: disable_sys_led {
|
||||
pinctrl-single,bits = <0x0 0x0 0x8000>;
|
||||
};
|
||||
};
|
||||
|
||||
ethernet0: ethernet@1b00a300 {
|
||||
compatible = "realtek,rtl838x-eth";
|
||||
reg = <0x1b00a300 0x100>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <24 3>;
|
||||
#interrupt-cells = <1>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
sram0: sram@9f000000 {
|
||||
compatible = "mmio-sram";
|
||||
reg = <0x9f000000 0x10000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x9f000000 0x10000>;
|
||||
};
|
||||
|
||||
switch0: switch@1b000000 {
|
||||
compatible = "realtek,rtl83xx-switch";
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <20 2>;
|
||||
};
|
||||
};
|
96
target/linux/realtek/dts-5.15/rtl838x_hpe_1920.dtsi
Normal file
96
target/linux/realtek/dts-5.15/rtl838x_hpe_1920.dtsi
Normal file
|
@ -0,0 +1,96 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,38400";
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
watchdog1: watchdog {
|
||||
// PT7A7514
|
||||
compatible = "linux,wdt-gpio";
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
|
||||
hw_algo = "toggle";
|
||||
hw_margin_ms = <1000>;
|
||||
always-running;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_disable_sys_led>;
|
||||
};
|
||||
};
|
||||
|
||||
&watchdog0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <50000000>;
|
||||
m25p,fast-read;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "bootware_basic";
|
||||
reg = <0x0 0x50000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@0x60000 {
|
||||
label = "bootware_data";
|
||||
reg = <0x60000 0x30000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@0x90000 {
|
||||
label = "bootware_extend";
|
||||
reg = <0x90000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@0x100000 {
|
||||
label = "bootware_basic_backup";
|
||||
reg = <0x100000 0x50000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@0x160000 {
|
||||
label = "bootware_data_backup";
|
||||
reg = <0x160000 0x30000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@0x190000 {
|
||||
label = "bootware_extend_backup";
|
||||
reg = <0x190000 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@0x300000 {
|
||||
label = "firmware";
|
||||
compatible = "h3c,vfs-firmware";
|
||||
reg = <0x300000 0x1cf0000>;
|
||||
};
|
||||
|
||||
partition@0x1ff0000 {
|
||||
label = "factory";
|
||||
reg = <0x1ff0000 0x10000>;
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
163
target/linux/realtek/dts-5.15/rtl8393_d-link_dgs-1210-52.dts
Normal file
163
target/linux/realtek/dts-5.15/rtl8393_d-link_dgs-1210-52.dts
Normal file
|
@ -0,0 +1,163 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl839x.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_common.dtsi"
|
||||
#include "rtl83xx_d-link_dgs-1210_gpio.dtsi"
|
||||
#include "rtl839x_d-link_dgs-1210_gpio.dtsi"
|
||||
|
||||
/ {
|
||||
compatible = "d-link,dgs-1210-52", "realtek,rtl8393-soc";
|
||||
model = "D-Link DGS-1210-52";
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* External phy RTL8218B #1 */
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
/* External phy RTL8218B #2 */
|
||||
EXTERNAL_PHY(8)
|
||||
EXTERNAL_PHY(9)
|
||||
EXTERNAL_PHY(10)
|
||||
EXTERNAL_PHY(11)
|
||||
EXTERNAL_PHY(12)
|
||||
EXTERNAL_PHY(13)
|
||||
EXTERNAL_PHY(14)
|
||||
EXTERNAL_PHY(15)
|
||||
|
||||
/* External phy RTL8218B #3 */
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
|
||||
/* External phy RTL8218B #4 */
|
||||
EXTERNAL_PHY(24)
|
||||
EXTERNAL_PHY(25)
|
||||
EXTERNAL_PHY(26)
|
||||
EXTERNAL_PHY(27)
|
||||
EXTERNAL_PHY(28)
|
||||
EXTERNAL_PHY(29)
|
||||
EXTERNAL_PHY(30)
|
||||
EXTERNAL_PHY(31)
|
||||
|
||||
/* External phy RTL8218B #5 */
|
||||
EXTERNAL_PHY(32)
|
||||
EXTERNAL_PHY(33)
|
||||
EXTERNAL_PHY(34)
|
||||
EXTERNAL_PHY(35)
|
||||
EXTERNAL_PHY(36)
|
||||
EXTERNAL_PHY(37)
|
||||
EXTERNAL_PHY(38)
|
||||
EXTERNAL_PHY(39)
|
||||
|
||||
/* External phy RTL8218B #6 */
|
||||
EXTERNAL_PHY(40)
|
||||
EXTERNAL_PHY(41)
|
||||
EXTERNAL_PHY(42)
|
||||
EXTERNAL_PHY(43)
|
||||
EXTERNAL_PHY(44)
|
||||
EXTERNAL_PHY(45)
|
||||
EXTERNAL_PHY(46)
|
||||
EXTERNAL_PHY(47)
|
||||
|
||||
/* External phy RTL8214FC */
|
||||
EXTERNAL_SFP_PHY_FULL(48, 0)
|
||||
EXTERNAL_SFP_PHY_FULL(49, 1)
|
||||
EXTERNAL_SFP_PHY_FULL(50, 2)
|
||||
EXTERNAL_SFP_PHY_FULL(51, 3)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, qsgmii)
|
||||
SWITCH_PORT(9, 10, qsgmii)
|
||||
SWITCH_PORT(10, 11, qsgmii)
|
||||
SWITCH_PORT(11, 12, qsgmii)
|
||||
SWITCH_PORT(12, 13, qsgmii)
|
||||
SWITCH_PORT(13, 14, qsgmii)
|
||||
SWITCH_PORT(14, 15, qsgmii)
|
||||
SWITCH_PORT(15, 16, qsgmii)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
SWITCH_PORT(24, 25, qsgmii)
|
||||
SWITCH_PORT(25, 26, qsgmii)
|
||||
SWITCH_PORT(26, 27, qsgmii)
|
||||
SWITCH_PORT(27, 28, qsgmii)
|
||||
SWITCH_PORT(28, 29, qsgmii)
|
||||
SWITCH_PORT(29, 30, qsgmii)
|
||||
SWITCH_PORT(30, 31, qsgmii)
|
||||
SWITCH_PORT(31, 32, qsgmii)
|
||||
|
||||
SWITCH_PORT(32, 33, qsgmii)
|
||||
SWITCH_PORT(33, 34, qsgmii)
|
||||
SWITCH_PORT(34, 35, qsgmii)
|
||||
SWITCH_PORT(35, 36, qsgmii)
|
||||
SWITCH_PORT(36, 37, qsgmii)
|
||||
SWITCH_PORT(37, 38, qsgmii)
|
||||
SWITCH_PORT(38, 39, qsgmii)
|
||||
SWITCH_PORT(39, 40, qsgmii)
|
||||
|
||||
SWITCH_PORT(40, 41, qsgmii)
|
||||
SWITCH_PORT(41, 42, qsgmii)
|
||||
SWITCH_PORT(42, 43, qsgmii)
|
||||
SWITCH_PORT(43, 44, qsgmii)
|
||||
SWITCH_PORT(44, 45, qsgmii)
|
||||
SWITCH_PORT(45, 46, qsgmii)
|
||||
SWITCH_PORT(46, 47, qsgmii)
|
||||
SWITCH_PORT(47, 48, qsgmii)
|
||||
|
||||
SWITCH_PORT(48, 49, qsgmii)
|
||||
SWITCH_PORT(49, 50, qsgmii)
|
||||
SWITCH_PORT(50, 51, qsgmii)
|
||||
SWITCH_PORT(51, 52, qsgmii)
|
||||
|
||||
/* CPU-Port */
|
||||
port@52 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <52>;
|
||||
phy-mode = "qsgmii";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,380 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl839x.dtsi"
|
||||
#include "rtl83xx_panasonic_mxxeg-pn28xx0k.dtsi"
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
/ {
|
||||
compatible = "panasonic,m48eg-pn28480k", "realtek,rtl8393-soc";
|
||||
model = "Panasonic Switch-M48eG PN28480K";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_status_eco_green;
|
||||
led-failsafe = &led_status_eco_amber;
|
||||
led-running = &led_status_eco_green;
|
||||
led-upgrade = &led_status_eco_green;
|
||||
};
|
||||
|
||||
fan: gpio-fan {
|
||||
compatible = "gpio-fan";
|
||||
gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
|
||||
/* the actual speeds (rpm) are unknown, just use dummy values */
|
||||
gpio-fan,speed-map = <1 0>, <2 1>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
/*
|
||||
* sfp0/1/2/3 are "combo" port with each TP port (45/46/47/48),
|
||||
* and they are connected to the RTL8218FB. Currently, there is
|
||||
* no support for the chip and only TP ports work by the RTL8218B
|
||||
* support.
|
||||
*/
|
||||
sfp0: sfp-p45 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
tx-fault-gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>;
|
||||
tx-disable-gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
|
||||
los-gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
sfp1: sfp-p46 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
tx-fault-gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
|
||||
tx-disable-gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 6 GPIO_ACTIVE_LOW>;
|
||||
los-gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
sfp2: sfp-p47 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c2>;
|
||||
tx-fault-gpio = <&gpio1 8 GPIO_ACTIVE_HIGH>;
|
||||
tx-disable-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
||||
los-gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
sfp3: sfp-p48 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c3>;
|
||||
tx-fault-gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
|
||||
tx-disable-gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 14 GPIO_ACTIVE_LOW>;
|
||||
los-gpio = <&gpio1 15 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
/*
|
||||
* Zone for SoC temperature
|
||||
*
|
||||
* Fan speed:
|
||||
*
|
||||
* - 0-44 celsius: Low
|
||||
* - 45-54 celsius: High
|
||||
*/
|
||||
cpu-thermal {
|
||||
polling-delay-passive = <1000>;
|
||||
polling-delay = <2000>;
|
||||
|
||||
thermal-sensors = <&tsens_soc>;
|
||||
|
||||
trips {
|
||||
cpu_alert: trip-point {
|
||||
temperature = <45000>;
|
||||
hysteresis = <4000>;
|
||||
type = "active";
|
||||
};
|
||||
|
||||
cpu_crit {
|
||||
temperature = <55000>;
|
||||
hysteresis = <1000>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map {
|
||||
trip = <&cpu_alert>;
|
||||
cooling-device = <&fan 0 1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Zone for system temperature
|
||||
*
|
||||
* Fan speed:
|
||||
*
|
||||
* - 0-39 celsius: Low
|
||||
* - 40-49 celsius: High
|
||||
*
|
||||
* Note: official recommended ranges of temperature on each
|
||||
* fan speed setting:
|
||||
*
|
||||
* - Low speed : 0-40 celsius
|
||||
* - High speed: 0-50 celsius
|
||||
*
|
||||
* (stock firmware doesn't support auto-selection of
|
||||
* speed and need to be selected manually by user)
|
||||
*/
|
||||
sys-thermal {
|
||||
polling-delay-passive = <1000>;
|
||||
polling-delay = <2000>;
|
||||
|
||||
thermal-sensors = <&tsens_sys>;
|
||||
|
||||
trips {
|
||||
sys_alert: trip-point {
|
||||
temperature = <40000>;
|
||||
hysteresis = <4000>;
|
||||
type = "active";
|
||||
};
|
||||
|
||||
sys_crit {
|
||||
temperature = <50000>;
|
||||
hysteresis = <2000>;
|
||||
type = "critical";
|
||||
};
|
||||
};
|
||||
|
||||
cooling-maps {
|
||||
map {
|
||||
trip = <&sys_alert>;
|
||||
cooling-device = <&fan 0 1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&leds {
|
||||
led_status_eco_amber: led-5 {
|
||||
label = "amber:status_eco";
|
||||
gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
function-enumerator = <1>;
|
||||
};
|
||||
|
||||
led_status_eco_green: led-6 {
|
||||
label = "green:status_eco";
|
||||
gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
function-enumerator = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_gpio_0 {
|
||||
scl-gpios = <&gpio0 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio0 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
|
||||
/* Microchip TCN75A (for SoC) */
|
||||
tsens_soc: sensor@48 {
|
||||
compatible = "microchip,tcn75";
|
||||
reg = <0x48>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
|
||||
/* Microchip TCN75A (for System) */
|
||||
tsens_sys: sensor@49 {
|
||||
compatible = "microchip,tcn75";
|
||||
reg = <0x49>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_gpio_1 {
|
||||
scl-gpios = <&gpio0 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
sda-gpios = <&gpio0 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
};
|
||||
|
||||
&gpio2 {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
/*
|
||||
* GPIO12 (IO1_4): 5x RTL8218B + RTL8218FB
|
||||
*
|
||||
* This GPIO pin should be specified as "reset-gpio" in mdio node,
|
||||
* but the current configuration of RTL8218B phy in the phy driver
|
||||
* seems to be incomplete and RTL8218FB phy won't be configured on
|
||||
* RTL8218D support. So, ethernet ports on these phys will be broken
|
||||
* after hard-resetting.
|
||||
* (RTL8218FB phy will be detected as RTL8218D by the phy driver)
|
||||
* At the moment, configure this GPIO pin as gpio-hog to avoid breaking
|
||||
* by resetting.
|
||||
*/
|
||||
ext_switch_reset {
|
||||
gpio-hog;
|
||||
gpios = <12 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "ext-switch-reset";
|
||||
};
|
||||
};
|
||||
|
||||
&i2c_switch {
|
||||
i2c0: i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
i2c1: i2c@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
i2c2: i2c@2 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <2>;
|
||||
};
|
||||
|
||||
i2c3: i2c@3 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
EXTERNAL_PHY(8)
|
||||
EXTERNAL_PHY(9)
|
||||
EXTERNAL_PHY(10)
|
||||
EXTERNAL_PHY(11)
|
||||
EXTERNAL_PHY(12)
|
||||
EXTERNAL_PHY(13)
|
||||
EXTERNAL_PHY(14)
|
||||
EXTERNAL_PHY(15)
|
||||
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
|
||||
EXTERNAL_PHY(24)
|
||||
EXTERNAL_PHY(25)
|
||||
EXTERNAL_PHY(26)
|
||||
EXTERNAL_PHY(27)
|
||||
EXTERNAL_PHY(28)
|
||||
EXTERNAL_PHY(29)
|
||||
EXTERNAL_PHY(30)
|
||||
EXTERNAL_PHY(31)
|
||||
|
||||
EXTERNAL_PHY(32)
|
||||
EXTERNAL_PHY(33)
|
||||
EXTERNAL_PHY(34)
|
||||
EXTERNAL_PHY(35)
|
||||
EXTERNAL_PHY(36)
|
||||
EXTERNAL_PHY(37)
|
||||
EXTERNAL_PHY(38)
|
||||
EXTERNAL_PHY(39)
|
||||
|
||||
/* RTL8218FB */
|
||||
EXTERNAL_PHY(40)
|
||||
EXTERNAL_PHY(41)
|
||||
EXTERNAL_PHY(42)
|
||||
EXTERNAL_PHY(43)
|
||||
EXTERNAL_PHY(44)
|
||||
EXTERNAL_PHY(45)
|
||||
EXTERNAL_PHY(46)
|
||||
EXTERNAL_PHY(47)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(0, 1, qsgmii)
|
||||
SWITCH_PORT(1, 2, qsgmii)
|
||||
SWITCH_PORT(2, 3, qsgmii)
|
||||
SWITCH_PORT(3, 4, qsgmii)
|
||||
SWITCH_PORT(4, 5, qsgmii)
|
||||
SWITCH_PORT(5, 6, qsgmii)
|
||||
SWITCH_PORT(6, 7, qsgmii)
|
||||
SWITCH_PORT(7, 8, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 9, qsgmii)
|
||||
SWITCH_PORT(9, 10, qsgmii)
|
||||
SWITCH_PORT(10, 11, qsgmii)
|
||||
SWITCH_PORT(11, 12, qsgmii)
|
||||
SWITCH_PORT(12, 13, qsgmii)
|
||||
SWITCH_PORT(13, 14, qsgmii)
|
||||
SWITCH_PORT(14, 15, qsgmii)
|
||||
SWITCH_PORT(15, 16, qsgmii)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
SWITCH_PORT(24, 25, qsgmii)
|
||||
SWITCH_PORT(25, 26, qsgmii)
|
||||
SWITCH_PORT(26, 27, qsgmii)
|
||||
SWITCH_PORT(27, 28, qsgmii)
|
||||
SWITCH_PORT(28, 29, qsgmii)
|
||||
SWITCH_PORT(29, 30, qsgmii)
|
||||
SWITCH_PORT(30, 31, qsgmii)
|
||||
SWITCH_PORT(31, 32, qsgmii)
|
||||
|
||||
SWITCH_PORT(32, 33, qsgmii)
|
||||
SWITCH_PORT(33, 34, qsgmii)
|
||||
SWITCH_PORT(34, 35, qsgmii)
|
||||
SWITCH_PORT(35, 36, qsgmii)
|
||||
SWITCH_PORT(36, 37, qsgmii)
|
||||
SWITCH_PORT(37, 38, qsgmii)
|
||||
SWITCH_PORT(38, 39, qsgmii)
|
||||
SWITCH_PORT(39, 40, qsgmii)
|
||||
|
||||
SWITCH_PORT(40, 41, qsgmii)
|
||||
SWITCH_PORT(41, 42, qsgmii)
|
||||
SWITCH_PORT(42, 43, qsgmii)
|
||||
SWITCH_PORT(43, 44, qsgmii)
|
||||
SWITCH_PORT(44, 45, qsgmii)
|
||||
SWITCH_PORT(45, 46, qsgmii)
|
||||
SWITCH_PORT(46, 47, qsgmii)
|
||||
SWITCH_PORT(47, 48, qsgmii)
|
||||
|
||||
port@52 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <52>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
422
target/linux/realtek/dts-5.15/rtl8393_tplink_sg2452p-v4.dts
Normal file
422
target/linux/realtek/dts-5.15/rtl8393_tplink_sg2452p-v4.dts
Normal file
|
@ -0,0 +1,422 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include "rtl839x.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/ {
|
||||
compatible = "tplink,sg2452p-v4", "realtek,rtl8393-soc";
|
||||
model = "TP-Link SG2452P v4";
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x10000000>;
|
||||
};
|
||||
|
||||
aliases {
|
||||
led-boot = &led_sys;
|
||||
led-failsafe = &led_sys;
|
||||
led-running = &led_sys;
|
||||
led-upgrade = &led_sys;
|
||||
label-mac-device = ðernet0;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,38400";
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
|
||||
speed {
|
||||
label = "speed";
|
||||
gpios = <&gpio0 19 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <BTN_0>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio_fan_sys {
|
||||
compatible = "gpio-fan";
|
||||
alarm-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
gpio_fan_psu_1 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&disable_jtag>;
|
||||
compatible = "gpio-fan";
|
||||
|
||||
alarm-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
|
||||
gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
|
||||
/* the actual speeds (rpm) are unknown, just use dummy values */
|
||||
gpio-fan,speed-map = <1 0>, <2 1>;
|
||||
#cooling-cells = <2>;
|
||||
};
|
||||
|
||||
gpio_fan_psu_2 {
|
||||
/* This fan runs in parallel to PSU1 fan, but has a separate
|
||||
* alarm GPIO. This is not (yet) supported by the gpio-fan driver,
|
||||
* so a separate instance is added
|
||||
*/
|
||||
compatible = "gpio-fan";
|
||||
alarm-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
leds {
|
||||
pinctrl-names = "default";
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led-0 {
|
||||
label = "green:speed";
|
||||
gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
};
|
||||
|
||||
led-1 {
|
||||
label = "green:poe";
|
||||
gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
};
|
||||
|
||||
led_sys: led-2 {
|
||||
label = "green:sys";
|
||||
gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
};
|
||||
|
||||
led-3 {
|
||||
label = "green:fan";
|
||||
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_STATUS;
|
||||
};
|
||||
|
||||
led-4 {
|
||||
label = "amber:fan";
|
||||
gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
function = "fault-fan";
|
||||
};
|
||||
|
||||
led-5 {
|
||||
label = "green:poe-max";
|
||||
gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = "alarm-poe";
|
||||
};
|
||||
};
|
||||
|
||||
i2c-gpio-0 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio0 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio0 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* LAN9 - LAN12 */
|
||||
tps23861@5 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x05>;
|
||||
};
|
||||
|
||||
/* LAN17 - LAN20 */
|
||||
tps23861@6 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x06>;
|
||||
};
|
||||
|
||||
/* LAN45 - LAN48 */
|
||||
tps23861@9 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x09>;
|
||||
};
|
||||
|
||||
/* LAN37 - LAN40 */
|
||||
tps23861@a {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x0a>;
|
||||
};
|
||||
|
||||
/* LAN1 - LAN4 */
|
||||
tps23861@14 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x14>;
|
||||
};
|
||||
|
||||
/* LAN25 - LAN28 */
|
||||
tps23861@24 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x24>;
|
||||
};
|
||||
|
||||
/* LAN33 - LAN 36 */
|
||||
tps23861@25 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x25>;
|
||||
};
|
||||
|
||||
/* LAN41 - LAN44 */
|
||||
tps23861@26 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x26>;
|
||||
};
|
||||
|
||||
/* LAN13 - LAN16 */
|
||||
tps23861@29 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x29>;
|
||||
};
|
||||
|
||||
/* LAN29 - LAN32 */
|
||||
tps23861@2c {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x2c>;
|
||||
};
|
||||
|
||||
/* LAN5 - LAN8 */
|
||||
tps23861@48 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x48>;
|
||||
};
|
||||
|
||||
/* LAN21 - LAN24 */
|
||||
tps23861@49 {
|
||||
compatible = "ti,tps23861";
|
||||
reg = <0x49>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio-restart {
|
||||
compatible = "gpio-restart";
|
||||
gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
poe-enable {
|
||||
gpio-hog;
|
||||
gpios = <23 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "poe-enable";
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0xe0000>;
|
||||
read-only;
|
||||
};
|
||||
partition@e0000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0xe0000 0x20000>;
|
||||
};
|
||||
|
||||
/* We use the "sys", "usrimg1" and "usrimg2" partitions
|
||||
* as firmware since the kernel needs to be in "sys", but the
|
||||
* partition is too small to hold the "rootfs" as well.
|
||||
* The original partition map contains:
|
||||
*
|
||||
* partition@100000 {
|
||||
* label = "sys";
|
||||
* reg = <0x100000 0x600000>;
|
||||
* };
|
||||
* partition@700000 {
|
||||
* label = "usrimg1";
|
||||
* reg = <0x700000 0xa00000>;
|
||||
* };
|
||||
* partition@1100000 {
|
||||
* label = "usrimg2";
|
||||
* reg = <0x1100000 0xa00000>;
|
||||
* };
|
||||
*/
|
||||
|
||||
partition@100000 {
|
||||
label = "firmware";
|
||||
reg = <0x100000 0x1a00000>;
|
||||
};
|
||||
partition@1b00000 {
|
||||
label = "usrappfs";
|
||||
reg = <0x1b00000 0x400000>;
|
||||
};
|
||||
partition@1f00000 {
|
||||
compatible = "nvmem-cells";
|
||||
label = "para";
|
||||
reg = <0x1f00000 0x100000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
read-only;
|
||||
|
||||
factory_macaddr: macaddr@fdff4 {
|
||||
reg = <0xfdff4 0x6>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
nvmem-cells = <&factory_macaddr>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* External phy RTL8218B #1 */
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
/* External phy RTL8218B #2 */
|
||||
EXTERNAL_PHY(8)
|
||||
EXTERNAL_PHY(9)
|
||||
EXTERNAL_PHY(10)
|
||||
EXTERNAL_PHY(11)
|
||||
EXTERNAL_PHY(12)
|
||||
EXTERNAL_PHY(13)
|
||||
EXTERNAL_PHY(14)
|
||||
EXTERNAL_PHY(15)
|
||||
|
||||
/* External phy RTL8218B #3 */
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
|
||||
/* External phy RTL8218B #4 */
|
||||
EXTERNAL_PHY(24)
|
||||
EXTERNAL_PHY(25)
|
||||
EXTERNAL_PHY(26)
|
||||
EXTERNAL_PHY(27)
|
||||
EXTERNAL_PHY(28)
|
||||
EXTERNAL_PHY(29)
|
||||
EXTERNAL_PHY(30)
|
||||
EXTERNAL_PHY(31)
|
||||
|
||||
/* External phy RTL8218B #5 */
|
||||
EXTERNAL_PHY(32)
|
||||
EXTERNAL_PHY(33)
|
||||
EXTERNAL_PHY(34)
|
||||
EXTERNAL_PHY(35)
|
||||
EXTERNAL_PHY(36)
|
||||
EXTERNAL_PHY(37)
|
||||
EXTERNAL_PHY(38)
|
||||
EXTERNAL_PHY(39)
|
||||
|
||||
/* External phy RTL8218B #6 */
|
||||
EXTERNAL_PHY(40)
|
||||
EXTERNAL_PHY(41)
|
||||
EXTERNAL_PHY(42)
|
||||
EXTERNAL_PHY(43)
|
||||
EXTERNAL_PHY(44)
|
||||
EXTERNAL_PHY(45)
|
||||
EXTERNAL_PHY(46)
|
||||
EXTERNAL_PHY(47)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(0, 01, qsgmii)
|
||||
SWITCH_PORT(1, 02, qsgmii)
|
||||
SWITCH_PORT(2, 03, qsgmii)
|
||||
SWITCH_PORT(3, 04, qsgmii)
|
||||
SWITCH_PORT(4, 05, qsgmii)
|
||||
SWITCH_PORT(5, 06, qsgmii)
|
||||
SWITCH_PORT(6, 07, qsgmii)
|
||||
SWITCH_PORT(7, 08, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 09, qsgmii)
|
||||
SWITCH_PORT(9, 10, qsgmii)
|
||||
SWITCH_PORT(10, 11, qsgmii)
|
||||
SWITCH_PORT(11, 12, qsgmii)
|
||||
SWITCH_PORT(12, 13, qsgmii)
|
||||
SWITCH_PORT(13, 14, qsgmii)
|
||||
SWITCH_PORT(14, 15, qsgmii)
|
||||
SWITCH_PORT(15, 16, qsgmii)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
SWITCH_PORT(24, 25, qsgmii)
|
||||
SWITCH_PORT(25, 26, qsgmii)
|
||||
SWITCH_PORT(26, 27, qsgmii)
|
||||
SWITCH_PORT(27, 28, qsgmii)
|
||||
SWITCH_PORT(28, 29, qsgmii)
|
||||
SWITCH_PORT(29, 30, qsgmii)
|
||||
SWITCH_PORT(30, 31, qsgmii)
|
||||
SWITCH_PORT(31, 32, qsgmii)
|
||||
|
||||
SWITCH_PORT(32, 33, qsgmii)
|
||||
SWITCH_PORT(33, 34, qsgmii)
|
||||
SWITCH_PORT(34, 35, qsgmii)
|
||||
SWITCH_PORT(35, 36, qsgmii)
|
||||
SWITCH_PORT(36, 37, qsgmii)
|
||||
SWITCH_PORT(37, 38, qsgmii)
|
||||
SWITCH_PORT(38, 39, qsgmii)
|
||||
SWITCH_PORT(39, 40, qsgmii)
|
||||
|
||||
SWITCH_PORT(40, 41, qsgmii)
|
||||
SWITCH_PORT(41, 42, qsgmii)
|
||||
SWITCH_PORT(42, 43, qsgmii)
|
||||
SWITCH_PORT(43, 44, qsgmii)
|
||||
SWITCH_PORT(44, 45, qsgmii)
|
||||
SWITCH_PORT(45, 46, qsgmii)
|
||||
SWITCH_PORT(46, 47, qsgmii)
|
||||
SWITCH_PORT(47, 48, qsgmii)
|
||||
|
||||
/* CPU-Port */
|
||||
port@52 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <52>;
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
320
target/linux/realtek/dts-5.15/rtl8393_zyxel_gs1900-48.dts
Normal file
320
target/linux/realtek/dts-5.15/rtl8393_zyxel_gs1900-48.dts
Normal file
|
@ -0,0 +1,320 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include "rtl839x.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,gs1900-48", "realtek,rtl8393-soc";
|
||||
model = "Zyxel GS1900-48";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_sys;
|
||||
led-failsafe = &led_sys;
|
||||
led-running = &led_sys;
|
||||
led-upgrade = &led_sys;
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
leds {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_disable_sys_led>;
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_sys: sys {
|
||||
label = "green:sys";
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio1: rtl8231-gpio {
|
||||
compatible = "realtek,rtl8231-gpio";
|
||||
#gpio-cells = <2>;
|
||||
indirect-access-bus-id = <3>;
|
||||
gpio-controller;
|
||||
};
|
||||
|
||||
gpio-restart {
|
||||
compatible = "gpio-restart";
|
||||
gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys-polled";
|
||||
poll-interval = <20>;
|
||||
|
||||
mode {
|
||||
label = "reset";
|
||||
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
/* i2c of the left SFP cage: port 49 */
|
||||
i2c0: i2c-gpio-0 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp0: sfp-p9 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
los-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 26 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
/* i2c of the right SFP cage: port 50 */
|
||||
i2c1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 30 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp1: sfp-p10 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
los-gpio = <&gpio1 33 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 32 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0x40000>;
|
||||
read-only;
|
||||
};
|
||||
partition@40000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x40000 0x10000>;
|
||||
read-only;
|
||||
};
|
||||
partition@50000 {
|
||||
label = "u-boot-env2";
|
||||
reg = <0x50000 0x10000>;
|
||||
read-only;
|
||||
};
|
||||
partition@60000 {
|
||||
label = "jffs";
|
||||
reg = <0x60000 0x100000>;
|
||||
};
|
||||
partition@160000 {
|
||||
label = "jffs2";
|
||||
reg = <0x160000 0x100000>;
|
||||
};
|
||||
partition@b260000 {
|
||||
label = "firmware";
|
||||
reg = <0x260000 0xda0000>;
|
||||
compatible = "openwrt,uimage", "denx,uimage";
|
||||
openwrt,ih-magic = <0x83800000>;
|
||||
};
|
||||
partition@930000 {
|
||||
label = "runtime2";
|
||||
reg = <0x930000 0x6d0000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* External phy RTL8218B #1 */
|
||||
EXTERNAL_PHY(0)
|
||||
EXTERNAL_PHY(1)
|
||||
EXTERNAL_PHY(2)
|
||||
EXTERNAL_PHY(3)
|
||||
EXTERNAL_PHY(4)
|
||||
EXTERNAL_PHY(5)
|
||||
EXTERNAL_PHY(6)
|
||||
EXTERNAL_PHY(7)
|
||||
|
||||
/* External phy RTL8218B #2 */
|
||||
EXTERNAL_PHY(8)
|
||||
EXTERNAL_PHY(9)
|
||||
EXTERNAL_PHY(10)
|
||||
EXTERNAL_PHY(11)
|
||||
EXTERNAL_PHY(12)
|
||||
EXTERNAL_PHY(13)
|
||||
EXTERNAL_PHY(14)
|
||||
EXTERNAL_PHY(15)
|
||||
|
||||
/* External phy RTL8218B #3 */
|
||||
EXTERNAL_PHY(16)
|
||||
EXTERNAL_PHY(17)
|
||||
EXTERNAL_PHY(18)
|
||||
EXTERNAL_PHY(19)
|
||||
EXTERNAL_PHY(20)
|
||||
EXTERNAL_PHY(21)
|
||||
EXTERNAL_PHY(22)
|
||||
EXTERNAL_PHY(23)
|
||||
|
||||
/* External phy RTL8218B #4 */
|
||||
EXTERNAL_PHY(24)
|
||||
EXTERNAL_PHY(25)
|
||||
EXTERNAL_PHY(26)
|
||||
EXTERNAL_PHY(27)
|
||||
EXTERNAL_PHY(28)
|
||||
EXTERNAL_PHY(29)
|
||||
EXTERNAL_PHY(30)
|
||||
EXTERNAL_PHY(31)
|
||||
|
||||
/* External phy RTL8218B #5 */
|
||||
EXTERNAL_PHY(32)
|
||||
EXTERNAL_PHY(33)
|
||||
EXTERNAL_PHY(34)
|
||||
EXTERNAL_PHY(35)
|
||||
EXTERNAL_PHY(36)
|
||||
EXTERNAL_PHY(37)
|
||||
EXTERNAL_PHY(38)
|
||||
EXTERNAL_PHY(39)
|
||||
|
||||
/* External phy RTL8218B #6 */
|
||||
EXTERNAL_PHY(40)
|
||||
EXTERNAL_PHY(41)
|
||||
EXTERNAL_PHY(42)
|
||||
EXTERNAL_PHY(43)
|
||||
EXTERNAL_PHY(44)
|
||||
EXTERNAL_PHY(45)
|
||||
EXTERNAL_PHY(46)
|
||||
EXTERNAL_PHY(47)
|
||||
|
||||
/* RTL8393 Internal SerDes */
|
||||
INTERNAL_PHY(48)
|
||||
INTERNAL_PHY(49)
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
SWITCH_PORT(0, 01, qsgmii)
|
||||
SWITCH_PORT(1, 02, qsgmii)
|
||||
SWITCH_PORT(2, 03, qsgmii)
|
||||
SWITCH_PORT(3, 04, qsgmii)
|
||||
SWITCH_PORT(4, 05, qsgmii)
|
||||
SWITCH_PORT(5, 06, qsgmii)
|
||||
SWITCH_PORT(6, 07, qsgmii)
|
||||
SWITCH_PORT(7, 08, qsgmii)
|
||||
|
||||
SWITCH_PORT(8, 09, qsgmii)
|
||||
SWITCH_PORT(9, 10, qsgmii)
|
||||
SWITCH_PORT(10, 11, qsgmii)
|
||||
SWITCH_PORT(11, 12, qsgmii)
|
||||
SWITCH_PORT(12, 13, qsgmii)
|
||||
SWITCH_PORT(13, 14, qsgmii)
|
||||
SWITCH_PORT(14, 15, qsgmii)
|
||||
SWITCH_PORT(15, 16, qsgmii)
|
||||
|
||||
SWITCH_PORT(16, 17, qsgmii)
|
||||
SWITCH_PORT(17, 18, qsgmii)
|
||||
SWITCH_PORT(18, 19, qsgmii)
|
||||
SWITCH_PORT(19, 20, qsgmii)
|
||||
SWITCH_PORT(20, 21, qsgmii)
|
||||
SWITCH_PORT(21, 22, qsgmii)
|
||||
SWITCH_PORT(22, 23, qsgmii)
|
||||
SWITCH_PORT(23, 24, qsgmii)
|
||||
|
||||
SWITCH_PORT(24, 25, qsgmii)
|
||||
SWITCH_PORT(25, 26, qsgmii)
|
||||
SWITCH_PORT(26, 27, qsgmii)
|
||||
SWITCH_PORT(27, 28, qsgmii)
|
||||
SWITCH_PORT(28, 29, qsgmii)
|
||||
SWITCH_PORT(29, 30, qsgmii)
|
||||
SWITCH_PORT(30, 31, qsgmii)
|
||||
SWITCH_PORT(31, 32, qsgmii)
|
||||
|
||||
SWITCH_PORT(32, 33, qsgmii)
|
||||
SWITCH_PORT(33, 34, qsgmii)
|
||||
SWITCH_PORT(34, 35, qsgmii)
|
||||
SWITCH_PORT(35, 36, qsgmii)
|
||||
SWITCH_PORT(36, 37, qsgmii)
|
||||
SWITCH_PORT(37, 38, qsgmii)
|
||||
SWITCH_PORT(38, 39, qsgmii)
|
||||
SWITCH_PORT(39, 40, qsgmii)
|
||||
|
||||
SWITCH_PORT(40, 41, qsgmii)
|
||||
SWITCH_PORT(41, 42, qsgmii)
|
||||
SWITCH_PORT(42, 43, qsgmii)
|
||||
SWITCH_PORT(43, 44, qsgmii)
|
||||
SWITCH_PORT(44, 45, qsgmii)
|
||||
SWITCH_PORT(45, 46, qsgmii)
|
||||
SWITCH_PORT(46, 47, qsgmii)
|
||||
SWITCH_PORT(47, 48, qsgmii)
|
||||
|
||||
/* SFP cages */
|
||||
port@48 {
|
||||
reg = <48>;
|
||||
label = "lan49";
|
||||
phy-mode = "sgmii";
|
||||
phy-handle = <&phy48>;
|
||||
sfp = <&sfp0>;
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
port@49 {
|
||||
reg = <49>;
|
||||
label = "lan50";
|
||||
phy-mode = "sgmii";
|
||||
phy-handle = <&phy49>;
|
||||
sfp = <&sfp1>;
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/* CPU-Port */
|
||||
port@52 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <52>;
|
||||
phy-mode = "qsgmii";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
319
target/linux/realtek/dts-5.15/rtl839x.dtsi
Normal file
319
target/linux/realtek/dts-5.15/rtl839x.dtsi
Normal file
|
@ -0,0 +1,319 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include <dt-bindings/clock/rtl83xx-clk.h>
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#define STRINGIZE(s) #s
|
||||
#define LAN_LABEL(p, s) STRINGIZE(p ## s)
|
||||
#define SWITCH_PORT_LABEL(n) LAN_LABEL(lan, n)
|
||||
|
||||
#define INTERNAL_PHY(n) \
|
||||
phy##n: ethernet-phy@##n { \
|
||||
reg = <##n>; \
|
||||
compatible = "ethernet-phy-ieee802.3-c22"; \
|
||||
phy-is-integrated; \
|
||||
};
|
||||
|
||||
#define EXTERNAL_PHY(n) \
|
||||
phy##n: ethernet-phy@##n { \
|
||||
reg = <##n>; \
|
||||
compatible = "ethernet-phy-ieee802.3-c22"; \
|
||||
};
|
||||
|
||||
#define EXTERNAL_SFP_PHY(n) \
|
||||
phy##n: ethernet-phy@##n { \
|
||||
compatible = "ethernet-phy-ieee802.3-c22"; \
|
||||
sfp; \
|
||||
media = "fibre"; \
|
||||
reg = <##n>; \
|
||||
};
|
||||
|
||||
#define EXTERNAL_SFP_PHY_FULL(n, s) \
|
||||
phy##n: ethernet-phy@##n { \
|
||||
compatible = "ethernet-phy-ieee802.3-c22"; \
|
||||
sfp = <&sfp##s>; \
|
||||
reg = <##n>; \
|
||||
};
|
||||
|
||||
#define SWITCH_PORT(n, s, m) \
|
||||
port@##n { \
|
||||
reg = <##n>; \
|
||||
label = SWITCH_PORT_LABEL(s) ; \
|
||||
phy-handle = <&phy##n>; \
|
||||
phy-mode = #m ; \
|
||||
};
|
||||
|
||||
#define SWITCH_SFP_PORT(n, s, m) \
|
||||
port@##n { \
|
||||
reg = <##n>; \
|
||||
label = SWITCH_PORT_LABEL(s) ; \
|
||||
phy-handle = <&phy##n>; \
|
||||
phy-mode = #m ; \
|
||||
fixed-link { \
|
||||
speed = <1000>; \
|
||||
full-duplex; \
|
||||
}; \
|
||||
};
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
compatible = "realtek,rtl839x-soc";
|
||||
|
||||
osc: oscillator {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
|
||||
ccu: clock-controller {
|
||||
compatible = "realtek,rtl8390-clock";
|
||||
#clock-cells = <1>;
|
||||
clocks = <&osc>;
|
||||
clock-names = "ref_clk";
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "mips,mips34Kc";
|
||||
reg = <0>;
|
||||
clocks = <&ccu CLK_CPU>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
compatible = "mips,mips34Kc";
|
||||
reg = <1>;
|
||||
clocks = <&ccu CLK_CPU>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu_opp_table: opp-table-0 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = /bits/ 64 <425000000>;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = /bits/ 64 <450000000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = /bits/ 64 <475000000>;
|
||||
};
|
||||
opp03 {
|
||||
opp-hz = /bits/ 64 <500000000>;
|
||||
};
|
||||
opp04 {
|
||||
opp-hz = /bits/ 64 <525000000>;
|
||||
};
|
||||
opp05 {
|
||||
opp-hz = /bits/ 64 <550000000>;
|
||||
};
|
||||
opp06 {
|
||||
opp-hz = /bits/ 64 <575000000>;
|
||||
};
|
||||
opp07 {
|
||||
opp-hz = /bits/ 64 <600000000>;
|
||||
};
|
||||
opp08 {
|
||||
opp-hz = /bits/ 64 <625000000>;
|
||||
};
|
||||
opp09 {
|
||||
opp-hz = /bits/ 64 <650000000>;
|
||||
};
|
||||
opp10 {
|
||||
opp-hz = /bits/ 64 <675000000>;
|
||||
};
|
||||
opp11 {
|
||||
opp-hz = /bits/ 64 <700000000>;
|
||||
};
|
||||
opp12 {
|
||||
opp-hz = /bits/ 64 <725000000>;
|
||||
};
|
||||
opp13 {
|
||||
opp-hz = /bits/ 64 <750000000>;
|
||||
};
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,115200";
|
||||
};
|
||||
|
||||
cpuintc: cpuintc {
|
||||
compatible = "mti,cpu-interrupt-controller";
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
soc: soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x18000000 0x10000>;
|
||||
|
||||
intc: interrupt-controller@3000 {
|
||||
compatible = "realtek,rtl8390-intc", "realtek,rtl-intc";
|
||||
reg = <0x3000 0x18>, <0x3018 0x18>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
interrupt-parent = <&cpuintc>;
|
||||
interrupts = <2>, <3>, <4>, <5>, <6>;
|
||||
};
|
||||
|
||||
spi0: spi@1200 {
|
||||
compatible = "realtek,rtl8380-spi";
|
||||
reg = <0x1200 0x100>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
timer0: timer@3100 {
|
||||
compatible = "realtek,rtl8390-timer", "realtek,otto-timer";
|
||||
reg = <0x3100 0x10>, <0x3110 0x10>, <0x3120 0x10>,
|
||||
<0x3130 0x10>, <0x3140 0x10>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <29 4>, <28 4>, <17 4>, <16 4>, <15 4>;
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
};
|
||||
|
||||
uart0: uart@2000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x2000 0x100>;
|
||||
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <31 1>;
|
||||
|
||||
reg-io-width = <1>;
|
||||
reg-shift = <2>;
|
||||
fifo-size = <1>;
|
||||
no-loopback-test;
|
||||
};
|
||||
|
||||
uart1: uart@2100 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&enable_uart1>;
|
||||
|
||||
compatible = "ns16550a";
|
||||
reg = <0x2100 0x100>;
|
||||
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <30 2>;
|
||||
|
||||
reg-io-width = <1>;
|
||||
reg-shift = <2>;
|
||||
fifo-size = <1>;
|
||||
no-loopback-test;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio0: gpio-controller@3500 {
|
||||
compatible = "realtek,rtl8390-gpio", "realtek,otto-gpio";
|
||||
reg = <0x3500 0x20>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <24>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <23 2>;
|
||||
};
|
||||
|
||||
watchdog0: watchdog@3150 {
|
||||
compatible = "realtek,rtl8390-wdt";
|
||||
reg = <0x3150 0xc>;
|
||||
|
||||
realtek,reset-mode = "soc";
|
||||
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
timeout-sec = <30>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupt-names = "phase1", "phase2";
|
||||
interrupts = <19 4>, <18 4>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pinmux@1b000004 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x1b000004 0x4>;
|
||||
|
||||
pinctrl-single,bit-per-mux;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0x1>;
|
||||
#pinctrl-cells = <2>;
|
||||
|
||||
enable_uart1: pinmux_enable_uart1 {
|
||||
pinctrl-single,bits = <0x0 0x1 0x3>;
|
||||
};
|
||||
|
||||
disable_jtag: pinmux_disable_jtag {
|
||||
pinctrl-single,bits = <0x0 0x2 0x3>;
|
||||
};
|
||||
};
|
||||
|
||||
/* LED_GLB_CTRL */
|
||||
pinmux@1b0000e4 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x1b0000e4 0x4>;
|
||||
|
||||
pinctrl-single,bit-per-mux;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0x1>;
|
||||
#pinctrl-cells = <2>;
|
||||
|
||||
/* enable GPIO 0 */
|
||||
pinmux_disable_sys_led: disable_sys_led {
|
||||
pinctrl-single,bits = <0x0 0x0 0x4000>;
|
||||
};
|
||||
};
|
||||
|
||||
ethernet0: ethernet@1b00a300 {
|
||||
compatible = "realtek,rtl838x-eth";
|
||||
reg = <0x1b00a300 0x100>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <24 3>;
|
||||
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
sram0: sram@9f000000 {
|
||||
compatible = "mmio-sram";
|
||||
reg = <0x9f000000 0x18000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0 0x9f000000 0x18000>;
|
||||
};
|
||||
|
||||
switch0: switch@1b000000 {
|
||||
status = "okay";
|
||||
compatible = "realtek,rtl83xx-switch";
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <20 2>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,75 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
/ {
|
||||
/* Lan 49 */
|
||||
i2c0: i2c-gpio-0 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp0: sfp-p49 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
los-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 8 GPIO_ACTIVE_LOW>;
|
||||
/* tx-disable-gpio handled by RTL8214FC based on media setting */
|
||||
};
|
||||
|
||||
/* Lan 50 */
|
||||
i2c1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp1: sfp-p50 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c1>;
|
||||
los-gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
|
||||
/* tx-disable-gpio handled by RTL8214FC based on media setting */
|
||||
};
|
||||
|
||||
/* Lan 51 */
|
||||
i2c2: i2c-gpio-2 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 23 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp2: sfp-p51 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c2>;
|
||||
los-gpio = <&gpio1 25 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 24 GPIO_ACTIVE_LOW>;
|
||||
/* tx-disable-gpio handled by RTL8214FC based on media setting */
|
||||
};
|
||||
|
||||
/* Lan 52 */
|
||||
i2c3: i2c-gpio-3 {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&gpio1 11 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
scl-gpios = <&gpio1 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
sfp3: sfp-p52 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c3>;
|
||||
los-gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio1 13 GPIO_ACTIVE_LOW>;
|
||||
/* tx-disable-gpio handled by RTL8214FC based on media setting */
|
||||
};
|
||||
};
|
|
@ -0,0 +1,83 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
led-boot = &led_power;
|
||||
led-failsafe = &led_power;
|
||||
led-running = &led_power;
|
||||
led-upgrade = &led_power;
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
leds: leds {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_disable_sys_led>;
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_power: power {
|
||||
label = "green:power";
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
indirect-access-bus-id = <0>;
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x00000000 0x80000>;
|
||||
read-only;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x00080000 0x40000>;
|
||||
};
|
||||
partition@c0000 {
|
||||
label = "board-name";
|
||||
reg = <0x000c0000 0x40000>;
|
||||
};
|
||||
partition@280000 {
|
||||
label = "firmware";
|
||||
compatible = "denx,uimage";
|
||||
reg = <0x00100000 0xd80000>;
|
||||
};
|
||||
partition@be80000 {
|
||||
label = "kernel2";
|
||||
reg = <0x00e80000 0x180000>;
|
||||
};
|
||||
partition@1000000 {
|
||||
label = "sysinfo";
|
||||
reg = <0x01000000 0x40000>;
|
||||
};
|
||||
partition@1040000 {
|
||||
label = "rootfs2";
|
||||
reg = <0x01040000 0xc00000>;
|
||||
};
|
||||
partition@1c40000 {
|
||||
label = "jffs2";
|
||||
reg = <0x01c40000 0x3c0000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
/ {
|
||||
gpio-restart {
|
||||
compatible = "gpio-restart";
|
||||
gpios = <&gpio1 34 GPIO_ACTIVE_LOW>;
|
||||
open-source;
|
||||
};
|
||||
|
||||
keys: keys {
|
||||
compatible = "gpio-keys-polled";
|
||||
poll-interval = <20>;
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio1 33 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio1: rtl8231-gpio {
|
||||
compatible = "realtek,rtl8231-gpio";
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
indirect-access-bus-id = <0>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,196 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,9600";
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
leds: leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led-0 {
|
||||
label = "amber:any_col";
|
||||
gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_AMBER>;
|
||||
function = LED_FUNCTION_FAULT;
|
||||
};
|
||||
|
||||
led-1 {
|
||||
label = "green:giga";
|
||||
gpios = <&gpio2 8 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
function-enumerator = <1>;
|
||||
};
|
||||
|
||||
led-2 {
|
||||
label = "green:100m";
|
||||
gpios = <&gpio2 9 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
function-enumerator = <2>;
|
||||
};
|
||||
|
||||
led-3 {
|
||||
label = "green:full";
|
||||
gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
function-enumerator = <3>;
|
||||
};
|
||||
|
||||
led-4 {
|
||||
label = "green:loop_history";
|
||||
gpios = <&gpio2 11 GPIO_ACTIVE_LOW>;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
function-enumerator = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
led_mode {
|
||||
label = "led-mode";
|
||||
gpios = <&gpio2 15 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <BTN_0>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio-restart {
|
||||
compatible = "gpio-restart";
|
||||
gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
i2c_gpio_0: i2c-gpio-0 {
|
||||
compatible = "i2c-gpio";
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gpio1: gpio@20 {
|
||||
compatible = "nxp,pca9555";
|
||||
reg = <0x20>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
gpio2: gpio@75 {
|
||||
compatible = "nxp,pca9539";
|
||||
reg = <0x75>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
/*
|
||||
* GPIO14 (IO1_6): Shift Register RESET (port LED)
|
||||
* - Switch-M8eG PN28080K: 3x 74HC164
|
||||
* - Switch-M16eG PN28160K: 4x 74HC164
|
||||
* - Switch-M24eG PN28240K: 6x 74HC164
|
||||
* - Switch-M48eG PN28480K: 12x 74HC164
|
||||
*/
|
||||
portled_sregister_reset {
|
||||
gpio-hog;
|
||||
gpios = <14 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "portled-sregister-reset";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c_gpio_1: i2c-gpio-1 {
|
||||
compatible = "i2c-gpio";
|
||||
i2c-gpio,delay-us = <2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
i2c_switch: i2c-switch@70 {
|
||||
compatible = "nxp,pca9545";
|
||||
reset-gpios = <&gpio2 13 GPIO_ACTIVE_LOW>;
|
||||
reg = <0x70>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0x80000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@80000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0x80000 0x10000>;
|
||||
};
|
||||
|
||||
partition@90000 {
|
||||
label = "u-boot-env2";
|
||||
reg = <0x90000 0x10000>;
|
||||
};
|
||||
|
||||
partition@a0000 {
|
||||
label = "sysinfo";
|
||||
reg = <0xa0000 0x60000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
/*
|
||||
* Filesystem area in stock firmware
|
||||
* (0x100000-0x1DFFFFF)
|
||||
*
|
||||
* stock firmware images are required to pass
|
||||
* the checking by the U-Boot, also for OpenWrt
|
||||
*
|
||||
* in OpenWrt:
|
||||
* - 0x100000-0xDFFFFF (13M): stock images
|
||||
* - 0xE00000-0x1DFFFFF(16M): OpenWrt image
|
||||
*/
|
||||
partition@100000 {
|
||||
label = "fs_reserved";
|
||||
reg = <0x100000 0xd00000>;
|
||||
};
|
||||
|
||||
partition@e00000 {
|
||||
compatible = "denx,uimage";
|
||||
label = "firmware";
|
||||
reg = <0xe00000 0x1000000>;
|
||||
};
|
||||
|
||||
partition@1e00000 {
|
||||
label = "vlog_data";
|
||||
reg = <0x1e00000 0x100000>;
|
||||
read-only;
|
||||
};
|
||||
|
||||
partition@1f00000 {
|
||||
label = "elog_data";
|
||||
reg = <0x1f00000 0x100000>;
|
||||
read-only;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
324
target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts
Normal file
324
target/linux/realtek/dts-5.15/rtl9302_zyxel_xgs1250-12.dts
Normal file
|
@ -0,0 +1,324 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/dts-v1/;
|
||||
|
||||
#include "rtl930x.dtsi"
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
|
||||
/ {
|
||||
compatible = "zyxel,xgs1250-12", "realtek,rtl838x-soc";
|
||||
model = "Zyxel XGS1250-12 Switch";
|
||||
|
||||
aliases {
|
||||
led-boot = &led_pwr_sys;
|
||||
led-failsafe = &led_pwr_sys;
|
||||
led-running = &led_pwr_sys;
|
||||
led-upgrade = &led_pwr_sys;
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
mode {
|
||||
label = "reset";
|
||||
gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
};
|
||||
};
|
||||
|
||||
/* i2c of the SFP cage: port 12 */
|
||||
i2c0: i2c-rtl9300 {
|
||||
compatible = "realtek,rtl9300-i2c";
|
||||
reg = <0x1b00036c 0x3c>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
sda-pin = <10>;
|
||||
scl-pin = <8>;
|
||||
clock-frequency = <100000>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinmux_disable_sys_led>;
|
||||
|
||||
led_pwr_sys: led-0 {
|
||||
label = "green:power";
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
function = LED_FUNCTION_POWER;
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
sfp0: sfp-p12 {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&i2c0>;
|
||||
los-gpio = <&gpio0 17 GPIO_ACTIVE_HIGH>;
|
||||
tx-fault-gpio = <&gpio0 20 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpio = <&gpio0 16 GPIO_ACTIVE_LOW>;
|
||||
tx-disable-gpio = <&gpio0 15 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
led_set: led_set@0 {
|
||||
compatible = "realtek,rtl9300-leds";
|
||||
led_set0 = <0x0000 0xffff 0x0a20 0x0b80>; // LED set 0: 1000Mbps, 10/100Mbps
|
||||
led_set1 = <0x0a0b 0x0a28 0x0a82 0x0a0b>; // LED set 1: (10G, 5G, 2.5G) (2.5G, 1G)
|
||||
// (5G, 10/100) (10G, 5G, 2.5G)
|
||||
led_set2 = <0x0000 0xffff 0x0a20 0x0a01>; // LED set 2: 1000MBit, 10GBit
|
||||
};
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "u-boot";
|
||||
reg = <0x0 0xe0000>;
|
||||
read-only;
|
||||
};
|
||||
partition@e0000 {
|
||||
label = "u-boot-env";
|
||||
reg = <0xe0000 0x10000>;
|
||||
};
|
||||
partition@f0000 {
|
||||
label = "u-boot-env2";
|
||||
reg = <0xf0000 0x10000>;
|
||||
read-only;
|
||||
};
|
||||
partition@100000 {
|
||||
label = "jffs";
|
||||
reg = <0x100000 0x100000>;
|
||||
};
|
||||
partition@200000 {
|
||||
label = "jffs2";
|
||||
reg = <0x200000 0x100000>;
|
||||
};
|
||||
partition@b300000 {
|
||||
label = "firmware";
|
||||
reg = <0x300000 0xce0000>;
|
||||
compatible = "openwrt,uimage", "denx,uimage";
|
||||
openwrt,ih-magic = <0x93001250>;
|
||||
};
|
||||
partition@fe0000 {
|
||||
label = "log";
|
||||
reg = <0xfe0000 0x20000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ðernet0 {
|
||||
mdio: mdio-bus {
|
||||
compatible = "realtek,rtl838x-mdio";
|
||||
regmap = <ðernet0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* External RTL8218D PHY */
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
rtl9300,smi-address = <0 0>;
|
||||
sds = < 2 >;
|
||||
// Disabled because we do not know how to bring up again
|
||||
// reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
phy1: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
rtl9300,smi-address = <0 1>;
|
||||
};
|
||||
phy2: ethernet-phy@2 {
|
||||
reg = <2>;
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
rtl9300,smi-address = <0 2>;
|
||||
};
|
||||
phy3: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
rtl9300,smi-address = <0 3>;
|
||||
};
|
||||
phy4: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
rtl9300,smi-address = <0 4>;
|
||||
};
|
||||
phy5: ethernet-phy@5 {
|
||||
reg = <5>;
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
rtl9300,smi-address = <0 5>;
|
||||
};
|
||||
phy6: ethernet-phy@6 {
|
||||
reg = <6>;
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
rtl9300,smi-address = <0 6>;
|
||||
};
|
||||
phy7: ethernet-phy@7 {
|
||||
reg = <7>;
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
rtl9300,smi-address = <0 7>;
|
||||
};
|
||||
|
||||
/* External Aquantia 113C PHYs */
|
||||
phy24: ethernet-phy@24 {
|
||||
reg = <24>;
|
||||
compatible = "ethernet-phy-ieee802.3-c45";
|
||||
rtl9300,smi-address = <1 8>;
|
||||
sds = < 6 >;
|
||||
// Disabled because we do not know how to bring up again
|
||||
// reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
phy25: ethernet-phy@25 {
|
||||
reg = <25>;
|
||||
compatible = "ethernet-phy-ieee802.3-c45";
|
||||
rtl9300,smi-address = <2 8>;
|
||||
sds = < 7 >;
|
||||
// Disabled because we do not know how to bring up again
|
||||
// reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
phy26: ethernet-phy@26 {
|
||||
reg = <26>;
|
||||
compatible = "ethernet-phy-ieee802.3-c45";
|
||||
rtl9300,smi-address = <3 8>;
|
||||
sds = < 8 >;
|
||||
// Disabled because we do not know how to bring up again
|
||||
// reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
/* SFP Ports */
|
||||
phy27: ethernet-phy@27 {
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
phy-is-integrated;
|
||||
reg = <27>;
|
||||
rtl9300,smi-address = <4 0>;
|
||||
sds = < 9 >;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "lan1";
|
||||
phy-handle = <&phy0>;
|
||||
phy-mode = "xgmii";
|
||||
led-set = <0>;
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan2";
|
||||
phy-handle = <&phy1>;
|
||||
phy-mode = "xgmii";
|
||||
led-set = <0>;
|
||||
};
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan3";
|
||||
phy-handle = <&phy2>;
|
||||
phy-mode = "xgmii";
|
||||
led-set = <0>;
|
||||
};
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan4";
|
||||
phy-handle = <&phy3>;
|
||||
phy-mode = "xgmii";
|
||||
led-set = <0>;
|
||||
};
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "lan5";
|
||||
phy-handle = <&phy4>;
|
||||
phy-mode = "xgmii";
|
||||
led-set = <0>;
|
||||
};
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "lan6";
|
||||
phy-handle = <&phy5>;
|
||||
phy-mode = "xgmii";
|
||||
led-set = <0>;
|
||||
};
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
label = "lan7";
|
||||
phy-handle = <&phy6>;
|
||||
phy-mode = "xgmii";
|
||||
led-set = <0>;
|
||||
};
|
||||
port@7 {
|
||||
reg = <7>;
|
||||
label = "lan8";
|
||||
phy-handle = <&phy7>;
|
||||
phy-mode = "xgmii";
|
||||
led-set = <0>;
|
||||
};
|
||||
|
||||
port@24 {
|
||||
reg = <24>;
|
||||
label = "lan9";
|
||||
phy-mode = "usxgmii";
|
||||
phy-handle = <&phy24>;
|
||||
led-set = <1>;
|
||||
};
|
||||
port@25 {
|
||||
reg = <25>;
|
||||
label = "lan10";
|
||||
phy-mode = "usxgmii";
|
||||
phy-handle = <&phy25>;
|
||||
led-set = <1>;
|
||||
};
|
||||
port@26 {
|
||||
reg = <26>;
|
||||
label = "lan11";
|
||||
phy-mode = "usxgmii";
|
||||
phy-handle = <&phy26>;
|
||||
led-set = <1>;
|
||||
};
|
||||
|
||||
port@27 {
|
||||
reg = <27>;
|
||||
label = "lan12";
|
||||
phy-mode = "10gbase-r";
|
||||
phy-handle = <&phy27>;
|
||||
sfp = <&sfp0>;
|
||||
led-set = <2>;
|
||||
|
||||
fixed-link {
|
||||
speed = <10000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
port@28 {
|
||||
ethernet = <ðernet0>;
|
||||
reg = <28>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <10000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
175
target/linux/realtek/dts-5.15/rtl930x.dtsi
Normal file
175
target/linux/realtek/dts-5.15/rtl930x.dtsi
Normal file
|
@ -0,0 +1,175 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
compatible = "realtek,rtl838x-soc";
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
frequency = <800000000>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "mips,mips34Kc";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x8000000>;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,115200";
|
||||
};
|
||||
|
||||
cpuintc: cpuintc {
|
||||
compatible = "mti,cpu-interrupt-controller";
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
lx_clk: lx_clk {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <175000000>;
|
||||
};
|
||||
|
||||
soc: soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x18000000 0x10000>;
|
||||
|
||||
intc: interrupt-controller@3000 {
|
||||
compatible = "realtek,rtl9300-intc", "realtek,rtl-intc";
|
||||
reg = <0x3000 0x18>, <0x3018 0x18>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
interrupt-parent = <&cpuintc>;
|
||||
interrupts = <2>, <3>, <4>, <5>, <6>, <7>;
|
||||
};
|
||||
|
||||
rtl9300clock: rtl9300clock@3200 {
|
||||
compatible = "realtek,rtl9300clock";
|
||||
reg = <0x3200 0x10>, <0x3210 0x10>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <7 5>, <8 5>;
|
||||
};
|
||||
|
||||
spi0: spi@1200 {
|
||||
compatible = "realtek,rtl8380-spi";
|
||||
reg = <0x1200 0x100>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
uart0: uart@2000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x2000 0x100>;
|
||||
|
||||
clocks = <&lx_clk>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <30 1>;
|
||||
|
||||
reg-io-width = <1>;
|
||||
reg-shift = <2>;
|
||||
fifo-size = <1>;
|
||||
no-loopback-test;
|
||||
};
|
||||
|
||||
uart1: uart@2100 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x2100 0x100>;
|
||||
|
||||
clocks = <&lx_clk>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <31 0>;
|
||||
|
||||
reg-io-width = <1>;
|
||||
reg-shift = <2>;
|
||||
fifo-size = <1>;
|
||||
no-loopback-test;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
watchdog0: watchdog@3260 {
|
||||
compatible = "realtek,rtl9300-wdt";
|
||||
reg = <0x3260 0xc>;
|
||||
|
||||
realtek,reset-mode = "soc";
|
||||
|
||||
clocks = <&lx_clk>;
|
||||
timeout-sec = <30>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupt-names = "phase1", "phase2";
|
||||
interrupts = <5 4>, <6 4>;
|
||||
};
|
||||
|
||||
gpio0: gpio-controller@3300 {
|
||||
compatible = "realtek,rtl9300-gpio", "realtek,otto-gpio";
|
||||
reg = <0x3300 0x1c>, <0x3338 0x8>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <24>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <13 1>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
pinmux_led: pinmux@1b00cc00 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x1b00cc00 0x4>;
|
||||
|
||||
pinctrl-single,bit-per-mux;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0x1>;
|
||||
#pinctrl-cells = <2>;
|
||||
|
||||
/* enable GPIO 0 */
|
||||
pinmux_disable_sys_led: disable_sys_led {
|
||||
pinctrl-single,bits = <0x0 0x0 0x1000>;
|
||||
};
|
||||
};
|
||||
|
||||
ethernet0: ethernet@1b00a300 {
|
||||
compatible = "realtek,rtl838x-eth";
|
||||
reg = <0x1b00a300 0x100>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <24 3>;
|
||||
|
||||
phy-mode = "internal";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
switch0: switch@1b000000 {
|
||||
compatible = "realtek,rtl83xx-switch";
|
||||
status = "okay";
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <23 2>;
|
||||
};
|
||||
};
|
200
target/linux/realtek/dts-5.15/rtl931x.dtsi
Normal file
200
target/linux/realtek/dts-5.15/rtl931x.dtsi
Normal file
|
@ -0,0 +1,200 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
|
||||
|
||||
#include <dt-bindings/interrupt-controller/mips-gic.h>
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
compatible = "realtek,rtl838x-soc";
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
frequency = <1000000000>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "mti,interaptive";
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
compatible = "mti,interaptive";
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x10000000>;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,115200";
|
||||
};
|
||||
|
||||
lx_clk: lx_clk {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <200000000>;
|
||||
};
|
||||
|
||||
cpuclock: cpuclock@0 {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
|
||||
/* FIXME: there should be way to detect this */
|
||||
clock-frequency = <1000000000>;
|
||||
};
|
||||
|
||||
cpuintc: cpuintc {
|
||||
compatible = "mti,cpu-interrupt-controller";
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
gic: interrupt-controller@1ddc0000 {
|
||||
compatible = "mti,gic";
|
||||
reg = <0x1ddc0000 0x20000>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
|
||||
/*
|
||||
* Declare the interrupt-parent even though the mti,gic
|
||||
* binding doesn't require it, such that the kernel can
|
||||
* figure out that cpu_intc is the root interrupt
|
||||
* controller & should be probed first.
|
||||
*/
|
||||
interrupt-parent = <&cpuintc>;
|
||||
|
||||
timer {
|
||||
compatible = "mti,gic-timer";
|
||||
interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
|
||||
clocks = <&cpuclock>;
|
||||
};
|
||||
};
|
||||
|
||||
soc: soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x18000000 0x10000>;
|
||||
|
||||
spi0: spi@1200 {
|
||||
status = "okay";
|
||||
|
||||
compatible = "realtek,rtl8380-spi";
|
||||
reg = <0x1200 0x100>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
watchdog0: watchdog@3260 {
|
||||
compatible = "realtek,rtl9310-wdt";
|
||||
reg = <0x3260 0xc>;
|
||||
|
||||
realtek,reset-mode = "soc";
|
||||
|
||||
clocks = <&lx_clk>;
|
||||
timeout-sec = <30>;
|
||||
|
||||
interrupt-parent = <&gic>;
|
||||
interrupt-names = "phase1", "phase2";
|
||||
interrupts = <GIC_SHARED 8 IRQ_TYPE_LEVEL_HIGH>, <GIC_SHARED 9 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
gpio0: gpio-controller@3300 {
|
||||
compatible = "realtek,rtl9310-gpio", "realtek,otto-gpio";
|
||||
reg = <0x3300 0x1c>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <32>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <GIC_SHARED 20 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
uart0: uart@2000 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x2000 0x100>;
|
||||
|
||||
clock-frequency = <200000000>;
|
||||
|
||||
interrupt-parent = <&gic>;
|
||||
#interrupt-cells = <3>;
|
||||
interrupts = <GIC_SHARED 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
reg-io-width = <1>;
|
||||
reg-shift = <2>;
|
||||
fifo-size = <1>;
|
||||
no-loopback-test;
|
||||
};
|
||||
|
||||
uart1: uart@2100 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x2100 0x100>;
|
||||
|
||||
clock-frequency = <200000000>;
|
||||
|
||||
interrupt-parent = <&gic>;
|
||||
#interrupt-cells = <3>;
|
||||
interrupts = <GIC_SHARED 23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
reg-io-width = <1>;
|
||||
reg-shift = <2>;
|
||||
fifo-size = <1>;
|
||||
no-loopback-test;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
pinmux: pinmux@1b001358 {
|
||||
compatible = "pinctrl-single";
|
||||
reg = <0x1b001358 0x4>;
|
||||
|
||||
pinctrl-single,bit-per-mux;
|
||||
pinctrl-single,register-width = <32>;
|
||||
pinctrl-single,function-mask = <0x1>;
|
||||
#pinctrl-cells = <2>;
|
||||
|
||||
/* Enable GPIO6 and GPIO7, possibly unknown others */
|
||||
pinmux_disable_jtag: disable_jtag {
|
||||
pinctrl-single,bits = <0x0 0x0 0x8000>;
|
||||
};
|
||||
|
||||
/* Controls GPIO0 */
|
||||
pinmux_disable_sys_led: disable_sys_led {
|
||||
pinctrl-single,bits = <0x0 0x0 0x100>;
|
||||
};
|
||||
};
|
||||
|
||||
ethernet0: ethernet@1b00a300 {
|
||||
status = "okay";
|
||||
compatible = "realtek,rtl838x-eth";
|
||||
reg = <0x1b00a300 0x100>;
|
||||
interrupt-parent = <&gic>;
|
||||
#interrupt-cells = <3>;
|
||||
interrupts = <GIC_SHARED 16 IRQ_TYPE_LEVEL_HIGH>;
|
||||
phy-mode = "internal";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
switch0: switch@1b000000 {
|
||||
compatible = "realtek,rtl83xx-switch";
|
||||
status = "okay";
|
||||
|
||||
interrupt-parent = <&gic>;
|
||||
#interrupt-cells = <3>;
|
||||
interrupts = <GIC_SHARED 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,85 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/timer/realtek,rtl8300-timer.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Realtek Timer Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Markus Stockhausen <markus.stockhausen@gmx.de>
|
||||
|
||||
description: |
|
||||
The Realtek SOCs of the RTL83XX and RTL93XX series have at least 5 known
|
||||
timers with corresponding interrupt lines . Their speed is derived from the
|
||||
Lexra Bus (LXB) by dividers. Each timer has a block of 4 control registers in
|
||||
the address range 0xb800xxxx with following start offsets.
|
||||
|
||||
RTL83XX: 0x3100, 0x3110, 0x3120, 0x3130, 0x3140
|
||||
RTL93XX: 0x3200, 0x3210, 0x3220, 0x3230, 0x3240
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- realtek,rtl8380-timer
|
||||
- realtek,rtl8390-timer
|
||||
- realtek,rtl9300-timer
|
||||
- const: realtek,otto-timer
|
||||
|
||||
reg:
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
description:
|
||||
List of timer register addresses.
|
||||
|
||||
interrupts:
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
description:
|
||||
List of timer interrupts.
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
timer0: timer@3100 {
|
||||
compatible = "realtek,rtl8380-timer", "realtek,otto-timer";
|
||||
reg = <0x3100 0x10>, <0x3110 0x10>, <0x3120 0x10>,
|
||||
<0x3130 0x10>, <0x3140 0x10>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <29 4>, <28 4>, <17 4>, <16 4>, <15 4>;
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
};
|
||||
- |
|
||||
timer0: timer@3100 {
|
||||
compatible = "realtek,rtl8390-timer", "realtek,otto-timer";
|
||||
reg = <0x3100 0x10>, <0x3110 0x10>, <0x3120 0x10>,
|
||||
<0x3130 0x10>, <0x3140 0x10>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <29 4>, <28 4>, <17 4>, <16 4>, <15 4>;
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
};
|
||||
- |
|
||||
timer0: timer@3200 {
|
||||
compatible = "realtek,rtl9300-timer", "realtek,otto-timer";
|
||||
reg = <0x3200 0x10>, <0x3210 0x10>, <0x3220 0x10>,
|
||||
<0x3230 0x10>, <0x3240 0x10>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <7 4>, <8 4>, <9 4>, <10 4>, <11 4>;
|
||||
clocks = <&ccu CLK_LXB>;
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,29 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef RTL838X_IOREMAP_H_
|
||||
#define RTL838X_IOREMAP_H_
|
||||
|
||||
static inline int is_rtl838x_internal_registers(phys_addr_t offset)
|
||||
{
|
||||
/* IO-Block */
|
||||
if (offset >= 0xb8000000 && offset < 0xb9000000)
|
||||
return 1;
|
||||
/* Switch block */
|
||||
if (offset >= 0xbb000000 && offset < 0xbc000000)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (is_rtl838x_internal_registers(offset))
|
||||
return (void __iomem *)offset;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int plat_iounmap(const volatile void __iomem *addr)
|
||||
{
|
||||
return is_rtl838x_internal_registers((unsigned long)addr);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,416 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2006-2012 Tony Wu (tonywu@realtek.com)
|
||||
* Copyright (C) 2020 B. Koblitz
|
||||
*/
|
||||
#ifndef _MACH_RTL838X_H_
|
||||
#define _MACH_RTL838X_H_
|
||||
|
||||
#include <asm/types.h>
|
||||
/*
|
||||
* Register access macros
|
||||
*/
|
||||
|
||||
#define RTL838X_SW_BASE ((volatile void *) 0xBB000000)
|
||||
|
||||
#define rtl83xx_r32(reg) readl(reg)
|
||||
#define rtl83xx_w32(val, reg) writel(val, reg)
|
||||
#define rtl83xx_w32_mask(clear, set, reg) rtl83xx_w32((rtl83xx_r32(reg) & ~(clear)) | (set), reg)
|
||||
|
||||
#define rtl83xx_r8(reg) readb(reg)
|
||||
#define rtl83xx_w8(val, reg) writeb(val, reg)
|
||||
|
||||
#define sw_r32(reg) readl(RTL838X_SW_BASE + reg)
|
||||
#define sw_w32(val, reg) writel(val, RTL838X_SW_BASE + reg)
|
||||
#define sw_w32_mask(clear, set, reg) \
|
||||
sw_w32((sw_r32(reg) & ~(clear)) | (set), reg)
|
||||
#define sw_r64(reg) ((((u64)readl(RTL838X_SW_BASE + reg)) << 32) | \
|
||||
readl(RTL838X_SW_BASE + reg + 4))
|
||||
|
||||
#define sw_w64(val, reg) do { \
|
||||
writel((u32)((val) >> 32), RTL838X_SW_BASE + reg); \
|
||||
writel((u32)((val) & 0xffffffff), \
|
||||
RTL838X_SW_BASE + reg + 4); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* SPRAM
|
||||
*/
|
||||
#define RTL838X_ISPRAM_BASE 0x0
|
||||
#define RTL838X_DSPRAM_BASE 0x0
|
||||
|
||||
/*
|
||||
* IRQ Controller
|
||||
*/
|
||||
#define RTL838X_IRQ_CPU_BASE 0
|
||||
#define RTL838X_IRQ_CPU_NUM 8
|
||||
#define RTL838X_IRQ_ICTL_BASE (RTL838X_IRQ_CPU_BASE + RTL838X_IRQ_CPU_NUM)
|
||||
#define RTL838X_IRQ_ICTL_NUM 32
|
||||
|
||||
#define RTL83XX_IRQ_UART0 31
|
||||
#define RTL83XX_IRQ_UART1 30
|
||||
#define RTL83XX_IRQ_TC0 29
|
||||
#define RTL83XX_IRQ_TC1 28
|
||||
#define RTL83XX_IRQ_OCPTO 27
|
||||
#define RTL83XX_IRQ_HLXTO 26
|
||||
#define RTL83XX_IRQ_SLXTO 25
|
||||
#define RTL83XX_IRQ_NIC 24
|
||||
#define RTL83XX_IRQ_GPIO_ABCD 23
|
||||
#define RTL83XX_IRQ_GPIO_EFGH 22
|
||||
#define RTL83XX_IRQ_RTC 21
|
||||
#define RTL83XX_IRQ_SWCORE 20
|
||||
#define RTL83XX_IRQ_WDT_IP1 19
|
||||
#define RTL83XX_IRQ_WDT_IP2 18
|
||||
|
||||
#define RTL9300_UART1_IRQ 31
|
||||
#define RTL9300_UART0_IRQ 30
|
||||
#define RTL9300_USB_H2_IRQ 28
|
||||
#define RTL9300_NIC_IRQ 24
|
||||
#define RTL9300_SWCORE_IRQ 23
|
||||
#define RTL9300_GPIO_ABC_IRQ 13
|
||||
#define RTL9300_TC4_IRQ 11
|
||||
#define RTL9300_TC3_IRQ 10
|
||||
#define RTL9300_TC2_IRQ 9
|
||||
#define RTL9300_TC1_IRQ 8
|
||||
#define RTL9300_TC0_IRQ 7
|
||||
|
||||
|
||||
/*
|
||||
* MIPS32R2 counter
|
||||
*/
|
||||
#define RTL838X_COMPARE_IRQ (RTL838X_IRQ_CPU_BASE + 7)
|
||||
|
||||
/*
|
||||
* ICTL
|
||||
* Base address 0xb8003000UL
|
||||
*/
|
||||
#define RTL838X_ICTL1_IRQ (RTL838X_IRQ_CPU_BASE + 2)
|
||||
#define RTL838X_ICTL2_IRQ (RTL838X_IRQ_CPU_BASE + 3)
|
||||
#define RTL838X_ICTL3_IRQ (RTL838X_IRQ_CPU_BASE + 4)
|
||||
#define RTL838X_ICTL4_IRQ (RTL838X_IRQ_CPU_BASE + 5)
|
||||
#define RTL838X_ICTL5_IRQ (RTL838X_IRQ_CPU_BASE + 6)
|
||||
|
||||
#define GIMR (0x00)
|
||||
#define UART0_IE (1 << 31)
|
||||
#define UART1_IE (1 << 30)
|
||||
#define TC0_IE (1 << 29)
|
||||
#define TC1_IE (1 << 28)
|
||||
#define OCPTO_IE (1 << 27)
|
||||
#define HLXTO_IE (1 << 26)
|
||||
#define SLXTO_IE (1 << 25)
|
||||
#define NIC_IE (1 << 24)
|
||||
#define GPIO_ABCD_IE (1 << 23)
|
||||
#define GPIO_EFGH_IE (1 << 22)
|
||||
#define RTC_IE (1 << 21)
|
||||
#define WDT_IP1_IE (1 << 19)
|
||||
#define WDT_IP2_IE (1 << 18)
|
||||
|
||||
#define GISR (0x04)
|
||||
#define UART0_IP (1 << 31)
|
||||
#define UART1_IP (1 << 30)
|
||||
#define TC0_IP (1 << 29)
|
||||
#define TC1_IP (1 << 28)
|
||||
#define OCPTO_IP (1 << 27)
|
||||
#define HLXTO_IP (1 << 26)
|
||||
#define SLXTO_IP (1 << 25)
|
||||
#define NIC_IP (1 << 24)
|
||||
#define GPIO_ABCD_IP (1 << 23)
|
||||
#define GPIO_EFGH_IP (1 << 22)
|
||||
#define RTC_IP (1 << 21)
|
||||
#define WDT_IP1_IP (1 << 19)
|
||||
#define WDT_IP2_IP (1 << 18)
|
||||
|
||||
|
||||
/* Interrupt Routing Selection */
|
||||
#define UART0_RS 2
|
||||
#define UART1_RS 1
|
||||
#define TC0_RS 5
|
||||
#define TC1_RS 1
|
||||
#define OCPTO_RS 1
|
||||
#define HLXTO_RS 1
|
||||
#define SLXTO_RS 1
|
||||
#define NIC_RS 4
|
||||
#define GPIO_ABCD_RS 4
|
||||
#define GPIO_EFGH_RS 4
|
||||
#define RTC_RS 4
|
||||
#define SWCORE_RS 3
|
||||
#define WDT_IP1_RS 4
|
||||
#define WDT_IP2_RS 5
|
||||
|
||||
/* Interrupt IRQ Assignments */
|
||||
#define UART0_IRQ 31
|
||||
#define UART1_IRQ 30
|
||||
#define TC0_IRQ 29
|
||||
#define TC1_IRQ 28
|
||||
#define OCPTO_IRQ 27
|
||||
#define HLXTO_IRQ 26
|
||||
#define SLXTO_IRQ 25
|
||||
#define NIC_IRQ 24
|
||||
#define GPIO_ABCD_IRQ 23
|
||||
#define GPIO_EFGH_IRQ 22
|
||||
#define RTC_IRQ 21
|
||||
#define SWCORE_IRQ 20
|
||||
#define WDT_IP1_IRQ 19
|
||||
#define WDT_IP2_IRQ 18
|
||||
|
||||
#define SYSTEM_FREQ 200000000
|
||||
#define RTL838X_UART0_BASE ((volatile void *)(0xb8002000UL))
|
||||
#define RTL838X_UART0_BAUD 38400 /* ex. 19200 or 38400 or 57600 or 115200 */
|
||||
#define RTL838X_UART0_FREQ (SYSTEM_FREQ - RTL838X_UART0_BAUD * 24)
|
||||
#define RTL838X_UART0_MAPBASE 0x18002000UL
|
||||
#define RTL838X_UART0_MAPSIZE 0x100
|
||||
#define RTL838X_UART0_IRQ UART0_IRQ
|
||||
|
||||
#define RTL838X_UART1_BASE ((volatile void *)(0xb8002100UL))
|
||||
#define RTL838X_UART1_BAUD 38400 /* ex. 19200 or 38400 or 57600 or 115200 */
|
||||
#define RTL838X_UART1_FREQ (SYSTEM_FREQ - RTL838X_UART1_BAUD * 24)
|
||||
#define RTL838X_UART1_MAPBASE 0x18002100UL
|
||||
#define RTL838X_UART1_MAPSIZE 0x100
|
||||
#define RTL838X_UART1_IRQ UART1_IRQ
|
||||
|
||||
#define UART0_RBR (RTL838X_UART0_BASE + 0x000)
|
||||
#define UART0_THR (RTL838X_UART0_BASE + 0x000)
|
||||
#define UART0_DLL (RTL838X_UART0_BASE + 0x000)
|
||||
#define UART0_IER (RTL838X_UART0_BASE + 0x004)
|
||||
#define UART0_DLM (RTL838X_UART0_BASE + 0x004)
|
||||
#define UART0_IIR (RTL838X_UART0_BASE + 0x008)
|
||||
#define UART0_FCR (RTL838X_UART0_BASE + 0x008)
|
||||
#define UART0_LCR (RTL838X_UART0_BASE + 0x00C)
|
||||
#define UART0_MCR (RTL838X_UART0_BASE + 0x010)
|
||||
#define UART0_LSR (RTL838X_UART0_BASE + 0x014)
|
||||
|
||||
#define UART1_RBR (RTL838X_UART1_BASE + 0x000)
|
||||
#define UART1_THR (RTL838X_UART1_BASE + 0x000)
|
||||
#define UART1_DLL (RTL838X_UART1_BASE + 0x000)
|
||||
#define UART1_IER (RTL838X_UART1_BASE + 0x004)
|
||||
#define UART1_DLM (RTL838X_UART1_BASE + 0x004)
|
||||
#define UART1_IIR (RTL838X_UART1_BASE + 0x008)
|
||||
#define UART1_FCR (RTL838X_UART1_BASE + 0x008)
|
||||
#define UART1_LCR (RTL838X_UART1_BASE + 0x00C)
|
||||
#define UART1_MCR (RTL838X_UART1_BASE + 0x010)
|
||||
#define UART1_LSR (RTL838X_UART1_BASE + 0x014)
|
||||
|
||||
/*
|
||||
* Memory Controller
|
||||
*/
|
||||
#define MC_MCR 0xB8001000
|
||||
#define MC_MCR_VAL 0x00000000
|
||||
|
||||
#define MC_DCR 0xB8001004
|
||||
#define MC_DCR0_VAL 0x54480000
|
||||
|
||||
#define MC_DTCR 0xB8001008
|
||||
#define MC_DTCR_VAL 0xFFFF05C0
|
||||
|
||||
/*
|
||||
* GPIO
|
||||
*/
|
||||
#define GPIO_CTRL_REG_BASE ((volatile void *) 0xb8003500)
|
||||
#define RTL838X_GPIO_PABC_CNR (GPIO_CTRL_REG_BASE + 0x0)
|
||||
#define RTL838X_GPIO_PABC_TYPE (GPIO_CTRL_REG_BASE + 0x04)
|
||||
#define RTL838X_GPIO_PABC_DIR (GPIO_CTRL_REG_BASE + 0x8)
|
||||
#define RTL838X_GPIO_PABC_DATA (GPIO_CTRL_REG_BASE + 0xc)
|
||||
#define RTL838X_GPIO_PABC_ISR (GPIO_CTRL_REG_BASE + 0x10)
|
||||
#define RTL838X_GPIO_PAB_IMR (GPIO_CTRL_REG_BASE + 0x14)
|
||||
#define RTL838X_GPIO_PC_IMR (GPIO_CTRL_REG_BASE + 0x18)
|
||||
|
||||
#define RTL930X_GPIO_CTRL_REG_BASE ((volatile void *) 0xb8003300)
|
||||
#define RTL930X_GPIO_PABCD_DIR (RTL930X_GPIO_CTRL_REG_BASE + 0x8)
|
||||
#define RTL930X_GPIO_PABCD_DAT (RTL930X_GPIO_CTRL_REG_BASE + 0xc)
|
||||
#define RTL930X_GPIO_PABCD_ISR (RTL930X_GPIO_CTRL_REG_BASE + 0x10)
|
||||
#define RTL930X_GPIO_PAB_IMR (RTL930X_GPIO_CTRL_REG_BASE + 0x14)
|
||||
#define RTL930X_GPIO_PCD_IMR (RTL930X_GPIO_CTRL_REG_BASE + 0x18)
|
||||
|
||||
#define RTL838X_MODEL_NAME_INFO (0x00D4)
|
||||
#define RTL839X_MODEL_NAME_INFO (0x0FF0)
|
||||
#define RTL93XX_MODEL_NAME_INFO (0x0004)
|
||||
#define RTL931X_CHIP_INFO_ADDR (0x0008)
|
||||
|
||||
#define RTL838X_LED_GLB_CTRL (0xA000)
|
||||
#define RTL839X_LED_GLB_CTRL (0x00E4)
|
||||
#define RTL9302_LED_GLB_CTRL (0xcc00)
|
||||
#define RTL930X_LED_GLB_CTRL (0xCC00)
|
||||
#define RTL931X_LED_GLB_CTRL (0x0600)
|
||||
|
||||
#define RTL838X_EXT_GPIO_DIR (0xA08C)
|
||||
#define RTL839X_EXT_GPIO_DIR (0x0214)
|
||||
#define RTL838X_EXT_GPIO_DATA (0xA094)
|
||||
#define RTL839X_EXT_GPIO_DATA (0x021c)
|
||||
#define RTL838X_EXT_GPIO_INDRT_ACCESS (0xA09C)
|
||||
#define RTL839X_EXT_GPIO_INDRT_ACCESS (0x0224)
|
||||
#define RTL838X_EXTRA_GPIO_CTRL (0xA0E0)
|
||||
#define RTL838X_DMY_REG5 (0x0144)
|
||||
#define RTL838X_EXTRA_GPIO_CTRL (0xA0E0)
|
||||
|
||||
#define RTL838X_GMII_INTF_SEL (0x1000)
|
||||
#define RTL838X_IO_DRIVING_ABILITY_CTRL (0x1010)
|
||||
|
||||
#define RTL838X_GPIO_A7 31
|
||||
#define RTL838X_GPIO_A6 30
|
||||
#define RTL838X_GPIO_A5 29
|
||||
#define RTL838X_GPIO_A4 28
|
||||
#define RTL838X_GPIO_A3 27
|
||||
#define RTL838X_GPIO_A2 26
|
||||
#define RTL838X_GPIO_A1 25
|
||||
#define RTL838X_GPIO_A0 24
|
||||
#define RTL838X_GPIO_B7 23
|
||||
#define RTL838X_GPIO_B6 22
|
||||
#define RTL838X_GPIO_B5 21
|
||||
#define RTL838X_GPIO_B4 20
|
||||
#define RTL838X_GPIO_B3 19
|
||||
#define RTL838X_GPIO_B2 18
|
||||
#define RTL838X_GPIO_B1 17
|
||||
#define RTL838X_GPIO_B0 16
|
||||
#define RTL838X_GPIO_C7 15
|
||||
#define RTL838X_GPIO_C6 14
|
||||
#define RTL838X_GPIO_C5 13
|
||||
#define RTL838X_GPIO_C4 12
|
||||
#define RTL838X_GPIO_C3 11
|
||||
#define RTL838X_GPIO_C2 10
|
||||
#define RTL838X_GPIO_C1 9
|
||||
#define RTL838X_GPIO_C0 8
|
||||
|
||||
#define RTL838X_INT_RW_CTRL (0x0058)
|
||||
#define RTL838X_EXT_VERSION (0x00D0)
|
||||
#define RTL838X_PLL_CML_CTRL (0x0FF8)
|
||||
#define RTL838X_STRAP_DBG (0x100C)
|
||||
|
||||
/*
|
||||
* Reset
|
||||
*/
|
||||
#define RGCR (0x1E70)
|
||||
#define RTL838X_RST_GLB_CTRL_0 (0x003c)
|
||||
#define RTL838X_RST_GLB_CTRL_1 (0x0040)
|
||||
#define RTL839X_RST_GLB_CTRL (0x0014)
|
||||
#define RTL930X_RST_GLB_CTRL_0 (0x000c)
|
||||
#define RTL931X_RST_GLB_CTRL (0x0400)
|
||||
|
||||
/* LED control by switch */
|
||||
#define RTL838X_LED_MODE_SEL (0x1004)
|
||||
#define RTL838X_LED_MODE_CTRL (0xA004)
|
||||
#define RTL838X_LED_P_EN_CTRL (0xA008)
|
||||
|
||||
/* LED control by software */
|
||||
#define RTL838X_LED_SW_CTRL (0x0128)
|
||||
#define RTL839X_LED_SW_CTRL (0xA00C)
|
||||
#define RTL838X_LED_SW_P_EN_CTRL (0xA010)
|
||||
#define RTL839X_LED_SW_P_EN_CTRL (0x012C)
|
||||
#define RTL838X_LED0_SW_P_EN_CTRL (0xA010)
|
||||
#define RTL839X_LED0_SW_P_EN_CTRL (0x012C)
|
||||
#define RTL838X_LED1_SW_P_EN_CTRL (0xA014)
|
||||
#define RTL839X_LED1_SW_P_EN_CTRL (0x0130)
|
||||
#define RTL838X_LED2_SW_P_EN_CTRL (0xA018)
|
||||
#define RTL839X_LED2_SW_P_EN_CTRL (0x0134)
|
||||
#define RTL838X_LED_SW_P_CTRL (0xA01C)
|
||||
#define RTL839X_LED_SW_P_CTRL (0x0144)
|
||||
|
||||
#define RTL839X_MAC_EFUSE_CTRL (0x02ac)
|
||||
|
||||
/*
|
||||
* MDIO via Realtek's SMI interface
|
||||
*/
|
||||
#define RTL838X_SMI_GLB_CTRL (0xa100)
|
||||
#define RTL838X_SMI_ACCESS_PHY_CTRL_0 (0xa1b8)
|
||||
#define RTL838X_SMI_ACCESS_PHY_CTRL_1 (0xa1bc)
|
||||
#define RTL838X_SMI_ACCESS_PHY_CTRL_2 (0xa1c0)
|
||||
#define RTL838X_SMI_ACCESS_PHY_CTRL_3 (0xa1c4)
|
||||
#define RTL838X_SMI_PORT0_5_ADDR_CTRL (0xa1c8)
|
||||
#define RTL838X_SMI_POLL_CTRL (0xa17c)
|
||||
|
||||
#define RTL839X_SMI_GLB_CTRL (0x03f8)
|
||||
#define RTL839X_SMI_PORT_POLLING_CTRL (0x03fc)
|
||||
#define RTL839X_PHYREG_ACCESS_CTRL (0x03DC)
|
||||
#define RTL839X_PHYREG_CTRL (0x03E0)
|
||||
#define RTL839X_PHYREG_PORT_CTRL (0x03E4)
|
||||
#define RTL839X_PHYREG_DATA_CTRL (0x03F0)
|
||||
#define RTL839X_PHYREG_MMD_CTRL (0x3F4)
|
||||
|
||||
#define RTL930X_SMI_GLB_CTRL (0xCA00)
|
||||
#define RTL930X_SMI_POLL_CTRL (0xca90)
|
||||
#define RTL930X_SMI_PORT0_15_POLLING_SEL (0xCA08)
|
||||
#define RTL930X_SMI_PORT16_27_POLLING_SEL (0xCA0C)
|
||||
#define RTL930X_SMI_PORT0_5_ADDR (0xCB80)
|
||||
#define RTL930X_SMI_ACCESS_PHY_CTRL_0 (0xCB70)
|
||||
#define RTL930X_SMI_ACCESS_PHY_CTRL_1 (0xCB74)
|
||||
#define RTL930X_SMI_ACCESS_PHY_CTRL_2 (0xCB78)
|
||||
#define RTL930X_SMI_ACCESS_PHY_CTRL_3 (0xCB7C)
|
||||
|
||||
#define RTL931X_SMI_GLB_CTRL1 (0x0CBC)
|
||||
#define RTL931X_SMI_GLB_CTRL0 (0x0CC0)
|
||||
#define RTL931X_SMI_PORT_POLLING_CTRL (0x0CCC)
|
||||
#define RTL931X_SMI_PORT_ADDR (0x0C74)
|
||||
#define RTL931X_SMI_PORT_POLLING_SEL (0x0C9C)
|
||||
#define RTL9310_SMI_PORT_POLLING_CTRL (0x0CCC)
|
||||
#define RTL931X_SMI_INDRT_ACCESS_CTRL_0 (0x0C00)
|
||||
#define RTL931X_SMI_INDRT_ACCESS_CTRL_1 (0x0C04)
|
||||
#define RTL931X_SMI_INDRT_ACCESS_CTRL_2 (0x0C08)
|
||||
#define RTL931X_SMI_INDRT_ACCESS_CTRL_3 (0x0C10)
|
||||
#define RTL931X_SMI_INDRT_ACCESS_BC_PHYID_CTRL (0x0C14)
|
||||
#define RTL931X_SMI_INDRT_ACCESS_MMD_CTRL (0xC18)
|
||||
#define RTL931X_MAC_L2_GLOBAL_CTRL2 (0x1358)
|
||||
#define RTL931X_MAC_L2_GLOBAL_CTRL1 (0x5548)
|
||||
|
||||
/*
|
||||
* Switch interrupts
|
||||
*/
|
||||
#define RTL838X_IMR_GLB (0x1100)
|
||||
#define RTL838X_IMR_PORT_LINK_STS_CHG (0x1104)
|
||||
#define RTL838X_ISR_GLB_SRC (0x1148)
|
||||
#define RTL838X_ISR_PORT_LINK_STS_CHG (0x114C)
|
||||
|
||||
#define RTL839X_IMR_GLB (0x0064)
|
||||
#define RTL839X_IMR_PORT_LINK_STS_CHG (0x0068)
|
||||
#define RTL839X_ISR_GLB_SRC (0x009c)
|
||||
#define RTL839X_ISR_PORT_LINK_STS_CHG (0x00a0)
|
||||
|
||||
#define RTL930X_IMR_GLB (0xC628)
|
||||
#define RTL930X_IMR_PORT_LINK_STS_CHG (0xC62C)
|
||||
#define RTL930X_ISR_GLB (0xC658)
|
||||
#define RTL930X_ISR_PORT_LINK_STS_CHG (0xC660)
|
||||
|
||||
// IMR_GLB does not exit on RTL931X
|
||||
#define RTL931X_IMR_PORT_LINK_STS_CHG (0x126C)
|
||||
#define RTL931X_ISR_GLB_SRC (0x12B4)
|
||||
#define RTL931X_ISR_PORT_LINK_STS_CHG (0x12B8)
|
||||
|
||||
/* Definition of family IDs */
|
||||
#define RTL8389_FAMILY_ID (0x8389)
|
||||
#define RTL8328_FAMILY_ID (0x8328)
|
||||
#define RTL8390_FAMILY_ID (0x8390)
|
||||
#define RTL8350_FAMILY_ID (0x8350)
|
||||
#define RTL8380_FAMILY_ID (0x8380)
|
||||
#define RTL8330_FAMILY_ID (0x8330)
|
||||
#define RTL9300_FAMILY_ID (0x9300)
|
||||
#define RTL9310_FAMILY_ID (0x9310)
|
||||
|
||||
/* SPI Support */
|
||||
#define RTL931X_SPI_CTRL0 (0x103C)
|
||||
|
||||
/* Basic SoC Features */
|
||||
#define RTL838X_CPU_PORT 28
|
||||
#define RTL839X_CPU_PORT 52
|
||||
#define RTL930X_CPU_PORT 28
|
||||
#define RTL931X_CPU_PORT 56
|
||||
|
||||
struct rtl83xx_soc_info {
|
||||
unsigned char *name;
|
||||
unsigned int id;
|
||||
unsigned int family;
|
||||
unsigned char *compatible;
|
||||
volatile void *sw_base;
|
||||
volatile void *icu_base;
|
||||
int cpu_port;
|
||||
};
|
||||
|
||||
/* rtl83xx-related functions used across subsystems */
|
||||
int rtl838x_smi_wait_op(int timeout);
|
||||
int rtl838x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
int rtl838x_write_phy(u32 port, u32 page, u32 reg, u32 val);
|
||||
int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val);
|
||||
int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val);
|
||||
int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
int rtl931x_write_phy(u32 port, u32 page, u32 reg, u32 val);
|
||||
|
||||
#endif /* _MACH_RTL838X_H_ */
|
200
target/linux/realtek/files-5.15/arch/mips/kernel/cevt-rtl9300.c
Normal file
200
target/linux/realtek/files-5.15/arch/mips/kernel/cevt-rtl9300.c
Normal file
|
@ -0,0 +1,200 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/idle.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/sched_clock.h>
|
||||
|
||||
#include <mach-rtl83xx.h>
|
||||
|
||||
/*
|
||||
* Timer registers
|
||||
* the RTL9300/9310 SoCs have 6 timers, each register block 0x10 apart
|
||||
*/
|
||||
#define RTL9300_TC_DATA 0x0
|
||||
#define RTL9300_TC_CNT 0x4
|
||||
#define RTL9300_TC_CTRL 0x8
|
||||
#define RTL9300_TC_CTRL_MODE BIT(24)
|
||||
#define RTL9300_TC_CTRL_EN BIT(28)
|
||||
#define RTL9300_TC_INT 0xc
|
||||
#define RTL9300_TC_INT_IP BIT(16)
|
||||
#define RTL9300_TC_INT_IE BIT(20)
|
||||
|
||||
// Timer modes
|
||||
#define TIMER_MODE_REPEAT 1
|
||||
#define TIMER_MODE_ONCE 0
|
||||
|
||||
// Minimum divider is 2
|
||||
#define DIVISOR_RTL9300 2
|
||||
|
||||
#define N_BITS 28
|
||||
|
||||
#define RTL9300_CLOCK_RATE 87500000
|
||||
|
||||
struct rtl9300_clk_dev {
|
||||
struct clock_event_device clkdev;
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
static void __iomem *rtl9300_tc_base(struct clock_event_device *clk)
|
||||
{
|
||||
struct rtl9300_clk_dev *rtl_clk = container_of(clk, struct rtl9300_clk_dev, clkdev);
|
||||
|
||||
return rtl_clk->base;
|
||||
}
|
||||
|
||||
static irqreturn_t rtl9300_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct rtl9300_clk_dev *rtl_clk = dev_id;
|
||||
struct clock_event_device *clk = &rtl_clk->clkdev;
|
||||
|
||||
u32 v = readl(rtl_clk->base + RTL9300_TC_INT);
|
||||
|
||||
// Acknowledge the IRQ
|
||||
v |= RTL9300_TC_INT_IP;
|
||||
writel(v, rtl_clk->base + RTL9300_TC_INT);
|
||||
|
||||
clk->event_handler(clk);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void rtl9300_clock_stop(void __iomem *base)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
writel(0, base + RTL9300_TC_CTRL);
|
||||
|
||||
// Acknowledge possibly pending IRQ
|
||||
v = readl(base + RTL9300_TC_INT);
|
||||
writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
|
||||
}
|
||||
|
||||
static void rtl9300_timer_start(void __iomem *base, bool periodic)
|
||||
{
|
||||
u32 v = (periodic ? RTL9300_TC_CTRL_MODE : 0) | RTL9300_TC_CTRL_EN | DIVISOR_RTL9300;
|
||||
|
||||
writel(0, base + RTL9300_TC_CNT);
|
||||
pr_debug("------------- starting timer base %08x\n", (u32)base);
|
||||
writel(v, base + RTL9300_TC_CTRL);
|
||||
}
|
||||
|
||||
static int rtl9300_next_event(unsigned long delta, struct clock_event_device *clk)
|
||||
{
|
||||
void __iomem *base = rtl9300_tc_base(clk);
|
||||
|
||||
rtl9300_clock_stop(base);
|
||||
writel(delta, base + RTL9300_TC_DATA);
|
||||
rtl9300_timer_start(base, TIMER_MODE_ONCE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9300_state_periodic(struct clock_event_device *clk)
|
||||
{
|
||||
void __iomem *base = rtl9300_tc_base(clk);
|
||||
|
||||
pr_debug("------------- rtl9300_state_periodic %08x\n", (u32)base);
|
||||
rtl9300_clock_stop(base);
|
||||
writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
|
||||
rtl9300_timer_start(base, TIMER_MODE_REPEAT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9300_state_oneshot(struct clock_event_device *clk)
|
||||
{
|
||||
void __iomem *base = rtl9300_tc_base(clk);
|
||||
|
||||
pr_debug("------------- rtl9300_state_oneshot %08x\n", (u32)base);
|
||||
rtl9300_clock_stop(base);
|
||||
writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
|
||||
rtl9300_timer_start(base, TIMER_MODE_ONCE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9300_shutdown(struct clock_event_device *clk)
|
||||
{
|
||||
void __iomem *base = rtl9300_tc_base(clk);
|
||||
|
||||
pr_debug("------------- rtl9300_shutdown %08x\n", (u32)base);
|
||||
rtl9300_clock_stop(base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl9300_clock_setup(void __iomem *base)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
// Disable timer
|
||||
writel(0, base + RTL9300_TC_CTRL);
|
||||
|
||||
// Acknowledge possibly pending IRQ
|
||||
v = readl(base + RTL9300_TC_INT);
|
||||
writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
|
||||
|
||||
// Setup maximum period (for use as clock-source)
|
||||
writel(0x0fffffff, base + RTL9300_TC_DATA);
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(struct rtl9300_clk_dev, rtl9300_clockevent);
|
||||
static DEFINE_PER_CPU(char [18], rtl9300_clock_name);
|
||||
|
||||
void rtl9300_clockevent_init(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
int irq;
|
||||
struct rtl9300_clk_dev *rtl_clk = &per_cpu(rtl9300_clockevent, cpu);
|
||||
struct clock_event_device *cd = &rtl_clk->clkdev;
|
||||
unsigned char *name = per_cpu(rtl9300_clock_name, cpu);
|
||||
unsigned long flags = IRQF_PERCPU | IRQF_TIMER;
|
||||
struct device_node *node;
|
||||
|
||||
pr_info("%s called for cpu%d\n", __func__, cpu);
|
||||
BUG_ON(cpu > 3); /* Only have 4 general purpose timers */
|
||||
|
||||
node = of_find_compatible_node(NULL, NULL, "realtek,rtl9300clock");
|
||||
if (!node) {
|
||||
pr_err("No DT entry found for realtek,rtl9300clock\n");
|
||||
return;
|
||||
}
|
||||
|
||||
irq = irq_of_parse_and_map(node, cpu);
|
||||
pr_info("%s using IRQ %d\n", __func__, irq);
|
||||
|
||||
rtl_clk->base = of_iomap(node, cpu);
|
||||
if (!rtl_clk->base) {
|
||||
pr_err("cannot map timer for cpu %d", cpu);
|
||||
return;
|
||||
}
|
||||
|
||||
rtl9300_clock_setup(rtl_clk->base);
|
||||
|
||||
sprintf(name, "rtl9300-counter-%d", cpu);
|
||||
cd->name = name;
|
||||
cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||
|
||||
clockevent_set_clock(cd, RTL9300_CLOCK_RATE);
|
||||
|
||||
cd->max_delta_ns = clockevent_delta2ns(0x0fffffff, cd);
|
||||
cd->max_delta_ticks = 0x0fffffff;
|
||||
cd->min_delta_ns = clockevent_delta2ns(0x20, cd);
|
||||
cd->min_delta_ticks = 0x20;
|
||||
cd->rating = 300;
|
||||
cd->irq = irq;
|
||||
cd->cpumask = cpumask_of(cpu);
|
||||
cd->set_next_event = rtl9300_next_event;
|
||||
cd->set_state_shutdown = rtl9300_shutdown;
|
||||
cd->set_state_periodic = rtl9300_state_periodic;
|
||||
cd->set_state_oneshot = rtl9300_state_oneshot;
|
||||
clockevents_register_device(cd);
|
||||
|
||||
irq_set_affinity(irq, cd->cpumask);
|
||||
|
||||
if (request_irq(irq, rtl9300_timer_interrupt, flags, name, rtl_clk))
|
||||
pr_err("Failed to request irq %d (%s)\n", irq, name);
|
||||
|
||||
writel(RTL9300_TC_INT_IE, rtl_clk->base + RTL9300_TC_INT);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Makefile for the rtl838x specific parts of the kernel
|
||||
#
|
||||
|
||||
obj-y := setup.o prom.o
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Realtek RTL838x SoCs
|
||||
#
|
||||
cflags-$(CONFIG_RTL83XX) += -I$(srctree)/arch/mips/include/asm/mach-rtl838x/
|
||||
load-$(CONFIG_RTL83XX) += 0xffffffff80000000
|
216
target/linux/realtek/files-5.15/arch/mips/rtl838x/prom.c
Normal file
216
target/linux/realtek/files-5.15/arch/mips/rtl838x/prom.c
Normal file
|
@ -0,0 +1,216 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* prom.c
|
||||
* Early intialization code for the Realtek RTL838X SoC
|
||||
*
|
||||
* based on the original BSP by
|
||||
* Copyright (C) 2006-2012 Tony Wu (tonywu@realtek.com)
|
||||
* Copyright (C) 2020 B. Koblitz
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/fw/fw.h>
|
||||
#include <asm/smp-ops.h>
|
||||
#include <asm/mips-cps.h>
|
||||
|
||||
#include <mach-rtl83xx.h>
|
||||
|
||||
extern char arcs_cmdline[];
|
||||
extern const char __appended_dtb;
|
||||
|
||||
struct rtl83xx_soc_info soc_info;
|
||||
const void *fdt;
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_SMP
|
||||
extern const struct plat_smp_ops vsmp_smp_ops;
|
||||
static struct plat_smp_ops rtl_smp_ops;
|
||||
|
||||
static void rtl_init_secondary(void)
|
||||
{
|
||||
#ifndef CONFIG_CEVT_R4K
|
||||
/*
|
||||
* These devices are low on resources. There might be the chance that CEVT_R4K
|
||||
* is not enabled in kernel build. Nevertheless the timer and interrupt 7 might
|
||||
* be active by default after startup of secondary VPE. With no registered
|
||||
* handler that leads to continuous unhandeled interrupts. In this case disable
|
||||
* counting (DC) in the core and confirm a pending interrupt.
|
||||
*/
|
||||
write_c0_cause(read_c0_cause() | CAUSEF_DC);
|
||||
write_c0_compare(0);
|
||||
#endif /* CONFIG_CEVT_R4K */
|
||||
/*
|
||||
* Enable all CPU interrupts, as everything is managed by the external
|
||||
* controller. TODO: Standard vsmp_init_secondary() has special treatment for
|
||||
* Malta if external GIC is available. Maybe we need this too.
|
||||
*/
|
||||
if (mips_gic_present())
|
||||
pr_warn("%s: GIC present. Maybe interrupt enabling required.\n", __func__);
|
||||
else
|
||||
set_c0_status(ST0_IM);
|
||||
}
|
||||
#endif /* CONFIG_MIPS_MT_SMP */
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return soc_info.name;
|
||||
}
|
||||
|
||||
void __init prom_free_prom_memory(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void __init device_tree_init(void)
|
||||
{
|
||||
if (!fdt_check_header(&__appended_dtb)) {
|
||||
fdt = &__appended_dtb;
|
||||
pr_info("Using appended Device Tree.\n");
|
||||
}
|
||||
initial_boot_params = (void *)fdt;
|
||||
unflatten_and_copy_device_tree();
|
||||
}
|
||||
|
||||
void __init identify_rtl9302(void)
|
||||
{
|
||||
switch (sw_r32(RTL93XX_MODEL_NAME_INFO) & 0xfffffff0) {
|
||||
case 0x93020810:
|
||||
soc_info.name = "RTL9302A 12x2.5G";
|
||||
break;
|
||||
case 0x93021010:
|
||||
soc_info.name = "RTL9302B 8x2.5G";
|
||||
break;
|
||||
case 0x93021810:
|
||||
soc_info.name = "RTL9302C 16x2.5G";
|
||||
break;
|
||||
case 0x93022010:
|
||||
soc_info.name = "RTL9302D 24x2.5G";
|
||||
break;
|
||||
case 0x93020800:
|
||||
soc_info.name = "RTL9302A";
|
||||
break;
|
||||
case 0x93021000:
|
||||
soc_info.name = "RTL9302B";
|
||||
break;
|
||||
case 0x93021800:
|
||||
soc_info.name = "RTL9302C";
|
||||
break;
|
||||
case 0x93022000:
|
||||
soc_info.name = "RTL9302D";
|
||||
break;
|
||||
case 0x93023001:
|
||||
soc_info.name = "RTL9302F";
|
||||
break;
|
||||
default:
|
||||
soc_info.name = "RTL9302";
|
||||
}
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
uint32_t model;
|
||||
|
||||
/* uart0 */
|
||||
setup_8250_early_printk_port(0xb8002000, 2, 0);
|
||||
|
||||
model = sw_r32(RTL838X_MODEL_NAME_INFO);
|
||||
pr_info("RTL838X model is %x\n", model);
|
||||
model = model >> 16 & 0xFFFF;
|
||||
|
||||
if ((model != 0x8328) && (model != 0x8330) && (model != 0x8332)
|
||||
&& (model != 0x8380) && (model != 0x8382)) {
|
||||
model = sw_r32(RTL839X_MODEL_NAME_INFO);
|
||||
pr_info("RTL839X model is %x\n", model);
|
||||
model = model >> 16 & 0xFFFF;
|
||||
}
|
||||
|
||||
if ((model & 0x8390) != 0x8380 && (model & 0x8390) != 0x8390) {
|
||||
model = sw_r32(RTL93XX_MODEL_NAME_INFO);
|
||||
pr_info("RTL93XX model is %x\n", model);
|
||||
model = model >> 16 & 0xFFFF;
|
||||
}
|
||||
|
||||
soc_info.id = model;
|
||||
|
||||
switch (model) {
|
||||
case 0x8328:
|
||||
soc_info.name = "RTL8328";
|
||||
soc_info.family = RTL8328_FAMILY_ID;
|
||||
break;
|
||||
case 0x8332:
|
||||
soc_info.name = "RTL8332";
|
||||
soc_info.family = RTL8380_FAMILY_ID;
|
||||
break;
|
||||
case 0x8380:
|
||||
soc_info.name = "RTL8380";
|
||||
soc_info.family = RTL8380_FAMILY_ID;
|
||||
break;
|
||||
case 0x8382:
|
||||
soc_info.name = "RTL8382";
|
||||
soc_info.family = RTL8380_FAMILY_ID;
|
||||
break;
|
||||
case 0x8390:
|
||||
soc_info.name = "RTL8390";
|
||||
soc_info.family = RTL8390_FAMILY_ID;
|
||||
break;
|
||||
case 0x8391:
|
||||
soc_info.name = "RTL8391";
|
||||
soc_info.family = RTL8390_FAMILY_ID;
|
||||
break;
|
||||
case 0x8392:
|
||||
soc_info.name = "RTL8392";
|
||||
soc_info.family = RTL8390_FAMILY_ID;
|
||||
break;
|
||||
case 0x8393:
|
||||
soc_info.name = "RTL8393";
|
||||
soc_info.family = RTL8390_FAMILY_ID;
|
||||
break;
|
||||
case 0x9301:
|
||||
soc_info.name = "RTL9301";
|
||||
soc_info.family = RTL9300_FAMILY_ID;
|
||||
break;
|
||||
case 0x9302:
|
||||
identify_rtl9302();
|
||||
soc_info.family = RTL9300_FAMILY_ID;
|
||||
break;
|
||||
case 0x9303:
|
||||
soc_info.name = "RTL9303";
|
||||
soc_info.family = RTL9300_FAMILY_ID;
|
||||
break;
|
||||
case 0x9313:
|
||||
soc_info.name = "RTL9313";
|
||||
soc_info.family = RTL9310_FAMILY_ID;
|
||||
break;
|
||||
default:
|
||||
soc_info.name = "DEFAULT";
|
||||
soc_info.family = 0;
|
||||
}
|
||||
|
||||
pr_info("SoC Type: %s\n", get_system_type());
|
||||
|
||||
fw_init_cmdline();
|
||||
|
||||
mips_cpc_probe();
|
||||
|
||||
if (!register_cps_smp_ops())
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_SMP
|
||||
if (cpu_has_mipsmt) {
|
||||
rtl_smp_ops = vsmp_smp_ops;
|
||||
rtl_smp_ops.init_secondary = rtl_init_secondary;
|
||||
register_smp_ops(&rtl_smp_ops);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
register_up_smp_ops();
|
||||
}
|
105
target/linux/realtek/files-5.15/arch/mips/rtl838x/setup.c
Normal file
105
target/linux/realtek/files-5.15/arch/mips/rtl838x/setup.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Setup for the Realtek RTL838X SoC:
|
||||
* Memory, Timer and Serial
|
||||
*
|
||||
* Copyright (C) 2020 B. Koblitz
|
||||
* based on the original BSP by
|
||||
* Copyright (C) 2006-2012 Tony Wu (tonywu@realtek.com)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/console.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/irqchip.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/smp-ops.h>
|
||||
|
||||
#include "mach-rtl83xx.h"
|
||||
|
||||
extern struct rtl83xx_soc_info soc_info;
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
void *dtb;
|
||||
|
||||
set_io_port_base(KSEG1);
|
||||
|
||||
if (fw_passed_dtb) /* UHI interface */
|
||||
dtb = (void *)fw_passed_dtb;
|
||||
else if (&__dtb_start[0] != &__dtb_end[0])
|
||||
dtb = (void *)__dtb_start;
|
||||
else
|
||||
panic("no dtb found");
|
||||
|
||||
/*
|
||||
* Load the devicetree. This causes the chosen node to be
|
||||
* parsed resulting in our memory appearing
|
||||
*/
|
||||
__dt_setup_arch(dtb);
|
||||
}
|
||||
|
||||
void plat_time_init_fallback(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
u32 freq = 500000000;
|
||||
|
||||
np = of_find_node_by_name(NULL, "cpus");
|
||||
if (!np) {
|
||||
pr_err("Missing 'cpus' DT node, using default frequency.");
|
||||
} else {
|
||||
if (of_property_read_u32(np, "frequency", &freq) < 0)
|
||||
pr_err("No 'frequency' property in DT, using default.");
|
||||
else
|
||||
pr_info("CPU frequency from device tree: %dMHz", freq / 1000000);
|
||||
of_node_put(np);
|
||||
}
|
||||
mips_hpt_frequency = freq / 2;
|
||||
}
|
||||
|
||||
void __init plat_time_init(void)
|
||||
{
|
||||
/*
|
||||
* Initialization routine resembles generic MIPS plat_time_init() with
|
||||
* lazy error handling. The final fallback is only needed until we have
|
||||
* converted all device trees to new clock syntax.
|
||||
*/
|
||||
struct device_node *np;
|
||||
struct clk *clk;
|
||||
|
||||
of_clk_init(NULL);
|
||||
|
||||
mips_hpt_frequency = 0;
|
||||
np = of_get_cpu_node(0, NULL);
|
||||
if (!np) {
|
||||
pr_err("Failed to get CPU node\n");
|
||||
} else {
|
||||
clk = of_clk_get(np, 0);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk));
|
||||
} else {
|
||||
mips_hpt_frequency = clk_get_rate(clk) / 2;
|
||||
clk_put(clk);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mips_hpt_frequency)
|
||||
plat_time_init_fallback();
|
||||
|
||||
timer_probe();
|
||||
}
|
||||
|
||||
void __init arch_init_irq(void)
|
||||
{
|
||||
irqchip_init();
|
||||
}
|
19
target/linux/realtek/files-5.15/drivers/clk/realtek/Kconfig
Normal file
19
target/linux/realtek/files-5.15/drivers/clk/realtek/Kconfig
Normal file
|
@ -0,0 +1,19 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
menuconfig COMMON_CLK_REALTEK
|
||||
bool "Support for Realtek's clock controllers"
|
||||
depends on RTL83XX
|
||||
|
||||
if COMMON_CLK_REALTEK
|
||||
|
||||
config COMMON_CLK_RTL83XX
|
||||
bool "Clock driver for Realtek RTL83XX"
|
||||
depends on RTL83XX
|
||||
select SRAM
|
||||
help
|
||||
This driver adds support for the Realtek RTL83xx series basic clocks.
|
||||
This includes chips in the RTL838x series, such as RTL8380, RTL8381,
|
||||
RTL832, as well as chips from the RTL839x series, such as RTL8390,
|
||||
RT8391, RTL8392, RTL8393 and RTL8396.
|
||||
|
||||
endif
|
|
@ -0,0 +1,2 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_COMMON_CLK_RTL83XX) += clk-rtl83xx.o clk-rtl838x-sram.o clk-rtl839x-sram.o
|
|
@ -0,0 +1,150 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Realtek RTL838X SRAM clock setters
|
||||
* Copyright (C) 2022 Markus Stockhausen <markus.stockhausen@gmx.de>
|
||||
*/
|
||||
|
||||
#include <dt-bindings/clock/rtl83xx-clk.h>
|
||||
|
||||
#include "clk-rtl83xx.h"
|
||||
|
||||
#define rGLB $t0
|
||||
#define rCTR $t1
|
||||
#define rMSK $t2
|
||||
#define rSLP $t3
|
||||
#define rTMP $t4
|
||||
|
||||
.set noreorder
|
||||
|
||||
.globl rtcl_838x_dram_start
|
||||
rtcl_838x_dram_start:
|
||||
|
||||
/*
|
||||
* Functions start here and should avoid access to normal memory. REMARK! Do not forget about
|
||||
* stack pointer and dirty caches that might interfere.
|
||||
*/
|
||||
|
||||
.globl rtcl_838x_dram_set_rate
|
||||
.ent rtcl_838x_dram_set_rate
|
||||
rtcl_838x_dram_set_rate:
|
||||
|
||||
#ifdef CONFIG_RTL838X
|
||||
|
||||
li rCTR, RTL_SW_CORE_BASE
|
||||
addiu rGLB, rCTR, RTL838X_PLL_GLB_CTRL
|
||||
ori rTMP, $0, CLK_CPU
|
||||
beq $a0, rTMP, pre_cpu
|
||||
ori rTMP, $0, CLK_MEM
|
||||
beq $a0, rTMP, pre_mem
|
||||
nop
|
||||
pre_lxb:
|
||||
ori rSLP, $0, RTL838X_GLB_CTRL_LXB_PLL_READY_MASK
|
||||
addiu rCTR, rCTR, RTL838X_PLL_LXB_CTRL0
|
||||
b main_set
|
||||
ori rMSK, $0, RTL838X_GLB_CTRL_EN_LXB_PLL_MASK
|
||||
pre_mem:
|
||||
/* simple 64K data cache flush to avoid unexpected memory access */
|
||||
li rMSK, RTL_SRAM_BASE
|
||||
li rTMP, 2048
|
||||
pre_flush:
|
||||
lw $0, 0(rMSK)
|
||||
addiu rMSK, rMSK, 32
|
||||
addiu rTMP, rTMP, -1
|
||||
bne rTMP, $0, pre_flush
|
||||
lw $0, -4(rMSK)
|
||||
|
||||
ori rSLP, $0, RTL838X_GLB_CTRL_MEM_PLL_READY_MASK
|
||||
addiu rCTR, rCTR, RTL838X_PLL_MEM_CTRL0
|
||||
b main_set
|
||||
ori rMSK, $0, RTL838X_GLB_CTRL_EN_MEM_PLL_MASK
|
||||
pre_cpu:
|
||||
/* switch CPU to LXB clock */
|
||||
ori rMSK, $0, RTL838X_GLB_CTRL_CPU_PLL_SC_MUX_MASK
|
||||
nor rMSK, rMSK, $0
|
||||
sync
|
||||
lw rTMP, 0(rGLB)
|
||||
and rTMP, rTMP, rMSK
|
||||
sw rTMP, 0(rGLB)
|
||||
sync
|
||||
|
||||
ori rSLP, $0, RTL838X_GLB_CTRL_CPU_PLL_READY_MASK
|
||||
addiu rCTR, rCTR, RTL838X_PLL_CPU_CTRL0
|
||||
ori rMSK, $0, RTL838X_GLB_CTRL_EN_CPU_PLL_MASK
|
||||
main_set:
|
||||
/* disable PLL */
|
||||
nor rMSK, rMSK, 0
|
||||
sync
|
||||
lw rTMP, 0(rGLB)
|
||||
sync
|
||||
and rTMP, rTMP, rMSK
|
||||
sync
|
||||
sw rTMP, 0(rGLB)
|
||||
|
||||
/* set new PLL values */
|
||||
sync
|
||||
sw $a1, 0(rCTR)
|
||||
sw $a2, 4(rCTR)
|
||||
sync
|
||||
|
||||
/* enable PLL (will reset it and clear ready status) */
|
||||
nor rMSK, rMSK, 0
|
||||
sync
|
||||
lw rTMP, 0(rGLB)
|
||||
sync
|
||||
or rTMP, rTMP, rMSK
|
||||
sync
|
||||
sw rTMP, 0(rGLB)
|
||||
|
||||
/* wait for PLL to become ready */
|
||||
wait_ready:
|
||||
lw rTMP, 0(rGLB)
|
||||
and rTMP, rTMP, rSLP
|
||||
bne rTMP, $0, wait_ready
|
||||
sync
|
||||
|
||||
/* branch to post processing */
|
||||
ori rTMP, $0, CLK_CPU
|
||||
beq $a0, rTMP, post_cpu
|
||||
ori rTMP, $0, CLK_MEM
|
||||
beq $a0, rTMP, post_mem
|
||||
nop
|
||||
post_lxb:
|
||||
jr $ra
|
||||
nop
|
||||
post_mem:
|
||||
jr $ra
|
||||
nop
|
||||
post_cpu:
|
||||
/* stabilize clock to avoid crash, empirically determined */
|
||||
ori rSLP, $0, 0x3000
|
||||
wait_cpu:
|
||||
bnez rSLP, wait_cpu
|
||||
addiu rSLP, rSLP, -1
|
||||
|
||||
/* switch CPU to PLL clock */
|
||||
ori rMSK, $0, RTL838X_GLB_CTRL_CPU_PLL_SC_MUX_MASK
|
||||
sync
|
||||
lw rTMP, 0(rGLB)
|
||||
or rTMP, rTMP, rMSK
|
||||
sw rTMP, 0(rGLB)
|
||||
sync
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
#else /* !CONFIG_RTL838X */
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
#endif
|
||||
|
||||
.end rtcl_838x_dram_set_rate
|
||||
|
||||
/*
|
||||
* End marker. Do not delete.
|
||||
*/
|
||||
.word RTL_SRAM_MARKER
|
||||
.globl rtcl_838x_dram_size
|
||||
rtcl_838x_dram_size:
|
||||
.word .-rtcl_838x_dram_start
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Realtek RTL839X SRAM clock setters
|
||||
* Copyright (C) 2022 Markus Stockhausen <markus.stockhausen@gmx.de>
|
||||
*/
|
||||
|
||||
#include <asm/mipsregs.h>
|
||||
#include <dt-bindings/clock/rtl83xx-clk.h>
|
||||
|
||||
#include "clk-rtl83xx.h"
|
||||
|
||||
#define rGLB $t0
|
||||
#define rCTR $t1
|
||||
#define rMSK $t2
|
||||
#define rSLP1 $t3
|
||||
#define rSLP2 $t4
|
||||
#define rSLP3 $t5
|
||||
#define rTMP $t6
|
||||
#define rCP0 $t7
|
||||
|
||||
.set noreorder
|
||||
|
||||
.globl rtcl_839x_dram_start
|
||||
rtcl_839x_dram_start:
|
||||
|
||||
/*
|
||||
* Functions start here and should avoid access to normal memory. REMARK! Do not forget about
|
||||
* stack pointer and dirty caches that might interfere.
|
||||
*/
|
||||
|
||||
.globl rtcl_839x_dram_set_rate
|
||||
.ent rtcl_839x_dram_set_rate
|
||||
rtcl_839x_dram_set_rate:
|
||||
|
||||
#ifdef CONFIG_RTL839X
|
||||
|
||||
/* disable MIPS 34K branch and return prediction */
|
||||
mfc0 rCP0, CP0_CONFIG, 7
|
||||
ori rTMP, rCP0, 0xc
|
||||
mtc0 rTMP, CP0_CONFIG, 7
|
||||
|
||||
li rCTR, RTL_SW_CORE_BASE
|
||||
addiu rGLB, rCTR, RTL839X_PLL_GLB_CTRL
|
||||
ori rTMP, $0, CLK_CPU
|
||||
beq $a0, rTMP, pre_cpu
|
||||
ori rTMP, $0, CLK_MEM
|
||||
beq $a0, rTMP, pre_mem
|
||||
nop
|
||||
pre_lxb:
|
||||
li rSLP1, 0x400000
|
||||
li rSLP2, 0x400000
|
||||
li rSLP3, 0x400000
|
||||
addiu rCTR, rCTR, RTL839X_PLL_LXB_CTRL0
|
||||
b main_set
|
||||
ori rMSK, $0, RTL839X_GLB_CTRL_LXB_CLKSEL_MASK
|
||||
pre_mem:
|
||||
/* try to avoid memory access with simple 64K data cache flush */
|
||||
li rMSK, RTL_SRAM_BASE
|
||||
li rTMP, 2048
|
||||
pre_flush:
|
||||
lw $0, 0(rMSK)
|
||||
addiu rMSK, rMSK, 32
|
||||
addiu rTMP, rTMP, -1
|
||||
bne rTMP, $0, pre_flush
|
||||
lw $0, -4(rMSK)
|
||||
|
||||
li rSLP1, 0x10000
|
||||
li rSLP2, 0x10000
|
||||
li rSLP3, 0x10000
|
||||
addiu rCTR, rCTR, RTL839X_PLL_MEM_CTRL0
|
||||
b main_set
|
||||
ori rMSK, $0, RTL839X_GLB_CTRL_MEM_CLKSEL_MASK
|
||||
pre_cpu:
|
||||
li rSLP1, 0x1000
|
||||
li rSLP2, 0x1000
|
||||
li rSLP3, 0x200
|
||||
addiu rCTR, rCTR, RTL839X_PLL_CPU_CTRL0
|
||||
ori rMSK, $0, RTL839X_GLB_CTRL_CPU_CLKSEL_MASK
|
||||
main_set:
|
||||
/* switch to fixed clock */
|
||||
sync
|
||||
lw rTMP, 0(rGLB)
|
||||
sync
|
||||
or rTMP, rTMP, rMSK
|
||||
sync
|
||||
sw rTMP, 0(rGLB)
|
||||
|
||||
/* wait until fixed clock in use */
|
||||
or rTMP, rSLP1, $0
|
||||
wait_fixclock:
|
||||
bnez rTMP, wait_fixclock
|
||||
addiu rTMP, rTMP, -1
|
||||
|
||||
/* set new PLL values */
|
||||
sync
|
||||
sw $a1, 0(rCTR)
|
||||
sw $a2, 4(rCTR)
|
||||
sync
|
||||
|
||||
/* wait for value takeover */
|
||||
or rTMP, rSLP2, $0
|
||||
wait_pll:
|
||||
bnez rTMP, wait_pll
|
||||
addiu rTMP, rTMP, -1
|
||||
|
||||
/* switch back to PLL clock*/
|
||||
nor rMSK, rMSK, $0
|
||||
sync
|
||||
lw rTMP, 0(rGLB)
|
||||
sync
|
||||
and rTMP, rTMP, rMSK
|
||||
sync
|
||||
sw rTMP, 0(rGLB)
|
||||
|
||||
/* wait until PLL clock in use */
|
||||
or rTMP, rSLP3, $0
|
||||
wait_pllclock:
|
||||
bnez rTMP, wait_pllclock
|
||||
addiu rTMP, rTMP, -1
|
||||
|
||||
/* restore branch prediction */
|
||||
mtc0 rCP0, CP0_CONFIG, 7
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
#else /* !CONFIG_RTL839X */
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
#endif
|
||||
|
||||
.end rtcl_839x_dram_set_rate
|
||||
|
||||
/*
|
||||
* End marker. Do not delete.
|
||||
*/
|
||||
.word RTL_SRAM_MARKER
|
||||
.globl rtcl_839x_dram_size
|
||||
rtcl_839x_dram_size:
|
||||
.word .-rtcl_839x_dram_start
|
||||
|
|
@ -0,0 +1,766 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Realtek RTL83XX clock driver
|
||||
* Copyright (C) 2022 Markus Stockhausen <markus.stockhausen@gmx.de>
|
||||
*
|
||||
* This driver provides basic clock support for the central core clock unit (CCU) and its PLLs
|
||||
* inside the RTL838X and RTL8389X SOC. Currently CPU, memory and LXB clock information can be
|
||||
* accessed. To make use of the driver add the following devices and configurations at the
|
||||
* appropriate locations to the DT.
|
||||
*
|
||||
* #include <dt-bindings/clock/rtl83xx-clk.h>
|
||||
*
|
||||
* sram0: sram@9f000000 {
|
||||
* compatible = "mmio-sram";
|
||||
* reg = <0x9f000000 0x18000>;
|
||||
* #address-cells = <1>;
|
||||
* #size-cells = <1>;
|
||||
* ranges = <0 0x9f000000 0x18000>;
|
||||
* };
|
||||
*
|
||||
* osc: oscillator {
|
||||
* compatible = "fixed-clock";
|
||||
* #clock-cells = <0>;
|
||||
* clock-frequency = <25000000>;
|
||||
* };
|
||||
*
|
||||
* ccu: clock-controller {
|
||||
* compatible = "realtek,rtl8380-clock";
|
||||
* #clock-cells = <1>;
|
||||
* clocks = <&osc>;
|
||||
* clock-names = "ref_clk";
|
||||
* };
|
||||
*
|
||||
*
|
||||
* The SRAM part is needed to be able to set clocks. When changing clocks the code must not run
|
||||
* from DRAM. Otherwise system might freeze. Take care to adjust CCU compatibility, SRAM address
|
||||
* and size to the target SOC device. Afterwards one can access/identify the clocks in the other
|
||||
* DT devices with <&ccu CLK_CPU>, <&ccu CLK_MEM> or <&ccu CLK_LXB>. Additionally the clocks can
|
||||
* be used inside the kernel with
|
||||
*
|
||||
* cpu_clk = clk_get(NULL, "cpu_clk");
|
||||
* mem_clk = clk_get(NULL, "mem_clk");
|
||||
* lxb_clk = clk_get(NULL, "lxb_clk");
|
||||
*
|
||||
* This driver can be directly used by the DT based cpufreq driver (CONFIG_CPUFREQ_DT) if CPU
|
||||
* references the right clock and sane operating points (OPP) are provided. E.g.
|
||||
*
|
||||
* cpu@0 {
|
||||
* compatible = "mips,mips4KEc";
|
||||
* reg = <0>;
|
||||
* clocks = <&ccu CLK_CPU>;
|
||||
* operating-points-v2 = <&cpu_opp_table>;
|
||||
* };
|
||||
*
|
||||
* cpu_opp_table: opp-table-0 {
|
||||
* compatible = "operating-points-v2";
|
||||
* opp-shared;
|
||||
* opp00 {
|
||||
* opp-hz = /bits/ 64 <425000000>;
|
||||
* };
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/mipsmtregs.h>
|
||||
#include <dt-bindings/clock/rtl83xx-clk.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/genalloc.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "clk-rtl83xx.h"
|
||||
|
||||
#define read_sw(reg) ioread32(((void *)RTL_SW_CORE_BASE) + reg)
|
||||
#define read_soc(reg) ioread32(((void *)RTL_SOC_BASE) + reg)
|
||||
|
||||
#define write_sw(val, reg) iowrite32(val, ((void *)RTL_SW_CORE_BASE) + reg)
|
||||
#define write_soc(val, reg) iowrite32(val, ((void *)RTL_SOC_BASE) + reg)
|
||||
|
||||
/*
|
||||
* some hardware specific definitions
|
||||
*/
|
||||
|
||||
#define SOC_RTL838X 0
|
||||
#define SOC_RTL839X 1
|
||||
#define SOC_COUNT 2
|
||||
|
||||
#define MEM_DDR1 1
|
||||
#define MEM_DDR2 2
|
||||
#define MEM_DDR3 3
|
||||
|
||||
#define REG_CTRL0 0
|
||||
#define REG_CTRL1 1
|
||||
#define REG_COUNT 2
|
||||
|
||||
#define OSC_RATE 25000000
|
||||
|
||||
static const int rtcl_regs[SOC_COUNT][REG_COUNT][CLK_COUNT] = {
|
||||
{
|
||||
{ RTL838X_PLL_CPU_CTRL0, RTL838X_PLL_MEM_CTRL0, RTL838X_PLL_LXB_CTRL0 },
|
||||
{ RTL838X_PLL_CPU_CTRL1, RTL838X_PLL_MEM_CTRL1, RTL838X_PLL_LXB_CTRL1 },
|
||||
}, {
|
||||
{ RTL839X_PLL_CPU_CTRL0, RTL839X_PLL_MEM_CTRL0, RTL839X_PLL_LXB_CTRL0 },
|
||||
{ RTL839X_PLL_CPU_CTRL1, RTL839X_PLL_MEM_CTRL1, RTL839X_PLL_LXB_CTRL1 },
|
||||
}
|
||||
};
|
||||
|
||||
#define RTCL_REG_SET(_rate, _ctrl0, _ctrl1) \
|
||||
{ \
|
||||
.rate = _rate, \
|
||||
.ctrl0 = _ctrl0, \
|
||||
.ctrl1 = _ctrl1, \
|
||||
}
|
||||
|
||||
struct rtcl_reg_set {
|
||||
unsigned int rate;
|
||||
unsigned int ctrl0;
|
||||
unsigned int ctrl1;
|
||||
};
|
||||
|
||||
/*
|
||||
* The following configuration tables are valid operation points for their corresponding PLLs.
|
||||
* The magic numbers are precalculated mulitpliers and dividers to keep the driver simple. They
|
||||
* also provide rates outside the allowed physical specifications. E.g. DDR3 memory has a lower
|
||||
* limit of 303 MHz or the CPU might get unstable if set to anything above its startup frequency.
|
||||
* Additionally the Realtek SOCs tend to expect CPU speed > MEM speed > LXB speed. The caller or
|
||||
* DT configuration must take care that only valid operating points are selected.
|
||||
*/
|
||||
|
||||
static const struct rtcl_reg_set rtcl_838x_cpu_reg_set[] = {
|
||||
RTCL_REG_SET(300000000, 0x045c8, 0x1414530e),
|
||||
RTCL_REG_SET(325000000, 0x04648, 0x1414530e),
|
||||
RTCL_REG_SET(350000000, 0x046c8, 0x1414530e),
|
||||
RTCL_REG_SET(375000000, 0x04748, 0x1414530e),
|
||||
RTCL_REG_SET(400000000, 0x045c8, 0x0c14530e),
|
||||
RTCL_REG_SET(425000000, 0x04628, 0x0c14530e),
|
||||
RTCL_REG_SET(450000000, 0x04688, 0x0c14530e),
|
||||
RTCL_REG_SET(475000000, 0x046e8, 0x0c14530e),
|
||||
RTCL_REG_SET(500000000, 0x04748, 0x0c14530e),
|
||||
RTCL_REG_SET(525000000, 0x047a8, 0x0c14530e),
|
||||
RTCL_REG_SET(550000000, 0x04808, 0x0c14530e),
|
||||
RTCL_REG_SET(575000000, 0x04868, 0x0c14530e),
|
||||
RTCL_REG_SET(600000000, 0x048c8, 0x0c14530e),
|
||||
RTCL_REG_SET(625000000, 0x04928, 0x0c14530e)
|
||||
};
|
||||
|
||||
static const struct rtcl_reg_set rtcl_838x_mem_reg_set[] = {
|
||||
RTCL_REG_SET(200000000, 0x041bc, 0x14018C80),
|
||||
RTCL_REG_SET(225000000, 0x0417c, 0x0c018C80),
|
||||
RTCL_REG_SET(250000000, 0x041ac, 0x0c018C80),
|
||||
RTCL_REG_SET(275000000, 0x0412c, 0x04018C80),
|
||||
RTCL_REG_SET(300000000, 0x0414c, 0x04018c80),
|
||||
RTCL_REG_SET(325000000, 0x0416c, 0x04018c80),
|
||||
RTCL_REG_SET(350000000, 0x0418c, 0x04018c80),
|
||||
RTCL_REG_SET(375000000, 0x041ac, 0x04018c80)
|
||||
};
|
||||
|
||||
static const struct rtcl_reg_set rtcl_838x_lxb_reg_set[] = {
|
||||
RTCL_REG_SET(100000000, 0x043c8, 0x001ad30e),
|
||||
RTCL_REG_SET(125000000, 0x043c8, 0x001ad30e),
|
||||
RTCL_REG_SET(150000000, 0x04508, 0x1c1ad30e),
|
||||
RTCL_REG_SET(175000000, 0x04508, 0x1c1ad30e),
|
||||
RTCL_REG_SET(200000000, 0x047c8, 0x001ad30e)
|
||||
};
|
||||
|
||||
static const struct rtcl_reg_set rtcl_839x_cpu_reg_set[] = {
|
||||
RTCL_REG_SET(400000000, 0x0414c, 0x00000005),
|
||||
RTCL_REG_SET(425000000, 0x041ec, 0x00000006),
|
||||
RTCL_REG_SET(450000000, 0x0417c, 0x00000005),
|
||||
RTCL_REG_SET(475000000, 0x0422c, 0x00000006),
|
||||
RTCL_REG_SET(500000000, 0x041ac, 0x00000005),
|
||||
RTCL_REG_SET(525000000, 0x0426c, 0x00000006),
|
||||
RTCL_REG_SET(550000000, 0x0412c, 0x00000004),
|
||||
RTCL_REG_SET(575000000, 0x042ac, 0x00000006),
|
||||
RTCL_REG_SET(600000000, 0x0414c, 0x00000004),
|
||||
RTCL_REG_SET(625000000, 0x042ec, 0x00000006),
|
||||
RTCL_REG_SET(650000000, 0x0416c, 0x00000004),
|
||||
RTCL_REG_SET(675000000, 0x04324, 0x00000006),
|
||||
RTCL_REG_SET(700000000, 0x0418c, 0x00000004),
|
||||
RTCL_REG_SET(725000000, 0x0436c, 0x00000006),
|
||||
RTCL_REG_SET(750000000, 0x0438c, 0x00000006),
|
||||
RTCL_REG_SET(775000000, 0x043ac, 0x00000006),
|
||||
RTCL_REG_SET(800000000, 0x043cc, 0x00000006),
|
||||
RTCL_REG_SET(825000000, 0x043ec, 0x00000006),
|
||||
RTCL_REG_SET(850000000, 0x0440c, 0x00000006)
|
||||
};
|
||||
|
||||
static const struct rtcl_reg_set rtcl_839x_mem_reg_set[] = {
|
||||
RTCL_REG_SET(100000000, 0x041cc, 0x00000000),
|
||||
RTCL_REG_SET(125000000, 0x041ac, 0x00000007),
|
||||
RTCL_REG_SET(150000000, 0x0414c, 0x00000006),
|
||||
RTCL_REG_SET(175000000, 0x0418c, 0x00000006),
|
||||
RTCL_REG_SET(200000000, 0x041cc, 0x00000006),
|
||||
RTCL_REG_SET(225000000, 0x0417c, 0x00000005),
|
||||
RTCL_REG_SET(250000000, 0x041ac, 0x00000005),
|
||||
RTCL_REG_SET(275000000, 0x0412c, 0x00000004),
|
||||
RTCL_REG_SET(300000000, 0x0414c, 0x00000004),
|
||||
RTCL_REG_SET(325000000, 0x0416c, 0x00000004),
|
||||
RTCL_REG_SET(350000000, 0x0418c, 0x00000004),
|
||||
RTCL_REG_SET(375000000, 0x041ac, 0x00000004),
|
||||
RTCL_REG_SET(400000000, 0x041cc, 0x00000004)
|
||||
};
|
||||
|
||||
static const struct rtcl_reg_set rtcl_839x_lxb_reg_set[] = {
|
||||
RTCL_REG_SET(50000000, 0x1414c, 0x00000003),
|
||||
RTCL_REG_SET(100000000, 0x0814c, 0x00000003),
|
||||
RTCL_REG_SET(150000000, 0x0414c, 0x00000003),
|
||||
RTCL_REG_SET(200000000, 0x0414c, 0x00000007)
|
||||
};
|
||||
|
||||
struct rtcl_rtab_set {
|
||||
int count;
|
||||
const struct rtcl_reg_set *rset;
|
||||
};
|
||||
|
||||
#define RTCL_RTAB_SET(_rset) \
|
||||
{ \
|
||||
.count = ARRAY_SIZE(_rset), \
|
||||
.rset = _rset, \
|
||||
}
|
||||
|
||||
static const struct rtcl_rtab_set rtcl_rtab_set[SOC_COUNT][CLK_COUNT] = {
|
||||
{
|
||||
RTCL_RTAB_SET(rtcl_838x_cpu_reg_set),
|
||||
RTCL_RTAB_SET(rtcl_838x_mem_reg_set),
|
||||
RTCL_RTAB_SET(rtcl_838x_lxb_reg_set)
|
||||
}, {
|
||||
RTCL_RTAB_SET(rtcl_839x_cpu_reg_set),
|
||||
RTCL_RTAB_SET(rtcl_839x_mem_reg_set),
|
||||
RTCL_RTAB_SET(rtcl_839x_lxb_reg_set)
|
||||
}
|
||||
};
|
||||
|
||||
#define RTCL_ROUND_SET(_min, _max, _step) \
|
||||
{ \
|
||||
.min = _min, \
|
||||
.max = _max, \
|
||||
.step = _step, \
|
||||
}
|
||||
|
||||
struct rtcl_round_set {
|
||||
unsigned long min;
|
||||
unsigned long max;
|
||||
unsigned long step;
|
||||
};
|
||||
|
||||
static const struct rtcl_round_set rtcl_round_set[SOC_COUNT][CLK_COUNT] = {
|
||||
{
|
||||
RTCL_ROUND_SET(300000000, 625000000, 25000000),
|
||||
RTCL_ROUND_SET(200000000, 375000000, 25000000),
|
||||
RTCL_ROUND_SET(100000000, 200000000, 25000000)
|
||||
}, {
|
||||
RTCL_ROUND_SET(400000000, 850000000, 25000000),
|
||||
RTCL_ROUND_SET(100000000, 400000000, 25000000),
|
||||
RTCL_ROUND_SET(50000000, 200000000, 50000000)
|
||||
}
|
||||
};
|
||||
|
||||
static const int rtcl_divn3[] = { 2, 3, 4, 6 };
|
||||
static const int rtcl_xdiv[] = { 2, 4, 2 };
|
||||
|
||||
/*
|
||||
* module data structures
|
||||
*/
|
||||
|
||||
#define RTCL_CLK_INFO(_idx, _name, _pname, _dname) \
|
||||
{ \
|
||||
.idx = _idx, \
|
||||
.name = _name, \
|
||||
.parent_name = _pname, \
|
||||
.display_name = _dname, \
|
||||
}
|
||||
|
||||
struct rtcl_clk_info {
|
||||
unsigned int idx;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
const char *display_name;
|
||||
};
|
||||
|
||||
struct rtcl_clk {
|
||||
struct clk_hw hw;
|
||||
unsigned int idx;
|
||||
unsigned long min;
|
||||
unsigned long max;
|
||||
unsigned long rate;
|
||||
unsigned long startup;
|
||||
};
|
||||
|
||||
static const struct rtcl_clk_info rtcl_clk_info[CLK_COUNT] = {
|
||||
RTCL_CLK_INFO(CLK_CPU, "cpu_clk", "ref_clk", "CPU"),
|
||||
RTCL_CLK_INFO(CLK_MEM, "mem_clk", "ref_clk", "MEM"),
|
||||
RTCL_CLK_INFO(CLK_LXB, "lxb_clk", "ref_clk", "LXB")
|
||||
};
|
||||
|
||||
struct rtcl_dram {
|
||||
int type;
|
||||
int buswidth;
|
||||
};
|
||||
|
||||
struct rtcl_sram {
|
||||
int *pmark;
|
||||
unsigned long vbase;
|
||||
};
|
||||
|
||||
struct rtcl_ccu {
|
||||
spinlock_t lock;
|
||||
unsigned int soc;
|
||||
struct rtcl_sram sram;
|
||||
struct rtcl_dram dram;
|
||||
struct device_node *np;
|
||||
struct platform_device *pdev;
|
||||
struct rtcl_clk clks[CLK_COUNT];
|
||||
};
|
||||
|
||||
struct rtcl_ccu *rtcl_ccu;
|
||||
|
||||
#define rtcl_hw_to_clk(_hw) container_of(_hw, struct rtcl_clk, hw)
|
||||
|
||||
/*
|
||||
* SRAM relocatable assembler functions. The dram() parts point to normal kernel memory while
|
||||
* the sram() parts are the same functions but relocated to SRAM.
|
||||
*/
|
||||
|
||||
extern void rtcl_838x_dram_start(void);
|
||||
extern int rtcl_838x_dram_size;
|
||||
|
||||
extern void (*rtcl_838x_dram_set_rate)(int clk_idx, int ctrl0, int ctrl1);
|
||||
static void (*rtcl_838x_sram_set_rate)(int clk_idx, int ctrl0, int ctrl1);
|
||||
|
||||
extern void rtcl_839x_dram_start(void);
|
||||
extern int rtcl_839x_dram_size;
|
||||
|
||||
extern void (*rtcl_839x_dram_set_rate)(int clk_idx, int ctrl0, int ctrl1);
|
||||
static void (*rtcl_839x_sram_set_rate)(int clk_idx, int ctrl0, int ctrl1);
|
||||
|
||||
/*
|
||||
* clock setter/getter functions
|
||||
*/
|
||||
|
||||
static unsigned long rtcl_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
{
|
||||
struct rtcl_clk *clk = rtcl_hw_to_clk(hw);
|
||||
unsigned int ctrl0, ctrl1, div1, div2, cmu_ncode_in;
|
||||
unsigned int cmu_sel_prediv, cmu_sel_div4, cmu_divn2, cmu_divn2_selb, cmu_divn3_sel;
|
||||
|
||||
if ((clk->idx >= CLK_COUNT) || (!rtcl_ccu) || (rtcl_ccu->soc >= SOC_COUNT))
|
||||
return 0;
|
||||
|
||||
ctrl0 = read_sw(rtcl_regs[rtcl_ccu->soc][REG_CTRL0][clk->idx]);
|
||||
ctrl1 = read_sw(rtcl_regs[rtcl_ccu->soc][REG_CTRL1][clk->idx]);
|
||||
|
||||
cmu_sel_prediv = 1 << RTL_PLL_CTRL0_CMU_SEL_PREDIV(ctrl0);
|
||||
cmu_sel_div4 = RTL_PLL_CTRL0_CMU_SEL_DIV4(ctrl0) ? 4 : 1;
|
||||
cmu_ncode_in = RTL_PLL_CTRL0_CMU_NCODE_IN(ctrl0) + 4;
|
||||
cmu_divn2 = RTL_PLL_CTRL0_CMU_DIVN2(ctrl0) + 4;
|
||||
|
||||
switch (rtcl_ccu->soc) {
|
||||
case SOC_RTL838X:
|
||||
if ((ctrl0 == 0) && (ctrl1 == 0) && (clk->idx == CLK_LXB))
|
||||
return 200000000;
|
||||
|
||||
cmu_divn2_selb = RTL838X_PLL_CTRL1_CMU_DIVN2_SELB(ctrl1);
|
||||
cmu_divn3_sel = rtcl_divn3[RTL838X_PLL_CTRL1_CMU_DIVN3_SEL(ctrl1)];
|
||||
break;
|
||||
case SOC_RTL839X:
|
||||
cmu_divn2_selb = RTL839X_PLL_CTRL1_CMU_DIVN2_SELB(ctrl1);
|
||||
cmu_divn3_sel = rtcl_divn3[RTL839X_PLL_CTRL1_CMU_DIVN3_SEL(ctrl1)];
|
||||
break;
|
||||
}
|
||||
div1 = cmu_divn2_selb ? cmu_divn3_sel : cmu_divn2;
|
||||
div2 = rtcl_xdiv[clk->idx];
|
||||
|
||||
return (((parent_rate / 16) * cmu_ncode_in) / (div1 * div2)) *
|
||||
cmu_sel_prediv * cmu_sel_div4 * 16;
|
||||
}
|
||||
|
||||
static int rtcl_838x_set_rate(int clk_idx, const struct rtcl_reg_set *reg)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
/*
|
||||
* Runtime of this function (including locking)
|
||||
* CPU: up to 14000 cycles / up to 56 us at 250 MHz (half default speed)
|
||||
*/
|
||||
spin_lock_irqsave(&rtcl_ccu->lock, irqflags);
|
||||
rtcl_838x_sram_set_rate(clk_idx, reg->ctrl0, reg->ctrl1);
|
||||
spin_unlock_irqrestore(&rtcl_ccu->lock, irqflags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtcl_839x_set_rate(int clk_idx, const struct rtcl_reg_set *reg)
|
||||
{
|
||||
unsigned long vpflags;
|
||||
unsigned long irqflags;
|
||||
/*
|
||||
* Runtime of this function (including locking)
|
||||
* CPU: up to 31000 cycles / up to 89 us at 350 MHz (half default speed)
|
||||
*/
|
||||
spin_lock_irqsave(&rtcl_ccu->lock, irqflags);
|
||||
vpflags = dvpe();
|
||||
rtcl_839x_sram_set_rate(clk_idx, reg->ctrl0, reg->ctrl1);
|
||||
evpe(vpflags);
|
||||
spin_unlock_irqrestore(&rtcl_ccu->lock, irqflags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtcl_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
|
||||
{
|
||||
int tab_idx;
|
||||
struct rtcl_clk *clk = rtcl_hw_to_clk(hw);
|
||||
const struct rtcl_rtab_set *rtab = &rtcl_rtab_set[rtcl_ccu->soc][clk->idx];
|
||||
const struct rtcl_round_set *round = &rtcl_round_set[rtcl_ccu->soc][clk->idx];
|
||||
|
||||
if ((parent_rate != OSC_RATE) || (!rtcl_ccu->sram.vbase))
|
||||
return -EINVAL;
|
||||
/*
|
||||
* Currently we do not know if SRAM is stable on these devices. Maybe someone changes memory in
|
||||
* this region and does not care about proper allocation. So check if something might go wrong.
|
||||
*/
|
||||
if (unlikely(*rtcl_ccu->sram.pmark != RTL_SRAM_MARKER)) {
|
||||
dev_err(&rtcl_ccu->pdev->dev, "SRAM code lost\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tab_idx = (rate - round->min) / round->step;
|
||||
if ((tab_idx < 0) || (tab_idx >= rtab->count) || (rtab->rset[tab_idx].rate != rate))
|
||||
return -EINVAL;
|
||||
|
||||
rtcl_ccu->clks[clk->idx].rate = rate;
|
||||
|
||||
switch (rtcl_ccu->soc) {
|
||||
case SOC_RTL838X:
|
||||
return rtcl_838x_set_rate(clk->idx, &rtab->rset[tab_idx]);
|
||||
case SOC_RTL839X:
|
||||
return rtcl_839x_set_rate(clk->idx, &rtab->rset[tab_idx]);
|
||||
}
|
||||
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static long rtcl_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate)
|
||||
{
|
||||
struct rtcl_clk *clk = rtcl_hw_to_clk(hw);
|
||||
unsigned long rrate = max(clk->min, min(clk->max, rate));
|
||||
const struct rtcl_round_set *round = &rtcl_round_set[rtcl_ccu->soc][clk->idx];
|
||||
|
||||
rrate = ((rrate + (round->step >> 1)) / round->step) * round->step;
|
||||
rrate -= (rrate > clk->max) ? round->step : 0;
|
||||
rrate += (rrate < clk->min) ? round->step : 0;
|
||||
|
||||
return rrate;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialization functions to register the CCU and its clocks
|
||||
*/
|
||||
|
||||
#define RTCL_SRAM_FUNC(SOC, PBASE, FN) ({ \
|
||||
rtcl_##SOC##_sram_##FN = ((void *)&rtcl_##SOC##_dram_##FN \
|
||||
- (void *)&rtcl_##SOC##_dram_start) \
|
||||
+ (void *)PBASE; })
|
||||
|
||||
static const struct clk_ops rtcl_clk_ops = {
|
||||
.set_rate = rtcl_set_rate,
|
||||
.round_rate = rtcl_round_rate,
|
||||
.recalc_rate = rtcl_recalc_rate,
|
||||
};
|
||||
|
||||
static int rtcl_ccu_create(struct device_node *np)
|
||||
{
|
||||
int soc;
|
||||
|
||||
if (of_device_is_compatible(np, "realtek,rtl8380-clock"))
|
||||
soc = SOC_RTL838X;
|
||||
else if (of_device_is_compatible(np, "realtek,rtl8390-clock"))
|
||||
soc = SOC_RTL839X;
|
||||
else
|
||||
return -ENXIO;
|
||||
|
||||
rtcl_ccu = kzalloc(sizeof(*rtcl_ccu), GFP_KERNEL);
|
||||
if (IS_ERR(rtcl_ccu))
|
||||
return -ENOMEM;
|
||||
|
||||
rtcl_ccu->np = np;
|
||||
rtcl_ccu->soc = soc;
|
||||
rtcl_ccu->dram.type = RTL_MC_MCR_DRAMTYPE(read_soc(RTL_MC_MCR));
|
||||
rtcl_ccu->dram.buswidth = RTL_MC_DCR_BUSWIDTH(read_soc(RTL_MC_DCR));
|
||||
spin_lock_init(&rtcl_ccu->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtcl_register_clkhw(int clk_idx)
|
||||
{
|
||||
int ret;
|
||||
struct clk *clk;
|
||||
struct clk_init_data hw_init = { };
|
||||
struct rtcl_clk *rclk = &rtcl_ccu->clks[clk_idx];
|
||||
struct clk_parent_data parent_data = { .fw_name = rtcl_clk_info[clk_idx].parent_name };
|
||||
|
||||
rclk->idx = clk_idx;
|
||||
rclk->hw.init = &hw_init;
|
||||
|
||||
hw_init.num_parents = 1;
|
||||
hw_init.ops = &rtcl_clk_ops;
|
||||
hw_init.parent_data = &parent_data;
|
||||
hw_init.name = rtcl_clk_info[clk_idx].name;
|
||||
|
||||
ret = of_clk_hw_register(rtcl_ccu->np, &rclk->hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_hw_register_clkdev(&rclk->hw, rtcl_clk_info[clk_idx].name, NULL);
|
||||
|
||||
clk = clk_get(NULL, rtcl_clk_info[clk_idx].name);
|
||||
rclk->startup = clk_get_rate(clk);
|
||||
clk_put(clk);
|
||||
|
||||
switch (clk_idx) {
|
||||
case CLK_CPU:
|
||||
rclk->min = rtcl_round_set[rtcl_ccu->soc][clk_idx].min;
|
||||
rclk->max = rtcl_round_set[rtcl_ccu->soc][clk_idx].max;
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* TODO: This driver supports PLL reclocking and nothing else. Additional required steps for non
|
||||
* CPU PLLs are missing. E.g. if we want to change memory clocks the right way we must adapt a lot
|
||||
* of other settings like MCR and DTRx timing registers (0xb80001000, 0xb8001008, ...) and initiate
|
||||
* a DLL reset so that hardware operates in the allowed limits. This is far too complex without
|
||||
* official support. Avoid this for now.
|
||||
*/
|
||||
rclk->min = rclk->max = rclk->startup;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk_hw *rtcl_get_clkhw(struct of_phandle_args *clkspec, void *prv)
|
||||
{
|
||||
unsigned int idx = clkspec->args[0];
|
||||
|
||||
if (idx >= CLK_COUNT) {
|
||||
pr_err("%s: Invalid index %u\n", __func__, idx);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return &rtcl_ccu->clks[idx].hw;
|
||||
}
|
||||
|
||||
static int rtcl_ccu_register_clocks(void)
|
||||
{
|
||||
int clk_idx, ret;
|
||||
|
||||
for (clk_idx = 0; clk_idx < CLK_COUNT; clk_idx++) {
|
||||
ret = rtcl_register_clkhw(clk_idx);
|
||||
if (ret) {
|
||||
pr_err("%s: Couldn't register %s clock\n",
|
||||
__func__, rtcl_clk_info[clk_idx].display_name);
|
||||
goto err_hw_unregister;
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_clk_add_hw_provider(rtcl_ccu->np, rtcl_get_clkhw, rtcl_ccu);
|
||||
if (ret) {
|
||||
pr_err("%s: Couldn't register clock provider of %s\n",
|
||||
__func__, of_node_full_name(rtcl_ccu->np));
|
||||
goto err_hw_unregister;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_hw_unregister:
|
||||
for (--clk_idx; clk_idx >= 0; --clk_idx)
|
||||
clk_hw_unregister(&rtcl_ccu->clks[clk_idx].hw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rtcl_init_sram(void)
|
||||
{
|
||||
struct gen_pool *sram_pool;
|
||||
phys_addr_t sram_pbase;
|
||||
unsigned long sram_vbase;
|
||||
struct device_node *node;
|
||||
struct platform_device *pdev = NULL;
|
||||
void *dram_start;
|
||||
int dram_size;
|
||||
const char *wrn = ", rate setting disabled.\n";
|
||||
|
||||
switch (rtcl_ccu->soc) {
|
||||
case SOC_RTL838X:
|
||||
dram_start = &rtcl_838x_dram_start;
|
||||
dram_size = rtcl_838x_dram_size;
|
||||
break;
|
||||
case SOC_RTL839X:
|
||||
dram_start = &rtcl_839x_dram_start;
|
||||
dram_size = rtcl_839x_dram_size;
|
||||
break;
|
||||
default:
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
for_each_compatible_node(node, NULL, "mmio-sram") {
|
||||
pdev = of_find_device_by_node(node);
|
||||
if (pdev) {
|
||||
of_node_put(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pdev) {
|
||||
dev_warn(&rtcl_ccu->pdev->dev, "no SRAM device found%s", wrn);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
sram_pool = gen_pool_get(&pdev->dev, NULL);
|
||||
if (!sram_pool) {
|
||||
dev_warn(&rtcl_ccu->pdev->dev, "SRAM pool unavailable%s", wrn);
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
sram_vbase = gen_pool_alloc(sram_pool, dram_size);
|
||||
if (!sram_vbase) {
|
||||
dev_warn(&rtcl_ccu->pdev->dev, "can not allocate SRAM%s", wrn);
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_vbase);
|
||||
memcpy((void *)sram_pbase, dram_start, dram_size);
|
||||
flush_icache_range((unsigned long)sram_pbase, (unsigned long)(sram_pbase + dram_size));
|
||||
|
||||
switch (rtcl_ccu->soc) {
|
||||
case SOC_RTL838X:
|
||||
RTCL_SRAM_FUNC(838x, sram_pbase, set_rate);
|
||||
break;
|
||||
case SOC_RTL839X:
|
||||
RTCL_SRAM_FUNC(839x, sram_pbase, set_rate);
|
||||
break;
|
||||
}
|
||||
|
||||
rtcl_ccu->sram.pmark = (int *)((void *)sram_pbase + (dram_size - 4));
|
||||
rtcl_ccu->sram.vbase = sram_vbase;
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_device:
|
||||
put_device(&pdev->dev);
|
||||
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
void rtcl_ccu_log_early(void)
|
||||
{
|
||||
int clk_idx;
|
||||
char meminfo[80], clkinfo[255], msg[255] = "rtl83xx-clk: initialized";
|
||||
|
||||
sprintf(meminfo, " (%d Bit DDR%d)", rtcl_ccu->dram.buswidth, rtcl_ccu->dram.type);
|
||||
for (clk_idx = 0; clk_idx < CLK_COUNT; clk_idx++) {
|
||||
sprintf(clkinfo, ", %s %lu MHz", rtcl_clk_info[clk_idx].display_name,
|
||||
rtcl_ccu->clks[clk_idx].startup / 1000000);
|
||||
if (clk_idx == CLK_MEM)
|
||||
strcat(clkinfo, meminfo);
|
||||
strcat(msg, clkinfo);
|
||||
}
|
||||
pr_info("%s\n", msg);
|
||||
}
|
||||
|
||||
void rtcl_ccu_log_late(void)
|
||||
{
|
||||
int clk_idx;
|
||||
struct rtcl_clk *rclk;
|
||||
bool overclock = false;
|
||||
char clkinfo[80], msg[255] = "rate setting enabled";
|
||||
|
||||
for (clk_idx = 0; clk_idx < CLK_COUNT; clk_idx++) {
|
||||
rclk = &rtcl_ccu->clks[clk_idx];
|
||||
overclock |= rclk->max > rclk->startup;
|
||||
sprintf(clkinfo, ", %s %lu-%lu MHz", rtcl_clk_info[clk_idx].display_name,
|
||||
rclk->min / 1000000, rclk->max / 1000000);
|
||||
strcat(msg, clkinfo);
|
||||
}
|
||||
if (overclock)
|
||||
strcat(msg, ", OVERCLOCK AT OWN RISK");
|
||||
|
||||
dev_info(&rtcl_ccu->pdev->dev, "%s\n", msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Early registration: This module provides core startup clocks that are needed for generic SOC
|
||||
* init and for further builtin devices (e.g. UART). Register asap via clock framework.
|
||||
*/
|
||||
|
||||
static void __init rtcl_probe_early(struct device_node *np)
|
||||
{
|
||||
if (rtcl_ccu_create(np))
|
||||
return;
|
||||
|
||||
if (rtcl_ccu_register_clocks())
|
||||
kfree(rtcl_ccu);
|
||||
else
|
||||
rtcl_ccu_log_early();
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE_DRIVER(rtl838x_clk, "realtek,rtl8380-clock", rtcl_probe_early);
|
||||
CLK_OF_DECLARE_DRIVER(rtl839x_clk, "realtek,rtl8390-clock", rtcl_probe_early);
|
||||
|
||||
/*
|
||||
* Late registration: Finally register as normal platform driver. At this point we can make use
|
||||
* of other modules like SRAM.
|
||||
*/
|
||||
|
||||
static const struct of_device_id rtcl_dt_ids[] = {
|
||||
{ .compatible = "realtek,rtl8380-clock" },
|
||||
{ .compatible = "realtek,rtl8390-clock" },
|
||||
{}
|
||||
};
|
||||
|
||||
static int rtcl_probe_late(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!rtcl_ccu) {
|
||||
dev_err(&pdev->dev, "early initialization not run");
|
||||
return -ENXIO;
|
||||
}
|
||||
rtcl_ccu->pdev = pdev;
|
||||
ret = rtcl_init_sram();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rtcl_ccu_log_late();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rtcl_platform_driver = {
|
||||
.driver = {
|
||||
.name = "rtl83xx-clk",
|
||||
.of_match_table = rtcl_dt_ids,
|
||||
},
|
||||
.probe = rtcl_probe_late,
|
||||
};
|
||||
|
||||
static int __init rtcl_init_subsys(void)
|
||||
{
|
||||
return platform_driver_register(&rtcl_platform_driver);
|
||||
}
|
||||
|
||||
/*
|
||||
* The driver does not know when SRAM module has finally loaded. With an arch_initcall() we might
|
||||
* overtake SRAM initialization. Be polite and give the system a little more time.
|
||||
*/
|
||||
|
||||
subsys_initcall(rtcl_init_subsys);
|
|
@ -0,0 +1,75 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Realtek RTL83XX clock headers
|
||||
* Copyright (C) 2022 Markus Stockhausen <markus.stockhausen@gmx.de>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Switch registers (e.g. PLL)
|
||||
*/
|
||||
|
||||
#define RTL_SW_CORE_BASE (0xbb000000)
|
||||
|
||||
#define RTL838X_PLL_GLB_CTRL (0x0fc0)
|
||||
#define RTL838X_PLL_CPU_CTRL0 (0x0fc4)
|
||||
#define RTL838X_PLL_CPU_CTRL1 (0x0fc8)
|
||||
#define RTL838X_PLL_LXB_CTRL0 (0x0fd0)
|
||||
#define RTL838X_PLL_LXB_CTRL1 (0x0fd4)
|
||||
#define RTL838X_PLL_MEM_CTRL0 (0x0fdc)
|
||||
#define RTL838X_PLL_MEM_CTRL1 (0x0fe0)
|
||||
|
||||
#define RTL839X_PLL_GLB_CTRL (0x0024)
|
||||
#define RTL839X_PLL_CPU_CTRL0 (0x0028)
|
||||
#define RTL839X_PLL_CPU_CTRL1 (0x002c)
|
||||
#define RTL839X_PLL_LXB_CTRL0 (0x0038)
|
||||
#define RTL839X_PLL_LXB_CTRL1 (0x003c)
|
||||
#define RTL839X_PLL_MEM_CTRL0 (0x0048)
|
||||
#define RTL839X_PLL_MEM_CTRL1 (0x004c)
|
||||
|
||||
#define RTL_PLL_CTRL0_CMU_SEL_PREDIV(v) (((v) >> 0) & 0x3)
|
||||
#define RTL_PLL_CTRL0_CMU_SEL_DIV4(v) (((v) >> 2) & 0x1)
|
||||
#define RTL_PLL_CTRL0_CMU_NCODE_IN(v) (((v) >> 4) & 0xff)
|
||||
#define RTL_PLL_CTRL0_CMU_DIVN2(v) (((v) >> 12) & 0xff)
|
||||
|
||||
#define RTL838X_GLB_CTRL_EN_CPU_PLL_MASK (1 << 0)
|
||||
#define RTL838X_GLB_CTRL_EN_LXB_PLL_MASK (1 << 1)
|
||||
#define RTL838X_GLB_CTRL_EN_MEM_PLL_MASK (1 << 2)
|
||||
#define RTL838X_GLB_CTRL_CPU_PLL_READY_MASK (1 << 8)
|
||||
#define RTL838X_GLB_CTRL_LXB_PLL_READY_MASK (1 << 9)
|
||||
#define RTL838X_GLB_CTRL_MEM_PLL_READY_MASK (1 << 10)
|
||||
#define RTL838X_GLB_CTRL_CPU_PLL_SC_MUX_MASK (1 << 12)
|
||||
|
||||
#define RTL838X_PLL_CTRL1_CMU_DIVN2_SELB(v) (((v) >> 26) & 0x1)
|
||||
#define RTL838X_PLL_CTRL1_CMU_DIVN3_SEL(v) (((v) >> 27) & 0x3)
|
||||
|
||||
#define RTL839X_GLB_CTRL_CPU_CLKSEL_MASK (1 << 11)
|
||||
#define RTL839X_GLB_CTRL_MEM_CLKSEL_MASK (1 << 12)
|
||||
#define RTL839X_GLB_CTRL_LXB_CLKSEL_MASK (1 << 13)
|
||||
|
||||
#define RTL839X_PLL_CTRL1_CMU_DIVN2_SELB(v) (((v) >> 2) & 0x1)
|
||||
#define RTL839X_PLL_CTRL1_CMU_DIVN3_SEL(v) (((v) >> 0) & 0x3)
|
||||
|
||||
/*
|
||||
* Core registers (e.g. memory controller)
|
||||
*/
|
||||
|
||||
#define RTL_SOC_BASE (0xB8000000)
|
||||
|
||||
#define RTL_MC_MCR (0x1000)
|
||||
#define RTL_MC_DCR (0x1004)
|
||||
#define RTL_MC_DTR0 (0x1008)
|
||||
#define RTL_MC_DTR1 (0x100c)
|
||||
#define RTL_MC_DTR2 (0x1010)
|
||||
#define RTL_MC_DMCR (0x101c)
|
||||
#define RTL_MC_DACCR (0x1500)
|
||||
#define RTL_MC_DCDR (0x1060)
|
||||
|
||||
#define RTL_MC_MCR_DRAMTYPE(v) ((((v) >> 28) & 0xf) + 1)
|
||||
#define RTL_MC_DCR_BUSWIDTH(v) (8 << (((v) >> 24) & 0xf))
|
||||
|
||||
/*
|
||||
* Other stuff
|
||||
*/
|
||||
|
||||
#define RTL_SRAM_MARKER (0x5eaf00d5)
|
||||
#define RTL_SRAM_BASE (0x9f000000)
|
|
@ -0,0 +1,299 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpuhotplug.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sched_clock.h>
|
||||
|
||||
#include "timer-of.h"
|
||||
|
||||
#define RTTM_DATA 0x0
|
||||
#define RTTM_CNT 0x4
|
||||
#define RTTM_CTRL 0x8
|
||||
#define RTTM_INT 0xc
|
||||
|
||||
#define RTTM_CTRL_ENABLE BIT(28)
|
||||
#define RTTM_INT_PENDING BIT(16)
|
||||
#define RTTM_INT_ENABLE BIT(20)
|
||||
|
||||
/*
|
||||
* The Otto platform provides multiple 28 bit timers/counters with the following
|
||||
* operating logic. If enabled the timer counts up. Per timer one can set a
|
||||
* maximum counter value as an end marker. If end marker is reached the timer
|
||||
* fires an interrupt. If the timer "overflows" by reaching the end marker or
|
||||
* by adding 1 to 0x0fffffff the counter is reset to 0. When this happens and
|
||||
* the timer is in operating mode COUNTER it stops. In mode TIMER it will
|
||||
* continue to count up.
|
||||
*/
|
||||
|
||||
#define RTTM_CTRL_COUNTER 0
|
||||
#define RTTM_CTRL_TIMER BIT(24)
|
||||
|
||||
#define RTTM_BIT_COUNT 28
|
||||
#define RTTM_MIN_DELTA 8
|
||||
#define RTTM_MAX_DELTA CLOCKSOURCE_MASK(28)
|
||||
|
||||
/*
|
||||
* Timers are derived from the LXB clock frequency. Usually this is a fixed
|
||||
* multiple of the 25 MHz oscillator. The 930X SOC is an exception from that.
|
||||
* Its LXB clock has only dividers and uses the switch PLL of 2.45 GHz as its
|
||||
* base. The only meaningful frequencies we can achieve from that are 175.000
|
||||
* MHz and 153.125 MHz. The greatest common divisor of all explained possible
|
||||
* speeds is 3125000. Pin the timers to this 3.125 MHz reference frequency.
|
||||
*/
|
||||
|
||||
#define RTTM_TICKS_PER_SEC 3125000
|
||||
|
||||
struct rttm_cs {
|
||||
struct timer_of to;
|
||||
struct clocksource cs;
|
||||
};
|
||||
|
||||
/*
|
||||
* Simple internal register functions
|
||||
*/
|
||||
|
||||
static inline void rttm_set_counter(void __iomem *base, unsigned int counter)
|
||||
{
|
||||
iowrite32(counter, base + RTTM_CNT);
|
||||
}
|
||||
|
||||
static inline unsigned int rttm_get_counter(void __iomem *base)
|
||||
{
|
||||
return ioread32(base + RTTM_CNT);
|
||||
}
|
||||
|
||||
static inline void rttm_set_period(void __iomem *base, unsigned int period)
|
||||
{
|
||||
iowrite32(period, base + RTTM_DATA);
|
||||
}
|
||||
|
||||
static inline void rttm_disable_timer(void __iomem *base)
|
||||
{
|
||||
iowrite32(0, base + RTTM_CTRL);
|
||||
}
|
||||
|
||||
static inline void rttm_enable_timer(void __iomem *base, u32 mode, u32 divisor)
|
||||
{
|
||||
iowrite32(RTTM_CTRL_ENABLE | mode | divisor, base + RTTM_CTRL);
|
||||
}
|
||||
|
||||
static inline void rttm_ack_irq(void __iomem *base)
|
||||
{
|
||||
iowrite32(ioread32(base + RTTM_INT) | RTTM_INT_PENDING, base + RTTM_INT);
|
||||
}
|
||||
|
||||
static inline void rttm_enable_irq(void __iomem *base)
|
||||
{
|
||||
iowrite32(RTTM_INT_ENABLE, base + RTTM_INT);
|
||||
}
|
||||
|
||||
static inline void rttm_disable_irq(void __iomem *base)
|
||||
{
|
||||
iowrite32(0, base + RTTM_INT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Aggregated control functions for kernel clock framework
|
||||
*/
|
||||
|
||||
#define RTTM_DEBUG(base) \
|
||||
pr_debug("------------- %s %d %08x\n", __func__, \
|
||||
smp_processor_id(), (u32)base)
|
||||
|
||||
static irqreturn_t rttm_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *clkevt = dev_id;
|
||||
struct timer_of *to = to_timer_of(clkevt);
|
||||
|
||||
rttm_ack_irq(to->of_base.base);
|
||||
RTTM_DEBUG(to->of_base.base);
|
||||
clkevt->event_handler(clkevt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void rttm_stop_timer(void __iomem *base)
|
||||
{
|
||||
rttm_disable_timer(base);
|
||||
rttm_ack_irq(base);
|
||||
}
|
||||
|
||||
static void rttm_start_timer(struct timer_of *to, u32 mode)
|
||||
{
|
||||
rttm_set_counter(to->of_base.base, 0);
|
||||
rttm_enable_timer(to->of_base.base, mode, to->of_clk.rate / RTTM_TICKS_PER_SEC);
|
||||
}
|
||||
|
||||
static int rttm_next_event(unsigned long delta, struct clock_event_device *clkevt)
|
||||
{
|
||||
struct timer_of *to = to_timer_of(clkevt);
|
||||
|
||||
RTTM_DEBUG(to->of_base.base);
|
||||
rttm_stop_timer(to->of_base.base);
|
||||
rttm_set_period(to->of_base.base, delta);
|
||||
rttm_start_timer(to, RTTM_CTRL_COUNTER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rttm_state_oneshot(struct clock_event_device *clkevt)
|
||||
{
|
||||
struct timer_of *to = to_timer_of(clkevt);
|
||||
|
||||
RTTM_DEBUG(to->of_base.base);
|
||||
rttm_stop_timer(to->of_base.base);
|
||||
rttm_set_period(to->of_base.base, RTTM_TICKS_PER_SEC / HZ);
|
||||
rttm_start_timer(to, RTTM_CTRL_COUNTER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rttm_state_periodic(struct clock_event_device *clkevt)
|
||||
{
|
||||
struct timer_of *to = to_timer_of(clkevt);
|
||||
|
||||
RTTM_DEBUG(to->of_base.base);
|
||||
rttm_stop_timer(to->of_base.base);
|
||||
rttm_set_period(to->of_base.base, RTTM_TICKS_PER_SEC / HZ);
|
||||
rttm_start_timer(to, RTTM_CTRL_TIMER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rttm_state_shutdown(struct clock_event_device *clkevt)
|
||||
{
|
||||
struct timer_of *to = to_timer_of(clkevt);
|
||||
|
||||
RTTM_DEBUG(to->of_base.base);
|
||||
rttm_stop_timer(to->of_base.base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rttm_setup_timer(void __iomem *base)
|
||||
{
|
||||
RTTM_DEBUG(base);
|
||||
rttm_stop_timer(base);
|
||||
rttm_set_period(base, 0);
|
||||
}
|
||||
|
||||
static u64 rttm_read_clocksource(struct clocksource *cs)
|
||||
{
|
||||
struct rttm_cs *rcs = container_of(cs, struct rttm_cs, cs);
|
||||
|
||||
return (u64)rttm_get_counter(rcs->to.of_base.base);
|
||||
}
|
||||
|
||||
/*
|
||||
* Module initialization part.
|
||||
*/
|
||||
|
||||
static DEFINE_PER_CPU(struct timer_of, rttm_to) = {
|
||||
.flags = TIMER_OF_BASE | TIMER_OF_CLOCK | TIMER_OF_IRQ,
|
||||
.of_irq = {
|
||||
.flags = IRQF_PERCPU | IRQF_TIMER,
|
||||
.handler = rttm_timer_interrupt,
|
||||
},
|
||||
.clkevt = {
|
||||
.rating = 400,
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_state_periodic = rttm_state_periodic,
|
||||
.set_state_shutdown = rttm_state_shutdown,
|
||||
.set_state_oneshot = rttm_state_oneshot,
|
||||
.set_next_event = rttm_next_event
|
||||
},
|
||||
};
|
||||
|
||||
static int rttm_enable_clocksource(struct clocksource *cs)
|
||||
{
|
||||
struct rttm_cs *rcs = container_of(cs, struct rttm_cs, cs);
|
||||
|
||||
rttm_disable_irq(rcs->to.of_base.base);
|
||||
rttm_setup_timer(rcs->to.of_base.base);
|
||||
rttm_enable_timer(rcs->to.of_base.base, RTTM_CTRL_TIMER,
|
||||
rcs->to.of_clk.rate / RTTM_TICKS_PER_SEC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct rttm_cs rttm_cs = {
|
||||
.to = {
|
||||
.flags = TIMER_OF_BASE | TIMER_OF_CLOCK,
|
||||
},
|
||||
.cs = {
|
||||
.name = "realtek_otto_timer",
|
||||
.rating = 400,
|
||||
.mask = CLOCKSOURCE_MASK(RTTM_BIT_COUNT),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
.read = rttm_read_clocksource,
|
||||
.enable = rttm_enable_clocksource
|
||||
}
|
||||
};
|
||||
|
||||
static u64 notrace rttm_read_clock(void)
|
||||
{
|
||||
return (u64)rttm_get_counter(rttm_cs.to.of_base.base);
|
||||
}
|
||||
|
||||
static int rttm_cpu_starting(unsigned int cpu)
|
||||
{
|
||||
struct timer_of *to = per_cpu_ptr(&rttm_to, cpu);
|
||||
|
||||
RTTM_DEBUG(to->of_base.base);
|
||||
to->clkevt.cpumask = cpumask_of(cpu);
|
||||
irq_set_affinity(to->of_irq.irq, to->clkevt.cpumask);
|
||||
clockevents_config_and_register(&to->clkevt, RTTM_TICKS_PER_SEC,
|
||||
RTTM_MIN_DELTA, RTTM_MAX_DELTA);
|
||||
rttm_enable_irq(to->of_base.base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init rttm_probe(struct device_node *np)
|
||||
{
|
||||
int cpu, cpu_rollback;
|
||||
struct timer_of *to;
|
||||
int clkidx = num_possible_cpus();
|
||||
/*
|
||||
* Use the first n timers as per CPU clock event generators
|
||||
*/
|
||||
for_each_possible_cpu(cpu) {
|
||||
to = per_cpu_ptr(&rttm_to, cpu);
|
||||
to->of_irq.index = to->of_base.index = cpu;
|
||||
if (timer_of_init(np, to)) {
|
||||
pr_err("%s: setup of timer %d failed\n", __func__, cpu);
|
||||
goto rollback;
|
||||
}
|
||||
rttm_setup_timer(to->of_base.base);
|
||||
}
|
||||
/*
|
||||
* Activate the n'th+1 timer as a stable CPU clocksource.
|
||||
*/
|
||||
to = &rttm_cs.to;
|
||||
to->of_base.index = clkidx;
|
||||
timer_of_init(np, to);
|
||||
if (rttm_cs.to.of_base.base && rttm_cs.to.of_clk.rate) {
|
||||
clocksource_register_hz(&rttm_cs.cs, RTTM_TICKS_PER_SEC);
|
||||
sched_clock_register(rttm_read_clock, RTTM_BIT_COUNT, RTTM_TICKS_PER_SEC);
|
||||
} else
|
||||
pr_err("%s: setup of timer %d as clocksoure failed", __func__, clkidx);
|
||||
|
||||
return cpuhp_setup_state(CPUHP_AP_REALTEK_TIMER_STARTING,
|
||||
"timer/realtek:online",
|
||||
rttm_cpu_starting, NULL);
|
||||
rollback:
|
||||
pr_err("%s: timer registration failed\n", __func__);
|
||||
for_each_possible_cpu(cpu_rollback) {
|
||||
if (cpu_rollback == cpu)
|
||||
break;
|
||||
to = per_cpu_ptr(&rttm_to, cpu_rollback);
|
||||
timer_of_cleanup(to);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
TIMER_OF_DECLARE(otto_timer, "realtek,otto-timer", rttm_probe);
|
355
target/linux/realtek/files-5.15/drivers/gpio/gpio-rtl8231.c
Normal file
355
target/linux/realtek/files-5.15/drivers/gpio/gpio-rtl8231.c
Normal file
|
@ -0,0 +1,355 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||
|
||||
/* RTL8231 registers for LED control */
|
||||
#define RTL8231_LED_FUNC0 0x0000
|
||||
#define RTL8231_LED_FUNC1 0x0001
|
||||
#define RTL8231_READY_MASK 0x03f0
|
||||
#define RTL8231_READY_VALUE 0x0370
|
||||
#define RTL8231_GPIO_PIN_SEL(gpio) ((0x0002) + ((gpio) >> 4))
|
||||
#define RTL8231_GPIO_DIR(gpio) ((0x0005) + ((gpio) >> 4))
|
||||
#define RTL8231_GPIO_DATA(gpio) ((0x001C) + ((gpio) >> 4))
|
||||
|
||||
#define USEC_TIMEOUT 5000
|
||||
|
||||
#define RTL8231_SMI_BUS_ID_MAX 0x1F
|
||||
|
||||
struct rtl8231_gpios {
|
||||
struct gpio_chip gc;
|
||||
struct device *dev;
|
||||
u32 id;
|
||||
u32 smi_bus_id;
|
||||
u16 reg_shadow[0x20];
|
||||
u32 reg_cached;
|
||||
int ext_gpio_indrt_access;
|
||||
};
|
||||
|
||||
extern struct rtl83xx_soc_info soc_info;
|
||||
|
||||
DEFINE_MUTEX(miim_lock);
|
||||
|
||||
static u32 rtl8231_read(struct rtl8231_gpios *gpios, u32 reg)
|
||||
{
|
||||
u32 t = 0, n = 0;
|
||||
|
||||
reg &= 0x1f;
|
||||
|
||||
/* Calculate read register address */
|
||||
t = (gpios->smi_bus_id << 2) | (reg << 7);
|
||||
|
||||
/* Set execution bit: cleared when operation completed */
|
||||
t |= 1;
|
||||
|
||||
// Start execution
|
||||
sw_w32(t, gpios->ext_gpio_indrt_access);
|
||||
do {
|
||||
udelay(1);
|
||||
t = sw_r32(gpios->ext_gpio_indrt_access);
|
||||
n++;
|
||||
} while ((t & 1) && (n < USEC_TIMEOUT));
|
||||
|
||||
if (n >= USEC_TIMEOUT)
|
||||
return 0x80000000;
|
||||
|
||||
pr_debug("%s: %x, %x, %x\n", __func__, gpios->smi_bus_id,
|
||||
reg, (t & 0xffff0000) >> 16);
|
||||
|
||||
return (t & 0xffff0000) >> 16;
|
||||
}
|
||||
|
||||
static int rtl8231_write(struct rtl8231_gpios *gpios, u32 reg, u32 data)
|
||||
{
|
||||
u32 t = 0, n = 0;
|
||||
|
||||
pr_debug("%s: %x, %x, %x\n", __func__, gpios->smi_bus_id, reg, data);
|
||||
reg &= 0x1f;
|
||||
|
||||
t = (gpios->smi_bus_id << 2) | (reg << 7) | (data << 16);
|
||||
/* Set write bit */
|
||||
t |= 2;
|
||||
|
||||
/* Set execution bit: cleared when operation completed */
|
||||
t |= 1;
|
||||
|
||||
// Start execution
|
||||
sw_w32(t, gpios->ext_gpio_indrt_access);
|
||||
do {
|
||||
udelay(1);
|
||||
t = sw_r32(gpios->ext_gpio_indrt_access);
|
||||
} while ((t & 1) && (n < USEC_TIMEOUT));
|
||||
|
||||
if (n >= USEC_TIMEOUT)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 rtl8231_read_cached(struct rtl8231_gpios *gpios, u32 reg)
|
||||
{
|
||||
if (reg > 0x1f)
|
||||
return 0;
|
||||
|
||||
if (gpios->reg_cached & (1 << reg))
|
||||
return gpios->reg_shadow[reg];
|
||||
|
||||
return rtl8231_read(gpios, reg);
|
||||
}
|
||||
|
||||
/* Set Direction of the RTL8231 pin:
|
||||
* dir 1: input
|
||||
* dir 0: output
|
||||
*/
|
||||
static int rtl8231_pin_dir(struct rtl8231_gpios *gpios, u32 gpio, u32 dir)
|
||||
{
|
||||
u32 v;
|
||||
int pin_sel_addr = RTL8231_GPIO_PIN_SEL(gpio);
|
||||
int pin_dir_addr = RTL8231_GPIO_DIR(gpio);
|
||||
int dpin = gpio % 16;
|
||||
|
||||
if (gpio > 31) {
|
||||
pr_debug("WARNING: HIGH pin\n");
|
||||
dpin += 5;
|
||||
pin_dir_addr = pin_sel_addr;
|
||||
}
|
||||
|
||||
v = rtl8231_read_cached(gpios, pin_dir_addr);
|
||||
if (v & 0x80000000) {
|
||||
pr_err("Error reading RTL8231\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
v = (v & ~(1 << dpin)) | (dir << dpin);
|
||||
rtl8231_write(gpios, pin_dir_addr, v);
|
||||
gpios->reg_shadow[pin_dir_addr] = v;
|
||||
gpios->reg_cached |= 1 << pin_dir_addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8231_pin_dir_get(struct rtl8231_gpios *gpios, u32 gpio, u32 *dir)
|
||||
{
|
||||
/* dir 1: input
|
||||
* dir 0: output
|
||||
*/
|
||||
|
||||
u32 v;
|
||||
int pin_dir_addr = RTL8231_GPIO_DIR(gpio);
|
||||
int pin = gpio % 16;
|
||||
|
||||
if (gpio > 31) {
|
||||
pin_dir_addr = RTL8231_GPIO_PIN_SEL(gpio);
|
||||
pin += 5;
|
||||
}
|
||||
|
||||
v = rtl8231_read(gpios, pin_dir_addr);
|
||||
if (v & (1 << pin))
|
||||
*dir = 1;
|
||||
else
|
||||
*dir = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8231_pin_set(struct rtl8231_gpios *gpios, u32 gpio, u32 data)
|
||||
{
|
||||
u32 v = rtl8231_read(gpios, RTL8231_GPIO_DATA(gpio));
|
||||
|
||||
pr_debug("%s: %d to %d\n", __func__, gpio, data);
|
||||
if (v & 0x80000000) {
|
||||
pr_err("Error reading RTL8231\n");
|
||||
return -1;
|
||||
}
|
||||
v = (v & ~(1 << (gpio % 16))) | (data << (gpio % 16));
|
||||
rtl8231_write(gpios, RTL8231_GPIO_DATA(gpio), v);
|
||||
gpios->reg_shadow[RTL8231_GPIO_DATA(gpio)] = v;
|
||||
gpios->reg_cached |= 1 << RTL8231_GPIO_DATA(gpio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8231_pin_get(struct rtl8231_gpios *gpios, u32 gpio, u16 *state)
|
||||
{
|
||||
u32 v = rtl8231_read(gpios, RTL8231_GPIO_DATA(gpio));
|
||||
|
||||
if (v & 0x80000000) {
|
||||
pr_err("Error reading RTL8231\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*state = v & 0xffff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8231_direction_input(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
int err;
|
||||
struct rtl8231_gpios *gpios = gpiochip_get_data(gc);
|
||||
|
||||
pr_debug("%s: %d\n", __func__, offset);
|
||||
mutex_lock(&miim_lock);
|
||||
err = rtl8231_pin_dir(gpios, offset, 1);
|
||||
mutex_unlock(&miim_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rtl8231_direction_output(struct gpio_chip *gc, unsigned int offset, int value)
|
||||
{
|
||||
int err;
|
||||
struct rtl8231_gpios *gpios = gpiochip_get_data(gc);
|
||||
|
||||
pr_debug("%s: %d\n", __func__, offset);
|
||||
mutex_lock(&miim_lock);
|
||||
err = rtl8231_pin_dir(gpios, offset, 0);
|
||||
mutex_unlock(&miim_lock);
|
||||
if (!err)
|
||||
err = rtl8231_pin_set(gpios, offset, value);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rtl8231_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
u32 v = 0;
|
||||
struct rtl8231_gpios *gpios = gpiochip_get_data(gc);
|
||||
|
||||
pr_debug("%s: %d\n", __func__, offset);
|
||||
mutex_lock(&miim_lock);
|
||||
rtl8231_pin_dir_get(gpios, offset, &v);
|
||||
mutex_unlock(&miim_lock);
|
||||
return v;
|
||||
}
|
||||
|
||||
static int rtl8231_gpio_get(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
u16 state = 0;
|
||||
struct rtl8231_gpios *gpios = gpiochip_get_data(gc);
|
||||
|
||||
mutex_lock(&miim_lock);
|
||||
rtl8231_pin_get(gpios, offset, &state);
|
||||
mutex_unlock(&miim_lock);
|
||||
if (state & (1 << (offset % 16)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtl8231_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
|
||||
{
|
||||
struct rtl8231_gpios *gpios = gpiochip_get_data(gc);
|
||||
|
||||
rtl8231_pin_set(gpios, offset, value);
|
||||
}
|
||||
|
||||
int rtl8231_init(struct rtl8231_gpios *gpios)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
pr_info("%s called, MDIO bus ID: %d\n", __func__, gpios->smi_bus_id);
|
||||
|
||||
gpios->reg_cached = 0;
|
||||
|
||||
if (soc_info.family == RTL8390_FAMILY_ID) {
|
||||
// RTL8390: Enable external gpio in global led control register
|
||||
sw_w32_mask(0x7 << 18, 0x4 << 18, RTL839X_LED_GLB_CTRL);
|
||||
} else if (soc_info.family == RTL8380_FAMILY_ID) {
|
||||
// RTL8380: Enable RTL8231 indirect access mode
|
||||
sw_w32_mask(0, 1, RTL838X_EXTRA_GPIO_CTRL);
|
||||
sw_w32_mask(3, 1, RTL838X_DMY_REG5);
|
||||
}
|
||||
|
||||
ret = rtl8231_read(gpios, RTL8231_LED_FUNC1);
|
||||
if ((ret & 0x80000000) || ((ret & RTL8231_READY_MASK) != RTL8231_READY_VALUE))
|
||||
return -ENXIO;
|
||||
|
||||
/* Select GPIO functionality and force input direction for pins 0-36 */
|
||||
rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(0), 0xffff);
|
||||
rtl8231_write(gpios, RTL8231_GPIO_DIR(0), 0xffff);
|
||||
rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(16), 0xffff);
|
||||
rtl8231_write(gpios, RTL8231_GPIO_DIR(16), 0xffff);
|
||||
rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(32), 0x03ff);
|
||||
|
||||
/* Set LED_Start to enable drivers for output mode */
|
||||
rtl8231_write(gpios, RTL8231_LED_FUNC0, 1 << 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rtl8231_gpio_of_match[] = {
|
||||
{ .compatible = "realtek,rtl8231-gpio" },
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, rtl8231_gpio_of_match);
|
||||
|
||||
static int rtl8231_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct rtl8231_gpios *gpios;
|
||||
int err;
|
||||
|
||||
pr_info("Probing RTL8231 GPIOs\n");
|
||||
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "No DT found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL);
|
||||
if (!gpios)
|
||||
return -ENOMEM;
|
||||
|
||||
gpios->id = soc_info.id;
|
||||
if (soc_info.family == RTL8380_FAMILY_ID) {
|
||||
gpios->ext_gpio_indrt_access = RTL838X_EXT_GPIO_INDRT_ACCESS;
|
||||
}
|
||||
|
||||
if (soc_info.family == RTL8390_FAMILY_ID) {
|
||||
gpios->ext_gpio_indrt_access = RTL839X_EXT_GPIO_INDRT_ACCESS;
|
||||
}
|
||||
|
||||
err = of_property_read_u32(np, "indirect-access-bus-id", &gpios->smi_bus_id);
|
||||
if (!err && gpios->smi_bus_id > RTL8231_SMI_BUS_ID_MAX)
|
||||
err = -EINVAL;
|
||||
|
||||
if (err) {
|
||||
dev_err(dev, "invalid or missing indirect-access-bus-id\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = rtl8231_init(gpios);
|
||||
if (err) {
|
||||
dev_err(dev, "no device found at bus address %d\n", gpios->smi_bus_id);
|
||||
return err;
|
||||
}
|
||||
|
||||
gpios->dev = dev;
|
||||
gpios->gc.base = -1;
|
||||
gpios->gc.ngpio = 37;
|
||||
gpios->gc.label = "rtl8231";
|
||||
gpios->gc.parent = dev;
|
||||
gpios->gc.owner = THIS_MODULE;
|
||||
gpios->gc.can_sleep = true;
|
||||
|
||||
gpios->gc.direction_input = rtl8231_direction_input;
|
||||
gpios->gc.direction_output = rtl8231_direction_output;
|
||||
gpios->gc.set = rtl8231_gpio_set;
|
||||
gpios->gc.get = rtl8231_gpio_get;
|
||||
gpios->gc.get_direction = rtl8231_get_direction;
|
||||
|
||||
err = devm_gpiochip_add_data(dev, &gpios->gc, gpios);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct platform_driver rtl8231_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "rtl8231-gpio",
|
||||
.of_match_table = rtl8231_gpio_of_match,
|
||||
},
|
||||
.probe = rtl8231_gpio_probe,
|
||||
};
|
||||
|
||||
module_platform_driver(rtl8231_gpio_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Realtek RTL8231 GPIO expansion chip support");
|
||||
MODULE_LICENSE("GPL v2");
|
488
target/linux/realtek/files-5.15/drivers/i2c/busses/i2c-rtl9300.c
Normal file
488
target/linux/realtek/files-5.15/drivers/i2c/busses/i2c-rtl9300.c
Normal file
|
@ -0,0 +1,488 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include "i2c-rtl9300.h"
|
||||
|
||||
#define REG(i, x) (i->base + x + (i->scl_num ? i->mst2_offset : 0))
|
||||
#define REG_MASK(i, clear, set, reg) \
|
||||
writel((readl(REG(i, reg)) & ~(clear)) | (set), REG(i, reg))
|
||||
|
||||
struct i2c_drv_data {
|
||||
int scl0_pin;
|
||||
int scl1_pin;
|
||||
int sda0_pin;
|
||||
struct i2c_algorithm *algo;
|
||||
int (*read)(struct rtl9300_i2c *i2c, u8 *buf, int len);
|
||||
int (*write)(struct rtl9300_i2c *i2c, u8 *buf, int len);
|
||||
void (*reg_addr_set)(struct rtl9300_i2c *i2c, u32 reg, u16 len);
|
||||
int (*config_xfer)(struct rtl9300_i2c *i2c, u16 addr, u16 len);
|
||||
int (*execute_xfer)(struct rtl9300_i2c *i2c, char read_write, int size,
|
||||
union i2c_smbus_data * data, int len);
|
||||
void (*writel)(struct rtl9300_i2c *i2c, u32 data);
|
||||
void (*config_io)(struct rtl9300_i2c *i2c, int scl_num, int sda_num);
|
||||
u32 mst2_offset;
|
||||
};
|
||||
|
||||
DEFINE_MUTEX(i2c_lock);
|
||||
|
||||
static void rtl9300_i2c_reg_addr_set(struct rtl9300_i2c *i2c, u32 reg, u16 len)
|
||||
{
|
||||
// Set register address width
|
||||
REG_MASK(i2c, 0x3 << RTL9300_I2C_CTRL2_MADDR_WIDTH, len << RTL9300_I2C_CTRL2_MADDR_WIDTH,
|
||||
RTL9300_I2C_CTRL2);
|
||||
|
||||
// Set register address
|
||||
REG_MASK(i2c, 0xffffff << RTL9300_I2C_CTRL1_MEM_ADDR, reg << RTL9300_I2C_CTRL1_MEM_ADDR,
|
||||
RTL9300_I2C_CTRL1);
|
||||
}
|
||||
|
||||
static void rtl9310_i2c_reg_addr_set(struct rtl9300_i2c *i2c, u32 reg, u16 len)
|
||||
{
|
||||
// Set register address width
|
||||
REG_MASK(i2c, 0x3 << RTL9310_I2C_CTRL_MADDR_WIDTH, len << RTL9310_I2C_CTRL_MADDR_WIDTH,
|
||||
RTL9310_I2C_CTRL);
|
||||
|
||||
// Set register address
|
||||
writel(reg, REG(i2c, RTL9310_I2C_MEMADDR));
|
||||
}
|
||||
|
||||
static void rtl9300_i2c_config_io(struct rtl9300_i2c *i2c, int scl_num, int sda_num)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
// Set SCL pin
|
||||
REG_MASK(i2c, 0, BIT(RTL9300_I2C_CTRL1_GPIO8_SCL_SEL), RTL9300_I2C_CTRL1);
|
||||
|
||||
// Set SDA pin
|
||||
REG_MASK(i2c, 0x7 << RTL9300_I2C_CTRL1_SDA_OUT_SEL,
|
||||
i2c->sda_num << RTL9300_I2C_CTRL1_SDA_OUT_SEL, RTL9300_I2C_CTRL1);
|
||||
|
||||
// Set SDA pin to I2C functionality
|
||||
v = readl(i2c->base + RTL9300_I2C_MST_GLB_CTRL);
|
||||
v |= BIT(i2c->sda_num);
|
||||
writel(v, i2c->base + RTL9300_I2C_MST_GLB_CTRL);
|
||||
}
|
||||
|
||||
static void rtl9310_i2c_config_io(struct rtl9300_i2c *i2c, int scl_num, int sda_num)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
// Set SCL pin
|
||||
REG_MASK(i2c, 0, BIT(RTL9310_I2C_MST_IF_SEL_GPIO_SCL_SEL + scl_num), RTL9310_I2C_MST_IF_SEL);
|
||||
|
||||
// Set SDA pin
|
||||
REG_MASK(i2c, 0x7 << RTL9310_I2C_CTRL_SDA_OUT_SEL,
|
||||
i2c->sda_num << RTL9310_I2C_CTRL_SDA_OUT_SEL, RTL9310_I2C_CTRL);
|
||||
|
||||
// Set SDA pin to I2C functionality
|
||||
v = readl(i2c->base + RTL9310_I2C_MST_IF_SEL);
|
||||
v |= BIT(i2c->sda_num);
|
||||
writel(v, i2c->base + RTL9310_I2C_MST_IF_SEL);
|
||||
}
|
||||
|
||||
static int rtl9300_i2c_config_xfer(struct rtl9300_i2c *i2c, u16 addr, u16 len)
|
||||
{
|
||||
// Set bus frequency
|
||||
REG_MASK(i2c, 0x3 << RTL9300_I2C_CTRL2_SCL_FREQ,
|
||||
i2c->bus_freq << RTL9300_I2C_CTRL2_SCL_FREQ, RTL9300_I2C_CTRL2);
|
||||
|
||||
// Set slave device address
|
||||
REG_MASK(i2c, 0x7f << RTL9300_I2C_CTRL2_DEV_ADDR,
|
||||
addr << RTL9300_I2C_CTRL2_DEV_ADDR, RTL9300_I2C_CTRL2);
|
||||
|
||||
// Set data length
|
||||
REG_MASK(i2c, 0xf << RTL9300_I2C_CTRL2_DATA_WIDTH,
|
||||
((len - 1) & 0xf) << RTL9300_I2C_CTRL2_DATA_WIDTH, RTL9300_I2C_CTRL2);
|
||||
|
||||
// Set read mode to random
|
||||
REG_MASK(i2c, 0x1 << RTL9300_I2C_CTRL2_READ_MODE, 0, RTL9300_I2C_CTRL2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9310_i2c_config_xfer(struct rtl9300_i2c *i2c, u16 addr, u16 len)
|
||||
{
|
||||
// Set bus frequency
|
||||
REG_MASK(i2c, 0x3 << RTL9310_I2C_CTRL_SCL_FREQ,
|
||||
i2c->bus_freq << RTL9310_I2C_CTRL_SCL_FREQ, RTL9310_I2C_CTRL);
|
||||
|
||||
// Set slave device address
|
||||
REG_MASK(i2c, 0x7f << RTL9310_I2C_CTRL_DEV_ADDR,
|
||||
addr << RTL9310_I2C_CTRL_DEV_ADDR, RTL9310_I2C_CTRL);
|
||||
|
||||
// Set data length
|
||||
REG_MASK(i2c, 0xf << RTL9310_I2C_CTRL_DATA_WIDTH,
|
||||
((len - 1) & 0xf) << RTL9310_I2C_CTRL_DATA_WIDTH, RTL9310_I2C_CTRL);
|
||||
|
||||
// Set read mode to random
|
||||
REG_MASK(i2c, 0x1 << RTL9310_I2C_CTRL_READ_MODE, 0, RTL9310_I2C_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_read(void __iomem *r0, u8 *buf, int len)
|
||||
{
|
||||
int i;
|
||||
u32 v;
|
||||
|
||||
if (len > 16)
|
||||
return -EIO;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i % 4 == 0)
|
||||
v = readl(r0 + i);
|
||||
buf[i] = v;
|
||||
v >>= 8;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int i2c_write(void __iomem *r0, u8 *buf, int len)
|
||||
{
|
||||
u32 v;
|
||||
int i;
|
||||
|
||||
if (len > 16)
|
||||
return -EIO;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (! (i % 4))
|
||||
v = 0;
|
||||
v <<= 8;
|
||||
v |= buf[i];
|
||||
if (i % 4 == 3 || i == len - 1)
|
||||
writel(v, r0 + (i / 4) * 4);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int rtl9300_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, int len)
|
||||
{
|
||||
return i2c_read(REG(i2c, RTL9300_I2C_DATA_WORD0), buf, len);
|
||||
}
|
||||
|
||||
static int rtl9300_i2c_write(struct rtl9300_i2c *i2c, u8 *buf, int len)
|
||||
{
|
||||
return i2c_write(REG(i2c, RTL9300_I2C_DATA_WORD0), buf, len);
|
||||
}
|
||||
|
||||
static int rtl9310_i2c_read(struct rtl9300_i2c *i2c, u8 *buf, int len)
|
||||
{
|
||||
return i2c_read(REG(i2c, RTL9310_I2C_DATA), buf, len);
|
||||
}
|
||||
|
||||
static int rtl9310_i2c_write(struct rtl9300_i2c *i2c, u8 *buf, int len)
|
||||
{
|
||||
return i2c_write(REG(i2c, RTL9310_I2C_DATA), buf, len);
|
||||
}
|
||||
|
||||
static void rtl9300_writel(struct rtl9300_i2c *i2c, u32 data)
|
||||
{
|
||||
writel(data, REG(i2c, RTL9300_I2C_DATA_WORD0));
|
||||
}
|
||||
|
||||
static void rtl9310_writel(struct rtl9300_i2c *i2c, u32 data)
|
||||
{
|
||||
writel(data, REG(i2c, RTL9310_I2C_DATA));
|
||||
}
|
||||
|
||||
|
||||
static int rtl9300_execute_xfer(struct rtl9300_i2c *i2c, char read_write,
|
||||
int size, union i2c_smbus_data * data, int len)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
if (read_write == I2C_SMBUS_READ)
|
||||
REG_MASK(i2c, BIT(RTL9300_I2C_CTRL1_RWOP), 0, RTL9300_I2C_CTRL1);
|
||||
else
|
||||
REG_MASK(i2c, 0, BIT(RTL9300_I2C_CTRL1_RWOP), RTL9300_I2C_CTRL1);
|
||||
|
||||
REG_MASK(i2c, 0, BIT(RTL9300_I2C_CTRL1_I2C_TRIG), RTL9300_I2C_CTRL1);
|
||||
do {
|
||||
v = readl(REG(i2c, RTL9300_I2C_CTRL1));
|
||||
} while (v & BIT(RTL9300_I2C_CTRL1_I2C_TRIG));
|
||||
|
||||
if (v & BIT(RTL9300_I2C_CTRL1_I2C_FAIL))
|
||||
return -EIO;
|
||||
|
||||
if (read_write == I2C_SMBUS_READ) {
|
||||
if (size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA){
|
||||
data->byte = readl(REG(i2c, RTL9300_I2C_DATA_WORD0));
|
||||
} else if (size == I2C_SMBUS_WORD_DATA) {
|
||||
data->word = readl(REG(i2c, RTL9300_I2C_DATA_WORD0));
|
||||
} else if (len > 0) {
|
||||
rtl9300_i2c_read(i2c, &data->block[0], len);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9310_execute_xfer(struct rtl9300_i2c *i2c, char read_write,
|
||||
int size, union i2c_smbus_data * data, int len)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
if (read_write == I2C_SMBUS_READ)
|
||||
REG_MASK(i2c, BIT(RTL9310_I2C_CTRL_RWOP), 0, RTL9310_I2C_CTRL);
|
||||
else
|
||||
REG_MASK(i2c, 0, BIT(RTL9310_I2C_CTRL_RWOP), RTL9310_I2C_CTRL);
|
||||
|
||||
REG_MASK(i2c, 0, BIT(RTL9310_I2C_CTRL_I2C_TRIG), RTL9310_I2C_CTRL);
|
||||
do {
|
||||
v = readl(REG(i2c, RTL9310_I2C_CTRL));
|
||||
} while (v & BIT(RTL9310_I2C_CTRL_I2C_TRIG));
|
||||
|
||||
if (v & BIT(RTL9310_I2C_CTRL_I2C_FAIL))
|
||||
return -EIO;
|
||||
|
||||
if (read_write == I2C_SMBUS_READ) {
|
||||
if (size == I2C_SMBUS_BYTE || size == I2C_SMBUS_BYTE_DATA){
|
||||
data->byte = readl(REG(i2c, RTL9310_I2C_DATA));
|
||||
} else if (size == I2C_SMBUS_WORD_DATA) {
|
||||
data->word = readl(REG(i2c, RTL9310_I2C_DATA));
|
||||
} else if (len > 0) {
|
||||
rtl9310_i2c_read(i2c, &data->block[0], len);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9300_i2c_smbus_xfer(struct i2c_adapter * adap, u16 addr,
|
||||
unsigned short flags, char read_write,
|
||||
u8 command, int size, union i2c_smbus_data * data)
|
||||
{
|
||||
struct rtl9300_i2c *i2c = i2c_get_adapdata(adap);
|
||||
struct i2c_drv_data *drv_data = (struct i2c_drv_data *)device_get_match_data(i2c->dev);
|
||||
int len = 0, ret;
|
||||
|
||||
mutex_lock(&i2c_lock);
|
||||
switch (size) {
|
||||
case I2C_SMBUS_QUICK:
|
||||
drv_data->config_xfer(i2c, addr, 0);
|
||||
drv_data->reg_addr_set(i2c, 0, 0);
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BYTE:
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
drv_data->config_xfer(i2c, addr, 0);
|
||||
drv_data->reg_addr_set(i2c, command, 1);
|
||||
} else {
|
||||
drv_data->config_xfer(i2c, addr, 1);
|
||||
drv_data->reg_addr_set(i2c, 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
pr_debug("I2C_SMBUS_BYTE_DATA %02x, read %d cmd %02x\n", addr, read_write, command);
|
||||
drv_data->reg_addr_set(i2c, command, 1);
|
||||
drv_data->config_xfer(i2c, addr, 1);
|
||||
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
pr_debug("--> data %02x\n", data->byte);
|
||||
drv_data->writel(i2c, data->byte);
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
pr_debug("I2C_SMBUS_WORD %02x, read %d\n", addr, read_write);
|
||||
drv_data->reg_addr_set(i2c, command, 1);
|
||||
drv_data->config_xfer(i2c, addr, 2);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
drv_data->writel(i2c, data->word);
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
pr_debug("I2C_SMBUS_BLOCK_DATA %02x, read %d, len %d\n",
|
||||
addr, read_write, data->block[0]);
|
||||
drv_data->reg_addr_set(i2c, command, 1);
|
||||
drv_data->config_xfer(i2c, addr, data->block[0]);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
drv_data->write(i2c, &data->block[1], data->block[0]);
|
||||
len = data->block[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = drv_data->execute_xfer(i2c, read_write, size, data, len);
|
||||
|
||||
mutex_unlock(&i2c_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 rtl9300_i2c_func(struct i2c_adapter *a)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm rtl9300_i2c_algo = {
|
||||
.smbus_xfer = rtl9300_i2c_smbus_xfer,
|
||||
.functionality = rtl9300_i2c_func,
|
||||
};
|
||||
|
||||
struct i2c_adapter_quirks rtl9300_i2c_quirks = {
|
||||
.flags = I2C_AQ_NO_CLK_STRETCH,
|
||||
.max_read_len = 16,
|
||||
.max_write_len = 16,
|
||||
};
|
||||
|
||||
static int rtl9300_i2c_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct rtl9300_i2c *i2c;
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_drv_data *drv_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
u32 clock_freq, pin;
|
||||
int ret = 0;
|
||||
|
||||
pr_info("%s probing I2C adapter\n", __func__);
|
||||
|
||||
if (!node) {
|
||||
dev_err(i2c->dev, "No DT found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
drv_data = (struct i2c_drv_data *) device_get_match_data(&pdev->dev);
|
||||
|
||||
i2c = devm_kzalloc(&pdev->dev, sizeof(struct rtl9300_i2c), GFP_KERNEL);
|
||||
if (!i2c)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
i2c->mst2_offset = drv_data->mst2_offset;
|
||||
if (IS_ERR(i2c->base))
|
||||
return PTR_ERR(i2c->base);
|
||||
|
||||
pr_debug("%s base memory %08x\n", __func__, (u32)i2c->base);
|
||||
i2c->dev = &pdev->dev;
|
||||
|
||||
if (of_property_read_u32(node, "clock-frequency", &clock_freq)) {
|
||||
clock_freq = I2C_MAX_STANDARD_MODE_FREQ;
|
||||
}
|
||||
switch(clock_freq) {
|
||||
case I2C_MAX_STANDARD_MODE_FREQ:
|
||||
i2c->bus_freq = RTL9300_I2C_STD_FREQ;
|
||||
break;
|
||||
|
||||
case I2C_MAX_FAST_MODE_FREQ:
|
||||
i2c->bus_freq = RTL9300_I2C_FAST_FREQ;
|
||||
break;
|
||||
default:
|
||||
dev_warn(i2c->dev, "clock-frequency %d not supported\n", clock_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "SCL speed %d, mode is %d\n", clock_freq, i2c->bus_freq);
|
||||
|
||||
if (of_property_read_u32(node, "scl-pin", &pin)) {
|
||||
dev_warn(i2c->dev, "SCL pin not found in DT, using default\n");
|
||||
pin = drv_data->scl0_pin;
|
||||
}
|
||||
if (!(pin == drv_data->scl0_pin || pin == drv_data->scl1_pin)) {
|
||||
dev_warn(i2c->dev, "SCL pin %d not supported\n", pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
i2c->scl_num = pin == drv_data->scl0_pin ? 0 : 1;
|
||||
pr_info("%s scl_num %d\n", __func__, i2c->scl_num);
|
||||
|
||||
if (of_property_read_u32(node, "sda-pin", &pin)) {
|
||||
dev_warn(i2c->dev, "SDA pin not found in DT, using default \n");
|
||||
pin = drv_data->sda0_pin;
|
||||
}
|
||||
i2c->sda_num = pin - drv_data->sda0_pin;
|
||||
if (i2c->sda_num < 0 || i2c->sda_num > 7) {
|
||||
dev_warn(i2c->dev, "SDA pin %d not supported\n", pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
pr_info("%s sda_num %d\n", __func__, i2c->sda_num);
|
||||
|
||||
adap = &i2c->adap;
|
||||
adap->owner = THIS_MODULE;
|
||||
adap->algo = &rtl9300_i2c_algo;
|
||||
adap->retries = 3;
|
||||
adap->dev.parent = &pdev->dev;
|
||||
i2c_set_adapdata(adap, i2c);
|
||||
adap->dev.of_node = node;
|
||||
strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
|
||||
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
|
||||
drv_data->config_io(i2c, i2c->scl_num, i2c->sda_num);
|
||||
|
||||
ret = i2c_add_adapter(adap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtl9300_i2c_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rtl9300_i2c *i2c = platform_get_drvdata(pdev);
|
||||
|
||||
i2c_del_adapter(&i2c->adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct i2c_drv_data rtl9300_i2c_drv_data = {
|
||||
.scl0_pin = 8,
|
||||
.scl1_pin = 17,
|
||||
.sda0_pin = 9,
|
||||
.read = rtl9300_i2c_read,
|
||||
.read = rtl9300_i2c_write,
|
||||
.reg_addr_set = rtl9300_i2c_reg_addr_set,
|
||||
.config_xfer = rtl9300_i2c_config_xfer,
|
||||
.execute_xfer = rtl9300_execute_xfer,
|
||||
.writel = rtl9300_writel,
|
||||
.config_io = rtl9300_i2c_config_io,
|
||||
.mst2_offset = 0x1c,
|
||||
};
|
||||
|
||||
struct i2c_drv_data rtl9310_i2c_drv_data = {
|
||||
.scl0_pin = 13,
|
||||
.scl1_pin = 14,
|
||||
.sda0_pin = 0,
|
||||
.read = rtl9310_i2c_read,
|
||||
.read = rtl9310_i2c_write,
|
||||
.reg_addr_set = rtl9310_i2c_reg_addr_set,
|
||||
.config_xfer = rtl9310_i2c_config_xfer,
|
||||
.execute_xfer = rtl9310_execute_xfer,
|
||||
.writel = rtl9310_writel,
|
||||
.config_io = rtl9310_i2c_config_io,
|
||||
.mst2_offset = 0x18,
|
||||
};
|
||||
|
||||
static const struct of_device_id i2c_rtl9300_dt_ids[] = {
|
||||
{ .compatible = "realtek,rtl9300-i2c", .data = (void *) &rtl9300_i2c_drv_data },
|
||||
{ .compatible = "realtek,rtl9310-i2c", .data = (void *) &rtl9310_i2c_drv_data },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rtl838x_eth_of_ids);
|
||||
|
||||
static struct platform_driver rtl9300_i2c_driver = {
|
||||
.probe = rtl9300_i2c_probe,
|
||||
.remove = rtl9300_i2c_remove,
|
||||
.driver = {
|
||||
.name = "i2c-rtl9300",
|
||||
.pm = NULL,
|
||||
.of_match_table = i2c_rtl9300_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(rtl9300_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Birger Koblitz");
|
||||
MODULE_DESCRIPTION("RTL9300 I2C host driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef I2C_RTL9300_H
|
||||
#define I2C_RTL9300_H
|
||||
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#define RTL9300_I2C_CTRL1 0x00
|
||||
#define RTL9300_I2C_CTRL1_MEM_ADDR 8
|
||||
#define RTL9300_I2C_CTRL1_SDA_OUT_SEL 4
|
||||
#define RTL9300_I2C_CTRL1_GPIO8_SCL_SEL 3
|
||||
#define RTL9300_I2C_CTRL1_RWOP 2
|
||||
#define RTL9300_I2C_CTRL1_I2C_FAIL 1
|
||||
#define RTL9300_I2C_CTRL1_I2C_TRIG 0
|
||||
|
||||
#define RTL9300_I2C_CTRL2 0x04
|
||||
#define RTL9300_I2C_CTRL2_DRIVE_ACK_DELAY 20
|
||||
#define RTL9300_I2C_CTRL2_CHECK_ACK_DELAY 16
|
||||
#define RTL9300_I2C_CTRL2_READ_MODE 15
|
||||
#define RTL9300_I2C_CTRL2_DEV_ADDR 8
|
||||
#define RTL9300_I2C_CTRL2_DATA_WIDTH 4
|
||||
#define RTL9300_I2C_CTRL2_MADDR_WIDTH 2
|
||||
#define RTL9300_I2C_CTRL2_SCL_FREQ 0
|
||||
|
||||
#define RTL9300_I2C_DATA_WORD0 0x08
|
||||
|
||||
#define RTL9300_I2C_MST_GLB_CTRL 0x18
|
||||
|
||||
#define RTL9310_I2C_MST_IF_CTRL 0x00
|
||||
|
||||
#define RTL9310_I2C_MST_IF_SEL 0x04
|
||||
#define RTL9310_I2C_MST_IF_SEL_GPIO_SCL_SEL 12
|
||||
|
||||
#define RTL9310_I2C_CTRL 0x08
|
||||
#define RTL9310_I2C_CTRL_SCL_FREQ 30
|
||||
#define RTL9310_I2C_CTRL_CHECK_ACK_DELAY 26
|
||||
#define RTL9310_I2C_CTRL_DRIVE_ACK_DELAY 22
|
||||
#define RTL9310_I2C_CTRL_SDA_OUT_SEL 18
|
||||
#define RTL9310_I2C_CTRL_DEV_ADDR 11
|
||||
#define RTL9310_I2C_CTRL_MADDR_WIDTH 9
|
||||
#define RTL9310_I2C_CTRL_DATA_WIDTH 5
|
||||
#define RTL9310_I2C_CTRL_READ_MODE 4
|
||||
#define RTL9310_I2C_CTRL_RWOP 2
|
||||
#define RTL9310_I2C_CTRL_I2C_FAIL 1
|
||||
#define RTL9310_I2C_CTRL_I2C_TRIG 0
|
||||
|
||||
#define RTL9310_I2C_MEMADDR 0x0c
|
||||
|
||||
#define RTL9310_I2C_DATA 0x10
|
||||
|
||||
#define RTL9300_I2C_STD_FREQ 0
|
||||
#define RTL9300_I2C_FAST_FREQ 1
|
||||
|
||||
struct rtl9300_i2c {
|
||||
void __iomem *base;
|
||||
u32 mst2_offset;
|
||||
struct device *dev;
|
||||
struct i2c_adapter adap;
|
||||
u8 bus_freq;
|
||||
u8 sda_num; // SDA channel number
|
||||
u8 scl_num; // SCL channel, mapping to master 1 or 2
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,293 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* I2C multiplexer for the 2 I2C Masters of the RTL9300
|
||||
* with up to 8 channels each, but which are not entirely
|
||||
* independent of each other
|
||||
*/
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mux/consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "../busses/i2c-rtl9300.h"
|
||||
|
||||
#define NUM_MASTERS 2
|
||||
#define NUM_BUSSES 8
|
||||
|
||||
#define REG(mst, x) (mux->base + x + (mst ? mux->i2c->mst2_offset : 0))
|
||||
#define REG_MASK(mst, clear, set, reg) \
|
||||
writel((readl(REG((mst),(reg))) & ~(clear)) | (set), REG((mst),(reg)))
|
||||
|
||||
struct channel {
|
||||
u8 sda_num;
|
||||
u8 scl_num;
|
||||
};
|
||||
|
||||
static struct channel channels[NUM_MASTERS * NUM_BUSSES];
|
||||
|
||||
struct rtl9300_mux {
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct i2c_adapter *parent;
|
||||
struct rtl9300_i2c * i2c;
|
||||
};
|
||||
|
||||
struct i2c_mux_data {
|
||||
int scl0_pin;
|
||||
int scl1_pin;
|
||||
int sda0_pin;
|
||||
int sda_pins;
|
||||
int (*i2c_mux_select)(struct i2c_mux_core *muxc, u32 chan);
|
||||
int (*i2c_mux_deselect)(struct i2c_mux_core *muxc, u32 chan);
|
||||
void (*sda_sel)(struct i2c_mux_core *muxc, int pin);
|
||||
};
|
||||
|
||||
static int rtl9300_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
struct rtl9300_mux *mux = i2c_mux_priv(muxc);
|
||||
|
||||
// Set SCL pin
|
||||
REG_MASK(channels[chan].scl_num, 0,
|
||||
BIT(RTL9300_I2C_CTRL1_GPIO8_SCL_SEL), RTL9300_I2C_CTRL1);
|
||||
|
||||
// Set SDA pin
|
||||
REG_MASK(channels[chan].scl_num, 0x7 << RTL9300_I2C_CTRL1_SDA_OUT_SEL,
|
||||
channels[chan].sda_num << RTL9300_I2C_CTRL1_SDA_OUT_SEL, RTL9300_I2C_CTRL1);
|
||||
|
||||
mux->i2c->sda_num = channels[chan].sda_num;
|
||||
mux->i2c->scl_num = channels[chan].scl_num;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9310_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
struct rtl9300_mux *mux = i2c_mux_priv(muxc);
|
||||
|
||||
// Set SCL pin
|
||||
REG_MASK(0, 0, BIT(RTL9310_I2C_MST_IF_SEL_GPIO_SCL_SEL + channels[chan].scl_num),
|
||||
RTL9310_I2C_MST_IF_SEL);
|
||||
|
||||
// Set SDA pin
|
||||
REG_MASK(channels[chan].scl_num, 0xf << RTL9310_I2C_CTRL_SDA_OUT_SEL,
|
||||
channels[chan].sda_num << RTL9310_I2C_CTRL_SDA_OUT_SEL, RTL9310_I2C_CTRL);
|
||||
|
||||
mux->i2c->sda_num = channels[chan].sda_num;
|
||||
mux->i2c->scl_num = channels[chan].scl_num;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9300_i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl9300_sda_sel(struct i2c_mux_core *muxc, int pin)
|
||||
{
|
||||
struct rtl9300_mux *mux = i2c_mux_priv(muxc);
|
||||
u32 v;
|
||||
|
||||
// Set SDA pin to I2C functionality
|
||||
v = readl(REG(0, RTL9300_I2C_MST_GLB_CTRL));
|
||||
v |= BIT(pin);
|
||||
writel(v, REG(0, RTL9300_I2C_MST_GLB_CTRL));
|
||||
}
|
||||
|
||||
static void rtl9310_sda_sel(struct i2c_mux_core *muxc, int pin)
|
||||
{
|
||||
struct rtl9300_mux *mux = i2c_mux_priv(muxc);
|
||||
u32 v;
|
||||
|
||||
// Set SDA pin to I2C functionality
|
||||
v = readl(REG(0, RTL9310_I2C_MST_IF_SEL));
|
||||
v |= BIT(pin);
|
||||
writel(v, REG(0, RTL9310_I2C_MST_IF_SEL));
|
||||
}
|
||||
|
||||
static struct device_node *mux_parent_adapter(struct device *dev, struct rtl9300_mux *mux)
|
||||
{
|
||||
struct device_node *node = dev->of_node;
|
||||
struct device_node *parent_np;
|
||||
struct i2c_adapter *parent;
|
||||
|
||||
parent_np = of_parse_phandle(node, "i2c-parent", 0);
|
||||
if (!parent_np) {
|
||||
dev_err(dev, "Cannot parse i2c-parent\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
parent = of_find_i2c_adapter_by_node(parent_np);
|
||||
of_node_put(parent_np);
|
||||
if (!parent)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
if (!(of_device_is_compatible(parent_np, "realtek,rtl9300-i2c")
|
||||
|| of_device_is_compatible(parent_np, "realtek,rtl9310-i2c"))){
|
||||
dev_err(dev, "I2C parent not an RTL9300 I2C controller\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
mux->parent = parent;
|
||||
mux->i2c = (struct rtl9300_i2c *)i2c_get_adapdata(parent);
|
||||
mux->base = mux->i2c->base;
|
||||
|
||||
return parent_np;
|
||||
}
|
||||
|
||||
struct i2c_mux_data rtl9300_i2c_mux_data = {
|
||||
.scl0_pin = 8,
|
||||
.scl1_pin = 17,
|
||||
.sda0_pin = 9,
|
||||
.sda_pins = 8,
|
||||
.i2c_mux_select = rtl9300_i2c_mux_select,
|
||||
.i2c_mux_deselect = rtl9300_i2c_mux_deselect,
|
||||
.sda_sel = rtl9300_sda_sel,
|
||||
};
|
||||
|
||||
struct i2c_mux_data rtl9310_i2c_mux_data = {
|
||||
.scl0_pin = 13,
|
||||
.scl1_pin = 14,
|
||||
.sda0_pin = 0,
|
||||
.sda_pins = 16,
|
||||
.i2c_mux_select = rtl9310_i2c_mux_select,
|
||||
.i2c_mux_deselect = rtl9300_i2c_mux_deselect,
|
||||
.sda_sel = rtl9310_sda_sel,
|
||||
};
|
||||
|
||||
static const struct of_device_id rtl9300_i2c_mux_of_match[] = {
|
||||
{ .compatible = "realtek,i2c-mux-rtl9300", .data = (void *) &rtl9300_i2c_mux_data},
|
||||
{ .compatible = "realtek,i2c-mux-rtl9310", .data = (void *) &rtl9310_i2c_mux_data},
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, rtl9300_i2c_mux_of_match);
|
||||
|
||||
static int rtl9300_i2c_mux_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *node = dev->of_node;
|
||||
struct device_node *parent_np;
|
||||
struct device_node *child;
|
||||
struct i2c_mux_core *muxc;
|
||||
struct rtl9300_mux *mux;
|
||||
struct i2c_mux_data *mux_data;
|
||||
int children;
|
||||
int ret;
|
||||
|
||||
pr_info("%s probing I2C adapter\n", __func__);
|
||||
|
||||
if (!node) {
|
||||
dev_err(dev, "No DT found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
|
||||
if (!mux)
|
||||
return -ENOMEM;
|
||||
|
||||
mux->dev = dev;
|
||||
|
||||
mux_data = (struct i2c_mux_data *) device_get_match_data(dev);
|
||||
|
||||
parent_np = mux_parent_adapter(dev, mux);
|
||||
if (IS_ERR(parent_np))
|
||||
return dev_err_probe(dev, PTR_ERR(parent_np), "i2c-parent adapter not found\n");
|
||||
|
||||
pr_info("%s base memory %08x\n", __func__, (u32)mux->base);
|
||||
|
||||
children = of_get_child_count(node);
|
||||
|
||||
muxc = i2c_mux_alloc(mux->parent, dev, children, 0, 0,
|
||||
mux_data->i2c_mux_select, mux_data->i2c_mux_deselect);
|
||||
if (!muxc) {
|
||||
ret = -ENOMEM;
|
||||
goto err_parent;
|
||||
}
|
||||
muxc->priv = mux;
|
||||
|
||||
platform_set_drvdata(pdev, muxc);
|
||||
|
||||
for_each_child_of_node(node, child) {
|
||||
u32 chan;
|
||||
u32 pin;
|
||||
|
||||
ret = of_property_read_u32(child, "reg", &chan);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "no reg property for node '%pOFn'\n",
|
||||
child);
|
||||
goto err_children;
|
||||
}
|
||||
|
||||
if (chan >= NUM_MASTERS * NUM_BUSSES) {
|
||||
dev_err(dev, "invalid reg %u\n", chan);
|
||||
ret = -EINVAL;
|
||||
goto err_children;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(child, "scl-pin", &pin)) {
|
||||
dev_warn(dev, "SCL pin not found in DT, using default\n");
|
||||
pin = mux_data->scl0_pin;
|
||||
}
|
||||
if (!(pin == mux_data->scl0_pin || pin == mux_data->scl1_pin)) {
|
||||
dev_warn(dev, "SCL pin %d not supported\n", pin);
|
||||
ret = -EINVAL;
|
||||
goto err_children;
|
||||
}
|
||||
channels[chan].scl_num = pin == mux_data->scl0_pin ? 0 : 1;
|
||||
pr_info("%s channel %d scl_num %d\n", __func__, chan, channels[chan].scl_num);
|
||||
|
||||
if (of_property_read_u32(child, "sda-pin", &pin)) {
|
||||
dev_warn(dev, "SDA pin not found in DT, using default \n");
|
||||
pin = mux_data->sda0_pin;
|
||||
}
|
||||
channels[chan].sda_num = pin - mux_data->sda0_pin;
|
||||
if (channels[chan].sda_num < 0 || channels[chan].sda_num >= mux_data->sda_pins) {
|
||||
dev_warn(dev, "SDA pin %d not supported\n", pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
pr_info("%s channel %d sda_num %d\n", __func__, chan, channels[chan].sda_num);
|
||||
|
||||
mux_data->sda_sel(muxc, channels[chan].sda_num);
|
||||
|
||||
ret = i2c_mux_add_adapter(muxc, 0, chan, 0);
|
||||
if (ret)
|
||||
goto err_children;
|
||||
}
|
||||
|
||||
dev_info(dev, "%d-port mux on %s adapter\n", children, mux->parent->name);
|
||||
|
||||
return 0;
|
||||
|
||||
err_children:
|
||||
i2c_mux_del_adapters(muxc);
|
||||
err_parent:
|
||||
i2c_put_adapter(mux->parent);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtl9300_i2c_mux_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
|
||||
|
||||
i2c_mux_del_adapters(muxc);
|
||||
i2c_put_adapter(muxc->parent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver i2c_mux_driver = {
|
||||
.probe = rtl9300_i2c_mux_probe,
|
||||
.remove = rtl9300_i2c_mux_remove,
|
||||
.driver = {
|
||||
.name = "i2c-mux-rtl9300",
|
||||
.of_match_table = rtl9300_i2c_mux_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(i2c_mux_driver);
|
||||
|
||||
MODULE_DESCRIPTION("RTL9300 I2C multiplexer driver");
|
||||
MODULE_AUTHOR("Birger Koblitz");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config NET_DSA_RTL83XX
|
||||
tristate "Realtek RTL838x/RTL839x switch support"
|
||||
depends on RTL83XX
|
||||
select NET_DSA_TAG_TRAILER
|
||||
help
|
||||
This driver adds support for Realtek RTL83xx series switching.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_NET_DSA_RTL83XX) += common.o dsa.o \
|
||||
rtl838x.o rtl839x.o rtl930x.o rtl931x.o debugfs.o qos.o tc.o
|
1696
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c
Normal file
1696
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,727 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||
#include "rtl83xx.h"
|
||||
|
||||
#define RTL838X_DRIVER_NAME "rtl838x"
|
||||
|
||||
#define RTL8380_LED_GLB_CTRL (0xA000)
|
||||
#define RTL8380_LED_MODE_SEL (0x1004)
|
||||
#define RTL8380_LED_MODE_CTRL (0xA004)
|
||||
#define RTL8380_LED_P_EN_CTRL (0xA008)
|
||||
#define RTL8380_LED_SW_CTRL (0xA00C)
|
||||
#define RTL8380_LED0_SW_P_EN_CTRL (0xA010)
|
||||
#define RTL8380_LED1_SW_P_EN_CTRL (0xA014)
|
||||
#define RTL8380_LED2_SW_P_EN_CTRL (0xA018)
|
||||
#define RTL8380_LED_SW_P_CTRL(p) (0xA01C + (((p) << 2)))
|
||||
|
||||
#define RTL8390_LED_GLB_CTRL (0x00E4)
|
||||
#define RTL8390_LED_SET_2_3_CTRL (0x00E8)
|
||||
#define RTL8390_LED_SET_0_1_CTRL (0x00EC)
|
||||
#define RTL8390_LED_COPR_SET_SEL_CTRL(p) (0x00F0 + (((p >> 4) << 2)))
|
||||
#define RTL8390_LED_FIB_SET_SEL_CTRL(p) (0x0100 + (((p >> 4) << 2)))
|
||||
#define RTL8390_LED_COPR_PMASK_CTRL(p) (0x0110 + (((p >> 5) << 2)))
|
||||
#define RTL8390_LED_FIB_PMASK_CTRL(p) (0x00118 + (((p >> 5) << 2)))
|
||||
#define RTL8390_LED_COMBO_CTRL(p) (0x0120 + (((p >> 5) << 2)))
|
||||
#define RTL8390_LED_SW_CTRL (0x0128)
|
||||
#define RTL8390_LED_SW_P_EN_CTRL(p) (0x012C + (((p / 10) << 2)))
|
||||
#define RTL8390_LED_SW_P_CTRL(p) (0x0144 + (((p) << 2)))
|
||||
|
||||
#define RTL838X_MIR_QID_CTRL(grp) (0xAD44 + (((grp) << 2)))
|
||||
#define RTL838X_MIR_RSPAN_VLAN_CTRL(grp) (0xA340 + (((grp) << 2)))
|
||||
#define RTL838X_MIR_RSPAN_VLAN_CTRL_MAC(grp) (0xAA70 + (((grp) << 2)))
|
||||
#define RTL838X_MIR_RSPAN_TX_CTRL (0xA350)
|
||||
#define RTL838X_MIR_RSPAN_TX_TAG_RM_CTRL (0xAA80)
|
||||
#define RTL838X_MIR_RSPAN_TX_TAG_EN_CTRL (0xAA84)
|
||||
#define RTL839X_MIR_RSPAN_VLAN_CTRL(grp) (0xA340 + (((grp) << 2)))
|
||||
#define RTL839X_MIR_RSPAN_TX_CTRL (0x69b0)
|
||||
#define RTL839X_MIR_RSPAN_TX_TAG_RM_CTRL (0x2550)
|
||||
#define RTL839X_MIR_RSPAN_TX_TAG_EN_CTRL (0x2554)
|
||||
#define RTL839X_MIR_SAMPLE_RATE_CTRL (0x2558)
|
||||
|
||||
#define RTL838X_STAT_PRVTE_DROP_COUNTERS (0x6A00)
|
||||
#define RTL839X_STAT_PRVTE_DROP_COUNTERS (0x3E00)
|
||||
#define RTL930X_STAT_PRVTE_DROP_COUNTERS (0xB5B8)
|
||||
#define RTL931X_STAT_PRVTE_DROP_COUNTERS (0xd800)
|
||||
|
||||
int rtl83xx_port_get_stp_state(struct rtl838x_switch_priv *priv, int port);
|
||||
void rtl83xx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
|
||||
void rtl83xx_fast_age(struct dsa_switch *ds, int port);
|
||||
u32 rtl838x_get_egress_rate(struct rtl838x_switch_priv *priv, int port);
|
||||
u32 rtl839x_get_egress_rate(struct rtl838x_switch_priv *priv, int port);
|
||||
int rtl838x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate);
|
||||
int rtl839x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate);
|
||||
|
||||
|
||||
const char *rtl838x_drop_cntr[] = {
|
||||
"ALE_TX_GOOD_PKTS", "MAC_RX_DROP", "ACL_FWD_DROP", "HW_ATTACK_PREVENTION_DROP",
|
||||
"RMA_DROP", "VLAN_IGR_FLTR_DROP", "INNER_OUTER_CFI_EQUAL_1_DROP", "PORT_MOVE_DROP",
|
||||
"NEW_SA_DROP", "MAC_LIMIT_SYS_DROP", "MAC_LIMIT_VLAN_DROP", "MAC_LIMIT_PORT_DROP",
|
||||
"SWITCH_MAC_DROP", "ROUTING_EXCEPTION_DROP", "DA_LKMISS_DROP", "RSPAN_DROP",
|
||||
"ACL_LKMISS_DROP", "ACL_DROP", "INBW_DROP", "IGR_METER_DROP",
|
||||
"ACCEPT_FRAME_TYPE_DROP", "STP_IGR_DROP", "INVALID_SA_DROP", "SA_BLOCKING_DROP",
|
||||
"DA_BLOCKING_DROP", "L2_INVALID_DPM_DROP", "MCST_INVALID_DPM_DROP", "RX_FLOW_CONTROL_DROP",
|
||||
"STORM_SPPRS_DROP", "LALS_DROP", "VLAN_EGR_FILTER_DROP", "STP_EGR_DROP",
|
||||
"SRC_PORT_FILTER_DROP", "PORT_ISOLATION_DROP", "ACL_FLTR_DROP", "MIRROR_FLTR_DROP",
|
||||
"TX_MAX_DROP", "LINK_DOWN_DROP", "FLOW_CONTROL_DROP", "BRIDGE .1d discards"
|
||||
};
|
||||
|
||||
const char *rtl839x_drop_cntr[] = {
|
||||
"ALE_TX_GOOD_PKTS", "ERROR_PKTS", "EGR_ACL_DROP", "EGR_METER_DROP",
|
||||
"OAM", "CFM" "VLAN_IGR_FLTR", "VLAN_ERR",
|
||||
"INNER_OUTER_CFI_EQUAL_1", "VLAN_TAG_FORMAT", "SRC_PORT_SPENDING_TREE", "INBW",
|
||||
"RMA", "HW_ATTACK_PREVENTION", "PROTO_STORM", "MCAST_SA",
|
||||
"IGR_ACL_DROP", "IGR_METER_DROP", "DFLT_ACTION_FOR_MISS_ACL_AND_C2SC", "NEW_SA",
|
||||
"PORT_MOVE", "SA_BLOCKING", "ROUTING_EXCEPTION", "SRC_PORT_SPENDING_TREE_NON_FWDING",
|
||||
"MAC_LIMIT", "UNKNOW_STORM", "MISS_DROP", "CPU_MAC_DROP",
|
||||
"DA_BLOCKING", "SRC_PORT_FILTER_BEFORE_EGR_ACL", "VLAN_EGR_FILTER", "SPANNING_TRE",
|
||||
"PORT_ISOLATION", "OAM_EGRESS_DROP", "MIRROR_ISOLATION", "MAX_LEN_BEFORE_EGR_ACL",
|
||||
"SRC_PORT_FILTER_BEFORE_MIRROR", "MAX_LEN_BEFORE_MIRROR", "SPECIAL_CONGEST_BEFORE_MIRROR",
|
||||
"LINK_STATUS_BEFORE_MIRROR",
|
||||
"WRED_BEFORE_MIRROR", "MAX_LEN_AFTER_MIRROR", "SPECIAL_CONGEST_AFTER_MIRROR",
|
||||
"LINK_STATUS_AFTER_MIRROR",
|
||||
"WRED_AFTER_MIRROR"
|
||||
};
|
||||
|
||||
const char *rtl930x_drop_cntr[] = {
|
||||
"OAM_PARSER", "UC_RPF", "DEI_CFI", "MAC_IP_SUBNET_BASED_VLAN", "VLAN_IGR_FILTER",
|
||||
"L2_UC_MC", "IPV_IP6_MC_BRIDGE", "PTP", "USER_DEF_0_3", "RESERVED",
|
||||
"RESERVED1", "RESERVED2", "BPDU_RMA", "LACP", "LLDP",
|
||||
"EAPOL", "XX_RMA", "L3_IPUC_NON_IP", "IP4_IP6_HEADER_ERROR", "L3_BAD_IP",
|
||||
"L3_DIP_DMAC_MISMATCH", "IP4_IP_OPTION", "IP_UC_MC_ROUTING_LOOK_UP_MISS", "L3_DST_NULL_INTF",
|
||||
"L3_PBR_NULL_INTF",
|
||||
"HOST_NULL_INTF", "ROUTE_NULL_INTF", "BRIDGING_ACTION", "ROUTING_ACTION", "IPMC_RPF",
|
||||
"L2_NEXTHOP_AGE_OUT", "L3_UC_TTL_FAIL", "L3_MC_TTL_FAIL", "L3_UC_MTU_FAIL", "L3_MC_MTU_FAIL",
|
||||
"L3_UC_ICMP_REDIR", "IP6_MLD_OTHER_ACT", "ND", "IP_MC_RESERVED", "IP6_HBH",
|
||||
"INVALID_SA", "L2_HASH_FULL", "NEW_SA", "PORT_MOVE_FORBID", "STATIC_PORT_MOVING",
|
||||
"DYNMIC_PORT_MOVING", "L3_CRC", "MAC_LIMIT", "ATTACK_PREVENT", "ACL_FWD_ACTION",
|
||||
"OAMPDU", "OAM_MUX", "TRUNK_FILTER", "ACL_DROP", "IGR_BW",
|
||||
"ACL_METER", "VLAN_ACCEPT_FRAME_TYPE", "MSTP_SRC_DROP_DISABLED_BLOCKING", "SA_BLOCK", "DA_BLOCK",
|
||||
"STORM_CONTROL", "VLAN_EGR_FILTER", "MSTP_DESTINATION_DROP", "SRC_PORT_FILTER", "PORT_ISOLATION",
|
||||
"TX_MAX_FRAME_SIZE", "EGR_LINK_STATUS", "MAC_TX_DISABLE", "MAC_PAUSE_FRAME", "MAC_RX_DROP",
|
||||
"MIRROR_ISOLATE", "RX_FC", "EGR_QUEUE", "HSM_RUNOUT", "ROUTING_DISABLE", "INVALID_L2_NEXTHOP_ENTRY",
|
||||
"L3_MC_SRC_FLT", "CPUTAG_FLT", "FWD_PMSK_NULL", "IPUC_ROUTING_LOOKUP_MISS", "MY_DEV_DROP",
|
||||
"STACK_NONUC_BLOCKING_PMSK", "STACK_PORT_NOT_FOUND", "ACL_LOOPBACK_DROP", "IP6_ROUTING_EXT_HEADER"
|
||||
};
|
||||
|
||||
const char *rtl931x_drop_cntr[] = {
|
||||
"ALE_RX_GOOD_PKTS", "RX_MAX_FRAME_SIZE", "MAC_RX_DROP", "OPENFLOW_IP_MPLS_TTL", "OPENFLOW_TBL_MISS",
|
||||
"IGR_BW", "SPECIAL_CONGEST", "EGR_QUEUE", "RESERVED", "EGR_LINK_STATUS", "STACK_UCAST_NONUCAST_TTL", // 10
|
||||
"STACK_NONUC_BLOCKING_PMSK", "L2_CRC", "SRC_PORT_FILTER", "PARSER_PACKET_TOO_LONG", "PARSER_MALFORM_PACKET",
|
||||
"MPLS_OVER_2_LBL", "EACL_METER", "IACL_METER", "PROTO_STORM", "INVALID_CAPWAP_HEADER", // 20
|
||||
"MAC_IP_SUBNET_BASED_VLAN", "OAM_PARSER", "UC_MC_RPF", "IP_MAC_BINDING_MATCH_MISMATCH", "SA_BLOCK",
|
||||
"TUNNEL_IP_ADDRESS_CHECK", "EACL_DROP", "IACL_DROP", "ATTACK_PREVENT", "SYSTEM_PORT_LIMIT_LEARN", // 30,
|
||||
"OAMPDU", "CCM_RX", "CFM_UNKNOWN_TYPE", "LBM_LBR_LTM_LTR", "Y_1731", "VLAN_LIMIT_LEARN",
|
||||
"VLAN_ACCEPT_FRAME_TYPE", "CFI_1", "STATIC_DYNAMIC_PORT_MOVING", "PORT_MOVE_FORBID", // 40
|
||||
"L3_CRC", "BPDU_PTP_LLDP_EAPOL_RMA", "MSTP_SRC_DROP_DISABLED_BLOCKING", "INVALID_SA", "NEW_SA",
|
||||
"VLAN_IGR_FILTER", "IGR_VLAN_CONVERT", "GRATUITOUS_ARP", "MSTP_SRC_DROP", "L2_HASH_FULL", // 50
|
||||
"MPLS_UNKNOWN_LBL", "L3_IPUC_NON_IP", "TTL", "MTU", "ICMP_REDIRECT", "STORM_CONTROL", "L3_DIP_DMAC_MISMATCH",
|
||||
"IP4_IP_OPTION", "IP6_HBH_EXT_HEADER", "IP4_IP6_HEADER_ERROR", // 60
|
||||
"ROUTING_IP_ADDR_CHECK", "ROUTING_EXCEPTION", "DA_BLOCK", "OAM_MUX", "PORT_ISOLATION", "VLAN_EGR_FILTER",
|
||||
"MIRROR_ISOLATE", "MSTP_DESTINATION_DROP", "L2_MC_BRIDGE", "IP_UC_MC_ROUTING_LOOK_UP_MISS", // 70
|
||||
"L2_UC", "L2_MC", "IP4_MC", "IP6_MC", "L3_UC_MC_ROUTE", "UNKNOWN_L2_UC_FLPM", "BC_FLPM",
|
||||
"VLAN_PRO_UNKNOWN_L2_MC_FLPM", "VLAN_PRO_UNKNOWN_IP4_MC_FLPM", "VLAN_PROFILE_UNKNOWN_IP6_MC_FLPM" // 80,
|
||||
};
|
||||
|
||||
static ssize_t rtl838x_common_read(char __user *buffer, size_t count,
|
||||
loff_t *ppos, unsigned int value)
|
||||
{
|
||||
char *buf;
|
||||
ssize_t len;
|
||||
|
||||
if (*ppos != 0)
|
||||
return 0;
|
||||
|
||||
buf = kasprintf(GFP_KERNEL, "0x%08x\n", value);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (count < strlen(buf)) {
|
||||
kfree(buf);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
|
||||
kfree(buf);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t rtl838x_common_write(const char __user *buffer, size_t count,
|
||||
loff_t *ppos, unsigned int *value)
|
||||
{
|
||||
char b[32];
|
||||
ssize_t len;
|
||||
int ret;
|
||||
|
||||
if (*ppos != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (count >= sizeof(b))
|
||||
return -ENOSPC;
|
||||
|
||||
len = simple_write_to_buffer(b, sizeof(b) - 1, ppos,
|
||||
buffer, count);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
b[len] = '\0';
|
||||
ret = kstrtouint(b, 16, value);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t stp_state_read(struct file *filp, char __user *buffer, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
struct dsa_switch *ds = p->dp->ds;
|
||||
int value = rtl83xx_port_get_stp_state(ds->priv, p->dp->index);
|
||||
|
||||
if (value < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return rtl838x_common_read(buffer, count, ppos, (u32)value);
|
||||
}
|
||||
|
||||
static ssize_t stp_state_write(struct file *filp, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
u32 value;
|
||||
size_t res = rtl838x_common_write(buffer, count, ppos, &value);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
rtl83xx_port_stp_state_set(p->dp->ds, p->dp->index, (u8)value);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static const struct file_operations stp_state_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = stp_state_read,
|
||||
.write = stp_state_write,
|
||||
};
|
||||
|
||||
static ssize_t drop_counter_read(struct file *filp, char __user *buffer, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = filp->private_data;
|
||||
int i;
|
||||
const char **d;
|
||||
u32 v;
|
||||
char *buf;
|
||||
int n = 0, len, offset;
|
||||
int num;
|
||||
|
||||
switch (priv->family_id) {
|
||||
case RTL8380_FAMILY_ID:
|
||||
d = rtl838x_drop_cntr;
|
||||
offset = RTL838X_STAT_PRVTE_DROP_COUNTERS;
|
||||
num = 40;
|
||||
break;
|
||||
case RTL8390_FAMILY_ID:
|
||||
d = rtl839x_drop_cntr;
|
||||
offset = RTL839X_STAT_PRVTE_DROP_COUNTERS;
|
||||
num = 45;
|
||||
break;
|
||||
case RTL9300_FAMILY_ID:
|
||||
d = rtl930x_drop_cntr;
|
||||
offset = RTL930X_STAT_PRVTE_DROP_COUNTERS;
|
||||
num = 85;
|
||||
break;
|
||||
case RTL9310_FAMILY_ID:
|
||||
d = rtl931x_drop_cntr;
|
||||
offset = RTL931X_STAT_PRVTE_DROP_COUNTERS;
|
||||
num = 81;
|
||||
break;
|
||||
}
|
||||
|
||||
buf = kmalloc(30 * num, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
v = sw_r32(offset + (i << 2)) & 0xffff;
|
||||
n += sprintf(buf + n, "%s: %d\n", d[i], v);
|
||||
}
|
||||
|
||||
if (count < strlen(buf)) {
|
||||
kfree(buf);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
|
||||
kfree(buf);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations drop_counter_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = drop_counter_read,
|
||||
};
|
||||
|
||||
static void l2_table_print_entry(struct seq_file *m, struct rtl838x_switch_priv *priv,
|
||||
struct rtl838x_l2_entry *e)
|
||||
{
|
||||
u64 portmask;
|
||||
int i;
|
||||
|
||||
if (e->type == L2_UNICAST) {
|
||||
seq_puts(m, "L2_UNICAST\n");
|
||||
|
||||
seq_printf(m, " mac %02x:%02x:%02x:%02x:%02x:%02x vid %u rvid %u\n",
|
||||
e->mac[0], e->mac[1], e->mac[2], e->mac[3], e->mac[4], e->mac[5],
|
||||
e->vid, e->rvid);
|
||||
|
||||
seq_printf(m, " port %d age %d", e->port, e->age);
|
||||
if (e->is_static)
|
||||
seq_puts(m, " static");
|
||||
if (e->block_da)
|
||||
seq_puts(m, " block_da");
|
||||
if (e->block_sa)
|
||||
seq_puts(m, " block_sa");
|
||||
if (e->suspended)
|
||||
seq_puts(m, " suspended");
|
||||
if (e->next_hop)
|
||||
seq_printf(m, " next_hop route_id %u", e->nh_route_id);
|
||||
seq_puts(m, "\n");
|
||||
|
||||
} else {
|
||||
if (e->type == L2_MULTICAST) {
|
||||
seq_puts(m, "L2_MULTICAST\n");
|
||||
|
||||
seq_printf(m, " mac %02x:%02x:%02x:%02x:%02x:%02x vid %u rvid %u\n",
|
||||
e->mac[0], e->mac[1], e->mac[2], e->mac[3], e->mac[4], e->mac[5],
|
||||
e->vid, e->rvid);
|
||||
}
|
||||
|
||||
if (e->type == IP4_MULTICAST || e->type == IP6_MULTICAST) {
|
||||
seq_puts(m, (e->type == IP4_MULTICAST) ?
|
||||
"IP4_MULTICAST\n" : "IP6_MULTICAST\n");
|
||||
|
||||
seq_printf(m, " gip %08x sip %08x vid %u rvid %u\n",
|
||||
e->mc_gip, e->mc_sip, e->vid, e->rvid);
|
||||
}
|
||||
|
||||
portmask = priv->r->read_mcast_pmask(e->mc_portmask_index);
|
||||
seq_printf(m, " index %u ports", e->mc_portmask_index);
|
||||
for (i = 0; i < 64; i++) {
|
||||
if (portmask & BIT_ULL(i))
|
||||
seq_printf(m, " %d", i);
|
||||
}
|
||||
seq_puts(m, "\n");
|
||||
}
|
||||
|
||||
seq_puts(m, "\n");
|
||||
}
|
||||
|
||||
static int l2_table_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = m->private;
|
||||
struct rtl838x_l2_entry e;
|
||||
int i, bucket, index;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
for (i = 0; i < priv->fib_entries; i++) {
|
||||
bucket = i >> 2;
|
||||
index = i & 0x3;
|
||||
priv->r->read_l2_entry_using_hash(bucket, index, &e);
|
||||
|
||||
if (!e.valid)
|
||||
continue;
|
||||
|
||||
seq_printf(m, "Hash table bucket %d index %d ", bucket, index);
|
||||
l2_table_print_entry(m, priv, &e);
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
priv->r->read_cam(i, &e);
|
||||
|
||||
if (!e.valid)
|
||||
continue;
|
||||
|
||||
seq_printf(m, "CAM index %d ", i);
|
||||
l2_table_print_entry(m, priv, &e);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l2_table_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return single_open(filp, l2_table_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations l2_table_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = l2_table_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static ssize_t age_out_read(struct file *filp, char __user *buffer, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
struct dsa_switch *ds = p->dp->ds;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
int value = sw_r32(priv->r->l2_port_aging_out);
|
||||
|
||||
if (value < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return rtl838x_common_read(buffer, count, ppos, (u32)value);
|
||||
}
|
||||
|
||||
static ssize_t age_out_write(struct file *filp, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
u32 value;
|
||||
size_t res = rtl838x_common_write(buffer, count, ppos, &value);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
rtl83xx_fast_age(p->dp->ds, p->dp->index);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static const struct file_operations age_out_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = age_out_read,
|
||||
.write = age_out_write,
|
||||
};
|
||||
|
||||
static ssize_t port_egress_rate_read(struct file *filp, char __user *buffer, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
struct dsa_switch *ds = p->dp->ds;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
int value;
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
value = rtl838x_get_egress_rate(priv, p->dp->index);
|
||||
else
|
||||
value = rtl839x_get_egress_rate(priv, p->dp->index);
|
||||
|
||||
if (value < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return rtl838x_common_read(buffer, count, ppos, (u32)value);
|
||||
}
|
||||
|
||||
static ssize_t port_egress_rate_write(struct file *filp, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rtl838x_port *p = filp->private_data;
|
||||
struct dsa_switch *ds = p->dp->ds;
|
||||
struct rtl838x_switch_priv *priv = ds->priv;
|
||||
u32 value;
|
||||
size_t res = rtl838x_common_write(buffer, count, ppos, &value);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
rtl838x_set_egress_rate(priv, p->dp->index, value);
|
||||
else
|
||||
rtl839x_set_egress_rate(priv, p->dp->index, value);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static const struct file_operations port_egress_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = simple_open,
|
||||
.read = port_egress_rate_read,
|
||||
.write = port_egress_rate_write,
|
||||
};
|
||||
|
||||
|
||||
static const struct debugfs_reg32 port_ctrl_regs[] = {
|
||||
{ .name = "port_isolation", .offset = RTL838X_PORT_ISO_CTRL(0), },
|
||||
{ .name = "mac_force_mode", .offset = RTL838X_MAC_FORCE_MODE_CTRL, },
|
||||
};
|
||||
|
||||
void rtl838x_dbgfs_cleanup(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
debugfs_remove_recursive(priv->dbgfs_dir);
|
||||
|
||||
// kfree(priv->dbgfs_entries);
|
||||
}
|
||||
|
||||
static int rtl838x_dbgfs_port_init(struct dentry *parent, struct rtl838x_switch_priv *priv,
|
||||
int port)
|
||||
{
|
||||
struct dentry *port_dir;
|
||||
struct debugfs_regset32 *port_ctrl_regset;
|
||||
|
||||
port_dir = debugfs_create_dir(priv->ports[port].dp->name, parent);
|
||||
|
||||
if (priv->family_id == RTL8380_FAMILY_ID) {
|
||||
debugfs_create_x32("storm_rate_uc", 0644, port_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_STORM_CTRL_PORT_UC(port)));
|
||||
|
||||
debugfs_create_x32("storm_rate_mc", 0644, port_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_STORM_CTRL_PORT_MC(port)));
|
||||
|
||||
debugfs_create_x32("storm_rate_bc", 0644, port_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_STORM_CTRL_PORT_BC(port)));
|
||||
} else {
|
||||
debugfs_create_x32("storm_rate_uc", 0644, port_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL839X_STORM_CTRL_PORT_UC_0(port)));
|
||||
|
||||
debugfs_create_x32("storm_rate_mc", 0644, port_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL839X_STORM_CTRL_PORT_MC_0(port)));
|
||||
|
||||
debugfs_create_x32("storm_rate_bc", 0644, port_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL839X_STORM_CTRL_PORT_BC_0(port)));
|
||||
}
|
||||
|
||||
debugfs_create_u32("id", 0444, port_dir, (u32 *)&priv->ports[port].dp->index);
|
||||
|
||||
port_ctrl_regset = devm_kzalloc(priv->dev, sizeof(*port_ctrl_regset), GFP_KERNEL);
|
||||
if (!port_ctrl_regset)
|
||||
return -ENOMEM;
|
||||
|
||||
port_ctrl_regset->regs = port_ctrl_regs;
|
||||
port_ctrl_regset->nregs = ARRAY_SIZE(port_ctrl_regs);
|
||||
port_ctrl_regset->base = (void *)(RTL838X_SW_BASE + (port << 2));
|
||||
debugfs_create_regset32("port_ctrl", 0400, port_dir, port_ctrl_regset);
|
||||
|
||||
debugfs_create_file("stp_state", 0600, port_dir, &priv->ports[port], &stp_state_fops);
|
||||
debugfs_create_file("age_out", 0600, port_dir, &priv->ports[port], &age_out_fops);
|
||||
debugfs_create_file("port_egress_rate", 0600, port_dir, &priv->ports[port],
|
||||
&port_egress_fops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl838x_dbgfs_leds(struct dentry *parent, struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
struct dentry *led_dir;
|
||||
int p;
|
||||
char led_sw_p_ctrl_name[20];
|
||||
char port_led_name[20];
|
||||
|
||||
led_dir = debugfs_create_dir("led", parent);
|
||||
|
||||
if (priv->family_id == RTL8380_FAMILY_ID) {
|
||||
debugfs_create_x32("led_glb_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED_GLB_CTRL));
|
||||
debugfs_create_x32("led_mode_sel", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED_MODE_SEL));
|
||||
debugfs_create_x32("led_mode_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED_MODE_CTRL));
|
||||
debugfs_create_x32("led_p_en_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED_P_EN_CTRL));
|
||||
debugfs_create_x32("led_sw_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED_SW_CTRL));
|
||||
debugfs_create_x32("led0_sw_p_en_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED0_SW_P_EN_CTRL));
|
||||
debugfs_create_x32("led1_sw_p_en_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED1_SW_P_EN_CTRL));
|
||||
debugfs_create_x32("led2_sw_p_en_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED2_SW_P_EN_CTRL));
|
||||
for (p = 0; p < 28; p++) {
|
||||
snprintf(led_sw_p_ctrl_name, sizeof(led_sw_p_ctrl_name),
|
||||
"led_sw_p_ctrl.%02d", p);
|
||||
debugfs_create_x32(led_sw_p_ctrl_name, 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8380_LED_SW_P_CTRL(p)));
|
||||
}
|
||||
} else if (priv->family_id == RTL8390_FAMILY_ID) {
|
||||
debugfs_create_x32("led_glb_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_GLB_CTRL));
|
||||
debugfs_create_x32("led_set_2_3", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_SET_2_3_CTRL));
|
||||
debugfs_create_x32("led_set_0_1", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_SET_0_1_CTRL));
|
||||
for (p = 0; p < 4; p++) {
|
||||
snprintf(port_led_name, sizeof(port_led_name), "led_copr_set_sel.%1d", p);
|
||||
debugfs_create_x32(port_led_name, 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_COPR_SET_SEL_CTRL(p << 4)));
|
||||
snprintf(port_led_name, sizeof(port_led_name), "led_fib_set_sel.%1d", p);
|
||||
debugfs_create_x32(port_led_name, 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_FIB_SET_SEL_CTRL(p << 4)));
|
||||
}
|
||||
debugfs_create_x32("led_copr_pmask_ctrl_0", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_COPR_PMASK_CTRL(0)));
|
||||
debugfs_create_x32("led_copr_pmask_ctrl_1", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_COPR_PMASK_CTRL(32)));
|
||||
debugfs_create_x32("led_fib_pmask_ctrl_0", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_FIB_PMASK_CTRL(0)));
|
||||
debugfs_create_x32("led_fib_pmask_ctrl_1", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_FIB_PMASK_CTRL(32)));
|
||||
debugfs_create_x32("led_combo_ctrl_0", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_COMBO_CTRL(0)));
|
||||
debugfs_create_x32("led_combo_ctrl_1", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_COMBO_CTRL(32)));
|
||||
debugfs_create_x32("led_sw_ctrl", 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_SW_CTRL));
|
||||
for (p = 0; p < 5; p++) {
|
||||
snprintf(port_led_name, sizeof(port_led_name), "led_sw_p_en_ctrl.%1d", p);
|
||||
debugfs_create_x32(port_led_name, 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_SW_P_EN_CTRL(p * 10)));
|
||||
}
|
||||
for (p = 0; p < 28; p++) {
|
||||
snprintf(port_led_name, sizeof(port_led_name), "led_sw_p_ctrl.%02d", p);
|
||||
debugfs_create_x32(port_led_name, 0644, led_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL8390_LED_SW_P_CTRL(p)));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtl838x_dbgfs_init(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
struct dentry *rtl838x_dir;
|
||||
struct dentry *port_dir;
|
||||
struct dentry *mirror_dir;
|
||||
struct debugfs_regset32 *port_ctrl_regset;
|
||||
int ret, i;
|
||||
char lag_name[10];
|
||||
char mirror_name[10];
|
||||
|
||||
pr_info("%s called\n", __func__);
|
||||
rtl838x_dir = debugfs_lookup(RTL838X_DRIVER_NAME, NULL);
|
||||
if (!rtl838x_dir)
|
||||
rtl838x_dir = debugfs_create_dir(RTL838X_DRIVER_NAME, NULL);
|
||||
|
||||
priv->dbgfs_dir = rtl838x_dir;
|
||||
|
||||
debugfs_create_u32("soc", 0444, rtl838x_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_MODEL_NAME_INFO));
|
||||
|
||||
/* Create one directory per port */
|
||||
for (i = 0; i < priv->cpu_port; i++) {
|
||||
if (priv->ports[i].phy) {
|
||||
ret = rtl838x_dbgfs_port_init(rtl838x_dir, priv, i);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create directory for CPU-port */
|
||||
port_dir = debugfs_create_dir("cpu_port", rtl838x_dir);
|
||||
port_ctrl_regset = devm_kzalloc(priv->dev, sizeof(*port_ctrl_regset), GFP_KERNEL);
|
||||
if (!port_ctrl_regset) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
port_ctrl_regset->regs = port_ctrl_regs;
|
||||
port_ctrl_regset->nregs = ARRAY_SIZE(port_ctrl_regs);
|
||||
port_ctrl_regset->base = (void *)(RTL838X_SW_BASE + (priv->cpu_port << 2));
|
||||
debugfs_create_regset32("port_ctrl", 0400, port_dir, port_ctrl_regset);
|
||||
debugfs_create_u8("id", 0444, port_dir, &priv->cpu_port);
|
||||
|
||||
/* Create entries for LAGs */
|
||||
for (i = 0; i < priv->n_lags; i++) {
|
||||
snprintf(lag_name, sizeof(lag_name), "lag.%02d", i);
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
debugfs_create_x32(lag_name, 0644, rtl838x_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + priv->r->trk_mbr_ctr(i)));
|
||||
else
|
||||
debugfs_create_x64(lag_name, 0644, rtl838x_dir,
|
||||
(u64 *)(RTL838X_SW_BASE + priv->r->trk_mbr_ctr(i)));
|
||||
}
|
||||
|
||||
/* Create directories for mirror groups */
|
||||
for (i = 0; i < 4; i++) {
|
||||
snprintf(mirror_name, sizeof(mirror_name), "mirror.%1d", i);
|
||||
mirror_dir = debugfs_create_dir(mirror_name, rtl838x_dir);
|
||||
if (priv->family_id == RTL8380_FAMILY_ID) {
|
||||
debugfs_create_x32("ctrl", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_MIR_CTRL + i * 4));
|
||||
debugfs_create_x32("ingress_pm", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + priv->r->mir_spm + i * 4));
|
||||
debugfs_create_x32("egress_pm", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + priv->r->mir_dpm + i * 4));
|
||||
debugfs_create_x32("qid", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_MIR_QID_CTRL(i)));
|
||||
debugfs_create_x32("rspan_vlan", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_MIR_RSPAN_VLAN_CTRL(i)));
|
||||
debugfs_create_x32("rspan_vlan_mac", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_MIR_RSPAN_VLAN_CTRL_MAC(i)));
|
||||
debugfs_create_x32("rspan_tx", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_MIR_RSPAN_TX_CTRL));
|
||||
debugfs_create_x32("rspan_tx_tag_rm", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_MIR_RSPAN_TX_TAG_RM_CTRL));
|
||||
debugfs_create_x32("rspan_tx_tag_en", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_MIR_RSPAN_TX_TAG_EN_CTRL));
|
||||
} else {
|
||||
debugfs_create_x32("ctrl", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL839X_MIR_CTRL + i * 4));
|
||||
debugfs_create_x64("ingress_pm", 0644, mirror_dir,
|
||||
(u64 *)(RTL838X_SW_BASE + priv->r->mir_spm + i * 8));
|
||||
debugfs_create_x64("egress_pm", 0644, mirror_dir,
|
||||
(u64 *)(RTL838X_SW_BASE + priv->r->mir_dpm + i * 8));
|
||||
debugfs_create_x32("rspan_vlan", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL839X_MIR_RSPAN_VLAN_CTRL(i)));
|
||||
debugfs_create_x32("rspan_tx", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL839X_MIR_RSPAN_TX_CTRL));
|
||||
debugfs_create_x32("rspan_tx_tag_rm", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL839X_MIR_RSPAN_TX_TAG_RM_CTRL));
|
||||
debugfs_create_x32("rspan_tx_tag_en", 0644, mirror_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL839X_MIR_RSPAN_TX_TAG_EN_CTRL));
|
||||
debugfs_create_x64("sample_rate", 0644, mirror_dir,
|
||||
(u64 *)(RTL838X_SW_BASE + RTL839X_MIR_SAMPLE_RATE_CTRL));
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
debugfs_create_x32("bpdu_flood_mask", 0644, rtl838x_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + priv->r->rma_bpdu_fld_pmask));
|
||||
else
|
||||
debugfs_create_x64("bpdu_flood_mask", 0644, rtl838x_dir,
|
||||
(u64 *)(RTL838X_SW_BASE + priv->r->rma_bpdu_fld_pmask));
|
||||
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
debugfs_create_x32("vlan_ctrl", 0644, rtl838x_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL838X_VLAN_CTRL));
|
||||
else
|
||||
debugfs_create_x32("vlan_ctrl", 0644, rtl838x_dir,
|
||||
(u32 *)(RTL838X_SW_BASE + RTL839X_VLAN_CTRL));
|
||||
|
||||
ret = rtl838x_dbgfs_leds(rtl838x_dir, priv);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
debugfs_create_file("drop_counters", 0400, rtl838x_dir, priv, &drop_counter_fops);
|
||||
|
||||
debugfs_create_file("l2_table", 0400, rtl838x_dir, priv, &l2_table_fops);
|
||||
|
||||
return;
|
||||
err:
|
||||
rtl838x_dbgfs_cleanup(priv);
|
||||
}
|
||||
|
||||
void rtl930x_dbgfs_init(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
struct dentry *dbg_dir;
|
||||
|
||||
pr_info("%s called\n", __func__);
|
||||
dbg_dir = debugfs_lookup(RTL838X_DRIVER_NAME, NULL);
|
||||
if (!dbg_dir)
|
||||
dbg_dir = debugfs_create_dir(RTL838X_DRIVER_NAME, NULL);
|
||||
|
||||
priv->dbgfs_dir = dbg_dir;
|
||||
|
||||
debugfs_create_file("drop_counters", 0400, dbg_dir, priv, &drop_counter_fops);
|
||||
|
||||
debugfs_create_file("l2_table", 0400, dbg_dir, priv, &l2_table_fops);
|
||||
}
|
2259
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c
Normal file
2259
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/dsa.c
Normal file
File diff suppressed because it is too large
Load diff
576
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/qos.c
Normal file
576
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/qos.c
Normal file
|
@ -0,0 +1,576 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <net/dsa.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||
#include "rtl83xx.h"
|
||||
|
||||
static struct rtl838x_switch_priv *switch_priv;
|
||||
extern struct rtl83xx_soc_info soc_info;
|
||||
|
||||
enum scheduler_type {
|
||||
WEIGHTED_FAIR_QUEUE = 0,
|
||||
WEIGHTED_ROUND_ROBIN,
|
||||
};
|
||||
|
||||
int max_available_queue[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
int default_queue_weights[] = {1, 1, 1, 1, 1, 1, 1, 1};
|
||||
int dot1p_priority_remapping[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
|
||||
static void rtl839x_read_scheduling_table(int port)
|
||||
{
|
||||
u32 cmd = 1 << 9 /* Execute cmd */
|
||||
| 0 << 8 /* Read */
|
||||
| 0 << 6 /* Table type 0b00 */
|
||||
| (port & 0x3f);
|
||||
rtl839x_exec_tbl2_cmd(cmd);
|
||||
}
|
||||
|
||||
static void rtl839x_write_scheduling_table(int port)
|
||||
{
|
||||
u32 cmd = 1 << 9 /* Execute cmd */
|
||||
| 1 << 8 /* Write */
|
||||
| 0 << 6 /* Table type 0b00 */
|
||||
| (port & 0x3f);
|
||||
rtl839x_exec_tbl2_cmd(cmd);
|
||||
}
|
||||
|
||||
static void rtl839x_read_out_q_table(int port)
|
||||
{
|
||||
u32 cmd = 1 << 9 /* Execute cmd */
|
||||
| 0 << 8 /* Read */
|
||||
| 2 << 6 /* Table type 0b10 */
|
||||
| (port & 0x3f);
|
||||
rtl839x_exec_tbl2_cmd(cmd);
|
||||
}
|
||||
|
||||
static void rtl838x_storm_enable(struct rtl838x_switch_priv *priv, int port, bool enable)
|
||||
{
|
||||
// Enable Storm control for that port for UC, MC, and BC
|
||||
if (enable)
|
||||
sw_w32(0x7, RTL838X_STORM_CTRL_LB_CTRL(port));
|
||||
else
|
||||
sw_w32(0x0, RTL838X_STORM_CTRL_LB_CTRL(port));
|
||||
}
|
||||
|
||||
u32 rtl838x_get_egress_rate(struct rtl838x_switch_priv *priv, int port)
|
||||
{
|
||||
u32 rate;
|
||||
|
||||
if (port > priv->cpu_port)
|
||||
return 0;
|
||||
rate = sw_r32(RTL838X_SCHED_P_EGR_RATE_CTRL(port)) & 0x3fff;
|
||||
return rate;
|
||||
}
|
||||
|
||||
/* Sets the rate limit, 10MBit/s is equal to a rate value of 625 */
|
||||
int rtl838x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate)
|
||||
{
|
||||
u32 old_rate;
|
||||
|
||||
if (port > priv->cpu_port)
|
||||
return -1;
|
||||
|
||||
old_rate = sw_r32(RTL838X_SCHED_P_EGR_RATE_CTRL(port));
|
||||
sw_w32(rate, RTL838X_SCHED_P_EGR_RATE_CTRL(port));
|
||||
|
||||
return old_rate;
|
||||
}
|
||||
|
||||
/* Set the rate limit for a particular queue in Bits/s
|
||||
* units of the rate is 16Kbps
|
||||
*/
|
||||
void rtl838x_egress_rate_queue_limit(struct rtl838x_switch_priv *priv, int port,
|
||||
int queue, u32 rate)
|
||||
{
|
||||
if (port > priv->cpu_port)
|
||||
return;
|
||||
if (queue > 7)
|
||||
return;
|
||||
sw_w32(rate, RTL838X_SCHED_Q_EGR_RATE_CTRL(port, queue));
|
||||
}
|
||||
|
||||
static void rtl838x_rate_control_init(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
pr_info("Enabling Storm control\n");
|
||||
// TICK_PERIOD_PPS
|
||||
if (priv->id == 0x8380)
|
||||
sw_w32_mask(0x3ff << 20, 434 << 20, RTL838X_SCHED_LB_TICK_TKN_CTRL_0);
|
||||
|
||||
// Set burst rate
|
||||
sw_w32(0x00008000, RTL838X_STORM_CTRL_BURST_0); // UC
|
||||
sw_w32(0x80008000, RTL838X_STORM_CTRL_BURST_1); // MC and BC
|
||||
|
||||
// Set burst Packets per Second to 32
|
||||
sw_w32(0x00000020, RTL838X_STORM_CTRL_BURST_PPS_0); // UC
|
||||
sw_w32(0x00200020, RTL838X_STORM_CTRL_BURST_PPS_1); // MC and BC
|
||||
|
||||
// Include IFG in storm control, rate based on bytes/s (0 = packets)
|
||||
sw_w32_mask(0, 1 << 6 | 1 << 5, RTL838X_STORM_CTRL);
|
||||
// Bandwidth control includes preamble and IFG (10 Bytes)
|
||||
sw_w32_mask(0, 1, RTL838X_SCHED_CTRL);
|
||||
|
||||
// On SoCs except RTL8382M, set burst size of port egress
|
||||
if (priv->id != 0x8382)
|
||||
sw_w32_mask(0xffff, 0x800, RTL838X_SCHED_LB_THR);
|
||||
|
||||
/* Enable storm control on all ports with a PHY and limit rates,
|
||||
* for UC and MC for both known and unknown addresses */
|
||||
for (i = 0; i < priv->cpu_port; i++) {
|
||||
if (priv->ports[i].phy) {
|
||||
sw_w32((1 << 18) | 0x8000, RTL838X_STORM_CTRL_PORT_UC(i));
|
||||
sw_w32((1 << 18) | 0x8000, RTL838X_STORM_CTRL_PORT_MC(i));
|
||||
sw_w32(0x8000, RTL838X_STORM_CTRL_PORT_BC(i));
|
||||
rtl838x_storm_enable(priv, i, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Attack prevention, enable all attack prevention measures
|
||||
//sw_w32(0x1ffff, RTL838X_ATK_PRVNT_CTRL);
|
||||
/* Attack prevention, drop (bit = 0) problematic packets on all ports.
|
||||
* Setting bit = 1 means: trap to CPU
|
||||
*/
|
||||
//sw_w32(0, RTL838X_ATK_PRVNT_ACT);
|
||||
// Enable attack prevention on all ports
|
||||
//sw_w32(0x0fffffff, RTL838X_ATK_PRVNT_PORT_EN);
|
||||
}
|
||||
|
||||
/* Sets the rate limit, 10MBit/s is equal to a rate value of 625 */
|
||||
u32 rtl839x_get_egress_rate(struct rtl838x_switch_priv *priv, int port)
|
||||
{
|
||||
u32 rate;
|
||||
|
||||
pr_debug("%s: Getting egress rate on port %d to %d\n", __func__, port, rate);
|
||||
if (port >= priv->cpu_port)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
rtl839x_read_scheduling_table(port);
|
||||
|
||||
rate = sw_r32(RTL839X_TBL_ACCESS_DATA_2(7));
|
||||
rate <<= 12;
|
||||
rate |= sw_r32(RTL839X_TBL_ACCESS_DATA_2(8)) >> 20;
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
/* Sets the rate limit, 10MBit/s is equal to a rate value of 625, returns previous rate */
|
||||
int rtl839x_set_egress_rate(struct rtl838x_switch_priv *priv, int port, u32 rate)
|
||||
{
|
||||
u32 old_rate;
|
||||
|
||||
pr_debug("%s: Setting egress rate on port %d to %d\n", __func__, port, rate);
|
||||
if (port >= priv->cpu_port)
|
||||
return -1;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
rtl839x_read_scheduling_table(port);
|
||||
|
||||
old_rate = sw_r32(RTL839X_TBL_ACCESS_DATA_2(7)) & 0xff;
|
||||
old_rate <<= 12;
|
||||
old_rate |= sw_r32(RTL839X_TBL_ACCESS_DATA_2(8)) >> 20;
|
||||
sw_w32_mask(0xff, (rate >> 12) & 0xff, RTL839X_TBL_ACCESS_DATA_2(7));
|
||||
sw_w32_mask(0xfff << 20, rate << 20, RTL839X_TBL_ACCESS_DATA_2(8));
|
||||
|
||||
rtl839x_write_scheduling_table(port);
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
return old_rate;
|
||||
}
|
||||
|
||||
/* Set the rate limit for a particular queue in Bits/s
|
||||
* units of the rate is 16Kbps
|
||||
*/
|
||||
void rtl839x_egress_rate_queue_limit(struct rtl838x_switch_priv *priv, int port,
|
||||
int queue, u32 rate)
|
||||
{
|
||||
int lsb = 128 + queue * 20;
|
||||
int low_byte = 8 - (lsb >> 5);
|
||||
int start_bit = lsb - (low_byte << 5);
|
||||
u32 high_mask = 0xfffff >> (32 - start_bit);
|
||||
|
||||
pr_debug("%s: Setting egress rate on port %d, queue %d to %d\n",
|
||||
__func__, port, queue, rate);
|
||||
if (port >= priv->cpu_port)
|
||||
return;
|
||||
if (queue > 7)
|
||||
return;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
rtl839x_read_scheduling_table(port);
|
||||
|
||||
sw_w32_mask(0xfffff << start_bit, (rate & 0xfffff) << start_bit,
|
||||
RTL839X_TBL_ACCESS_DATA_2(low_byte));
|
||||
if (high_mask)
|
||||
sw_w32_mask(high_mask, (rate & 0xfffff) >> (32- start_bit),
|
||||
RTL839X_TBL_ACCESS_DATA_2(low_byte - 1));
|
||||
|
||||
rtl839x_write_scheduling_table(port);
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
}
|
||||
|
||||
static void rtl839x_rate_control_init(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
int p, q;
|
||||
|
||||
pr_info("%s: enabling rate control\n", __func__);
|
||||
/* Tick length and token size settings for SoC with 250MHz,
|
||||
* RTL8350 family would use 50MHz
|
||||
*/
|
||||
// Set the special tick period
|
||||
sw_w32(976563, RTL839X_STORM_CTRL_SPCL_LB_TICK_TKN_CTRL);
|
||||
// Ingress tick period and token length 10G
|
||||
sw_w32(18 << 11 | 151, RTL839X_IGR_BWCTRL_LB_TICK_TKN_CTRL_0);
|
||||
// Ingress tick period and token length 1G
|
||||
sw_w32(245 << 11 | 129, RTL839X_IGR_BWCTRL_LB_TICK_TKN_CTRL_1);
|
||||
// Egress tick period 10G, bytes/token 10G and tick period 1G, bytes/token 1G
|
||||
sw_w32(18 << 24 | 151 << 16 | 185 << 8 | 97, RTL839X_SCHED_LB_TICK_TKN_CTRL);
|
||||
// Set the tick period of the CPU and the Token Len
|
||||
sw_w32(3815 << 8 | 1, RTL839X_SCHED_LB_TICK_TKN_PPS_CTRL);
|
||||
|
||||
// Set the Weighted Fair Queueing burst size
|
||||
sw_w32_mask(0xffff, 4500, RTL839X_SCHED_LB_THR);
|
||||
|
||||
// Storm-rate calculation is based on bytes/sec (bit 5), include IFG (bit 6)
|
||||
sw_w32_mask(0, 1 << 5 | 1 << 6, RTL839X_STORM_CTRL);
|
||||
|
||||
/* Based on the rate control mode being bytes/s
|
||||
* set tick period and token length for 10G
|
||||
*/
|
||||
sw_w32(18 << 10 | 151, RTL839X_STORM_CTRL_LB_TICK_TKN_CTRL_0);
|
||||
/* and for 1G ports */
|
||||
sw_w32(246 << 10 | 129, RTL839X_STORM_CTRL_LB_TICK_TKN_CTRL_1);
|
||||
|
||||
/* Set default burst rates on all ports (the same for 1G / 10G) with a PHY
|
||||
* for UC, MC and BC
|
||||
* For 1G port, the minimum burst rate is 1700, maximum 65535,
|
||||
* For 10G ports it is 2650 and 1048575 respectively */
|
||||
for (p = 0; p < priv->cpu_port; p++) {
|
||||
if (priv->ports[p].phy && !priv->ports[p].is10G) {
|
||||
sw_w32_mask(0xffff, 0x8000, RTL839X_STORM_CTRL_PORT_UC_1(p));
|
||||
sw_w32_mask(0xffff, 0x8000, RTL839X_STORM_CTRL_PORT_MC_1(p));
|
||||
sw_w32_mask(0xffff, 0x8000, RTL839X_STORM_CTRL_PORT_BC_1(p));
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup ingress/egress per-port rate control */
|
||||
for (p = 0; p < priv->cpu_port; p++) {
|
||||
if (!priv->ports[p].phy)
|
||||
continue;
|
||||
|
||||
if (priv->ports[p].is10G)
|
||||
rtl839x_set_egress_rate(priv, p, 625000); // 10GB/s
|
||||
else
|
||||
rtl839x_set_egress_rate(priv, p, 62500); // 1GB/s
|
||||
|
||||
// Setup queues: all RTL83XX SoCs have 8 queues, maximum rate
|
||||
for (q = 0; q < 8; q++)
|
||||
rtl839x_egress_rate_queue_limit(priv, p, q, 0xfffff);
|
||||
|
||||
if (priv->ports[p].is10G) {
|
||||
// Set high threshold to maximum
|
||||
sw_w32_mask(0xffff, 0xffff, RTL839X_IGR_BWCTRL_PORT_CTRL_10G_0(p));
|
||||
} else {
|
||||
// Set high threshold to maximum
|
||||
sw_w32_mask(0xffff, 0xffff, RTL839X_IGR_BWCTRL_PORT_CTRL_1(p));
|
||||
}
|
||||
}
|
||||
|
||||
// Set global ingress low watermark rate
|
||||
sw_w32(65532, RTL839X_IGR_BWCTRL_CTRL_LB_THR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void rtl838x_setup_prio2queue_matrix(int *min_queues)
|
||||
{
|
||||
int i;
|
||||
u32 v;
|
||||
|
||||
pr_info("Current Intprio2queue setting: %08x\n", sw_r32(RTL838X_QM_INTPRI2QID_CTRL));
|
||||
for (i = 0; i < MAX_PRIOS; i++)
|
||||
v |= i << (min_queues[i] * 3);
|
||||
sw_w32(v, RTL838X_QM_INTPRI2QID_CTRL);
|
||||
}
|
||||
|
||||
void rtl839x_setup_prio2queue_matrix(int *min_queues)
|
||||
{
|
||||
int i, q;
|
||||
|
||||
pr_info("Current Intprio2queue setting: %08x\n", sw_r32(RTL839X_QM_INTPRI2QID_CTRL(0)));
|
||||
for (i = 0; i < MAX_PRIOS; i++) {
|
||||
q = min_queues[i];
|
||||
sw_w32(i << (q * 3), RTL839X_QM_INTPRI2QID_CTRL(q));
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets the CPU queue depending on the internal priority of a packet */
|
||||
void rtl83xx_setup_prio2queue_cpu_matrix(int *max_queues)
|
||||
{
|
||||
int reg = soc_info.family == RTL8380_FAMILY_ID ? RTL838X_QM_PKT2CPU_INTPRI_MAP
|
||||
: RTL839X_QM_PKT2CPU_INTPRI_MAP;
|
||||
int i;
|
||||
u32 v;
|
||||
|
||||
pr_info("QM_PKT2CPU_INTPRI_MAP: %08x\n", sw_r32(reg));
|
||||
for (i = 0; i < MAX_PRIOS; i++)
|
||||
v |= max_queues[i] << (i * 3);
|
||||
sw_w32(v, reg);
|
||||
}
|
||||
|
||||
void rtl83xx_setup_default_prio2queue(void)
|
||||
{
|
||||
if (soc_info.family == RTL8380_FAMILY_ID) {
|
||||
rtl838x_setup_prio2queue_matrix(max_available_queue);
|
||||
} else {
|
||||
rtl839x_setup_prio2queue_matrix(max_available_queue);
|
||||
}
|
||||
rtl83xx_setup_prio2queue_cpu_matrix(max_available_queue);
|
||||
}
|
||||
|
||||
/* Sets the output queue assigned to a port, the port can be the CPU-port */
|
||||
void rtl839x_set_egress_queue(int port, int queue)
|
||||
{
|
||||
sw_w32(queue << ((port % 10) *3), RTL839X_QM_PORT_QNUM(port));
|
||||
}
|
||||
|
||||
/* Sets the priority assigned of an ingress port, the port can be the CPU-port */
|
||||
void rtl83xx_set_ingress_priority(int port, int priority)
|
||||
{
|
||||
if (soc_info.family == RTL8380_FAMILY_ID)
|
||||
sw_w32(priority << ((port % 10) *3), RTL838X_PRI_SEL_PORT_PRI(port));
|
||||
else
|
||||
sw_w32(priority << ((port % 10) *3), RTL839X_PRI_SEL_PORT_PRI(port));
|
||||
|
||||
}
|
||||
|
||||
int rtl839x_get_scheduling_algorithm(struct rtl838x_switch_priv *priv, int port)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
rtl839x_read_scheduling_table(port);
|
||||
v = sw_r32(RTL839X_TBL_ACCESS_DATA_2(8));
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
if (v & BIT(19))
|
||||
return WEIGHTED_ROUND_ROBIN;
|
||||
return WEIGHTED_FAIR_QUEUE;
|
||||
}
|
||||
|
||||
void rtl839x_set_scheduling_algorithm(struct rtl838x_switch_priv *priv, int port,
|
||||
enum scheduler_type sched)
|
||||
{
|
||||
enum scheduler_type t = rtl839x_get_scheduling_algorithm(priv, port);
|
||||
u32 v, oam_state, oam_port_state;
|
||||
u32 count;
|
||||
int i, egress_rate;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
/* Check whether we need to empty the egress queue of that port due to Errata E0014503 */
|
||||
if (sched == WEIGHTED_FAIR_QUEUE && t == WEIGHTED_ROUND_ROBIN && port != priv->cpu_port) {
|
||||
// Read Operations, Adminstatrion and Management control register
|
||||
oam_state = sw_r32(RTL839X_OAM_CTRL);
|
||||
|
||||
// Get current OAM state
|
||||
oam_port_state = sw_r32(RTL839X_OAM_PORT_ACT_CTRL(port));
|
||||
|
||||
// Disable OAM to block traffice
|
||||
v = sw_r32(RTL839X_OAM_CTRL);
|
||||
sw_w32_mask(0, 1, RTL839X_OAM_CTRL);
|
||||
v = sw_r32(RTL839X_OAM_CTRL);
|
||||
|
||||
// Set to trap action OAM forward (bits 1, 2) and OAM Mux Action Drop (bit 0)
|
||||
sw_w32(0x2, RTL839X_OAM_PORT_ACT_CTRL(port));
|
||||
|
||||
// Set port egress rate to unlimited
|
||||
egress_rate = rtl839x_set_egress_rate(priv, port, 0xFFFFF);
|
||||
|
||||
// Wait until the egress used page count of that port is 0
|
||||
i = 0;
|
||||
do {
|
||||
usleep_range(100, 200);
|
||||
rtl839x_read_out_q_table(port);
|
||||
count = sw_r32(RTL839X_TBL_ACCESS_DATA_2(6));
|
||||
count >>= 20;
|
||||
i++;
|
||||
} while (i < 3500 && count > 0);
|
||||
}
|
||||
|
||||
// Actually set the scheduling algorithm
|
||||
rtl839x_read_scheduling_table(port);
|
||||
sw_w32_mask(BIT(19), sched ? BIT(19) : 0, RTL839X_TBL_ACCESS_DATA_2(8));
|
||||
rtl839x_write_scheduling_table(port);
|
||||
|
||||
if (sched == WEIGHTED_FAIR_QUEUE && t == WEIGHTED_ROUND_ROBIN && port != priv->cpu_port) {
|
||||
// Restore OAM state to control register
|
||||
sw_w32(oam_state, RTL839X_OAM_CTRL);
|
||||
|
||||
// Restore trap action state
|
||||
sw_w32(oam_port_state, RTL839X_OAM_PORT_ACT_CTRL(port));
|
||||
|
||||
// Restore port egress rate
|
||||
rtl839x_set_egress_rate(priv, port, egress_rate);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
}
|
||||
|
||||
void rtl839x_set_scheduling_queue_weights(struct rtl838x_switch_priv *priv, int port,
|
||||
int *queue_weights)
|
||||
{
|
||||
int i, lsb, low_byte, start_bit, high_mask;
|
||||
|
||||
mutex_lock(&priv->reg_mutex);
|
||||
|
||||
rtl839x_read_scheduling_table(port);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
lsb = 48 + i * 8;
|
||||
low_byte = 8 - (lsb >> 5);
|
||||
start_bit = lsb - (low_byte << 5);
|
||||
high_mask = 0x3ff >> (32 - start_bit);
|
||||
sw_w32_mask(0x3ff << start_bit, (queue_weights[i] & 0x3ff) << start_bit,
|
||||
RTL839X_TBL_ACCESS_DATA_2(low_byte));
|
||||
if (high_mask)
|
||||
sw_w32_mask(high_mask, (queue_weights[i] & 0x3ff) >> (32- start_bit),
|
||||
RTL839X_TBL_ACCESS_DATA_2(low_byte - 1));
|
||||
}
|
||||
|
||||
rtl839x_write_scheduling_table(port);
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
}
|
||||
|
||||
void rtl838x_config_qos(void)
|
||||
{
|
||||
int i, p;
|
||||
u32 v;
|
||||
|
||||
pr_info("Setting up RTL838X QoS\n");
|
||||
pr_info("RTL838X_PRI_SEL_TBL_CTRL(i): %08x\n", sw_r32(RTL838X_PRI_SEL_TBL_CTRL(0)));
|
||||
rtl83xx_setup_default_prio2queue();
|
||||
|
||||
// Enable inner (bit 12) and outer (bit 13) priority remapping from DSCP
|
||||
sw_w32_mask(0, BIT(12) | BIT(13), RTL838X_PRI_DSCP_INVLD_CTRL0);
|
||||
|
||||
/* Set default weight for calculating internal priority, in prio selection group 0
|
||||
* Port based (prio 3), Port outer-tag (4), DSCP (5), Inner Tag (6), Outer Tag (7)
|
||||
*/
|
||||
v = 3 | (4 << 3) | (5 << 6) | (6 << 9) | (7 << 12);
|
||||
sw_w32(v, RTL838X_PRI_SEL_TBL_CTRL(0));
|
||||
|
||||
// Set the inner and outer priority one-to-one to re-marked outer dot1p priority
|
||||
v = 0;
|
||||
for (p = 0; p < 8; p++)
|
||||
v |= p << (3 * p);
|
||||
sw_w32(v, RTL838X_RMK_OPRI_CTRL);
|
||||
sw_w32(v, RTL838X_RMK_IPRI_CTRL);
|
||||
|
||||
v = 0;
|
||||
for (p = 0; p < 8; p++)
|
||||
v |= (dot1p_priority_remapping[p] & 0x7) << (p * 3);
|
||||
sw_w32(v, RTL838X_PRI_SEL_IPRI_REMAP);
|
||||
|
||||
// On all ports set scheduler type to WFQ
|
||||
for (i = 0; i <= soc_info.cpu_port; i++)
|
||||
sw_w32(0, RTL838X_SCHED_P_TYPE_CTRL(i));
|
||||
|
||||
// Enable egress scheduler for CPU-Port
|
||||
sw_w32_mask(0, BIT(8), RTL838X_SCHED_LB_CTRL(soc_info.cpu_port));
|
||||
|
||||
// Enable egress drop allways on
|
||||
sw_w32_mask(0, BIT(11), RTL838X_FC_P_EGR_DROP_CTRL(soc_info.cpu_port));
|
||||
|
||||
// Give special trap frames priority 7 (BPDUs) and routing exceptions:
|
||||
sw_w32_mask(0, 7 << 3 | 7, RTL838X_QM_PKT2CPU_INTPRI_2);
|
||||
// Give RMA frames priority 7:
|
||||
sw_w32_mask(0, 7, RTL838X_QM_PKT2CPU_INTPRI_1);
|
||||
}
|
||||
|
||||
void rtl839x_config_qos(void)
|
||||
{
|
||||
int port, p, q;
|
||||
u32 v;
|
||||
struct rtl838x_switch_priv *priv = switch_priv;
|
||||
|
||||
pr_info("Setting up RTL839X QoS\n");
|
||||
pr_info("RTL839X_PRI_SEL_TBL_CTRL(i): %08x\n", sw_r32(RTL839X_PRI_SEL_TBL_CTRL(0)));
|
||||
rtl83xx_setup_default_prio2queue();
|
||||
|
||||
for (port = 0; port < soc_info.cpu_port; port++)
|
||||
sw_w32(7, RTL839X_QM_PORT_QNUM(port));
|
||||
|
||||
// CPU-port gets queue number 7
|
||||
sw_w32(7, RTL839X_QM_PORT_QNUM(soc_info.cpu_port));
|
||||
|
||||
for (port = 0; port <= soc_info.cpu_port; port++) {
|
||||
rtl83xx_set_ingress_priority(port, 0);
|
||||
rtl839x_set_scheduling_algorithm(priv, port, WEIGHTED_FAIR_QUEUE);
|
||||
rtl839x_set_scheduling_queue_weights(priv, port, default_queue_weights);
|
||||
// Do re-marking based on outer tag
|
||||
sw_w32_mask(0, BIT(port % 32), RTL839X_RMK_PORT_DEI_TAG_CTRL(port));
|
||||
}
|
||||
|
||||
// Remap dot1p priorities to internal priority, for this the outer tag needs be re-marked
|
||||
v = 0;
|
||||
for (p = 0; p < 8; p++)
|
||||
v |= (dot1p_priority_remapping[p] & 0x7) << (p * 3);
|
||||
sw_w32(v, RTL839X_PRI_SEL_IPRI_REMAP);
|
||||
|
||||
/* Configure Drop Precedence for Drop Eligible Indicator (DEI)
|
||||
* Index 0: 0
|
||||
* Index 1: 2
|
||||
* Each indicator is 2 bits long
|
||||
*/
|
||||
sw_w32(2 << 2, RTL839X_PRI_SEL_DEI2DP_REMAP);
|
||||
|
||||
// Re-mark DEI: 4 bit-fields of 2 bits each, field 0 is bits 0-1, ...
|
||||
sw_w32((0x1 << 2) | (0x1 << 4), RTL839X_RMK_DEI_CTRL);
|
||||
|
||||
/* Set Congestion avoidance drop probability to 0 for drop precedences 0-2 (bits 24-31)
|
||||
* low threshold (bits 0-11) to 4095 and high threshold (bits 12-23) to 4095
|
||||
* Weighted Random Early Detection (WRED) is used
|
||||
*/
|
||||
sw_w32(4095 << 12| 4095, RTL839X_WRED_PORT_THR_CTRL(0));
|
||||
sw_w32(4095 << 12| 4095, RTL839X_WRED_PORT_THR_CTRL(1));
|
||||
sw_w32(4095 << 12| 4095, RTL839X_WRED_PORT_THR_CTRL(2));
|
||||
|
||||
/* Set queue-based congestion avoidance properties, register fields are as
|
||||
* for forward RTL839X_WRED_PORT_THR_CTRL
|
||||
*/
|
||||
for (q = 0; q < 8; q++) {
|
||||
sw_w32(255 << 24 | 78 << 12 | 68, RTL839X_WRED_QUEUE_THR_CTRL(q, 0));
|
||||
sw_w32(255 << 24 | 74 << 12 | 64, RTL839X_WRED_QUEUE_THR_CTRL(q, 0));
|
||||
sw_w32(255 << 24 | 70 << 12 | 60, RTL839X_WRED_QUEUE_THR_CTRL(q, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void __init rtl83xx_setup_qos(struct rtl838x_switch_priv *priv)
|
||||
{
|
||||
switch_priv = priv;
|
||||
|
||||
pr_info("In %s\n", __func__);
|
||||
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
return rtl838x_config_qos();
|
||||
else if (priv->family_id == RTL8390_FAMILY_ID)
|
||||
return rtl839x_config_qos();
|
||||
|
||||
if (priv->family_id == RTL8380_FAMILY_ID)
|
||||
rtl838x_rate_control_init(priv);
|
||||
else if (priv->family_id == RTL8390_FAMILY_ID)
|
||||
rtl839x_rate_control_init(priv);
|
||||
|
||||
}
|
2054
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.c
Normal file
2054
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.c
Normal file
File diff suppressed because it is too large
Load diff
1093
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h
Normal file
1093
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl838x.h
Normal file
File diff suppressed because it is too large
Load diff
1937
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl839x.c
Normal file
1937
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl839x.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,137 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _NET_DSA_RTL83XX_H
|
||||
#define _NET_DSA_RTL83XX_H
|
||||
|
||||
#include <net/dsa.h>
|
||||
#include "rtl838x.h"
|
||||
|
||||
|
||||
#define RTL8380_VERSION_A 'A'
|
||||
#define RTL8390_VERSION_A 'A'
|
||||
#define RTL8380_VERSION_B 'B'
|
||||
|
||||
struct fdb_update_work {
|
||||
struct work_struct work;
|
||||
struct net_device *ndev;
|
||||
u64 macs[];
|
||||
};
|
||||
|
||||
#define MIB_DESC(_size, _offset, _name) {.size = _size, .offset = _offset, .name = _name}
|
||||
struct rtl83xx_mib_desc {
|
||||
unsigned int size;
|
||||
unsigned int offset;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/* API for switch table access */
|
||||
struct table_reg {
|
||||
u16 addr;
|
||||
u16 data;
|
||||
u8 max_data;
|
||||
u8 c_bit;
|
||||
u8 t_bit;
|
||||
u8 rmode;
|
||||
u8 tbl;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
#define TBL_DESC(_addr, _data, _max_data, _c_bit, _t_bit, _rmode) \
|
||||
{ .addr = _addr, .data = _data, .max_data = _max_data, .c_bit = _c_bit, \
|
||||
.t_bit = _t_bit, .rmode = _rmode \
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
RTL8380_TBL_L2 = 0,
|
||||
RTL8380_TBL_0,
|
||||
RTL8380_TBL_1,
|
||||
RTL8390_TBL_L2,
|
||||
RTL8390_TBL_0,
|
||||
RTL8390_TBL_1,
|
||||
RTL8390_TBL_2,
|
||||
RTL9300_TBL_L2,
|
||||
RTL9300_TBL_0,
|
||||
RTL9300_TBL_1,
|
||||
RTL9300_TBL_2,
|
||||
RTL9300_TBL_HSB,
|
||||
RTL9300_TBL_HSA,
|
||||
RTL9310_TBL_0,
|
||||
RTL9310_TBL_1,
|
||||
RTL9310_TBL_2,
|
||||
RTL9310_TBL_3,
|
||||
RTL9310_TBL_4,
|
||||
RTL9310_TBL_5,
|
||||
RTL_TBL_END
|
||||
} rtl838x_tbl_reg_t;
|
||||
|
||||
void rtl_table_init(void);
|
||||
struct table_reg *rtl_table_get(rtl838x_tbl_reg_t r, int t);
|
||||
void rtl_table_release(struct table_reg *r);
|
||||
void rtl_table_read(struct table_reg *r, int idx);
|
||||
void rtl_table_write(struct table_reg *r, int idx);
|
||||
inline u16 rtl_table_data(struct table_reg *r, int i);
|
||||
inline u32 rtl_table_data_r(struct table_reg *r, int i);
|
||||
inline void rtl_table_data_w(struct table_reg *r, u32 v, int i);
|
||||
|
||||
void __init rtl83xx_setup_qos(struct rtl838x_switch_priv *priv);
|
||||
|
||||
int rtl83xx_packet_cntr_alloc(struct rtl838x_switch_priv *priv);
|
||||
|
||||
int rtl83xx_port_is_under(const struct net_device * dev, struct rtl838x_switch_priv *priv);
|
||||
|
||||
int read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
int write_phy(u32 port, u32 page, u32 reg, u32 val);
|
||||
|
||||
/* Port register accessor functions for the RTL839x and RTL931X SoCs */
|
||||
void rtl839x_mask_port_reg_be(u64 clear, u64 set, int reg);
|
||||
u64 rtl839x_get_port_reg_be(int reg);
|
||||
void rtl839x_set_port_reg_be(u64 set, int reg);
|
||||
void rtl839x_mask_port_reg_le(u64 clear, u64 set, int reg);
|
||||
void rtl839x_set_port_reg_le(u64 set, int reg);
|
||||
u64 rtl839x_get_port_reg_le(int reg);
|
||||
|
||||
/* Port register accessor functions for the RTL838x and RTL930X SoCs */
|
||||
void rtl838x_mask_port_reg(u64 clear, u64 set, int reg);
|
||||
void rtl838x_set_port_reg(u64 set, int reg);
|
||||
u64 rtl838x_get_port_reg(int reg);
|
||||
|
||||
/* RTL838x-specific */
|
||||
u32 rtl838x_hash(struct rtl838x_switch_priv *priv, u64 seed);
|
||||
irqreturn_t rtl838x_switch_irq(int irq, void *dev_id);
|
||||
void rtl8380_get_version(struct rtl838x_switch_priv *priv);
|
||||
void rtl838x_vlan_profile_dump(int index);
|
||||
int rtl83xx_dsa_phy_read(struct dsa_switch *ds, int phy_addr, int phy_reg);
|
||||
void rtl8380_sds_rst(int mac);
|
||||
int rtl8380_sds_power(int mac, int val);
|
||||
void rtl838x_print_matrix(void);
|
||||
|
||||
/* RTL839x-specific */
|
||||
u32 rtl839x_hash(struct rtl838x_switch_priv *priv, u64 seed);
|
||||
irqreturn_t rtl839x_switch_irq(int irq, void *dev_id);
|
||||
void rtl8390_get_version(struct rtl838x_switch_priv *priv);
|
||||
void rtl839x_vlan_profile_dump(int index);
|
||||
int rtl83xx_dsa_phy_write(struct dsa_switch *ds, int phy_addr, int phy_reg, u16 val);
|
||||
void rtl839x_exec_tbl2_cmd(u32 cmd);
|
||||
void rtl839x_print_matrix(void);
|
||||
|
||||
/* RTL930x-specific */
|
||||
u32 rtl930x_hash(struct rtl838x_switch_priv *priv, u64 seed);
|
||||
irqreturn_t rtl930x_switch_irq(int irq, void *dev_id);
|
||||
irqreturn_t rtl839x_switch_irq(int irq, void *dev_id);
|
||||
void rtl930x_vlan_profile_dump(int index);
|
||||
int rtl9300_sds_power(int mac, int val);
|
||||
void rtl9300_sds_rst(int sds_num, u32 mode);
|
||||
int rtl9300_serdes_setup(int sds_num, phy_interface_t phy_mode);
|
||||
void rtl930x_print_matrix(void);
|
||||
|
||||
/* RTL931x-specific */
|
||||
irqreturn_t rtl931x_switch_irq(int irq, void *dev_id);
|
||||
int rtl931x_sds_cmu_band_get(int sds, phy_interface_t mode);
|
||||
int rtl931x_sds_cmu_band_set(int sds, bool enable, u32 band, phy_interface_t mode);
|
||||
void rtl931x_sds_init(u32 sds, phy_interface_t mode);
|
||||
|
||||
int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_lag_upper_info *info);
|
||||
int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port);
|
||||
|
||||
#endif /* _NET_DSA_RTL83XX_H */
|
||||
|
2560
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c
Normal file
2560
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl930x.c
Normal file
File diff suppressed because it is too large
Load diff
1701
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c
Normal file
1701
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/rtl931x.c
Normal file
File diff suppressed because it is too large
Load diff
409
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/tc.c
Normal file
409
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/tc.c
Normal file
|
@ -0,0 +1,409 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <net/dsa.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/flow_offload.h>
|
||||
#include <linux/rhashtable.h>
|
||||
|
||||
#include <asm/mach-rtl838x/mach-rtl83xx.h>
|
||||
#include "rtl83xx.h"
|
||||
#include "rtl838x.h"
|
||||
|
||||
/*
|
||||
* Parse the flow rule for the matching conditions
|
||||
*/
|
||||
static int rtl83xx_parse_flow_rule(struct rtl838x_switch_priv *priv,
|
||||
struct flow_rule *rule, struct rtl83xx_flow *flow)
|
||||
{
|
||||
struct flow_dissector *dissector = rule->match.dissector;
|
||||
|
||||
pr_debug("In %s\n", __func__);
|
||||
/* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */
|
||||
if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 ||
|
||||
(dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) == 0) {
|
||||
pr_err("Cannot form TC key: used_keys = 0x%x\n", dissector->used_keys);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
|
||||
struct flow_match_basic match;
|
||||
|
||||
pr_debug("%s: BASIC\n", __func__);
|
||||
flow_rule_match_basic(rule, &match);
|
||||
if (match.key->n_proto == htons(ETH_P_ARP))
|
||||
flow->rule.frame_type = 0;
|
||||
if (match.key->n_proto == htons(ETH_P_IP))
|
||||
flow->rule.frame_type = 2;
|
||||
if (match.key->n_proto == htons(ETH_P_IPV6))
|
||||
flow->rule.frame_type = 3;
|
||||
if ((match.key->n_proto == htons(ETH_P_ARP)) || flow->rule.frame_type)
|
||||
flow->rule.frame_type_m = 3;
|
||||
if (flow->rule.frame_type >= 2) {
|
||||
if (match.key->ip_proto == IPPROTO_UDP)
|
||||
flow->rule.frame_type_l4 = 0;
|
||||
if (match.key->ip_proto == IPPROTO_TCP)
|
||||
flow->rule.frame_type_l4 = 1;
|
||||
if (match.key->ip_proto == IPPROTO_ICMP
|
||||
|| match.key->ip_proto ==IPPROTO_ICMPV6)
|
||||
flow->rule.frame_type_l4 = 2;
|
||||
if (match.key->ip_proto == IPPROTO_TCP)
|
||||
flow->rule.frame_type_l4 = 3;
|
||||
if ((match.key->ip_proto == IPPROTO_UDP) || flow->rule.frame_type_l4)
|
||||
flow->rule.frame_type_l4_m = 7;
|
||||
}
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
|
||||
struct flow_match_eth_addrs match;
|
||||
|
||||
pr_debug("%s: ETH_ADDR\n", __func__);
|
||||
flow_rule_match_eth_addrs(rule, &match);
|
||||
ether_addr_copy(flow->rule.dmac, match.key->dst);
|
||||
ether_addr_copy(flow->rule.dmac_m, match.mask->dst);
|
||||
ether_addr_copy(flow->rule.smac, match.key->src);
|
||||
ether_addr_copy(flow->rule.smac_m, match.mask->src);
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
|
||||
struct flow_match_vlan match;
|
||||
|
||||
pr_debug("%s: VLAN\n", __func__);
|
||||
flow_rule_match_vlan(rule, &match);
|
||||
flow->rule.itag = match.key->vlan_id;
|
||||
flow->rule.itag_m = match.mask->vlan_id;
|
||||
// TODO: What about match.key->vlan_priority ?
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
|
||||
struct flow_match_ipv4_addrs match;
|
||||
|
||||
pr_debug("%s: IPV4\n", __func__);
|
||||
flow_rule_match_ipv4_addrs(rule, &match);
|
||||
flow->rule.is_ipv6 = false;
|
||||
flow->rule.dip = match.key->dst;
|
||||
flow->rule.dip_m = match.mask->dst;
|
||||
flow->rule.sip = match.key->src;
|
||||
flow->rule.sip_m = match.mask->src;
|
||||
} else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
|
||||
struct flow_match_ipv6_addrs match;
|
||||
|
||||
pr_debug("%s: IPV6\n", __func__);
|
||||
flow->rule.is_ipv6 = true;
|
||||
flow_rule_match_ipv6_addrs(rule, &match);
|
||||
flow->rule.dip6 = match.key->dst;
|
||||
flow->rule.dip6_m = match.mask->dst;
|
||||
flow->rule.sip6 = match.key->src;
|
||||
flow->rule.sip6_m = match.mask->src;
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
|
||||
struct flow_match_ports match;
|
||||
|
||||
pr_debug("%s: PORTS\n", __func__);
|
||||
flow_rule_match_ports(rule, &match);
|
||||
flow->rule.dport = match.key->dst;
|
||||
flow->rule.dport_m = match.mask->dst;
|
||||
flow->rule.sport = match.key->src;
|
||||
flow->rule.sport_m = match.mask->src;
|
||||
}
|
||||
|
||||
// TODO: ICMP
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rtl83xx_flow_bypass_all(struct rtl83xx_flow *flow)
|
||||
{
|
||||
flow->rule.bypass_sel = true;
|
||||
flow->rule.bypass_all = true;
|
||||
flow->rule.bypass_igr_stp = true;
|
||||
flow->rule.bypass_ibc_sc = true;
|
||||
}
|
||||
|
||||
static int rtl83xx_parse_fwd(struct rtl838x_switch_priv *priv,
|
||||
const struct flow_action_entry *act, struct rtl83xx_flow *flow)
|
||||
{
|
||||
struct net_device *dev = act->dev;
|
||||
int port;
|
||||
|
||||
port = rtl83xx_port_is_under(dev, priv);
|
||||
if (port < 0) {
|
||||
netdev_info(dev, "%s: not a DSA device.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
flow->rule.fwd_sel = true;
|
||||
flow->rule.fwd_data = port;
|
||||
pr_debug("Using port index: %d\n", port);
|
||||
rtl83xx_flow_bypass_all(flow);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl83xx_add_flow(struct rtl838x_switch_priv *priv, struct flow_cls_offload *f,
|
||||
struct rtl83xx_flow *flow)
|
||||
{
|
||||
struct flow_rule *rule = flow_cls_offload_flow_rule(f);
|
||||
const struct flow_action_entry *act;
|
||||
int i, err;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
rtl83xx_parse_flow_rule(priv, rule, flow);
|
||||
|
||||
flow_action_for_each(i, act, &rule->action) {
|
||||
switch (act->id) {
|
||||
case FLOW_ACTION_DROP:
|
||||
pr_debug("%s: DROP\n", __func__);
|
||||
flow->rule.drop = true;
|
||||
rtl83xx_flow_bypass_all(flow);
|
||||
return 0;
|
||||
|
||||
case FLOW_ACTION_TRAP:
|
||||
pr_debug("%s: TRAP\n", __func__);
|
||||
flow->rule.fwd_data = priv->cpu_port;
|
||||
flow->rule.fwd_act = PIE_ACT_REDIRECT_TO_PORT;
|
||||
rtl83xx_flow_bypass_all(flow);
|
||||
break;
|
||||
|
||||
case FLOW_ACTION_MANGLE:
|
||||
pr_err("%s: FLOW_ACTION_MANGLE not supported\n", __func__);
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
case FLOW_ACTION_ADD:
|
||||
pr_err("%s: FLOW_ACTION_ADD not supported\n", __func__);
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
case FLOW_ACTION_VLAN_PUSH:
|
||||
pr_debug("%s: VLAN_PUSH\n", __func__);
|
||||
// TODO: act->vlan.proto
|
||||
flow->rule.ivid_act = PIE_ACT_VID_ASSIGN;
|
||||
flow->rule.ivid_sel = true;
|
||||
flow->rule.ivid_data = htons(act->vlan.vid);
|
||||
flow->rule.ovid_act = PIE_ACT_VID_ASSIGN;
|
||||
flow->rule.ovid_sel = true;
|
||||
flow->rule.ovid_data = htons(act->vlan.vid);
|
||||
flow->rule.fwd_mod_to_cpu = true;
|
||||
break;
|
||||
|
||||
case FLOW_ACTION_VLAN_POP:
|
||||
pr_debug("%s: VLAN_POP\n", __func__);
|
||||
flow->rule.ivid_act = PIE_ACT_VID_ASSIGN;
|
||||
flow->rule.ivid_data = 0;
|
||||
flow->rule.ivid_sel = true;
|
||||
flow->rule.ovid_act = PIE_ACT_VID_ASSIGN;
|
||||
flow->rule.ovid_data = 0;
|
||||
flow->rule.ovid_sel = true;
|
||||
flow->rule.fwd_mod_to_cpu = true;
|
||||
break;
|
||||
|
||||
case FLOW_ACTION_CSUM:
|
||||
pr_err("%s: FLOW_ACTION_CSUM not supported\n", __func__);
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
case FLOW_ACTION_REDIRECT:
|
||||
pr_debug("%s: REDIRECT\n", __func__);
|
||||
err = rtl83xx_parse_fwd(priv, act, flow);
|
||||
if (err)
|
||||
return err;
|
||||
flow->rule.fwd_act = PIE_ACT_REDIRECT_TO_PORT;
|
||||
break;
|
||||
|
||||
case FLOW_ACTION_MIRRED:
|
||||
pr_debug("%s: MIRRED\n", __func__);
|
||||
err = rtl83xx_parse_fwd(priv, act, flow);
|
||||
if (err)
|
||||
return err;
|
||||
flow->rule.fwd_act = PIE_ACT_COPY_TO_PORT;
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("%s: Flow action not supported: %d\n", __func__, act->id);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rhashtable_params tc_ht_params = {
|
||||
.head_offset = offsetof(struct rtl83xx_flow, node),
|
||||
.key_offset = offsetof(struct rtl83xx_flow, cookie),
|
||||
.key_len = sizeof(((struct rtl83xx_flow *)0)->cookie),
|
||||
.automatic_shrinking = true,
|
||||
};
|
||||
|
||||
static int rtl83xx_configure_flower(struct rtl838x_switch_priv *priv,
|
||||
struct flow_cls_offload *f)
|
||||
{
|
||||
struct rtl83xx_flow *flow;
|
||||
int err = 0;
|
||||
|
||||
pr_debug("In %s\n", __func__);
|
||||
|
||||
rcu_read_lock();
|
||||
pr_debug("Cookie %08lx\n", f->cookie);
|
||||
flow = rhashtable_lookup(&priv->tc_ht, &f->cookie, tc_ht_params);
|
||||
if (flow) {
|
||||
pr_info("%s: Got flow\n", __func__);
|
||||
err = -EEXIST;
|
||||
goto rcu_unlock;
|
||||
}
|
||||
|
||||
rcu_unlock:
|
||||
rcu_read_unlock();
|
||||
if (flow)
|
||||
goto out;
|
||||
pr_debug("%s: New flow\n", __func__);
|
||||
|
||||
flow = kzalloc(sizeof(*flow), GFP_KERNEL);
|
||||
if (!flow) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
flow->cookie = f->cookie;
|
||||
flow->priv = priv;
|
||||
|
||||
err = rhashtable_insert_fast(&priv->tc_ht, &flow->node, tc_ht_params);
|
||||
if (err) {
|
||||
pr_err("Could not insert add new rule\n");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
rtl83xx_add_flow(priv, f, flow); // TODO: check error
|
||||
|
||||
// Add log action to flow
|
||||
flow->rule.packet_cntr = rtl83xx_packet_cntr_alloc(priv);
|
||||
if (flow->rule.packet_cntr >= 0) {
|
||||
pr_debug("Using packet counter %d\n", flow->rule.packet_cntr);
|
||||
flow->rule.log_sel = true;
|
||||
flow->rule.log_data = flow->rule.packet_cntr;
|
||||
}
|
||||
|
||||
err = priv->r->pie_rule_add(priv, &flow->rule);
|
||||
return err;
|
||||
|
||||
out_free:
|
||||
kfree(flow);
|
||||
out:
|
||||
pr_err("%s: error %d\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rtl83xx_delete_flower(struct rtl838x_switch_priv *priv,
|
||||
struct flow_cls_offload * cls_flower)
|
||||
{
|
||||
struct rtl83xx_flow *flow;
|
||||
|
||||
pr_debug("In %s\n", __func__);
|
||||
rcu_read_lock();
|
||||
flow = rhashtable_lookup_fast(&priv->tc_ht, &cls_flower->cookie, tc_ht_params);
|
||||
if (!flow) {
|
||||
rcu_read_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->r->pie_rule_rm(priv, &flow->rule);
|
||||
|
||||
rhashtable_remove_fast(&priv->tc_ht, &flow->node, tc_ht_params);
|
||||
|
||||
kfree_rcu(flow, rcu_head);
|
||||
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl83xx_stats_flower(struct rtl838x_switch_priv *priv,
|
||||
struct flow_cls_offload * cls_flower)
|
||||
{
|
||||
struct rtl83xx_flow *flow;
|
||||
unsigned long lastused = 0;
|
||||
int total_packets, new_packets;
|
||||
|
||||
pr_debug("%s: \n", __func__);
|
||||
flow = rhashtable_lookup_fast(&priv->tc_ht, &cls_flower->cookie, tc_ht_params);
|
||||
if (!flow)
|
||||
return -1;
|
||||
|
||||
if (flow->rule.packet_cntr >= 0) {
|
||||
total_packets = priv->r->packet_cntr_read(flow->rule.packet_cntr);
|
||||
pr_debug("Total packets: %d\n", total_packets);
|
||||
new_packets = total_packets - flow->rule.last_packet_cnt;
|
||||
flow->rule.last_packet_cnt = total_packets;
|
||||
}
|
||||
|
||||
// TODO: We need a second PIE rule to count the bytes
|
||||
flow_stats_update(&cls_flower->stats, 100 * new_packets, new_packets, 0, lastused,
|
||||
FLOW_ACTION_HW_STATS_IMMEDIATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl83xx_setup_tc_cls_flower(struct rtl838x_switch_priv *priv,
|
||||
struct flow_cls_offload *cls_flower)
|
||||
{
|
||||
pr_debug("%s: %d\n", __func__, cls_flower->command);
|
||||
switch (cls_flower->command) {
|
||||
case FLOW_CLS_REPLACE:
|
||||
return rtl83xx_configure_flower(priv, cls_flower);
|
||||
case FLOW_CLS_DESTROY:
|
||||
return rtl83xx_delete_flower(priv, cls_flower);
|
||||
case FLOW_CLS_STATS:
|
||||
return rtl83xx_stats_flower(priv, cls_flower);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int rtl83xx_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
|
||||
void *cb_priv)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv = cb_priv;
|
||||
|
||||
switch (type) {
|
||||
case TC_SETUP_CLSFLOWER:
|
||||
pr_debug("%s: TC_SETUP_CLSFLOWER\n", __func__);
|
||||
return rtl83xx_setup_tc_cls_flower(priv, type_data);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static LIST_HEAD(rtl83xx_block_cb_list);
|
||||
|
||||
int rtl83xx_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
|
||||
{
|
||||
struct rtl838x_switch_priv *priv;
|
||||
struct flow_block_offload *f = type_data;
|
||||
static bool first_time = true;
|
||||
int err;
|
||||
|
||||
pr_debug("%s: %d\n", __func__, type);
|
||||
|
||||
if(!netdev_uses_dsa(dev)) {
|
||||
pr_err("%s: no DSA\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
priv = dev->dsa_ptr->ds->priv;
|
||||
|
||||
switch (type) {
|
||||
case TC_SETUP_BLOCK:
|
||||
if (first_time) {
|
||||
first_time = false;
|
||||
err = rhashtable_init(&priv->tc_ht, &tc_ht_params);
|
||||
if (err)
|
||||
pr_err("%s: Could not initialize hash table\n", __func__);
|
||||
}
|
||||
|
||||
f->unlocked_driver_cb = true;
|
||||
return flow_block_cb_setup_simple(type_data,
|
||||
&rtl83xx_block_cb_list,
|
||||
rtl83xx_setup_tc_block_cb,
|
||||
priv, priv, true);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
2588
target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c
Normal file
2588
target/linux/realtek/files-5.15/drivers/net/ethernet/rtl838x_eth.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,457 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _RTL838X_ETH_H
|
||||
#define _RTL838X_ETH_H
|
||||
|
||||
/*
|
||||
* Register definition
|
||||
*/
|
||||
|
||||
/* Per port MAC control */
|
||||
#define RTL838X_MAC_PORT_CTRL (0xd560)
|
||||
#define RTL839X_MAC_PORT_CTRL (0x8004)
|
||||
#define RTL930X_MAC_L2_PORT_CTRL (0x3268)
|
||||
#define RTL930X_MAC_PORT_CTRL (0x3260)
|
||||
#define RTL931X_MAC_L2_PORT_CTRL (0x6000)
|
||||
#define RTL931X_MAC_PORT_CTRL (0x6004)
|
||||
|
||||
/* DMA interrupt control and status registers */
|
||||
#define RTL838X_DMA_IF_CTRL (0x9f58)
|
||||
#define RTL838X_DMA_IF_INTR_STS (0x9f54)
|
||||
#define RTL838X_DMA_IF_INTR_MSK (0x9f50)
|
||||
|
||||
#define RTL839X_DMA_IF_CTRL (0x786c)
|
||||
#define RTL839X_DMA_IF_INTR_STS (0x7868)
|
||||
#define RTL839X_DMA_IF_INTR_MSK (0x7864)
|
||||
|
||||
#define RTL930X_DMA_IF_CTRL (0xe028)
|
||||
#define RTL930X_DMA_IF_INTR_RX_RUNOUT_STS (0xe01C)
|
||||
#define RTL930X_DMA_IF_INTR_RX_DONE_STS (0xe020)
|
||||
#define RTL930X_DMA_IF_INTR_TX_DONE_STS (0xe024)
|
||||
#define RTL930X_DMA_IF_INTR_RX_RUNOUT_MSK (0xe010)
|
||||
#define RTL930X_DMA_IF_INTR_RX_DONE_MSK (0xe014)
|
||||
#define RTL930X_DMA_IF_INTR_TX_DONE_MSK (0xe018)
|
||||
#define RTL930X_L2_NTFY_IF_INTR_MSK (0xe04C)
|
||||
#define RTL930X_L2_NTFY_IF_INTR_STS (0xe050)
|
||||
|
||||
/* TODO: RTL931X_DMA_IF_CTRL has different bits meanings */
|
||||
#define RTL931X_DMA_IF_CTRL (0x0928)
|
||||
#define RTL931X_DMA_IF_INTR_RX_RUNOUT_STS (0x091c)
|
||||
#define RTL931X_DMA_IF_INTR_RX_DONE_STS (0x0920)
|
||||
#define RTL931X_DMA_IF_INTR_TX_DONE_STS (0x0924)
|
||||
#define RTL931X_DMA_IF_INTR_RX_RUNOUT_MSK (0x0910)
|
||||
#define RTL931X_DMA_IF_INTR_RX_DONE_MSK (0x0914)
|
||||
#define RTL931X_DMA_IF_INTR_TX_DONE_MSK (0x0918)
|
||||
#define RTL931X_L2_NTFY_IF_INTR_MSK (0x09E4)
|
||||
#define RTL931X_L2_NTFY_IF_INTR_STS (0x09E8)
|
||||
|
||||
#define RTL838X_MAC_FORCE_MODE_CTRL (0xa104)
|
||||
#define RTL839X_MAC_FORCE_MODE_CTRL (0x02bc)
|
||||
#define RTL930X_MAC_FORCE_MODE_CTRL (0xCA1C)
|
||||
#define RTL931X_MAC_FORCE_MODE_CTRL (0x0ddc)
|
||||
|
||||
/* MAC address settings */
|
||||
#define RTL838X_MAC (0xa9ec)
|
||||
#define RTL839X_MAC (0x02b4)
|
||||
#define RTL838X_MAC_ALE (0x6b04)
|
||||
#define RTL838X_MAC2 (0xa320)
|
||||
#define RTL930X_MAC_L2_ADDR_CTRL (0xC714)
|
||||
#define RTL931X_MAC_L2_ADDR_CTRL (0x135c)
|
||||
|
||||
/* Ringbuffer setup */
|
||||
#define RTL838X_DMA_RX_BASE (0x9f00)
|
||||
#define RTL839X_DMA_RX_BASE (0x780c)
|
||||
#define RTL930X_DMA_RX_BASE (0xdf00)
|
||||
#define RTL931X_DMA_RX_BASE (0x0800)
|
||||
|
||||
#define RTL838X_DMA_TX_BASE (0x9f40)
|
||||
#define RTL839X_DMA_TX_BASE (0x784c)
|
||||
#define RTL930X_DMA_TX_BASE (0xe000)
|
||||
#define RTL931X_DMA_TX_BASE (0x0900)
|
||||
|
||||
#define RTL838X_DMA_IF_RX_RING_SIZE (0xB7E4)
|
||||
#define RTL839X_DMA_IF_RX_RING_SIZE (0x6038)
|
||||
#define RTL930X_DMA_IF_RX_RING_SIZE (0x7C60)
|
||||
#define RTL931X_DMA_IF_RX_RING_SIZE (0x2080)
|
||||
|
||||
#define RTL838X_DMA_IF_RX_RING_CNTR (0xB7E8)
|
||||
#define RTL839X_DMA_IF_RX_RING_CNTR (0x603c)
|
||||
#define RTL930X_DMA_IF_RX_RING_CNTR (0x7C8C)
|
||||
#define RTL931X_DMA_IF_RX_RING_CNTR (0x20AC)
|
||||
|
||||
#define RTL838X_DMA_IF_RX_CUR (0x9F20)
|
||||
#define RTL839X_DMA_IF_RX_CUR (0x782c)
|
||||
#define RTL930X_DMA_IF_RX_CUR (0xdf80)
|
||||
#define RTL931X_DMA_IF_RX_CUR (0x0880)
|
||||
|
||||
#define RTL838X_DMA_IF_TX_CUR_DESC_ADDR_CTRL (0x9F48)
|
||||
#define RTL930X_DMA_IF_TX_CUR_DESC_ADDR_CTRL (0xE008)
|
||||
|
||||
#define RTL838X_DMY_REG31 (0x3b28)
|
||||
#define RTL838X_SDS_MODE_SEL (0x0028)
|
||||
#define RTL838X_SDS_CFG_REG (0x0034)
|
||||
#define RTL838X_INT_MODE_CTRL (0x005c)
|
||||
#define RTL838X_CHIP_INFO (0x00d8)
|
||||
#define RTL838X_SDS4_REG28 (0xef80)
|
||||
#define RTL838X_SDS4_DUMMY0 (0xef8c)
|
||||
#define RTL838X_SDS5_EXT_REG6 (0xf18c)
|
||||
|
||||
/* L2 features */
|
||||
#define RTL839X_TBL_ACCESS_L2_CTRL (0x1180)
|
||||
#define RTL839X_TBL_ACCESS_L2_DATA(idx) (0x1184 + ((idx) << 2))
|
||||
#define RTL838X_TBL_ACCESS_CTRL_0 (0x6914)
|
||||
#define RTL838X_TBL_ACCESS_DATA_0(idx) (0x6918 + ((idx) << 2))
|
||||
|
||||
/* MAC-side link state handling */
|
||||
#define RTL838X_MAC_LINK_STS (0xa188)
|
||||
#define RTL839X_MAC_LINK_STS (0x0390)
|
||||
#define RTL930X_MAC_LINK_STS (0xCB10)
|
||||
#define RTL931X_MAC_LINK_STS (0x0ec0)
|
||||
|
||||
#define RTL838X_MAC_LINK_SPD_STS (0xa190)
|
||||
#define RTL839X_MAC_LINK_SPD_STS (0x03a0)
|
||||
#define RTL930X_MAC_LINK_SPD_STS (0xCB18)
|
||||
#define RTL931X_MAC_LINK_SPD_STS (0x0ed0)
|
||||
|
||||
#define RTL838X_MAC_LINK_DUP_STS (0xa19c)
|
||||
#define RTL839X_MAC_LINK_DUP_STS (0x03b0)
|
||||
#define RTL930X_MAC_LINK_DUP_STS (0xCB28)
|
||||
#define RTL931X_MAC_LINK_DUP_STS (0x0ef0)
|
||||
|
||||
// TODO: RTL8390_MAC_LINK_MEDIA_STS_ADDR ???
|
||||
|
||||
#define RTL838X_MAC_TX_PAUSE_STS (0xa1a0)
|
||||
#define RTL839X_MAC_TX_PAUSE_STS (0x03b8)
|
||||
#define RTL930X_MAC_TX_PAUSE_STS (0xCB2C)
|
||||
#define RTL931X_MAC_TX_PAUSE_STS (0x0ef8)
|
||||
|
||||
#define RTL838X_MAC_RX_PAUSE_STS (0xa1a4)
|
||||
#define RTL839X_MAC_RX_PAUSE_STS (0xCB30)
|
||||
#define RTL930X_MAC_RX_PAUSE_STS (0xC2F8)
|
||||
#define RTL931X_MAC_RX_PAUSE_STS (0x0f00)
|
||||
|
||||
#define RTL838X_EEE_TX_TIMER_GIGA_CTRL (0xaa04)
|
||||
#define RTL838X_EEE_TX_TIMER_GELITE_CTRL (0xaa08)
|
||||
|
||||
#define RTL930X_L2_UNKN_UC_FLD_PMSK (0x9064)
|
||||
#define RTL931X_L2_UNKN_UC_FLD_PMSK (0xC8F4)
|
||||
|
||||
#define RTL839X_MAC_GLB_CTRL (0x02a8)
|
||||
#define RTL839X_SCHED_LB_TICK_TKN_CTRL (0x60f8)
|
||||
|
||||
#define RTL838X_L2_TBL_FLUSH_CTRL (0x3370)
|
||||
#define RTL839X_L2_TBL_FLUSH_CTRL (0x3ba0)
|
||||
#define RTL930X_L2_TBL_FLUSH_CTRL (0x9404)
|
||||
#define RTL931X_L2_TBL_FLUSH_CTRL (0xCD9C)
|
||||
|
||||
#define RTL930X_L2_PORT_SABLK_CTRL (0x905c)
|
||||
#define RTL930X_L2_PORT_DABLK_CTRL (0x9060)
|
||||
|
||||
/* MAC link state bits */
|
||||
#define FORCE_EN (1 << 0)
|
||||
#define FORCE_LINK_EN (1 << 1)
|
||||
#define NWAY_EN (1 << 2)
|
||||
#define DUPLX_MODE (1 << 3)
|
||||
#define TX_PAUSE_EN (1 << 6)
|
||||
#define RX_PAUSE_EN (1 << 7)
|
||||
|
||||
/* L2 Notification DMA interface */
|
||||
#define RTL839X_DMA_IF_NBUF_BASE_DESC_ADDR_CTRL (0x785C)
|
||||
#define RTL839X_L2_NOTIFICATION_CTRL (0x7808)
|
||||
#define RTL931X_L2_NTFY_RING_BASE_ADDR (0x09DC)
|
||||
#define RTL931X_L2_NTFY_RING_CUR_ADDR (0x09E0)
|
||||
#define RTL839X_L2_NOTIFICATION_CTRL (0x7808)
|
||||
#define RTL931X_L2_NTFY_CTRL (0xCDC8)
|
||||
#define RTL838X_L2_CTRL_0 (0x3200)
|
||||
#define RTL839X_L2_CTRL_0 (0x3800)
|
||||
#define RTL930X_L2_CTRL (0x8FD8)
|
||||
#define RTL931X_L2_CTRL (0xC800)
|
||||
|
||||
/* TRAPPING to CPU-PORT */
|
||||
#define RTL838X_SPCL_TRAP_IGMP_CTRL (0x6984)
|
||||
#define RTL838X_RMA_CTRL_0 (0x4300)
|
||||
#define RTL838X_RMA_CTRL_1 (0x4304)
|
||||
#define RTL839X_RMA_CTRL_0 (0x1200)
|
||||
|
||||
#define RTL839X_SPCL_TRAP_IGMP_CTRL (0x1058)
|
||||
#define RTL839X_RMA_CTRL_1 (0x1204)
|
||||
#define RTL839X_RMA_CTRL_2 (0x1208)
|
||||
#define RTL839X_RMA_CTRL_3 (0x120C)
|
||||
|
||||
#define RTL930X_VLAN_APP_PKT_CTRL (0xA23C)
|
||||
#define RTL930X_RMA_CTRL_0 (0x9E60)
|
||||
#define RTL930X_RMA_CTRL_1 (0x9E64)
|
||||
#define RTL930X_RMA_CTRL_2 (0x9E68)
|
||||
|
||||
#define RTL931X_VLAN_APP_PKT_CTRL (0x96b0)
|
||||
#define RTL931X_RMA_CTRL_0 (0x8800)
|
||||
#define RTL931X_RMA_CTRL_1 (0x8804)
|
||||
#define RTL931X_RMA_CTRL_2 (0x8808)
|
||||
|
||||
/* Advanced SMI control for clause 45 PHYs */
|
||||
#define RTL930X_SMI_MAC_TYPE_CTRL (0xCA04)
|
||||
#define RTL930X_SMI_PORT24_27_ADDR_CTRL (0xCB90)
|
||||
#define RTL930X_SMI_PORT0_15_POLLING_SEL (0xCA08)
|
||||
#define RTL930X_SMI_PORT16_27_POLLING_SEL (0xCA0C)
|
||||
|
||||
#define RTL930X_SMI_10GPHY_POLLING_REG0_CFG (0xCBB4)
|
||||
#define RTL930X_SMI_10GPHY_POLLING_REG9_CFG (0xCBB8)
|
||||
#define RTL930X_SMI_10GPHY_POLLING_REG10_CFG (0xCBBC)
|
||||
#define RTL930X_SMI_PRVTE_POLLING_CTRL (0xCA10)
|
||||
|
||||
/* Registers of the internal Serdes of the 8390 */
|
||||
#define RTL839X_SDS12_13_XSG0 (0xB800)
|
||||
|
||||
/* Chip configuration registers of the RTL9310 */
|
||||
#define RTL931X_MEM_ENCAP_INIT (0x4854)
|
||||
#define RTL931X_MEM_MIB_INIT (0x7E18)
|
||||
#define RTL931X_MEM_ACL_INIT (0x40BC)
|
||||
#define RTL931X_MEM_ALE_INIT_0 (0x83F0)
|
||||
#define RTL931X_MEM_ALE_INIT_1 (0x83F4)
|
||||
#define RTL931X_MEM_ALE_INIT_2 (0x82E4)
|
||||
#define RTL931X_MDX_CTRL_RSVD (0x0fcc)
|
||||
#define RTL931X_PS_SOC_CTRL (0x13f8)
|
||||
#define RTL931X_SMI_10GPHY_POLLING_SEL2 (0xCF8)
|
||||
#define RTL931X_SMI_10GPHY_POLLING_SEL3 (0xCFC)
|
||||
#define RTL931X_SMI_10GPHY_POLLING_SEL4 (0xD00)
|
||||
|
||||
/* Registers of the internal Serdes of the 8380 */
|
||||
#define RTL838X_SDS4_FIB_REG0 (0xF800)
|
||||
|
||||
inline int rtl838x_mac_port_ctrl(int p)
|
||||
{
|
||||
return RTL838X_MAC_PORT_CTRL + (p << 7);
|
||||
}
|
||||
|
||||
inline int rtl839x_mac_port_ctrl(int p)
|
||||
{
|
||||
return RTL839X_MAC_PORT_CTRL + (p << 7);
|
||||
}
|
||||
|
||||
/* On the RTL931XX, the functionality of the MAC port control register is split up
|
||||
* into RTL931X_MAC_L2_PORT_CTRL and RTL931X_MAC_PORT_CTRL the functionality used
|
||||
* by the Ethernet driver is in the same bits now in RTL931X_MAC_L2_PORT_CTRL
|
||||
*/
|
||||
|
||||
inline int rtl930x_mac_port_ctrl(int p)
|
||||
{
|
||||
return RTL930X_MAC_L2_PORT_CTRL + (p << 6);
|
||||
}
|
||||
|
||||
inline int rtl931x_mac_port_ctrl(int p)
|
||||
{
|
||||
return RTL931X_MAC_L2_PORT_CTRL + (p << 7);
|
||||
}
|
||||
|
||||
inline int rtl838x_dma_if_rx_ring_size(int i)
|
||||
{
|
||||
return RTL838X_DMA_IF_RX_RING_SIZE + ((i >> 3) << 2);
|
||||
}
|
||||
|
||||
inline int rtl839x_dma_if_rx_ring_size(int i)
|
||||
{
|
||||
return RTL839X_DMA_IF_RX_RING_SIZE + ((i >> 3) << 2);
|
||||
}
|
||||
|
||||
inline int rtl930x_dma_if_rx_ring_size(int i)
|
||||
{
|
||||
return RTL930X_DMA_IF_RX_RING_SIZE + ((i / 3) << 2);
|
||||
}
|
||||
|
||||
inline int rtl931x_dma_if_rx_ring_size(int i)
|
||||
{
|
||||
return RTL931X_DMA_IF_RX_RING_SIZE + ((i / 3) << 2);
|
||||
}
|
||||
|
||||
inline int rtl838x_dma_if_rx_ring_cntr(int i)
|
||||
{
|
||||
return RTL838X_DMA_IF_RX_RING_CNTR + ((i >> 3) << 2);
|
||||
}
|
||||
|
||||
inline int rtl839x_dma_if_rx_ring_cntr(int i)
|
||||
{
|
||||
return RTL839X_DMA_IF_RX_RING_CNTR + ((i >> 3) << 2);
|
||||
}
|
||||
|
||||
inline int rtl930x_dma_if_rx_ring_cntr(int i)
|
||||
{
|
||||
return RTL930X_DMA_IF_RX_RING_CNTR + ((i / 3) << 2);
|
||||
}
|
||||
|
||||
inline int rtl931x_dma_if_rx_ring_cntr(int i)
|
||||
{
|
||||
return RTL931X_DMA_IF_RX_RING_CNTR + ((i / 3) << 2);
|
||||
}
|
||||
|
||||
inline u32 rtl838x_get_mac_link_sts(int port)
|
||||
{
|
||||
return (sw_r32(RTL838X_MAC_LINK_STS) & BIT(port));
|
||||
}
|
||||
|
||||
inline u32 rtl839x_get_mac_link_sts(int p)
|
||||
{
|
||||
return (sw_r32(RTL839X_MAC_LINK_STS + ((p >> 5) << 2)) & BIT(p % 32));
|
||||
}
|
||||
|
||||
inline u32 rtl930x_get_mac_link_sts(int port)
|
||||
{
|
||||
u32 link = sw_r32(RTL930X_MAC_LINK_STS);
|
||||
|
||||
link = sw_r32(RTL930X_MAC_LINK_STS);
|
||||
pr_info("%s link state is %08x\n", __func__, link);
|
||||
return link & BIT(port);
|
||||
}
|
||||
|
||||
inline u32 rtl931x_get_mac_link_sts(int p)
|
||||
{
|
||||
return (sw_r32(RTL931X_MAC_LINK_STS + ((p >> 5) << 2)) & BIT(p % 32));
|
||||
}
|
||||
|
||||
inline u32 rtl838x_get_mac_link_dup_sts(int port)
|
||||
{
|
||||
return (sw_r32(RTL838X_MAC_LINK_DUP_STS) & BIT(port));
|
||||
}
|
||||
|
||||
inline u32 rtl839x_get_mac_link_dup_sts(int p)
|
||||
{
|
||||
return (sw_r32(RTL839X_MAC_LINK_DUP_STS + ((p >> 5) << 2)) & BIT(p % 32));
|
||||
}
|
||||
|
||||
inline u32 rtl930x_get_mac_link_dup_sts(int port)
|
||||
{
|
||||
return (sw_r32(RTL930X_MAC_LINK_DUP_STS) & BIT(port));
|
||||
}
|
||||
|
||||
inline u32 rtl931x_get_mac_link_dup_sts(int p)
|
||||
{
|
||||
return (sw_r32(RTL931X_MAC_LINK_DUP_STS + ((p >> 5) << 2)) & BIT(p % 32));
|
||||
}
|
||||
|
||||
inline u32 rtl838x_get_mac_link_spd_sts(int port)
|
||||
{
|
||||
int r = RTL838X_MAC_LINK_SPD_STS + ((port >> 4) << 2);
|
||||
u32 speed = sw_r32(r);
|
||||
|
||||
speed >>= (port % 16) << 1;
|
||||
return (speed & 0x3);
|
||||
}
|
||||
|
||||
inline u32 rtl839x_get_mac_link_spd_sts(int port)
|
||||
{
|
||||
int r = RTL839X_MAC_LINK_SPD_STS + ((port >> 4) << 2);
|
||||
u32 speed = sw_r32(r);
|
||||
|
||||
speed >>= (port % 16) << 1;
|
||||
return (speed & 0x3);
|
||||
}
|
||||
|
||||
|
||||
inline u32 rtl930x_get_mac_link_spd_sts(int port)
|
||||
{
|
||||
int r = RTL930X_MAC_LINK_SPD_STS + ((port >> 3) << 2);
|
||||
u32 speed = sw_r32(r);
|
||||
|
||||
speed >>= (port % 8) << 2;
|
||||
return (speed & 0xf);
|
||||
}
|
||||
|
||||
inline u32 rtl931x_get_mac_link_spd_sts(int port)
|
||||
{
|
||||
int r = RTL931X_MAC_LINK_SPD_STS + ((port >> 3) << 2);
|
||||
u32 speed = sw_r32(r);
|
||||
|
||||
speed >>= (port % 8) << 2;
|
||||
return (speed & 0xf);
|
||||
}
|
||||
|
||||
inline u32 rtl838x_get_mac_rx_pause_sts(int port)
|
||||
{
|
||||
return (sw_r32(RTL838X_MAC_RX_PAUSE_STS) & (1 << port));
|
||||
}
|
||||
|
||||
inline u32 rtl839x_get_mac_rx_pause_sts(int p)
|
||||
{
|
||||
return (sw_r32(RTL839X_MAC_RX_PAUSE_STS + ((p >> 5) << 2)) & BIT(p % 32));
|
||||
}
|
||||
|
||||
inline u32 rtl930x_get_mac_rx_pause_sts(int port)
|
||||
{
|
||||
return (sw_r32(RTL930X_MAC_RX_PAUSE_STS) & (1 << port));
|
||||
}
|
||||
|
||||
inline u32 rtl931x_get_mac_rx_pause_sts(int p)
|
||||
{
|
||||
return (sw_r32(RTL931X_MAC_RX_PAUSE_STS + ((p >> 5) << 2)) & BIT(p % 32));
|
||||
}
|
||||
|
||||
inline u32 rtl838x_get_mac_tx_pause_sts(int port)
|
||||
{
|
||||
return (sw_r32(RTL838X_MAC_TX_PAUSE_STS) & (1 << port));
|
||||
}
|
||||
|
||||
inline u32 rtl839x_get_mac_tx_pause_sts(int p)
|
||||
{
|
||||
return (sw_r32(RTL839X_MAC_TX_PAUSE_STS + ((p >> 5) << 2)) & BIT(p % 32));
|
||||
}
|
||||
|
||||
inline u32 rtl930x_get_mac_tx_pause_sts(int port)
|
||||
{
|
||||
return (sw_r32(RTL930X_MAC_TX_PAUSE_STS) & (1 << port));
|
||||
}
|
||||
|
||||
inline u32 rtl931x_get_mac_tx_pause_sts(int p)
|
||||
{
|
||||
return (sw_r32(RTL931X_MAC_TX_PAUSE_STS + ((p >> 5) << 2)) & BIT(p % 32));
|
||||
}
|
||||
|
||||
struct p_hdr;
|
||||
struct dsa_tag;
|
||||
|
||||
struct rtl838x_eth_reg {
|
||||
irqreturn_t (*net_irq)(int irq, void *dev_id);
|
||||
int (*mac_port_ctrl)(int port);
|
||||
int dma_if_intr_sts;
|
||||
int dma_if_intr_msk;
|
||||
int dma_if_intr_rx_runout_sts;
|
||||
int dma_if_intr_rx_done_sts;
|
||||
int dma_if_intr_tx_done_sts;
|
||||
int dma_if_intr_rx_runout_msk;
|
||||
int dma_if_intr_rx_done_msk;
|
||||
int dma_if_intr_tx_done_msk;
|
||||
int l2_ntfy_if_intr_sts;
|
||||
int l2_ntfy_if_intr_msk;
|
||||
int dma_if_ctrl;
|
||||
int mac_force_mode_ctrl;
|
||||
int dma_rx_base;
|
||||
int dma_tx_base;
|
||||
int (*dma_if_rx_ring_size)(int ring);
|
||||
int (*dma_if_rx_ring_cntr)(int ring);
|
||||
int dma_if_rx_cur;
|
||||
int rst_glb_ctrl;
|
||||
u32 (*get_mac_link_sts)(int port);
|
||||
u32 (*get_mac_link_dup_sts)(int port);
|
||||
u32 (*get_mac_link_spd_sts)(int port);
|
||||
u32 (*get_mac_rx_pause_sts)(int port);
|
||||
u32 (*get_mac_tx_pause_sts)(int port);
|
||||
int mac;
|
||||
int l2_tbl_flush_ctrl;
|
||||
void (*update_cntr)(int r, int work_done);
|
||||
void (*create_tx_header)(struct p_hdr *h, unsigned int dest_port, int prio);
|
||||
bool (*decode_tag)(struct p_hdr *h, struct dsa_tag *tag);
|
||||
};
|
||||
|
||||
int rtl838x_write_phy(u32 port, u32 page, u32 reg, u32 val);
|
||||
int rtl838x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
int rtl838x_write_mmd_phy(u32 port, u32 addr, u32 reg, u32 val);
|
||||
int rtl838x_read_mmd_phy(u32 port, u32 addr, u32 reg, u32 *val);
|
||||
int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val);
|
||||
int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
|
||||
int rtl839x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val);
|
||||
int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val);
|
||||
int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
int rtl931x_write_phy(u32 port, u32 page, u32 reg, u32 val);
|
||||
int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
|
||||
int rtl83xx_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data);
|
||||
|
||||
#endif /* _RTL838X_ETH_H */
|
4018
target/linux/realtek/files-5.15/drivers/net/phy/rtl83xx-phy.c
Normal file
4018
target/linux/realtek/files-5.15/drivers/net/phy/rtl83xx-phy.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,68 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
struct rtl83xx_shared_private {
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) part {
|
||||
uint16_t start;
|
||||
uint8_t wordsize;
|
||||
uint8_t words;
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) fw_header {
|
||||
uint32_t magic;
|
||||
uint32_t phy;
|
||||
uint32_t checksum;
|
||||
uint32_t version;
|
||||
struct part parts[10];
|
||||
};
|
||||
|
||||
// TODO: fixed path?
|
||||
#define FIRMWARE_838X_8380_1 "rtl838x_phy/rtl838x_8380.fw"
|
||||
#define FIRMWARE_838X_8214FC_1 "rtl838x_phy/rtl838x_8214fc.fw"
|
||||
#define FIRMWARE_838X_8218b_1 "rtl838x_phy/rtl838x_8218b.fw"
|
||||
|
||||
/* External RTL8218B and RTL8214FC IDs are identical */
|
||||
#define PHY_ID_RTL8214C 0x001cc942
|
||||
#define PHY_ID_RTL8214FC 0x001cc981
|
||||
#define PHY_ID_RTL8218B_E 0x001cc981
|
||||
#define PHY_ID_RTL8218D 0x001cc983
|
||||
#define PHY_ID_RTL8218B_I 0x001cca40
|
||||
#define PHY_ID_RTL8221B 0x001cc849
|
||||
#define PHY_ID_RTL8226 0x001cc838
|
||||
#define PHY_ID_RTL8390_GENERIC 0x001ccab0
|
||||
#define PHY_ID_RTL8393_I 0x001c8393
|
||||
#define PHY_ID_RTL9300_I 0x70d03106
|
||||
|
||||
// PHY MMD devices
|
||||
#define MMD_AN 7
|
||||
#define MMD_VEND2 31
|
||||
|
||||
/* Registers of the internal Serdes of the 8380 */
|
||||
#define RTL838X_SDS_MODE_SEL (0x0028)
|
||||
#define RTL838X_SDS_CFG_REG (0x0034)
|
||||
#define RTL838X_INT_MODE_CTRL (0x005c)
|
||||
#define RTL838X_DMY_REG31 (0x3b28)
|
||||
|
||||
#define RTL8380_SDS4_FIB_REG0 (0xF800)
|
||||
#define RTL838X_SDS4_REG28 (0xef80)
|
||||
#define RTL838X_SDS4_DUMMY0 (0xef8c)
|
||||
#define RTL838X_SDS5_EXT_REG6 (0xf18c)
|
||||
#define RTL838X_SDS4_FIB_REG0 (RTL838X_SDS4_REG28 + 0x880)
|
||||
#define RTL838X_SDS5_FIB_REG0 (RTL838X_SDS4_REG28 + 0x980)
|
||||
|
||||
/* Registers of the internal SerDes of the RTL8390 */
|
||||
#define RTL839X_SDS12_13_XSG0 (0xB800)
|
||||
|
||||
/* Registers of the internal Serdes of the 9300 */
|
||||
#define RTL930X_SDS_INDACS_CMD (0x03B0)
|
||||
#define RTL930X_SDS_INDACS_DATA (0x03B4)
|
||||
#define RTL930X_MAC_FORCE_MODE_CTRL (0xCA1C)
|
||||
|
||||
/*Registers of the internal SerDes of the 9310 */
|
||||
#define RTL931X_SERDES_INDRT_ACCESS_CTRL (0x5638)
|
||||
#define RTL931X_SERDES_INDRT_DATA_CTRL (0x563C)
|
||||
#define RTL931X_SERDES_MODE_CTRL (0x13cc)
|
||||
#define RTL931X_PS_SERDES_OFF_MODE_CTRL_ADDR (0x13F4)
|
||||
#define RTL931X_MAC_SERDES_MODE_CTRL(sds) (0x136C + (((sds) << 2)))
|
|
@ -0,0 +1,15 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2022 Markus Stockhausen
|
||||
*
|
||||
* RTL83XX clock indices
|
||||
*/
|
||||
#ifndef __DT_BINDINGS_CLOCK_RTL83XX_H
|
||||
#define __DT_BINDINGS_CLOCK_RTL83XX_H
|
||||
|
||||
#define CLK_CPU 0
|
||||
#define CLK_MEM 1
|
||||
#define CLK_LXB 2
|
||||
#define CLK_COUNT 3
|
||||
|
||||
#endif /* __DT_BINDINGS_CLOCK_RTL83XX_H */
|
|
@ -0,0 +1,103 @@
|
|||
From a362c0ce64866939c3daa17c76943cfed555b065 Mon Sep 17 00:00:00 2001
|
||||
From: Sander Vanheule <sander@svanheule.net>
|
||||
Date: Tue, 30 Mar 2021 19:48:42 +0200
|
||||
Subject: dt-bindings: gpio: Binding for Realtek Otto GPIO
|
||||
|
||||
Add a binding description for Realtek's GPIO controller found on several
|
||||
of their MIPS-based SoCs (codenamed Otto), such as the RTL838x and
|
||||
RTL839x series of switch SoCs.
|
||||
|
||||
A fallback binding 'realtek,otto-gpio' is provided for cases where the
|
||||
actual port ordering is not known yet, and enabling the interrupt
|
||||
controller may result in uncaught interrupts.
|
||||
|
||||
Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
|
||||
---
|
||||
.../bindings/gpio/realtek,otto-gpio.yaml | 78 ++++++++++++++++++++++
|
||||
1 file changed, 78 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml
|
||||
@@ -0,0 +1,78 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/gpio/realtek,otto-gpio.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Realtek Otto GPIO controller
|
||||
+
|
||||
+maintainers:
|
||||
+ - Sander Vanheule <sander@svanheule.net>
|
||||
+ - Bert Vermeulen <bert@biot.com>
|
||||
+
|
||||
+description: |
|
||||
+ Realtek's GPIO controller on their MIPS switch SoCs (Otto platform) consists
|
||||
+ of two banks of 32 GPIOs. These GPIOs can generate edge-triggered interrupts.
|
||||
+ Each bank's interrupts are cascased into one interrupt line on the parent
|
||||
+ interrupt controller, if provided.
|
||||
+ This binding allows defining a single bank in the devicetree. The interrupt
|
||||
+ controller is not supported on the fallback compatible name, which only
|
||||
+ allows for GPIO port use.
|
||||
+
|
||||
+properties:
|
||||
+ $nodename:
|
||||
+ pattern: "^gpio@[0-9a-f]+$"
|
||||
+
|
||||
+ compatible:
|
||||
+ items:
|
||||
+ - enum:
|
||||
+ - realtek,rtl8380-gpio
|
||||
+ - realtek,rtl8390-gpio
|
||||
+ - const: realtek,otto-gpio
|
||||
+
|
||||
+ reg:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ "#gpio-cells":
|
||||
+ const: 2
|
||||
+
|
||||
+ gpio-controller: true
|
||||
+
|
||||
+ ngpios:
|
||||
+ minimum: 1
|
||||
+ maximum: 32
|
||||
+
|
||||
+ interrupt-controller: true
|
||||
+
|
||||
+ "#interrupt-cells":
|
||||
+ const: 2
|
||||
+
|
||||
+ interrupts:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - reg
|
||||
+ - "#gpio-cells"
|
||||
+ - gpio-controller
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+dependencies:
|
||||
+ interrupt-controller: [ interrupts ]
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ gpio@3500 {
|
||||
+ compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio";
|
||||
+ reg = <0x3500 0x1c>;
|
||||
+ gpio-controller;
|
||||
+ #gpio-cells = <2>;
|
||||
+ ngpios = <24>;
|
||||
+ interrupt-controller;
|
||||
+ #interrupt-cells = <2>;
|
||||
+ interrupt-parent = <&rtlintc>;
|
||||
+ interrupts = <23>;
|
||||
+ };
|
||||
+
|
||||
+...
|
|
@ -0,0 +1,394 @@
|
|||
From f0f7d662e8514169c90d3d84cd6df773b2983088 Mon Sep 17 00:00:00 2001
|
||||
From: Sander Vanheule <sander@svanheule.net>
|
||||
Date: Tue, 30 Mar 2021 19:48:43 +0200
|
||||
Subject: gpio: Add Realtek Otto GPIO support
|
||||
|
||||
Realtek MIPS SoCs (platform name Otto) have GPIO controllers with up to
|
||||
64 GPIOs, divided over two banks. Each bank has a set of registers for
|
||||
32 GPIOs, with support for edge-triggered interrupts.
|
||||
|
||||
Each GPIO bank consists of four 8-bit GPIO ports (ABCD and EFGH). Most
|
||||
registers pack one bit per GPIO, except for the IMR register, which
|
||||
packs two bits per GPIO (AB-CD).
|
||||
|
||||
Although the byte order is currently assumed to have port A..D at offset
|
||||
0x0..0x3, this has been observed to be reversed on other, Lexra-based,
|
||||
SoCs (e.g. RTL8196E/97D/97F).
|
||||
|
||||
Interrupt support is disabled for the fallback devicetree-compatible
|
||||
'realtek,otto-gpio'. This allows for quick support of GPIO banks in
|
||||
which the byte order would be unknown. In this case, the port ordering
|
||||
in the IMR registers may not match the reversed order in the other
|
||||
registers (DCBA, and BA-DC or DC-BA).
|
||||
|
||||
Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
|
||||
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
|
||||
---
|
||||
drivers/gpio/Kconfig | 13 ++
|
||||
drivers/gpio/Makefile | 1 +
|
||||
drivers/gpio/gpio-realtek-otto.c | 325 +++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 339 insertions(+)
|
||||
create mode 100644 drivers/gpio/gpio-realtek-otto.c
|
||||
|
||||
--- a/drivers/gpio/Kconfig
|
||||
+++ b/drivers/gpio/Kconfig
|
||||
@@ -489,6 +489,19 @@ config GPIO_RDA
|
||||
help
|
||||
Say Y here to support RDA Micro GPIO controller.
|
||||
|
||||
+config GPIO_REALTEK_OTTO
|
||||
+ tristate "Realtek Otto GPIO support"
|
||||
+ depends on MACH_REALTEK_RTL
|
||||
+ default MACH_REALTEK_RTL
|
||||
+ select GPIO_GENERIC
|
||||
+ select GPIOLIB_IRQCHIP
|
||||
+ help
|
||||
+ The GPIO controller on the Otto MIPS platform supports up to two
|
||||
+ banks of 32 GPIOs, with edge triggered interrupts. The 32 GPIOs
|
||||
+ are grouped in four 8-bit wide ports.
|
||||
+
|
||||
+ When built as a module, the module will be called realtek_otto_gpio.
|
||||
+
|
||||
config GPIO_REG
|
||||
bool
|
||||
help
|
||||
--- a/drivers/gpio/Makefile
|
||||
+++ b/drivers/gpio/Makefile
|
||||
@@ -125,6 +125,7 @@ obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t
|
||||
obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o
|
||||
obj-$(CONFIG_GPIO_RDA) += gpio-rda.o
|
||||
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
|
||||
+obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o
|
||||
obj-$(CONFIG_GPIO_REG) += gpio-reg.o
|
||||
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
|
||||
obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/gpio/gpio-realtek-otto.c
|
||||
@@ -0,0 +1,325 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+
|
||||
+#include <linux/gpio/driver.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/minmax.h>
|
||||
+#include <linux/mod_devicetable.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/property.h>
|
||||
+
|
||||
+/*
|
||||
+ * Total register block size is 0x1C for one bank of four ports (A, B, C, D).
|
||||
+ * An optional second bank, with ports E, F, G, and H, may be present, starting
|
||||
+ * at register offset 0x1C.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Pin select: (0) "normal", (1) "dedicate peripheral"
|
||||
+ * Not used on RTL8380/RTL8390, peripheral selection is managed by control bits
|
||||
+ * in the peripheral registers.
|
||||
+ */
|
||||
+#define REALTEK_GPIO_REG_CNR 0x00
|
||||
+/* Clear bit (0) for input, set bit (1) for output */
|
||||
+#define REALTEK_GPIO_REG_DIR 0x08
|
||||
+#define REALTEK_GPIO_REG_DATA 0x0C
|
||||
+/* Read bit for IRQ status, write 1 to clear IRQ */
|
||||
+#define REALTEK_GPIO_REG_ISR 0x10
|
||||
+/* Two bits per GPIO in IMR registers */
|
||||
+#define REALTEK_GPIO_REG_IMR 0x14
|
||||
+#define REALTEK_GPIO_REG_IMR_AB 0x14
|
||||
+#define REALTEK_GPIO_REG_IMR_CD 0x18
|
||||
+#define REALTEK_GPIO_IMR_LINE_MASK GENMASK(1, 0)
|
||||
+#define REALTEK_GPIO_IRQ_EDGE_FALLING 1
|
||||
+#define REALTEK_GPIO_IRQ_EDGE_RISING 2
|
||||
+#define REALTEK_GPIO_IRQ_EDGE_BOTH 3
|
||||
+
|
||||
+#define REALTEK_GPIO_MAX 32
|
||||
+#define REALTEK_GPIO_PORTS_PER_BANK 4
|
||||
+
|
||||
+/**
|
||||
+ * realtek_gpio_ctrl - Realtek Otto GPIO driver data
|
||||
+ *
|
||||
+ * @gc: Associated gpio_chip instance
|
||||
+ * @base: Base address of the register block for a GPIO bank
|
||||
+ * @lock: Lock for accessing the IRQ registers and values
|
||||
+ * @intr_mask: Mask for interrupts lines
|
||||
+ * @intr_type: Interrupt type selection
|
||||
+ *
|
||||
+ * Because the interrupt mask register (IMR) combines the function of IRQ type
|
||||
+ * selection and masking, two extra values are stored. @intr_mask is used to
|
||||
+ * mask/unmask the interrupts for a GPIO port, and @intr_type is used to store
|
||||
+ * the selected interrupt types. The logical AND of these values is written to
|
||||
+ * IMR on changes.
|
||||
+ */
|
||||
+struct realtek_gpio_ctrl {
|
||||
+ struct gpio_chip gc;
|
||||
+ void __iomem *base;
|
||||
+ raw_spinlock_t lock;
|
||||
+ u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
|
||||
+ u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
|
||||
+};
|
||||
+
|
||||
+/* Expand with more flags as devices with other quirks are added */
|
||||
+enum realtek_gpio_flags {
|
||||
+ /*
|
||||
+ * Allow disabling interrupts, for cases where the port order is
|
||||
+ * unknown. This may result in a port mismatch between ISR and IMR.
|
||||
+ * An interrupt would appear to come from a different line than the
|
||||
+ * line the IRQ handler was assigned to, causing uncaught interrupts.
|
||||
+ */
|
||||
+ GPIO_INTERRUPTS_DISABLED = BIT(0),
|
||||
+};
|
||||
+
|
||||
+static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
|
||||
+{
|
||||
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
|
||||
+
|
||||
+ return container_of(gc, struct realtek_gpio_ctrl, gc);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Normal port order register access
|
||||
+ *
|
||||
+ * Port information is stored with the first port at offset 0, followed by the
|
||||
+ * second, etc. Most registers store one bit per GPIO and use a u8 value per
|
||||
+ * port. The two interrupt mask registers store two bits per GPIO, so use u16
|
||||
+ * values.
|
||||
+ */
|
||||
+static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
|
||||
+ unsigned int port, u16 irq_type, u16 irq_mask)
|
||||
+{
|
||||
+ iowrite16(irq_type & irq_mask, ctrl->base + REALTEK_GPIO_REG_IMR + 2 * port);
|
||||
+}
|
||||
+
|
||||
+static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
|
||||
+ unsigned int port, u8 mask)
|
||||
+{
|
||||
+ iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + port);
|
||||
+}
|
||||
+
|
||||
+static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
|
||||
+{
|
||||
+ return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + port);
|
||||
+}
|
||||
+
|
||||
+/* Set the rising and falling edge mask bits for a GPIO port pin */
|
||||
+static u16 realtek_gpio_imr_bits(unsigned int pin, u16 value)
|
||||
+{
|
||||
+ return (value & REALTEK_GPIO_IMR_LINE_MASK) << 2 * pin;
|
||||
+}
|
||||
+
|
||||
+static void realtek_gpio_irq_ack(struct irq_data *data)
|
||||
+{
|
||||
+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
|
||||
+ irq_hw_number_t line = irqd_to_hwirq(data);
|
||||
+ unsigned int port = line / 8;
|
||||
+ unsigned int port_pin = line % 8;
|
||||
+
|
||||
+ realtek_gpio_clear_isr(ctrl, port, BIT(port_pin));
|
||||
+}
|
||||
+
|
||||
+static void realtek_gpio_irq_unmask(struct irq_data *data)
|
||||
+{
|
||||
+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
|
||||
+ unsigned int line = irqd_to_hwirq(data);
|
||||
+ unsigned int port = line / 8;
|
||||
+ unsigned int port_pin = line % 8;
|
||||
+ unsigned long flags;
|
||||
+ u16 m;
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&ctrl->lock, flags);
|
||||
+ m = ctrl->intr_mask[port];
|
||||
+ m |= realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
|
||||
+ ctrl->intr_mask[port] = m;
|
||||
+ realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
|
||||
+ raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
||||
+}
|
||||
+
|
||||
+static void realtek_gpio_irq_mask(struct irq_data *data)
|
||||
+{
|
||||
+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
|
||||
+ unsigned int line = irqd_to_hwirq(data);
|
||||
+ unsigned int port = line / 8;
|
||||
+ unsigned int port_pin = line % 8;
|
||||
+ unsigned long flags;
|
||||
+ u16 m;
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&ctrl->lock, flags);
|
||||
+ m = ctrl->intr_mask[port];
|
||||
+ m &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
|
||||
+ ctrl->intr_mask[port] = m;
|
||||
+ realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
|
||||
+ raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
||||
+}
|
||||
+
|
||||
+static int realtek_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
||||
+{
|
||||
+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
|
||||
+ unsigned int line = irqd_to_hwirq(data);
|
||||
+ unsigned int port = line / 8;
|
||||
+ unsigned int port_pin = line % 8;
|
||||
+ unsigned long flags;
|
||||
+ u16 type, t;
|
||||
+
|
||||
+ switch (flow_type & IRQ_TYPE_SENSE_MASK) {
|
||||
+ case IRQ_TYPE_EDGE_FALLING:
|
||||
+ type = REALTEK_GPIO_IRQ_EDGE_FALLING;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_EDGE_RISING:
|
||||
+ type = REALTEK_GPIO_IRQ_EDGE_RISING;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_EDGE_BOTH:
|
||||
+ type = REALTEK_GPIO_IRQ_EDGE_BOTH;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ irq_set_handler_locked(data, handle_edge_irq);
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&ctrl->lock, flags);
|
||||
+ t = ctrl->intr_type[port];
|
||||
+ t &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
|
||||
+ t |= realtek_gpio_imr_bits(port_pin, type);
|
||||
+ ctrl->intr_type[port] = t;
|
||||
+ realtek_gpio_write_imr(ctrl, port, t, ctrl->intr_mask[port]);
|
||||
+ raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void realtek_gpio_irq_handler(struct irq_desc *desc)
|
||||
+{
|
||||
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
||||
+ struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
|
||||
+ struct irq_chip *irq_chip = irq_desc_get_chip(desc);
|
||||
+ unsigned int lines_done;
|
||||
+ unsigned int port_pin_count;
|
||||
+ unsigned int irq;
|
||||
+ unsigned long status;
|
||||
+ int offset;
|
||||
+
|
||||
+ chained_irq_enter(irq_chip, desc);
|
||||
+
|
||||
+ for (lines_done = 0; lines_done < gc->ngpio; lines_done += 8) {
|
||||
+ status = realtek_gpio_read_isr(ctrl, lines_done / 8);
|
||||
+ port_pin_count = min(gc->ngpio - lines_done, 8U);
|
||||
+ for_each_set_bit(offset, &status, port_pin_count) {
|
||||
+ irq = irq_find_mapping(gc->irq.domain, offset);
|
||||
+ generic_handle_irq(irq);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ chained_irq_exit(irq_chip, desc);
|
||||
+}
|
||||
+
|
||||
+static int realtek_gpio_irq_init(struct gpio_chip *gc)
|
||||
+{
|
||||
+ struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
|
||||
+ unsigned int port;
|
||||
+
|
||||
+ for (port = 0; (port * 8) < gc->ngpio; port++) {
|
||||
+ realtek_gpio_write_imr(ctrl, port, 0, 0);
|
||||
+ realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct irq_chip realtek_gpio_irq_chip = {
|
||||
+ .name = "realtek-otto-gpio",
|
||||
+ .irq_ack = realtek_gpio_irq_ack,
|
||||
+ .irq_mask = realtek_gpio_irq_mask,
|
||||
+ .irq_unmask = realtek_gpio_irq_unmask,
|
||||
+ .irq_set_type = realtek_gpio_irq_set_type,
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id realtek_gpio_of_match[] = {
|
||||
+ {
|
||||
+ .compatible = "realtek,otto-gpio",
|
||||
+ .data = (void *)GPIO_INTERRUPTS_DISABLED,
|
||||
+ },
|
||||
+ {
|
||||
+ .compatible = "realtek,rtl8380-gpio",
|
||||
+ },
|
||||
+ {
|
||||
+ .compatible = "realtek,rtl8390-gpio",
|
||||
+ },
|
||||
+ {}
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, realtek_gpio_of_match);
|
||||
+
|
||||
+static int realtek_gpio_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ unsigned int dev_flags;
|
||||
+ struct gpio_irq_chip *girq;
|
||||
+ struct realtek_gpio_ctrl *ctrl;
|
||||
+ u32 ngpios;
|
||||
+ int err, irq;
|
||||
+
|
||||
+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
|
||||
+ if (!ctrl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ dev_flags = (unsigned int) device_get_match_data(dev);
|
||||
+
|
||||
+ ngpios = REALTEK_GPIO_MAX;
|
||||
+ device_property_read_u32(dev, "ngpios", &ngpios);
|
||||
+
|
||||
+ if (ngpios > REALTEK_GPIO_MAX) {
|
||||
+ dev_err(&pdev->dev, "invalid ngpios (max. %d)\n",
|
||||
+ REALTEK_GPIO_MAX);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ ctrl->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(ctrl->base))
|
||||
+ return PTR_ERR(ctrl->base);
|
||||
+
|
||||
+ raw_spin_lock_init(&ctrl->lock);
|
||||
+
|
||||
+ err = bgpio_init(&ctrl->gc, dev, 4,
|
||||
+ ctrl->base + REALTEK_GPIO_REG_DATA, NULL, NULL,
|
||||
+ ctrl->base + REALTEK_GPIO_REG_DIR, NULL,
|
||||
+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "unable to init generic GPIO");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ ctrl->gc.ngpio = ngpios;
|
||||
+ ctrl->gc.owner = THIS_MODULE;
|
||||
+
|
||||
+ irq = platform_get_irq_optional(pdev, 0);
|
||||
+ if (!(dev_flags & GPIO_INTERRUPTS_DISABLED) && irq > 0) {
|
||||
+ girq = &ctrl->gc.irq;
|
||||
+ girq->chip = &realtek_gpio_irq_chip;
|
||||
+ girq->default_type = IRQ_TYPE_NONE;
|
||||
+ girq->handler = handle_bad_irq;
|
||||
+ girq->parent_handler = realtek_gpio_irq_handler;
|
||||
+ girq->num_parents = 1;
|
||||
+ girq->parents = devm_kcalloc(dev, girq->num_parents,
|
||||
+ sizeof(*girq->parents), GFP_KERNEL);
|
||||
+ if (!girq->parents)
|
||||
+ return -ENOMEM;
|
||||
+ girq->parents[0] = irq;
|
||||
+ girq->init_hw = realtek_gpio_irq_init;
|
||||
+ }
|
||||
+
|
||||
+ return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver realtek_gpio_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "realtek-otto-gpio",
|
||||
+ .of_match_table = realtek_gpio_of_match,
|
||||
+ },
|
||||
+ .probe = realtek_gpio_probe,
|
||||
+};
|
||||
+module_platform_driver(realtek_gpio_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Realtek Otto GPIO support");
|
||||
+MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");
|
||||
+MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,57 @@
|
|||
From 6acbd614c2c8d3b8de5fb7605d6e24b9b3a8a17b Mon Sep 17 00:00:00 2001
|
||||
From: Bert Vermeulen <bert@biot.com>
|
||||
Date: Wed, 20 Jan 2021 14:59:27 +0100
|
||||
Subject: spi: Realtek RTL838x/RTL839x SPI controller
|
||||
|
||||
Signed-off-by: Bert Vermeulen <bert@biot.com>
|
||||
Link: https://lore.kernel.org/r/20210120135928.246054-2-bert@biot.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
.../devicetree/bindings/spi/realtek,rtl-spi.yaml | 41 ++++++++++++++++++++++
|
||||
1 file changed, 41 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml
|
||||
@@ -0,0 +1,41 @@
|
||||
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/spi/realtek,rtl-spi.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Realtek RTL838x/RTL839x SPI controller
|
||||
+
|
||||
+maintainers:
|
||||
+ - Bert Vermeulen <bert@biot.com>
|
||||
+ - Birger Koblitz <mail@birger-koblitz.de>
|
||||
+
|
||||
+allOf:
|
||||
+ - $ref: "spi-controller.yaml#"
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ oneOf:
|
||||
+ - const: realtek,rtl8380-spi
|
||||
+ - const: realtek,rtl8382-spi
|
||||
+ - const: realtek,rtl8391-spi
|
||||
+ - const: realtek,rtl8392-spi
|
||||
+ - const: realtek,rtl8393-spi
|
||||
+
|
||||
+ reg:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - reg
|
||||
+
|
||||
+unevaluatedProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ spi: spi@1200 {
|
||||
+ compatible = "realtek,rtl8382-spi";
|
||||
+ reg = <0x1200 0x100>;
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ };
|
|
@ -0,0 +1,248 @@
|
|||
From a8af5cc2ff1e804694629a8ef320935629dd15ba Mon Sep 17 00:00:00 2001
|
||||
From: Bert Vermeulen <bert@biot.com>
|
||||
Date: Wed, 20 Jan 2021 14:59:28 +0100
|
||||
Subject: spi: realtek-rtl: Add support for Realtek RTL838x/RTL839x SPI
|
||||
controllers
|
||||
|
||||
This driver likely also supports earlier (RTL8196) and later (RTL93xx)
|
||||
SoCs.
|
||||
|
||||
The SPI hardware in these SoCs is specifically intended for connecting NOR
|
||||
bootflash chips, and only used for that in dozens of examined devices.
|
||||
However boiled down to basics, it's really just a half-duplex SPI
|
||||
controller.
|
||||
|
||||
The hardware appears to have a vestigial second chip-select control, but
|
||||
it hasn't been seen in the wild and is thus not supported.
|
||||
|
||||
Signed-off-by: Bert Vermeulen <bert@biot.com>
|
||||
Link: https://lore.kernel.org/r/20210120135928.246054-3-bert@biot.com
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/Makefile | 1 +
|
||||
drivers/spi/spi-realtek-rtl.c | 209 ++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 210 insertions(+)
|
||||
create mode 100644 drivers/spi/spi-realtek-rtl.c
|
||||
|
||||
--- a/drivers/spi/Makefile
|
||||
+++ b/drivers/spi/Makefile
|
||||
@@ -94,6 +94,7 @@ obj-$(CONFIG_SPI_QCOM_QSPI) += spi-qcom
|
||||
obj-$(CONFIG_SPI_QUP) += spi-qup.o
|
||||
obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
|
||||
obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o
|
||||
+obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o
|
||||
obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o
|
||||
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
|
||||
obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/spi/spi-realtek-rtl.c
|
||||
@@ -0,0 +1,209 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/mod_devicetable.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+
|
||||
+struct rtspi {
|
||||
+ void __iomem *base;
|
||||
+};
|
||||
+
|
||||
+/* SPI Flash Configuration Register */
|
||||
+#define RTL_SPI_SFCR 0x00
|
||||
+#define RTL_SPI_SFCR_RBO BIT(28)
|
||||
+#define RTL_SPI_SFCR_WBO BIT(27)
|
||||
+
|
||||
+/* SPI Flash Control and Status Register */
|
||||
+#define RTL_SPI_SFCSR 0x08
|
||||
+#define RTL_SPI_SFCSR_CSB0 BIT(31)
|
||||
+#define RTL_SPI_SFCSR_CSB1 BIT(30)
|
||||
+#define RTL_SPI_SFCSR_RDY BIT(27)
|
||||
+#define RTL_SPI_SFCSR_CS BIT(24)
|
||||
+#define RTL_SPI_SFCSR_LEN_MASK ~(0x03 << 28)
|
||||
+#define RTL_SPI_SFCSR_LEN1 (0x00 << 28)
|
||||
+#define RTL_SPI_SFCSR_LEN4 (0x03 << 28)
|
||||
+
|
||||
+/* SPI Flash Data Register */
|
||||
+#define RTL_SPI_SFDR 0x0c
|
||||
+
|
||||
+#define REG(x) (rtspi->base + x)
|
||||
+
|
||||
+
|
||||
+static void rt_set_cs(struct spi_device *spi, bool active)
|
||||
+{
|
||||
+ struct rtspi *rtspi = spi_controller_get_devdata(spi->controller);
|
||||
+ u32 value;
|
||||
+
|
||||
+ /* CS0 bit is active low */
|
||||
+ value = readl(REG(RTL_SPI_SFCSR));
|
||||
+ if (active)
|
||||
+ value |= RTL_SPI_SFCSR_CSB0;
|
||||
+ else
|
||||
+ value &= ~RTL_SPI_SFCSR_CSB0;
|
||||
+ writel(value, REG(RTL_SPI_SFCSR));
|
||||
+}
|
||||
+
|
||||
+static void set_size(struct rtspi *rtspi, int size)
|
||||
+{
|
||||
+ u32 value;
|
||||
+
|
||||
+ value = readl(REG(RTL_SPI_SFCSR));
|
||||
+ value &= RTL_SPI_SFCSR_LEN_MASK;
|
||||
+ if (size == 4)
|
||||
+ value |= RTL_SPI_SFCSR_LEN4;
|
||||
+ else if (size == 1)
|
||||
+ value |= RTL_SPI_SFCSR_LEN1;
|
||||
+ writel(value, REG(RTL_SPI_SFCSR));
|
||||
+}
|
||||
+
|
||||
+static inline void wait_ready(struct rtspi *rtspi)
|
||||
+{
|
||||
+ while (!(readl(REG(RTL_SPI_SFCSR)) & RTL_SPI_SFCSR_RDY))
|
||||
+ cpu_relax();
|
||||
+}
|
||||
+static void send4(struct rtspi *rtspi, const u32 *buf)
|
||||
+{
|
||||
+ wait_ready(rtspi);
|
||||
+ set_size(rtspi, 4);
|
||||
+ writel(*buf, REG(RTL_SPI_SFDR));
|
||||
+}
|
||||
+
|
||||
+static void send1(struct rtspi *rtspi, const u8 *buf)
|
||||
+{
|
||||
+ wait_ready(rtspi);
|
||||
+ set_size(rtspi, 1);
|
||||
+ writel(buf[0] << 24, REG(RTL_SPI_SFDR));
|
||||
+}
|
||||
+
|
||||
+static void rcv4(struct rtspi *rtspi, u32 *buf)
|
||||
+{
|
||||
+ wait_ready(rtspi);
|
||||
+ set_size(rtspi, 4);
|
||||
+ *buf = readl(REG(RTL_SPI_SFDR));
|
||||
+}
|
||||
+
|
||||
+static void rcv1(struct rtspi *rtspi, u8 *buf)
|
||||
+{
|
||||
+ wait_ready(rtspi);
|
||||
+ set_size(rtspi, 1);
|
||||
+ *buf = readl(REG(RTL_SPI_SFDR)) >> 24;
|
||||
+}
|
||||
+
|
||||
+static int transfer_one(struct spi_controller *ctrl, struct spi_device *spi,
|
||||
+ struct spi_transfer *xfer)
|
||||
+{
|
||||
+ struct rtspi *rtspi = spi_controller_get_devdata(ctrl);
|
||||
+ void *rx_buf;
|
||||
+ const void *tx_buf;
|
||||
+ int cnt;
|
||||
+
|
||||
+ tx_buf = xfer->tx_buf;
|
||||
+ rx_buf = xfer->rx_buf;
|
||||
+ cnt = xfer->len;
|
||||
+ if (tx_buf) {
|
||||
+ while (cnt >= 4) {
|
||||
+ send4(rtspi, tx_buf);
|
||||
+ tx_buf += 4;
|
||||
+ cnt -= 4;
|
||||
+ }
|
||||
+ while (cnt) {
|
||||
+ send1(rtspi, tx_buf);
|
||||
+ tx_buf++;
|
||||
+ cnt--;
|
||||
+ }
|
||||
+ } else if (rx_buf) {
|
||||
+ while (cnt >= 4) {
|
||||
+ rcv4(rtspi, rx_buf);
|
||||
+ rx_buf += 4;
|
||||
+ cnt -= 4;
|
||||
+ }
|
||||
+ while (cnt) {
|
||||
+ rcv1(rtspi, rx_buf);
|
||||
+ rx_buf++;
|
||||
+ cnt--;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ spi_finalize_current_transfer(ctrl);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void init_hw(struct rtspi *rtspi)
|
||||
+{
|
||||
+ u32 value;
|
||||
+
|
||||
+ /* Turn on big-endian byte ordering */
|
||||
+ value = readl(REG(RTL_SPI_SFCR));
|
||||
+ value |= RTL_SPI_SFCR_RBO | RTL_SPI_SFCR_WBO;
|
||||
+ writel(value, REG(RTL_SPI_SFCR));
|
||||
+
|
||||
+ value = readl(REG(RTL_SPI_SFCSR));
|
||||
+ /* Permanently disable CS1, since it's never used */
|
||||
+ value |= RTL_SPI_SFCSR_CSB1;
|
||||
+ /* Select CS0 for use */
|
||||
+ value &= RTL_SPI_SFCSR_CS;
|
||||
+ writel(value, REG(RTL_SPI_SFCSR));
|
||||
+}
|
||||
+
|
||||
+static int realtek_rtl_spi_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct spi_controller *ctrl;
|
||||
+ struct rtspi *rtspi;
|
||||
+ int err;
|
||||
+
|
||||
+ ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*rtspi));
|
||||
+ if (!ctrl) {
|
||||
+ dev_err(&pdev->dev, "Error allocating SPI controller\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ platform_set_drvdata(pdev, ctrl);
|
||||
+ rtspi = spi_controller_get_devdata(ctrl);
|
||||
+
|
||||
+ rtspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
|
||||
+ if (IS_ERR(rtspi->base)) {
|
||||
+ dev_err(&pdev->dev, "Could not map SPI register address");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ init_hw(rtspi);
|
||||
+
|
||||
+ ctrl->dev.of_node = pdev->dev.of_node;
|
||||
+ ctrl->flags = SPI_CONTROLLER_HALF_DUPLEX;
|
||||
+ ctrl->set_cs = rt_set_cs;
|
||||
+ ctrl->transfer_one = transfer_one;
|
||||
+
|
||||
+ err = devm_spi_register_controller(&pdev->dev, ctrl);
|
||||
+ if (err) {
|
||||
+ dev_err(&pdev->dev, "Could not register SPI controller\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static const struct of_device_id realtek_rtl_spi_of_ids[] = {
|
||||
+ { .compatible = "realtek,rtl8380-spi" },
|
||||
+ { .compatible = "realtek,rtl8382-spi" },
|
||||
+ { .compatible = "realtek,rtl8391-spi" },
|
||||
+ { .compatible = "realtek,rtl8392-spi" },
|
||||
+ { .compatible = "realtek,rtl8393-spi" },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, realtek_rtl_spi_of_ids);
|
||||
+
|
||||
+static struct platform_driver realtek_rtl_spi_driver = {
|
||||
+ .probe = realtek_rtl_spi_probe,
|
||||
+ .driver = {
|
||||
+ .name = "realtek-rtl-spi",
|
||||
+ .of_match_table = realtek_rtl_spi_of_ids,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(realtek_rtl_spi_driver);
|
||||
+
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_AUTHOR("Bert Vermeulen <bert@biot.com>");
|
||||
+MODULE_DESCRIPTION("Realtek RTL SPI driver");
|
|
@ -0,0 +1,78 @@
|
|||
From 4a2b92a5d3519fc2c1edda4d4aa0e05bff41e8de Mon Sep 17 00:00:00 2001
|
||||
From: Bert Vermeulen <bert@biot.com>
|
||||
Date: Fri, 22 Jan 2021 21:42:23 +0100
|
||||
Subject: dt-bindings: interrupt-controller: Add Realtek RTL838x/RTL839x
|
||||
support
|
||||
|
||||
Document the binding for the Realtek RTL838x/RTL839x interrupt controller.
|
||||
|
||||
Reviewed-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Bert Vermeulen <bert@biot.com>
|
||||
[maz: Add a commit message, as the author couldn't be bothered...]
|
||||
Signed-off-by: Marc Zyngier <maz@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20210122204224.509124-2-bert@biot.com
|
||||
---
|
||||
.../interrupt-controller/realtek,rtl-intc.yaml | 57 ++++++++++++++++++++++
|
||||
1 file changed, 57 insertions(+)
|
||||
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
|
||||
|
||||
--- /dev/null
|
||||
+++ b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
|
||||
@@ -0,0 +1,57 @@
|
||||
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
+%YAML 1.2
|
||||
+---
|
||||
+$id: http://devicetree.org/schemas/interrupt-controller/realtek,rtl-intc.yaml#
|
||||
+$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
+
|
||||
+title: Realtek RTL SoC interrupt controller devicetree bindings
|
||||
+
|
||||
+maintainers:
|
||||
+ - Birger Koblitz <mail@birger-koblitz.de>
|
||||
+ - Bert Vermeulen <bert@biot.com>
|
||||
+ - John Crispin <john@phrozen.org>
|
||||
+
|
||||
+properties:
|
||||
+ compatible:
|
||||
+ const: realtek,rtl-intc
|
||||
+
|
||||
+ "#interrupt-cells":
|
||||
+ const: 1
|
||||
+
|
||||
+ reg:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ interrupts:
|
||||
+ maxItems: 1
|
||||
+
|
||||
+ interrupt-controller: true
|
||||
+
|
||||
+ "#address-cells":
|
||||
+ const: 0
|
||||
+
|
||||
+ interrupt-map:
|
||||
+ description: Describes mapping from SoC interrupts to CPU interrupts
|
||||
+
|
||||
+required:
|
||||
+ - compatible
|
||||
+ - reg
|
||||
+ - "#interrupt-cells"
|
||||
+ - interrupt-controller
|
||||
+ - "#address-cells"
|
||||
+ - interrupt-map
|
||||
+
|
||||
+additionalProperties: false
|
||||
+
|
||||
+examples:
|
||||
+ - |
|
||||
+ intc: interrupt-controller@3000 {
|
||||
+ compatible = "realtek,rtl-intc";
|
||||
+ #interrupt-cells = <1>;
|
||||
+ interrupt-controller;
|
||||
+ reg = <0x3000 0x20>;
|
||||
+ #address-cells = <0>;
|
||||
+ interrupt-map =
|
||||
+ <31 &cpuintc 2>,
|
||||
+ <30 &cpuintc 1>,
|
||||
+ <29 &cpuintc 5>;
|
||||
+ };
|
|
@ -0,0 +1,211 @@
|
|||
From 9f3a0f34b84ad1b9a8f2bdae44b66f16685b2143 Mon Sep 17 00:00:00 2001
|
||||
From: Bert Vermeulen <bert@biot.com>
|
||||
Date: Fri, 22 Jan 2021 21:42:24 +0100
|
||||
Subject: irqchip: Add support for Realtek RTL838x/RTL839x interrupt controller
|
||||
|
||||
This is a standard IRQ driver with only status and mask registers.
|
||||
|
||||
The mapping from SoC interrupts (18-31) to MIPS core interrupts is
|
||||
done via an interrupt-map in device tree.
|
||||
|
||||
Signed-off-by: Bert Vermeulen <bert@biot.com>
|
||||
Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
|
||||
Acked-by: John Crispin <john@phrozen.org>
|
||||
Signed-off-by: Marc Zyngier <maz@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20210122204224.509124-3-bert@biot.com
|
||||
---
|
||||
drivers/irqchip/Makefile | 1 +
|
||||
drivers/irqchip/irq-realtek-rtl.c | 180 ++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 181 insertions(+)
|
||||
create mode 100644 drivers/irqchip/irq-realtek-rtl.c
|
||||
|
||||
--- a/drivers/irqchip/Makefile
|
||||
+++ b/drivers/irqchip/Makefile
|
||||
@@ -114,3 +114,4 @@ obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-l
|
||||
obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o
|
||||
obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o
|
||||
obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o
|
||||
+obj-$(CONFIG_MACH_REALTEK_RTL) += irq-realtek-rtl.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/irqchip/irq-realtek-rtl.c
|
||||
@@ -0,0 +1,180 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (C) 2020 Birger Koblitz <mail@birger-koblitz.de>
|
||||
+ * Copyright (C) 2020 Bert Vermeulen <bert@biot.com>
|
||||
+ * Copyright (C) 2020 John Crispin <john@phrozen.org>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/of_irq.h>
|
||||
+#include <linux/irqchip.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/irqchip/chained_irq.h>
|
||||
+
|
||||
+/* Global Interrupt Mask Register */
|
||||
+#define RTL_ICTL_GIMR 0x00
|
||||
+/* Global Interrupt Status Register */
|
||||
+#define RTL_ICTL_GISR 0x04
|
||||
+/* Interrupt Routing Registers */
|
||||
+#define RTL_ICTL_IRR0 0x08
|
||||
+#define RTL_ICTL_IRR1 0x0c
|
||||
+#define RTL_ICTL_IRR2 0x10
|
||||
+#define RTL_ICTL_IRR3 0x14
|
||||
+
|
||||
+#define REG(x) (realtek_ictl_base + x)
|
||||
+
|
||||
+static DEFINE_RAW_SPINLOCK(irq_lock);
|
||||
+static void __iomem *realtek_ictl_base;
|
||||
+
|
||||
+static void realtek_ictl_unmask_irq(struct irq_data *i)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ u32 value;
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&irq_lock, flags);
|
||||
+
|
||||
+ value = readl(REG(RTL_ICTL_GIMR));
|
||||
+ value |= BIT(i->hwirq);
|
||||
+ writel(value, REG(RTL_ICTL_GIMR));
|
||||
+
|
||||
+ raw_spin_unlock_irqrestore(&irq_lock, flags);
|
||||
+}
|
||||
+
|
||||
+static void realtek_ictl_mask_irq(struct irq_data *i)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ u32 value;
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&irq_lock, flags);
|
||||
+
|
||||
+ value = readl(REG(RTL_ICTL_GIMR));
|
||||
+ value &= ~BIT(i->hwirq);
|
||||
+ writel(value, REG(RTL_ICTL_GIMR));
|
||||
+
|
||||
+ raw_spin_unlock_irqrestore(&irq_lock, flags);
|
||||
+}
|
||||
+
|
||||
+static struct irq_chip realtek_ictl_irq = {
|
||||
+ .name = "realtek-rtl-intc",
|
||||
+ .irq_mask = realtek_ictl_mask_irq,
|
||||
+ .irq_unmask = realtek_ictl_unmask_irq,
|
||||
+};
|
||||
+
|
||||
+static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
|
||||
+{
|
||||
+ irq_set_chip_and_handler(hw, &realtek_ictl_irq, handle_level_irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct irq_domain_ops irq_domain_ops = {
|
||||
+ .map = intc_map,
|
||||
+ .xlate = irq_domain_xlate_onecell,
|
||||
+};
|
||||
+
|
||||
+static void realtek_irq_dispatch(struct irq_desc *desc)
|
||||
+{
|
||||
+ struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
+ struct irq_domain *domain;
|
||||
+ unsigned int pending;
|
||||
+
|
||||
+ chained_irq_enter(chip, desc);
|
||||
+ pending = readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR));
|
||||
+ if (unlikely(!pending)) {
|
||||
+ spurious_interrupt();
|
||||
+ goto out;
|
||||
+ }
|
||||
+ domain = irq_desc_get_handler_data(desc);
|
||||
+ generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
|
||||
+
|
||||
+out:
|
||||
+ chained_irq_exit(chip, desc);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * SoC interrupts are cascaded to MIPS CPU interrupts according to the
|
||||
+ * interrupt-map in the device tree. Each SoC interrupt gets 4 bits for
|
||||
+ * the CPU interrupt in an Interrupt Routing Register. Max 32 SoC interrupts
|
||||
+ * thus go into 4 IRRs.
|
||||
+ */
|
||||
+static int __init map_interrupts(struct device_node *node, struct irq_domain *domain)
|
||||
+{
|
||||
+ struct device_node *cpu_ictl;
|
||||
+ const __be32 *imap;
|
||||
+ u32 imaplen, soc_int, cpu_int, tmp, regs[4];
|
||||
+ int ret, i, irr_regs[] = {
|
||||
+ RTL_ICTL_IRR3,
|
||||
+ RTL_ICTL_IRR2,
|
||||
+ RTL_ICTL_IRR1,
|
||||
+ RTL_ICTL_IRR0,
|
||||
+ };
|
||||
+ u8 mips_irqs_set;
|
||||
+
|
||||
+ ret = of_property_read_u32(node, "#address-cells", &tmp);
|
||||
+ if (ret || tmp)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ imap = of_get_property(node, "interrupt-map", &imaplen);
|
||||
+ if (!imap || imaplen % 3)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mips_irqs_set = 0;
|
||||
+ memset(regs, 0, sizeof(regs));
|
||||
+ for (i = 0; i < imaplen; i += 3 * sizeof(u32)) {
|
||||
+ soc_int = be32_to_cpup(imap);
|
||||
+ if (soc_int > 31)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ cpu_ictl = of_find_node_by_phandle(be32_to_cpup(imap + 1));
|
||||
+ if (!cpu_ictl)
|
||||
+ return -EINVAL;
|
||||
+ ret = of_property_read_u32(cpu_ictl, "#interrupt-cells", &tmp);
|
||||
+ if (ret || tmp != 1)
|
||||
+ return -EINVAL;
|
||||
+ of_node_put(cpu_ictl);
|
||||
+
|
||||
+ cpu_int = be32_to_cpup(imap + 2);
|
||||
+ if (cpu_int > 7)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!(mips_irqs_set & BIT(cpu_int))) {
|
||||
+ irq_set_chained_handler_and_data(cpu_int, realtek_irq_dispatch,
|
||||
+ domain);
|
||||
+ mips_irqs_set |= BIT(cpu_int);
|
||||
+ }
|
||||
+
|
||||
+ regs[(soc_int * 4) / 32] |= cpu_int << (soc_int * 4) % 32;
|
||||
+ imap += 3;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 4; i++)
|
||||
+ writel(regs[i], REG(irr_regs[i]));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __init realtek_rtl_of_init(struct device_node *node, struct device_node *parent)
|
||||
+{
|
||||
+ struct irq_domain *domain;
|
||||
+ int ret;
|
||||
+
|
||||
+ realtek_ictl_base = of_iomap(node, 0);
|
||||
+ if (!realtek_ictl_base)
|
||||
+ return -ENXIO;
|
||||
+
|
||||
+ /* Disable all cascaded interrupts */
|
||||
+ writel(0, REG(RTL_ICTL_GIMR));
|
||||
+
|
||||
+ domain = irq_domain_add_simple(node, 32, 0,
|
||||
+ &irq_domain_ops, NULL);
|
||||
+
|
||||
+ ret = map_interrupts(node, domain);
|
||||
+ if (ret) {
|
||||
+ pr_err("invalid interrupt map\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+IRQCHIP_DECLARE(realtek_rtl_intc, "realtek,rtl-intc", realtek_rtl_of_init);
|
|
@ -0,0 +1,22 @@
|
|||
From: Sander Vanheule <sander@svanheule.net>
|
||||
Subject: gpio: realtek-otto: fix GPIO line IRQ offset
|
||||
|
||||
The irqchip uses one domain for all GPIO lines, so th line offset should be
|
||||
determined w.r.t. the first line of the first port, not the first line of the
|
||||
triggered port.
|
||||
|
||||
Fixes: 0d82fb1127fb ("gpio: Add Realtek Otto GPIO support")
|
||||
Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
Link: https://lore.kernel.org/linux-gpio/20211028085243.34360-1-sander@svanheule.net/
|
||||
|
||||
--- a/drivers/gpio/gpio-realtek-otto.c
|
||||
+++ b/drivers/gpio/gpio-realtek-otto.c
|
||||
@@ -206,7 +206,7 @@ static void realtek_gpio_irq_handler(str
|
||||
status = realtek_gpio_read_isr(ctrl, lines_done / 8);
|
||||
port_pin_count = min(gc->ngpio - lines_done, 8U);
|
||||
for_each_set_bit(offset, &status, port_pin_count) {
|
||||
- irq = irq_find_mapping(gc->irq.domain, offset);
|
||||
+ irq = irq_find_mapping(gc->irq.domain, offset + lines_done);
|
||||
generic_handle_irq(irq);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,467 @@
|
|||
From 293903b9dfe43520f01374dc1661be11d6838c49 Mon Sep 17 00:00:00 2001
|
||||
From: Sander Vanheule <sander@svanheule.net>
|
||||
Date: Thu, 18 Nov 2021 17:29:52 +0100
|
||||
Subject: watchdog: Add Realtek Otto watchdog timer
|
||||
|
||||
Realtek MIPS SoCs (platform name Otto) have a watchdog timer with
|
||||
pretimeout notifitication support. The WDT can (partially) hard reset,
|
||||
or soft reset the SoC.
|
||||
|
||||
This driver implements all features as described in the devicetree
|
||||
binding, except the phase2 interrupt, and also functions as a restart
|
||||
handler. The cpu reset mode is considered to be a "warm" restart, since
|
||||
this mode does not reset all peripherals. Being an embedded system
|
||||
though, the "cpu" and "software" modes will still cause the bootloader
|
||||
to run on restart.
|
||||
|
||||
It is not known how a forced system reset can be disabled on the
|
||||
supported platforms. This means that the phase2 interrupt will only fire
|
||||
at the same time as reset, so implementing phase2 is of little use.
|
||||
|
||||
Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
|
||||
Link: https://lore.kernel.org/r/6d060bccbdcc709cfa79203485db85aad3c3beb5.1637252610.git.sander@svanheule.net
|
||||
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
|
||||
---
|
||||
MAINTAINERS | 7 +
|
||||
drivers/watchdog/Kconfig | 13 ++
|
||||
drivers/watchdog/Makefile | 1 +
|
||||
drivers/watchdog/realtek_otto_wdt.c | 384 ++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 405 insertions(+)
|
||||
create mode 100644 drivers/watchdog/realtek_otto_wdt.c
|
||||
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -14816,6 +14816,13 @@ S: Maintained
|
||||
F: include/sound/rt*.h
|
||||
F: sound/soc/codecs/rt*
|
||||
|
||||
+REALTEK OTTO WATCHDOG
|
||||
+M: Sander Vanheule <sander@svanheule.net>
|
||||
+L: linux-watchdog@vger.kernel.org
|
||||
+S: Maintained
|
||||
+F: Documentation/devicetree/bindings/watchdog/realtek,otto-wdt.yaml
|
||||
+F: driver/watchdog/realtek_otto_wdt.c
|
||||
+
|
||||
REALTEK RTL83xx SMI DSA ROUTER CHIPS
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
S: Maintained
|
||||
--- a/drivers/watchdog/Kconfig
|
||||
+++ b/drivers/watchdog/Kconfig
|
||||
@@ -995,6 +995,19 @@ config RTD119X_WATCHDOG
|
||||
Say Y here to include support for the watchdog timer in
|
||||
Realtek RTD1295 SoCs.
|
||||
|
||||
+config REALTEK_OTTO_WDT
|
||||
+ tristate "Realtek Otto MIPS watchdog support"
|
||||
+ depends on MACH_REALTEK_RTL || COMPILE_TEST
|
||||
+ depends on COMMON_CLK
|
||||
+ select WATCHDOG_CORE
|
||||
+ default MACH_REALTEK_RTL
|
||||
+ help
|
||||
+ Say Y here to include support for the watchdog timer on Realtek
|
||||
+ RTL838x, RTL839x, RTL930x SoCs. This watchdog has pretimeout
|
||||
+ notifications and system reset on timeout.
|
||||
+
|
||||
+ When built as a module this will be called realtek_otto_wdt.
|
||||
+
|
||||
config SPRD_WATCHDOG
|
||||
tristate "Spreadtrum watchdog support"
|
||||
depends on ARCH_SPRD || COMPILE_TEST
|
||||
--- a/drivers/watchdog/Makefile
|
||||
+++ b/drivers/watchdog/Makefile
|
||||
@@ -174,6 +174,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
|
||||
obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
|
||||
obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o
|
||||
obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o
|
||||
+obj-$(CONFIG_REALTEK_OTTO_WDT) += realtek_otto_wdt.o
|
||||
|
||||
# PARISC Architecture
|
||||
|
||||
--- /dev/null
|
||||
+++ b/drivers/watchdog/realtek_otto_wdt.c
|
||||
@@ -0,0 +1,384 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+
|
||||
+/*
|
||||
+ * Realtek Otto MIPS platform watchdog
|
||||
+ *
|
||||
+ * Watchdog timer that will reset the system after timeout, using the selected
|
||||
+ * reset mode.
|
||||
+ *
|
||||
+ * Counter scaling and timeouts:
|
||||
+ * - Base prescale of (2 << 25), providing tick duration T_0: 168ms @ 200MHz
|
||||
+ * - PRESCALE: logarithmic prescaler adding a factor of {1, 2, 4, 8}
|
||||
+ * - Phase 1: Times out after (PHASE1 + 1) × PRESCALE × T_0
|
||||
+ * Generates an interrupt, WDT cannot be stopped after phase 1
|
||||
+ * - Phase 2: starts after phase 1, times out after (PHASE2 + 1) × PRESCALE × T_0
|
||||
+ * Resets the system according to RST_MODE
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bits.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/math.h>
|
||||
+#include <linux/minmax.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mod_devicetable.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/property.h>
|
||||
+#include <linux/reboot.h>
|
||||
+#include <linux/watchdog.h>
|
||||
+
|
||||
+#define OTTO_WDT_REG_CNTR 0x0
|
||||
+#define OTTO_WDT_CNTR_PING BIT(31)
|
||||
+
|
||||
+#define OTTO_WDT_REG_INTR 0x4
|
||||
+#define OTTO_WDT_INTR_PHASE_1 BIT(31)
|
||||
+#define OTTO_WDT_INTR_PHASE_2 BIT(30)
|
||||
+
|
||||
+#define OTTO_WDT_REG_CTRL 0x8
|
||||
+#define OTTO_WDT_CTRL_ENABLE BIT(31)
|
||||
+#define OTTO_WDT_CTRL_PRESCALE GENMASK(30, 29)
|
||||
+#define OTTO_WDT_CTRL_PHASE1 GENMASK(26, 22)
|
||||
+#define OTTO_WDT_CTRL_PHASE2 GENMASK(19, 15)
|
||||
+#define OTTO_WDT_CTRL_RST_MODE GENMASK(1, 0)
|
||||
+#define OTTO_WDT_MODE_SOC 0
|
||||
+#define OTTO_WDT_MODE_CPU 1
|
||||
+#define OTTO_WDT_MODE_SOFTWARE 2
|
||||
+#define OTTO_WDT_CTRL_DEFAULT OTTO_WDT_MODE_CPU
|
||||
+
|
||||
+#define OTTO_WDT_PRESCALE_MAX 3
|
||||
+
|
||||
+/*
|
||||
+ * One higher than the max values contained in PHASE{1,2}, since a value of 0
|
||||
+ * corresponds to one tick.
|
||||
+ */
|
||||
+#define OTTO_WDT_PHASE_TICKS_MAX 32
|
||||
+
|
||||
+/*
|
||||
+ * The maximum reset delay is actually 2×32 ticks, but that would require large
|
||||
+ * pretimeout values for timeouts longer than 32 ticks. Limit the maximum timeout
|
||||
+ * to 32 + 1 to ensure small pretimeout values can be configured as expected.
|
||||
+ */
|
||||
+#define OTTO_WDT_TIMEOUT_TICKS_MAX (OTTO_WDT_PHASE_TICKS_MAX + 1)
|
||||
+
|
||||
+struct otto_wdt_ctrl {
|
||||
+ struct watchdog_device wdev;
|
||||
+ struct device *dev;
|
||||
+ void __iomem *base;
|
||||
+ unsigned int clk_rate_khz;
|
||||
+ int irq_phase1;
|
||||
+};
|
||||
+
|
||||
+static int otto_wdt_start(struct watchdog_device *wdev)
|
||||
+{
|
||||
+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
|
||||
+ u32 v;
|
||||
+
|
||||
+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
|
||||
+ v |= OTTO_WDT_CTRL_ENABLE;
|
||||
+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int otto_wdt_stop(struct watchdog_device *wdev)
|
||||
+{
|
||||
+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
|
||||
+ u32 v;
|
||||
+
|
||||
+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
|
||||
+ v &= ~OTTO_WDT_CTRL_ENABLE;
|
||||
+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int otto_wdt_ping(struct watchdog_device *wdev)
|
||||
+{
|
||||
+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
|
||||
+
|
||||
+ iowrite32(OTTO_WDT_CNTR_PING, ctrl->base + OTTO_WDT_REG_CNTR);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int otto_wdt_tick_ms(struct otto_wdt_ctrl *ctrl, int prescale)
|
||||
+{
|
||||
+ return DIV_ROUND_CLOSEST(1 << (25 + prescale), ctrl->clk_rate_khz);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * The timer asserts the PHASE1/PHASE2 IRQs when the number of ticks exceeds
|
||||
+ * the value stored in those fields. This means each phase will run for at least
|
||||
+ * one tick, so small values need to be clamped to correctly reflect the timeout.
|
||||
+ */
|
||||
+static inline unsigned int div_round_ticks(unsigned int val, unsigned int tick_duration,
|
||||
+ unsigned int min_ticks)
|
||||
+{
|
||||
+ return max(min_ticks, DIV_ROUND_UP(val, tick_duration));
|
||||
+}
|
||||
+
|
||||
+static int otto_wdt_determine_timeouts(struct watchdog_device *wdev, unsigned int timeout,
|
||||
+ unsigned int pretimeout)
|
||||
+{
|
||||
+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
|
||||
+ unsigned int pretimeout_ms = pretimeout * 1000;
|
||||
+ unsigned int timeout_ms = timeout * 1000;
|
||||
+ unsigned int prescale_next = 0;
|
||||
+ unsigned int phase1_ticks;
|
||||
+ unsigned int phase2_ticks;
|
||||
+ unsigned int total_ticks;
|
||||
+ unsigned int prescale;
|
||||
+ unsigned int tick_ms;
|
||||
+ u32 v;
|
||||
+
|
||||
+ do {
|
||||
+ prescale = prescale_next;
|
||||
+ if (prescale > OTTO_WDT_PRESCALE_MAX)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ tick_ms = otto_wdt_tick_ms(ctrl, prescale);
|
||||
+ total_ticks = div_round_ticks(timeout_ms, tick_ms, 2);
|
||||
+ phase1_ticks = div_round_ticks(timeout_ms - pretimeout_ms, tick_ms, 1);
|
||||
+ phase2_ticks = total_ticks - phase1_ticks;
|
||||
+
|
||||
+ prescale_next++;
|
||||
+ } while (phase1_ticks > OTTO_WDT_PHASE_TICKS_MAX
|
||||
+ || phase2_ticks > OTTO_WDT_PHASE_TICKS_MAX);
|
||||
+
|
||||
+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
|
||||
+
|
||||
+ v &= ~(OTTO_WDT_CTRL_PRESCALE | OTTO_WDT_CTRL_PHASE1 | OTTO_WDT_CTRL_PHASE2);
|
||||
+ v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE1, phase1_ticks - 1);
|
||||
+ v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE2, phase2_ticks - 1);
|
||||
+ v |= FIELD_PREP(OTTO_WDT_CTRL_PRESCALE, prescale);
|
||||
+
|
||||
+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
|
||||
+
|
||||
+ timeout_ms = total_ticks * tick_ms;
|
||||
+ ctrl->wdev.timeout = timeout_ms / 1000;
|
||||
+
|
||||
+ pretimeout_ms = phase2_ticks * tick_ms;
|
||||
+ ctrl->wdev.pretimeout = pretimeout_ms / 1000;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int otto_wdt_set_timeout(struct watchdog_device *wdev, unsigned int val)
|
||||
+{
|
||||
+ return otto_wdt_determine_timeouts(wdev, val, min(wdev->pretimeout, val - 1));
|
||||
+}
|
||||
+
|
||||
+static int otto_wdt_set_pretimeout(struct watchdog_device *wdev, unsigned int val)
|
||||
+{
|
||||
+ return otto_wdt_determine_timeouts(wdev, wdev->timeout, val);
|
||||
+}
|
||||
+
|
||||
+static int otto_wdt_restart(struct watchdog_device *wdev, unsigned long reboot_mode,
|
||||
+ void *data)
|
||||
+{
|
||||
+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
|
||||
+ u32 reset_mode;
|
||||
+ u32 v;
|
||||
+
|
||||
+ disable_irq(ctrl->irq_phase1);
|
||||
+
|
||||
+ switch (reboot_mode) {
|
||||
+ case REBOOT_SOFT:
|
||||
+ reset_mode = OTTO_WDT_MODE_SOFTWARE;
|
||||
+ break;
|
||||
+ case REBOOT_WARM:
|
||||
+ reset_mode = OTTO_WDT_MODE_CPU;
|
||||
+ break;
|
||||
+ default:
|
||||
+ reset_mode = OTTO_WDT_MODE_SOC;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Configure for shortest timeout and wait for reset to occur */
|
||||
+ v = FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, reset_mode) | OTTO_WDT_CTRL_ENABLE;
|
||||
+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
|
||||
+
|
||||
+ mdelay(3 * otto_wdt_tick_ms(ctrl, 0));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t otto_wdt_phase1_isr(int irq, void *dev_id)
|
||||
+{
|
||||
+ struct otto_wdt_ctrl *ctrl = dev_id;
|
||||
+
|
||||
+ iowrite32(OTTO_WDT_INTR_PHASE_1, ctrl->base + OTTO_WDT_REG_INTR);
|
||||
+ dev_crit(ctrl->dev, "phase 1 timeout\n");
|
||||
+ watchdog_notify_pretimeout(&ctrl->wdev);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static const struct watchdog_ops otto_wdt_ops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .start = otto_wdt_start,
|
||||
+ .stop = otto_wdt_stop,
|
||||
+ .ping = otto_wdt_ping,
|
||||
+ .set_timeout = otto_wdt_set_timeout,
|
||||
+ .set_pretimeout = otto_wdt_set_pretimeout,
|
||||
+ .restart = otto_wdt_restart,
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_info otto_wdt_info = {
|
||||
+ .identity = "Realtek Otto watchdog timer",
|
||||
+ .options = WDIOF_KEEPALIVEPING |
|
||||
+ WDIOF_MAGICCLOSE |
|
||||
+ WDIOF_SETTIMEOUT |
|
||||
+ WDIOF_PRETIMEOUT,
|
||||
+};
|
||||
+
|
||||
+static void otto_wdt_clock_action(void *data)
|
||||
+{
|
||||
+ clk_disable_unprepare(data);
|
||||
+}
|
||||
+
|
||||
+static int otto_wdt_probe_clk(struct otto_wdt_ctrl *ctrl)
|
||||
+{
|
||||
+ struct clk *clk = devm_clk_get(ctrl->dev, NULL);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (IS_ERR(clk))
|
||||
+ return dev_err_probe(ctrl->dev, PTR_ERR(clk), "Failed to get clock\n");
|
||||
+
|
||||
+ ret = clk_prepare_enable(clk);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(ctrl->dev, ret, "Failed to enable clock\n");
|
||||
+
|
||||
+ ret = devm_add_action_or_reset(ctrl->dev, otto_wdt_clock_action, clk);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ctrl->clk_rate_khz = clk_get_rate(clk) / 1000;
|
||||
+ if (ctrl->clk_rate_khz == 0)
|
||||
+ return dev_err_probe(ctrl->dev, -ENXIO, "Failed to get clock rate\n");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int otto_wdt_probe_reset_mode(struct otto_wdt_ctrl *ctrl)
|
||||
+{
|
||||
+ static const char *mode_property = "realtek,reset-mode";
|
||||
+ const struct fwnode_handle *node = ctrl->dev->fwnode;
|
||||
+ int mode_count;
|
||||
+ u32 mode;
|
||||
+ u32 v;
|
||||
+
|
||||
+ if (!node)
|
||||
+ return -ENXIO;
|
||||
+
|
||||
+ mode_count = fwnode_property_string_array_count(node, mode_property);
|
||||
+ if (mode_count < 0)
|
||||
+ return mode_count;
|
||||
+ else if (mode_count == 0)
|
||||
+ return 0;
|
||||
+ else if (mode_count != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (fwnode_property_match_string(node, mode_property, "soc") == 0)
|
||||
+ mode = OTTO_WDT_MODE_SOC;
|
||||
+ else if (fwnode_property_match_string(node, mode_property, "cpu") == 0)
|
||||
+ mode = OTTO_WDT_MODE_CPU;
|
||||
+ else if (fwnode_property_match_string(node, mode_property, "software") == 0)
|
||||
+ mode = OTTO_WDT_MODE_SOFTWARE;
|
||||
+ else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
|
||||
+ v &= ~OTTO_WDT_CTRL_RST_MODE;
|
||||
+ v |= FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, mode);
|
||||
+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int otto_wdt_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct otto_wdt_ctrl *ctrl;
|
||||
+ unsigned int max_tick_ms;
|
||||
+ int ret;
|
||||
+
|
||||
+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
|
||||
+ if (!ctrl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ctrl->dev = dev;
|
||||
+ ctrl->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(ctrl->base))
|
||||
+ return PTR_ERR(ctrl->base);
|
||||
+
|
||||
+ /* Clear any old interrupts and reset initial state */
|
||||
+ iowrite32(OTTO_WDT_INTR_PHASE_1 | OTTO_WDT_INTR_PHASE_2,
|
||||
+ ctrl->base + OTTO_WDT_REG_INTR);
|
||||
+ iowrite32(OTTO_WDT_CTRL_DEFAULT, ctrl->base + OTTO_WDT_REG_CTRL);
|
||||
+
|
||||
+ ret = otto_wdt_probe_clk(ctrl);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ctrl->irq_phase1 = platform_get_irq_byname(pdev, "phase1");
|
||||
+ if (ctrl->irq_phase1 < 0)
|
||||
+ return ctrl->irq_phase1;
|
||||
+
|
||||
+ ret = devm_request_irq(dev, ctrl->irq_phase1, otto_wdt_phase1_isr, 0,
|
||||
+ "realtek-otto-wdt", ctrl);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "Failed to get IRQ for phase1\n");
|
||||
+
|
||||
+ ret = otto_wdt_probe_reset_mode(ctrl);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "Invalid reset mode specified\n");
|
||||
+
|
||||
+ ctrl->wdev.parent = dev;
|
||||
+ ctrl->wdev.info = &otto_wdt_info;
|
||||
+ ctrl->wdev.ops = &otto_wdt_ops;
|
||||
+
|
||||
+ /*
|
||||
+ * Since pretimeout cannot be disabled, min. timeout is twice the
|
||||
+ * subsystem resolution. Max. timeout is ca. 43s at a bus clock of 200MHz.
|
||||
+ */
|
||||
+ ctrl->wdev.min_timeout = 2;
|
||||
+ max_tick_ms = otto_wdt_tick_ms(ctrl, OTTO_WDT_PRESCALE_MAX);
|
||||
+ ctrl->wdev.max_hw_heartbeat_ms = max_tick_ms * OTTO_WDT_TIMEOUT_TICKS_MAX;
|
||||
+ ctrl->wdev.timeout = min(30U, ctrl->wdev.max_hw_heartbeat_ms / 1000);
|
||||
+
|
||||
+ watchdog_set_drvdata(&ctrl->wdev, ctrl);
|
||||
+ watchdog_init_timeout(&ctrl->wdev, 0, dev);
|
||||
+ watchdog_stop_on_reboot(&ctrl->wdev);
|
||||
+ watchdog_set_restart_priority(&ctrl->wdev, 128);
|
||||
+
|
||||
+ ret = otto_wdt_determine_timeouts(&ctrl->wdev, ctrl->wdev.timeout, 1);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "Failed to set timeout\n");
|
||||
+
|
||||
+ return devm_watchdog_register_device(dev, &ctrl->wdev);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id otto_wdt_ids[] = {
|
||||
+ { .compatible = "realtek,rtl8380-wdt" },
|
||||
+ { .compatible = "realtek,rtl8390-wdt" },
|
||||
+ { .compatible = "realtek,rtl9300-wdt" },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, otto_wdt_ids);
|
||||
+
|
||||
+static struct platform_driver otto_wdt_driver = {
|
||||
+ .probe = otto_wdt_probe,
|
||||
+ .driver = {
|
||||
+ .name = "realtek-otto-watchdog",
|
||||
+ .of_match_table = otto_wdt_ids,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(otto_wdt_driver);
|
||||
+
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");
|
||||
+MODULE_DESCRIPTION("Realtek Otto watchdog timer driver");
|
|
@ -0,0 +1,53 @@
|
|||
From c6af53f038aa32cec12e8a305ba07c7ef168f1b0 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 4 Jan 2022 12:07:00 +0000
|
||||
Subject: [PATCH 2/3] net: mdio: add helpers to extract clause 45 regad and
|
||||
devad fields
|
||||
|
||||
Add a couple of helpers and definitions to extract the clause 45 regad
|
||||
and devad fields from the regnum passed into MDIO drivers.
|
||||
|
||||
Tested-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
include/linux/mdio.h | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
--- a/include/linux/mdio.h
|
||||
+++ b/include/linux/mdio.h
|
||||
@@ -7,6 +7,7 @@
|
||||
#define __LINUX_MDIO_H__
|
||||
|
||||
#include <uapi/linux/mdio.h>
|
||||
+#include <linux/bitfield.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
/* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit
|
||||
@@ -14,6 +15,7 @@
|
||||
*/
|
||||
#define MII_ADDR_C45 (1<<30)
|
||||
#define MII_DEVADDR_C45_SHIFT 16
|
||||
+#define MII_DEVADDR_C45_MASK GENMASK(20, 16)
|
||||
#define MII_REGADDR_C45_MASK GENMASK(15, 0)
|
||||
|
||||
struct gpio_desc;
|
||||
@@ -342,6 +344,16 @@ static inline u32 mdiobus_c45_addr(int d
|
||||
return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum;
|
||||
}
|
||||
|
||||
+static inline u16 mdiobus_c45_regad(u32 regnum)
|
||||
+{
|
||||
+ return FIELD_GET(MII_REGADDR_C45_MASK, regnum);
|
||||
+}
|
||||
+
|
||||
+static inline u16 mdiobus_c45_devad(u32 regnum)
|
||||
+{
|
||||
+ return FIELD_GET(MII_DEVADDR_C45_MASK, regnum);
|
||||
+}
|
||||
+
|
||||
static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
|
||||
u16 regnum)
|
||||
{
|
|
@ -0,0 +1,123 @@
|
|||
From 512c5be35223d9baa2629efa1084cf5210eaee80 Mon Sep 17 00:00:00 2001
|
||||
From: Sander Vanheule <sander@svanheule.net>
|
||||
Date: Sat, 9 Apr 2022 21:55:47 +0200
|
||||
Subject: [PATCH 2/6] gpio: realtek-otto: Support reversed port layouts
|
||||
|
||||
The GPIO port layout on the RTL930x SoC series is reversed compared to
|
||||
the RTL838x and RTL839x SoC series. Add new port offset calculator
|
||||
functions to ensure the correct order is used when reading port IRQ
|
||||
data, and ensure bgpio uses the right byte ordering.
|
||||
|
||||
Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
|
||||
---
|
||||
drivers/gpio/gpio-realtek-otto.c | 55 +++++++++++++++++++++++++++++---
|
||||
1 file changed, 51 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/gpio/gpio-realtek-otto.c
|
||||
+++ b/drivers/gpio/gpio-realtek-otto.c
|
||||
@@ -58,6 +58,8 @@ struct realtek_gpio_ctrl {
|
||||
raw_spinlock_t lock;
|
||||
u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
|
||||
u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
|
||||
+ unsigned int (*port_offset_u8)(unsigned int port);
|
||||
+ unsigned int (*port_offset_u16)(unsigned int port);
|
||||
};
|
||||
|
||||
/* Expand with more flags as devices with other quirks are added */
|
||||
@@ -69,6 +71,11 @@ enum realtek_gpio_flags {
|
||||
* line the IRQ handler was assigned to, causing uncaught interrupts.
|
||||
*/
|
||||
GPIO_INTERRUPTS_DISABLED = BIT(0),
|
||||
+ /*
|
||||
+ * Port order is reversed, meaning DCBA register layout for 1-bit
|
||||
+ * fields, and [BA, DC] for 2-bit fields.
|
||||
+ */
|
||||
+ GPIO_PORTS_REVERSED = BIT(1),
|
||||
};
|
||||
|
||||
static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
|
||||
@@ -86,21 +93,50 @@ static struct realtek_gpio_ctrl *irq_dat
|
||||
* port. The two interrupt mask registers store two bits per GPIO, so use u16
|
||||
* values.
|
||||
*/
|
||||
+static unsigned int realtek_gpio_port_offset_u8(unsigned int port)
|
||||
+{
|
||||
+ return port;
|
||||
+}
|
||||
+
|
||||
+static unsigned int realtek_gpio_port_offset_u16(unsigned int port)
|
||||
+{
|
||||
+ return 2 * port;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Reversed port order register access
|
||||
+ *
|
||||
+ * For registers with one bit per GPIO, all ports are stored as u8-s in one
|
||||
+ * register in reversed order. The two interrupt mask registers store two bits
|
||||
+ * per GPIO, so use u16 values. The first register contains ports 1 and 0, the
|
||||
+ * second ports 3 and 2.
|
||||
+ */
|
||||
+static unsigned int realtek_gpio_port_offset_u8_rev(unsigned int port)
|
||||
+{
|
||||
+ return 3 - port;
|
||||
+}
|
||||
+
|
||||
+static unsigned int realtek_gpio_port_offset_u16_rev(unsigned int port)
|
||||
+{
|
||||
+ return 2 * (port ^ 1);
|
||||
+}
|
||||
+
|
||||
static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
|
||||
unsigned int port, u16 irq_type, u16 irq_mask)
|
||||
{
|
||||
- iowrite16(irq_type & irq_mask, ctrl->base + REALTEK_GPIO_REG_IMR + 2 * port);
|
||||
+ iowrite16(irq_type & irq_mask,
|
||||
+ ctrl->base + REALTEK_GPIO_REG_IMR + ctrl->port_offset_u16(port));
|
||||
}
|
||||
|
||||
static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
|
||||
unsigned int port, u8 mask)
|
||||
{
|
||||
- iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + port);
|
||||
+ iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
|
||||
}
|
||||
|
||||
static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
|
||||
{
|
||||
- return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + port);
|
||||
+ return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
|
||||
}
|
||||
|
||||
/* Set the rising and falling edge mask bits for a GPIO port pin */
|
||||
@@ -253,6 +289,7 @@ MODULE_DEVICE_TABLE(of, realtek_gpio_of_
|
||||
static int realtek_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
+ unsigned long bgpio_flags;
|
||||
unsigned int dev_flags;
|
||||
struct gpio_irq_chip *girq;
|
||||
struct realtek_gpio_ctrl *ctrl;
|
||||
@@ -280,10 +317,20 @@ static int realtek_gpio_probe(struct pla
|
||||
|
||||
raw_spin_lock_init(&ctrl->lock);
|
||||
|
||||
+ if (dev_flags & GPIO_PORTS_REVERSED) {
|
||||
+ bgpio_flags = 0;
|
||||
+ ctrl->port_offset_u8 = realtek_gpio_port_offset_u8_rev;
|
||||
+ ctrl->port_offset_u16 = realtek_gpio_port_offset_u16_rev;
|
||||
+ } else {
|
||||
+ bgpio_flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
|
||||
+ ctrl->port_offset_u8 = realtek_gpio_port_offset_u8;
|
||||
+ ctrl->port_offset_u16 = realtek_gpio_port_offset_u16;
|
||||
+ }
|
||||
+
|
||||
err = bgpio_init(&ctrl->gc, dev, 4,
|
||||
ctrl->base + REALTEK_GPIO_REG_DATA, NULL, NULL,
|
||||
ctrl->base + REALTEK_GPIO_REG_DIR, NULL,
|
||||
- BGPIOF_BIG_ENDIAN_BYTE_ORDER);
|
||||
+ bgpio_flags);
|
||||
if (err) {
|
||||
dev_err(dev, "unable to init generic GPIO");
|
||||
return err;
|
|
@ -0,0 +1,153 @@
|
|||
From 95fa6dbe58f286a8f87cb37b7516232eb678de2d Mon Sep 17 00:00:00 2001
|
||||
From: Sander Vanheule <sander@svanheule.net>
|
||||
Date: Sat, 9 Apr 2022 21:55:48 +0200
|
||||
Subject: [PATCH 3/6] gpio: realtek-otto: Support per-cpu interrupts
|
||||
|
||||
On SoCs with multiple cores, it is possible that the GPIO interrupt
|
||||
controller supports assigning specific pins to one or more cores.
|
||||
|
||||
IRQ balancing can be performed on a line-by-line basis if the parent
|
||||
interrupt is routed to all available cores, which is the default upon
|
||||
initialisation.
|
||||
|
||||
Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
|
||||
---
|
||||
drivers/gpio/gpio-realtek-otto.c | 75 +++++++++++++++++++++++++++++++-
|
||||
1 file changed, 74 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/gpio/gpio-realtek-otto.c
|
||||
+++ b/drivers/gpio/gpio-realtek-otto.c
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
+#include <linux/cpumask.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
@@ -55,6 +56,8 @@
|
||||
struct realtek_gpio_ctrl {
|
||||
struct gpio_chip gc;
|
||||
void __iomem *base;
|
||||
+ void __iomem *cpumask_base;
|
||||
+ struct cpumask cpu_irq_maskable;
|
||||
raw_spinlock_t lock;
|
||||
u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
|
||||
u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
|
||||
@@ -76,6 +79,11 @@ enum realtek_gpio_flags {
|
||||
* fields, and [BA, DC] for 2-bit fields.
|
||||
*/
|
||||
GPIO_PORTS_REVERSED = BIT(1),
|
||||
+ /*
|
||||
+ * Interrupts can be enabled per cpu. This requires a secondary IO
|
||||
+ * range, where the per-cpu enable masks are located.
|
||||
+ */
|
||||
+ GPIO_INTERRUPTS_PER_CPU = BIT(2),
|
||||
};
|
||||
|
||||
static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
|
||||
@@ -250,14 +258,61 @@ static void realtek_gpio_irq_handler(str
|
||||
chained_irq_exit(irq_chip, desc);
|
||||
}
|
||||
|
||||
+static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl,
|
||||
+ unsigned int port, int cpu)
|
||||
+{
|
||||
+ return ctrl->cpumask_base + ctrl->port_offset_u8(port) +
|
||||
+ REALTEK_GPIO_PORTS_PER_BANK * cpu;
|
||||
+}
|
||||
+
|
||||
+static int realtek_gpio_irq_set_affinity(struct irq_data *data,
|
||||
+ const struct cpumask *dest, bool force)
|
||||
+{
|
||||
+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
|
||||
+ unsigned int line = irqd_to_hwirq(data);
|
||||
+ unsigned int port = line / 8;
|
||||
+ unsigned int port_pin = line % 8;
|
||||
+ void __iomem *irq_cpu_mask;
|
||||
+ unsigned long flags;
|
||||
+ int cpu;
|
||||
+ u8 v;
|
||||
+
|
||||
+ if (!ctrl->cpumask_base)
|
||||
+ return -ENXIO;
|
||||
+
|
||||
+ raw_spin_lock_irqsave(&ctrl->lock, flags);
|
||||
+
|
||||
+ for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
|
||||
+ irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
|
||||
+ v = ioread8(irq_cpu_mask);
|
||||
+
|
||||
+ if (cpumask_test_cpu(cpu, dest))
|
||||
+ v |= BIT(port_pin);
|
||||
+ else
|
||||
+ v &= ~BIT(port_pin);
|
||||
+
|
||||
+ iowrite8(v, irq_cpu_mask);
|
||||
+ }
|
||||
+
|
||||
+ raw_spin_unlock_irqrestore(&ctrl->lock, flags);
|
||||
+
|
||||
+ irq_data_update_effective_affinity(data, dest);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int realtek_gpio_irq_init(struct gpio_chip *gc)
|
||||
{
|
||||
struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
|
||||
unsigned int port;
|
||||
+ int cpu;
|
||||
|
||||
for (port = 0; (port * 8) < gc->ngpio; port++) {
|
||||
realtek_gpio_write_imr(ctrl, port, 0, 0);
|
||||
realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
|
||||
+
|
||||
+ for_each_cpu(cpu, &ctrl->cpu_irq_maskable)
|
||||
+ iowrite8(GENMASK(7, 0), realtek_gpio_irq_cpu_mask(ctrl, port, cpu));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -269,6 +324,7 @@ static struct irq_chip realtek_gpio_irq_
|
||||
.irq_mask = realtek_gpio_irq_mask,
|
||||
.irq_unmask = realtek_gpio_irq_unmask,
|
||||
.irq_set_type = realtek_gpio_irq_set_type,
|
||||
+ .irq_set_affinity = realtek_gpio_irq_set_affinity,
|
||||
};
|
||||
|
||||
static const struct of_device_id realtek_gpio_of_match[] = {
|
||||
@@ -293,8 +349,10 @@ static int realtek_gpio_probe(struct pla
|
||||
unsigned int dev_flags;
|
||||
struct gpio_irq_chip *girq;
|
||||
struct realtek_gpio_ctrl *ctrl;
|
||||
+ struct resource *res;
|
||||
u32 ngpios;
|
||||
- int err, irq;
|
||||
+ unsigned int nr_cpus;
|
||||
+ int cpu, err, irq;
|
||||
|
||||
ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
|
||||
if (!ctrl)
|
||||
@@ -355,6 +413,21 @@ static int realtek_gpio_probe(struct pla
|
||||
girq->init_hw = realtek_gpio_irq_init;
|
||||
}
|
||||
|
||||
+ cpumask_clear(&ctrl->cpu_irq_maskable);
|
||||
+
|
||||
+ if ((dev_flags & GPIO_INTERRUPTS_PER_CPU) && irq > 0) {
|
||||
+ ctrl->cpumask_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
|
||||
+ if (IS_ERR(ctrl->cpumask_base))
|
||||
+ return dev_err_probe(dev, PTR_ERR(ctrl->cpumask_base),
|
||||
+ "missing CPU IRQ mask registers");
|
||||
+
|
||||
+ nr_cpus = resource_size(res) / REALTEK_GPIO_PORTS_PER_BANK;
|
||||
+ nr_cpus = min(nr_cpus, num_present_cpus());
|
||||
+
|
||||
+ for (cpu = 0; cpu < nr_cpus; cpu++)
|
||||
+ cpumask_set_cpu(cpu, &ctrl->cpu_irq_maskable);
|
||||
+ }
|
||||
+
|
||||
return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue