Merge Official Source

This commit is contained in:
CN_SZTL 2020-03-08 01:27:54 +08:00
commit 5ab172228c
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
43 changed files with 3232 additions and 38 deletions

View File

@ -15,6 +15,8 @@ board=$(board_name)
case "$board" in
alfa-network,ap121f|\
buffalo,bhr-4grv2|\
devolo,magic-2-wifi|\
domywifi,dw33d|\
engenius,ecb1750|\
etactica,eg200|\
glinet,gl-ar300m-lite|\

View File

@ -8,13 +8,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=dnsmasq
PKG_UPSTREAM_VERSION:=2.81rc1
PKG_UPSTREAM_VERSION:=2.81rc2
PKG_VERSION:=$(subst test,~~test,$(subst rc,~rc,$(PKG_UPSTREAM_VERSION)))
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_UPSTREAM_VERSION).tar.xz
PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/release-candidates
PKG_HASH:=47afc967fb3d673d1700ebfa2192ab1436197fa6e135e335f0d0ef17cdb2f0fc
PKG_HASH:=218a5414836c0a553b57f5506d001f48b5eadc869d0fa21499ab1cdca75c1912
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=COPYING

View File

@ -0,0 +1,50 @@
From e68b7bee24bb04c32554e153fea2cffd69437b65 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Date: Fri, 6 Mar 2020 10:15:20 +0000
Subject: [PATCH 1/2] suppress non linux network unused var warnings
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/dnsmasq.c | 4 +++-
src/network.c | 3 +++
2 files changed, 6 insertions(+), 1 deletion(-)
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -1860,7 +1860,8 @@ static void check_dns_listeners(time_t n
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
{
char a;
-
+ (void)a; /* suppress potential unused warning */
+
daemon->tcp_pids[i] = p;
daemon->tcp_pipes[i] = pipefd[0];
#ifdef HAVE_LINUX_NETWORK
@@ -1911,6 +1912,7 @@ static void check_dns_listeners(time_t n
if (!option_bool(OPT_DEBUG))
{
char a = 0;
+ (void)a; /* suppress potential unused warning */
alarm(CHILD_LIFETIME);
close(pipefd[0]); /* close read end in child. */
daemon->pipe_to_parent = pipefd[1];
--- a/src/network.c
+++ b/src/network.c
@@ -785,6 +785,8 @@ int set_ipv6pktinfo(int fd)
/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
int tcp_interface(int fd, int af)
{
+ (void)fd; /* suppress potential unused warning */
+ (void)af; /* suppress potential unused warning */
int if_index = 0;
#ifdef HAVE_LINUX_NETWORK
@@ -1187,6 +1189,7 @@ int local_bind(int fd, union mysockaddr
#endif
}
+ (void)intname; /* suppress potential unused warning */
#if defined(SO_BINDTODEVICE)
if (intname[0] != 0 &&
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)

View File

@ -0,0 +1,27 @@
From 84fe908e64a6e904166f728860ab8dfaa47850d2 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Date: Fri, 6 Mar 2020 10:28:09 +0000
Subject: [PATCH 2/2] rfc3315: fix incorrect logical '&&' warning
rfc3315.c:1711:28: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
if (!(addr_list->flags && ADDRLIST_DECLINED) ||
^ ~~~~~~~~~~~~~~~~~
It's a flag bit so should be bitwise '&' operator
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
---
src/rfc3315.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -1708,7 +1708,7 @@ static int config_valid(struct dhcp_conf
return 0;
for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
- if (!(addr_list->flags && ADDRLIST_DECLINED) ||
+ if (!(addr_list->flags & ADDRLIST_DECLINED) ||
difftime(now, addr_list->decline_time) >= (float)DECLINE_BACKOFF)
{
addrpart = addr6part(&addr_list->addr.addr6);

View File

@ -0,0 +1,182 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include "ar9344.dtsi"
/ {
model = "Devolo Magic 2 Wifi";
compatible = "devolo,magic-2-wifi", "qca,ar9344";
aliases {
led-boot = &led_dlan_red;
led-failsafe = &led_dlan_red;
led-running = &led_dlan_white;
led-upgrade = &led_dlan_red;
};
leds {
compatible = "gpio-leds";
wlan {
label = "devolo:white:wlan";
gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
linux,default-trigger = "phy1tpt";
};
led_dlan_white: dlan_white {
label = "devolo:white:dlan";
gpios = <&gpio 14 GPIO_ACTIVE_LOW>;
};
led_dlan_red: dlan_red {
label = "devolo:red:dlan";
gpios = <&gpio 15 GPIO_ACTIVE_HIGH>;
panic-indicator;
};
};
keys {
compatible = "gpio-keys";
reset {
label = "Reset button";
linux,code = <KEY_RESTART>;
gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
debounce-interval = <60>;
};
wifi {
label = "WIFI button";
linux,code = <KEY_RFKILL>;
gpios = <&gpio 20 GPIO_ACTIVE_HIGH>;
debounce-interval = <60>;
};
dlan {
label = "DLAN button";
linux,code = <BTN_0>;
gpios = <&gpio 22 GPIO_ACTIVE_LOW>;
debounce-interval = <60>;
};
};
};
&gpio {
status = "okay";
wlan_power {
gpio-hog;
line-name = "WLAN power";
gpios = <&gpio 21 GPIO_ACTIVE_HIGH>;
output-high;
};
};
&spi {
status = "okay";
num-cs = <1>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <25000000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
uboot: partition@0 {
label = "u-boot";
reg = <0x0 0x40000>;
read-only;
};
partition@40000 {
label = "u-boot-env";
reg = <0x40000 0x10000>;
read-only;
};
partition@50000 {
label = "Config1";
reg = <0x50000 0x10000>;
read-only;
};
partition@60000 {
label = "Config2";
reg = <0x60000 0x10000>;
read-only;
};
partition@70000 {
compatible = "denx,uimage";
label = "firmware";
reg = <0x70000 0xf80000>;
};
art: partition@ff0000 {
label = "art";
reg = <0xff0000 0x10000>;
read-only;
};
};
};
};
&ref {
clock-frequency = <40000000>;
};
&uart {
status = "okay";
};
&eth0 {
status = "okay";
pll-data = <0x02000000 0x00000101 0x00001616>;
mtd-mac-address = <&art 0x1002>;
mtd-mac-address-increment = <2>;
phy-mode = "rgmii";
phy-handle = <&phy0>;
};
&wmac {
status = "okay";
mtd-cal-data = <&art 0x1000>;
};
&pcie {
status = "okay";
wifi@0,0 {
compatible = "qcom,ath10k";
reg = <0 0 0 0 0>;
};
};
&mdio0 {
status = "okay";
phy0: ethernet-phy@0 {
reg = <0>;
phy-mode = "rgmii";
qca,ar8327-initvals = <
/* PORT0: RGMII, MAC0/6 exchage, tx_delay 01, No rx_delay */
0x04 0x06400000
0x08 0x00000000 /* PORT5 PAD MODE CTRL */
0x0c 0x00000000 /* PORT6 PAD MODE CTRL */
0x7c 0x0000007e /* PORT0_STATUS */
>;
};
};

View File

@ -0,0 +1,217 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include "qca9557.dtsi"
/ {
compatible = "domywifi,dw33d", "qca,qca9558";
model = "DomyWifi DW33D";
chosen {
bootargs = "console=ttyS0,115200n8";
};
aliases {
led-boot = &led_system;
led-failsafe = &led_system;
led-running = &led_system;
led-upgrade = &led_system;
};
leds {
compatible = "gpio-leds";
led_system: system {
label = "dw33d:blue:system";
gpios = <&gpio 14 GPIO_ACTIVE_LOW>;
};
mmc {
label = "dw33d:blue:mmc";
gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
trigger-sources = <&hub_port0>;
linux,default-trigger = "usbport";
};
usb {
label = "dw33d:blue:usb";
gpios = <&gpio 15 GPIO_ACTIVE_LOW>;
trigger-sources = <&hub_port1>;
linux,default-trigger = "usbport";
};
wlan2g {
label = "dw33d:blue:wlan2g";
gpios = <&gpio 13 GPIO_ACTIVE_LOW>;
linux,default-trigger = "phy1tpt";
};
internet {
label = "dw33d:blue:internet";
gpios = <&gpio 22 GPIO_ACTIVE_LOW>;
};
};
keys {
compatible = "gpio-keys";
reset {
label = "Reset button";
linux,code = <KEY_RESTART>;
gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
debounce-interval = <60>;
};
};
};
&pcie0 {
status = "okay";
wifi@0,0 {
compatible = "qcom,ath10k";
reg = <0 0 0 0 0>;
};
};
&uart {
status = "okay";
};
&usb_phy0 {
status = "okay";
};
&usb0 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
hub_port0: port@1 {
reg = <1>;
#trigger-source-cells = <0>;
};
};
&usb_phy1 {
status = "okay";
};
&usb1 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
hub_port1: port@1 {
reg = <1>;
#trigger-source-cells = <0>;
};
};
&spi {
status = "okay";
num-cs = <1>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <25000000>;
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>;
};
partition@50000 {
label = "oem-firmware";
reg = <0x50000 0xfa0000>;
};
art: partition@ff0000 {
label = "art";
reg = <0xff0000 0x10000>;
read-only;
};
};
};
};
&nand {
status = "okay";
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "kernel";
reg = <0x0 0x500000>;
};
partition@500000 {
label = "ubi";
reg = <0x500000 0x5b00000>;
};
partition@6000000 {
label = "oem-backup";
reg = <0x6000000 0x2000000>;
};
};
};
&mdio0 {
status = "okay";
phy0: ethernet-phy@0 {
reg = <0>;
qca,ar8327-initvals = <
0x04 0x87600000 /* PORT0 PAD MODE CTRL */
0x0c 0x00080080 /* PORT6 PAD MODE CTRL */
0x7c 0x0000007e /* PORT0_STATUS */
0x94 0x0000007e /* PORT6 STATUS */
>;
};
};
&eth0 {
status = "okay";
mtd-mac-address = <&art 0x0>;
pll-data = <0x56000000 0x00000101 0x00001616>;
phy-handle = <&phy0>;
};
&eth1 {
status = "okay";
mtd-mac-address = <&art 0x6>;
pll-data = <0x03000101 0x00000101 0x00001616>;
fixed-link {
speed = <1000>;
full-duplex;
};
};
&wmac {
status = "okay";
mtd-cal-data = <&art 0x1000>;
mtd-mac-address = <&art 0xc>;
};

View File

@ -0,0 +1,186 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include "qca9557.dtsi"
/ {
model = "Sitecom WLR-8100 (X8 AC1750)";
compatible = "sitecom,wlr-8100", "qca,qca9558";
chosen {
bootargs = "console=ttyS0,115200n8";
};
aliases {
led-boot = &led_status_amber;
led-failsafe = &led_status_amber;
led-running = &led_status_amber;
led-upgrade = &led_status_amber;
};
keys {
compatible = "gpio-keys";
wifi2g_rfkill {
label = "2.4GHz - RFKILL";
gpios = <&gpio 21 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RFKILL>;
};
wifi5g_restart {
label = "5GHz - RESTART";
gpios = <&gpio 22 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
};
leds {
compatible = "gpio-leds";
led_status_amber: status_amber {
label = "wlr-8100:amber:status";
gpios = <&gpio 18 GPIO_ACTIVE_LOW>;
default-state = "on";
};
ops {
label = "wlr-8100:white:ops";
gpios = <&gpio 23 GPIO_ACTIVE_LOW>;
};
wifi2g {
label = "wlr-8100:blue:wifi2g";
gpios = <&gpio 19 GPIO_ACTIVE_LOW>;
linux,default-trigger = "phy1tpt";
};
wifi5g {
label = "wlr-8100:blue:wifi5g";
gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
linux,default-trigger = "phy0tpt";
};
};
};
&spi {
status = "okay";
num-cs = <1>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <25000000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
uboot: partition@0 {
label = "u-boot";
reg = <0x000000 0x030000>;
read-only;
};
partition@30000 {
label = "u-boot-env";
reg = <0x030000 0x010000>;
read-only;
};
partition@40000 {
compatible = "denx,uimage";
label = "firmware";
reg = <0x040000 0xf10000>;
};
partition@f50000 {
label = "manufacture";
reg = <0xf50000 0x040000>;
read-only;
};
partition@f90000 {
label = "backup";
reg = <0xf90000 0x010000>;
read-only;
};
partition@fa0000 {
label = "storage";
reg = <0xfa0000 0x050000>;
read-only;
};
art: partition@ff0000 {
label = "art";
reg = <0xff0000 0x010000>;
read-only;
};
};
};
};
&pcie0 {
status = "okay";
};
&pcie1 {
status = "okay";
wifi@0,0 {
compatible = "qcom,ath10k";
reg = <0 0 0 0 0>;
};
};
&uart {
status = "okay";
};
&usb_phy0 {
status = "okay";
};
&usb0 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
};
&mdio0 {
status = "okay";
phy0: ethernet-phy@0 {
reg = <0>;
qca,ar8327-initvals = <
0x04 0x87600000 /* PORT0 PAD MODE CTRL */
0x50 0xc437c437 /* LED Control Register 0 */
0x54 0xc337c337 /* LED Control Register 1 */
0x58 0x00000000 /* LED Control Register 2 */
0x5c 0x03ffff00 /* LED Control Register 3 */
0x7c 0x0000007e /* PORT0_STATUS */
>;
};
};
&eth0 {
status = "okay";
phy-handle = <&phy0>;
pll-data = <0xa6000000 0x00000101 0x00001616>;
gmac-config {
device = <&gmac>;
rgmii-enabled = <1>;
};
};
&wmac {
status = "okay";
qca,no-eeprom;
};

