mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
kernel: bump to 4.14.141, 4.19.69
This commit is contained in:
parent
f051b8d247
commit
6219af90ab
@ -7,12 +7,12 @@ ifdef CONFIG_TESTING_KERNEL
|
||||
endif
|
||||
|
||||
LINUX_VERSION-4.9 = .190
|
||||
LINUX_VERSION-4.14 = .140
|
||||
LINUX_VERSION-4.19 = .68
|
||||
LINUX_VERSION-4.14 = .141
|
||||
LINUX_VERSION-4.19 = .69
|
||||
|
||||
LINUX_KERNEL_HASH-4.9.190 = fe8a1ca080a462de6832762ba8b71410b828f0e52c1e11d3c46d83e9ac1e0a16
|
||||
LINUX_KERNEL_HASH-4.14.140 = 795eed2515715ef29edd24f7a70912040cc206ec9a049c370cb305515f3fbdf2
|
||||
LINUX_KERNEL_HASH-4.19.68 = 91875940518c0a8cecfa02ffcf371e4d8266b80971a95103e89a86b8a326a02b
|
||||
LINUX_KERNEL_HASH-4.14.141 = 0bb9f0812326ec4554de1bea02628840e03b6664b5abfd9d8510049e43203a17
|
||||
LINUX_KERNEL_HASH-4.19.69 = c091760b520a4e4a4c7034a8329cc2689a0ea3f81a377b694ed196d623e2d987
|
||||
|
||||
remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1))))
|
||||
sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1)))))))
|
||||
|
@ -24,7 +24,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
|
||||
--- a/drivers/net/can/spi/mcp251x.c
|
||||
+++ b/drivers/net/can/spi/mcp251x.c
|
||||
@@ -950,6 +950,9 @@ static int mcp251x_open(struct net_devic
|
||||
@@ -939,6 +939,9 @@ static int mcp251x_open(struct net_devic
|
||||
priv->tx_skb = NULL;
|
||||
priv->tx_len = 0;
|
||||
|
||||
|
@ -26,7 +26,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
/* Device and char device-related information */
|
||||
static DEFINE_IDA(gpio_ida);
|
||||
static dev_t gpio_devt;
|
||||
@@ -2626,7 +2628,7 @@ int gpiod_direction_output(struct gpio_d
|
||||
@@ -2628,7 +2630,7 @@ int gpiod_direction_output(struct gpio_d
|
||||
value = !!value;
|
||||
|
||||
/* GPIOs used for IRQs shall not be set as output */
|
||||
@ -35,7 +35,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
||||
gpiod_err(desc,
|
||||
"%s: tried to set a GPIO tied to an IRQ as output\n",
|
||||
__func__);
|
||||
@@ -3314,7 +3316,7 @@ int gpiochip_lock_as_irq(struct gpio_chi
|
||||
@@ -3316,7 +3318,7 @@ int gpiochip_lock_as_irq(struct gpio_chi
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
|
||||
#define USB_VENDOR_ID_BELKIN 0x050d
|
||||
#define USB_DEVICE_ID_FLIP_KVM 0x3201
|
||||
|
||||
@@ -1187,6 +1190,9 @@
|
||||
@@ -1188,6 +1191,9 @@
|
||||
#define USB_VENDOR_ID_XAT 0x2505
|
||||
#define USB_DEVICE_ID_XAT_CSR 0x0220
|
||||
|
||||
@ -53,7 +53,7 @@ Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE2), HID_QUIRK_ALWAYS_POLL },
|
||||
@@ -172,6 +173,7 @@ static const struct hid_device_id hid_qu
|
||||
@@ -173,6 +174,7 @@ static const struct hid_device_id hid_qu
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
|
@ -89,7 +89,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
|
||||
--- a/drivers/gpio/gpiolib.c
|
||||
+++ b/drivers/gpio/gpiolib.c
|
||||
@@ -1940,7 +1940,8 @@ int gpiochip_add_pingroup_range(struct g
|
||||
@@ -1942,7 +1942,8 @@ int gpiochip_add_pingroup_range(struct g
|
||||
|
||||
list_add_tail(&pin_range->node, &gdev->pin_ranges);
|
||||
|
||||
@ -99,7 +99,7 @@ Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
|
||||
|
||||
@@ -1992,7 +1993,7 @@ int gpiochip_add_pin_range(struct gpio_c
|
||||
@@ -1994,7 +1995,7 @@ int gpiochip_add_pin_range(struct gpio_c
|
||||
|
||||
list_add_tail(&pin_range->node, &gdev->pin_ranges);
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2015 OpenWrt.org
|
||||
|
||||
. /lib/upgrade/common.sh
|
||||
|
||||
RECOVERY_PART=/dev/mmcblk0p1
|
||||
|
||||
move_config() {
|
||||
@ -11,7 +13,7 @@ move_config() {
|
||||
insmod vfat
|
||||
mkdir -p /recovery
|
||||
mount -o rw,noatime $RECOVERY_PART /recovery
|
||||
[ -f /recovery/sysupgrade.tgz ] && mv -f /recovery/sysupgrade.tgz /
|
||||
[ -f "/recovery/$BACKUP_FILE" ] && mv -f "/recovery/$BACKUP_FILE" /
|
||||
umount /recovery
|
||||
fi
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ platform_check_image() {
|
||||
platform_copy_config_emmc() {
|
||||
mkdir -p /recovery
|
||||
mount -o rw,noatime /dev/mmcblk0p1 /recovery
|
||||
cp -af "$CONF_TAR" /recovery/
|
||||
cp -af "$UPGRADE_BACKUP" "/recovery/$BACKUP_FILE"
|
||||
sync
|
||||
umount /recovery
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Ryder Lee <ryder.lee@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
@ -16,13 +15,8 @@
|
||||
model = "Bananapi BPI-R64";
|
||||
compatible = "bananapi,bpi-r64", "mediatek,mt7622";
|
||||
|
||||
aliases {
|
||||
serial0 = &uart0;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512";
|
||||
bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512";
|
||||
};
|
||||
|
||||
cpus {
|
||||
@ -49,10 +43,17 @@
|
||||
wps {
|
||||
label = "wps";
|
||||
linux,code = <KEY_WPS_BUTTON>;
|
||||
gpios = <&pio 102 GPIO_ACTIVE_LOW>;
|
||||
gpios = <&pio 102 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
gsw: gsw@0 {
|
||||
compatible = "mediatek,mt753x";
|
||||
mediatek,ethsys = <ðsys>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
@ -69,13 +70,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
gsw: gsw@0 {
|
||||
compatible = "mediatek,mt753x";
|
||||
mediatek,ethsys = <ðsys>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
memory {
|
||||
reg = <0 0x40000000 0 0x40000000>;
|
||||
};
|
||||
@ -105,6 +99,7 @@
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&bch {
|
||||
@ -122,23 +117,59 @@
|
||||
};
|
||||
|
||||
ð {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <ð_pins>;
|
||||
status = "okay";
|
||||
|
||||
gmac0: mac@0 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <0>;
|
||||
phy-mode = "sgmii";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
gmac1: mac@1 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <1>;
|
||||
phy-handle = <&phy5>;
|
||||
phy-mode = "rgmii";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
|
||||
mdio: mdio-bus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
phy5: ethernet-phy@5 {
|
||||
reg = <5>;
|
||||
phy-mode = "sgmii";
|
||||
&gsw {
|
||||
mediatek,mdio = <&mdio>;
|
||||
mediatek,portmap = "wllll";
|
||||
mediatek,mdio_master_pinmux = <0>;
|
||||
reset-gpios = <&pio 54 0>;
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <53 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "okay";
|
||||
|
||||
port5: port@5 {
|
||||
compatible = "mediatek,mt753x-port";
|
||||
reg = <5>;
|
||||
phy-mode = "rgmii";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
port6: port@6 {
|
||||
compatible = "mediatek,mt753x-port";
|
||||
reg = <6>;
|
||||
phy-mode = "sgmii";
|
||||
fixed-link {
|
||||
speed = <2500>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -540,35 +571,3 @@
|
||||
pinctrl-0 = <&watchdog_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gsw {
|
||||
mediatek,mdio = <&mdio>;
|
||||
mediatek,portmap = "llllw";
|
||||
mediatek,mdio_master_pinmux = <0>;
|
||||
reset-gpios = <&pio 54 0>;
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <53 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "okay";
|
||||
|
||||
port5: port@5 {
|
||||
compatible = "mediatek,mt753x-port";
|
||||
reg = <5>;
|
||||
phy-mode = "rgmii";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
port6: port@6 {
|
||||
compatible = "mediatek,mt753x-port";
|
||||
reg = <6>;
|
||||
phy-mode = "sgmii";
|
||||
fixed-link {
|
||||
speed = <2500>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
config MT753X_GSW
|
||||
tristate "Driver for the MediaTek MT753x switch"
|
||||
|
||||
|
@ -7,5 +7,5 @@ obj-$(CONFIG_MT753X_GSW) += mt753x.o
|
||||
mt753x-$(CONFIG_SWCONFIG) += mt753x_swconfig.o
|
||||
|
||||
mt753x-y += mt753x_mdio.o mt7530.o mt7531.o \
|
||||
mt753x_common.o mt753x_nl.o
|
||||
|
||||
mt753x_common.o mt753x_vlan.o \
|
||||
mt753x_nl.o
|
||||
|
@ -1,11 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for MediaTek MT7530 gigabit switch
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Weijie Gao <weijie.gao@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -276,19 +272,73 @@ static void mt7530_core_reg_write(struct gsw_mt753x *gsw, u32 reg, u32 val)
|
||||
gsw->mmd_write(gsw, 0, 0x1f, reg, val);
|
||||
}
|
||||
|
||||
static void mt7530_trgmii_setting(struct gsw_mt753x *gsw)
|
||||
{
|
||||
u16 i;
|
||||
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, 0x0780);
|
||||
mdelay(1);
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0);
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, 0x87);
|
||||
mdelay(1);
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, 0x87);
|
||||
|
||||
/* PLL BIAS enable */
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP4,
|
||||
RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN);
|
||||
mdelay(1);
|
||||
|
||||
/* PLL LPF enable */
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP4,
|
||||
RG_SYSPLL_DDSFBK_EN |
|
||||
RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN);
|
||||
|
||||
/* sys PLL enable */
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP2,
|
||||
RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
|
||||
(1 << RG_SYSPLL_POSDIV_S));
|
||||
|
||||
/* LCDDDS PWDS */
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP7,
|
||||
(3 << RG_LCCDS_C_S) |
|
||||
RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
|
||||
mdelay(1);
|
||||
|
||||
/* Enable MT7530 TRGMII clock */
|
||||
mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, GSWCK_EN | TRGMIICK_EN);
|
||||
|
||||
/* lower Tx Driving */
|
||||
for (i = 0 ; i < NUM_TRGMII_ODT; i++)
|
||||
mt753x_reg_write(gsw, TRGMII_TD_ODT(i),
|
||||
(4 << TX_DM_DRVP_S) | (4 << TX_DM_DRVN_S));
|
||||
}
|
||||
|
||||
static void mt7530_rgmii_setting(struct gsw_mt753x *gsw)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, 0x0c80);
|
||||
mdelay(1);
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0);
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, 0x87);
|
||||
mdelay(1);
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, 0x87);
|
||||
|
||||
val = mt753x_reg_read(gsw, TRGMII_TXCTRL);
|
||||
val &= ~TXC_INV;
|
||||
mt753x_reg_write(gsw, TRGMII_TXCTRL, val);
|
||||
|
||||
mt753x_reg_write(gsw, TRGMII_TCK_CTRL,
|
||||
(8 << TX_TAP_S) | (0x55 << TX_TRAIN_WD_S));
|
||||
}
|
||||
|
||||
static int mt7530_mac_port_setup(struct gsw_mt753x *gsw)
|
||||
{
|
||||
u32 hwstrap, p6ecr = 0, p5mcr, p6mcr, phyad;
|
||||
|
||||
hwstrap = mt753x_reg_read(gsw, HWSTRAP);
|
||||
hwstrap = mt753x_reg_read(gsw, MHWSTRAP);
|
||||
hwstrap &= ~(P6_INTF_DIS | P5_INTF_MODE_RGMII | P5_INTF_DIS_S);
|
||||
hwstrap |= CHG_TRAP | P5_INTF_SEL_GMAC5;
|
||||
|
||||
if (gsw->direct_phy_access)
|
||||
hwstrap &= ~C_MDIO_BPS_S;
|
||||
else
|
||||
hwstrap |= C_MDIO_BPS_S;
|
||||
|
||||
hwstrap |= P5_INTF_SEL_GMAC5;
|
||||
if (!gsw->port5_cfg.enabled) {
|
||||
p5mcr = FORCE_MODE;
|
||||
hwstrap |= P5_INTF_DIS_S;
|
||||
@ -358,10 +408,11 @@ parse_p6:
|
||||
|
||||
switch (gsw->port6_cfg.phy_mode) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
p6ecr = BIT(1);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_TRGMII:
|
||||
/* set MT7530 central align */
|
||||
p6ecr = BIT(1); /* TODO: confirm this */
|
||||
p6ecr = BIT(0);
|
||||
break;
|
||||
default:
|
||||
dev_info(gsw->dev, "%s is not supported by port6\n",
|
||||
@ -382,8 +433,7 @@ parse_p6:
|
||||
|
||||
static void mt7530_core_pll_setup(struct gsw_mt753x *gsw)
|
||||
{
|
||||
u32 hwstrap, val, ncpo1, ssc_delta;
|
||||
int i;
|
||||
u32 hwstrap;
|
||||
|
||||
hwstrap = mt753x_reg_read(gsw, HWSTRAP);
|
||||
|
||||
@ -418,48 +468,23 @@ static void mt7530_core_pll_setup(struct gsw_mt753x *gsw)
|
||||
break;
|
||||
}
|
||||
|
||||
hwstrap = mt753x_reg_read(gsw, HWSTRAP);
|
||||
hwstrap |= CHG_TRAP;
|
||||
if (gsw->direct_phy_access)
|
||||
hwstrap &= ~C_MDIO_BPS_S;
|
||||
else
|
||||
hwstrap |= C_MDIO_BPS_S;
|
||||
|
||||
mt753x_reg_write(gsw, MHWSTRAP, hwstrap);
|
||||
|
||||
if (gsw->port6_cfg.enabled &&
|
||||
gsw->port6_cfg.phy_mode == PHY_INTERFACE_MODE_TRGMII) {
|
||||
ncpo1 = 0x1400;
|
||||
ssc_delta = 0x57;
|
||||
mt7530_trgmii_setting(gsw);
|
||||
} else {
|
||||
/* RGMII */
|
||||
ncpo1 = 0x0c80;
|
||||
ssc_delta = 0x87;
|
||||
mt7530_rgmii_setting(gsw);
|
||||
}
|
||||
|
||||
/* Setup the MT7530 TRGMII Tx Clock */
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP5, ncpo1);
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP6, 0);
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP10, ssc_delta);
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP11, ssc_delta);
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP4,
|
||||
RG_SYSPLL_DDSFBK_EN |
|
||||
RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN);
|
||||
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP2,
|
||||
RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
|
||||
(1 << RG_SYSPLL_POSDIV_S));
|
||||
|
||||
mt7530_core_reg_write(gsw, CORE_PLL_GROUP7,
|
||||
RG_LCDDS_PCW_NCPO_CHG | (3 << RG_LCCDS_C_S) |
|
||||
RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
|
||||
|
||||
/* Enable MT7530 TRGMII clock */
|
||||
mt7530_core_reg_write(gsw, TRGMII_GSW_CLK_CG, GSWCK_EN | TRGMIICK_EN);
|
||||
|
||||
val = mt753x_reg_read(gsw, TRGMII_TXCTRL);
|
||||
val &= ~TXC_INV;
|
||||
mt753x_reg_write(gsw, TRGMII_TXCTRL, val);
|
||||
|
||||
/* lower Tx Driving */
|
||||
for (i = 0 ; i < NUM_TRGMII_ODT; i++)
|
||||
mt753x_reg_write(gsw, TRGMII_TD_ODT(i),
|
||||
(8 << TX_DM_DRVP_S) | (8 << TX_DM_DRVN_S));
|
||||
|
||||
mt753x_reg_write(gsw, TRGMII_TCK_CTRL,
|
||||
(8 << TX_TAP_S) | (0x55 << TX_TRAIN_WD_S));
|
||||
|
||||
/* delay setting for 10/1000M */
|
||||
mt753x_reg_write(gsw, P5RGMIIRXCR,
|
||||
CSR_RGMII_EDGE_ALIGN |
|
||||
@ -519,13 +544,17 @@ static void mt7530_phy_setting(struct gsw_mt753x *gsw)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool get_phy_access_mode(const struct device_node *np)
|
||||
{
|
||||
return of_property_read_bool(np, "mt7530,direct-phy-access");
|
||||
}
|
||||
|
||||
static int mt7530_sw_init(struct gsw_mt753x *gsw)
|
||||
{
|
||||
int i;
|
||||
u32 val;
|
||||
|
||||
gsw->direct_phy_access = of_property_read_bool(gsw->dev->of_node,
|
||||
"mt7530,direct-phy-access");
|
||||
gsw->direct_phy_access = get_phy_access_mode(gsw->dev->of_node);
|
||||
|
||||
/* Force MT7530 to use (in)direct PHY access */
|
||||
val = mt753x_reg_read(gsw, HWSTRAP);
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#ifndef _MT7530_H_
|
||||
|
@ -1,11 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for MediaTek MT7531 gigabit switch
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Zhanguo Ju <zhanguo.ju@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -66,6 +62,11 @@
|
||||
/* PHY ENABLE Register bitmap define */
|
||||
#define PHY_DEV1F 0x1f
|
||||
#define PHY_DEV1F_REG_44 0x44
|
||||
#define PHY_DEV1F_REG_104 0x104
|
||||
#define PHY_DEV1F_REG_10A 0x10a
|
||||
#define PHY_DEV1F_REG_10B 0x10b
|
||||
#define PHY_DEV1F_REG_10C 0x10c
|
||||
#define PHY_DEV1F_REG_10D 0x10d
|
||||
#define PHY_DEV1F_REG_268 0x268
|
||||
#define PHY_DEV1F_REG_269 0x269
|
||||
#define PHY_DEV1F_REG_403 0x403
|
||||
@ -74,6 +75,8 @@
|
||||
#define GBE_EFUSE_SETTING BIT(3)
|
||||
#define PHY_EN_BYPASS_MODE BIT(4)
|
||||
#define POWER_ON_OFF BIT(5)
|
||||
#define PHY_PLL_M GENMASK(9, 8)
|
||||
#define PHY_PLL_SEL(x) (((x) << 8) & GENMASK(9, 8))
|
||||
|
||||
/* PHY EEE Register bitmap of define */
|
||||
#define PHY_DEV07 0x07
|
||||
@ -142,7 +145,7 @@
|
||||
#define ANA_PLLGP_CR5 0x78bc
|
||||
|
||||
/* GPIO mode define */
|
||||
#define GPIO_MODE_REGS(x) (0x7c0c + ((x / 8) * 4))
|
||||
#define GPIO_MODE_REGS(x) (0x7c0c + (((x) / 8) * 4))
|
||||
#define GPIO_MODE_S 4
|
||||
|
||||
/* GPIO GROUP IOLB SMT0 Control */
|
||||
@ -638,6 +641,68 @@ static int mt7531_set_gpio_pinmux(struct gsw_mt753x *gsw)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7531_phy_pll_setup(struct gsw_mt753x *gsw)
|
||||
{
|
||||
u32 hwstrap;
|
||||
u32 val;
|
||||
|
||||
hwstrap = mt753x_reg_read(gsw, HWSTRAP);
|
||||
|
||||
switch ((hwstrap & XTAL_FSEL_M) >> XTAL_FSEL_S) {
|
||||
case XTAL_25MHZ:
|
||||
/* disable pll auto calibration */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_104, 0x608);
|
||||
|
||||
/* change pll sel */
|
||||
val = gsw->mmd_read(gsw, 0, PHY_DEV1F,
|
||||
PHY_DEV1F_REG_403);
|
||||
val &= ~(PHY_PLL_M);
|
||||
val |= PHY_PLL_SEL(3);
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val);
|
||||
|
||||
/* set divider ratio */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F,
|
||||
PHY_DEV1F_REG_10A, 0x1009);
|
||||
|
||||
/* set divider ratio */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10B, 0x7c6);
|
||||
|
||||
/* capacitance and resistance adjustment */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F,
|
||||
PHY_DEV1F_REG_10C, 0xa8be);
|
||||
|
||||
break;
|
||||
case XTAL_40MHZ:
|
||||
/* disable pll auto calibration */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_104, 0x608);
|
||||
|
||||
/* change pll sel */
|
||||
val = gsw->mmd_read(gsw, 0, PHY_DEV1F,
|
||||
PHY_DEV1F_REG_403);
|
||||
val &= ~(PHY_PLL_M);
|
||||
val |= PHY_PLL_SEL(3);
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val);
|
||||
|
||||
/* set divider ratio */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F,
|
||||
PHY_DEV1F_REG_10A, 0x1018);
|
||||
|
||||
/* set divider ratio */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10B, 0xc676);
|
||||
|
||||
/* capacitance and resistance adjustment */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F,
|
||||
PHY_DEV1F_REG_10C, 0xd8be);
|
||||
break;
|
||||
}
|
||||
|
||||
/* power down pll. additional delay is not required via mdio access */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10D, 0x10);
|
||||
|
||||
/* power up pll */
|
||||
gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_10D, 0x14);
|
||||
}
|
||||
|
||||
static void mt7531_phy_setting(struct gsw_mt753x *gsw)
|
||||
{
|
||||
int i;
|
||||
@ -694,7 +759,7 @@ static void mt7531_adjust_line_driving(struct gsw_mt753x *gsw, u32 port)
|
||||
gsw->mmd_write(gsw, port, PHY_DEV1E, RXADC_CONTROL_3, 0x4444);
|
||||
|
||||
/* Adjust Line driver current for different mode */
|
||||
gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_271, 0x2c63);
|
||||
gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_271, 0x2ca5);
|
||||
|
||||
/* Adjust Line driver current for different mode */
|
||||
gsw->mmd_write(gsw, port, PHY_DEV1F, TXVLD_DA_272, 0xc6b);
|
||||
@ -709,10 +774,10 @@ static void mt7531_adjust_line_driving(struct gsw_mt753x *gsw, u32 port)
|
||||
gsw->mmd_write(gsw, port, PHY_DEV1E, PHY_DEV1E_REG_41, 0x3333);
|
||||
|
||||
/* Adjust TX class AB driver 1 */
|
||||
gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_268, 0x3aa);
|
||||
gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_268, 0x388);
|
||||
|
||||
/* Adjust TX class AB driver 2 */
|
||||
gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_269, 0xaaaa);
|
||||
gsw->mmd_write(gsw, port, PHY_DEV1F, PHY_DEV1F_REG_269, 0x4448);
|
||||
}
|
||||
|
||||
static void mt7531_eee_setting(struct gsw_mt753x *gsw, u32 port)
|
||||
@ -797,6 +862,8 @@ static int mt7531_sw_post_init(struct gsw_mt753x *gsw)
|
||||
int i;
|
||||
u32 val;
|
||||
|
||||
mt7531_phy_pll_setup(gsw);
|
||||
|
||||
/* Internal PHYs are disabled by default. SW should enable them.
|
||||
* Note that this may already be enabled in bootloader stage.
|
||||
*/
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#ifndef _MT7531_H_
|
||||
|
@ -1,11 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Driver for MediaTek MT753x gigabit switch
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Weijie Gao <weijie.gao@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _MT753X_H_
|
||||
@ -22,13 +18,10 @@
|
||||
#include <linux/switch.h>
|
||||
#endif
|
||||
|
||||
#define MT753X_DFL_CPU_PORT 6
|
||||
#define MT753X_NUM_PORTS 7
|
||||
#define MT753X_NUM_PHYS 5
|
||||
#define MT753X_NUM_VLANS 4095
|
||||
#include "mt753x_vlan.h"
|
||||
|
||||
#define MT753X_MAX_VID 4095
|
||||
#define MT753X_MIN_VID 0
|
||||
#define MT753X_DFL_CPU_PORT 6
|
||||
#define MT753X_NUM_PHYS 5
|
||||
|
||||
#define MT753X_DFL_SMI_ADDR 0x1f
|
||||
#define MT753X_SMI_ADDR_MASK 0x1f
|
||||
@ -40,16 +33,6 @@ enum mt753x_model {
|
||||
MT7531 = 0x7531
|
||||
};
|
||||
|
||||
struct mt753x_port_entry {
|
||||
u16 pvid;
|
||||
};
|
||||
|
||||
struct mt753x_vlan_entry {
|
||||
u16 vid;
|
||||
u8 member;
|
||||
u8 etags;
|
||||
};
|
||||
|
||||
struct mt753x_port_cfg {
|
||||
struct device_node *np;
|
||||
int phy_mode;
|
||||
@ -82,7 +65,7 @@ struct gsw_mt753x {
|
||||
struct mt753x_port_cfg port5_cfg;
|
||||
struct mt753x_port_cfg port6_cfg;
|
||||
|
||||
bool phy_status_poll;
|
||||
int phy_status_poll;
|
||||
struct mt753x_phy phys[MT753X_NUM_PHYS];
|
||||
|
||||
int phy_link_sts;
|
||||
@ -93,14 +76,13 @@ struct gsw_mt753x {
|
||||
|
||||
#ifdef CONFIG_SWCONFIG
|
||||
struct switch_dev swdev;
|
||||
|
||||
struct mt753x_vlan_entry vlan_entries[MT753X_NUM_VLANS];
|
||||
struct mt753x_port_entry port_entries[MT753X_NUM_PORTS];
|
||||
|
||||
int global_vlan_enable;
|
||||
u32 cpu_port;
|
||||
#endif
|
||||
|
||||
int global_vlan_enable;
|
||||
struct mt753x_vlan_entry vlan_entries[MT753X_NUM_VLANS];
|
||||
struct mt753x_port_entry port_entries[MT753X_NUM_PORTS];
|
||||
|
||||
int (*mii_read)(struct gsw_mt753x *gsw, int phy, int reg);
|
||||
void (*mii_write)(struct gsw_mt753x *gsw, int phy, int reg, u16 val);
|
||||
|
||||
@ -228,5 +210,4 @@ void mt753x_irq_enable(struct gsw_mt753x *gsw);
|
||||
#define MT753X_REG_PAGE_ADDR_M 0xffc0
|
||||
#define MT753X_REG_ADDR_S 2
|
||||
#define MT753X_REG_ADDR_M 0x3c
|
||||
|
||||
#endif /* _MT753X_H_ */
|
||||
|
@ -1,11 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Common part for MediaTek MT753x gigabit switch
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Weijie Gao <weijie.gao@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -56,8 +52,8 @@ static void display_port_link_status(struct gsw_mt753x *gsw, u32 port)
|
||||
}
|
||||
|
||||
if (pmsr & MAC_LNK_STS) {
|
||||
dev_info(gsw->dev, "Port %d Link is Up - %s/%s\n",
|
||||
port, speed, (pmsr & MAC_DPX_STS) ? "Full" : "Half");
|
||||
dev_info(gsw->dev, "Port %d Link is Up - %s/%s\n",
|
||||
port, speed, (pmsr & MAC_DPX_STS) ? "Full" : "Half");
|
||||
} else {
|
||||
dev_info(gsw->dev, "Port %d Link is Down\n", port);
|
||||
}
|
||||
|
@ -1,11 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for MediaTek MT753x gigabit switch
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Weijie Gao <weijie.gao@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@ -232,6 +228,11 @@ void mt753x_mmd_ind_write(struct gsw_mt753x *gsw, int addr, int devad, u16 reg,
|
||||
mutex_unlock(&gsw->mii_lock);
|
||||
}
|
||||
|
||||
static inline int mt753x_get_duplex(const struct device_node *np)
|
||||
{
|
||||
return of_property_read_bool(np, "full-duplex");
|
||||
}
|
||||
|
||||
static void mt753x_load_port_cfg(struct gsw_mt753x *gsw)
|
||||
{
|
||||
struct device_node *port_np;
|
||||
@ -279,9 +280,7 @@ static void mt753x_load_port_cfg(struct gsw_mt753x *gsw)
|
||||
u32 speed;
|
||||
|
||||
port_cfg->force_link = 1;
|
||||
port_cfg->duplex = of_property_read_bool(
|
||||
fixed_link_node,
|
||||
"full-duplex");
|
||||
port_cfg->duplex = mt753x_get_duplex(fixed_link_node);
|
||||
|
||||
if (of_property_read_u32(fixed_link_node, "speed",
|
||||
&speed)) {
|
||||
@ -331,6 +330,7 @@ static void mt753x_remove_gsw(struct gsw_mt753x *gsw)
|
||||
mutex_unlock(&mt753x_devs_lock);
|
||||
}
|
||||
|
||||
|
||||
struct gsw_mt753x *mt753x_get_gsw(u32 id)
|
||||
{
|
||||
struct gsw_mt753x *dev;
|
||||
@ -416,150 +416,6 @@ static int mt753x_hw_reset(struct gsw_mt753x *gsw)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt753x_mdio_read(struct mii_bus *bus, int addr, int reg)
|
||||
{
|
||||
struct gsw_mt753x *gsw = bus->priv;
|
||||
|
||||
return gsw->mii_read(gsw, addr, reg);
|
||||
}
|
||||
|
||||
static int mt753x_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val)
|
||||
{
|
||||
struct gsw_mt753x *gsw = bus->priv;
|
||||
|
||||
gsw->mii_write(gsw, addr, reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops mt753x_dummy_netdev_ops = {
|
||||
};
|
||||
|
||||
static void mt753x_phy_link_handler(struct net_device *dev)
|
||||
{
|
||||
struct mt753x_phy *phy = container_of(dev, struct mt753x_phy, netdev);
|
||||
struct phy_device *phydev = phy->phydev;
|
||||
struct gsw_mt753x *gsw = phy->gsw;
|
||||
u32 port = phy - gsw->phys;
|
||||
|
||||
if (phydev->link) {
|
||||
dev_info(gsw->dev,
|
||||
"Port %d Link is Up - %s/%s - flow control %s\n",
|
||||
port, phy_speed_to_str(phydev->speed),
|
||||
(phydev->duplex == DUPLEX_FULL) ? "Full" : "Half",
|
||||
phydev->pause ? "rx/tx" : "off");
|
||||
} else {
|
||||
dev_info(gsw->dev, "Port %d Link is Down\n", port);
|
||||
}
|
||||
}
|
||||
|
||||
static void mt753x_connect_internal_phys(struct gsw_mt753x *gsw,
|
||||
struct device_node *mii_np)
|
||||
{
|
||||
struct device_node *phy_np;
|
||||
struct mt753x_phy *phy;
|
||||
int phy_mode;
|
||||
u32 phyad;
|
||||
|
||||
if (!mii_np)
|
||||
return;
|
||||
|
||||
for_each_child_of_node(mii_np, phy_np) {
|
||||
if (of_property_read_u32(phy_np, "reg", &phyad))
|
||||
continue;
|
||||
|
||||
if (phyad >= MT753X_NUM_PHYS)
|
||||
continue;
|
||||
|
||||
phy_mode = of_get_phy_mode(phy_np);
|
||||
if (phy_mode < 0) {
|
||||
dev_info(gsw->dev, "incorrect phy-mode %d for PHY %d\n",
|
||||
phy_mode, phyad);
|
||||
continue;
|
||||
}
|
||||
|
||||
phy = &gsw->phys[phyad];
|
||||
phy->gsw = gsw;
|
||||
|
||||
init_dummy_netdev(&phy->netdev);
|
||||
phy->netdev.netdev_ops = &mt753x_dummy_netdev_ops;
|
||||
|
||||
phy->phydev = of_phy_connect(&phy->netdev, phy_np,
|
||||
mt753x_phy_link_handler, 0, phy_mode);
|
||||
if (!phy->phydev) {
|
||||
dev_info(gsw->dev, "could not connect to PHY %d\n",
|
||||
phyad);
|
||||
continue;
|
||||
}
|
||||
|
||||
phy_start(phy->phydev);
|
||||
}
|
||||
}
|
||||
|
||||
static void mt753x_disconnect_internal_phys(struct gsw_mt753x *gsw)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gsw->phys); i++) {
|
||||
if (gsw->phys[i].phydev) {
|
||||
phy_stop(gsw->phys[i].phydev);
|
||||
phy_disconnect(gsw->phys[i].phydev);
|
||||
gsw->phys[i].phydev = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int mt753x_mdio_register(struct gsw_mt753x *gsw)
|
||||
{
|
||||
struct device_node *mii_np;
|
||||
int i, ret;
|
||||
|
||||
mii_np = of_get_child_by_name(gsw->dev->of_node, "mdio-bus");
|
||||
if (mii_np && !of_device_is_available(mii_np)) {
|
||||
ret = -ENODEV;
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
gsw->gphy_bus = devm_mdiobus_alloc(gsw->dev);
|
||||
if (!gsw->gphy_bus) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
gsw->gphy_bus->name = "mt753x_mdio";
|
||||
gsw->gphy_bus->read = mt753x_mdio_read;
|
||||
gsw->gphy_bus->write = mt753x_mdio_write;
|
||||
gsw->gphy_bus->priv = gsw;
|
||||
gsw->gphy_bus->parent = gsw->dev;
|
||||
gsw->gphy_bus->phy_mask = BIT(MT753X_NUM_PHYS) - 1;
|
||||
|
||||
for (i = 0; i < PHY_MAX_ADDR; i++)
|
||||
gsw->gphy_bus->irq[i] = PHY_POLL;
|
||||
|
||||
if (mii_np)
|
||||
snprintf(gsw->gphy_bus->id, MII_BUS_ID_SIZE, "%s@%s",
|
||||
mii_np->name, gsw->dev->of_node->name);
|
||||
else
|
||||
snprintf(gsw->gphy_bus->id, MII_BUS_ID_SIZE, "mdio@%s",
|
||||
gsw->dev->of_node->name);
|
||||
|
||||
ret = of_mdiobus_register(gsw->gphy_bus, mii_np);
|
||||
|
||||
if (ret) {
|
||||
devm_mdiobus_free(gsw->dev, gsw->gphy_bus);
|
||||
gsw->gphy_bus = NULL;
|
||||
} else {
|
||||
if (gsw->phy_status_poll)
|
||||
mt753x_connect_internal_phys(gsw, mii_np);
|
||||
}
|
||||
|
||||
err_put_node:
|
||||
if (mii_np)
|
||||
of_node_put(mii_np);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t mt753x_irq_handler(int irq, void *dev)
|
||||
{
|
||||
struct gsw_mt753x *gsw = dev;
|
||||
@ -580,6 +436,7 @@ static int mt753x_probe(struct platform_device *pdev)
|
||||
struct mii_bus *mdio_bus;
|
||||
int ret = -EINVAL;
|
||||
struct chip_rev rev;
|
||||
struct mt753x_mapping *map;
|
||||
int i;
|
||||
|
||||
mdio = of_parse_phandle(np, "mediatek,mdio", 0);
|
||||
@ -599,12 +456,21 @@ static int mt753x_probe(struct platform_device *pdev)
|
||||
mutex_init(&gsw->mii_lock);
|
||||
|
||||
/* Switch hard reset */
|
||||
mt753x_hw_reset(gsw);
|
||||
if (mt753x_hw_reset(gsw))
|
||||
goto fail;
|
||||
|
||||
/* Fetch the SMI address dirst */
|
||||
if (of_property_read_u32(np, "mediatek,smi-addr", &gsw->smi_addr))
|
||||
gsw->smi_addr = MT753X_DFL_SMI_ADDR;
|
||||
|
||||
/* Get LAN/WAN port mapping */
|
||||
map = mt753x_find_mapping(np);
|
||||
if (map) {
|
||||
mt753x_apply_mapping(gsw, map);
|
||||
gsw->global_vlan_enable = 1;
|
||||
dev_info(gsw->dev, "LAN/WAN VLAN setting=%s\n", map->name);
|
||||
}
|
||||
|
||||
/* Load MAC port configurations */
|
||||
mt753x_load_port_cfg(gsw);
|
||||
|
||||
@ -653,11 +519,7 @@ static int mt753x_probe(struct platform_device *pdev)
|
||||
|
||||
mt753x_add_gsw(gsw);
|
||||
|
||||
mt753x_mdio_register(gsw);
|
||||
|
||||
#ifdef CONFIG_SWCONFIG
|
||||
mt753x_swconfig_init(gsw);
|
||||
#endif
|
||||
|
||||
if (sw->post_init)
|
||||
sw->post_init(gsw);
|
||||
@ -687,10 +549,6 @@ static int mt753x_remove(struct platform_device *pdev)
|
||||
mt753x_swconfig_destroy(gsw);
|
||||
#endif
|
||||
|
||||
mt753x_disconnect_internal_phys(gsw);
|
||||
|
||||
mdiobus_unregister(gsw->gphy_bus);
|
||||
|
||||
mt753x_remove_gsw(gsw);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
@ -1,11 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Configuration layer for MediaTek MT753x gigabit switch
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
@ -17,10 +13,6 @@
|
||||
#include "mt753x.h"
|
||||
#include "mt753x_nl.h"
|
||||
|
||||
#define MT753X_NL_CMD_REQ_ATTRS(attr) \
|
||||
.required_attrs = attr, \
|
||||
.nr_required_attrs = ARRAY_SIZE(attr),
|
||||
|
||||
struct mt753x_nl_cmd_item {
|
||||
enum mt753x_cmd cmd;
|
||||
bool require_dev;
|
||||
@ -61,7 +53,6 @@ static const struct genl_ops mt753x_nl_ops[] = {
|
||||
};
|
||||
|
||||
static struct genl_family mt753x_nl_family = {
|
||||
// .id = GENL_ID_GENERATE,
|
||||
.name = MT753X_GENL_NAME,
|
||||
.version = MT753X_GENL_VERSION,
|
||||
.maxattr = MT753X_NR_ATTR_TYPE,
|
||||
@ -208,7 +199,8 @@ static int mt753x_nl_reply_read(struct genl_info *info, struct gsw_mt753x *gsw)
|
||||
{
|
||||
struct sk_buff *rep_skb = NULL;
|
||||
s32 phy, devad, reg;
|
||||
int ret, value;
|
||||
int value;
|
||||
int ret = 0;
|
||||
|
||||
phy = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_PHY, -1);
|
||||
devad = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_DEVAD, -1);
|
||||
@ -252,7 +244,7 @@ static int mt753x_nl_reply_write(struct genl_info *info, struct gsw_mt753x *gsw)
|
||||
struct sk_buff *rep_skb = NULL;
|
||||
s32 phy, devad, reg;
|
||||
u32 value;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
phy = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_PHY, -1);
|
||||
devad = mt753x_nl_get_s32(info, MT753X_ATTR_TYPE_DEVAD, -1);
|
||||
@ -312,12 +304,14 @@ static const struct mt753x_nl_cmd_item mt753x_nl_cmds[] = {
|
||||
.cmd = MT753X_CMD_READ,
|
||||
.require_dev = true,
|
||||
.process = mt753x_nl_reply_read,
|
||||
MT753X_NL_CMD_REQ_ATTRS(mt753x_nl_cmd_read_attrs)
|
||||
.required_attrs = mt753x_nl_cmd_read_attrs,
|
||||
.nr_required_attrs = ARRAY_SIZE(mt753x_nl_cmd_read_attrs),
|
||||
}, {
|
||||
.cmd = MT753X_CMD_WRITE,
|
||||
.require_dev = true,
|
||||
.process = mt753x_nl_reply_write,
|
||||
MT753X_NL_CMD_REQ_ATTRS(mt753x_nl_cmd_write_attrs)
|
||||
.required_attrs = mt753x_nl_cmd_write_attrs,
|
||||
.nr_required_attrs = ARRAY_SIZE(mt753x_nl_cmd_write_attrs),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,11 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Driver for MediaTek MT753x gigabit switch
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _MT753X_NL_H_
|
||||
|
@ -1,11 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Register definitions for MediaTek MT753x Gigabit switches
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Weijie Gao <weijie.gao@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _MT753X_REGS_H_
|
||||
|
@ -1,11 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* OpenWrt swconfig support for MediaTek MT753x Gigabit switch
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Weijie Gao <weijie.gao@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <linux/if.h>
|
||||
@ -93,64 +89,6 @@ enum {
|
||||
MT753X_ATTR_ENABLE_VLAN,
|
||||
};
|
||||
|
||||
struct mt753x_mapping {
|
||||
char *name;
|
||||
u16 pvids[MT753X_NUM_PORTS];
|
||||
u8 members[MT753X_NUM_VLANS];
|
||||
u8 etags[MT753X_NUM_VLANS];
|
||||
u16 vids[MT753X_NUM_VLANS];
|
||||
} mt753x_defaults[] = {
|
||||
{
|
||||
.name = "llllw",
|
||||
.pvids = { 1, 1, 1, 1, 2, 2, 1 },
|
||||
.members = { 0, 0x4f, 0x30 },
|
||||
.etags = { 0, 0, 0 },
|
||||
.vids = { 0, 1, 2 },
|
||||
}, {
|
||||
.name = "wllll",
|
||||
.pvids = { 2, 1, 1, 1, 1, 2, 1 },
|
||||
.members = { 0, 0x5e, 0x21 },
|
||||
.etags = { 0, 0, 0 },
|
||||
.vids = { 0, 1, 2 },
|
||||
}, {
|
||||
.name = "lwlll",
|
||||
.pvids = { 1, 2, 1, 1, 1, 2, 1 },
|
||||
.members = { 0, 0x5d, 0x22 },
|
||||
.etags = { 0, 0, 0 },
|
||||
.vids = { 0, 1, 2 },
|
||||
},
|
||||
};
|
||||
|
||||
struct mt753x_mapping *mt753x_find_mapping(struct device_node *np)
|
||||
{
|
||||
const char *map;
|
||||
int i;
|
||||
|
||||
if (of_property_read_string(np, "mediatek,portmap", &map))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mt753x_defaults); i++)
|
||||
if (!strcmp(map, mt753x_defaults[i].name))
|
||||
return &mt753x_defaults[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void mt753x_apply_mapping(struct gsw_mt753x *gsw,
|
||||
struct mt753x_mapping *map)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < MT753X_NUM_PORTS; i++)
|
||||
gsw->port_entries[i].pvid = map->pvids[i];
|
||||
|
||||
for (i = 0; i < MT753X_NUM_VLANS; i++) {
|
||||
gsw->vlan_entries[i].member = map->members[i];
|
||||
gsw->vlan_entries[i].etags = map->etags[i];
|
||||
gsw->vlan_entries[i].vid = map->vids[i];
|
||||
}
|
||||
}
|
||||
|
||||
static int mt753x_get_vlan_enable(struct switch_dev *dev,
|
||||
const struct switch_attr *attr,
|
||||
struct switch_val *val)
|
||||
@ -201,27 +139,6 @@ static int mt753x_set_port_pvid(struct switch_dev *dev, int port, int pvid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val)
|
||||
{
|
||||
int i;
|
||||
|
||||
mt753x_reg_write(gsw, VTCR,
|
||||
VTCR_BUSY | ((cmd << VTCR_FUNC_S) & VTCR_FUNC_M) |
|
||||
(val & VTCR_VID_M));
|
||||
|
||||
for (i = 0; i < 300; i++) {
|
||||
u32 val = mt753x_reg_read(gsw, VTCR);
|
||||
|
||||
if ((val & VTCR_BUSY) == 0)
|
||||
break;
|
||||
|
||||
usleep_range(1000, 1100);
|
||||
}
|
||||
|
||||
if (i == 300)
|
||||
dev_info(gsw->dev, "vtcr timeout\n");
|
||||
}
|
||||
|
||||
static int mt753x_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
|
||||
{
|
||||
struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
|
||||
@ -447,114 +364,16 @@ static void mt753x_port_isolation(struct gsw_mt753x *gsw)
|
||||
(VA_TRANSPARENT_PORT << VLAN_ATTR_S));
|
||||
}
|
||||
|
||||
static void mt753x_write_vlan_entry(struct gsw_mt753x *gsw, int vlan, u16 vid,
|
||||
u8 ports, u8 etags)
|
||||
{
|
||||
int port;
|
||||
u32 val;
|
||||
|
||||
/* vlan port membership */
|
||||
if (ports)
|
||||
mt753x_reg_write(gsw, VAWD1,
|
||||
IVL_MAC | VTAG_EN | VENTRY_VALID |
|
||||
((ports << PORT_MEM_S) & PORT_MEM_M));
|
||||
else
|
||||
mt753x_reg_write(gsw, VAWD1, 0);
|
||||
|
||||
/* egress mode */
|
||||
val = 0;
|
||||
for (port = 0; port < MT753X_NUM_PORTS; port++) {
|
||||
if (etags & BIT(port))
|
||||
val |= ETAG_CTRL_TAG << PORT_ETAG_S(port);
|
||||
else
|
||||
val |= ETAG_CTRL_UNTAG << PORT_ETAG_S(port);
|
||||
}
|
||||
mt753x_reg_write(gsw, VAWD2, val);
|
||||
|
||||
/* write to vlan table */
|
||||
mt753x_vlan_ctrl(gsw, VTCR_WRITE_VLAN_ENTRY, vid);
|
||||
}
|
||||
|
||||
static int mt753x_apply_config(struct switch_dev *dev)
|
||||
{
|
||||
struct gsw_mt753x *gsw = container_of(dev, struct gsw_mt753x, swdev);
|
||||
int i, j;
|
||||
u8 tag_ports;
|
||||
u8 untag_ports;
|
||||
|
||||
if (!gsw->global_vlan_enable) {
|
||||
mt753x_port_isolation(gsw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set all ports as security mode */
|
||||
for (i = 0; i < MT753X_NUM_PORTS; i++)
|
||||
mt753x_reg_write(gsw, PCR(i),
|
||||
PORT_MATRIX_M | SECURITY_MODE);
|
||||
|
||||
/* check if a port is used in tag/untag vlan egress mode */
|
||||
tag_ports = 0;
|
||||
untag_ports = 0;
|
||||
|
||||
for (i = 0; i < MT753X_NUM_VLANS; i++) {
|
||||
u8 member = gsw->vlan_entries[i].member;
|
||||
u8 etags = gsw->vlan_entries[i].etags;
|
||||
|
||||
if (!member)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < MT753X_NUM_PORTS; j++) {
|
||||
if (!(member & BIT(j)))
|
||||
continue;
|
||||
|
||||
if (etags & BIT(j))
|
||||
tag_ports |= 1u << j;
|
||||
else
|
||||
untag_ports |= 1u << j;
|
||||
}
|
||||
}
|
||||
|
||||
/* set all untag-only ports as transparent and the rest as user port */
|
||||
for (i = 0; i < MT753X_NUM_PORTS; i++) {
|
||||
u32 pvc_mode = 0x8100 << STAG_VPID_S;
|
||||
|
||||
if (untag_ports & BIT(i) && !(tag_ports & BIT(i)))
|
||||
pvc_mode = (0x8100 << STAG_VPID_S) |
|
||||
(VA_TRANSPARENT_PORT << VLAN_ATTR_S);
|
||||
|
||||
mt753x_reg_write(gsw, PVC(i), pvc_mode);
|
||||
}
|
||||
|
||||
/* first clear the swtich vlan table */
|
||||
for (i = 0; i < MT753X_NUM_VLANS; i++)
|
||||
mt753x_write_vlan_entry(gsw, i, i, 0, 0);
|
||||
|
||||
/* now program only vlans with members to avoid
|
||||
* clobbering remapped entries in later iterations
|
||||
*/
|
||||
for (i = 0; i < MT753X_NUM_VLANS; i++) {
|
||||
u16 vid = gsw->vlan_entries[i].vid;
|
||||
u8 member = gsw->vlan_entries[i].member;
|
||||
u8 etags = gsw->vlan_entries[i].etags;
|
||||
|
||||
if (member)
|
||||
mt753x_write_vlan_entry(gsw, i, vid, member, etags);
|
||||
}
|
||||
|
||||
/* Port Default PVID */
|
||||
for (i = 0; i < MT753X_NUM_PORTS; i++) {
|
||||
int vlan = gsw->port_entries[i].pvid;
|
||||
u16 pvid = 0;
|
||||
u32 val;
|
||||
|
||||
if (vlan < MT753X_NUM_VLANS && gsw->vlan_entries[vlan].member)
|
||||
pvid = gsw->vlan_entries[vlan].vid;
|
||||
|
||||
val = mt753x_reg_read(gsw, PPBV1(i));
|
||||
val &= ~GRP_PORT_VID_M;
|
||||
val |= pvid;
|
||||
mt753x_reg_write(gsw, PPBV1(i), val);
|
||||
}
|
||||
mt753x_apply_vlan_config(gsw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -659,7 +478,6 @@ int mt753x_swconfig_init(struct gsw_mt753x *gsw)
|
||||
{
|
||||
struct device_node *np = gsw->dev->of_node;
|
||||
struct switch_dev *swdev;
|
||||
struct mt753x_mapping *map;
|
||||
int ret;
|
||||
|
||||
if (of_property_read_u32(np, "mediatek,cpuport", &gsw->cpu_port))
|
||||
@ -676,14 +494,11 @@ int mt753x_swconfig_init(struct gsw_mt753x *gsw)
|
||||
|
||||
ret = register_switch(swdev, NULL);
|
||||
if (ret) {
|
||||
dev_err(gsw->dev, "Failed to register switch %s\n",
|
||||
swdev->name);
|
||||
dev_notice(gsw->dev, "Failed to register switch %s\n",
|
||||
swdev->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
map = mt753x_find_mapping(gsw->dev->of_node);
|
||||
if (map)
|
||||
mt753x_apply_mapping(gsw, map);
|
||||
mt753x_apply_config(swdev);
|
||||
|
||||
return 0;
|
||||
|
@ -1,19 +1,29 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* OpenWrt swconfig support for MediaTek MT753x Gigabit switch
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
* Author: Weijie Gao <weijie.gao@mediatek.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _MT753X_SWCONFIG_H_
|
||||
#define _MT753X_SWCONFIG_H_
|
||||
|
||||
#ifdef CONFIG_SWCONFIG
|
||||
#include <linux/switch.h>
|
||||
#include "mt753x.h"
|
||||
|
||||
int mt753x_swconfig_init(struct gsw_mt753x *gsw);
|
||||
void mt753x_swconfig_destroy(struct gsw_mt753x *gsw);
|
||||
#else
|
||||
static inline int mt753x_swconfig_init(struct gsw_mt753x *gsw)
|
||||
{
|
||||
mt753x_apply_vlan_config(gsw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mt753x_swconfig_destroy(struct gsw_mt753x *gsw)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MT753X_SWCONFIG_H_ */
|
||||
|
@ -0,0 +1,183 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#include "mt753x.h"
|
||||
#include "mt753x_regs.h"
|
||||
|
||||
struct mt753x_mapping mt753x_def_mapping[] = {
|
||||
{
|
||||
.name = "llllw",
|
||||
.pvids = { 1, 1, 1, 1, 2, 2, 1 },
|
||||
.members = { 0, 0x4f, 0x30 },
|
||||
.etags = { 0, 0, 0 },
|
||||
.vids = { 0, 1, 2 },
|
||||
}, {
|
||||
.name = "wllll",
|
||||
.pvids = { 2, 1, 1, 1, 1, 2, 1 },
|
||||
.members = { 0, 0x5e, 0x21 },
|
||||
.etags = { 0, 0, 0 },
|
||||
.vids = { 0, 1, 2 },
|
||||
}, {
|
||||
.name = "lwlll",
|
||||
.pvids = { 1, 2, 1, 1, 1, 2, 1 },
|
||||
.members = { 0, 0x5d, 0x22 },
|
||||
.etags = { 0, 0, 0 },
|
||||
.vids = { 0, 1, 2 },
|
||||
},
|
||||
};
|
||||
|
||||
void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val)
|
||||
{
|
||||
int i;
|
||||
|
||||
mt753x_reg_write(gsw, VTCR,
|
||||
VTCR_BUSY | ((cmd << VTCR_FUNC_S) & VTCR_FUNC_M) |
|
||||
(val & VTCR_VID_M));
|
||||
|
||||
for (i = 0; i < 300; i++) {
|
||||
u32 val = mt753x_reg_read(gsw, VTCR);
|
||||
|
||||
if ((val & VTCR_BUSY) == 0)
|
||||
break;
|
||||
|
||||
usleep_range(1000, 1100);
|
||||
}
|
||||
|
||||
if (i == 300)
|
||||
dev_info(gsw->dev, "vtcr timeout\n");
|
||||
}
|
||||
|
||||
static void mt753x_write_vlan_entry(struct gsw_mt753x *gsw, int vlan, u16 vid,
|
||||
u8 ports, u8 etags)
|
||||
{
|
||||
int port;
|
||||
u32 val;
|
||||
|
||||
/* vlan port membership */
|
||||
if (ports)
|
||||
mt753x_reg_write(gsw, VAWD1,
|
||||
IVL_MAC | VTAG_EN | VENTRY_VALID |
|
||||
((ports << PORT_MEM_S) & PORT_MEM_M));
|
||||
else
|
||||
mt753x_reg_write(gsw, VAWD1, 0);
|
||||
|
||||
/* egress mode */
|
||||
val = 0;
|
||||
for (port = 0; port < MT753X_NUM_PORTS; port++) {
|
||||
if (etags & BIT(port))
|
||||
val |= ETAG_CTRL_TAG << PORT_ETAG_S(port);
|
||||
else
|
||||
val |= ETAG_CTRL_UNTAG << PORT_ETAG_S(port);
|
||||
}
|
||||
mt753x_reg_write(gsw, VAWD2, val);
|
||||
|
||||
/* write to vlan table */
|
||||
mt753x_vlan_ctrl(gsw, VTCR_WRITE_VLAN_ENTRY, vid);
|
||||
}
|
||||
|
||||
void mt753x_apply_vlan_config(struct gsw_mt753x *gsw)
|
||||
{
|
||||
int i, j;
|
||||
u8 tag_ports;
|
||||
u8 untag_ports;
|
||||
|
||||
/* set all ports as security mode */
|
||||
for (i = 0; i < MT753X_NUM_PORTS; i++)
|
||||
mt753x_reg_write(gsw, PCR(i),
|
||||
PORT_MATRIX_M | SECURITY_MODE);
|
||||
|
||||
/* check if a port is used in tag/untag vlan egress mode */
|
||||
tag_ports = 0;
|
||||
untag_ports = 0;
|
||||
|
||||
for (i = 0; i < MT753X_NUM_VLANS; i++) {
|
||||
u8 member = gsw->vlan_entries[i].member;
|
||||
u8 etags = gsw->vlan_entries[i].etags;
|
||||
|
||||
if (!member)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < MT753X_NUM_PORTS; j++) {
|
||||
if (!(member & BIT(j)))
|
||||
continue;
|
||||
|
||||
if (etags & BIT(j))
|
||||
tag_ports |= 1u << j;
|
||||
else
|
||||
untag_ports |= 1u << j;
|
||||
}
|
||||
}
|
||||
|
||||
/* set all untag-only ports as transparent and the rest as user port */
|
||||
for (i = 0; i < MT753X_NUM_PORTS; i++) {
|
||||
u32 pvc_mode = 0x8100 << STAG_VPID_S;
|
||||
|
||||
if (untag_ports & BIT(i) && !(tag_ports & BIT(i)))
|
||||
pvc_mode = (0x8100 << STAG_VPID_S) |
|
||||
(VA_TRANSPARENT_PORT << VLAN_ATTR_S);
|
||||
|
||||
mt753x_reg_write(gsw, PVC(i), pvc_mode);
|
||||
}
|
||||
|
||||
/* first clear the switch vlan table */
|
||||
for (i = 0; i < MT753X_NUM_VLANS; i++)
|
||||
mt753x_write_vlan_entry(gsw, i, i, 0, 0);
|
||||
|
||||
/* now program only vlans with members to avoid
|
||||
* clobbering remapped entries in later iterations
|
||||
*/
|
||||
for (i = 0; i < MT753X_NUM_VLANS; i++) {
|
||||
u16 vid = gsw->vlan_entries[i].vid;
|
||||
u8 member = gsw->vlan_entries[i].member;
|
||||
u8 etags = gsw->vlan_entries[i].etags;
|
||||
|
||||
if (member)
|
||||
mt753x_write_vlan_entry(gsw, i, vid, member, etags);
|
||||
}
|
||||
|
||||
/* Port Default PVID */
|
||||
for (i = 0; i < MT753X_NUM_PORTS; i++) {
|
||||
int vlan = gsw->port_entries[i].pvid;
|
||||
u16 pvid = 0;
|
||||
u32 val;
|
||||
|
||||
if (vlan < MT753X_NUM_VLANS && gsw->vlan_entries[vlan].member)
|
||||
pvid = gsw->vlan_entries[vlan].vid;
|
||||
|
||||
val = mt753x_reg_read(gsw, PPBV1(i));
|
||||
val &= ~GRP_PORT_VID_M;
|
||||
val |= pvid;
|
||||
mt753x_reg_write(gsw, PPBV1(i), val);
|
||||
}
|
||||
}
|
||||
|
||||
struct mt753x_mapping *mt753x_find_mapping(struct device_node *np)
|
||||
{
|
||||
const char *map;
|
||||
int i;
|
||||
|
||||
if (of_property_read_string(np, "mediatek,portmap", &map))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mt753x_def_mapping); i++)
|
||||
if (!strcmp(map, mt753x_def_mapping[i].name))
|
||||
return &mt753x_def_mapping[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void mt753x_apply_mapping(struct gsw_mt753x *gsw, struct mt753x_mapping *map)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < MT753X_NUM_PORTS; i++)
|
||||
gsw->port_entries[i].pvid = map->pvids[i];
|
||||
|
||||
for (i = 0; i < MT753X_NUM_VLANS; i++) {
|
||||
gsw->vlan_entries[i].member = map->members[i];
|
||||
gsw->vlan_entries[i].etags = map->etags[i];
|
||||
gsw->vlan_entries[i].vid = map->vids[i];
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2018 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#ifndef _MT753X_VLAN_H_
|
||||
#define _MT753X_VLAN_H_
|
||||
|
||||
#define MT753X_NUM_PORTS 7
|
||||
#define MT753X_NUM_VLANS 4095
|
||||
#define MT753X_MAX_VID 4095
|
||||
#define MT753X_MIN_VID 0
|
||||
|
||||
struct gsw_mt753x;
|
||||
|
||||
struct mt753x_port_entry {
|
||||
u16 pvid;
|
||||
};
|
||||
|
||||
struct mt753x_vlan_entry {
|
||||
u16 vid;
|
||||
u8 member;
|
||||
u8 etags;
|
||||
};
|
||||
|
||||
struct mt753x_mapping {
|
||||
char *name;
|
||||
u16 pvids[MT753X_NUM_PORTS];
|
||||
u8 members[MT753X_NUM_VLANS];
|
||||
u8 etags[MT753X_NUM_VLANS];
|
||||
u16 vids[MT753X_NUM_VLANS];
|
||||
};
|
||||
|
||||
extern struct mt753x_mapping mt753x_defaults[];
|
||||
|
||||
void mt753x_vlan_ctrl(struct gsw_mt753x *gsw, u32 cmd, u32 val);
|
||||
void mt753x_apply_vlan_config(struct gsw_mt753x *gsw);
|
||||
struct mt753x_mapping *mt753x_find_mapping(struct device_node *np);
|
||||
void mt753x_apply_mapping(struct gsw_mt753x *gsw, struct mt753x_mapping *map);
|
||||
#endif /* _MT753X_VLAN_H_ */
|
@ -10,7 +10,7 @@ Signed-off-by: John Crispin <john@phrozen.org>
|
||||
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -1937,7 +1937,7 @@ static struct phy_driver genphy_driver =
|
||||
@@ -1943,7 +1943,7 @@ static struct phy_driver genphy_driver =
|
||||
.config_init = genphy_config_init,
|
||||
.features = PHY_GBIT_FEATURES | SUPPORTED_MII |
|
||||
SUPPORTED_AUI | SUPPORTED_FIBRE |
|
||||
|
@ -1,36 +1,44 @@
|
||||
--- a/drivers/net/phy/mtk/mt753x/Makefile
|
||||
+++ b/drivers/net/phy/mtk/mt753x/Makefile
|
||||
@@ -7,5 +7,5 @@ obj-$(CONFIG_MT753X_GSW) += mt753x.o
|
||||
mt753x-$(CONFIG_SWCONFIG) += mt753x_swconfig.o
|
||||
@@ -8,4 +8,4 @@ mt753x-$(CONFIG_SWCONFIG) += mt753x_swco
|
||||
|
||||
mt753x-y += mt753x_mdio.o mt7530.o mt7531.o \
|
||||
- mt753x_common.o mt753x_nl.o
|
||||
+ mt753x_common.o mt753x_nl.o mt753x_phy.o
|
||||
|
||||
mt753x_common.o mt753x_vlan.o \
|
||||
- mt753x_nl.o
|
||||
+ mt753x_nl.o mt753x_phy.o
|
||||
--- a/drivers/net/phy/mtk/mt753x/mt7531.c
|
||||
+++ b/drivers/net/phy/mtk/mt753x/mt7531.c
|
||||
@@ -582,6 +582,18 @@ static void mt7531_core_pll_setup(struct
|
||||
@@ -585,6 +585,27 @@ static void mt7531_core_pll_setup(struct
|
||||
|
||||
static int mt7531_internal_phy_calibration(struct gsw_mt753x *gsw)
|
||||
{
|
||||
+ u32 i, val;
|
||||
+ int ret;
|
||||
+
|
||||
+ dev_info(gsw->dev,">>>>>>>>>>>>>>>>>>>>>>>>>>>>> START CALIBRATION:\n");
|
||||
+
|
||||
+ /* gphy value from sw path */
|
||||
+ val = gsw->mmd_read(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403);
|
||||
+ val |= GBE_EFUSE_SETTING;
|
||||
+ gsw->mmd_write(gsw, 0, PHY_DEV1F, PHY_DEV1F_REG_403, val);
|
||||
+
|
||||
+ for (i = 0; i < 5; i++) {
|
||||
+ dev_info(gsw->dev, "-------- gephy-calbration (port:%d) --------\n",
|
||||
+ i);
|
||||
+ ret = mt753x_phy_calibration(gsw, i);
|
||||
+
|
||||
+ /* set Auto-negotiation with giga extension. */
|
||||
+ gsw->mii_write(gsw, i, 0, 0x1340);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- a/drivers/net/phy/mtk/mt753x/mt753x.h
|
||||
+++ b/drivers/net/phy/mtk/mt753x/mt753x.h
|
||||
@@ -147,6 +147,8 @@ void mt753x_mmd_ind_write(struct gsw_mt7
|
||||
@@ -129,6 +129,8 @@ void mt753x_mmd_ind_write(struct gsw_mt7
|
||||
void mt753x_irq_worker(struct work_struct *work);
|
||||
void mt753x_irq_enable(struct gsw_mt753x *gsw);
|
||||
|
||||
@ -41,7 +49,7 @@
|
||||
#define MMD_CMD_S 14
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/phy/mtk/mt753x/mt753x_phy.c
|
||||
@@ -0,0 +1,947 @@
|
||||
@@ -0,0 +1,1061 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * Common part for MediaTek MT753x gigabit switch
|
||||
@ -62,6 +70,9 @@
|
||||
+{
|
||||
+ u32 phy_val;
|
||||
+ phy_val = gsw->mmd_read(gsw, port_num, dev_addr, reg_addr);
|
||||
+
|
||||
+ //printk("switch phy cl45 r %d 0x%x 0x%x = %x\n",port_num, dev_addr, reg_addr, phy_val);
|
||||
+ //switch_phy_read_cl45(port_num, dev_addr, reg_addr, &phy_val);
|
||||
+ return phy_val;
|
||||
+}
|
||||
+
|
||||
@ -70,6 +81,8 @@
|
||||
+ u32 phy_val;
|
||||
+ gsw->mmd_write(gsw, port_num, dev_addr, reg_addr, write_data);
|
||||
+ phy_val = gsw->mmd_read(gsw, port_num, dev_addr, reg_addr);
|
||||
+ //printk("switch phy cl45 w %d 0x%x 0x%x 0x%x --> read back 0x%x\n",port_num, dev_addr, reg_addr, write_data, phy_val);
|
||||
+ //switch_phy_write_cl45(port_num, dev_addr, reg_addr, write_data);
|
||||
+}
|
||||
+
|
||||
+void switch_phy_write(struct gsw_mt753x *gsw, u32 port_num, u32 reg_addr, u32 write_data){
|
||||
@ -108,7 +121,10 @@
|
||||
+{
|
||||
+ u8 all_ana_cal_status;
|
||||
+ u32 cnt, tmp_1e_17c;
|
||||
+ //tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017c, 0x0001); // da_calin_flag pull high
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
|
||||
+ //printk("delay = %d\n", delay);
|
||||
+
|
||||
+ cnt = 10000;
|
||||
+ do {
|
||||
+ udelay(delay);
|
||||
@ -122,10 +138,45 @@
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0);
|
||||
+ return all_ana_cal_status;
|
||||
+ } else {
|
||||
+ pr_info("MDC/MDIO error\n");
|
||||
+ return 0;
|
||||
+ tmp_1e_17c = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c);
|
||||
+ if ((tmp_1e_17c & 0x1) != 1) {
|
||||
+ pr_info("FIRST MDC/MDIO write error\n");
|
||||
+ pr_info("FIRST 1e_17c = %x\n", tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c));
|
||||
+
|
||||
+ }
|
||||
+ printk("re-K again\n");
|
||||
+
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
|
||||
+ cnt = 10000;
|
||||
+ do {
|
||||
+ udelay(delay);
|
||||
+ cnt--;
|
||||
+ tmp_1e_17c = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c);
|
||||
+ if ((tmp_1e_17c & 0x1) != 1) {
|
||||
+ pr_info("SECOND MDC/MDIO write error\n");
|
||||
+ pr_info("SECOND 1e_17c = %x\n", tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17c));
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0x0001);
|
||||
+ }
|
||||
+ } while ((cnt != 0) && (tmp_1e_17c == 0));
|
||||
+
|
||||
+ cnt = 10000;
|
||||
+ do {
|
||||
+ udelay(delay);
|
||||
+ cnt--;
|
||||
+ all_ana_cal_status = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x17b) & 0x1;
|
||||
+
|
||||
+ } while ((all_ana_cal_status == 0) && (cnt != 0));
|
||||
+
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x17c, 0);
|
||||
+ }
|
||||
+
|
||||
+ if(all_ana_cal_status == 0){
|
||||
+ pr_info("!!!!!!!!!!!! dev1Eh_reg17b ERROR\n");
|
||||
+ }
|
||||
+
|
||||
+ return all_ana_cal_status;
|
||||
+}
|
||||
+
|
||||
@ -141,6 +192,12 @@
|
||||
+ u8 cnt = 0;
|
||||
+ u16 dev1e_17a_tmp, dev1e_e0_tmp;
|
||||
+
|
||||
+ /* *** Iext/Rext Cal start ************ */
|
||||
+ all_ana_cal_status = ANACAL_INIT;
|
||||
+ /* analog calibration enable, Rext calibration enable */
|
||||
+ /* 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a */
|
||||
+ /* 1e_dc[0]:rg_txvos_calen */
|
||||
+ /* 1e_e1[4]:rg_cal_refsel(0:1.2V) */
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00db, 0x1110)
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1110);
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00dc, 0x0000);
|
||||
@ -148,15 +205,18 @@
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x00e1, 0x0000);
|
||||
+ //tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e1, 0x10);
|
||||
+
|
||||
+ rg_zcal_ctrl = 0x20;
|
||||
+ dev1e_e0_ana_cal_r5 = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0xe0);
|
||||
+ rg_zcal_ctrl = 0x20;/* start with 0 dB */
|
||||
+ dev1e_e0_ana_cal_r5 = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0xe0); // get default value
|
||||
+ /* 1e_e0[5:0]:rg_zcal_ctrl */
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0xe0, rg_zcal_ctrl);
|
||||
+ all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr);/* delay 20 usec */
|
||||
+
|
||||
+ if (all_ana_cal_status == 0) {
|
||||
+ all_ana_cal_status = ANACAL_ERROR;
|
||||
+ printk(" GE Rext AnaCal ERROR init! \r\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ /* 1e_17a[8]:ad_cal_comp_out */
|
||||
+ ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a) >> 8) & 0x1;
|
||||
+ if (ad_cal_comp_out_init == 1)
|
||||
+ calibration_polarity = -1;
|
||||
@ -180,7 +240,7 @@
|
||||
+ dev1e_17a_tmp = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a);
|
||||
+ dev1e_e0_tmp = tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0xe0);
|
||||
+ if ((rg_zcal_ctrl == 0x3F) || (rg_zcal_ctrl == 0x00)) {
|
||||
+ all_ana_cal_status = ANACAL_SATURATION;
|
||||
+ all_ana_cal_status = ANACAL_SATURATION; /* need to FT(IC fail?) */
|
||||
+ printk(" GE Rext AnaCal Saturation! \r\n");
|
||||
+ rg_zcal_ctrl = 0x20; /* 0 dB */
|
||||
+ }
|
||||
@ -188,12 +248,13 @@
|
||||
+ }
|
||||
+
|
||||
+ if (all_ana_cal_status == ANACAL_ERROR) {
|
||||
+ rg_zcal_ctrl = 0x20;
|
||||
+ rg_zcal_ctrl = 0x20; /* 0 dB */
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
|
||||
+ } else if(all_ana_cal_status == ANACAL_FINISH){
|
||||
+ //tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, ((rg_zcal_ctrl << 8) | rg_zcal_ctrl));
|
||||
+ printk("0x1e-e0 = %x\n", tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x00e0));
|
||||
+ /* **** 1f_115[2:0] = rg_zcal_ctrl[5:3] // Mog review */
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1f, 0x0115, ((rg_zcal_ctrl & 0x3f) >> 3));
|
||||
+ printk("0x1f-115 = %x\n", tc_phy_read_dev_reg(gsw, PHY0, 0x1f, 0x115));
|
||||
+ printk(" GE Rext AnaCal Done! (%d)(0x%x) \r\n", cnt, rg_zcal_ctrl);
|
||||
@ -215,38 +276,38 @@
|
||||
+ u16 dev1e_e0_ana_cal_r5;
|
||||
+ int calibration_polarity;
|
||||
+ u8 cnt = 0;
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1100);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1100); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000); // 1e_dc[0]:rg_txvos_calen
|
||||
+
|
||||
+ for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++) {
|
||||
+ rg_zcal_ctrl = 0x20;
|
||||
+ rg_zcal_ctrl = 0x20; // start with 0 dB
|
||||
+ dev1e_e0_ana_cal_r5 = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x00e0) & (~0x003f));
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl)); // 1e_e0[5:0]:rg_zcal_ctrl
|
||||
+ if(calibration_pair == ANACAL_PAIR_A)
|
||||
+ {
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1101);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1101); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);
|
||||
+ //printk("R50 pair A 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x00dc));
|
||||
+
|
||||
+ }
|
||||
+ else if(calibration_pair == ANACAL_PAIR_B)
|
||||
+ {
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x1000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x1000); // 1e_dc[12]:rg_zcalen_b
|
||||
+ //printk("R50 pair B 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x00db),tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x00dc));
|
||||
+
|
||||
+ }
|
||||
+ else if(calibration_pair == ANACAL_PAIR_C)
|
||||
+ {
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0100);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0100); // 1e_dc[8]:rg_zcalen_c
|
||||
+ //printk("R50 pair C 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x00dc));
|
||||
+
|
||||
+ }
|
||||
+ else // if(calibration_pair == ANACAL_PAIR_D)
|
||||
+ {
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0010);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x1100); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0010); // 1e_dc[4]:rg_zcalen_d
|
||||
+ //printk("R50 pair D 1e_db=%x 1e_db=%x\n", tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x00db), tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x00dc));
|
||||
+
|
||||
+ }
|
||||
@ -259,7 +320,7 @@
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a)>>8) & 0x1;
|
||||
+ ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a)>>8) & 0x1; // 1e_17a[8]:ad_cal_comp_out
|
||||
+ if(ad_cal_comp_out_init == 1)
|
||||
+ calibration_polarity = -1;
|
||||
+ else
|
||||
@ -293,11 +354,11 @@
|
||||
+ }
|
||||
+
|
||||
+ if(all_ana_cal_status == ANACAL_ERROR) {
|
||||
+ rg_zcal_ctrl = 0x20;
|
||||
+ rg_zcal_ctrl = 0x20; // 0 dB
|
||||
+ //tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00e0, (dev1e_e0_ana_cal_r5 | rg_zcal_ctrl));
|
||||
+ }
|
||||
+ else {
|
||||
+ rg_zcal_ctrl = MT753x_ZCAL_TO_R50ohm_GE_TBL_100[rg_zcal_ctrl - 9];
|
||||
+ rg_zcal_ctrl = MT753x_ZCAL_TO_R50ohm_GE_TBL_100[rg_zcal_ctrl - 9]; // wait Mog zcal/r50 mapping table
|
||||
+ printk( " GE R50 AnaCal Done! (%d) (0x%x)(0x%x) \r\n", cnt, rg_zcal_ctrl, (rg_zcal_ctrl|0x80));
|
||||
+ }
|
||||
+
|
||||
@ -305,7 +366,7 @@
|
||||
+ ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0174) & (~0x7f00);
|
||||
+ //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0174);
|
||||
+ //printk( " GE-a 1e_174(0x%x)(0x%x), 1e_175(0x%x) \r\n", tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0174), ad_cal_comp_out_init, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0175));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0174, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<8)&0xff00) | 0x8000)));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0174, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<8)&0xff00) | 0x8000))); // 1e_174[15:8]
|
||||
+ //printk( " GE-a 1e_174(0x%x), 1e_175(0x%x) \r\n", tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0175));
|
||||
+ }
|
||||
+ else if(calibration_pair == ANACAL_PAIR_B) {
|
||||
@ -313,18 +374,18 @@
|
||||
+ //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0174);
|
||||
+ //printk( " GE-b 1e_174(0x%x)(0x%x), 1e_175(0x%x) \r\n", tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0174), ad_cal_comp_out_init, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0175));
|
||||
+
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0174, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<0)&0x00ff) | 0x0080)));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0174, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<0)&0x00ff) | 0x0080))); // 1e_174[7:0]
|
||||
+ //printk( " GE-b 1e_174(0x%x), 1e_175(0x%x) \r\n", tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0175));
|
||||
+ }
|
||||
+ else if(calibration_pair == ANACAL_PAIR_C) {
|
||||
+ ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0175) & (~0x7f00);
|
||||
+ //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0175);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0175, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<8)&0xff00) | 0x8000)));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0175, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<8)&0xff00) | 0x8000))); // 1e_175[15:8]
|
||||
+ //printk( " GE-c 1e_174(0x%x), 1e_175(0x%x) \r\n", tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0175));
|
||||
+ } else {// if(calibration_pair == ANACAL_PAIR_D)
|
||||
+ ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0175) & (~0x007f);
|
||||
+ //ad_cal_comp_out_init = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0175);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0175, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<0)&0x00ff) | 0x0080)));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0175, (ad_cal_comp_out_init | (((rg_zcal_ctrl<<0)&0x00ff) | 0x0080))); // 1e_175[7:0]
|
||||
+ //printk( " GE-d 1e_174(0x%x), 1e_175(0x%x) \r\n", tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0174), tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0175));
|
||||
+ }
|
||||
+ //tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00e0, ((rg_zcal_ctrl<<8)|rg_zcal_ctrl));
|
||||
@ -345,10 +406,11 @@
|
||||
+ u8 tx_offset_reg_shift, tabl_idx, i;
|
||||
+ u8 cnt = 0;
|
||||
+ u16 tx_offset_reg, reg_temp, cal_temp;
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0100);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0001);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0096, 0x8000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0xf808);
|
||||
+ //switch_phy_write(phyaddr, R0, 0x2100);//harry tmp
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0100); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0001); // 1e_dc[0]:rg_txvos_calen
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0096, 0x8000); // 1e_96[15]:bypass_tx_offset_cal, Hw bypass, Fw cal
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0xf808); // 1e_3e
|
||||
+ for(i = 0; i <= 4; i++)
|
||||
+ tc_phy_write_dev_reg(gsw, i, 0x1e, 0x00dd, 0x0000);
|
||||
+ for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++)
|
||||
@ -358,45 +420,45 @@
|
||||
+
|
||||
+ if(calibration_pair == ANACAL_PAIR_A) {
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x145, 0x5010);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x1000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_0V));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_0V));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x1000); // 1e_dd[12]:rg_txg_calen_a
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_0V)); // 1e_17d:dac_in0_a
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_0V)); // 1e_181:dac_in1_a
|
||||
+ //printk("tx offset pairA 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
|
||||
+ reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0172) & (~0x3f00));
|
||||
+ tx_offset_reg_shift = 8;
|
||||
+ tx_offset_reg_shift = 8; // 1e_172[13:8]
|
||||
+ tx_offset_reg = 0x0172;
|
||||
+
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
|
||||
+ } else if(calibration_pair == ANACAL_PAIR_B) {
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x1e, 0x145, 0x5018);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0100);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_0V));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_0V));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0100); // 1e_dd[8]:rg_txg_calen_b
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_0V)); // 1e_17e:dac_in0_b
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_0V)); // 1e_182:dac_in1_b
|
||||
+ //printk("tx offset pairB 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
|
||||
+ reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0172) & (~0x003f));
|
||||
+ tx_offset_reg_shift = 0;
|
||||
+ tx_offset_reg_shift = 0; // 1e_172[5:0]
|
||||
+ tx_offset_reg = 0x0172;
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
|
||||
+ } else if(calibration_pair == ANACAL_PAIR_C) {
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0010);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_0V));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_0V));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0010); // 1e_dd[4]:rg_txg_calen_c
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_0V)); // 1e_17f:dac_in0_c
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_0V)); // 1e_183:dac_in1_c
|
||||
+ reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0173) & (~0x3f00));
|
||||
+ //printk("tx offset pairC 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
|
||||
+ tx_offset_reg_shift = 8;
|
||||
+ tx_offset_reg_shift = 8; // 1e_173[13:8]
|
||||
+ tx_offset_reg = 0x0173;
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
|
||||
+ } else {// if(calibration_pair == ANACAL_PAIR_D)
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0001);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_0V));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_0V));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0001); // 1e_dd[0]:rg_txg_calen_d
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_0V)); // 1e_180:dac_in0_d
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_0V)); // 1e_184:dac_in1_d
|
||||
+ //printk("tx offset pairD 1e_dd = %x, 1e_17d=%x, 1e_181=%x\n", tc_phy_read_dev_reg(phyaddr, 0x1e, 0x00dd), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x017d), tc_phy_read_dev_reg(phyaddr, 0x1e, 0x0181));
|
||||
+ reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x0173) & (~0x003f));
|
||||
+ tx_offset_reg_shift = 0;
|
||||
+ tx_offset_reg_shift = 0; // 1e_173[5:0]
|
||||
+ tx_offset_reg = 0x0173;
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
|
||||
+ }
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift)));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, tx_offset_reg, (reg_temp|(tx_offset_temp<<tx_offset_reg_shift))); // 1e_172, 1e_173
|
||||
+ all_ana_cal_status = all_ge_ana_cal_wait(gsw, delay, phyaddr); // delay 20 usec
|
||||
+ if(all_ana_cal_status == 0) {
|
||||
+ all_ana_cal_status = ANACAL_ERROR;
|
||||
@ -404,7 +466,7 @@
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a)>>8) & 0x1;
|
||||
+ ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a)>>8) & 0x1; // 1e_17a[8]:ad_cal_comp_out
|
||||
+ if(ad_cal_comp_out_init == 1)
|
||||
+ calibration_polarity = 1;
|
||||
+ else
|
||||
@ -431,7 +493,7 @@
|
||||
+ all_ana_cal_status = ANACAL_FINISH;
|
||||
+ } else {
|
||||
+ if((tabl_idx == 0)||(tabl_idx == 0x3f)) {
|
||||
+ all_ana_cal_status = ANACAL_SATURATION;
|
||||
+ all_ana_cal_status = ANACAL_SATURATION; // need to FT
|
||||
+ printk( " GE Tx offset AnaCal Saturation! \r\n");
|
||||
+ }
|
||||
+ }
|
||||
@ -454,12 +516,12 @@
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, 0x0000);
|
||||
+
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0000); // disable analog calibration circuit
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000); // disable Tx offset calibration circuit
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000); // disable analog calibration circuit
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000); // disable Tx offset calibration circuit
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0x0000); // disable Tx VLD force mode
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0000); // disable Tx offset/amplitude calibration circuit
|
||||
+}
|
||||
+
|
||||
+int ge_cal_tx_amp(struct gsw_mt753x *gsw, u8 phyaddr, u32 delay)
|
||||
@ -470,11 +532,11 @@
|
||||
+ u32 tx_amp_reg_shift;
|
||||
+ u16 reg_temp;
|
||||
+ u32 tx_amp_temp, tx_amp_reg, cnt=0, tx_amp_reg_100;
|
||||
+ u32 reg_backup, reg_tmp;
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1100);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0001);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e1, 0x0010);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0xf808);
|
||||
+ u32 debug_tmp, reg_backup, reg_tmp;
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x1100); // 1e_db[12]:rg_cal_ckinv, [8]:rg_ana_calen, [4]:rg_rext_calen, [0]:rg_zcalen_a
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0001); // 1e_dc[0]:rg_txvos_calen
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00e1, 0x0010); // 1e_e1[4]:select 1V
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0xf808); // 1e_3e:enable Tx VLD
|
||||
+
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x11, 0xff00);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27a, 0x33);
|
||||
@ -483,36 +545,36 @@
|
||||
+ for(i = 0; i <= 4; i++)
|
||||
+ tc_phy_write_dev_reg(gsw, i, 0x1e, 0x00dd, 0x0000);
|
||||
+ for(calibration_pair = ANACAL_PAIR_A; calibration_pair <= ANACAL_PAIR_D; calibration_pair ++) {
|
||||
+ tx_amp_temp = 0x20;
|
||||
+ tx_amp_temp = 0x20; // start with 0 dB
|
||||
+
|
||||
+ if(calibration_pair == ANACAL_PAIR_A) {
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x1000); // 1e_dd[12]
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_2V)); // 1e_17d
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_2V)); // 1e_181
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x1000); // 1e_dd[12]:tx_a amp calibration enable
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017d, (0x8000|DAC_IN_2V)); // 1e_17d:dac_in0_a
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0181, (0x8000|DAC_IN_2V)); // 1e_181:dac_in1_a
|
||||
+ reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x012) & (~0xfc00));
|
||||
+ tx_amp_reg_shift = 10; // 1e_12[15:10]
|
||||
+ tx_amp_reg = 0x12;
|
||||
+ tx_amp_reg_100 = 0x16;
|
||||
+ } else if(calibration_pair == ANACAL_PAIR_B) {
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0100); // 1e_dd[8]
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_2V)); // 1e_17e
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_2V)); // 1e_182
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0100); // 1e_dd[8]:tx_b amp calibration enable
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017e, (0x8000|DAC_IN_2V)); // 1e_17e:dac_in0_b
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0182, (0x8000|DAC_IN_2V)); // 1e_182:dac_in1_b
|
||||
+ reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x017) & (~0x3f00));
|
||||
+ tx_amp_reg_shift = 8; // 1e_17[13:8]
|
||||
+ tx_amp_reg = 0x17;
|
||||
+ tx_amp_reg_100 = 0x18;
|
||||
+ } else if(calibration_pair == ANACAL_PAIR_C) {
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0010); // 1e_dd[4]
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_2V)); // 1e_17f
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_2V)); // 1e_183
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0010); // 1e_dd[4]:tx_c amp calibration enable
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x017f, (0x8000|DAC_IN_2V)); // 1e_17f:dac_in0_c
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0183, (0x8000|DAC_IN_2V)); // 1e_183:dac_in1_c
|
||||
+ reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x019) & (~0x3f00));
|
||||
+ tx_amp_reg_shift = 8; // 1e_19[13:8]
|
||||
+ tx_amp_reg = 0x19;
|
||||
+ tx_amp_reg_100 = 0x20;
|
||||
+ } else { //if(calibration_pair == ANACAL_PAIR_D)
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0001); // 1e_dd[0]
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_2V)); // 1e_180
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_2V)); // 1e_184
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0001); // 1e_dd[0]:tx_d amp calibration enable
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0180, (0x8000|DAC_IN_2V)); // 1e_180:dac_in0_d
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x0184, (0x8000|DAC_IN_2V)); // 1e_184:dac_in1_d
|
||||
+ reg_temp = (tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x021) & (~0x3f00));
|
||||
+ tx_amp_reg_shift = 8; // 1e_21[13:8]
|
||||
+ tx_amp_reg = 0x21;
|
||||
@ -527,7 +589,7 @@
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a)>>8) & 0x1; // 1e_17a[8]
|
||||
+ ad_cal_comp_out_init = (tc_phy_read_dev_reg(gsw, PHY0, 0x1e, 0x017a)>>8) & 0x1; // 1e_17a[8]:ad_cal_comp_out
|
||||
+ if(ad_cal_comp_out_init == 1)
|
||||
+ calibration_polarity = -1;
|
||||
+ else
|
||||
@ -685,6 +747,7 @@
|
||||
+ reg_backup |= ((reg_tmp << 10) | (reg_tmp << 0));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x12, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x12);
|
||||
+ //printk("PORT[%d] 1e.012 = %x (OFFSET_1000M_PAIR_A)\n", phyaddr, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x16);
|
||||
+ reg_tmp = ((reg_backup & 0x3f) >> 0);
|
||||
+ reg_tmp -= 8;
|
||||
@ -692,6 +755,7 @@
|
||||
+ reg_backup |= (reg_tmp << 0);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x16, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x16);
|
||||
+ //printk("PORT[%d] 1e.016 = %x (OFFSET_TESTMODE_1000M_PAIR_A)\n", phyaddr, reg_backup);
|
||||
+ }
|
||||
+ else if(calibration_pair == ANACAL_PAIR_B){
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x17);
|
||||
@ -701,6 +765,7 @@
|
||||
+ reg_backup |= ((reg_tmp << 8) | (reg_tmp << 0));
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x17, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x17);
|
||||
+ //printk("PORT[%d] 1e.017 = %x (OFFSET_1000M_PAIR_B)\n", phyaddr, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x18);
|
||||
+ reg_tmp = ((reg_backup & 0x3f) >> 0);
|
||||
+ reg_tmp -= 8;
|
||||
@ -708,6 +773,7 @@
|
||||
+ reg_backup |= (reg_tmp << 0);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x18);
|
||||
+ //printk("PORT[%d] 1e.018 = %x (OFFSET_TESTMODE_1000M_PAIR_B)\n", phyaddr, reg_backup);
|
||||
+ }
|
||||
+ else if(calibration_pair == ANACAL_PAIR_C){
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x19);
|
||||
@ -717,6 +783,7 @@
|
||||
+ reg_backup |= (reg_tmp << 8);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x19, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x19);
|
||||
+ //printk("PORT[%d] 1e.019 = %x (OFFSET_1000M_PAIR_C)\n", phyaddr, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x20);
|
||||
+ reg_tmp = ((reg_backup & 0x3f) >> 0);
|
||||
+ reg_tmp -= 8;
|
||||
@ -724,6 +791,7 @@
|
||||
+ reg_backup |= (reg_tmp << 0);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x20, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x20);
|
||||
+ //printk("PORT[%d] 1e.020 = %x (OFFSET_TESTMODE_1000M_PAIR_C)\n", phyaddr, reg_backup);
|
||||
+ }
|
||||
+ else if(calibration_pair == ANACAL_PAIR_D){
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x21);
|
||||
@ -733,6 +801,7 @@
|
||||
+ reg_backup |= (reg_tmp << 8);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x21, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x21);
|
||||
+ //printk("PORT[%d] 1e.021 = %x (OFFSET_1000M_PAIR_D)\n", phyaddr, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x22);
|
||||
+ reg_tmp = ((reg_backup & 0x3f) >> 0);
|
||||
+ reg_tmp -= 8;
|
||||
@ -740,12 +809,45 @@
|
||||
+ reg_backup |= (reg_tmp << 0);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x22, reg_backup);
|
||||
+ reg_backup = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x22);
|
||||
+ //printk("PORT[%d] 1e.022 = %x (OFFSET_TESTMODE_1000M_PAIR_D)\n", phyaddr, reg_backup);
|
||||
+ }
|
||||
+
|
||||
+ if (calibration_pair == ANACAL_PAIR_A){
|
||||
+ //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
|
||||
+ debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x12);
|
||||
+ //printk("1e.012 = 0x%x\n", debug_tmp);
|
||||
+ debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x16);
|
||||
+ //printk("1e.016 = 0x%x\n", debug_tmp);
|
||||
+ }
|
||||
+
|
||||
+ else if(calibration_pair == ANACAL_PAIR_B){
|
||||
+ //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
|
||||
+ debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x17);
|
||||
+ //printk("1e.017 = 0x%x\n", debug_tmp);
|
||||
+ debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x18);
|
||||
+ //printk("1e.018 = 0x%x\n", debug_tmp);
|
||||
+ }
|
||||
+ else if(calibration_pair == ANACAL_PAIR_C){
|
||||
+ //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
|
||||
+ debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x19);
|
||||
+ //printk("1e.019 = 0x%x\n", debug_tmp);
|
||||
+ debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x20);
|
||||
+ //printk("1e.020 = 0x%x\n", debug_tmp);
|
||||
+ }
|
||||
+ else if(calibration_pair == ANACAL_PAIR_D){
|
||||
+ //printk("PORT (%d) TX_AMP PAIR (A) FINAL CALIBRATION RESULT\n", phyaddr);
|
||||
+ debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x21);
|
||||
+ //printk("1e.021 = 0x%x\n", debug_tmp);
|
||||
+ debug_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x22);
|
||||
+ //printk("1e.022 = 0x%x\n", debug_tmp);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ printk( " GE Tx amp AnaCal Done! (pair-%d)(1e_%x = 0x%x)\n", calibration_pair, tx_amp_reg, tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, tx_amp_reg));
|
||||
+
|
||||
+ } else {
|
||||
+ if((tx_amp_temp == 0x3f)||(tx_amp_temp == 0x00)) {
|
||||
+ all_ana_cal_status = ANACAL_SATURATION;
|
||||
+ all_ana_cal_status = ANACAL_SATURATION; // need to FT
|
||||
+ printk( " GE Tx amp AnaCal Saturation! \r\n");
|
||||
+ }
|
||||
+ }
|
||||
@ -767,11 +869,11 @@
|
||||
+
|
||||
+ /* disable analog calibration circuit */
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00db, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0000);
|
||||
+ tc_phy_write_dev_reg(gsw, PHY0, 0x1e, 0x00dc, 0x0000); // disable Tx offset calibration circuit
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00db, 0x0000); // disable analog calibration circuit
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dc, 0x0000); // disable Tx offset calibration circuit
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x003e, 0x0000); // disable Tx VLD force mode
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x00dd, 0x0000); // disable Tx offset/amplitude calibration circuit
|
||||
+
|
||||
+
|
||||
+
|
||||
@ -788,18 +890,28 @@
|
||||
+ u32 reg_tmp,reg_tmp0, reg_tmp1, i;
|
||||
+ u32 CALDLY = 40;
|
||||
+ int ret;
|
||||
+ /* set [12]AN disable, [8]full duplex, [13/6]1000Mbps */
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x0, 0x0140);
|
||||
+ switch_phy_write(gsw, phyaddr, R0, 0x140);
|
||||
+
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x145, 0x1010);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, RG_185, 0);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x100, 0xc000);
|
||||
+ //tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x403, 0x1099);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x145, 0x1010);/* fix mdi */
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, RG_185, 0);/* disable tx slew control */
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x100, 0xc000);/* BG voltage output */
|
||||
+ //tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x403, 0x1099); //bypass efuse
|
||||
+
|
||||
+#if (1)
|
||||
+ // 1f_27c[12:8] cr_da_tx_i2mpb_10m Trimming TX bias setup(@10M)
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27c, 0x1f1f);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x27c, 0x3300);
|
||||
+
|
||||
+ reg_tmp1 = tc_phy_read_dev_reg(gsw, PHY0, 0x1f, 0x27c);
|
||||
+ //dev1Fh_reg273h TXVLD DA register - Adjust voltage mode TX amplitude.
|
||||
+ //tc_phy_write_dev_reg(phyaddr, 0x1f, 0x273, 0);
|
||||
+ //tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x273, 0x1000);
|
||||
+ //reg_tmp1 = tc_phy_read_dev_reg(gsw, phyaddr, 0x1f, 0x273);
|
||||
+ //printk("reg_tmp1273 = %x\n", reg_tmp1);
|
||||
+ /*1e_11 TX overshoot Enable (PAIR A/B/C/D) in gbe mode*/
|
||||
+
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x11);
|
||||
+ reg_tmp = reg_tmp | (0xf << 12);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x11, reg_tmp);
|
||||
@ -856,11 +968,13 @@
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18e, 0x0001);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x18f, 0x0001);
|
||||
+
|
||||
+ /*da_tx_bias1_b_tx_standby = 5'b10 (dev1eh_reg3aah[12:8])*/
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x3aa);
|
||||
+ reg_tmp = reg_tmp & ~(0x1f00);
|
||||
+ reg_tmp = reg_tmp | 0x2 << 8;
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x3aa, reg_tmp);
|
||||
+
|
||||
+ /*da_tx_bias1_a_tx_standby = 5'b10 (dev1eh_reg3a9h[4:0])*/
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1e, 0x3a9);
|
||||
+ reg_tmp = reg_tmp & ~(0x1f);
|
||||
+ reg_tmp = reg_tmp | 0x2;
|
||||
@ -872,7 +986,7 @@
|
||||
+{
|
||||
+ u32 reg_tmp1;
|
||||
+
|
||||
+ //pr_info("PORT %d RX_DC_OFFSET\n", phyaddr);
|
||||
+ pr_info("PORT %d RX_DC_OFFSET\n", phyaddr);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x96, 0x8000);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x37, 0x3);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1e, 0x107, 0x4000);
|
||||
@ -892,11 +1006,13 @@
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x114f);
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1f, 0x1a);
|
||||
+ reg_tmp = reg_tmp & 0xff;
|
||||
+ pr_info("before pairA output = %x\n", reg_tmp);
|
||||
+ udelay(40);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1142);
|
||||
+ udelay(40);
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1f, 0x1a);
|
||||
+ reg_tmp = reg_tmp & 0xff;
|
||||
+ pr_info("after pairA output = %x\n", reg_tmp);
|
||||
+ if ((reg_tmp & 0x80) != 0)
|
||||
+ reg_tmp = (~reg_tmp) + 1;
|
||||
+ if ((reg_tmp & 0xff) >4)
|
||||
@ -911,11 +1027,13 @@
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1151);
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1f, 0x1a);
|
||||
+ reg_tmp = reg_tmp & 0xff;
|
||||
+ pr_info("before pairB output = %x\n", reg_tmp);
|
||||
+ udelay(40);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1143);
|
||||
+ udelay(40);
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1f, 0x1a);
|
||||
+ reg_tmp = reg_tmp & 0xff;
|
||||
+ pr_info("after pairB output = %x\n", reg_tmp);
|
||||
+ if ((reg_tmp & 0x80) != 0)
|
||||
+ reg_tmp = (~reg_tmp) + 1;
|
||||
+ if ((reg_tmp & 0xff) >4)
|
||||
@ -930,11 +1048,13 @@
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1153);
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1f, 0x1a);
|
||||
+ reg_tmp = reg_tmp & 0xff;
|
||||
+ pr_info("before pairC output = %x\n", reg_tmp);
|
||||
+ udelay(40);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1144);
|
||||
+ udelay(40);
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1f, 0x1a);
|
||||
+ reg_tmp = reg_tmp & 0xff;
|
||||
+ pr_info("after pairC output = %x\n", reg_tmp);
|
||||
+ if ((reg_tmp & 0x80) != 0)
|
||||
+ reg_tmp = (~reg_tmp) + 1;
|
||||
+ if ((reg_tmp & 0xff) >4)
|
||||
@ -949,11 +1069,13 @@
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1155);
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1f, 0x1a);
|
||||
+ reg_tmp = reg_tmp & 0xff;
|
||||
+ pr_info("before pairD output = %x\n", reg_tmp);
|
||||
+ udelay(40);
|
||||
+ tc_phy_write_dev_reg(gsw, phyaddr, 0x1f, 0x15, (phyaddr << 13) | 0x1145);
|
||||
+ udelay(40);
|
||||
+ reg_tmp = tc_phy_read_dev_reg(gsw, phyaddr, 0x1f, 0x1a);
|
||||
+ reg_tmp = reg_tmp & 0xff;
|
||||
+ pr_info("after pairD output = %x\n", reg_tmp);
|
||||
+ if ((reg_tmp & 0x80) != 0)
|
||||
+ reg_tmp = (~reg_tmp) + 1;
|
||||
+ if ((reg_tmp & 0xff) >4)
|
||||
|
@ -0,0 +1,534 @@
|
||||
diff -urN a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
|
||||
--- a/drivers/clk/clk-devres.c 2019-08-29 16:59:26.540010395 +0800
|
||||
+++ b/drivers/clk/clk-devres.c 2019-08-29 17:02:09.215924786 +0800
|
||||
@@ -34,6 +34,17 @@
|
||||
}
|
||||
EXPORT_SYMBOL(devm_clk_get);
|
||||
|
||||
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
|
||||
+{
|
||||
+ struct clk *clk = devm_clk_get(dev, id);
|
||||
+
|
||||
+ if (clk == ERR_PTR(-ENOENT))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return clk;
|
||||
+}
|
||||
+EXPORT_SYMBOL(devm_clk_get_optional);
|
||||
+
|
||||
struct clk_bulk_devres {
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
diff -urN a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
|
||||
--- a/drivers/pci/controller/pcie-mediatek.c 2019-08-29 16:59:10.520410188 +0800
|
||||
+++ b/drivers/pci/controller/pcie-mediatek.c 2019-08-29 17:01:58.340199243 +0800
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/msi.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_pci.h>
|
||||
#include <linux/of_platform.h>
|
||||
@@ -162,6 +163,7 @@
|
||||
* @phy: pointer to PHY control block
|
||||
* @lane: lane count
|
||||
* @slot: port slot
|
||||
+ * @irq: GIC irq
|
||||
* @irq_domain: legacy INTx IRQ domain
|
||||
* @inner_domain: inner IRQ domain
|
||||
* @msi_domain: MSI IRQ domain
|
||||
@@ -182,6 +184,7 @@
|
||||
struct phy *phy;
|
||||
u32 lane;
|
||||
u32 slot;
|
||||
+ int irq;
|
||||
struct irq_domain *irq_domain;
|
||||
struct irq_domain *inner_domain;
|
||||
struct irq_domain *msi_domain;
|
||||
@@ -225,10 +228,8 @@
|
||||
|
||||
clk_disable_unprepare(pcie->free_ck);
|
||||
|
||||
- if (dev->pm_domain) {
|
||||
- pm_runtime_put_sync(dev);
|
||||
- pm_runtime_disable(dev);
|
||||
- }
|
||||
+ pm_runtime_put_sync(dev);
|
||||
+ pm_runtime_disable(dev);
|
||||
}
|
||||
|
||||
static void mtk_pcie_port_free(struct mtk_pcie_port *port)
|
||||
@@ -394,75 +395,6 @@
|
||||
.write = mtk_pcie_config_write,
|
||||
};
|
||||
|
||||
-static int mtk_pcie_startup_port_v2(struct mtk_pcie_port *port)
|
||||
-{
|
||||
- struct mtk_pcie *pcie = port->pcie;
|
||||
- struct resource *mem = &pcie->mem;
|
||||
- const struct mtk_pcie_soc *soc = port->pcie->soc;
|
||||
- u32 val;
|
||||
- size_t size;
|
||||
- int err;
|
||||
-
|
||||
- /* MT7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
|
||||
- if (pcie->base) {
|
||||
- val = readl(pcie->base + PCIE_SYS_CFG_V2);
|
||||
- val |= PCIE_CSR_LTSSM_EN(port->slot) |
|
||||
- PCIE_CSR_ASPM_L1_EN(port->slot);
|
||||
- writel(val, pcie->base + PCIE_SYS_CFG_V2);
|
||||
- }
|
||||
-
|
||||
- /* Assert all reset signals */
|
||||
- writel(0, port->base + PCIE_RST_CTRL);
|
||||
-
|
||||
- /*
|
||||
- * Enable PCIe link down reset, if link status changed from link up to
|
||||
- * link down, this will reset MAC control registers and configuration
|
||||
- * space.
|
||||
- */
|
||||
- writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
|
||||
-
|
||||
- /* De-assert PHY, PE, PIPE, MAC and configuration reset */
|
||||
- val = readl(port->base + PCIE_RST_CTRL);
|
||||
- val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
|
||||
- PCIE_MAC_SRSTB | PCIE_CRSTB;
|
||||
- writel(val, port->base + PCIE_RST_CTRL);
|
||||
-
|
||||
- /* Set up vendor ID and class code */
|
||||
- if (soc->need_fix_class_id) {
|
||||
- val = PCI_VENDOR_ID_MEDIATEK;
|
||||
- writew(val, port->base + PCIE_CONF_VEND_ID);
|
||||
-
|
||||
- val = PCI_CLASS_BRIDGE_HOST;
|
||||
- writew(val, port->base + PCIE_CONF_CLASS_ID);
|
||||
- }
|
||||
-
|
||||
- /* 100ms timeout value should be enough for Gen1/2 training */
|
||||
- err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
|
||||
- !!(val & PCIE_PORT_LINKUP_V2), 20,
|
||||
- 100 * USEC_PER_MSEC);
|
||||
- if (err)
|
||||
- return -ETIMEDOUT;
|
||||
-
|
||||
- /* Set INTx mask */
|
||||
- val = readl(port->base + PCIE_INT_MASK);
|
||||
- val &= ~INTX_MASK;
|
||||
- writel(val, port->base + PCIE_INT_MASK);
|
||||
-
|
||||
- /* Set AHB to PCIe translation windows */
|
||||
- size = mem->end - mem->start;
|
||||
- val = lower_32_bits(mem->start) | AHB2PCIE_SIZE(fls(size));
|
||||
- writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
|
||||
-
|
||||
- val = upper_32_bits(mem->start);
|
||||
- writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
|
||||
-
|
||||
- /* Set PCIe to AXI translation memory space.*/
|
||||
- val = fls(0xffffffff) | WIN_ENABLE;
|
||||
- writel(val, port->base + PCIE_AXI_WINDOW0);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static void mtk_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
|
||||
{
|
||||
struct mtk_pcie_port *port = irq_data_get_irq_chip_data(data);
|
||||
@@ -601,6 +533,27 @@
|
||||
writel(val, port->base + PCIE_INT_MASK);
|
||||
}
|
||||
|
||||
+static void mtk_pcie_irq_teardown(struct mtk_pcie *pcie)
|
||||
+{
|
||||
+ struct mtk_pcie_port *port, *tmp;
|
||||
+
|
||||
+ list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
|
||||
+ irq_set_chained_handler_and_data(port->irq, NULL, NULL);
|
||||
+
|
||||
+ if (port->irq_domain)
|
||||
+ irq_domain_remove(port->irq_domain);
|
||||
+
|
||||
+ if (IS_ENABLED(CONFIG_PCI_MSI)) {
|
||||
+ if (port->msi_domain)
|
||||
+ irq_domain_remove(port->msi_domain);
|
||||
+ if (port->inner_domain)
|
||||
+ irq_domain_remove(port->inner_domain);
|
||||
+ }
|
||||
+
|
||||
+ irq_dispose_mapping(port->irq);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int mtk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
@@ -630,6 +583,7 @@
|
||||
|
||||
port->irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
|
||||
&intx_domain_ops, port);
|
||||
+ of_node_put(pcie_intc_node);
|
||||
if (!port->irq_domain) {
|
||||
dev_err(dev, "failed to get INTx IRQ domain\n");
|
||||
return -ENODEV;
|
||||
@@ -639,8 +593,6 @@
|
||||
ret = mtk_pcie_allocate_msi_domains(port);
|
||||
if (ret)
|
||||
return ret;
|
||||
-
|
||||
- mtk_pcie_enable_msi(port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -693,7 +645,7 @@
|
||||
struct mtk_pcie *pcie = port->pcie;
|
||||
struct device *dev = pcie->dev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
- int err, irq;
|
||||
+ int err;
|
||||
|
||||
err = mtk_pcie_init_irq_domain(port, node);
|
||||
if (err) {
|
||||
@@ -701,8 +653,81 @@
|
||||
return err;
|
||||
}
|
||||
|
||||
- irq = platform_get_irq(pdev, port->slot);
|
||||
- irq_set_chained_handler_and_data(irq, mtk_pcie_intr_handler, port);
|
||||
+ port->irq = platform_get_irq(pdev, port->slot);
|
||||
+ irq_set_chained_handler_and_data(port->irq,
|
||||
+ mtk_pcie_intr_handler, port);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mtk_pcie_startup_port_v2(struct mtk_pcie_port *port)
|
||||
+{
|
||||
+ struct mtk_pcie *pcie = port->pcie;
|
||||
+ struct resource *mem = &pcie->mem;
|
||||
+ const struct mtk_pcie_soc *soc = port->pcie->soc;
|
||||
+ u32 val;
|
||||
+ size_t size;
|
||||
+ int err;
|
||||
+
|
||||
+ /* MT7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
|
||||
+ if (pcie->base) {
|
||||
+ val = readl(pcie->base + PCIE_SYS_CFG_V2);
|
||||
+ val |= PCIE_CSR_LTSSM_EN(port->slot) |
|
||||
+ PCIE_CSR_ASPM_L1_EN(port->slot);
|
||||
+ writel(val, pcie->base + PCIE_SYS_CFG_V2);
|
||||
+ }
|
||||
+
|
||||
+ /* Assert all reset signals */
|
||||
+ writel(0, port->base + PCIE_RST_CTRL);
|
||||
+
|
||||
+ /*
|
||||
+ * Enable PCIe link down reset, if link status changed from link up to
|
||||
+ * link down, this will reset MAC control registers and configuration
|
||||
+ * space.
|
||||
+ */
|
||||
+ writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
|
||||
+
|
||||
+ /* De-assert PHY, PE, PIPE, MAC and configuration reset */
|
||||
+ val = readl(port->base + PCIE_RST_CTRL);
|
||||
+ val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
|
||||
+ PCIE_MAC_SRSTB | PCIE_CRSTB;
|
||||
+ writel(val, port->base + PCIE_RST_CTRL);
|
||||
+
|
||||
+ /* Set up vendor ID and class code */
|
||||
+ if (soc->need_fix_class_id) {
|
||||
+ val = PCI_VENDOR_ID_MEDIATEK;
|
||||
+ writew(val, port->base + PCIE_CONF_VEND_ID);
|
||||
+
|
||||
+ val = PCI_CLASS_BRIDGE_PCI;
|
||||
+ writew(val, port->base + PCIE_CONF_CLASS_ID);
|
||||
+ }
|
||||
+
|
||||
+ /* 100ms timeout value should be enough for Gen1/2 training */
|
||||
+ err = readl_poll_timeout(port->base + PCIE_LINK_STATUS_V2, val,
|
||||
+ !!(val & PCIE_PORT_LINKUP_V2), 20,
|
||||
+ 100 * USEC_PER_MSEC);
|
||||
+ if (err)
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ /* Set INTx mask */
|
||||
+ val = readl(port->base + PCIE_INT_MASK);
|
||||
+ val &= ~INTX_MASK;
|
||||
+ writel(val, port->base + PCIE_INT_MASK);
|
||||
+
|
||||
+ if (IS_ENABLED(CONFIG_PCI_MSI))
|
||||
+ mtk_pcie_enable_msi(port);
|
||||
+
|
||||
+ /* Set AHB to PCIe translation windows */
|
||||
+ size = mem->end - mem->start;
|
||||
+ val = lower_32_bits(mem->start) | AHB2PCIE_SIZE(fls(size));
|
||||
+ writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
|
||||
+
|
||||
+ val = upper_32_bits(mem->start);
|
||||
+ writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
|
||||
+
|
||||
+ /* Set PCIe to AXI translation memory space.*/
|
||||
+ val = fls(0xffffffff) | WIN_ENABLE;
|
||||
+ writel(val, port->base + PCIE_AXI_WINDOW0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -903,49 +928,29 @@
|
||||
|
||||
/* sys_ck might be divided into the following parts in some chips */
|
||||
snprintf(name, sizeof(name), "ahb_ck%d", slot);
|
||||
- port->ahb_ck = devm_clk_get(dev, name);
|
||||
- if (IS_ERR(port->ahb_ck)) {
|
||||
- if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER)
|
||||
- return -EPROBE_DEFER;
|
||||
-
|
||||
- port->ahb_ck = NULL;
|
||||
- }
|
||||
+ port->ahb_ck = devm_clk_get_optional(dev, name);
|
||||
+ if (IS_ERR(port->ahb_ck))
|
||||
+ return PTR_ERR(port->ahb_ck);
|
||||
|
||||
snprintf(name, sizeof(name), "axi_ck%d", slot);
|
||||
- port->axi_ck = devm_clk_get(dev, name);
|
||||
- if (IS_ERR(port->axi_ck)) {
|
||||
- if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER)
|
||||
- return -EPROBE_DEFER;
|
||||
-
|
||||
- port->axi_ck = NULL;
|
||||
- }
|
||||
+ port->axi_ck = devm_clk_get_optional(dev, name);
|
||||
+ if (IS_ERR(port->axi_ck))
|
||||
+ return PTR_ERR(port->axi_ck);
|
||||
|
||||
snprintf(name, sizeof(name), "aux_ck%d", slot);
|
||||
- port->aux_ck = devm_clk_get(dev, name);
|
||||
- if (IS_ERR(port->aux_ck)) {
|
||||
- if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER)
|
||||
- return -EPROBE_DEFER;
|
||||
-
|
||||
- port->aux_ck = NULL;
|
||||
- }
|
||||
+ port->aux_ck = devm_clk_get_optional(dev, name);
|
||||
+ if (IS_ERR(port->aux_ck))
|
||||
+ return PTR_ERR(port->aux_ck);
|
||||
|
||||
snprintf(name, sizeof(name), "obff_ck%d", slot);
|
||||
- port->obff_ck = devm_clk_get(dev, name);
|
||||
- if (IS_ERR(port->obff_ck)) {
|
||||
- if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER)
|
||||
- return -EPROBE_DEFER;
|
||||
-
|
||||
- port->obff_ck = NULL;
|
||||
- }
|
||||
+ port->obff_ck = devm_clk_get_optional(dev, name);
|
||||
+ if (IS_ERR(port->obff_ck))
|
||||
+ return PTR_ERR(port->obff_ck);
|
||||
|
||||
snprintf(name, sizeof(name), "pipe_ck%d", slot);
|
||||
- port->pipe_ck = devm_clk_get(dev, name);
|
||||
- if (IS_ERR(port->pipe_ck)) {
|
||||
- if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER)
|
||||
- return -EPROBE_DEFER;
|
||||
-
|
||||
- port->pipe_ck = NULL;
|
||||
- }
|
||||
+ port->pipe_ck = devm_clk_get_optional(dev, name);
|
||||
+ if (IS_ERR(port->pipe_ck))
|
||||
+ return PTR_ERR(port->pipe_ck);
|
||||
|
||||
snprintf(name, sizeof(name), "pcie-rst%d", slot);
|
||||
port->reset = devm_reset_control_get_optional_exclusive(dev, name);
|
||||
@@ -998,10 +1003,8 @@
|
||||
pcie->free_ck = NULL;
|
||||
}
|
||||
|
||||
- if (dev->pm_domain) {
|
||||
- pm_runtime_enable(dev);
|
||||
- pm_runtime_get_sync(dev);
|
||||
- }
|
||||
+ pm_runtime_enable(dev);
|
||||
+ pm_runtime_get_sync(dev);
|
||||
|
||||
/* enable top level clock */
|
||||
err = clk_prepare_enable(pcie->free_ck);
|
||||
@@ -1013,10 +1016,8 @@
|
||||
return 0;
|
||||
|
||||
err_free_ck:
|
||||
- if (dev->pm_domain) {
|
||||
- pm_runtime_put_sync(dev);
|
||||
- pm_runtime_disable(dev);
|
||||
- }
|
||||
+ pm_runtime_put_sync(dev);
|
||||
+ pm_runtime_disable(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1125,34 +1126,6 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int mtk_pcie_register_host(struct pci_host_bridge *host)
|
||||
-{
|
||||
- struct mtk_pcie *pcie = pci_host_bridge_priv(host);
|
||||
- struct pci_bus *child;
|
||||
- int err;
|
||||
-
|
||||
- host->busnr = pcie->busn.start;
|
||||
- host->dev.parent = pcie->dev;
|
||||
- host->ops = pcie->soc->ops;
|
||||
- host->map_irq = of_irq_parse_and_map_pci;
|
||||
- host->swizzle_irq = pci_common_swizzle;
|
||||
- host->sysdata = pcie;
|
||||
-
|
||||
- err = pci_scan_root_bus_bridge(host);
|
||||
- if (err < 0)
|
||||
- return err;
|
||||
-
|
||||
- pci_bus_size_bridges(host->bus);
|
||||
- pci_bus_assign_resources(host->bus);
|
||||
-
|
||||
- list_for_each_entry(child, &host->bus->children, node)
|
||||
- pcie_bus_configure_settings(child);
|
||||
-
|
||||
- pci_bus_add_devices(host->bus);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int mtk_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@@ -1179,7 +1152,14 @@
|
||||
if (err)
|
||||
goto put_resources;
|
||||
|
||||
- err = mtk_pcie_register_host(host);
|
||||
+ host->busnr = pcie->busn.start;
|
||||
+ host->dev.parent = pcie->dev;
|
||||
+ host->ops = pcie->soc->ops;
|
||||
+ host->map_irq = of_irq_parse_and_map_pci;
|
||||
+ host->swizzle_irq = pci_common_swizzle;
|
||||
+ host->sysdata = pcie;
|
||||
+
|
||||
+ err = pci_host_probe(host);
|
||||
if (err)
|
||||
goto put_resources;
|
||||
|
||||
@@ -1192,6 +1172,80 @@
|
||||
return err;
|
||||
}
|
||||
|
||||
+
|
||||
+static void mtk_pcie_free_resources(struct mtk_pcie *pcie)
|
||||
+{
|
||||
+ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
|
||||
+ struct list_head *windows = &host->windows;
|
||||
+
|
||||
+ pci_free_resource_list(windows);
|
||||
+}
|
||||
+
|
||||
+static int mtk_pcie_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mtk_pcie *pcie = platform_get_drvdata(pdev);
|
||||
+ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
|
||||
+
|
||||
+ pci_stop_root_bus(host->bus);
|
||||
+ pci_remove_root_bus(host->bus);
|
||||
+ mtk_pcie_free_resources(pcie);
|
||||
+
|
||||
+ mtk_pcie_irq_teardown(pcie);
|
||||
+
|
||||
+ mtk_pcie_put_resources(pcie);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __maybe_unused mtk_pcie_suspend_noirq(struct device *dev)
|
||||
+{
|
||||
+ struct mtk_pcie *pcie = dev_get_drvdata(dev);
|
||||
+ struct mtk_pcie_port *port;
|
||||
+
|
||||
+ if (list_empty(&pcie->ports))
|
||||
+ return 0;
|
||||
+
|
||||
+ list_for_each_entry(port, &pcie->ports, list) {
|
||||
+ clk_disable_unprepare(port->pipe_ck);
|
||||
+ clk_disable_unprepare(port->obff_ck);
|
||||
+ clk_disable_unprepare(port->axi_ck);
|
||||
+ clk_disable_unprepare(port->aux_ck);
|
||||
+ clk_disable_unprepare(port->ahb_ck);
|
||||
+ clk_disable_unprepare(port->sys_ck);
|
||||
+ phy_power_off(port->phy);
|
||||
+ phy_exit(port->phy);
|
||||
+ }
|
||||
+
|
||||
+ clk_disable_unprepare(pcie->free_ck);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __maybe_unused mtk_pcie_resume_noirq(struct device *dev)
|
||||
+{
|
||||
+ struct mtk_pcie *pcie = dev_get_drvdata(dev);
|
||||
+ struct mtk_pcie_port *port, *tmp;
|
||||
+
|
||||
+ if (list_empty(&pcie->ports))
|
||||
+ return 0;
|
||||
+
|
||||
+ clk_prepare_enable(pcie->free_ck);
|
||||
+
|
||||
+ list_for_each_entry_safe(port, tmp, &pcie->ports, list)
|
||||
+ mtk_pcie_enable_port(port);
|
||||
+
|
||||
+ /* In case of EP was removed while system suspend. */
|
||||
+ if (list_empty(&pcie->ports))
|
||||
+ clk_disable_unprepare(pcie->free_ck);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct dev_pm_ops mtk_pcie_pm_ops = {
|
||||
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_pcie_suspend_noirq,
|
||||
+ mtk_pcie_resume_noirq)
|
||||
+};
|
||||
+
|
||||
static const struct mtk_pcie_soc mtk_pcie_soc_v1 = {
|
||||
.ops = &mtk_pcie_ops,
|
||||
.startup = mtk_pcie_startup_port,
|
||||
@@ -1220,10 +1274,13 @@
|
||||
|
||||
static struct platform_driver mtk_pcie_driver = {
|
||||
.probe = mtk_pcie_probe,
|
||||
+ .remove = mtk_pcie_remove,
|
||||
.driver = {
|
||||
.name = "mtk-pcie",
|
||||
.of_match_table = mtk_pcie_ids,
|
||||
.suppress_bind_attrs = true,
|
||||
+ .pm = &mtk_pcie_pm_ops,
|
||||
},
|
||||
};
|
||||
-builtin_platform_driver(mtk_pcie_driver);
|
||||
+module_platform_driver(mtk_pcie_driver);
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
diff -urN a/include/linux/clk.h b/include/linux/clk.h
|
||||
--- a/include/linux/clk.h 2019-08-29 16:59:52.335365591 +0800
|
||||
+++ b/include/linux/clk.h 2019-08-29 17:02:17.107725525 +0800
|
||||
@@ -349,6 +349,17 @@
|
||||
struct clk *devm_clk_get(struct device *dev, const char *id);
|
||||
|
||||
/**
|
||||
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
|
||||
+ * clock producer.
|
||||
+ * @dev: device for clock "consumer"
|
||||
+ * @id: clock consumer ID
|
||||
+ *
|
||||
+ * Behaves the same as devm_clk_get() except where there is no clock producer.
|
||||
+ * In this case, instead of returning -ENOENT, the function returns NULL.
|
||||
+ */
|
||||
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
|
||||
+
|
||||
+/**
|
||||
* devm_get_clk_from_child - lookup and obtain a managed reference to a
|
||||
* clock producer from child node.
|
||||
* @dev: device for clock "consumer"
|
Loading…
Reference in New Issue
Block a user