View File

@ -80,6 +80,9 @@ comfast,cf-e560ac)
ucidef_set_led_switch "lan3" "LAN3" "$boardname:blue:lan3" "switch0" "0x08"
ucidef_set_led_switch "lan4" "LAN4" "$boardname:blue:lan4" "switch0" "0x10"
;;
devolo,magic-2-wifi)
ucidef_set_led_netdev "plcw" "dLAN" "devolo:white:dlan" "eth0.1" "rx"
;;
dlink,dir-842-c1|\
dlink,dir-842-c2|\
dlink,dir-842-c3|\

View File

@ -123,6 +123,10 @@ ath79_setup_interfaces()
ocedo,ursus)
ucidef_set_interface_lan "eth0 eth1"
;;
devolo,magic-2-wifi)
ucidef_add_switch "switch0" \
"0@eth0" "2:wan" "3:lan" "4:lan"
;;
dlink,dir-825-b1)
ucidef_set_interface_wan "eth1"
ucidef_add_switch "switch0" \
@ -142,7 +146,8 @@ ath79_setup_interfaces()
"0@eth0" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "5:wan"
;;
elecom,wrc-1750ghbk2-i|\
elecom,wrc-300ghbk2-i)
elecom,wrc-300ghbk2-i|\
sitecom,wlr-8100)
ucidef_add_switch "switch0" \
"0@eth0" "2:lan:4" "3:lan:3" "4:lan:2" "5:lan:1" "1:wan"
;;
@ -328,6 +333,9 @@ ath79_setup_macs()
lan_mac=$(fritz_tffs -n maca -i $(find_mtd_part "tffs (1)"))
wan_mac=$(fritz_tffs -n macb -i $(find_mtd_part "tffs (1)"))
;;
devolo,magic-2-wifi)
label_mac=$(macaddr_add "$(mtd_get_mac_binary art 0x1002)" 3)
;;
dlink,dir-825-b1)
lan_mac=$(mtd_get_mac_text "caldata" 0xffa0)
wan_mac=$(mtd_get_mac_text "caldata" 0xffb4)
@ -407,7 +415,8 @@ ath79_setup_macs()
wan_mac=$(mtd_get_mac_binary factory 0x0)
lan_mac=$(macaddr_setbit_la "$wan_mac")
;;
sitecom,wlr-7100)
sitecom,wlr-7100|\
sitecom,wlr-8100)
lan_mac=$(mtd_get_mac_ascii u-boot-env ethaddr)
wan_mac=$(mtd_get_mac_ascii u-boot-env wanaddr)
label_mac=$lan_mac

View File

@ -31,6 +31,10 @@ comfast,cf-e5)
ucidef_add_gpio_switch "lte_poweroff" "LTE Poweroff" "1" "1"
ucidef_add_gpio_switch "lte_reset" "LTE Reset" "12" "1"
;;
devolo,magic-2-wifi)
ucidef_add_gpio_switch "plc_pairing" "PLC pairing" "11" "1"
ucidef_add_gpio_switch "plc_enable" "PLC enable" "13" "1"
;;
dlink,dir-825-c1|\
dlink,dir-835-a1)
ucidef_add_gpio_switch "wan_led_auto" "WAN LED Auto" "20" "0"

View File

@ -37,7 +37,8 @@ case "$FIRMWARE" in
iodata,wn-ac1600dgr|\
iodata,wn-ac1600dgr2|\
iodata,wn-ag300dgr|\
sitecom,wlr-7100)
sitecom,wlr-7100|\
sitecom,wlr-8100)
caldata_extract "art" 0x1000 0x440
ath9k_patch_mac $(mtd_get_mac_ascii u-boot-env ethaddr)
;;

View File

@ -13,6 +13,7 @@ case "$FIRMWARE" in
case $board in
comfast,cf-wr650ac-v1|\
comfast,cf-wr650ac-v2|\
devolo,magic-2-wifi|\
ubnt,unifiac-lite|\
ubnt,unifiac-lr|\
ubnt,unifiac-mesh|\
@ -121,6 +122,14 @@ case "$FIRMWARE" in
;;
esac
;;
"ath10k/cal-pci-0000:01:00.0.bin")
case $board in
sitecom,wlr-8100)
caldata_extract "art" 0x5000 0x844
ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii u-boot-env ethaddr) +1)
;;
esac
;;
"ath10k/pre-cal-pci-0000:00:00.0.bin")
case $board in
comfast,cf-e313ac)

View File

@ -401,6 +401,15 @@ define Device/devolo_dvl1750x
endef
TARGET_DEVICES += devolo_dvl1750x
define Device/devolo_magic-2-wifi
SOC := ar9344
DEVICE_VENDOR := Devolo
DEVICE_MODEL := Magic 2 WiFi
DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct
IMAGE_SIZE := 15872k
endef
TARGET_DEVICES += devolo_magic-2-wifi
define Device/dlink_dir-505
SOC := ar9330
DEVICE_VENDOR := D-Link
@ -1086,6 +1095,22 @@ define Device/sitecom_wlr-7100
endef
TARGET_DEVICES += sitecom_wlr-7100
define Device/sitecom_wlr-8100
SOC := qca9558
DEVICE_VENDOR := Sitecom
DEVICE_MODEL := WLR-8100
DEVICE_ALT0_VENDOR := Sitecom
DEVICE_ALT0_MODEL := X8 AC1750
DEVICE_PACKAGES := ath10k-firmware-qca988x-ct kmod-ath10k-ct kmod-usb2 kmod-usb3
SUPPORTED_DEVICES += wlr8100
IMAGES += factory.dlf
IMAGE/factory.dlf := append-kernel | pad-to $$$$(BLOCKSIZE) | \
append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) | \
senao-header -r 0x222 -p 0x56 -t 2
IMAGE_SIZE := 15424k
endef
TARGET_DEVICES += sitecom_wlr-8100
define Device/teltonika_rut955
SOC := ar9344
DEVICE_VENDOR := Teltonika

View File

@ -47,6 +47,24 @@ define Device/aerohive_hiveap-121
endef
TARGET_DEVICES += aerohive_hiveap-121
define Device/domywifi_dw33d
SOC := qca9558
DEVICE_VENDOR := DomyWifi
DEVICE_MODEL := DW33D
DEVICE_PACKAGES := kmod-usb2 kmod-usb-storage kmod-usb-ledtrig-usbport \
kmod-ath10k-ct ath10k-firmware-qca988x-ct
KERNEL_SIZE := 5120k
IMAGE_SIZE := 98304k
BLOCKSIZE := 128k
PAGESIZE := 2048
UBINIZE_OPTS := -E 5
IMAGES += factory.bin
IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | \
check-size $$$$(IMAGE_SIZE)
endef
TARGET_DEVICES += domywifi_dw33d
define Device/glinet_gl-ar300m-common-nand
SOC := qca9531
DEVICE_VENDOR := GL.iNet

View File

@ -12,6 +12,10 @@ ath79_setup_interfaces()
mikrotik,routerboard-922uags-5hpacd)
ucidef_set_interface_lan "eth0"
;;
domywifi,dw33d)
ucidef_add_switch "switch0" \
"0@eth0" "1:wan" "2:lan" "3:lan" "4:lan" "5:lan" "6@eth1"
;;
glinet,gl-ar750s-nor|\
glinet,gl-ar750s-nor-nand)
ucidef_add_switch "switch0" \

View File

@ -10,6 +10,10 @@ board=$(board_name)
case "$FIRMWARE" in
"ath10k/cal-pci-0000:00:00.0.bin")
case $board in
domywifi,dw33d)
caldata_extract "art" 0x5000 0x844
ath10k_patch_mac $(mtd_get_mac_binary art 0x12)
;;
glinet,gl-ar750s-nor|\
glinet,gl-ar750s-nor-nand)
caldata_extract "art" 0x5000 0x844

View File

@ -22,8 +22,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
#include "gpiolib.h"
#include "gpiolib-of.h"
@@ -895,3 +897,68 @@ void of_gpiochip_remove(struct gpio_chip
gpiochip_remove_pin_ranges(chip);
@@ -915,3 +917,68 @@ void of_gpiochip_remove(struct gpio_chip
{
of_node_put(chip->of_node);
}
+
@ -141,7 +141,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
{
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -661,6 +661,7 @@ static inline void devm_acpi_dev_remove_
@@ -668,6 +668,7 @@ static inline void devm_acpi_dev_remove_
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
@ -149,7 +149,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
@@ -668,6 +669,13 @@ void gpiod_unexport(struct gpio_desc *de
@@ -675,6 +676,13 @@ void gpiod_unexport(struct gpio_desc *de
#else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */

View File

@ -0,0 +1,267 @@
From patchwork Fri Feb 21 21:23:31 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
X-Patchwork-Id: 1198835
Date: Fri, 21 Feb 2020 22:23:31 +0100
From: Daniel Golle <daniel@makrotopia.org>
To: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Jiri Slaby <jslaby@suse.com>, Petr =?utf-8?q?=C5=A0tetiar?= <ynezz@true.cz>,
Chuanhong Guo <gch981213@gmail.com>, Piotr Dymacz <pepe2k@gmail.com>
Subject: [PATCH v2] serial: ar933x_uart: add RS485 support
Message-ID: <20200221212331.GA21467@makrotopia.org>
MIME-Version: 1.0
Content-Disposition: inline
Sender: linux-kernel-owner@vger.kernel.org
Precedence: bulk
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org
Emulate half-duplex operation and use mctrl_gpio to add support for
RS485 tranceiver with transmit/receive switch hooked to RTS GPIO line.
This is needed to make use of the RS485 port found on Teltonika RUT955.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v2: use bool to indicate ongoing half-duplex send, use it afterwards
to decide whether we've just been in a send operation.
drivers/tty/serial/Kconfig | 1 +
drivers/tty/serial/ar933x_uart.c | 113 +++++++++++++++++++++++++++++--
2 files changed, 108 insertions(+), 6 deletions(-)
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1279,6 +1279,7 @@ config SERIAL_AR933X
tristate "AR933X serial port support"
depends on HAVE_CLK && ATH79
select SERIAL_CORE
+ select SERIAL_MCTRL_GPIO if GPIOLIB
help
If you have an Atheros AR933X SOC based board and want to use the
built-in UART of the SoC, say Y to this option.
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -13,6 +13,7 @@
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
@@ -29,6 +30,8 @@
#include <asm/mach-ath79/ar933x_uart.h>
+#include "serial_mctrl_gpio.h"
+
#define DRIVER_NAME "ar933x-uart"
#define AR933X_UART_MAX_SCALE 0xff
@@ -47,6 +50,8 @@ struct ar933x_uart_port {
unsigned int min_baud;
unsigned int max_baud;
struct clk *clk;
+ struct mctrl_gpios *gpios;
+ struct gpio_desc *rts_gpiod;
};
static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
@@ -100,6 +105,18 @@ static inline void ar933x_uart_stop_tx_i
ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
}
+static inline void ar933x_uart_start_rx_interrupt(struct ar933x_uart_port *up)
+{
+ up->ier |= AR933X_UART_INT_RX_VALID;
+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
+}
+
+static inline void ar933x_uart_stop_rx_interrupt(struct ar933x_uart_port *up)
+{
+ up->ier &= ~AR933X_UART_INT_RX_VALID;
+ ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
+}
+
static inline void ar933x_uart_putc(struct ar933x_uart_port *up, int ch)
{
unsigned int rdata;
@@ -125,11 +142,21 @@ static unsigned int ar933x_uart_tx_empty
static unsigned int ar933x_uart_get_mctrl(struct uart_port *port)
{
- return TIOCM_CAR;
+ struct ar933x_uart_port *up =
+ container_of(port, struct ar933x_uart_port, port);
+ int ret = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+
+ mctrl_gpio_get(up->gpios, &ret);
+
+ return ret;
}
static void ar933x_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
+ struct ar933x_uart_port *up =
+ container_of(port, struct ar933x_uart_port, port);
+
+ mctrl_gpio_set(up->gpios, mctrl);
}
static void ar933x_uart_start_tx(struct uart_port *port)
@@ -140,6 +167,37 @@ static void ar933x_uart_start_tx(struct
ar933x_uart_start_tx_interrupt(up);
}
+static void ar933x_uart_wait_tx_complete(struct ar933x_uart_port *up)
+{
+ unsigned int status;
+ unsigned int timeout = 60000;
+
+ /* Wait up to 60ms for the character(s) to be sent. */
+ do {
+ status = ar933x_uart_read(up, AR933X_UART_CS_REG);
+ if (--timeout == 0)
+ break;
+ udelay(1);
+ } while (status & AR933X_UART_CS_TX_BUSY);
+
+ if (timeout == 0)
+ dev_err(up->port.dev, "waiting for TX timed out\n");
+}
+
+static void ar933x_uart_rx_flush(struct ar933x_uart_port *up)
+{
+ unsigned int status;
+
+ /* clear RX_VALID interrupt */
+ ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_RX_VALID);
+
+ /* remove characters from the RX FIFO */
+ do {
+ ar933x_uart_write(up, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR);
+ status = ar933x_uart_read(up, AR933X_UART_DATA_REG);
+ } while (status & AR933X_UART_DATA_RX_CSR);
+}
+
static void ar933x_uart_stop_tx(struct uart_port *port)
{
struct ar933x_uart_port *up =
@@ -153,8 +211,7 @@ static void ar933x_uart_stop_rx(struct u
struct ar933x_uart_port *up =
container_of(port, struct ar933x_uart_port, port);
- up->ier &= ~AR933X_UART_INT_RX_VALID;
- ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
+ ar933x_uart_stop_rx_interrupt(up);
}
static void ar933x_uart_break_ctl(struct uart_port *port, int break_state)
@@ -336,11 +393,20 @@ static void ar933x_uart_rx_chars(struct
static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
{
struct circ_buf *xmit = &up->port.state->xmit;
+ struct serial_rs485 *rs485conf = &up->port.rs485;
int count;
+ bool half_duplex_send = false;
if (uart_tx_stopped(&up->port))
return;
+ if ((rs485conf->flags & SER_RS485_ENABLED) &&
+ (up->port.x_char || !uart_circ_empty(xmit))) {
+ ar933x_uart_stop_rx_interrupt(up);
+ gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_ON_SEND));
+ half_duplex_send = true;
+ }
+
count = up->port.fifosize;
do {
unsigned int rdata;
@@ -368,8 +434,14 @@ static void ar933x_uart_tx_chars(struct
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&up->port);
- if (!uart_circ_empty(xmit))
+ if (!uart_circ_empty(xmit)) {
ar933x_uart_start_tx_interrupt(up);
+ } else if (half_duplex_send) {
+ ar933x_uart_wait_tx_complete(up);
+ ar933x_uart_rx_flush(up);
+ ar933x_uart_start_rx_interrupt(up);
+ gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_AFTER_SEND));
+ }
}
static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id)
@@ -427,8 +499,7 @@ static int ar933x_uart_startup(struct ua
AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE);
/* Enable RX interrupts */
- up->ier = AR933X_UART_INT_RX_VALID;
- ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
+ ar933x_uart_start_rx_interrupt(up);
spin_unlock_irqrestore(&up->port.lock, flags);
@@ -511,6 +582,21 @@ static const struct uart_ops ar933x_uart
.verify_port = ar933x_uart_verify_port,
};
+static int ar933x_config_rs485(struct uart_port *port,
+ struct serial_rs485 *rs485conf)
+{
+ struct ar933x_uart_port *up =
+ container_of(port, struct ar933x_uart_port, port);
+
+ if ((rs485conf->flags & SER_RS485_ENABLED) &&
+ !up->rts_gpiod) {
+ dev_err(port->dev, "RS485 needs rts-gpio\n");
+ return 1;
+ }
+ port->rs485 = *rs485conf;
+ return 0;
+}
+
#ifdef CONFIG_SERIAL_AR933X_CONSOLE
static struct ar933x_uart_port *
ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS];
@@ -680,6 +766,8 @@ static int ar933x_uart_probe(struct plat
goto err_disable_clk;
}
+ uart_get_rs485_mode(&pdev->dev, &port->rs485);
+
port->mapbase = mem_res->start;
port->line = id;
port->irq = irq_res->start;
@@ -690,6 +778,7 @@ static int ar933x_uart_probe(struct plat
port->regshift = 2;
port->fifosize = AR933X_UART_FIFO_SIZE;
port->ops = &ar933x_uart_ops;
+ port->rs485_config = ar933x_config_rs485;
baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1);
up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD);
@@ -697,6 +786,18 @@ static int ar933x_uart_probe(struct plat
baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
+ up->gpios = mctrl_gpio_init(port, 0);
+ if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS)
+ return PTR_ERR(up->gpios);
+
+ up->rts_gpiod = mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS);
+
+ if ((port->rs485.flags & SER_RS485_ENABLED) &&
+ !up->rts_gpiod) {
+ dev_err(&pdev->dev, "lacking rts-gpio, disabling RS485\n");
+ port->rs485.flags &= ~SER_RS485_ENABLED;
+ }
+
#ifdef CONFIG_SERIAL_AR933X_CONSOLE
ar933x_console_ports[up->port.line] = up;
#endif

View File

@ -21,5 +21,5 @@
obj-y += parsers/
+obj-$(CONFIG_MTD_TPLINK_PARTS) += tplinkpart.o
# 'Users' - code which presents functionality to userspace.
obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o
obj-$(CONFIG_MTD_SPLIT) += mtdsplit/

View File

@ -305,7 +305,7 @@
list_for_each_entry(p, head, list) {
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -457,48 +457,53 @@ static void tcp_options_write(__be32 *pt
@@ -460,48 +460,53 @@ static void tcp_options_write(__be32 *pt
u16 options = opts->options; /* mungable copy */
if (unlikely(OPTION_MD5 & options)) {
@ -382,7 +382,7 @@
}
if (unlikely(opts->num_sack_blocks)) {
@@ -506,16 +511,17 @@ static void tcp_options_write(__be32 *pt
@@ -509,16 +514,17 @@ static void tcp_options_write(__be32 *pt
tp->duplicate_sack : tp->selective_acks;
int this_sack;
@ -406,7 +406,7 @@
}
tp->rx_opt.dsack = 0;
@@ -528,13 +534,14 @@ static void tcp_options_write(__be32 *pt
@@ -531,13 +537,14 @@ static void tcp_options_write(__be32 *pt
if (foc->exp) {
len = TCPOLEN_EXP_FASTOPEN_BASE + foc->len;
@ -706,7 +706,7 @@
EXPORT_SYMBOL(xfrm_parse_spi);
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3953,14 +3953,16 @@ static bool tcp_parse_aligned_timestamp(
@@ -3958,14 +3958,16 @@ static bool tcp_parse_aligned_timestamp(
{
const __be32 *ptr = (const __be32 *)(th + 1);
@ -754,7 +754,7 @@
ptr = ip6hoff + sizeof(struct ipv6hdr);
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -274,8 +274,10 @@ static inline bool neigh_key_eq128(const
@@ -273,8 +273,10 @@ static inline bool neigh_key_eq128(const
const u32 *n32 = (const u32 *)n->primary_key;
const u32 *p32 = pkey;
@ -780,7 +780,7 @@
* No flags defined yet.
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -443,8 +443,14 @@ void inet_proto_csum_replace16(__sum16 *
@@ -460,8 +460,14 @@ void inet_proto_csum_replace16(__sum16 *
bool pseudohdr)
{
__be32 diff[] = {
@ -799,7 +799,7 @@
*sum = csum_fold(csum_partial(diff, sizeof(diff),
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -496,7 +496,7 @@ static inline bool is_etherdev_addr(cons
@@ -489,7 +489,7 @@ static inline bool is_etherdev_addr(cons
* @b: Pointer to Ethernet header
*
* Compare two Ethernet headers, returns 0 if equal.
@ -808,7 +808,7 @@
* aligned OR the platform can handle unaligned access. This is the
* case for all packets coming into netif_receive_skb or similar
* entry points.
@@ -519,11 +519,12 @@ static inline unsigned long compare_ethe
@@ -512,11 +512,12 @@ static inline unsigned long compare_ethe
fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6);
return fold;
#else

View File

@ -10,6 +10,7 @@ DEVICE_TYPE:=nas
MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
KERNEL_PATCHVER:=4.14
KERNEL_TESTING_PATCHVER:=5.4
include $(INCLUDE_DIR)/target.mk

View File

@ -0,0 +1,367 @@
CONFIG_64BIT_TIME=y
CONFIG_ALIGNMENT_TRAP=y
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_CLOCKSOURCE_DATA=y
CONFIG_ARCH_HAS_BINFMT_FLAT=y
CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
CONFIG_ARCH_HAS_DMA_WRITE_COMBINE=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
CONFIG_ARCH_HAS_KCOV=y
CONFIG_ARCH_HAS_KEEPINITRD=y
CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
CONFIG_ARCH_HAS_PHYS_TO_DMA=y
CONFIG_ARCH_HAS_RESET_CONTROLLER=y
CONFIG_ARCH_HAS_SETUP_DMA_OPS=y
CONFIG_ARCH_HAS_SET_MEMORY=y
CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_ARCH_MULTIPLATFORM=y
CONFIG_ARCH_MULTI_CPU_AUTO=y
# CONFIG_ARCH_MULTI_V4 is not set
# CONFIG_ARCH_MULTI_V4T is not set
CONFIG_ARCH_MULTI_V4_V5=y
CONFIG_ARCH_MULTI_V5=y
CONFIG_ARCH_NR_GPIO=0
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_OXNAS=y
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_ARCH_WANT_LIBATA_LEDS=y
CONFIG_ARM=y
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set
CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE=y
CONFIG_ARM_CPU_SUSPEND=y
CONFIG_ARM_HAS_SG_CHAIN=y
CONFIG_ARM_L1_CACHE_SHIFT=5
CONFIG_ARM_PATCH_PHYS_VIRT=y
CONFIG_ARM_PMU=y
# CONFIG_ARM_SMMU is not set
CONFIG_ARM_THUMB=y
CONFIG_ARM_UNWIND=y
CONFIG_ATAGS=y
CONFIG_AUTO_ZRELADDR=y
CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y
CONFIG_BLK_CMDLINE_PARSER=y
CONFIG_BLK_DEBUG_FS=y
CONFIG_BLK_DEV_BSG=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_BLK_PM=y
CONFIG_BLK_SCSI_REQUEST=y
# CONFIG_BPF_SYSCALL is not set
CONFIG_CC_HAS_KASAN_GENERIC=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CLKSRC_MMIO=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CMA=y
CONFIG_CMA_ALIGNMENT=8
CONFIG_CMA_AREAS=7
# CONFIG_CMA_DEBUG is not set
# CONFIG_CMA_DEBUGFS is not set
CONFIG_CMA_SIZE_MBYTES=64
# CONFIG_CMA_SIZE_SEL_MAX is not set
CONFIG_CMA_SIZE_SEL_MBYTES=y
# CONFIG_CMA_SIZE_SEL_MIN is not set
# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
CONFIG_CMDLINE_PARTITION=y
CONFIG_COMMON_CLK=y
CONFIG_COMMON_CLK_OXNAS=y
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_CONTIG_ALLOC=y
CONFIG_COREDUMP=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5TJ=y
CONFIG_CPU_ARM926T=y
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_CP15=y
CONFIG_CPU_CP15_MMU=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
# CONFIG_CPU_ICACHE_DISABLE is not set
CONFIG_CPU_PABRT_LEGACY=y
CONFIG_CPU_PM=y
# CONFIG_CPU_IDLE_GOV_TEO is not set
CONFIG_CPU_THUMB_CAPABLE=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_USE_DOMAINS=y
CONFIG_CRASH_CORE=y
CONFIG_CRC16=y
# CONFIG_CRC32_SARWATE is not set
CONFIG_CRC32_SLICEBY8=y
CONFIG_CROSS_MEMORY_ATTACH=y
CONFIG_CRYPTO_RNG2=y
CONFIG_DEBUG_ALIGN_RODATA=y
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
# CONFIG_DEBUG_USER is not set
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_LZ4=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_DECOMPRESS_XZ=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_DMA_CMA=y
CONFIG_DMA_DECLARE_COHERENT=y
CONFIG_DMA_REMAP=y
CONFIG_DNOTIFY=y
CONFIG_DTC=y
# CONFIG_DWMAC_DWC_QOS_ETH is not set
CONFIG_DWMAC_GENERIC=y
CONFIG_DWMAC_OXNAS=y
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
CONFIG_ELF_CORE=y
CONFIG_FAT_FS=y
CONFIG_FIXED_PHY=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_FREEZER=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GPIOLIB=y
CONFIG_GPIOLIB_IRQCHIP=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_GENERIC_PLATFORM=y
CONFIG_HANDLE_DOMAIN_IRQ=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HAVE_ARCH_AUDITSYSCALL=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_ARCH_PFN_VALID=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_CLK_PREPARE=y
CONFIG_HAVE_CONTEXT_TRACKING=y
CONFIG_HAVE_COPY_THREAD_TLS=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_HAVE_EBPF_JIT=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_HAVE_NET_DSA=y
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_PCI=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_HAVE_PERF_REGS=y
CONFIG_HAVE_PERF_USER_STACK_DUMP=y
CONFIG_HAVE_PROC_CPU=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_RSEQ=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_UID16=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
CONFIG_HID=y
CONFIG_HID_GENERIC=y
CONFIG_HWMON=y
CONFIG_HZ_FIXED=0
CONFIG_ICPLUS_PHY=y
CONFIG_INET_DIAG=y
# CONFIG_INET_DIAG_DESTROY is not set
# CONFIG_INET_RAW_DIAG is not set
CONFIG_INET_TCP_DIAG=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_INPUT=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
CONFIG_IOMMU_SUPPORT=y
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
# CONFIG_ISDN is not set
# CONFIG_JFFS2_FS is not set
CONFIG_KALLSYMS=y
CONFIG_KASAN_STACK=1
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_XZ is not set
CONFIG_KEXEC=y
CONFIG_KEXEC_CORE=y
# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
# CONFIG_LEDS_TRIGGER_NETDEV is not set
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LIBFDT=y
CONFIG_LOCALVERSION_AUTO=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LZ4_DECOMPRESS=y
CONFIG_LZO_DECOMPRESS=y
# CONFIG_MACH_OX810SE is not set
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MEMFD_CREATE=y
CONFIG_MEMORY_ISOLATION=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
CONFIG_MODULES_TREE_LOOKUP=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_KUSER_HELPERS=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NET_PTP_CLASSIFY=y
CONFIG_NLS=y
CONFIG_NO_HZ=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
# CONFIG_NVMEM_REBOOT_MODE is not set
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OF_NET=y
CONFIG_OF_RESERVED_MEM=y
CONFIG_OLD_SIGACTION=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_OXNAS_RPS_TIMER=y
CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PAGE_POOL=y
# CONFIG_PANIC_ON_OOPS is not set
CONFIG_PANIC_ON_OOPS_VALUE=0
CONFIG_PANIC_TIMEOUT=0
CONFIG_PERF_EVENTS=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
CONFIG_PHY_OXNAS=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_OXNAS=y
# CONFIG_PINCTRL_SINGLE is not set
CONFIG_PLUGIN_HOSTCC="g++"
CONFIG_PM=y
CONFIG_PM_CLK=y
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_OXNAS=y
CONFIG_PPS=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_RAS=y
CONFIG_RATIONAL=y
CONFIG_RCU_TRACE=y
CONFIG_RD_BZIP2=y
CONFIG_RD_GZIP=y
CONFIG_RD_LZ4=y
CONFIG_RD_LZMA=y
CONFIG_RD_LZO=y
CONFIG_RD_XZ=y
CONFIG_REALTEK_PHY=y
CONFIG_REFCOUNT_FULL=y
CONFIG_REGMAP=y
CONFIG_REGMAP_MMIO=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_OXNAS=y
CONFIG_SCHED_DEBUG=y
CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIO=y
CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_SERPORT=y
CONFIG_SIMPLE_PM_BUS=y
CONFIG_SLUB_DEBUG=y
CONFIG_SOCK_DIAG=y
CONFIG_SPARSE_IRQ=y
CONFIG_SPLIT_PTLOCK_CPUS=999999
CONFIG_SRCU=y
CONFIG_STACKTRACE=y
# CONFIG_STAGING is not set
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PLATFORM=y
# CONFIG_STMMAC_SELFTESTS is not set
# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
CONFIG_SWPHY=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TINY_SRCU=y
CONFIG_TRACE_CLOCK=y
CONFIG_UBSAN_ALIGNMENT=y
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
CONFIG_UNIX_SCM=y
CONFIG_UNWINDER_ARM=y
# CONFIG_UNWINDER_FRAME_POINTER is not set
CONFIG_USB_SUPPORT=y
# CONFIG_USERIO is not set
CONFIG_USE_OF=y
CONFIG_VERSATILE_FPGA_IRQ=y
CONFIG_VERSATILE_FPGA_IRQ_NR=4
CONFIG_VFAT_FS=y
# CONFIG_VFP is not set
# CONFIG_VLAN_8021Q is not set
CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_WATCHDOG is not set
# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_BCJ=y
CONFIG_XZ_DEC_IA64=y
CONFIG_XZ_DEC_POWERPC=y
CONFIG_XZ_DEC_SPARC=y
CONFIG_XZ_DEC_X86=y
CONFIG_ZBOOT_ROM_BSS=0
CONFIG_ZBOOT_ROM_TEXT=0
CONFIG_ZLIB_INFLATE=y

View File

@ -0,0 +1,674 @@
/*
* PCIe driver for PLX NAS782X SoCs
*
* Author: Ma Haijun <mahaijuns@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/mbus.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/phy.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/io.h>
#include <linux/sizes.h>
#include "../pci.h"
#define SYS_CTRL_HCSL_CTRL_REGOFFSET 0x114
static inline void oxnas_register_clear_mask(void __iomem *p, unsigned mask)
{
u32 val = readl_relaxed(p);
val &= ~mask;
writel_relaxed(val, p);
}
static inline void oxnas_register_set_mask(void __iomem *p, unsigned mask)
{
u32 val = readl_relaxed(p);
val |= mask;
writel_relaxed(val, p);
}
static inline void oxnas_register_value_mask(void __iomem *p,
unsigned mask, unsigned new_value)
{
/* TODO sanity check mask & new_value = new_value */
u32 val = readl_relaxed(p);
val &= ~mask;
val |= new_value;
writel_relaxed(val, p);
}
#define VERSION_ID_MAGIC 0x082510b5
#define LINK_UP_TIMEOUT_SECONDS 1
#define NUM_CONTROLLERS 1
enum {
PCIE_DEVICE_TYPE_MASK = 0x0F,
PCIE_DEVICE_TYPE_ENDPOINT = 0,
PCIE_DEVICE_TYPE_LEGACY_ENDPOINT = 1,
PCIE_DEVICE_TYPE_ROOT = 4,
PCIE_LTSSM = BIT(4),
PCIE_READY_ENTR_L23 = BIT(9),
PCIE_LINK_UP = BIT(11),
PCIE_OBTRANS = BIT(12),
};
/* core config registers */
enum {
PCI_CONFIG_VERSION_DEVICEID = 0,
PCI_CONFIG_COMMAND_STATUS = 4,
};
/* inbound config registers */
enum {
IB_ADDR_XLATE_ENABLE = 0xFC,
/* bits */
ENABLE_IN_ADDR_TRANS = BIT(0),
};
/* outbound config registers, offset relative to PCIE_POM0_MEM_ADDR */
enum {
PCIE_POM0_MEM_ADDR = 0,
PCIE_POM1_MEM_ADDR = 4,
PCIE_IN0_MEM_ADDR = 8,
PCIE_IN1_MEM_ADDR = 12,
PCIE_IN_IO_ADDR = 16,
PCIE_IN_CFG0_ADDR = 20,
PCIE_IN_CFG1_ADDR = 24,
PCIE_IN_MSG_ADDR = 28,
PCIE_IN0_MEM_LIMIT = 32,
PCIE_IN1_MEM_LIMIT = 36,
PCIE_IN_IO_LIMIT = 40,
PCIE_IN_CFG0_LIMIT = 44,
PCIE_IN_CFG1_LIMIT = 48,
PCIE_IN_MSG_LIMIT = 52,
PCIE_AHB_SLAVE_CTRL = 56,
PCIE_SLAVE_BE_SHIFT = 22,
};
#define PCIE_SLAVE_BE(val) ((val) << PCIE_SLAVE_BE_SHIFT)
#define PCIE_SLAVE_BE_MASK PCIE_SLAVE_BE(0xF)
struct oxnas_pcie_shared {
/* seems all access are serialized, no lock required */
int refcount;
};
/* Structure representing one PCIe interfaces */
struct oxnas_pcie {
void __iomem *cfgbase;
void __iomem *base;
void __iomem *inbound;
struct regmap *sys_ctrl;
unsigned int outbound_offset;
unsigned int pcie_ctrl_offset;
struct phy *phy;
int haslink;
struct platform_device *pdev;
struct resource io;
struct resource cfg;
struct resource pre_mem; /* prefetchable */
struct resource non_mem; /* non-prefetchable */
struct resource busn; /* max available bus numbers */
int card_reset; /* gpio pin, optional */
unsigned hcsl_en; /* hcsl pci enable bit */
struct clk *clk;
struct clk *busclk; /* for pcie bus, actually the PLLB */
void *private_data[1];
spinlock_t lock;
};
static struct oxnas_pcie_shared pcie_shared = {
.refcount = 0,
};
static inline struct oxnas_pcie *sys_to_pcie(struct pci_sys_data *sys)
{
return sys->private_data;
}
static inline void set_out_lanes(struct oxnas_pcie *pcie, unsigned lanes)
{
regmap_update_bits(pcie->sys_ctrl, pcie->outbound_offset + PCIE_AHB_SLAVE_CTRL,
PCIE_SLAVE_BE_MASK, PCIE_SLAVE_BE(lanes));
wmb();
}
static int oxnas_pcie_link_up(struct oxnas_pcie *pcie)
{
unsigned long end;
unsigned int val;
/* Poll for PCIE link up */
end = jiffies + (LINK_UP_TIMEOUT_SECONDS * HZ);
while (!time_after(jiffies, end)) {
regmap_read(pcie->sys_ctrl, pcie->pcie_ctrl_offset, &val);
if (val & PCIE_LINK_UP)
return 1;
}
return 0;
}
static void oxnas_pcie_setup_hw(struct oxnas_pcie *pcie)
{
/* We won't have any inbound address translation. This allows PCI
* devices to access anywhere in the AHB address map. Might be regarded
* as a bit dangerous, but let's get things working before we worry
* about that
*/
oxnas_register_clear_mask(pcie->inbound + IB_ADDR_XLATE_ENABLE,
ENABLE_IN_ADDR_TRANS);
wmb();
/*
* Program outbound translation windows
*
* Outbound window is what is referred to as "PCI client" region in HRM
*
* Could use the larger alternative address space to get >>64M regions
* for graphics cards etc., but will not bother at this point.
*
* IP bug means that AMBA window size must be a power of 2
*
* Set mem0 window for first 16MB of outbound window non-prefetchable
* Set mem1 window for second 16MB of outbound window prefetchable
* Set io window for next 16MB of outbound window
* Set cfg0 for final 1MB of outbound window
*
* Ignore mem1, cfg1 and msg windows for now as no obvious use cases for
* 820 that would need them
*
* Probably ideally want no offset between mem0 window start as seen by
* ARM and as seen on PCI bus and get Linux to assign memory regions to
* PCI devices using the same "PCI client" region start address as seen
* by ARM
*/
/* Set PCIeA mem0 region to be 1st 16MB of the 64MB PCIeA window */
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN0_MEM_ADDR, pcie->non_mem.start);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN0_MEM_LIMIT, pcie->non_mem.end);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_POM0_MEM_ADDR, pcie->non_mem.start);
/* Set PCIeA mem1 region to be 2nd 16MB of the 64MB PCIeA window */
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN1_MEM_ADDR, pcie->pre_mem.start);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN1_MEM_LIMIT, pcie->pre_mem.end);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_POM1_MEM_ADDR, pcie->pre_mem.start);
/* Set PCIeA io to be third 16M region of the 64MB PCIeA window*/
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN_IO_ADDR, pcie->io.start);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN_IO_LIMIT, pcie->io.end);
/* Set PCIeA cgf0 to be last 16M region of the 64MB PCIeA window*/
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN_CFG0_ADDR, pcie->cfg.start);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN_CFG0_LIMIT, pcie->cfg.end);
wmb();
/* Enable outbound address translation */
regmap_write_bits(pcie->sys_ctrl, pcie->pcie_ctrl_offset, PCIE_OBTRANS, PCIE_OBTRANS);
wmb();
/*
* Program PCIe command register for core to:
* enable memory space
* enable bus master
* enable io
*/
writel_relaxed(7, pcie->base + PCI_CONFIG_COMMAND_STATUS);
/* which is which */
wmb();
}
static unsigned oxnas_pcie_cfg_to_offset(
struct pci_sys_data *sys,
unsigned char bus_number,
unsigned int devfn,
int where)
{
unsigned int function = PCI_FUNC(devfn);
unsigned int slot = PCI_SLOT(devfn);
unsigned char bus_number_offset;
bus_number_offset = bus_number - sys->busnr;
/*
* We'll assume for now that the offset, function, slot, bus encoding
* should map onto linear, contiguous addresses in PCIe config space,
* albeit that the majority will be unused as only slot 0 is valid for
* any PCIe bus and most devices have only function 0
*
* Could be that PCIe in fact works by not encoding the slot number into
* the config space address as it's known that only slot 0 is valid.
* We'll have to experiment if/when we get a PCIe switch connected to
* the PCIe host
*/
return (bus_number_offset << 20) | (slot << 15) | (function << 12) |
(where & ~3);
}
/* PCI configuration space write function */
static int oxnas_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
unsigned long flags;
struct oxnas_pcie *pcie = sys_to_pcie(bus->sysdata);
unsigned offset;
u32 value;
u32 lanes;
/* Only a single device per bus for PCIe point-to-point links */
if (PCI_SLOT(devfn) > 0)
return PCIBIOS_DEVICE_NOT_FOUND;
if (!pcie->haslink)
return PCIBIOS_DEVICE_NOT_FOUND;
offset = oxnas_pcie_cfg_to_offset(bus->sysdata, bus->number, devfn,
where);
value = val << (8 * (where & 3));
lanes = (0xf >> (4-size)) << (where & 3);
/* it race with mem and io write, but the possibility is low, normally
* all config writes happens at driver initialize stage, wont interleave
* with others.
* and many pcie cards use dword (4bytes) access mem/io access only,
* so not bother to copy that ugly work-around now. */
spin_lock_irqsave(&pcie->lock, flags);
set_out_lanes(pcie, lanes);
writel_relaxed(value, pcie->cfgbase + offset);
set_out_lanes(pcie, 0xf);
spin_unlock_irqrestore(&pcie->lock, flags);
return PCIBIOS_SUCCESSFUL;
}
/* PCI configuration space read function */
static int oxnas_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
int size, u32 *val)
{
struct oxnas_pcie *pcie = sys_to_pcie(bus->sysdata);
unsigned offset;
u32 value;
u32 left_bytes, right_bytes;
/* Only a single device per bus for PCIe point-to-point links */
if (PCI_SLOT(devfn) > 0) {
*val = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
if (!pcie->haslink) {
*val = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
offset = oxnas_pcie_cfg_to_offset(bus->sysdata, bus->number, devfn,
where);
value = readl_relaxed(pcie->cfgbase + offset);
left_bytes = where & 3;
right_bytes = 4 - left_bytes - size;
value <<= right_bytes * 8;
value >>= (left_bytes + right_bytes) * 8;
*val = value;
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops oxnas_pcie_ops = {
.read = oxnas_pcie_rd_conf,
.write = oxnas_pcie_wr_conf,
};
static int oxnas_pcie_setup(int nr, struct pci_sys_data *sys)
{
struct oxnas_pcie *pcie = sys_to_pcie(sys);
pci_add_resource_offset(&sys->resources, &pcie->non_mem, sys->mem_offset);
pci_add_resource_offset(&sys->resources, &pcie->pre_mem, sys->mem_offset);
pci_add_resource_offset(&sys->resources, &pcie->io, sys->io_offset);
pci_add_resource(&sys->resources, &pcie->busn);
if (sys->busnr == 0) { /* default one */
sys->busnr = pcie->busn.start;
}
/* do not use devm_ioremap_resource, it does not like cfg resource */
pcie->cfgbase = devm_ioremap(&pcie->pdev->dev, pcie->cfg.start,
resource_size(&pcie->cfg));
if (!pcie->cfgbase)
return -ENOMEM;
oxnas_pcie_setup_hw(pcie);
return 1;
}
static void oxnas_pcie_enable(struct device *dev, struct oxnas_pcie *pcie)
{
struct hw_pci hw;
int i;
memset(&hw, 0, sizeof(hw));
for (i = 0; i < NUM_CONTROLLERS; i++)
pcie->private_data[i] = pcie;
hw.nr_controllers = NUM_CONTROLLERS;
/* I think use stack pointer is a bad idea though it is valid in this case */
hw.private_data = pcie->private_data;
hw.setup = oxnas_pcie_setup;
hw.map_irq = of_irq_parse_and_map_pci;
hw.ops = &oxnas_pcie_ops;
/* pass dev to maintain of tree, interrupt mapping rely on this */
pci_common_init_dev(dev, &hw);
}
static int oxnas_pcie_shared_init(struct platform_device *pdev, struct oxnas_pcie *pcie)
{
if (++pcie_shared.refcount == 1) {
phy_init(pcie->phy);
phy_power_on(pcie->phy);
return 0;
} else {
return 0;
}
}
#if 0
/* maybe we will call it when enter low power state */
static void oxnas_pcie_shared_deinit(struct platform_device *pdev)
{
if (--pcie_shared.refcount == 0) {
/* no cleanup needed */;
}
}
#endif
static int
oxnas_pcie_map_registers(struct platform_device *pdev,
struct device_node *np,
struct oxnas_pcie *pcie)
{
struct resource regs;
int ret = 0;
u32 outbound_ctrl_offset;
u32 pcie_ctrl_offset;
ret = of_address_to_resource(np, 0, &regs);
if (ret) {
dev_err(&pdev->dev, "failed to parse base register space\n");
return -EINVAL;
}
pcie->base = devm_ioremap_resource(&pdev->dev, &regs);
if (!pcie->base) {
dev_err(&pdev->dev, "failed to map base register space\n");
return -ENOMEM;
}
ret = of_address_to_resource(np, 1, &regs);
if (ret) {
dev_err(&pdev->dev, "failed to parse inbound register space\n");
return -EINVAL;
}
pcie->inbound = devm_ioremap_resource(&pdev->dev, &regs);
if (!pcie->inbound) {
dev_err(&pdev->dev, "failed to map inbound register space\n");
return -ENOMEM;
}
pcie->phy = devm_of_phy_get(&pdev->dev, np, NULL);
if (IS_ERR(pcie->phy)) {
if (PTR_ERR(pcie->phy) == -EPROBE_DEFER) {
dev_err(&pdev->dev, "failed to probe phy\n");
return PTR_ERR(pcie->phy);
}
dev_warn(&pdev->dev, "phy not attached\n");
pcie->phy = NULL;
}
if (of_property_read_u32(np, "plxtech,pcie-outbound-offset",
&outbound_ctrl_offset)) {
dev_err(&pdev->dev, "failed to parse outbound register offset\n");
return -EINVAL;
}
pcie->outbound_offset = outbound_ctrl_offset;
if (of_property_read_u32(np, "plxtech,pcie-ctrl-offset",
&pcie_ctrl_offset)) {
dev_err(&pdev->dev, "failed to parse pcie-ctrl register offset\n");
return -EINVAL;
}
pcie->pcie_ctrl_offset = pcie_ctrl_offset;
return 0;
}
static int oxnas_pcie_init_res(struct platform_device *pdev,
struct oxnas_pcie *pcie,
struct device_node *np)
{
struct of_pci_range range;
struct of_pci_range_parser parser;
int ret;
if (of_pci_range_parser_init(&parser, np))
return -EINVAL;
/* Get the I/O and memory ranges from DT */
for_each_of_pci_range(&parser, &range) {
unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
if (restype == IORESOURCE_IO) {
of_pci_range_to_resource(&range, np, &pcie->io);
pcie->io.name = "I/O";
}
if (restype == IORESOURCE_MEM) {
if (range.flags & IORESOURCE_PREFETCH) {
of_pci_range_to_resource(&range, np, &pcie->pre_mem);
pcie->pre_mem.name = "PRE MEM";
} else {
of_pci_range_to_resource(&range, np, &pcie->non_mem);
pcie->non_mem.name = "NON MEM";
}
}
if (restype == 0)
of_pci_range_to_resource(&range, np, &pcie->cfg);
}
/* Get the bus range */
ret = of_pci_parse_bus_range(np, &pcie->busn);
if (ret) {
dev_err(&pdev->dev, "failed to parse bus-range property: %d\n",
ret);
return ret;
}
pcie->card_reset = of_get_gpio(np, 0);
if (pcie->card_reset < 0)
dev_info(&pdev->dev, "card reset gpio pin not exists\n");
if (of_property_read_u32(np, "plxtech,pcie-hcsl-bit", &pcie->hcsl_en))
return -EINVAL;
pcie->clk = of_clk_get_by_name(np, "pcie");
if (IS_ERR(pcie->clk)) {
return PTR_ERR(pcie->clk);
}
pcie->busclk = of_clk_get_by_name(np, "busclk");
if (IS_ERR(pcie->busclk)) {
clk_put(pcie->clk);
return PTR_ERR(pcie->busclk);
}
return 0;
}
static void oxnas_pcie_init_hw(struct platform_device *pdev,
struct oxnas_pcie *pcie)
{
u32 version_id;
int ret;
clk_prepare_enable(pcie->busclk);
/* reset PCIe cards use hard-wired gpio pin */
if (pcie->card_reset >= 0 &&
!gpio_direction_output(pcie->card_reset, 0)) {
wmb();
mdelay(10);
/* must tri-state the pin to pull it up */
gpio_direction_input(pcie->card_reset);
wmb();
mdelay(100);
}
/* ToDo: use phy power-on port... */
regmap_update_bits(pcie->sys_ctrl, SYS_CTRL_HCSL_CTRL_REGOFFSET,
BIT(pcie->hcsl_en), BIT(pcie->hcsl_en));
/* core */
ret = device_reset(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "core reset failed %d\n", ret);
return;
}
/* Start PCIe core clocks */
clk_prepare_enable(pcie->clk);
version_id = readl_relaxed(pcie->base + PCI_CONFIG_VERSION_DEVICEID);
dev_info(&pdev->dev, "PCIe version/deviceID 0x%x\n", version_id);
if (version_id != VERSION_ID_MAGIC) {
dev_info(&pdev->dev, "PCIe controller not found\n");
pcie->haslink = 0;
return;
}
/* allow entry to L23 state */
regmap_write_bits(pcie->sys_ctrl, pcie->pcie_ctrl_offset,
PCIE_READY_ENTR_L23, PCIE_READY_ENTR_L23);
/* Set PCIe core into RootCore mode */
regmap_write_bits(pcie->sys_ctrl, pcie->pcie_ctrl_offset,
PCIE_DEVICE_TYPE_MASK, PCIE_DEVICE_TYPE_ROOT);
wmb();
/* Bring up the PCI core */
regmap_write_bits(pcie->sys_ctrl, pcie->pcie_ctrl_offset,
PCIE_LTSSM, PCIE_LTSSM);
wmb();
}
static int oxnas_pcie_probe(struct platform_device *pdev)
{
struct oxnas_pcie *pcie;
struct device_node *np = pdev->dev.of_node;
int ret;
pcie = devm_kzalloc(&pdev->dev, sizeof(struct oxnas_pcie),
GFP_KERNEL);
if (!pcie)
return -ENOMEM;
pcie->pdev = pdev;
pcie->haslink = 1;
spin_lock_init(&pcie->lock);
pcie->sys_ctrl = syscon_regmap_lookup_by_compatible("oxsemi,ox820-sys-ctrl");
if (IS_ERR(pcie->sys_ctrl))
return PTR_ERR(pcie->sys_ctrl);
ret = oxnas_pcie_init_res(pdev, pcie, np);
if (ret)
return ret;
if (pcie->card_reset >= 0) {
ret = gpio_request_one(pcie->card_reset, GPIOF_DIR_IN,
dev_name(&pdev->dev));
if (ret) {
dev_err(&pdev->dev, "cannot request gpio pin %d\n",
pcie->card_reset);
return ret;
}
}
ret = oxnas_pcie_map_registers(pdev, np, pcie);
if (ret) {
dev_err(&pdev->dev, "cannot map registers\n");
goto err_free_gpio;
}
ret = oxnas_pcie_shared_init(pdev, pcie);
if (ret)
goto err_free_gpio;
/* if hw not found, haslink cleared */
oxnas_pcie_init_hw(pdev, pcie);
if (pcie->haslink && oxnas_pcie_link_up(pcie)) {
pcie->haslink = 1;
dev_info(&pdev->dev, "link up\n");
} else {
pcie->haslink = 0;
dev_info(&pdev->dev, "link down\n");
}
/* should we register our controller even when pcie->haslink is 0 ? */
/* register the controller with framework */
oxnas_pcie_enable(&pdev->dev, pcie);
return 0;
err_free_gpio:
if (pcie->card_reset)
gpio_free(pcie->card_reset);
return ret;
}
static const struct of_device_id oxnas_pcie_of_match_table[] = {
{ .compatible = "plxtech,nas782x-pcie", },
{},
};
static struct platform_driver oxnas_pcie_driver = {
.driver = {
.name = "oxnas-pcie",
.suppress_bind_attrs = true,
.of_match_table = oxnas_pcie_of_match_table,
},
.probe = oxnas_pcie_probe,
};
builtin_platform_driver(oxnas_pcie_driver);

View File

@ -0,0 +1,148 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 Daniel Golle <daniel@makrotopia.org>
*
*/
#include <dt-bindings/phy/phy.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/mfd/syscon.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#define ADDR_VAL(val) ((val) & 0xFFFF)
#define DATA_VAL(val) ((val) & 0xFFFF)
#define SYS_CTRL_HCSL_CTRL_REGOFFSET 0x114
enum {
HCSL_BIAS_ON = BIT(0),
HCSL_PCIE_EN = BIT(1),
HCSL_PCIEA_EN = BIT(2),
HCSL_PCIEB_EN = BIT(3),
};
enum {
/* pcie phy reg offset */
PHY_ADDR = 0,
PHY_DATA = 4,
/* phy data reg bits */
READ_EN = BIT(16),
WRITE_EN = BIT(17),
CAP_DATA = BIT(18),
};
struct oxnas_pcie_phy {
struct device *dev;
void __iomem *membase;
const struct phy_ops *ops;
struct regmap *sys_ctrl;
struct reset_control *rstc;
};
static int oxnas_pcie_phy_init(struct phy *phy)
{
struct oxnas_pcie_phy *pciephy = phy_get_drvdata(phy);
int ret;
/* generate clocks from HCSL buffers, shared parts */
regmap_write(pciephy->sys_ctrl, SYS_CTRL_HCSL_CTRL_REGOFFSET, HCSL_BIAS_ON|HCSL_PCIE_EN);
/* Ensure PCIe PHY is properly reset */
ret = reset_control_reset(pciephy->rstc);
if (ret) {
dev_err(pciephy->dev, "phy reset failed %d\n", ret);
return ret;
}
return 0;
}
static int oxnas_pcie_phy_power_on(struct phy *phy)
{
struct oxnas_pcie_phy *pciephy = phy_get_drvdata(phy);
/* Enable PCIe Pre-Emphasis: What these value means? */
writel(ADDR_VAL(0x0014), pciephy->membase + PHY_ADDR);
writel(DATA_VAL(0xce10) | CAP_DATA, pciephy->membase + PHY_DATA);
writel(DATA_VAL(0xce10) | WRITE_EN, pciephy->membase + PHY_DATA);
writel(ADDR_VAL(0x2004), pciephy->membase + PHY_ADDR);
writel(DATA_VAL(0x82c7) | CAP_DATA, pciephy->membase + PHY_DATA);
writel(DATA_VAL(0x82c7) | WRITE_EN, pciephy->membase + PHY_DATA);
return 0;
}
static const struct phy_ops ops = {
.init = oxnas_pcie_phy_init,
.power_on = oxnas_pcie_phy_power_on,
.owner = THIS_MODULE,
};
static int oxnas_pcie_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
struct phy *generic_phy;
struct phy_provider *phy_provider;
struct oxnas_pcie_phy *pciephy;
struct regmap *sys_ctrl;
struct reset_control *rstc;
void __iomem *membase;
membase = of_iomap(np, 0);
if (IS_ERR(membase))
return PTR_ERR(membase);
sys_ctrl = syscon_regmap_lookup_by_compatible("oxsemi,ox820-sys-ctrl");
if (IS_ERR(sys_ctrl))
return PTR_ERR(sys_ctrl);
rstc = devm_reset_control_get_shared(dev, "phy");
if (IS_ERR(rstc))
return PTR_ERR(rstc);
pciephy = devm_kzalloc(dev, sizeof(*pciephy), GFP_KERNEL);
if (!pciephy)
return -ENOMEM;
pciephy->sys_ctrl = sys_ctrl;
pciephy->rstc = rstc;
pciephy->membase = membase;
pciephy->dev = dev;
pciephy->ops = &ops;
generic_phy = devm_phy_create(dev, dev->of_node, pciephy->ops);
if (IS_ERR(generic_phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(generic_phy);
}
phy_set_drvdata(generic_phy, pciephy);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id oxnas_pcie_phy_id_table[] = {
{ .compatible = "oxsemi,ox820-pcie-phy" },
{ },
};
static struct platform_driver oxnas_pcie_phy_driver = {
.probe = oxnas_pcie_phy_probe,
.driver = {
.name = "ox820-pcie-phy",
.of_match_table = oxnas_pcie_phy_id_table,
},
};
builtin_platform_driver(oxnas_pcie_phy_driver);

View File

@ -2,6 +2,7 @@
#include "ox820.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
/ {
@ -31,7 +32,8 @@
i2c-gpio {
compatible = "i2c-gpio";
gpios = <&gpio1 9 0 &gpio1 10 0>;
sda-gpios = <&gpio1 9 (GPIO_ACTIVE_HIGH|GPIO_LINE_OPEN_DRAIN)>;
sck-gpios = <&gpio1 10 (GPIO_ACTIVE_HIGH|GPIO_LINE_OPEN_DRAIN)>;
i2c-gpio,delay-us = <10>;
#address-cells = <1>;
#size-cells = <0>;
@ -49,22 +51,22 @@
power {
label = "power";
gpios = <&gpio0 10 1>;
gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
linux,code = <KEY_POWER>;
};
reset {
label = "reset";
gpios = <&gpio0 11 1>;
gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
eject1 {
label = "eject1";
gpios = <&gpio0 5 1>;
gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
linux,code = <KEY_EJECTCD>;
};
eject2 {
label = "eject2";
gpios = <&gpio0 6 1>;
gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
linux,code = <162>;
};
};
@ -73,33 +75,33 @@
compatible = "gpio-leds";
led_status: status {
label = "kd20:blue:status";
gpios = <&gpio1 16 0>;
gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
};
led_warn: status2 {
label = "kd20:red:status";
gpios = <&gpio1 17 0>;
gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
};
hdd1blue {
label = "kd20:blue:hdd1";
gpios = <&gpio0 27 0>;
gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "ata1";
};
hdd1red {
label = "kd20:red:hdd1";
gpios = <&gpio1 4 0>;
gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
};
hdd2blue {
label = "kd20:blue:hdd2";
gpios = <&gpio1 6 0>;
gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "ata2";
};
hdd2red {
label = "kd20:red:hdd2";
gpios = <&gpio1 7 0>;
gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
};
usb {
label = "kd20:blue:usb";
gpios = <&gpio1 8 0>;
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ehci_port1>, <&ehci_port2>;
linux,default-trigger = "usbport";
};
@ -107,19 +109,19 @@
beeper: beeper {
compatible = "gpio-beeper";
gpios = <&gpio1 11 0>;
gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
};
gpio-fan {
compatible = "gpio-fan";
gpios = <&gpio0 2 1>;
gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
gpio-fan,speed-map = <0 0
3000 1>;
};
gpio-poweroff {
compatible = "gpio-poweroff";
gpios = <&gpio0 9 0>;
gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
};
};

View File

@ -88,6 +88,7 @@ CONFIG_PCI_MSI_IRQ_DOMAIN=y
# CONFIG_MTD_CFI is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_OXNAS=y

View File

@ -1,5 +1,5 @@
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -220,4 +220,9 @@ config VMD
To compile this driver as a module, choose M here: the
module will be called vmd.
@ -10,8 +10,8 @@
+ select PCIEPORTBUS
+
endmenu
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_PCIE_ALTERA) += pcie-altera
obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o

View File

@ -0,0 +1,11 @@
--- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
@@ -14,7 +14,7 @@
compatible = "cloudengines,pogoplugv3", "oxsemi,ox820";
chosen {
- bootargs = "earlyprintk";
+ bootargs = "earlyprintk console=ttyS0,115200";
stdout-path = "serial0:115200n8";
};

View File

@ -0,0 +1,32 @@
--- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
@@ -73,11 +73,27 @@
nand-ecc-algo = "hamming";
partition@0 {
- label = "boot";
- reg = <0x00000000 0x00e00000>;
+ label = "stage1";
+ reg = <0x00000000 0x00040000>;
read-only;
};
+ partition@40000 {
+ label = "u-boot";
+ reg = <0x00040000 0x00380000>;
+ read-only;
+ };
+
+ partition@3c0000 {
+ label = "u-boot-env";
+ reg = <0x003c0000 0x00080000>;
+ };
+
+ partition@440000 {
+ label = "kernel";
+ reg = <0x00440000 0x009c0000>;
+ };
+
partition@e00000 {
label = "ubi";
reg = <0x00e00000 0x07200000>;

View File

@ -0,0 +1,34 @@
--- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
@@ -27,24 +27,28 @@
serial0 = &uart0;
gpio0 = &gpio0;
gpio1 = &gpio1;
+ led-boot = &led_status;
+ led-failsafe = &led_warn;
+ led-running = &led_act;
+ led-upgrade = &led_warn;
};
leds {
compatible = "gpio-leds";
- blue {
+ led_status: blue {
label = "pogoplug:blue";
gpios = <&gpio0 2 0>;
default-state = "keep";
};
- orange {
+ led_warn: orange {
label = "pogoplug:orange";
gpios = <&gpio1 16 1>;
default-state = "keep";
};
- green {
+ led_act: green {
label = "pogoplug:green";
gpios = <&gpio1 17 1>;
default-state = "keep";

View File

@ -0,0 +1,11 @@
--- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
@@ -11,7 +11,7 @@
/ {
model = "Cloud Engines PogoPlug Series 3";
- compatible = "cloudengines,pogoplugv3", "oxsemi,ox820";
+ compatible = "cloudengines,pogoplug-series-3", "cloudengines,pogoplugv3", "oxsemi,ox820";
chosen {
bootargs = "earlyprintk console=ttyS0,115200";

View File

@ -0,0 +1,63 @@
From 552ed4955c1fee1109bf5ba137dc35a411a1448c Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Fri, 1 Jun 2018 02:41:15 +0200
Subject: [PATCH] arm: ox820: remove left-overs
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/clk/clk-oxnas.c | 2 --
include/dt-bindings/clock/oxsemi,ox820.h | 32 +++++++++++-------------
2 files changed, 14 insertions(+), 20 deletions(-)
--- a/drivers/clk/clk-oxnas.c
+++ b/drivers/clk/clk-oxnas.c
@@ -29,8 +29,6 @@ struct oxnas_stdclk_data {
struct clk_hw_onecell_data *onecell_data;
struct clk_oxnas_gate **gates;
unsigned int ngates;
- struct clk_oxnas_pll **plls;
- unsigned int nplls;
};
/* Regmap offsets */
--- a/include/dt-bindings/clock/oxsemi,ox820.h
+++ b/include/dt-bindings/clock/oxsemi,ox820.h
@@ -6,24 +6,20 @@
#ifndef DT_CLOCK_OXSEMI_OX820_H
#define DT_CLOCK_OXSEMI_OX820_H
-/* PLLs */
-#define CLK_820_PLLA 0
-#define CLK_820_PLLB 1
-
/* Gate Clocks */
-#define CLK_820_LEON 2
-#define CLK_820_DMA_SGDMA 3
-#define CLK_820_CIPHER 4
-#define CLK_820_SD 5
-#define CLK_820_SATA 6
-#define CLK_820_AUDIO 7
-#define CLK_820_USBMPH 8
-#define CLK_820_ETHA 9
-#define CLK_820_PCIEA 10
-#define CLK_820_NAND 11
-#define CLK_820_PCIEB 12
-#define CLK_820_ETHB 13
-#define CLK_820_REF600 14
-#define CLK_820_USBDEV 15
+#define CLK_820_LEON 0
+#define CLK_820_DMA_SGDMA 1
+#define CLK_820_CIPHER 2
+#define CLK_820_SD 3
+#define CLK_820_SATA 4
+#define CLK_820_AUDIO 5
+#define CLK_820_USBMPH 6
+#define CLK_820_ETHA 7
+#define CLK_820_PCIEA 8
+#define CLK_820_NAND 9
+#define CLK_820_PCIEB 10
+#define CLK_820_ETHB 11
+#define CLK_820_REF600 12
+#define CLK_820_USBDEV 13
#endif /* DT_CLOCK_OXSEMI_OX820_H */

View File

@ -0,0 +1,273 @@
--- a/drivers/clk/clk-oxnas.c
+++ b/drivers/clk/clk-oxnas.c
@@ -5,19 +5,42 @@
* Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
*/
+#include <linux/clk.h>
+#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/stringify.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
+#include <linux/reset.h>
#include <dt-bindings/clock/oxsemi,ox810se.h>
#include <dt-bindings/clock/oxsemi,ox820.h>
+#define REF300_DIV_INT_SHIFT 8
+#define REF300_DIV_FRAC_SHIFT 0
+#define REF300_DIV_INT(val) ((val) << REF300_DIV_INT_SHIFT)
+#define REF300_DIV_FRAC(val) ((val) << REF300_DIV_FRAC_SHIFT)
+
+#define PLLB_BYPASS 1
+#define PLLB_ENSAT 3
+#define PLLB_OUTDIV 4
+#define PLLB_REFDIV 8
+#define PLLB_DIV_INT_SHIFT 8
+#define PLLB_DIV_FRAC_SHIFT 0
+#define PLLB_DIV_INT(val) ((val) << PLLB_DIV_INT_SHIFT)
+#define PLLB_DIV_FRAC(val) ((val) << PLLB_DIV_FRAC_SHIFT)
+
+#define PLLA_REFDIV_MASK 0x3F
+#define PLLA_REFDIV_SHIFT 8
+#define PLLA_OUTDIV_MASK 0x7
+#define PLLA_OUTDIV_SHIFT 4
+
/* Standard regmap gate clocks */
struct clk_oxnas_gate {
struct clk_hw hw;
@@ -36,6 +59,135 @@ struct oxnas_stdclk_data {
#define CLK_SET_REGOFFSET 0x2c
#define CLK_CLR_REGOFFSET 0x30
+#define PLLA_CTRL0_REGOFFSET 0x1f0
+#define PLLA_CTRL1_REGOFFSET 0x1f4
+#define PLLB_CTRL0_REGOFFSET 0x1001f0
+#define MHZ (1000 * 1000)
+
+struct clk_oxnas_pll {
+ struct clk_hw hw;
+ struct device_node *devnode;
+ struct reset_control *rstc;
+ struct regmap *syscon;
+};
+
+#define to_clk_oxnas_pll(_hw) container_of(_hw, struct clk_oxnas_pll, hw)
+
+static unsigned long plla_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_oxnas_pll *plla = to_clk_oxnas_pll(hw);
+ unsigned long fin = parent_rate;
+ unsigned long refdiv, outdiv;
+ unsigned int pll0, fbdiv;
+
+ BUG_ON(regmap_read(plla->syscon, PLLA_CTRL0_REGOFFSET, &pll0));
+
+ refdiv = (pll0 >> PLLA_REFDIV_SHIFT) & PLLA_REFDIV_MASK;
+ refdiv += 1;
+ outdiv = (pll0 >> PLLA_OUTDIV_SHIFT) & PLLA_OUTDIV_MASK;
+ outdiv += 1;
+
+ BUG_ON(regmap_read(plla->syscon, PLLA_CTRL1_REGOFFSET, &fbdiv));
+ /* seems we will not be here when pll is bypassed, so ignore this
+ * case */
+
+ return fin / MHZ * fbdiv / (refdiv * outdiv) / 32768 * MHZ;
+}
+
+static const char *pll_clk_parents[] = {
+ "oscillator",
+};
+
+static struct clk_ops plla_ops = {
+ .recalc_rate = plla_clk_recalc_rate,
+};
+
+static struct clk_init_data clk_plla_init = {
+ .name = "plla",
+ .ops = &plla_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static int pllb_clk_is_prepared(struct clk_hw *hw)
+{
+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
+
+ return !!pllb->rstc;
+}
+
+static int pllb_clk_prepare(struct clk_hw *hw)
+{
+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
+
+ pllb->rstc = of_reset_control_get(pllb->devnode, NULL);
+
+ return IS_ERR(pllb->rstc) ? PTR_ERR(pllb->rstc) : 0;
+}
+
+static void pllb_clk_unprepare(struct clk_hw *hw)
+{
+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
+
+ BUG_ON(IS_ERR(pllb->rstc));
+
+ reset_control_put(pllb->rstc);
+ pllb->rstc = NULL;
+}
+
+static int pllb_clk_enable(struct clk_hw *hw)
+{
+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
+
+ BUG_ON(IS_ERR(pllb->rstc));
+
+ /* put PLL into bypass */
+ regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), BIT(PLLB_BYPASS));
+ wmb();
+ udelay(10);
+ reset_control_assert(pllb->rstc);
+ udelay(10);
+ /* set PLL B control information */
+ regmap_write_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, 0xffff,
+ (1 << PLLB_ENSAT) | (1 << PLLB_OUTDIV) | (2 << PLLB_REFDIV));
+ reset_control_deassert(pllb->rstc);
+ udelay(100);
+ regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), 0);
+
+ return 0;
+}
+
+static void pllb_clk_disable(struct clk_hw *hw)
+{
+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
+
+ BUG_ON(IS_ERR(pllb->rstc));
+
+ /* put PLL into bypass */
+ regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), BIT(PLLB_BYPASS));
+
+ wmb();
+ udelay(10);
+
+ reset_control_assert(pllb->rstc);
+}
+
+static struct clk_ops pllb_ops = {
+ .prepare = pllb_clk_prepare,
+ .unprepare = pllb_clk_unprepare,
+ .is_prepared = pllb_clk_is_prepared,
+ .enable = pllb_clk_enable,
+ .disable = pllb_clk_disable,
+};
+
+static struct clk_init_data clk_pllb_init = {
+ .name = "pllb",
+ .ops = &pllb_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
static inline struct clk_oxnas_gate *to_clk_oxnas_gate(struct clk_hw *hw)
{
return container_of(hw, struct clk_oxnas_gate, hw);
@@ -249,3 +401,42 @@ static struct platform_driver oxnas_stdc
},
};
builtin_platform_driver(oxnas_stdclk_driver);
+
+void __init oxnas_init_plla(struct device_node *np)
+{
+ struct clk *clk;
+ struct clk_oxnas_pll *plla;
+
+ plla = kmalloc(sizeof(*plla), GFP_KERNEL);
+ BUG_ON(!plla);
+
+ plla->syscon = syscon_node_to_regmap(of_get_parent(np));
+ plla->hw.init = &clk_plla_init;
+ plla->devnode = np;
+ plla->rstc = NULL;
+ clk = clk_register(NULL, &plla->hw);
+ BUG_ON(IS_ERR(clk));
+ /* mark it as enabled */
+ clk_prepare_enable(clk);
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(oxnas_plla, "plxtech,nas782x-plla", oxnas_init_plla);
+
+void __init oxnas_init_pllb(struct device_node *np)
+{
+ struct clk *clk;
+ struct clk_oxnas_pll *pllb;
+
+ pllb = kmalloc(sizeof(*pllb), GFP_KERNEL);
+ BUG_ON(!pllb);
+
+ pllb->syscon = syscon_node_to_regmap(of_get_parent(np));
+ pllb->hw.init = &clk_pllb_init;
+ pllb->devnode = np;
+ pllb->rstc = NULL;
+
+ clk = clk_register(NULL, &pllb->hw);
+ BUG_ON(IS_ERR(clk));
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(oxnas_pllb, "plxtech,nas782x-pllb", oxnas_init_pllb);
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -61,12 +61,6 @@
clocks = <&osc>;
};
- plla: plla {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <850000000>;
- };
-
armclk: armclk {
compatible = "fixed-factor-clock";
#clock-cells = <0>;
@@ -266,6 +260,19 @@
compatible = "oxsemi,ox820-stdclk", "oxsemi,ox810se-stdclk";
#clock-cells = <1>;
};
+
+ plla: plla {
+ compatible = "plxtech,nas782x-plla";
+ #clock-cells = <0>;
+ clocks = <&osc>;
+ };
+
+ pllb: pllb {
+ compatible = "plxtech,nas782x-pllb";
+ #clock-cells = <0>;
+ clocks = <&osc>;
+ resets = <&reset RESET_PLLB>;
+ };
};
};
@@ -287,6 +294,13 @@
clocks = <&armclk>;
};
+ watchdog@620 {
+ compatible = "mpcore_wdt";
+ reg = <0x620 0x20>;
+ interrupts = <GIC_PPI 14 (GIC_CPU_MASK_RAW(3)|IRQ_TYPE_LEVEL_HIGH)>;
+ clocks = <&armclk>;
+ };
+
gic: gic@1000 {
compatible = "arm,arm11mp-gic";
interrupt-controller;

View File

@ -0,0 +1,25 @@
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -123,6 +123,12 @@ config POWER_RESET_OCELOT_RESET
help
This driver supports restart for Microsemi Ocelot SoC.
+config POWER_RESET_OXNAS
+ bool "OXNAS SoC restart driver"
+ depends on ARCH_OXNAS
+ help
+ Restart support for OXNAS boards.
+
config POWER_RESET_PIIX4_POWEROFF
tristate "Intel PIIX4 power-off driver"
depends on PCI
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_POWER_RESET_GPIO) += gpio-p
obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
+obj-$(CONFIG_POWER_RESET_OXNAS) += oxnas-restart.o
obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o
obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o

View File

@ -0,0 +1,44 @@
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -247,6 +247,15 @@
};
};
+ pcie_phy: pcie-phy@a00000 {
+ compatible = "oxsemi,ox820-pcie-phy";
+ reg = <0xa00000 0x10>;
+ #phy-cells = <0>;
+ resets = <&reset RESET_PCIEPHY>;
+ reset-names = "phy";
+ status = "disabled";
+ };
+
sys: sys-ctrl@e00000 {
compatible = "oxsemi,ox820-sys-ctrl", "syscon", "simple-mfd";
reg = <0xe00000 0x200000>;
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -35,6 +35,13 @@ config PHY_LPC18XX_USB_OTG
This driver is need for USB0 support on LPC18xx/43xx and takes
care of enabling and clock setup.
+config PHY_OXNAS
+ tristate "Oxford Semi. OX820 PCI-E PHY support"
+ depends on HAS_IOMEM && OF && (ARM || COMPILE_TEST)
+ select GENERIC_PHY
+ help
+ This option enables support for OXNAS OX820 SoC PCIE PHY.
+
config PHY_PISTACHIO_USB
tristate "IMG Pistachio USB2.0 PHY driver"
depends on MACH_PISTACHIO
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
+obj-$(CONFIG_PHY_OXNAS) += phy-oxnas-pcie.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_ARCH_SUNXI) += allwinner/

View File

@ -0,0 +1,122 @@
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -48,6 +48,11 @@ config PCIE_CADENCE_EP
endpoint mode. This PCIe controller may be embedded into many
different vendors SoCs.
+config PCIE_OXNAS
+ bool "PLX Oxnas PCIe controller"
+ depends on ARCH_OXNAS
+ select PCIEPORTBUS
+
endmenu
config PCIE_XILINX_NWL
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-r
obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o
obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
+obj-$(CONFIG_PCIE_OXNAS) += pcie-oxnas.o
obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
obj-$(CONFIG_VMD) += vmd.o
# pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -289,7 +289,7 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
- ranges = <0 0x47000000 0x1000000>;
+ ranges = <0 0x47000000 0x2000>;
scu: scu@0 {
compatible = "arm,arm11mp-scu";
@@ -318,5 +318,86 @@
<0x100 0x500>;
};
};
+
+ pcie0: pcie-controller@47c00000 {
+ compatible = "plxtech,nas782x-pcie";
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ /* flag & space bus address host address size */
+ ranges = < 0x82000000 0 0x48000000 0x48000000 0 0x2000000
+ 0xC2000000 0 0x4A000000 0x4A000000 0 0x1E00000
+ 0x81000000 0 0x4BE00000 0x4BE00000 0 0x0100000
+ 0x80000000 0 0x4BF00000 0x4BF00000 0 0x0100000>;
+
+ bus-range = <0x00 0x7f>;
+
+ /* cfg inbound translator */
+ reg = <0x47c00000 0x1000>, <0x47d00000 0x100>;
+
+ phys = <&pcie_phy>;
+ phy-names = "pcie-phy";
+
+ #interrupt-cells = <1>;
+ /* wild card mask, match all bus address & interrupt specifier */
+ /* format: bus address mask, interrupt specifier mask */
+ /* each bit 1 means need match, 0 means ignored when match */
+ interrupt-map-mask = <0 0 0 0>;
+ /* format: a list of: bus address, interrupt specifier,
+ * parent interrupt controller & specifier */
+ interrupt-map = <0 0 0 0 &gic 0 19 0x304>;
+ gpios = <&gpio1 12 0>;
+ clocks = <&stdclk CLK_820_PCIEA>, <&pllb>;
+ clock-names = "pcie", "busclk";
+ resets = <&reset RESET_PCIEA>;
+ reset-names = "pcie";
+
+ plxtech,pcie-hcsl-bit = <2>;
+ plxtech,pcie-ctrl-offset = <0x120>;
+ plxtech,pcie-outbound-offset = <0x138>;
+ status = "disabled";
+ };
+
+ pcie1: pcie-controller@47e00000 {
+ compatible = "plxtech,nas782x-pcie";
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ /* flag & space bus address host address size */
+ ranges = < 0x82000000 0 0x4C000000 0x4C000000 0 0x2000000
+ 0xC2000000 0 0x4E000000 0x4E000000 0 0x1E00000
+ 0x81000000 0 0x4FE00000 0x4FE00000 0 0x0100000
+ 0x80000000 0 0x4FF00000 0x4FF00000 0 0x0100000>;
+
+ bus-range = <0x80 0xff>;
+
+ /* cfg inbound translator */
+ reg = <0x47e00000 0x1000>, <0x47f00000 0x100>;
+
+ phys = <&pcie_phy>;
+ phy-names = "pcie-phy";
+
+ #interrupt-cells = <1>;
+ /* wild card mask, match all bus address & interrupt specifier */
+ /* format: bus address mask, interrupt specifier mask */
+ /* each bit 1 means need match, 0 means ignored when match */
+ interrupt-map-mask = <0 0 0 0>;
+ /* format: a list of: bus address, interrupt specifier,
+ * parent interrupt controller & specifier */
+ interrupt-map = <0 0 0 0 &gic 0 20 0x304>;
+
+ /* gpios = <&gpio1 12 0>; */
+ clocks = <&stdclk CLK_820_PCIEB>, <&pllb>;
+ clock-names = "pcie", "busclk";
+ resets = <&reset RESET_PCIEB>;
+ reset-names = "pcie";
+
+ plxtech,pcie-hcsl-bit = <3>;
+ plxtech,pcie-ctrl-offset = <0x124>;
+ plxtech,pcie-outbound-offset = <0x174>;
+ status = "disabled";
+ };
};
};

View File

@ -0,0 +1,49 @@
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -508,6 +508,13 @@ config SATA_VITESSE
If unsure, say N.
+config SATA_OXNAS
+ tristate "PLXTECH NAS782X SATA support"
+ help
+ This option enables support for Nas782x Serial ATA controller.
+
+ If unsure, say N.
+
comment "PATA SFF controllers with BMDMA"
config PATA_ALI
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_SATA_SVW) += sata_svw.o
obj-$(CONFIG_SATA_ULI) += sata_uli.o
obj-$(CONFIG_SATA_VIA) += sata_via.o
obj-$(CONFIG_SATA_VITESSE) += sata_vsc.o
+obj-$(CONFIG_SATA_OXNAS) += sata_oxnas.o
# SFF PATA w/ BMDMA
obj-$(CONFIG_PATA_ALI) += pata_ali.o
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -399,5 +399,20 @@
plxtech,pcie-outbound-offset = <0x174>;
status = "disabled";
};
+
+ sata: sata@45900000 {
+ compatible = "plxtech,nas782x-sata";
+ /* ports dmactl sgdma */
+ reg = <0x45900000 0x20000>, <0x459A0000 0x40>, <0x459B0000 0x20>,
+ /* core phy descriptors (optional) */
+ <0x459E0000 0x2000>, <0x44900000 0x0C>, <0x50000000 0x1000>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&stdclk CLK_820_SATA>;
+ resets = <&reset RESET_SATA>, <&reset RESET_SATA_LINK>, <&reset RESET_SATA_PHY>;
+ reset-names = "sata", "link", "phy";
+ nr-ports = <1>;
+ status = "disabled";
+ };
+
};
};

View File

@ -0,0 +1,10 @@
--- a/arch/arm/mach-oxnas/Kconfig
+++ b/arch/arm/mach-oxnas/Kconfig
@@ -2,6 +2,7 @@
menuconfig ARCH_OXNAS
bool "Oxford Semiconductor OXNAS Family SoCs"
select ARCH_HAS_RESET_CONTROLLER
+ select ARCH_WANT_LIBATA_LEDS
select COMMON_CLK_OXNAS
select GPIOLIB
select MFD_SYSCON

View File

@ -0,0 +1,73 @@
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -321,6 +321,13 @@ config USB_OCTEON_EHCI
USB 2.0 device support. All CN6XXX based chips with USB are
supported.
+config USB_EHCI_OXNAS
+ tristate "OXNAS EHCI Module"
+ depends on USB_EHCI_HCD && ARCH_OXNAS
+ select USB_EHCI_ROOT_HUB_TT
+ ---help---
+ Enable support for the OX820 SOC's on-chip EHCI controller.
+
endif # USB_EHCI_HCD
config USB_OXU210HP_HCD
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_USB_EHCI_HCD_STI) += ehci-s
obj-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o
obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o
+obj-$(CONFIG_USB_EHCI_OXNAS) += ehci-oxnas.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -106,6 +106,31 @@
status = "disabled";
};
+ ehci: ehci@40200100 {
+ compatible = "plxtech,nas782x-ehci";
+ reg = <0x40200100 0xf00>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&stdclk CLK_820_USBMPH>, <&pllb>, <&stdclk CLK_820_REF600>;
+ clock-names = "usb", "refsrc", "phyref";
+ resets = <&reset RESET_USBHS>, <&reset RESET_USBPHYA>, <&reset RESET_USBPHYB>;
+ reset-names = "host", "phya", "phyb";
+ oxsemi,sys-ctrl = <&sys>;
+ /* Otherwise ref300 is used, which is derived from sata phy
+ * in that case, usb depends on sata initialization */
+ /* FIXME: how to make this dependency explicit ? */
+ oxsemi,ehci_use_pllb;
+ status = "disabled";
+
+ ehci_port1: port@1 {
+ reg = <1>;
+ #trigger-source-cells = <0>;
+ };
+ ehci_port2: port@2 {
+ reg = <2>;
+ #trigger-source-cells = <0>;
+ };
+ };
+
apb-bridge@44000000 {
#address-cells = <1>;
#size-cells = <1>;
--- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
@@ -105,6 +105,10 @@
};
};
+&ehci {
+ status = "okay";
+};
+
&etha {
status = "okay";

View File

@ -0,0 +1,189 @@
From 71270226b14733a4b1f2cde58ea9265caa50b38d Mon Sep 17 00:00:00 2001
From: Adrian Panella <ianchi74@outlook.com>
Date: Thu, 9 Mar 2017 09:37:17 +0100
Subject: [PATCH 67/69] generic: Mangle bootloader's kernel arguments
The command-line arguments provided by the boot loader will be
appended to a new device tree property: bootloader-args.
If there is a property "append-rootblock" in DT under /chosen
and a root= option in bootloaders command line it will be parsed
and added to DT bootargs with the form: <append-rootblock>XX.
Only command line ATAG will be processed, the rest of the ATAGs
sent by bootloader will be ignored.
This is usefull in dual boot systems, to get the current root partition
without afecting the rest of the system.
Signed-off-by: Adrian Panella <ianchi74@outlook.com>
---
arch/arm/Kconfig | 11 +++++
arch/arm/boot/compressed/atags_to_fdt.c | 72 ++++++++++++++++++++++++++++++++-
init/main.c | 16 ++++++++
3 files changed, 98 insertions(+), 1 deletion(-)
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1825,6 +1825,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN
The command-line arguments provided by the boot loader will be
appended to the the device tree bootargs property.
+config ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
+ bool "Append rootblock parsing bootloader's kernel arguments"
+ help
+ The command-line arguments provided by the boot loader will be
+ appended to a new device tree property: bootloader-args.
+ If there is a property "append-rootblock" in DT under /chosen
+ and a root= option in bootloaders command line it will be parsed
+ and added to DT bootargs with the form: <append-rootblock>XX.
+ Only command line ATAG will be processed, the rest of the ATAGs
+ sent by bootloader will be ignored.
+
endchoice
config CMDLINE
--- a/arch/arm/boot/compressed/atags_to_fdt.c
+++ b/arch/arm/boot/compressed/atags_to_fdt.c
@@ -4,6 +4,8 @@
#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND)
#define do_extend_cmdline 1
+#elif defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+#define do_extend_cmdline 1
#else
#define do_extend_cmdline 0
#endif
@@ -67,6 +69,59 @@ static uint32_t get_cell_size(const void
return cell_size;
}
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+
+static char *append_rootblock(char *dest, const char *str, int len, void *fdt)
+{
+ char *ptr, *end;
+ char *root="root=";
+ int i, l;
+ const char *rootblock;
+
+ //ARM doesn't have __HAVE_ARCH_STRSTR, so search manually
+ ptr = str - 1;
+
+ do {
+ //first find an 'r' at the begining or after a space
+ do {
+ ptr++;
+ ptr = strchr(ptr, 'r');
+ if(!ptr) return dest;
+
+ } while (ptr != str && *(ptr-1) != ' ');
+
+ //then check for the rest
+ for(i = 1; i <= 4; i++)
+ if(*(ptr+i) != *(root+i)) break;
+
+ } while (i != 5);
+
+ end = strchr(ptr, ' ');
+ end = end ? (end - 1) : (strchr(ptr, 0) - 1);
+
+ //find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX )
+ for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++);
+ ptr = end + 1;
+
+ /* if append-rootblock property is set use it to append to command line */
+ rootblock = getprop(fdt, "/chosen", "append-rootblock", &l);
+ if(rootblock != NULL) {
+ if(*dest != ' ') {
+ *dest = ' ';
+ dest++;
+ len++;
+ }
+ if (len + l + i <= COMMAND_LINE_SIZE) {
+ memcpy(dest, rootblock, l);
+ dest += l - 1;
+ memcpy(dest, ptr, i);
+ dest += i;
+ }
+ }
+ return dest;
+}
+#endif
+
static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
{
char cmdline[COMMAND_LINE_SIZE];
@@ -86,12 +141,21 @@ static void merge_fdt_bootargs(void *fdt
/* and append the ATAG_CMDLINE */
if (fdt_cmdline) {
+
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+ //save original bootloader args
+ //and append ubi.mtd with root partition number to current cmdline
+ setprop_string(fdt, "/chosen", "bootloader-args", fdt_cmdline);
+ ptr = append_rootblock(ptr, fdt_cmdline, len, fdt);
+
+#else
len = strlen(fdt_cmdline);
if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) {
*ptr++ = ' ';
memcpy(ptr, fdt_cmdline, len);
ptr += len;
}
+#endif
}
*ptr = '\0';
@@ -166,7 +230,9 @@ int atags_to_fdt(void *atag_list, void *
else
setprop_string(fdt, "/chosen", "bootargs",
atag->u.cmdline.cmdline);
- } else if (atag->hdr.tag == ATAG_MEM) {
+ }
+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
+ else if (atag->hdr.tag == ATAG_MEM) {
if (memcount >= sizeof(mem_reg_property)/4)
continue;
if (!atag->u.mem.size)
@@ -210,6 +276,10 @@ int atags_to_fdt(void *atag_list, void *
setprop(fdt, "/memory", "reg", mem_reg_property,
4 * memcount * memsize);
}
+#else
+
+ }
+#endif
return fdt_pack(fdt);
}
--- a/init/main.c
+++ b/init/main.c
@@ -103,6 +103,10 @@
#define CREATE_TRACE_POINTS
#include <trace/events/initcall.h>
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+#include <linux/of.h>
+#endif
+
static int kernel_init(void *);
extern void init_IRQ(void);
@@ -630,6 +634,18 @@ asmlinkage __visible void __init start_k
page_alloc_init();
pr_notice("Kernel command line: %s\n", boot_command_line);
+
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+ //Show bootloader's original command line for reference
+ if(of_chosen) {
+ const char *prop = of_get_property(of_chosen, "bootloader-args", NULL);
+ if(prop)
+ pr_notice("Bootloader command line (ignored): %s\n", prop);
+ else
+ pr_notice("Bootloader command line not present\n");
+ }
+#endif
+
/* parameters may set static keys */
jump_label_init();
parse_early_param();

View File

@ -0,0 +1,57 @@
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1584,6 +1584,14 @@ unsigned ata_exec_internal_sg(struct ata
return AC_ERR_SYSTEM;
}
+ if (ap->ops->acquire_hw && !ap->ops->acquire_hw(ap, 0, 0)) {
+ spin_unlock_irqrestore(ap->lock, flags);
+ if (!ap->ops->acquire_hw(ap, 1, (2*HZ))) {
+ return AC_ERR_TIMEOUT;
+ }
+ spin_lock_irqsave(ap->lock, flags);
+ }
+
/* initialize internal qc */
qc = __ata_qc_from_tag(ap, ATA_TAG_INTERNAL);
@@ -5123,6 +5131,9 @@ struct ata_queued_cmd *ata_qc_new_init(s
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
return NULL;
+ if (ap->ops->qc_new && ap->ops->qc_new(ap))
+ return NULL;
+
/* libsas case */
if (ap->flags & ATA_FLAG_SAS_HOST) {
tag = ata_sas_allocate_tag(ap);
@@ -5168,6 +5179,8 @@ void ata_qc_free(struct ata_queued_cmd *
qc->tag = ATA_TAG_POISON;
if (ap->flags & ATA_FLAG_SAS_HOST)
ata_sas_free_tag(tag, ap);
+ if (ap->ops->qc_free)
+ ap->ops->qc_free(qc);
}
}
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -905,6 +905,8 @@ struct ata_port_operations {
void (*qc_prep)(struct ata_queued_cmd *qc);
unsigned int (*qc_issue)(struct ata_queued_cmd *qc);
bool (*qc_fill_rtf)(struct ata_queued_cmd *qc);
+ int (*qc_new)(struct ata_port *ap);
+ void (*qc_free)(struct ata_queued_cmd *qc);
/*
* Configuration and exception handling
@@ -995,6 +997,9 @@ struct ata_port_operations {
void (*phy_reset)(struct ata_port *ap);
void (*eng_timeout)(struct ata_port *ap);
+ int (*acquire_hw)(struct ata_port *ap, int may_sleep,
+ int timeout_jiffies);
+
/*
* ->inherits must be the last field and all the preceding
* fields must be pointers.