Re: [PATCH 64/64] i2c: reword i2c_algorithm in drivers according to newest specification

2024-03-25 Thread Oleksij Rempel
On Fri, Mar 22, 2024 at 02:25:57PM +0100, Wolfram Sang wrote:
> Match the wording in i2c_algorithm in I2C drivers wrt. the newest I2C
> v7, SMBus 3.2, I3C specifications and replace "master/slave" with more
> appropriate terms. For some drivers, this means no more conversions are
> needed. For the others more work needs to be done but this will be
> performed incrementally along with API changes/improvements. All these
> changes here are simple search/replace results.
> 
> Signed-off-by: Wolfram Sang 

Acked-by: Oleksij Rempel  # for i2c-imx.c 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |



[PATCH net-next v3 3/6] net: add generic selftest support

2021-04-19 Thread Oleksij Rempel
Port some parts of the stmmac selftest and reuse it as basic generic selftest
library. This patch was tested with following combinations:
- iMX6DL FEC -> AT8035
- iMX6DL FEC -> SJA1105Q switch -> KSZ8081
- iMX6DL FEC -> SJA1105Q switch -> KSZ9031
- AR9331 ag71xx -> AR9331 PHY
- AR9331 ag71xx -> AR9331 switch -> AR9331 PHY

Signed-off-by: Oleksij Rempel 
---
 include/net/selftests.h |  12 ++
 net/Kconfig |   4 +
 net/core/Makefile   |   1 +
 net/core/selftests.c| 400 
 4 files changed, 417 insertions(+)
 create mode 100644 include/net/selftests.h
 create mode 100644 net/core/selftests.c

diff --git a/include/net/selftests.h b/include/net/selftests.h
new file mode 100644
index ..9993b9498cf3
--- /dev/null
+++ b/include/net/selftests.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _NET_SELFTESTS
+#define _NET_SELFTESTS
+
+#include 
+
+void net_selftest(struct net_device *ndev, struct ethtool_test *etest,
+ u64 *buf);
+int net_selftest_get_count(void);
+void net_selftest_get_strings(u8 *data);
+
+#endif /* _NET_SELFTESTS */
diff --git a/net/Kconfig b/net/Kconfig
index 9c456acc379e..8d955195c069 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -429,6 +429,10 @@ config GRO_CELLS
 config SOCK_VALIDATE_XMIT
bool
 
+config NET_SELFTESTS
+   def_tristate PHYLIB
+   depends on PHYLIB
+
 config NET_SOCK_MSG
bool
default n
diff --git a/net/core/Makefile b/net/core/Makefile
index 0c2233c826fd..1a6168d8f23b 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_NET_DEVLINK) += devlink.o
 obj-$(CONFIG_GRO_CELLS) += gro_cells.o
 obj-$(CONFIG_FAILOVER) += failover.o
 ifeq ($(CONFIG_INET),y)
+obj-$(CONFIG_NET_SELFTESTS) += selftests.o
 obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o
 obj-$(CONFIG_BPF_SYSCALL) += sock_map.o
 endif
diff --git a/net/core/selftests.c b/net/core/selftests.c
new file mode 100644
index ..ba7b0171974c
--- /dev/null
+++ b/net/core/selftests.c
@@ -0,0 +1,400 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Synopsys, Inc. and/or its affiliates.
+ * stmmac Selftests Support
+ *
+ * Author: Jose Abreu 
+ *
+ * Ported from stmmac by:
+ * Copyright (C) 2021 Oleksij Rempel 
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+struct net_packet_attrs {
+   unsigned char *src;
+   unsigned char *dst;
+   u32 ip_src;
+   u32 ip_dst;
+   bool tcp;
+   u16 sport;
+   u16 dport;
+   int timeout;
+   int size;
+   int max_size;
+   u8 id;
+   u16 queue_mapping;
+};
+
+struct net_test_priv {
+   struct net_packet_attrs *packet;
+   struct packet_type pt;
+   struct completion comp;
+   int double_vlan;
+   int vlan_id;
+   int ok;
+};
+
+struct netsfhdr {
+   __be32 version;
+   __be64 magic;
+   u8 id;
+} __packed;
+
+static u8 net_test_next_id;
+
+#define NET_TEST_PKT_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) + \
+  sizeof(struct netsfhdr))
+#define NET_TEST_PKT_MAGIC 0xdeadcafecafedeadULL
+#define NET_LB_TIMEOUT msecs_to_jiffies(200)
+
+static struct sk_buff *net_test_get_skb(struct net_device *ndev,
+   struct net_packet_attrs *attr)
+{
+   struct sk_buff *skb = NULL;
+   struct udphdr *uhdr = NULL;
+   struct tcphdr *thdr = NULL;
+   struct netsfhdr *shdr;
+   struct ethhdr *ehdr;
+   struct iphdr *ihdr;
+   int iplen, size;
+
+   size = attr->size + NET_TEST_PKT_SIZE;
+
+   if (attr->tcp)
+   size += sizeof(struct tcphdr);
+   else
+   size += sizeof(struct udphdr);
+
+   if (attr->max_size && attr->max_size > size)
+   size = attr->max_size;
+
+   skb = netdev_alloc_skb(ndev, size);
+   if (!skb)
+   return NULL;
+
+   prefetchw(skb->data);
+
+   ehdr = skb_push(skb, ETH_HLEN);
+   skb_reset_mac_header(skb);
+
+   skb_set_network_header(skb, skb->len);
+   ihdr = skb_put(skb, sizeof(*ihdr));
+
+   skb_set_transport_header(skb, skb->len);
+   if (attr->tcp)
+   thdr = skb_put(skb, sizeof(*thdr));
+   else
+   uhdr = skb_put(skb, sizeof(*uhdr));
+
+   eth_zero_addr(ehdr->h_dest);
+
+   if (attr->src)
+   ether_addr_copy(ehdr->h_source, attr->src);
+   if (attr->dst)
+   ether_addr_copy(ehdr->h_dest, attr->dst);
+
+   ehdr->h_proto = htons(ETH_P_IP);
+
+   if (attr->tcp) {
+   thdr->source = htons(attr->sport);
+   thdr->dest = htons(attr->dport);
+   thdr->doff = sizeof(struct tcphdr) / 4;
+   thdr->check = 0;
+   } else {
+   uhdr->source = htons(attr->sport);
+   

[PATCH net-next v3 2/6] net: phy: genphy_loopback: add link speed configuration

2021-04-19 Thread Oleksij Rempel
In case of loopback, in most cases we need to disable autoneg support
and force some speed configuration. Otherwise, depending on currently
active auto negotiated link speed, the loopback may or may not work.

This patch was tested with following PHYs: TJA1102, KSZ8081, KSZ9031,
AT8035, AR9331.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/phy/phy.c|  3 ++-
 drivers/net/phy/phy_device.c | 28 ++--
 include/linux/phy.h  |  1 +
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index fc2e7cb5b2e5..1f0512e39c65 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -701,7 +701,7 @@ int phy_start_cable_test_tdr(struct phy_device *phydev,
 }
 EXPORT_SYMBOL(phy_start_cable_test_tdr);
 
-static int phy_config_aneg(struct phy_device *phydev)
+int phy_config_aneg(struct phy_device *phydev)
 {
if (phydev->drv->config_aneg)
return phydev->drv->config_aneg(phydev);
@@ -714,6 +714,7 @@ static int phy_config_aneg(struct phy_device *phydev)
 
return genphy_config_aneg(phydev);
 }
+EXPORT_SYMBOL(phy_config_aneg);
 
 /**
  * phy_check_link_status - check link status and set state accordingly
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 320a3e5cd10a..0a2d8bedf73d 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2565,8 +2565,32 @@ EXPORT_SYMBOL(genphy_resume);
 
 int genphy_loopback(struct phy_device *phydev, bool enable)
 {
-   return phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK,
- enable ? BMCR_LOOPBACK : 0);
+   if (enable) {
+   u16 val, ctl = BMCR_LOOPBACK;
+   int ret;
+
+   if (phydev->speed == SPEED_1000)
+   ctl |= BMCR_SPEED1000;
+   else if (phydev->speed == SPEED_100)
+   ctl |= BMCR_SPEED100;
+
+   if (phydev->duplex == DUPLEX_FULL)
+   ctl |= BMCR_FULLDPLX;
+
+   phy_modify(phydev, MII_BMCR, ~0, ctl);
+
+   ret = phy_read_poll_timeout(phydev, MII_BMSR, val,
+   val & BMSR_LSTATUS,
+   5000, 50, true);
+   if (ret)
+   return ret;
+   } else {
+   phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0);
+
+   phy_config_aneg(phydev);
+   }
+
+   return 0;
 }
 EXPORT_SYMBOL(genphy_loopback);
 
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 98fb441dd72e..98e351bb0964 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1410,6 +1410,7 @@ void phy_disconnect(struct phy_device *phydev);
 void phy_detach(struct phy_device *phydev);
 void phy_start(struct phy_device *phydev);
 void phy_stop(struct phy_device *phydev);
+int phy_config_aneg(struct phy_device *phydev);
 int phy_start_aneg(struct phy_device *phydev);
 int phy_aneg_done(struct phy_device *phydev);
 int phy_speed_down(struct phy_device *phydev, bool sync);
-- 
2.29.2



[PATCH net-next v3 6/6] net: dsa: enable selftest support for all switches by default

2021-04-19 Thread Oleksij Rempel
Most of generic selftest should be able to work with probably all ethernet
controllers. The DSA switches are not exception, so enable it by default at
least for DSA.

This patch was tested with SJA1105 and AR9331.

Signed-off-by: Oleksij Rempel 
---
 include/net/dsa.h |  2 ++
 net/dsa/Kconfig   |  1 +
 net/dsa/slave.c   | 21 +
 3 files changed, 24 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 57b2c49f72f4..b4f89522b545 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -577,6 +577,8 @@ struct dsa_switch_ops {
 int port, uint64_t *data);
void(*get_stats64)(struct dsa_switch *ds, int port,
   struct rtnl_link_stats64 *s);
+   void(*self_test)(struct dsa_switch *ds, int port,
+struct ethtool_test *etest, u64 *data);
 
/*
 * ethtool Wake-on-LAN
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 8746b07668ae..cbc2bd643ab2 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -9,6 +9,7 @@ menuconfig NET_DSA
select NET_SWITCHDEV
select PHYLINK
select NET_DEVLINK
+   select NET_SELFTESTS
help
  Say Y if you want to enable support for the hardware switches 
supported
  by the Distributed Switch Architecture.
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 995e0e16f295..e282b422f733 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -748,7 +749,10 @@ static void dsa_slave_get_strings(struct net_device *dev,
if (ds->ops->get_strings)
ds->ops->get_strings(ds, dp->index, stringset,
 data + 4 * len);
+   } else if (stringset ==  ETH_SS_TEST) {
+   net_selftest_get_strings(data);
}
+
 }
 
 static void dsa_slave_get_ethtool_stats(struct net_device *dev,
@@ -794,11 +798,27 @@ static int dsa_slave_get_sset_count(struct net_device 
*dev, int sset)
count += ds->ops->get_sset_count(ds, dp->index, sset);
 
return count;
+   } else if (sset ==  ETH_SS_TEST) {
+   return net_selftest_get_count();
}
 
return -EOPNOTSUPP;
 }
 
+static void dsa_slave_net_selftest(struct net_device *ndev,
+  struct ethtool_test *etest, u64 *buf)
+{
+   struct dsa_port *dp = dsa_slave_to_port(ndev);
+   struct dsa_switch *ds = dp->ds;
+
+   if (ds->ops->self_test) {
+   ds->ops->self_test(ds, dp->index, etest, buf);
+   return;
+   }
+
+   net_selftest(ndev, etest, buf);
+}
+
 static void dsa_slave_get_wol(struct net_device *dev, struct ethtool_wolinfo 
*w)
 {
struct dsa_port *dp = dsa_slave_to_port(dev);
@@ -1630,6 +1650,7 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_rxnfc  = dsa_slave_get_rxnfc,
.set_rxnfc  = dsa_slave_set_rxnfc,
.get_ts_info= dsa_slave_get_ts_info,
+   .self_test  = dsa_slave_net_selftest,
 };
 
 /* legacy way, bypassing the bridge */
-- 
2.29.2



[PATCH net-next v3 5/6] net: ag71xx: make use of generic NET_SELFTESTS library

2021-04-19 Thread Oleksij Rempel
With this patch the ag71xx on Atheros AR9331 will able to run generic net
selftests.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/ethernet/atheros/Kconfig  |  1 +
 drivers/net/ethernet/atheros/ag71xx.c | 20 
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/atheros/Kconfig 
b/drivers/net/ethernet/atheros/Kconfig
index fb803bf92ded..6842b74b0696 100644
--- a/drivers/net/ethernet/atheros/Kconfig
+++ b/drivers/net/ethernet/atheros/Kconfig
@@ -20,6 +20,7 @@ if NET_VENDOR_ATHEROS
 config AG71XX
tristate "Atheros AR7XXX/AR9XXX built-in ethernet mac support"
depends on ATH79
+   select NET_SELFTESTS
select PHYLINK
help
  If you wish to compile a kernel for AR7XXX/91XXX and enable
diff --git a/drivers/net/ethernet/atheros/ag71xx.c 
b/drivers/net/ethernet/atheros/ag71xx.c
index 7352f98123c7..eb067ce978ae 100644
--- a/drivers/net/ethernet/atheros/ag71xx.c
+++ b/drivers/net/ethernet/atheros/ag71xx.c
@@ -37,6 +37,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* For our NAPI weight bigger does *NOT* mean better - it means more
  * D-cache misses and lots more wasted cycles than we'll ever
@@ -497,12 +498,17 @@ static int ag71xx_ethtool_set_pauseparam(struct 
net_device *ndev,
 static void ag71xx_ethtool_get_strings(struct net_device *netdev, u32 sset,
   u8 *data)
 {
-   if (sset == ETH_SS_STATS) {
-   int i;
+   int i;
 
+   switch (sset) {
+   case ETH_SS_STATS:
for (i = 0; i < ARRAY_SIZE(ag71xx_statistics); i++)
memcpy(data + i * ETH_GSTRING_LEN,
   ag71xx_statistics[i].name, ETH_GSTRING_LEN);
+   break;
+   case ETH_SS_TEST:
+   net_selftest_get_strings(data);
+   break;
}
 }
 
@@ -519,9 +525,14 @@ static void ag71xx_ethtool_get_stats(struct net_device 
*ndev,
 
 static int ag71xx_ethtool_get_sset_count(struct net_device *ndev, int sset)
 {
-   if (sset == ETH_SS_STATS)
+   switch (sset) {
+   case ETH_SS_STATS:
return ARRAY_SIZE(ag71xx_statistics);
-   return -EOPNOTSUPP;
+   case ETH_SS_TEST:
+   return net_selftest_get_count();
+   default:
+   return -EOPNOTSUPP;
+   }
 }
 
 static const struct ethtool_ops ag71xx_ethtool_ops = {
@@ -536,6 +547,7 @@ static const struct ethtool_ops ag71xx_ethtool_ops = {
.get_strings= ag71xx_ethtool_get_strings,
.get_ethtool_stats  = ag71xx_ethtool_get_stats,
.get_sset_count = ag71xx_ethtool_get_sset_count,
+   .self_test  = net_selftest,
 };
 
 static int ag71xx_mdio_wait_busy(struct ag71xx *ag)
-- 
2.29.2



[PATCH net-next v3 4/6] net: fec: make use of generic NET_SELFTESTS library

2021-04-19 Thread Oleksij Rempel
With this patch FEC on iMX will able to run generic net selftests

Signed-off-by: Oleksij Rempel 
---
 drivers/net/ethernet/freescale/Kconfig| 1 +
 drivers/net/ethernet/freescale/fec_main.c | 7 +++
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/freescale/Kconfig 
b/drivers/net/ethernet/freescale/Kconfig
index 3f9175bdce77..3d937b4650b2 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -26,6 +26,7 @@ config FEC
   ARCH_MXC || SOC_IMX28 || COMPILE_TEST)
default ARCH_MXC || SOC_IMX28 if ARM
select CRC32
+   select NET_SELFTESTS
select PHYLIB
imply PTP_1588_CLOCK
help
diff --git a/drivers/net/ethernet/freescale/fec_main.c 
b/drivers/net/ethernet/freescale/fec_main.c
index 70aea9c274fe..d51b2eb1de71 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -2481,6 +2482,9 @@ static void fec_enet_get_strings(struct net_device 
*netdev,
memcpy(data + i * ETH_GSTRING_LEN,
fec_stats[i].name, ETH_GSTRING_LEN);
break;
+   case ETH_SS_TEST:
+   net_selftest_get_strings(data);
+   break;
}
 }
 
@@ -2489,6 +2493,8 @@ static int fec_enet_get_sset_count(struct net_device 
*dev, int sset)
switch (sset) {
case ETH_SS_STATS:
return ARRAY_SIZE(fec_stats);
+   case ETH_SS_TEST:
+   return net_selftest_get_count();
default:
return -EOPNOTSUPP;
}
@@ -2740,6 +2746,7 @@ static const struct ethtool_ops fec_enet_ethtool_ops = {
.set_wol= fec_enet_set_wol,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
+   .self_test  = net_selftest,
 };
 
 static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
-- 
2.29.2



[PATCH net-next v3 0/6] provide generic net selftest support

2021-04-19 Thread Oleksij Rempel
changes v3:
- make more granular tests
- enable loopback for all PHYs by default
- fix allmodconfig build errors
- poll for link status update after switching to the loopback mode

changes v2:
- make generic selftests available for all networking devices.
- make use of net_selftest* on FEC, ag71xx and all DSA switches.
- add loopback support on more PHYs.

This patch set provides diagnostic capabilities for some iMX, ag71xx or
any DSA based devices. For proper functionality, PHY loopback support is
needed.
So far there is only initial infrastructure with basic tests. 

Oleksij Rempel (6):
  net: phy: execute genphy_loopback() per default on all PHYs
  net: phy: genphy_loopback: add link speed configuration
  net: add generic selftest support
  net: fec: make use of generic NET_SELFTESTS library
  net: ag71xx: make use of generic NET_SELFTESTS library
  net: dsa: enable selftest support for all switches by default

 drivers/net/ethernet/atheros/Kconfig  |   1 +
 drivers/net/ethernet/atheros/ag71xx.c |  20 +-
 drivers/net/ethernet/freescale/Kconfig|   1 +
 drivers/net/ethernet/freescale/fec_main.c |   7 +
 drivers/net/phy/phy.c |   3 +-
 drivers/net/phy/phy_device.c  |  35 +-
 include/linux/phy.h   |   1 +
 include/net/dsa.h |   2 +
 include/net/selftests.h   |  12 +
 net/Kconfig   |   4 +
 net/core/Makefile |   1 +
 net/core/selftests.c  | 400 ++
 net/dsa/Kconfig   |   1 +
 net/dsa/slave.c   |  21 ++
 14 files changed, 500 insertions(+), 9 deletions(-)
 create mode 100644 include/net/selftests.h
 create mode 100644 net/core/selftests.c

-- 
2.29.2



[PATCH net-next v3 1/6] net: phy: execute genphy_loopback() per default on all PHYs

2021-04-19 Thread Oleksij Rempel
The generic loopback is really generic and is defined by the 802.3
standard, we should just mandate that drivers implement a custom
loopback if the generic one cannot work.

Suggested-by: Florian Fainelli 
Signed-off-by: Oleksij Rempel 
---
 drivers/net/phy/phy_device.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 73d29fd5e03d..320a3e5cd10a 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1777,6 +1777,9 @@ int phy_loopback(struct phy_device *phydev, bool enable)
struct phy_driver *phydrv = to_phy_driver(phydev->mdio.dev.driver);
int ret = 0;
 
+   if (!phydrv)
+   return -ENODEV;
+
mutex_lock(>lock);
 
if (enable && phydev->loopback_enabled) {
@@ -1789,10 +1792,10 @@ int phy_loopback(struct phy_device *phydev, bool enable)
goto out;
}
 
-   if (phydev->drv && phydrv->set_loopback)
+   if (phydrv->set_loopback)
ret = phydrv->set_loopback(phydev, enable);
else
-   ret = -EOPNOTSUPP;
+   ret = genphy_loopback(phydev, enable);
 
if (ret)
goto out;
-- 
2.29.2



[PATCH v2 7/7] net: dsa: enable selftest support for all switches by default

2021-04-15 Thread Oleksij Rempel
Most of generic selftest should be able to work with probably all ethernet
controllers. The DSA switches are not exception, so enable it by default at
least for DSA.

This patch was tested with SJA1105 and AR9331.

Signed-off-by: Oleksij Rempel 
---
 include/net/dsa.h |  2 ++
 net/dsa/Kconfig   |  1 +
 net/dsa/slave.c   | 21 +
 3 files changed, 24 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 57b2c49f72f4..b4f89522b545 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -577,6 +577,8 @@ struct dsa_switch_ops {
 int port, uint64_t *data);
void(*get_stats64)(struct dsa_switch *ds, int port,
   struct rtnl_link_stats64 *s);
+   void(*self_test)(struct dsa_switch *ds, int port,
+struct ethtool_test *etest, u64 *data);
 
/*
 * ethtool Wake-on-LAN
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 8746b07668ae..cbc2bd643ab2 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -9,6 +9,7 @@ menuconfig NET_DSA
select NET_SWITCHDEV
select PHYLINK
select NET_DEVLINK
+   select NET_SELFTESTS
help
  Say Y if you want to enable support for the hardware switches 
supported
  by the Distributed Switch Architecture.
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 995e0e16f295..e282b422f733 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -748,7 +749,10 @@ static void dsa_slave_get_strings(struct net_device *dev,
if (ds->ops->get_strings)
ds->ops->get_strings(ds, dp->index, stringset,
 data + 4 * len);
+   } else if (stringset ==  ETH_SS_TEST) {
+   net_selftest_get_strings(data);
}
+
 }
 
 static void dsa_slave_get_ethtool_stats(struct net_device *dev,
@@ -794,11 +798,27 @@ static int dsa_slave_get_sset_count(struct net_device 
*dev, int sset)
count += ds->ops->get_sset_count(ds, dp->index, sset);
 
return count;
+   } else if (sset ==  ETH_SS_TEST) {
+   return net_selftest_get_count();
}
 
return -EOPNOTSUPP;
 }
 
+static void dsa_slave_net_selftest(struct net_device *ndev,
+  struct ethtool_test *etest, u64 *buf)
+{
+   struct dsa_port *dp = dsa_slave_to_port(ndev);
+   struct dsa_switch *ds = dp->ds;
+
+   if (ds->ops->self_test) {
+   ds->ops->self_test(ds, dp->index, etest, buf);
+   return;
+   }
+
+   net_selftest(ndev, etest, buf);
+}
+
 static void dsa_slave_get_wol(struct net_device *dev, struct ethtool_wolinfo 
*w)
 {
struct dsa_port *dp = dsa_slave_to_port(dev);
@@ -1630,6 +1650,7 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_rxnfc  = dsa_slave_get_rxnfc,
.set_rxnfc  = dsa_slave_set_rxnfc,
.get_ts_info= dsa_slave_get_ts_info,
+   .self_test  = dsa_slave_net_selftest,
 };
 
 /* legacy way, bypassing the bridge */
-- 
2.29.2



[PATCH v2 5/7] net: fec: make use of generic NET_SELFTESTS library

2021-04-15 Thread Oleksij Rempel
With this patch FEC on iMX will able to run generic net selftests

Signed-off-by: Oleksij Rempel 
---
 drivers/net/ethernet/freescale/Kconfig| 1 +
 drivers/net/ethernet/freescale/fec_main.c | 7 +++
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/freescale/Kconfig 
b/drivers/net/ethernet/freescale/Kconfig
index 3f9175bdce77..3d937b4650b2 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -26,6 +26,7 @@ config FEC
   ARCH_MXC || SOC_IMX28 || COMPILE_TEST)
default ARCH_MXC || SOC_IMX28 if ARM
select CRC32
+   select NET_SELFTESTS
select PHYLIB
imply PTP_1588_CLOCK
help
diff --git a/drivers/net/ethernet/freescale/fec_main.c 
b/drivers/net/ethernet/freescale/fec_main.c
index 70aea9c274fe..d51b2eb1de71 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -2481,6 +2482,9 @@ static void fec_enet_get_strings(struct net_device 
*netdev,
memcpy(data + i * ETH_GSTRING_LEN,
fec_stats[i].name, ETH_GSTRING_LEN);
break;
+   case ETH_SS_TEST:
+   net_selftest_get_strings(data);
+   break;
}
 }
 
@@ -2489,6 +2493,8 @@ static int fec_enet_get_sset_count(struct net_device 
*dev, int sset)
switch (sset) {
case ETH_SS_STATS:
return ARRAY_SIZE(fec_stats);
+   case ETH_SS_TEST:
+   return net_selftest_get_count();
default:
return -EOPNOTSUPP;
}
@@ -2740,6 +2746,7 @@ static const struct ethtool_ops fec_enet_ethtool_ops = {
.set_wol= fec_enet_set_wol,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
+   .self_test  = net_selftest,
 };
 
 static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
-- 
2.29.2



[PATCH v2 6/7] net: ag71xx: make use of generic NET_SELFTESTS library

2021-04-15 Thread Oleksij Rempel
With this patch the ag71xx on Atheros AR9331 will able to run generic net
selftests.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/ethernet/atheros/Kconfig  |  1 +
 drivers/net/ethernet/atheros/ag71xx.c | 20 
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/atheros/Kconfig 
b/drivers/net/ethernet/atheros/Kconfig
index fb803bf92ded..6842b74b0696 100644
--- a/drivers/net/ethernet/atheros/Kconfig
+++ b/drivers/net/ethernet/atheros/Kconfig
@@ -20,6 +20,7 @@ if NET_VENDOR_ATHEROS
 config AG71XX
tristate "Atheros AR7XXX/AR9XXX built-in ethernet mac support"
depends on ATH79
+   select NET_SELFTESTS
select PHYLINK
help
  If you wish to compile a kernel for AR7XXX/91XXX and enable
diff --git a/drivers/net/ethernet/atheros/ag71xx.c 
b/drivers/net/ethernet/atheros/ag71xx.c
index 7352f98123c7..eb067ce978ae 100644
--- a/drivers/net/ethernet/atheros/ag71xx.c
+++ b/drivers/net/ethernet/atheros/ag71xx.c
@@ -37,6 +37,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* For our NAPI weight bigger does *NOT* mean better - it means more
  * D-cache misses and lots more wasted cycles than we'll ever
@@ -497,12 +498,17 @@ static int ag71xx_ethtool_set_pauseparam(struct 
net_device *ndev,
 static void ag71xx_ethtool_get_strings(struct net_device *netdev, u32 sset,
   u8 *data)
 {
-   if (sset == ETH_SS_STATS) {
-   int i;
+   int i;
 
+   switch (sset) {
+   case ETH_SS_STATS:
for (i = 0; i < ARRAY_SIZE(ag71xx_statistics); i++)
memcpy(data + i * ETH_GSTRING_LEN,
   ag71xx_statistics[i].name, ETH_GSTRING_LEN);
+   break;
+   case ETH_SS_TEST:
+   net_selftest_get_strings(data);
+   break;
}
 }
 
@@ -519,9 +525,14 @@ static void ag71xx_ethtool_get_stats(struct net_device 
*ndev,
 
 static int ag71xx_ethtool_get_sset_count(struct net_device *ndev, int sset)
 {
-   if (sset == ETH_SS_STATS)
+   switch (sset) {
+   case ETH_SS_STATS:
return ARRAY_SIZE(ag71xx_statistics);
-   return -EOPNOTSUPP;
+   case ETH_SS_TEST:
+   return net_selftest_get_count();
+   default:
+   return -EOPNOTSUPP;
+   }
 }
 
 static const struct ethtool_ops ag71xx_ethtool_ops = {
@@ -536,6 +547,7 @@ static const struct ethtool_ops ag71xx_ethtool_ops = {
.get_strings= ag71xx_ethtool_get_strings,
.get_ethtool_stats  = ag71xx_ethtool_get_stats,
.get_sset_count = ag71xx_ethtool_get_sset_count,
+   .self_test  = net_selftest,
 };
 
 static int ag71xx_mdio_wait_busy(struct ag71xx *ag)
-- 
2.29.2



[PATCH net-next v2 0/7] provide generic net selftest support

2021-04-15 Thread Oleksij Rempel
changes v2:
- make this tests available for all netowking devices.
- enable them on FEC, ag71xx and all DSA switches.
- add and test loopback support on more PHYs.

This patch set provides diagnostic capabilities for some iMX, ag71xx or
any DSA based devices. For proper functionality, PHY loopback support is
needed.
So far there is only initial infrastructure with basic tests. 

Oleksij Rempel (7):
  net: phy: genphy_loopback: add link speed configuration
  net: phy: micrel: KSZ8081 & KSZ9031: add loopback support
  net: phy: at803x: AR8085 & AR9331: add loopback support
  net: add generic selftest support
  net: fec: make use of generic NET_SELFTESTS library
  net: ag71xx: make use of generic NET_SELFTESTS library
  net: dsa: enable selftest support for all switches by default

 drivers/net/ethernet/atheros/Kconfig  |   1 +
 drivers/net/ethernet/atheros/ag71xx.c |  20 +-
 drivers/net/ethernet/freescale/Kconfig|   1 +
 drivers/net/ethernet/freescale/fec_main.c |   7 +
 drivers/net/phy/at803x.c  |   2 +
 drivers/net/phy/micrel.c  |   2 +
 drivers/net/phy/phy.c |   3 +-
 drivers/net/phy/phy_device.c  |  21 +-
 include/linux/phy.h   |   1 +
 include/net/dsa.h |   2 +
 include/net/selftests.h   |  12 +
 net/Kconfig   |   4 +
 net/core/Makefile |   1 +
 net/core/selftests.c  | 366 ++
 net/dsa/Kconfig   |   1 +
 net/dsa/slave.c   |  21 ++
 16 files changed, 458 insertions(+), 7 deletions(-)
 create mode 100644 include/net/selftests.h
 create mode 100644 net/core/selftests.c

-- 
2.29.2



[PATCH v2 4/7] net: add generic selftest support

2021-04-15 Thread Oleksij Rempel
Port some parts of the stmmac selftest and reuse it as basic generic selftest
library. This patch was tested with following combinations:
- iMX6DL FEC -> AT8035
- iMX6DL FEC -> SJA1105Q switch -> KSZ8081
- iMX6DL FEC -> SJA1105Q switch -> KSZ9031
- AR9331 ag71xx -> AR9331 PHY
- AR9331 ag71xx -> AR9331 switch -> AR9331 PHY

Signed-off-by: Oleksij Rempel 
---
 include/net/selftests.h |  12 ++
 net/Kconfig |   4 +
 net/core/Makefile   |   1 +
 net/core/selftests.c| 366 
 4 files changed, 383 insertions(+)
 create mode 100644 include/net/selftests.h
 create mode 100644 net/core/selftests.c

diff --git a/include/net/selftests.h b/include/net/selftests.h
new file mode 100644
index ..9993b9498cf3
--- /dev/null
+++ b/include/net/selftests.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _NET_SELFTESTS
+#define _NET_SELFTESTS
+
+#include 
+
+void net_selftest(struct net_device *ndev, struct ethtool_test *etest,
+ u64 *buf);
+int net_selftest_get_count(void);
+void net_selftest_get_strings(u8 *data);
+
+#endif /* _NET_SELFTESTS */
diff --git a/net/Kconfig b/net/Kconfig
index 9c456acc379e..6e1285c8340e 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -429,6 +429,10 @@ config GRO_CELLS
 config SOCK_VALIDATE_XMIT
bool
 
+config NET_SELFTESTS
+   bool
+   default n
+
 config NET_SOCK_MSG
bool
default n
diff --git a/net/core/Makefile b/net/core/Makefile
index 0c2233c826fd..1a6168d8f23b 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_NET_DEVLINK) += devlink.o
 obj-$(CONFIG_GRO_CELLS) += gro_cells.o
 obj-$(CONFIG_FAILOVER) += failover.o
 ifeq ($(CONFIG_INET),y)
+obj-$(CONFIG_NET_SELFTESTS) += selftests.o
 obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o
 obj-$(CONFIG_BPF_SYSCALL) += sock_map.o
 endif
diff --git a/net/core/selftests.c b/net/core/selftests.c
new file mode 100644
index ..da1871d0f4ef
--- /dev/null
+++ b/net/core/selftests.c
@@ -0,0 +1,366 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Synopsys, Inc. and/or its affiliates.
+ * stmmac Selftests Support
+ *
+ * Author: Jose Abreu 
+ *
+ * Ported from stmmac by:
+ * Copyright (C) 2021 Oleksij Rempel 
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+struct net_packet_attrs {
+   unsigned char *src;
+   unsigned char *dst;
+   u32 ip_src;
+   u32 ip_dst;
+   int tcp;
+   int sport;
+   int dport;
+   int timeout;
+   int size;
+   int max_size;
+   u8 id;
+   u16 queue_mapping;
+};
+
+struct net_test_priv {
+   struct net_packet_attrs *packet;
+   struct packet_type pt;
+   struct completion comp;
+   int double_vlan;
+   int vlan_id;
+   int ok;
+};
+
+struct netsfhdr {
+   __be32 version;
+   __be64 magic;
+   u8 id;
+} __packed;
+
+static u8 net_test_next_id;
+
+#define NET_TEST_PKT_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) + \
+  sizeof(struct netsfhdr))
+#define NET_TEST_PKT_MAGIC 0xdeadcafecafedeadULL
+#define NET_LB_TIMEOUT msecs_to_jiffies(200)
+
+static struct sk_buff *net_test_get_udp_skb(struct net_device *ndev,
+   struct net_packet_attrs *attr)
+{
+   struct sk_buff *skb = NULL;
+   struct udphdr *uhdr = NULL;
+   struct tcphdr *thdr = NULL;
+   struct netsfhdr *shdr;
+   struct ethhdr *ehdr;
+   struct iphdr *ihdr;
+   int iplen, size;
+
+   size = attr->size + NET_TEST_PKT_SIZE;
+
+   if (attr->tcp)
+   size += sizeof(struct tcphdr);
+   else
+   size += sizeof(struct udphdr);
+
+   if (attr->max_size && attr->max_size > size)
+   size = attr->max_size;
+
+   skb = netdev_alloc_skb(ndev, size);
+   if (!skb)
+   return NULL;
+
+   prefetchw(skb->data);
+
+   ehdr = skb_push(skb, ETH_HLEN);
+   skb_reset_mac_header(skb);
+
+   skb_set_network_header(skb, skb->len);
+   ihdr = skb_put(skb, sizeof(*ihdr));
+
+   skb_set_transport_header(skb, skb->len);
+   if (attr->tcp)
+   thdr = skb_put(skb, sizeof(*thdr));
+   else
+   uhdr = skb_put(skb, sizeof(*uhdr));
+
+   eth_zero_addr(ehdr->h_dest);
+
+   if (attr->src)
+   ether_addr_copy(ehdr->h_source, attr->src);
+   if (attr->dst)
+   ether_addr_copy(ehdr->h_dest, attr->dst);
+
+   ehdr->h_proto = htons(ETH_P_IP);
+
+   if (attr->tcp) {
+   thdr->source = htons(attr->sport);
+   thdr->dest = htons(attr->dport);
+   thdr->doff = sizeof(struct tcphdr) / 4;
+   thdr->check = 0;
+   } else {
+   uhdr->source = htons(attr->sport);
+   uhdr->dest = htons(a

[PATCH v2 1/7] net: phy: genphy_loopback: add link speed configuration

2021-04-15 Thread Oleksij Rempel
In case of loopback, in most cases we need to disable autoneg support
and force some speed configuration. Otherwise, depending on currently
active auto negotiated link speed, the loopback may or may not work.

This patch was tested with following PHYs: TJA1102, KSZ8081, KSZ9031,
AT8035, AR9331.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/phy/phy.c|  3 ++-
 drivers/net/phy/phy_device.c | 21 +++--
 include/linux/phy.h  |  1 +
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index fc2e7cb5b2e5..1f0512e39c65 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -701,7 +701,7 @@ int phy_start_cable_test_tdr(struct phy_device *phydev,
 }
 EXPORT_SYMBOL(phy_start_cable_test_tdr);
 
-static int phy_config_aneg(struct phy_device *phydev)
+int phy_config_aneg(struct phy_device *phydev)
 {
if (phydev->drv->config_aneg)
return phydev->drv->config_aneg(phydev);
@@ -714,6 +714,7 @@ static int phy_config_aneg(struct phy_device *phydev)
 
return genphy_config_aneg(phydev);
 }
+EXPORT_SYMBOL(phy_config_aneg);
 
 /**
  * phy_check_link_status - check link status and set state accordingly
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 73d29fd5e03d..f484f191d2ff 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2562,8 +2562,25 @@ EXPORT_SYMBOL(genphy_resume);
 
 int genphy_loopback(struct phy_device *phydev, bool enable)
 {
-   return phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK,
- enable ? BMCR_LOOPBACK : 0);
+   if (enable) {
+   u16 ctl = BMCR_LOOPBACK;
+
+   if (phydev->speed == SPEED_1000)
+   ctl |= BMCR_SPEED1000;
+   else if (phydev->speed == SPEED_100)
+   ctl |= BMCR_SPEED100;
+
+   if (phydev->duplex == DUPLEX_FULL)
+   ctl |= BMCR_FULLDPLX;
+
+   phy_modify(phydev, MII_BMCR, ~0, ctl);
+   } else {
+   phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0);
+
+   phy_config_aneg(phydev);
+   }
+
+   return 0;
 }
 EXPORT_SYMBOL(genphy_loopback);
 
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 98fb441dd72e..98e351bb0964 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1410,6 +1410,7 @@ void phy_disconnect(struct phy_device *phydev);
 void phy_detach(struct phy_device *phydev);
 void phy_start(struct phy_device *phydev);
 void phy_stop(struct phy_device *phydev);
+int phy_config_aneg(struct phy_device *phydev);
 int phy_start_aneg(struct phy_device *phydev);
 int phy_aneg_done(struct phy_device *phydev);
 int phy_speed_down(struct phy_device *phydev, bool sync);
-- 
2.29.2



[PATCH v2 3/7] net: phy: at803x: AR8085 & AR9331: add loopback support

2021-04-15 Thread Oleksij Rempel
PHY loopback is needed for the ethernet controller self test support.
This PHY was tested with the generic net sefltest in combination with
FEC ethernet controller and AR9331 switch.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/phy/at803x.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index d7799beb811c..f74f427a8da5 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1128,6 +1128,7 @@ static struct phy_driver at803x_driver[] = {
.get_wol= at803x_get_wol,
.suspend= at803x_suspend,
.resume = at803x_resume,
+   .set_loopback   = genphy_loopback,
/* PHY_GBIT_FEATURES */
.read_status= at803x_read_status,
.config_intr= at803x_config_intr,
@@ -1207,6 +1208,7 @@ static struct phy_driver at803x_driver[] = {
.read_status= at803x_read_status,
.soft_reset = genphy_soft_reset,
.config_aneg= at803x_config_aneg,
+   .set_loopback   = genphy_loopback,
 } };
 
 module_phy_driver(at803x_driver);
-- 
2.29.2



[PATCH v2 2/7] net: phy: micrel: KSZ8081 & KSZ9031: add loopback support

2021-04-15 Thread Oleksij Rempel
PHY loopback is needed for the ethernet controller self test support.
This PHY was tested with the generic net sefltest in combination with
FEC ethernet controller and SJA1105 switch.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/phy/micrel.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index a14a00328fa3..26066b1e02e5 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -1311,6 +1311,7 @@ static struct phy_driver ksphy_driver[] = {
.get_stats  = kszphy_get_stats,
.suspend= kszphy_suspend,
.resume = kszphy_resume,
+   .set_loopback   = genphy_loopback,
 }, {
.phy_id = PHY_ID_KSZ8061,
.name   = "Micrel KSZ8061",
@@ -1356,6 +1357,7 @@ static struct phy_driver ksphy_driver[] = {
.get_stats  = kszphy_get_stats,
.suspend= genphy_suspend,
.resume = kszphy_resume,
+   .set_loopback   = genphy_loopback,
 }, {
.phy_id = PHY_ID_LAN8814,
.phy_id_mask= MICREL_PHY_ID_MASK,
-- 
2.29.2



Re: [PATCH v2 0/7] remove different PHY fixups

2021-04-13 Thread Oleksij Rempel
Hello,

On Tue, Mar 30, 2021 at 12:04:50PM -0300, Fabio Estevam wrote:
> Hi Andrew,
> 
> On Tue, Mar 30, 2021 at 11:30 AM Andrew Lunn  wrote:
> 
> > Hi Fabio
> >
> > I think it should be merged, and we fixup anything which does break.
> > We are probably at the point where more is broken by not merging it
> > than merging it.
> 
> Thanks for your feedback. I agree.
> 
> Shawn wants to collect some Acked-by for this series.
> 
> Could you please give your Acked-by for this series?

Andrew, can you please add you ACK?

Shawn will it be enough or you need more ACKs?

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


[Ping for Dmitry] Re: [PATCH v5 3/3] iio: adc: add ADC driver for the TI TSC2046 controller

2021-04-13 Thread Oleksij Rempel
Hi Dmitry,

probably this mail passed under your radar. Can you please add your
statement here.

On Mon, Mar 29, 2021 at 11:58:26AM +0100, Jonathan Cameron wrote:
> On Mon, 29 Mar 2021 09:31:31 +0200
> Oleksij Rempel  wrote:
> 
> > Basically the TI TSC2046 touchscreen controller is 8 channel ADC optimized 
> > for
> > the touchscreen use case. By implementing it as an IIO ADC device, we can
> > make use of resistive-adc-touch and iio-hwmon drivers.
> > 
> > Polled readings are currently not implemented to keep this patch small, so
> > iio-hwmon will not work out of the box for now.
> > 
> > So far, this driver was tested with a custom version of resistive-adc-touch 
> > driver,
> > since it needs to be extended to make use of Z1 and Z2 channels. The X/Y
> > are working without additional changes.
> > 
> > Signed-off-by: Oleksij Rempel 
> > Reviewed-by: Andy Shevchenko 
> Hi Oleksij,
> 
> Couple of things in here I missed before, but big question is still whether
> Dmitry is happy with what you mention in the cover letter:
> 
> "This driver can replace drivers/input/touchscreen/ads7846.c and has
> following advantages over it:
> - less code to maintain
> - shared code paths (resistive-adc-touch, iio-hwmon, etc)
> - can be used as plain IIO ADC to investigate signaling issues or test
>   real capacity of the plates and attached low-pass filters
>   (or use the touchscreen as a microphone if you like ;) )"
> 
> So two things that need addressing in here are
> iio_dev->name (part number, not hybrid of that an spi device name)
> Why oversampling is DT rather than userspace controllable.
> For that I'm looking for clear reasoning for the choice.
 
Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


Re: [PATCH net-next v1 4/9] net: dsa: qca: ar9331: make proper initial port defaults

2021-04-04 Thread Oleksij Rempel
Am 04.04.21 um 02:16 schrieb Vladimir Oltean:
> On Sat, Apr 03, 2021 at 01:48:43PM +0200, Oleksij Rempel wrote:
>> Make sure that all external port are actually isolated from each other,
>> so no packets are leaked.
>>
>> Signed-off-by: Oleksij Rempel 
>> ---
>>  drivers/net/dsa/qca/ar9331.c | 145 ++-
>>  1 file changed, 143 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
>> index 9a5035b2f0ff..a3de3598fbf5 100644
>> --- a/drivers/net/dsa/qca/ar9331.c
>> +++ b/drivers/net/dsa/qca/ar9331.c
>> @@ -60,10 +60,19 @@
>>
>>  /* MIB registers */
>>  #define AR9331_MIB_COUNTER(x)   (0x2 + ((x) * 
>> 0x100))
>>
>> @@ -229,6 +278,7 @@ struct ar9331_sw_priv {
>>  struct regmap *regmap;
>>  struct reset_control *sw_reset;
>>  struct ar9331_sw_port port[AR9331_SW_PORTS];
>> +int cpu_port;
>>  };
>>
>>  static struct ar9331_sw_priv *ar9331_sw_port_to_priv(struct ar9331_sw_port 
>> *port)
>> @@ -371,12 +421,72 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv 
>> *priv)
>>  return 0;
>>  }
>>
>> -static int ar9331_sw_setup(struct dsa_switch *ds)
>> +static int ar9331_sw_setup_port(struct dsa_switch *ds, int port)
>>  {
>>  struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
>>  struct regmap *regmap = priv->regmap;
>> +u32 port_mask, port_ctrl, val;
>>  int ret;
>>
>> +/* Generate default port settings */
>> +port_ctrl = FIELD_PREP(AR9331_SW_PORT_CTRL_PORT_STATE,
>> +   AR9331_SW_PORT_CTRL_PORT_STATE_DISABLED);
>> +
>> +if (dsa_is_cpu_port(ds, port)) {
>> +/*
>> + * CPU port should be allowed to communicate with all user
>> + * ports.
>> + */
>> +//port_mask = dsa_user_ports(ds);
>
> Code commented out should ideally not be part of a submitted patch.

Sorry I overlooked this one

> And the networking comment style is:
>
>   /* CPU port should be allowed to communicate with all user
>* ports.
>*/

Aaa... networking part of kernel code...

>> +port_mask = 0;
>> +/*
>> + * Enable atheros header on CPU port. This will allow us
>> + * communicate with each port separately
>> + */
>> +port_ctrl |= AR9331_SW_PORT_CTRL_HEAD_EN;
>> +port_ctrl |= AR9331_SW_PORT_CTRL_LEARN_EN;
>> +} else if (dsa_is_user_port(ds, port)) {
>> +/*
>> + * User ports should communicate only with the CPU port.
>> + */
>> +port_mask = BIT(priv->cpu_port);
>
> For all you care, the CPU port here is dsa_to_port(ds, port)->cpu_dp->index,
> no need to go to those lengths in order to find it. DSA does not have
> fixed number for the CPU port but a CPU port pointer per port in order
> to not close the door for the future support of multiple CPU ports.

ok.

>> +/* Enable unicast address learning by default */
>> +port_ctrl |= AR9331_SW_PORT_CTRL_LEARN_EN
>> +/* IGMP snooping seems to work correctly, let's use it */
>> +  | AR9331_SW_PORT_CTRL_IGMP_MLD_EN
>
> I don't really like this ad-hoc enablement of IGMP/MLD snooping from the 
> driver,
> please add the pass-through in DSA for SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED
> (dsa_slave_port_attr_set, dsa_port_switchdev_sync, dsa_port_switchdev_unsync
> should all call a dsa_switch_ops :: port_snoop_igmp_mld function) and then
> toggle this bit from there.

sounds good. Looks like there are few more driver need to be fixed:
drivers/net/dsa/lan9303-core.c
drivers/net/dsa/mv88e6xxx/chip.c


>
>> +  | AR9331_SW_PORT_CTRL_SINGLE_VLAN_EN;
>> +} else {
>> +/* Other ports do not need to communicate at all */
>> +port_mask = 0;
>> +}
>> +
>> +val = FIELD_PREP(AR9331_SW_PORT_VLAN_8021Q_MODE,
>> + AR9331_SW_8021Q_MODE_NONE) |
>> +FIELD_PREP(AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, port_mask) |
>> +FIELD_PREP(AR9331_SW_PORT_VLAN_PORT_VID,
>> +   AR9331_SW_PORT_VLAN_PORT_VID_DEF);
>> +
>> +ret = regmap_write(regmap, AR9331_SW_REG_PORT_VLAN(port), val);
>> +if (ret)
>> +goto error;
>> +
>> +ret = regmap_write(regmap, AR9331_SW_REG

Re: [PATCH net-next v1 1/9] net: dsa: add rcv_post call back

2021-04-03 Thread Oleksij Rempel
Am 04.04.21 um 01:21 schrieb Vladimir Oltean:
> On Sat, Apr 03, 2021 at 05:05:34PM +0300, Vladimir Oltean wrote:
>> On Sat, Apr 03, 2021 at 01:48:40PM +0200, Oleksij Rempel wrote:
>>> Some switches (for example ar9331) do not provide enough information
>>> about forwarded packets. If the switch decision was made based on IPv4
>>> or IPv6 header, we need to analyze it and set proper flag.
>>>
>>> Potentially we can do it in existing rcv path, on other hand we can
>>> avoid part of duplicated work and let the dsa framework set skb header
>>> pointers and then use preprocessed skb one step later withing the rcv_post
>>> call back.
>>>
>>> This patch is needed for ar9331 switch.
>>>
>>> Signed-off-by: Oleksij Rempel 
>>> ---
>>
>> I don't necessarily disagree with this, perhaps we can even move
>> Florian's dsa_untag_bridge_pvid() call inside a rcv_post() method
>> implemented by the DSA_TAG_PROTO_BRCM_LEGACY, DSA_TAG_PROTO_BRCM_PREPEND
>> and DSA_TAG_PROTO_BRCM taggers. Or even better, because Oleksij's
>> rcv_post is already prototype-compatible with dsa_untag_bridge_pvid, we
>> can already do:
>>
>>  .rcv_post = dsa_untag_bridge_pvid,
>>
>> This should be generally useful for stuff that DSA taggers need to do
>> which is easiest done after eth_type_trans() was called.
>
> I had some fun with an alternative method of parsing the frame for IGMP
> so that you can clear skb->offload_fwd_mark, which doesn't rely on the
> introduction of a new method in DSA. It should also have several other
> advantages compared to your solution such as the fact that it should
> work with VLAN-tagged packets.
>
> Background: we made Receive Packet Steering work on DSA master interfaces
> (echo 3 > /sys/class/net/eth0/queues/rx-1/rps_cpus) even when the DSA
> tag shifts to the right the IP headers and everything that comes
> afterwards. The flow dissector had to be patched for that, just grep for
> DSA in net/core/flow_dissector.c.
>
> The problem you're facing is that you can't parse the IP and IGMP
> headers in the tagger's rcv() method, since the network header,
> transport header offsets and skb->protocol are all messed up, since
> eth_type_trans hasn't been called yet.
>
> And that's the trick right there, you're between a rock and a hard
> place: too early because eth_type_trans wasn't called yet, and too late
> because skb->dev was changed and no longer points to the DSA master, so
> the flow dissector adjustment we made doesn't apply.
>
> But if you call the flow dissector _before_ you call "skb->dev =
> dsa_master_find_slave" (and yes, while the DSA tag is still there), then
> it's virtually as if you had called that while the skb belonged to the
> DSA master, so it should work with __skb_flow_dissect.
>
> In fact I prototyped this idea below. I wanted to check whether I can
> match something as fine-grained as an IGMPv2 Membership Report message,
> and I could.
>
> I prototyped it inside the ocelot tagging protocol driver because that's
> what I had handy. I used __skb_flow_dissect with my own flow dissector
> which had to be initialized at the tagger module_init time, even though
> I think I could have probably just called skb_flow_dissect_flow_keys
> with a standard dissector, and that would have removed the need for the
> custom module_init in tag_ocelot.c. One thing that is interesting is
> that I had to add the bits for IGMP parsing to the flow dissector
> myself (based on the existing ICMP code). I was too lazy to do that for
> MLD as well, but it is really not hard. Or even better, if you don't
> need to look at all inside the IGMP/MLD header, I think you can even
> omit adding this parsing code to the flow dissector and just look at
> basic.n_proto and basic.ip_proto.
>
> See the snippet below. Hope it helps.
>
> -[ cut here ]-
> diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
> index ffd386ea0dbb..4c25fa47637a 100644
> --- a/include/net/flow_dissector.h
> +++ b/include/net/flow_dissector.h
> @@ -190,6 +190,20 @@ struct flow_dissector_key_icmp {
>   u16 id;
>  };
>
> +/**
> + * flow_dissector_key_igmp:
> + *   type: indicates the message type, see include/uapi/linux/igmp.h
> + *   code: Max Resp Code, the maximum time in 1/10 second
> + * increments before sending a responding report
> + *   group: the multicast address being queried when sending a
> + *  Group-Specific or Group-and-Source-Specific Query.
> + */
> +struct flow_dissector_key_igmp {
> + 

Re: [PATCH net-next v1 2/9] net: dsa: tag_ar9331: detect IGMP and MLD packets

2021-04-03 Thread Oleksij Rempel
Am 04.04.21 um 02:02 schrieb Vladimir Oltean:
> On Sat, Apr 03, 2021 at 07:14:56PM +0200, Oleksij Rempel wrote:
>> Am 03.04.21 um 16:49 schrieb Andrew Lunn:
>>>> @@ -31,6 +96,13 @@ static struct sk_buff *ar9331_tag_xmit(struct sk_buff 
>>>> *skb,
>>>>__le16 *phdr;
>>>>u16 hdr;
>>>>
>>>> +  if (dp->stp_state == BR_STATE_BLOCKING) {
>>>> +  /* TODO: should we reflect it in the stats? */
>>>> +  netdev_warn_once(dev, "%s:%i dropping blocking packet\n",
>>>> +   __func__, __LINE__);
>>>> +  return NULL;
>>>> +  }
>>>> +
>>>>phdr = skb_push(skb, AR9331_HDR_LEN);
>>>>
>>>>hdr = FIELD_PREP(AR9331_HDR_VERSION_MASK, AR9331_HDR_VERSION);
>>>
>>> Hi Oleksij
>>>
>>> This change does not seem to fit with what this patch is doing.
>>
>> done
>>
>>> I also think it is wrong. You still need BPDU to pass through a
>>> blocked port, otherwise spanning tree protocol will be unstable.
>>
>> We need a better filter, otherwise, in case of software based STP, we are 
>> leaking packages on
>> blocked port. For example DHCP do trigger lots of spam in the kernel log.
>
> I have no idea whatsoever what 'software based STP' is, if you have
> hardware-accelerated forwarding.

I do not mean hardware-accelerated forwarding, i mean
hardware-accelerated STP port state helpers.

>> I'll drop STP patch for now, it will be better to make a generic soft STP 
>> for all switches without
>> HW offloading. For example ksz9477 is doing SW based STP in similar way.
>
> How about we discuss first about what your switch is not doing properly?
> Have you debugged more than just watching the bridge change port states?
> As Andrew said, a port needs to accept and send link-local frames
> regardless of the STP state. In the BLOCKING state it must send no other
> frames and have address learning disabled. Is this what's happening, is
> the switch forwarding frames towards a BLOCKING port?

The switch is not forwarding BPDU frame to the CPU port. So, the linux
bridge will stack by cycling different state of the port where loop was
detected.

--
Regards,
Oleksij


Re: [PATCH net-next v1 2/9] net: dsa: tag_ar9331: detect IGMP and MLD packets

2021-04-03 Thread Oleksij Rempel
Am 03.04.21 um 16:49 schrieb Andrew Lunn:
>> @@ -31,6 +96,13 @@ static struct sk_buff *ar9331_tag_xmit(struct sk_buff 
>> *skb,
>>  __le16 *phdr;
>>  u16 hdr;
>>
>> +if (dp->stp_state == BR_STATE_BLOCKING) {
>> +/* TODO: should we reflect it in the stats? */
>> +netdev_warn_once(dev, "%s:%i dropping blocking packet\n",
>> + __func__, __LINE__);
>> +return NULL;
>> +}
>> +
>>  phdr = skb_push(skb, AR9331_HDR_LEN);
>>
>>  hdr = FIELD_PREP(AR9331_HDR_VERSION_MASK, AR9331_HDR_VERSION);
>
> Hi Oleksij
>
> This change does not seem to fit with what this patch is doing.

done

> I also think it is wrong. You still need BPDU to pass through a
> blocked port, otherwise spanning tree protocol will be unstable.

We need a better filter, otherwise, in case of software based STP, we are 
leaking packages on
blocked port. For example DHCP do trigger lots of spam in the kernel log.

I'll drop STP patch for now, it will be better to make a generic soft STP for 
all switches without
HW offloading. For example ksz9477 is doing SW based STP in similar way.

--
Regards,
Oleksij


Re: [PATCH net-next v1 2/9] net: dsa: tag_ar9331: detect IGMP and MLD packets

2021-04-03 Thread Oleksij Rempel
On Sat, Apr 03, 2021 at 04:46:06PM +0300, Vladimir Oltean wrote:
> On Sat, Apr 03, 2021 at 03:26:36PM +0200, Oleksij Rempel wrote:
> > On Sat, Apr 03, 2021 at 04:03:18PM +0300, Vladimir Oltean wrote:
> > > Hi Oleksij,
> > > 
> > > On Sat, Apr 03, 2021 at 01:48:41PM +0200, Oleksij Rempel wrote:
> > > > The ar9331 switch is not forwarding IGMP and MLD packets if IGMP
> > > > snooping is enabled. This patch is trying to mimic the HW heuristic to 
> > > > take
> > > > same decisions as this switch would do to be able to tell the linux
> > > > bridge if some packet was prabably forwarded or not.
> > > > 
> > > > Signed-off-by: Oleksij Rempel 
> > > > ---
> > > 
> > > I am not familiar with IGMP/MLD, therefore I don't really understand
> > > what problem you are trying to solve.
> > > 
> > > Your switch has packet traps for IGMP and MLD, ok. So it doesn't forward
> > > them. Must the IGMP/MLD packets be forwarded by an IGMP/MLD snooping
> > > bridge? Which ones and under what circumstances?
> > 
> > I'll better refer to the rfc:
> > https://tools.ietf.org/html/rfc4541
> 
> Ok, the question might have been a little bit dumb.
> I found this PDF:
> https://www.alliedtelesis.com/sites/default/files/documents/how-alliedware/howto_config_igmp1.pdf
> and it explains that:
> - a snooper floods the Membership Query messages from the network's
>   querier towards all ports that are not blocked by STP
> - a snooper forwards all Membership Report messages from a client
>   towards the All Groups port (which is how it reaches the querier).
> 
> I'm asking this because I just want to understand what the bridge code
> does. Does the code path for IGMP_HOST_MEMBERSHIP_REPORT (for example)
> for a snooper go through should_deliver -> nbp_switchdev_allowed_egress,
> which is what you are affecting here?

yes.

the exact path should depend on this configuration option:
/sys/devices/virtual/net/test/bridge/multicast_snooping

I assume, some optimization can be done by letting DSA know the state
of multicast_snooping.

Off-topic question, this patch set stops to work after rebasing against
latest netdev. I get following warning:
ip l s lan0 master test
RTNETLINK answers: Invalid argumen

Are there some API changes?

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


Re: [PATCH net-next v1 2/9] net: dsa: tag_ar9331: detect IGMP and MLD packets

2021-04-03 Thread Oleksij Rempel
On Sat, Apr 03, 2021 at 04:03:18PM +0300, Vladimir Oltean wrote:
> Hi Oleksij,
> 
> On Sat, Apr 03, 2021 at 01:48:41PM +0200, Oleksij Rempel wrote:
> > The ar9331 switch is not forwarding IGMP and MLD packets if IGMP
> > snooping is enabled. This patch is trying to mimic the HW heuristic to take
> > same decisions as this switch would do to be able to tell the linux
> > bridge if some packet was prabably forwarded or not.
> > 
> > Signed-off-by: Oleksij Rempel 
> > ---
> 
> I am not familiar with IGMP/MLD, therefore I don't really understand
> what problem you are trying to solve.
> 
> Your switch has packet traps for IGMP and MLD, ok. So it doesn't forward
> them. Must the IGMP/MLD packets be forwarded by an IGMP/MLD snooping
> bridge? Which ones and under what circumstances?

I'll better refer to the rfc:
https://tools.ietf.org/html/rfc4541

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


[PATCH net-next v1 5/9] net: dsa: qca: ar9331: add forwarding database support

2021-04-03 Thread Oleksij Rempel
This switch provides simple address resolution table, without VLAN or
multicast specific information.
With this patch we are able now to read, modify unicast and mulicast
addresses.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/dsa/qca/ar9331.c | 356 +++
 1 file changed, 356 insertions(+)

diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
index a3de3598fbf5..4a98f14f31f4 100644
--- a/drivers/net/dsa/qca/ar9331.c
+++ b/drivers/net/dsa/qca/ar9331.c
@@ -66,6 +66,47 @@
 #define AR9331_SW_REG_GLOBAL_CTRL  0x30
 #define AR9331_SW_GLOBAL_CTRL_MFS_MGENMASK(13, 0)
 
+/* Size of the address resolution table (ARL) */
+#define AR9331_SW_NUM_ARL_RECORDS  1024
+
+#define AR9331_SW_REG_ADDR_TABLE_FUNCTION0 0x50
+#define AR9331_SW_AT_ADDR_BYTES4   GENMASK(31, 24)
+#define AR9331_SW_AT_ADDR_BYTES5   GENMASK(23, 16)
+#define AR9331_SW_AT_FULL_VIO  BIT(12)
+#define AR9331_SW_AT_PORT_NUM  GENMASK(11, 8)
+#define AR9331_SW_AT_FLUSH_STATIC_EN   BIT(4)
+#define AR9331_SW_AT_BUSY  BIT(3)
+#define AR9331_SW_AT_FUNC  GENMASK(2, 0)
+#define AR9331_SW_AT_FUNC_NOP  0
+#define AR9331_SW_AT_FUNC_FLUSH_ALL1
+#define AR9331_SW_AT_FUNC_LOAD_ENTRY   2
+#define AR9331_SW_AT_FUNC_PURGE_ENTRY  3
+#define AR9331_SW_AT_FUNC_FLUSH_ALL_UNLOCKED   4
+#define AR9331_SW_AT_FUNC_FLUSH_PORT   5
+#define AR9331_SW_AT_FUNC_GET_NEXT 6
+#define AR9331_SW_AT_FUNC_FIND_MAC 7
+
+#define AR9331_SW_REG_ADDR_TABLE_FUNCTION1 0x54
+#define AR9331_SW_AT_ADDR_BYTES0   GENMASK(31, 24)
+#define AR9331_SW_AT_ADDR_BYTES1   GENMASK(23, 16)
+#define AR9331_SW_AT_ADDR_BYTES2   GENMASK(15, 8)
+#define AR9331_SW_AT_ADDR_BYTES3   GENMASK(7, 0)
+
+#define AR9331_SW_REG_ADDR_TABLE_FUNCTION2 0x58
+#define AR9331_SW_AT_COPY_TO_CPU   BIT(26)
+#define AR9331_SW_AT_REDIRECT_TOCPUBIT(25)
+#define AR9331_SW_AT_LEAKY_EN  BIT(24)
+#define AR9331_SW_AT_STATUSGENMASK(19, 16)
+#define AR9331_SW_AT_STATUS_EMPTY  0
+/* STATUS values from 7 to 1 are different aging levels */
+#define AR9331_SW_AT_STATUS_STATIC 0xf
+
+#define AR9331_SW_AT_SA_DROP_ENBIT(14)
+#define AR9331_SW_AT_MIRROR_EN BIT(13)
+#define AR9331_SW_AT_PRIORITY_EN   BIT(12)
+#define AR9331_SW_AT_PRIORITY  GENMASK(11, 10)
+#define AR9331_SW_AT_DES_PORT  GENMASK(5, 0)
+
 #define AR9331_SW_REG_ADDR_TABLE_CTRL  0x5c
 #define AR9331_SW_AT_ARP_ENBIT(20)
 #define AR9331_SW_AT_LEARN_CHANGE_EN   BIT(18)
@@ -266,6 +307,12 @@ struct ar9331_sw_port {
struct spinlock stats_lock;
 };
 
+struct ar9331_sw_fdb {
+   u8 port_mask;
+   u8 aging;
+   u8 mac[ETH_ALEN];
+};
+
 struct ar9331_sw_priv {
struct device *dev;
struct dsa_switch ds;
@@ -765,6 +812,309 @@ static void ar9331_get_stats64(struct dsa_switch *ds, int 
port,
spin_unlock(>stats_lock);
 }
 
+static int ar9331_sw_fdb_wait(struct ar9331_sw_priv *priv, u32 *f0)
+{
+   struct regmap *regmap = priv->regmap;
+
+   return regmap_read_poll_timeout(regmap,
+   AR9331_SW_REG_ADDR_TABLE_FUNCTION0,
+   *f0, !(*f0 & AR9331_SW_AT_BUSY),
+   10, 2000);
+}
+
+static int ar9331_sw_port_fdb_write(struct ar9331_sw_priv *priv,
+   u32 f0, u32 f1, u32 f2)
+{
+   struct regmap *regmap = priv->regmap;
+   int ret;
+
+   ret = regmap_write(regmap, AR9331_SW_REG_ADDR_TABLE_FUNCTION2, f2);
+   if (ret)
+   return ret;
+
+   ret = regmap_write(regmap, AR9331_SW_REG_ADDR_TABLE_FUNCTION1, f1);
+   if (ret)
+   return ret;
+
+   return regmap_write(regmap, AR9331_SW_REG_ADDR_TABLE_FUNCTION0, f0);
+}
+
+static int ar9331_sw_fdb_next(struct ar9331_sw_priv *priv,
+ struct ar9331_sw_fdb *fdb, int port)
+{
+   struct regmap *regmap = priv->regmap;
+   unsigned int status, ports;
+   u32 f0, f1, f2;
+   int ret;
+
+   /* Keep AT_ADDR_BYTES4/5 to search next entry after current */
+   ret = regmap_update_bits(regmap, AR9331_SW_REG_ADDR_TABLE_FUNCTION0,
+AR9331_SW_AT_FUNC | AR9331_SW_AT_BUSY,
+AR9331_SW_AT_BUSY |
+FIELD_PREP(AR9331_SW_AT_FUNC,
+   AR9331_SW_AT_FUNC_GET_NEXT));
+   if (ret)
+   return ret;
+
+   ret = ar9331_sw_fdb_wait(priv, );
+   if (ret)
+   return ret;
+
+   ret = re

[PATCH net-next v1 2/9] net: dsa: tag_ar9331: detect IGMP and MLD packets

2021-04-03 Thread Oleksij Rempel
The ar9331 switch is not forwarding IGMP and MLD packets if IGMP
snooping is enabled. This patch is trying to mimic the HW heuristic to take
same decisions as this switch would do to be able to tell the linux
bridge if some packet was prabably forwarded or not.

Signed-off-by: Oleksij Rempel 
---
 net/dsa/tag_ar9331.c | 130 +++
 1 file changed, 130 insertions(+)

diff --git a/net/dsa/tag_ar9331.c b/net/dsa/tag_ar9331.c
index 002cf7f952e2..0ba90e0f91bb 100644
--- a/net/dsa/tag_ar9331.c
+++ b/net/dsa/tag_ar9331.c
@@ -6,6 +6,8 @@
 
 #include 
 #include 
+#include 
+#include 
 
 #include "dsa_priv.h"
 
@@ -24,6 +26,69 @@
 #define AR9331_HDR_RESERVED_MASK   GENMASK(5, 4)
 #define AR9331_HDR_PORT_NUM_MASK   GENMASK(3, 0)
 
+/*
+ * This code replicated MLD detection more or less in the same way as the
+ * switch is doing it
+ */
+static int ipv6_mc_check_ip6hdr(struct sk_buff *skb)
+{
+   const struct ipv6hdr *ip6h;
+   unsigned int offset;
+
+   offset = skb_network_offset(skb) + sizeof(*ip6h);
+
+   if (!pskb_may_pull(skb, offset))
+   return -EINVAL;
+
+   ip6h = ipv6_hdr(skb);
+
+   if (ip6h->version != 6)
+   return -EINVAL;
+
+   skb_set_transport_header(skb, offset);
+
+   return 0;
+}
+
+static int ipv6_mc_check_exthdrs(struct sk_buff *skb)
+{
+   const struct ipv6hdr *ip6h;
+   int offset;
+   u8 nexthdr;
+   __be16 frag_off;
+
+   ip6h = ipv6_hdr(skb);
+
+   if (ip6h->nexthdr != IPPROTO_HOPOPTS)
+   return -ENOMSG;
+
+   nexthdr = ip6h->nexthdr;
+   offset = skb_network_offset(skb) + sizeof(*ip6h);
+   offset = ipv6_skip_exthdr(skb, offset, , _off);
+
+   if (offset < 0)
+   return -EINVAL;
+
+   if (nexthdr != IPPROTO_ICMPV6)
+   return -ENOMSG;
+
+   skb_set_transport_header(skb, offset);
+
+   return 0;
+}
+
+static int my_ipv6_mc_check_mld(struct sk_buff *skb)
+{
+   int ret;
+
+   ret = ipv6_mc_check_ip6hdr(skb);
+   if (ret < 0)
+   return ret;
+
+   return ipv6_mc_check_exthdrs(skb);
+}
+
+
 static struct sk_buff *ar9331_tag_xmit(struct sk_buff *skb,
   struct net_device *dev)
 {
@@ -31,6 +96,13 @@ static struct sk_buff *ar9331_tag_xmit(struct sk_buff *skb,
__le16 *phdr;
u16 hdr;
 
+   if (dp->stp_state == BR_STATE_BLOCKING) {
+   /* TODO: should we reflect it in the stats? */
+   netdev_warn_once(dev, "%s:%i dropping blocking packet\n",
+__func__, __LINE__);
+   return NULL;
+   }
+
phdr = skb_push(skb, AR9331_HDR_LEN);
 
hdr = FIELD_PREP(AR9331_HDR_VERSION_MASK, AR9331_HDR_VERSION);
@@ -80,11 +152,69 @@ static struct sk_buff *ar9331_tag_rcv(struct sk_buff *skb,
return skb;
 }
 
+static void ar9331_tag_rcv_post(struct sk_buff *skb)
+{
+   const struct iphdr *iph;
+   unsigned char *dest;
+   int ret;
+
+   /*
+* Since the switch do not tell us which packets was offloaded we assume
+* that all of them did. Except:
+* - port is not configured for forwarding to any other ports
+* - igmp/mld snooping is enabled
+* - unicast or multicast flood is disabled on some of bridged ports
+* - if we have two port bridge and one is not in forwarding state.
+* - packet was dropped on the output port..
+* - any other reasons?
+*/
+   skb->offload_fwd_mark = true;
+
+   dest = eth_hdr(skb)->h_dest;
+   /*
+* Complete not multicast traffic seems to be forwarded automatically,
+* as long as multicast and unicast flood are enabled
+*/
+   if (!(is_multicast_ether_addr(dest) && !is_broadcast_ether_addr(dest)))
+   return;
+
+
+   /*
+* Documentation do not providing any usable information on how the
+* igmp/mld snooping is implemented on this switch. Following
+* implementation is based on testing, by sending correct and malformed
+* packets to the switch.
+* It is not trying to find sane and properly formated packets. Instead
+* it is trying to be as close to the switch behavior as possible.
+*/
+   skb_reset_network_header(skb);
+   switch (ntohs(skb->protocol)) {
+   case ETH_P_IP:
+
+   if (!pskb_network_may_pull(skb, sizeof(*iph)))
+   break;
+
+   iph = ip_hdr(skb);
+   if (iph->protocol == IPPROTO_IGMP)
+   skb->offload_fwd_mark = false;
+
+   break;
+   case ETH_P_IPV6:
+   ret = my_ipv6_mc_check_mld(skb);
+   if (!ret)
+   skb->offload_fwd_mark = false;
+
+   break;
+   }
+}
+
+
 static const struct dsa_device_ops 

[PATCH net-next v1 7/9] net: dsa: qca: ar9331: add bridge support

2021-04-03 Thread Oleksij Rempel
This switch is providing forwarding matrix, with it we can configure
individual bridges. Potentially we can configure more then one not VLAN
based bridge on this HW.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/dsa/qca/ar9331.c | 73 
 1 file changed, 73 insertions(+)

diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
index b2c22ba924f0..bf9588574205 100644
--- a/drivers/net/dsa/qca/ar9331.c
+++ b/drivers/net/dsa/qca/ar9331.c
@@ -40,6 +40,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1134,6 +1135,76 @@ static int ar9331_sw_set_ageing_time(struct dsa_switch 
*ds,
  val);
 }
 
+static int ar9331_sw_port_bridge_join(struct dsa_switch *ds, int port,
+ struct net_device *br)
+{
+   struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+   struct regmap *regmap = priv->regmap;
+   int port_mask = BIT(priv->cpu_port);
+   int i, ret;
+   u32 val;
+
+   for (i = 0; i < ds->num_ports; i++) {
+   if (dsa_to_port(ds, i)->bridge_dev != br)
+   continue;
+
+   if (!dsa_is_user_port(ds, port))
+   continue;
+
+   val = FIELD_PREP(AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, 
BIT(port));
+   ret = regmap_set_bits(regmap, AR9331_SW_REG_PORT_VLAN(i), val);
+   if (ret)
+   goto error;
+
+   if (i != port)
+   port_mask |= BIT(i);
+   }
+
+   val = FIELD_PREP(AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, port_mask);
+   ret = regmap_update_bits(regmap, AR9331_SW_REG_PORT_VLAN(port),
+AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, val);
+   if (ret)
+   goto error;
+
+   return 0;
+error:
+   dev_err_ratelimited(priv->dev, "%s: error: %i\n", __func__, ret);
+
+   return ret;
+}
+
+static void ar9331_sw_port_bridge_leave(struct dsa_switch *ds, int port,
+   struct net_device *br)
+{
+   struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+   struct regmap *regmap = priv->regmap;
+   int i, ret;
+   u32 val;
+
+   for (i = 0; i < ds->num_ports; i++) {
+   if (dsa_to_port(ds, i)->bridge_dev != br)
+   continue;
+
+   if (!dsa_is_user_port(ds, port))
+   continue;
+
+   val = FIELD_PREP(AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, 
BIT(port));
+   ret = regmap_clear_bits(regmap, AR9331_SW_REG_PORT_VLAN(i), 
val);
+   if (ret)
+   goto error;
+   }
+
+   val = FIELD_PREP(AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, 
BIT(priv->cpu_port));
+   ret = regmap_update_bits(regmap, AR9331_SW_REG_PORT_VLAN(port),
+AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, val);
+   if (ret)
+   goto error;
+
+   return;
+error:
+   dev_err_ratelimited(priv->dev, "%s: error: %i\n", __func__, ret);
+}
+
 static const struct dsa_switch_ops ar9331_sw_ops = {
.get_tag_protocol   = ar9331_sw_get_tag_protocol,
.setup  = ar9331_sw_setup,
@@ -1150,6 +1221,8 @@ static const struct dsa_switch_ops ar9331_sw_ops = {
.port_mdb_add   = ar9331_sw_port_mdb_add,
.port_mdb_del   = ar9331_sw_port_mdb_del,
.set_ageing_time= ar9331_sw_set_ageing_time,
+   .port_bridge_join   = ar9331_sw_port_bridge_join,
+   .port_bridge_leave  = ar9331_sw_port_bridge_leave,
 };
 
 static irqreturn_t ar9331_sw_irq(int irq, void *data)
-- 
2.29.2



[PATCH net-next v1 3/9] net: dsa: qca: ar9331: reorder MDIO write sequence

2021-04-03 Thread Oleksij Rempel
In case of this switch we work with 32bit registers on top of 16bit
bus. Some registers (for example access to forwarding database) have
trigger bit on the first 16bit half of request and the result +
configuration of request in the second half. Without this this patch, we would
trigger database operation and overwrite result in one run.

To make it work properly, we should do the second part of transfer
before the first one is done.

So far, this rule seems to work for all registers on this switch.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/dsa/qca/ar9331.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
index ca2ad77b71f1..9a5035b2f0ff 100644
--- a/drivers/net/dsa/qca/ar9331.c
+++ b/drivers/net/dsa/qca/ar9331.c
@@ -837,16 +837,17 @@ static int ar9331_mdio_write(void *ctx, u32 reg, u32 val)
return 0;
}
 
-   ret = __ar9331_mdio_write(sbus, AR9331_SW_MDIO_PHY_MODE_REG, reg, val);
+   ret = __ar9331_mdio_write(sbus, AR9331_SW_MDIO_PHY_MODE_REG, reg + 2,
+ val >> 16);
if (ret < 0)
goto error;
 
-   ret = __ar9331_mdio_write(sbus, AR9331_SW_MDIO_PHY_MODE_REG, reg + 2,
- val >> 16);
+   ret = __ar9331_mdio_write(sbus, AR9331_SW_MDIO_PHY_MODE_REG, reg, val);
if (ret < 0)
goto error;
 
return 0;
+
 error:
dev_err_ratelimited(>dev, "Bus error. Failed to write 
register.\n");
return ret;
-- 
2.29.2



[PATCH net-next v1 6/9] net: dsa: qca: ar9331: add ageing time support

2021-04-03 Thread Oleksij Rempel
This switch provides global ageing time configuration, so let DSA use
it.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/dsa/qca/ar9331.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
index 4a98f14f31f4..b2c22ba924f0 100644
--- a/drivers/net/dsa/qca/ar9331.c
+++ b/drivers/net/dsa/qca/ar9331.c
@@ -1115,6 +1115,25 @@ static void ar9331_sw_port_fast_age(struct dsa_switch 
*ds, int port)
dev_err_ratelimited(priv->dev, "%s: error: %i\n", __func__, ret);
 }
 
+static int ar9331_sw_set_ageing_time(struct dsa_switch *ds,
+unsigned int ageing_time)
+{
+   struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+   struct regmap *regmap = priv->regmap;
+   u32 time, val;
+
+   time = DIV_ROUND_UP(ageing_time, AR9331_SW_AT_AGE_TIME_COEF);
+   if (!time)
+   time = 1;
+   else if (time > U16_MAX)
+   time = U16_MAX;
+
+   val = FIELD_PREP(AR9331_SW_AT_AGE_TIME, time) | AR9331_SW_AT_AGE_EN;
+   return regmap_update_bits(regmap, AR9331_SW_REG_ADDR_TABLE_CTRL,
+ AR9331_SW_AT_AGE_EN | AR9331_SW_AT_AGE_TIME,
+ val);
+}
+
 static const struct dsa_switch_ops ar9331_sw_ops = {
.get_tag_protocol   = ar9331_sw_get_tag_protocol,
.setup  = ar9331_sw_setup,
@@ -1130,6 +1149,7 @@ static const struct dsa_switch_ops ar9331_sw_ops = {
.port_fdb_dump  = ar9331_sw_port_fdb_dump,
.port_mdb_add   = ar9331_sw_port_mdb_add,
.port_mdb_del   = ar9331_sw_port_mdb_del,
+   .set_ageing_time= ar9331_sw_set_ageing_time,
 };
 
 static irqreturn_t ar9331_sw_irq(int irq, void *data)
@@ -1476,6 +1496,8 @@ static int ar9331_sw_probe(struct mdio_device *mdiodev)
priv->ops = ar9331_sw_ops;
ds->ops = >ops;
dev_set_drvdata(>dev, priv);
+   ds->ageing_time_min = AR9331_SW_AT_AGE_TIME_COEF;
+   ds->ageing_time_max = AR9331_SW_AT_AGE_TIME_COEF * U16_MAX;
 
for (i = 0; i < ARRAY_SIZE(priv->port); i++) {
struct ar9331_sw_port *port = >port[i];
-- 
2.29.2



[PATCH net-next v1 8/9] net: dsa: qca: ar9331: add STP support

2021-04-03 Thread Oleksij Rempel
According to the datasheet, this switch has configurable STP port
states. Suddenly LISTENING and BLOCKING states didn't forwarded packets
to the CPU and linux bridge continuously re enabled ports even if a  loop
was detected. To make it work, I reused bridge functionality to isolate
port in LISTENING and BLOCKING states.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/dsa/qca/ar9331.c | 69 
 1 file changed, 69 insertions(+)

diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
index bf9588574205..83b59e771a5f 100644
--- a/drivers/net/dsa/qca/ar9331.c
+++ b/drivers/net/dsa/qca/ar9331.c
@@ -327,6 +327,7 @@ struct ar9331_sw_priv {
struct reset_control *sw_reset;
struct ar9331_sw_port port[AR9331_SW_PORTS];
int cpu_port;
+   u32 isolated_ports;
 };
 
 static struct ar9331_sw_priv *ar9331_sw_port_to_priv(struct ar9331_sw_port 
*port)
@@ -1151,6 +1152,10 @@ static int ar9331_sw_port_bridge_join(struct dsa_switch 
*ds, int port,
if (!dsa_is_user_port(ds, port))
continue;
 
+   /* part of the bridge but should be isolated for now */
+   if (priv->isolated_ports & BIT(i))
+   continue;
+
val = FIELD_PREP(AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, 
BIT(port));
ret = regmap_set_bits(regmap, AR9331_SW_REG_PORT_VLAN(i), val);
if (ret)
@@ -1205,6 +1210,69 @@ static void ar9331_sw_port_bridge_leave(struct 
dsa_switch *ds, int port,
dev_err_ratelimited(priv->dev, "%s: error: %i\n", __func__, ret);
 }
 
+static void ar9331_sw_port_stp_state_set(struct dsa_switch *ds, int port,
+u8 state)
+{
+   struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+   struct net_device *br = dsa_to_port(ds, port)->bridge_dev;
+   struct regmap *regmap = priv->regmap;
+   u32 port_ctrl = 0, port_state = 0;
+   bool join = false;
+   int ret;
+
+   /*
+* STP hw support is buggy or I didn't understood it. So, it seems to
+* be easier to make hand crafted implementation by using bridge
+* functionality. Similar implementation can be found on ksz9477 switch
+* and may be we need some generic code to so for all related devices
+*/
+   switch (state) {
+   case BR_STATE_FORWARDING:
+   join = true;
+   fallthrough;
+   case BR_STATE_LEARNING:
+   port_ctrl = AR9331_SW_PORT_CTRL_LEARN_EN;
+   fallthrough;
+   case BR_STATE_LISTENING:
+   case BR_STATE_BLOCKING:
+   port_state = AR9331_SW_PORT_CTRL_PORT_STATE_FORWARD;
+   break;
+   case BR_STATE_DISABLED:
+   default:
+   port_state = AR9331_SW_PORT_CTRL_PORT_STATE_DISABLED;
+   break;
+   }
+
+   port_ctrl |= FIELD_PREP(AR9331_SW_PORT_CTRL_PORT_STATE, port_state);
+
+   ret = regmap_update_bits(regmap, AR9331_SW_REG_PORT_CTRL(port),
+AR9331_SW_PORT_CTRL_LEARN_EN |
+AR9331_SW_PORT_CTRL_PORT_STATE, port_ctrl);
+   if (ret)
+   goto error;
+
+   if (!dsa_is_user_port(ds, port))
+   return;
+
+   /*
+* here we care only about user ports. CPU port do not need this
+* configuration
+*/
+   if (join) {
+   priv->isolated_ports &= ~BIT(port);
+   if (br)
+   ar9331_sw_port_bridge_join(ds, port, br);
+   } else {
+   priv->isolated_ports |= BIT(port);
+   if (br)
+   ar9331_sw_port_bridge_leave(ds, port, br);
+   }
+
+   return;
+error:
+   dev_err_ratelimited(priv->dev, "%s: error: %i\n", __func__, ret);
+}
+
 static const struct dsa_switch_ops ar9331_sw_ops = {
.get_tag_protocol   = ar9331_sw_get_tag_protocol,
.setup  = ar9331_sw_setup,
@@ -1223,6 +1291,7 @@ static const struct dsa_switch_ops ar9331_sw_ops = {
.set_ageing_time= ar9331_sw_set_ageing_time,
.port_bridge_join   = ar9331_sw_port_bridge_join,
.port_bridge_leave  = ar9331_sw_port_bridge_leave,
+   .port_stp_state_set = ar9331_sw_port_stp_state_set,
 };
 
 static irqreturn_t ar9331_sw_irq(int irq, void *data)
-- 
2.29.2



[PATCH net-next v1 0/9] ar9331: mainline some parts of switch functionality

2021-04-03 Thread Oleksij Rempel
Till now the ar9331 switch was supporting only port multiplexing mode.
With this patch set we should be able to bridging, VLAN and STP

Oleksij Rempel (9):
  net: dsa: add rcv_post call back
  net: dsa: tag_ar9331: detect IGMP and MLD packets
  net: dsa: qca: ar9331: reorder MDIO write sequence
  net: dsa: qca: ar9331: make proper initial port defaults
  net: dsa: qca: ar9331: add forwarding database support
  net: dsa: qca: ar9331: add ageing time support
  net: dsa: qca: ar9331: add bridge support
  net: dsa: qca: ar9331: add STP support
  net: dsa: qca: ar9331: add vlan support

 drivers/net/dsa/qca/ar9331.c | 927 ++-
 include/net/dsa.h|   2 +
 net/dsa/dsa.c|   4 +
 net/dsa/port.c   |   1 +
 net/dsa/tag_ar9331.c | 130 +
 5 files changed, 1059 insertions(+), 5 deletions(-)

-- 
2.29.2



[PATCH net-next v1 4/9] net: dsa: qca: ar9331: make proper initial port defaults

2021-04-03 Thread Oleksij Rempel
Make sure that all external port are actually isolated from each other,
so no packets are leaked.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/dsa/qca/ar9331.c | 145 ++-
 1 file changed, 143 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
index 9a5035b2f0ff..a3de3598fbf5 100644
--- a/drivers/net/dsa/qca/ar9331.c
+++ b/drivers/net/dsa/qca/ar9331.c
@@ -60,10 +60,19 @@
 
 #define AR9331_SW_REG_FLOOD_MASK   0x2c
 #define AR9331_SW_FLOOD_MASK_BROAD_TO_CPU  BIT(26)
+#define AR9331_SW_FLOOD_MASK_MULTI_FLOOD_DPGENMASK(20, 16)
+#define AR9331_SW_FLOOD_MASK_UNI_FLOOD_DP  GENMASK(4, 0)
 
 #define AR9331_SW_REG_GLOBAL_CTRL  0x30
 #define AR9331_SW_GLOBAL_CTRL_MFS_MGENMASK(13, 0)
 
+#define AR9331_SW_REG_ADDR_TABLE_CTRL  0x5c
+#define AR9331_SW_AT_ARP_ENBIT(20)
+#define AR9331_SW_AT_LEARN_CHANGE_EN   BIT(18)
+#define AR9331_SW_AT_AGE_ENBIT(17)
+#define AR9331_SW_AT_AGE_TIME  GENMASK(15, 0)
+#define AR9331_SW_AT_AGE_TIME_COEF 6900 /* Not documented */
+
 #define AR9331_SW_REG_MDIO_CTRL0x98
 #define AR9331_SW_MDIO_CTRL_BUSY   BIT(31)
 #define AR9331_SW_MDIO_CTRL_MASTER_EN  BIT(30)
@@ -101,6 +110,46 @@
 AR9331_SW_PORT_STATUS_RX_FLOW_EN | AR9331_SW_PORT_STATUS_TX_FLOW_EN | \
 AR9331_SW_PORT_STATUS_SPEED_M)
 
+#define AR9331_SW_REG_PORT_CTRL(_port) (0x104 + (_port) * 
0x100)
+#define AR9331_SW_PORT_CTRL_ING_MIRROR_EN  BIT(17)
+#define AR9331_SW_PORT_CTRL_EG_MIRROR_EN   BIT(16)
+#define AR9331_SW_PORT_CTRL_DOUBLE_TAG_VLANBIT(15)
+#define AR9331_SW_PORT_CTRL_LEARN_EN   BIT(14)
+#define AR9331_SW_PORT_CTRL_SINGLE_VLAN_EN BIT(13)
+#define AR9331_SW_PORT_CTRL_MAC_LOOP_BACK  BIT(12)
+#define AR9331_SW_PORT_CTRL_HEAD_ENBIT(11)
+#define AR9331_SW_PORT_CTRL_IGMP_MLD_ENBIT(10)
+#define AR9331_SW_PORT_CTRL_EG_VLAN_MODE   GENMASK(9, 8)
+#define AR9331_SW_PORT_CTRL_EG_VLAN_MODE_KEEP  0
+#define AR9331_SW_PORT_CTRL_EG_VLAN_MODE_STRIP 1
+#define AR9331_SW_PORT_CTRL_EG_VLAN_MODE_ADD   2
+#define AR9331_SW_PORT_CTRL_EG_VLAN_MODE_DOUBLE3
+#define AR9331_SW_PORT_CTRL_LEARN_ONE_LOCK BIT(7)
+#define AR9331_SW_PORT_CTRL_PORT_LOCK_EN   BIT(6)
+#define AR9331_SW_PORT_CTRL_LOCK_DROP_EN   BIT(5)
+#define AR9331_SW_PORT_CTRL_PORT_STATE GENMASK(2, 0)
+#define AR9331_SW_PORT_CTRL_PORT_STATE_DISABLED0
+#define AR9331_SW_PORT_CTRL_PORT_STATE_BLOCKING1
+#define AR9331_SW_PORT_CTRL_PORT_STATE_LISTENING   2
+#define AR9331_SW_PORT_CTRL_PORT_STATE_LEARNING3
+#define AR9331_SW_PORT_CTRL_PORT_STATE_FORWARD 4
+
+#define AR9331_SW_REG_PORT_VLAN(_port) (0x108 + (_port) * 
0x100)
+#define AR9331_SW_PORT_VLAN_8021Q_MODE GENMASK(31, 30)
+#define AR9331_SW_8021Q_MODE_SECURE3
+#define AR9331_SW_8021Q_MODE_CHECK 2
+#define AR9331_SW_8021Q_MODE_FALLBACK  1
+#define AR9331_SW_8021Q_MODE_NONE  0
+#define AR9331_SW_PORT_VLAN_ING_PORT_PRI   GENMASK(29, 27)
+#define AR9331_SW_PORT_VLAN_FORCE_PORT_VLAN_EN BIT(26)
+#define AR9331_SW_PORT_VLAN_PORT_VID_MEMBERGENMASK(25, 16)
+#define AR9331_SW_PORT_VLAN_ARP_LEAKY_EN   BIT(15)
+#define AR9331_SW_PORT_VLAN_UNI_LEAKY_EN   BIT(14)
+#define AR9331_SW_PORT_VLAN_MULTI_LEAKY_EN BIT(13)
+#define AR9331_SW_PORT_VLAN_FORCE_DEFALUT_VID_EN   BIT(12)
+#define AR9331_SW_PORT_VLAN_PORT_VID   GENMASK(11, 0)
+#define AR9331_SW_PORT_VLAN_PORT_VID_DEF   1
+
 /* MIB registers */
 #define AR9331_MIB_COUNTER(x)  (0x2 + ((x) * 0x100))
 
@@ -229,6 +278,7 @@ struct ar9331_sw_priv {
struct regmap *regmap;
struct reset_control *sw_reset;
struct ar9331_sw_port port[AR9331_SW_PORTS];
+   int cpu_port;
 };
 
 static struct ar9331_sw_priv *ar9331_sw_port_to_priv(struct ar9331_sw_port 
*port)
@@ -371,12 +421,72 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv 
*priv)
return 0;
 }
 
-static int ar9331_sw_setup(struct dsa_switch *ds)
+static int ar9331_sw_setup_port(struct dsa_switch *ds, int port)
 {
struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
struct regmap *regmap = priv->regmap;
+   u32 port_mask, port_ctrl, val;
int ret;
 
+   /* Generate default port settings */
+   port_ctrl = FIELD_PREP(AR9331_SW_PORT_CTRL_PORT_STATE,
+  AR9331_SW_PORT_CTRL_PORT_STATE_DISABLED);
+
+   if (dsa_is_cpu_port(ds

[PATCH net-next v1 9/9] net: dsa: qca: ar9331: add vlan support

2021-04-03 Thread Oleksij Rempel
This switch provides simple VLAN resolution database for 16 entries (VLANs).
With this database we can cover typical functionalities as port based
VLANs, untagged and tagged egress. Port based ingress filtering.

The VLAN database is working on top of forwarding database. So,
potentially, we can have multiple VLANs on top of multiple bridges.
Hawing one VLAN on top of multiple bridges will fail on different
levels, most probably DSA framework should warn if some one wont to make
something likes this.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/dsa/qca/ar9331.c | 255 +++
 1 file changed, 255 insertions(+)

diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c
index 83b59e771a5f..40062388d4a7 100644
--- a/drivers/net/dsa/qca/ar9331.c
+++ b/drivers/net/dsa/qca/ar9331.c
@@ -67,6 +67,27 @@
 #define AR9331_SW_REG_GLOBAL_CTRL  0x30
 #define AR9331_SW_GLOBAL_CTRL_MFS_MGENMASK(13, 0)
 
+#define AR9331_SW_NUM_VLAN_RECORDS 16
+
+#define AR9331_SW_REG_VLAN_TABLE_FUNCTION0 0x40
+#define AR9331_SW_VT0_PRI_EN   BIT(31)
+#define AR9331_SW_VT0_PRI  GENMASK(30, 28)
+#define AR9331_SW_VT0_VID  GENMASK(27, 16)
+#define AR9331_SW_VT0_PORT_NUM GENMASK(11, 8)
+#define AR9331_SW_VT0_FULL_VIO BIT(4)
+#define AR9331_SW_VT0_BUSY BIT(3)
+#define AR9331_SW_VT0_FUNC GENMASK(2, 0)
+#define AR9331_SW_VT0_FUNC_NOP 0
+#define AR9331_SW_VT0_FUNC_FLUSH_ALL   1
+#define AR9331_SW_VT0_FUNC_LOAD_ENTRY  2
+#define AR9331_SW_VT0_FUNC_PURGE_ENTRY 3
+#define AR9331_SW_VT0_FUNC_DEL_PORT4
+#define AR9331_SW_VT0_FUNC_GET_NEXT5
+
+#define AR9331_SW_REG_VLAN_TABLE_FUNCTION1 0x44
+#define AR9331_SW_VT1_VALIDBIT(11)
+#define AR9331_SW_VT1_VID_MEM  GENMASK(9, 0)
+
 /* Size of the address resolution table (ARL) */
 #define AR9331_SW_NUM_ARL_RECORDS  1024
 
@@ -308,6 +329,11 @@ struct ar9331_sw_port {
struct spinlock stats_lock;
 };
 
+struct ar9331_sw_vlan_db {
+   u16 vid;
+   u8 port_mask;
+};
+
 struct ar9331_sw_fdb {
u8 port_mask;
u8 aging;
@@ -328,6 +354,7 @@ struct ar9331_sw_priv {
struct ar9331_sw_port port[AR9331_SW_PORTS];
int cpu_port;
u32 isolated_ports;
+   struct ar9331_sw_vlan_db vdb[AR9331_SW_NUM_VLAN_RECORDS];
 };
 
 static struct ar9331_sw_priv *ar9331_sw_port_to_priv(struct ar9331_sw_port 
*port)
@@ -1273,6 +1300,231 @@ static void ar9331_sw_port_stp_state_set(struct 
dsa_switch *ds, int port,
dev_err_ratelimited(priv->dev, "%s: error: %i\n", __func__, ret);
 }
 
+static int ar9331_port_vlan_filtering(struct dsa_switch *ds, int port,
+ bool vlan_filtering,
+ struct netlink_ext_ack *extack)
+{
+   struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+   struct regmap *regmap = priv->regmap;
+   u32 mode;
+   int ret;
+
+   if (vlan_filtering)
+   mode = AR9331_SW_8021Q_MODE_SECURE;
+   else
+   mode = AR9331_SW_8021Q_MODE_NONE;
+
+   ret = regmap_update_bits(regmap, AR9331_SW_REG_PORT_VLAN(port),
+AR9331_SW_PORT_VLAN_8021Q_MODE,
+FIELD_PREP(AR9331_SW_PORT_VLAN_8021Q_MODE,
+   mode));
+   if (ret)
+   dev_err_ratelimited(priv->dev, "%s: error: %pe\n",
+   __func__, ERR_PTR(ret));
+
+   return ret;
+}
+
+static int ar9331_sw_vt_wait(struct ar9331_sw_priv *priv, u32 *f0)
+{
+   struct regmap *regmap = priv->regmap;
+
+   return regmap_read_poll_timeout(regmap,
+   AR9331_SW_REG_VLAN_TABLE_FUNCTION0,
+   *f0, !(*f0 & AR9331_SW_VT0_BUSY),
+   100, 2000);
+}
+
+static int ar9331_sw_port_vt_rmw(struct ar9331_sw_priv *priv, u16 vid,
+u8 port_mask_set, u8 port_mask_clr)
+{
+   struct regmap *regmap = priv->regmap;
+   u32 f0, f1, port_mask = 0, port_mask_new, func;
+   struct ar9331_sw_vlan_db *vdb = NULL;
+   int ret, i;
+
+   if (!vid)
+   return 0;
+
+   ret = ar9331_sw_vt_wait(priv, );
+   if (ret)
+   return ret;
+
+   ret = regmap_write(regmap, AR9331_SW_REG_VLAN_TABLE_FUNCTION0, 0);
+   if (ret)
+   goto error;
+
+   ret = regmap_write(regmap, AR9331_SW_REG_VLAN_TABLE_FUNCTION1, 0);
+   if (ret)
+   goto error;
+
+   for (i = 0; i < ARRAY_SIZE(priv->vdb); i++) {
+   if (priv->vdb[i].vid == vid) {
+

[PATCH net-next v1 1/9] net: dsa: add rcv_post call back

2021-04-03 Thread Oleksij Rempel
Some switches (for example ar9331) do not provide enough information
about forwarded packets. If the switch decision was made based on IPv4
or IPv6 header, we need to analyze it and set proper flag.

Potentially we can do it in existing rcv path, on other hand we can
avoid part of duplicated work and let the dsa framework set skb header
pointers and then use preprocessed skb one step later withing the rcv_post
call back.

This patch is needed for ar9331 switch.

Signed-off-by: Oleksij Rempel 
---
 include/net/dsa.h | 2 ++
 net/dsa/dsa.c | 4 
 net/dsa/port.c| 1 +
 3 files changed, 7 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 57b2c49f72f4..f1a7aa4303a7 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -84,6 +84,7 @@ struct dsa_device_ops {
struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
   struct packet_type *pt);
+   void (*rcv_post)(struct sk_buff *skb);
void (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
 int *offset);
/* Used to determine which traffic should match the DSA filter in
@@ -247,6 +248,7 @@ struct dsa_port {
struct dsa_switch_tree *dst;
struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
   struct packet_type *pt);
+   void (*rcv_post)(struct sk_buff *skb);
bool (*filter)(const struct sk_buff *skb, struct net_device *dev);
 
enum {
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 84cad1be9ce4..fa3e7201e760 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -249,6 +249,10 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct 
net_device *dev,
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, skb->dev);
 
+
+   if (cpu_dp->rcv_post)
+   cpu_dp->rcv_post(skb);
+
if (unlikely(!dsa_slave_dev_check(skb->dev))) {
/* Packet is to be injected directly on an upper
 * device, e.g. a team/bond, so skip all DSA-port
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 01e30264b25b..859957688c62 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -720,6 +720,7 @@ void dsa_port_set_tag_protocol(struct dsa_port *cpu_dp,
 {
cpu_dp->filter = tag_ops->filter;
cpu_dp->rcv = tag_ops->rcv;
+   cpu_dp->rcv_post = tag_ops->rcv_post;
cpu_dp->tag_ops = tag_ops;
 }
 
-- 
2.29.2



Re: [PATCH net-next v1 3/3] net: fec: add basic selftest support

2021-04-01 Thread Oleksij Rempel
On Wed, Mar 31, 2021 at 02:27:19PM +0200, Andrew Lunn wrote:
> On Tue, Mar 30, 2021 at 03:54:07PM +0200, Oleksij Rempel wrote:
> > Port some parts of the stmmac selftest to the FEC. This patch was tested
> > on iMX6DL.
> > With this tests it is possible to detect some basic issues like:
> > - MAC loopback fail: most probably wrong clock configuration.
> > - PHY loopback fail: incorrect RGMII timings, damaged traces, etc
> 
> Hi
> 
> Oleksij
> 
> I've not done a side-by-side diff with stmmac, but i guess a lot of
> this code is identical?

ack

> Rather than make a copy/paste, could you move
> it somewhere under net and turn it into a library any driver can use?

yes, I assume, it is possible to make this code complete generic for all
devices, but we will need to provide some more call backs. For example
enable MAC loop back, enable DSA loopbacks and so on.

Do you have ideas for the new location of generic selftest code and
where  can be added loopback options for different levels?

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


[PATCH net-next v1 0/3] provide basic selftest support for the ethernet FEC driver

2021-03-30 Thread Oleksij Rempel
This patch set provides diagnostic capabilities for some iMX based
boards.
So far I add only initial infrastructure with basic tests and fixed some
PHY drivers. To validate this tests, I made some common
missconfigurations like wrong RGMII type, not configured clock providers
and so on.

Oleksij Rempel (3):
  net: phy: micrel: KSZ8081: add loopback support
  net: phy: at803x: AR8085: add loopback support
  net: fec: add basic selftest support

 drivers/net/ethernet/freescale/Makefile   |   2 +-
 drivers/net/ethernet/freescale/fec.h  |   6 +
 drivers/net/ethernet/freescale/fec_main.c |   6 +
 .../net/ethernet/freescale/fec_selftests.c| 425 ++
 drivers/net/phy/at803x.c  |  25 ++
 drivers/net/phy/micrel.c  |   1 +
 6 files changed, 464 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/freescale/fec_selftests.c

-- 
2.29.2



[PATCH net-next v1 2/3] net: phy: at803x: AR8085: add loopback support

2021-03-30 Thread Oleksij Rempel
PHY loopback is needed for the ethernet controller self test support.
This PHY was tested with the FEC sefltest.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/phy/at803x.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index d7799beb811c..8679738cf2ab 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -326,6 +326,30 @@ static int at803x_resume(struct phy_device *phydev)
return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0);
 }
 
+static int at803x_loopback(struct phy_device *phydev, bool enable)
+{
+   int ret;
+
+   if (enable)
+   ret = phy_clear_bits(phydev, MII_BMCR, BMCR_ANENABLE);
+   else
+   ret = phy_set_bits(phydev, MII_BMCR, BMCR_ANENABLE);
+
+   if (ret)
+   return ret;
+
+   ret = genphy_loopback(phydev, enable);
+
+   /*
+* Loop back needs some time to start transmitting packets in the loop.
+* Documentation says nothing about it, so I take time which seems to
+* work on AR8085.
+*/
+   msleep(1);
+
+   return ret;
+}
+
 static int at803x_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev,
unsigned int selector)
 {
@@ -1128,6 +1152,7 @@ static struct phy_driver at803x_driver[] = {
.get_wol= at803x_get_wol,
.suspend= at803x_suspend,
.resume = at803x_resume,
+   .set_loopback   = at803x_loopback,
/* PHY_GBIT_FEATURES */
.read_status= at803x_read_status,
.config_intr= at803x_config_intr,
-- 
2.29.2



[PATCH net-next v1 3/3] net: fec: add basic selftest support

2021-03-30 Thread Oleksij Rempel
Port some parts of the stmmac selftest to the FEC. This patch was tested
on iMX6DL.
With this tests it is possible to detect some basic issues like:
- MAC loopback fail: most probably wrong clock configuration.
- PHY loopback fail: incorrect RGMII timings, damaged traces, etc

Signed-off-by: Oleksij Rempel 
---
 drivers/net/ethernet/freescale/Makefile   |   2 +-
 drivers/net/ethernet/freescale/fec.h  |   6 +
 drivers/net/ethernet/freescale/fec_main.c |   6 +
 .../net/ethernet/freescale/fec_selftests.c| 425 ++
 4 files changed, 438 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/freescale/fec_selftests.c

diff --git a/drivers/net/ethernet/freescale/Makefile 
b/drivers/net/ethernet/freescale/Makefile
index 67c436400352..b936c6fe5911 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -4,7 +4,7 @@
 #
 
 obj-$(CONFIG_FEC) += fec.o
-fec-objs :=fec_main.o fec_ptp.o
+fec-objs :=fec_main.o fec_ptp.o fec_selftests.o
 
 obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
 ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
diff --git a/drivers/net/ethernet/freescale/fec.h 
b/drivers/net/ethernet/freescale/fec.h
index 0602d5d5d2ee..ade6a80934bf 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -467,6 +467,9 @@ struct bufdesc_ex {
  */
 #define FEC_QUIRK_NO_HARD_RESET(1 << 18)
 
+#define FEC_ENET_DRT   (1 << 1)
+#define FEC_ENET_LOOP  (1 << 0)
+
 struct bufdesc_prop {
int qid;
/* Address of Rx and Tx buffers */
@@ -604,6 +607,9 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev);
 void fec_ptp_disable_hwts(struct net_device *ndev);
 int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
 int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
+void fec_selftest(struct net_device *ndev, struct ethtool_test *etest, u64 
*data);
+int fec_selftest_get_count(void);
+void fec_selftest_get_strings(u8 *data);
 
 //
 #endif /* FEC_H */
diff --git a/drivers/net/ethernet/freescale/fec_main.c 
b/drivers/net/ethernet/freescale/fec_main.c
index 3db882322b2b..2ca72f7b5b7d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -2474,6 +2474,9 @@ static void fec_enet_get_strings(struct net_device 
*netdev,
 {
int i;
switch (stringset) {
+   case ETH_SS_TEST:
+   fec_selftest_get_strings(data);
+   break;
case ETH_SS_STATS:
for (i = 0; i < ARRAY_SIZE(fec_stats); i++)
memcpy(data + i * ETH_GSTRING_LEN,
@@ -2485,6 +2488,8 @@ static void fec_enet_get_strings(struct net_device 
*netdev,
 static int fec_enet_get_sset_count(struct net_device *dev, int sset)
 {
switch (sset) {
+   case ETH_SS_TEST:
+   return fec_selftest_get_count();
case ETH_SS_STATS:
return ARRAY_SIZE(fec_stats);
default:
@@ -2738,6 +2743,7 @@ static const struct ethtool_ops fec_enet_ethtool_ops = {
.set_wol= fec_enet_set_wol,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
+   .self_test  = fec_selftest,
 };
 
 static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
diff --git a/drivers/net/ethernet/freescale/fec_selftests.c 
b/drivers/net/ethernet/freescale/fec_selftests.c
new file mode 100644
index ..788213a6454f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fec_selftests.c
@@ -0,0 +1,425 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Synopsys, Inc. and/or its affiliates.
+ * stmmac Selftests Support
+ *
+ * Author: Jose Abreu 
+ *
+ * Ported from stmmac to the FEC by:
+ * Copyright (C) 2021 Oleksij Rempel 
+ */
+
+#include 
+#include 
+#include 
+
+#include "fec.h"
+
+struct fec_packet_attrs {
+   unsigned char *src;
+   unsigned char *dst;
+   u32 ip_src;
+   u32 ip_dst;
+   int tcp;
+   int sport;
+   int dport;
+   int timeout;
+   int size;
+   int max_size;
+   u8 id;
+   u16 queue_mapping;
+};
+
+struct fec_test_priv {
+   struct fec_packet_attrs *packet;
+   struct packet_type pt;
+   struct completion comp;
+   int double_vlan;
+   int vlan_id;
+   int ok;
+};
+
+struct fechdr {
+   __be32 version;
+   __be64 magic;
+   u8 id;
+} __packed;
+
+static u8 fec_test_next_id;
+
+#define FEC_TEST_PKT_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) + \
+ sizeof(struct fechdr))
+#define FEC_TEST_PKT_MAGIC 0xdeadcafecafedeadULL
+#define FEC_LB_TIMEOUT msecs_to_jiffies(200)
+
+static struct sk_buff *fec_test_get_udp_skb(struct fec_enet_private *fep,
+

[PATCH net-next v1 1/3] net: phy: micrel: KSZ8081: add loopback support

2021-03-30 Thread Oleksij Rempel
PHY loopback is needed for the ethernet controller self test support.
This PHY was tested with the FEC sefltest.

Signed-off-by: Oleksij Rempel 
---
 drivers/net/phy/micrel.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index a14a00328fa3..f05345f1c602 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -1311,6 +1311,7 @@ static struct phy_driver ksphy_driver[] = {
.get_stats  = kszphy_get_stats,
.suspend= kszphy_suspend,
.resume = kszphy_resume,
+   .set_loopback   = genphy_loopback,
 }, {
.phy_id = PHY_ID_KSZ8061,
.name   = "Micrel KSZ8061",
-- 
2.29.2



Re: [PATCH v5 1/3] dt-bindings:iio:adc: add generic settling-time-us and oversampling-ratio channel properties

2021-03-29 Thread Oleksij Rempel
On Mon, Mar 29, 2021 at 11:25:32AM +0100, Jonathan Cameron wrote:
> On Mon, 29 Mar 2021 09:31:29 +0200
> Oleksij Rempel  wrote:
> 
> > Settling time and over sampling is a typical challenge for different IIO ADC
> > devices. So, introduce channel specific settling-time-us and 
> > oversampling-ratio
> > properties to cover this use case.
> > 
> > Signed-off-by: Oleksij Rempel 
> > ---
> >  Documentation/devicetree/bindings/iio/adc/adc.yaml | 8 
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml 
> > b/Documentation/devicetree/bindings/iio/adc/adc.yaml
> > index 912a7635edc4..d5bc86d2a2af 100644
> > --- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
> > +++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
> > @@ -39,4 +39,12 @@ properties:
> >The first value specifies the positive input pin, the second
> >specifies the negative input pin.
> >  
> > +  settling-time-us:
> > +description:
> > +  Time between enabling the channel and firs stable readings.
> 
> first

ack

> > +
> > +  oversampling-ratio:
> > +$ref: /schemas/types.yaml#/definitions/uint32
> > +description: Number of data samples which are averaged for each read.
> 
> I think I've asked about this in previous reviews, but I want a clear 
> statement
> of why you think this property is a feature of the 'board' (and hence should 
> be
> in device tree) rather than setting sensible defaults and leaving any control
> to userspace?

yes, my reply was:
> Oversampling is used as replacement of or addition to the low-pass filter. The
> filter can be implemented on board, but it will change settling time
> characteristic. Since low-pass filter is board specific characteristic, this
> property belongs in device tree as well.

I could imagine that this values can be overwritten from user space for
diagnostic, but we need some working default values. 

Should I integrate this comment in to the yaml?

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


Re: [PATCH v2 0/7] remove different PHY fixups

2021-03-29 Thread Oleksij Rempel
On Mon, Mar 29, 2021 at 08:44:59AM +0800, Shawn Guo wrote:
> On Wed, Mar 24, 2021 at 06:54:24AM +0100, Oleksij Rempel wrote:
> > Hi Shawn,
> > 
> > ping, do this patches need some ACK from some one?
> 
> As this will break existing DTBs, I need more ACKs from people to see
> the consensus that this is the right thing to do.

Do you need ACKs from some concrete people?

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


Re: [PATCH v3 3/3] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-29 Thread Oleksij Rempel
On Mon, Mar 22, 2021 at 02:27:22PM +, Jonathan Cameron wrote:
> > > > +static DECLARE_TI_TSC2046_8_CHANNELS(tsc2046_adc, 12);
> > > > +
> > > > +static const struct tsc2046_adc_dcfg tsc2046_adc_dcfg_tsc2046e = {
> > > > +   .channels = tsc2046_adc_channels,
> > > > +   .num_channels = ARRAY_SIZE(tsc2046_adc_channels),
> > > > +};
> > > > +  
> > > 
> > > Hmm.  Flexibility that isn't yet used.  Normally I'm pretty resistant
> > > to this going in, unless I'm reassured that there is support for 
> > > additional
> > > devices already in the pipeline.  Is that true here?  Otherwise
> > > this is basically unneeded complexity.  
> > 
> > In the long term this driver should replace
> > drivers/input/touchscreen/ads7846.c
> > 
> > This driver supports ti,ads7843, ti,ads7845, ti,ads7846.. at least with
> > following number of supported channels:
> > ti,ads7843 - 4 channels: x, y, aux0, aux1
> > ti,ads7845 - 3 channels: x, y, aux0
> > ti,ads7846 - 8 channels...
> > 
> > Currently I don't have this HW for testing and there a subtle
> > differences that have to be taken care of and tested.
> > 
> 
> Note that I'm only going to merge this driver with an explicit statement
> from Dmitry as input maintainer that he is fine with this approach.

Since there is still no Dmitry's feedback please take a look to the
ti,ads7843 datasheet:
https://www.ti.com/lit/ds/symlink/ads7843.pdf

On the page 1 you can see, that this device has two general purpose ADC
inputs IN3, IN4. If some one will decide to mainline support for this
pins, will end with IIO ADC driver any way :)

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


[PATCH v5 2/3] dt-bindings:iio:adc: add documentation for TI TSC2046 controller

2021-03-29 Thread Oleksij Rempel
Add a binding documentation for the TI TSC2046 touchscreen controllers
ADC functionality.

Signed-off-by: Oleksij Rempel 
Reviewed-by: Rob Herring 
---
 .../bindings/iio/adc/ti,tsc2046.yaml  | 115 ++
 1 file changed, 115 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml

diff --git a/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml 
b/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
new file mode 100644
index ..601d69971d84
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/ti,tsc2046.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments TSC2046 touch screen controller.
+
+maintainers:
+  - Oleksij Rempel 
+
+description: |
+  TSC2046 is a touch screen controller with 8 channels ADC.
+
+properties:
+  compatible:
+enum:
+  - ti,tsc2046e-adc
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  spi-max-frequency: true
+
+  "#io-channel-cells":
+const: 1
+
+  '#address-cells':
+const: 1
+
+  '#size-cells':
+const: 0
+
+required:
+  - compatible
+  - reg
+
+patternProperties:
+  "^channel@[0-7]$":
+$ref: "adc.yaml"
+type: object
+
+properties:
+  reg:
+description: |
+  The channel number. It can have up to 8 channels
+items:
+  minimum: 0
+  maximum: 7
+
+  settling-time-us: true
+  oversampling-ratio: true
+
+required:
+  - reg
+
+additionalProperties: false
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+spi {
+#address-cells = <1>;
+#size-cells = <0>;
+
+adc@0 {
+compatible = "ti,tsc2046e-adc";
+reg = <0>;
+spi-max-frequency = <100>;
+interrupts-extended = < 20 IRQ_TYPE_LEVEL_LOW>;
+#io-channel-cells = <1>;
+
+#address-cells = <1>;
+#size-cells = <0>;
+
+channel@0 {
+  reg = <0>;
+};
+channel@1 {
+  reg = <1>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@2 {
+  reg = <2>;
+};
+channel@3 {
+  reg = <3>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@4 {
+  reg = <4>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@5 {
+  reg = <5>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@6 {
+  reg = <6>;
+};
+channel@7 {
+  reg = <7>;
+};
+};
+};
+...
-- 
2.29.2



[PATCH v5 1/3] dt-bindings:iio:adc: add generic settling-time-us and oversampling-ratio channel properties

2021-03-29 Thread Oleksij Rempel
Settling time and over sampling is a typical challenge for different IIO ADC
devices. So, introduce channel specific settling-time-us and oversampling-ratio
properties to cover this use case.

Signed-off-by: Oleksij Rempel 
---
 Documentation/devicetree/bindings/iio/adc/adc.yaml | 8 
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml 
b/Documentation/devicetree/bindings/iio/adc/adc.yaml
index 912a7635edc4..d5bc86d2a2af 100644
--- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
@@ -39,4 +39,12 @@ properties:
   The first value specifies the positive input pin, the second
   specifies the negative input pin.
 
+  settling-time-us:
+description:
+  Time between enabling the channel and firs stable readings.
+
+  oversampling-ratio:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: Number of data samples which are averaged for each read.
+
 additionalProperties: true
-- 
2.29.2



[PATCH v5 3/3] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-29 Thread Oleksij Rempel
Basically the TI TSC2046 touchscreen controller is 8 channel ADC optimized for
the touchscreen use case. By implementing it as an IIO ADC device, we can
make use of resistive-adc-touch and iio-hwmon drivers.

Polled readings are currently not implemented to keep this patch small, so
iio-hwmon will not work out of the box for now.

So far, this driver was tested with a custom version of resistive-adc-touch 
driver,
since it needs to be extended to make use of Z1 and Z2 channels. The X/Y
are working without additional changes.

Signed-off-by: Oleksij Rempel 
Reviewed-by: Andy Shevchenko 
---
 MAINTAINERS  |   8 +
 drivers/iio/adc/Kconfig  |  12 +
 drivers/iio/adc/Makefile |   1 +
 drivers/iio/adc/ti-tsc2046.c | 726 +++
 4 files changed, 747 insertions(+)
 create mode 100644 drivers/iio/adc/ti-tsc2046.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 9a9bf18bba00..e288fae26cde 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18013,6 +18013,14 @@ S: Supported
 F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt
 F: drivers/nfc/trf7970a.c
 
+TI TSC2046 ADC DRIVER
+M: Oleksij Rempel 
+R: ker...@pengutronix.de
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
+F: drivers/iio/adc/ti-tsc2046.c
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi 
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 769381b05b9a..6fe8d1046b4b 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1188,6 +1188,18 @@ config TI_TLC4541
  This driver can also be built as a module. If so, the module will be
  called ti-tlc4541.
 
+config TI_TSC2046
+   tristate "Texas Instruments TSC2046 ADC driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to build support for ADC functionality of Texas
+ Instruments TSC2046 touch screen controller.
+
+ This driver can also be built as a module. If so, the module will be
+ called ti-tsc2046.
+
 config TWL4030_MADC
tristate "TWL4030 MADC (Monitoring A/D Converter)"
depends on TWL4030_CORE
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index a226657d19c0..f70d877c555a 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o
 obj-$(CONFIG_TI_ADS131E08) += ti-ads131e08.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
 obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o
+obj-$(CONFIG_TI_TSC2046) += ti-tsc2046.o
 obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
 obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
 obj-$(CONFIG_VF610_ADC) += vf610_adc.o
diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c
new file mode 100644
index ..7fe3c677ab1c
--- /dev/null
+++ b/drivers/iio/adc/ti-tsc2046.c
@@ -0,0 +1,726 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Texas Instruments TSC2046 SPI ADC driver
+ *
+ * Copyright (c) 2021 Oleksij Rempel , Pengutronix
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * The PENIRQ of TSC2046 controller is implemented as level shifter attached to
+ * the X+ line. If voltage of the X+ line reaches a specific level the IRQ will
+ * be activated or deactivated.
+ * To make this kind of IRQ reusable as trigger following additions were
+ * implemented:
+ * - rate limiting:
+ *   For typical touchscreen use case, we need to trigger about each 10ms.
+ * - hrtimer:
+ *   Continue triggering at least once after the IRQ was deactivated. Then
+ *   deactivate this trigger to stop sampling in order to reduce power
+ *   consumption.
+ */
+
+#define TI_TSC2046_NAME"tsc2046"
+
+/* This driver doesn't aim at the peak continuous sample rate */
+#defineTI_TSC2046_MAX_SAMPLE_RATE  125000
+#defineTI_TSC2046_SAMPLE_BITS \
+   BITS_PER_TYPE(struct tsc2046_adc_atom)
+#defineTI_TSC2046_MAX_CLK_FREQ \
+   (TI_TSC2046_MAX_SAMPLE_RATE * TI_TSC2046_SAMPLE_BITS)
+
+#define TI_TSC2046_SAMPLE_INTERVAL_US  1
+
+#define TI_TSC2046_START   BIT(7)
+#define TI_TSC2046_ADDRGENMASK(6, 4)
+#define TI_TSC2046_ADDR_TEMP1  7
+#define TI_TSC2046_ADDR_AUX6
+#define TI_TSC2046_ADDR_X  5
+#define TI_TSC2046_ADDR_Z2 4
+#define TI_TSC2046_ADDR_Z1 3
+#define TI_TSC2046_ADDR_VBAT   2
+#define TI_TSC2046_ADDR_Y  1
+#define TI_TSC2046_ADDR_TEMP0  0
+
+/*
+ * The mode bit sets the resolution of the ADC. With this bit low, the next
+ * conversion 

[PATCH v5 0/3] mainline ti tsc2046 adc driver

2021-03-29 Thread Oleksij Rempel
changes v5:
- remove type for the settling-time-us property

changes v4:
- spell fixes
- add more comments
- make code more readable
- move scan_buf to the priv
- use FIELD_GET to extract ADC data
- make some multi line code as one line
- do not use atomic API for trig_more_count
- fix build warning on 64bit system
- add NULL check for the devm_kasprintf()
- use return devm_iio_device_register(), without additional error
  printing.

changes v3:
- different spell fixes
- add some notes about driver structure
- rename the trigger to point on the touchscreen nature of it
- rename DT binding to oversampling-ratio
- make sure we have some defaults in case no DT property is set

changes v2:
- rework and extend DT binding properties
- remove touchscreen related code from the IIO ADC driver
- make trigger be active longer then IRQ is requesting. This is needed
  to get "inactive" samples
- make oversampling and settle time configurable

TI TSC2046 is a touchscreen controller based on 8 channel ADC. Since most of
this ADC based touchscreen controller share same set of challenges, it
is better keep then as simple IIO ADC devices attached to a generic
resistive-adc-touch driver.

This driver can replace drivers/input/touchscreen/ads7846.c and has
following advantages over it:
- less code to maintain
- shared code paths (resistive-adc-touch, iio-hwmon, etc)
- can be used as plain IIO ADC to investigate signaling issues or test
  real capacity of the plates and attached low-pass filters
  (or use the touchscreen as a microphone if you like ;) )

Oleksij Rempel (3):
  dt-bindings:iio:adc: add generic settling-time-us and
oversampling-ratio channel properties
  dt-bindings:iio:adc: add documentation for TI TSC2046 controller
  iio: adc: add ADC driver for the TI TSC2046 controller

 .../devicetree/bindings/iio/adc/adc.yaml  |   8 +
 .../bindings/iio/adc/ti,tsc2046.yaml  | 115 +++
 MAINTAINERS   |   8 +
 drivers/iio/adc/Kconfig   |  12 +
 drivers/iio/adc/Makefile  |   1 +
 drivers/iio/adc/ti-tsc2046.c  | 726 ++
 6 files changed, 870 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
 create mode 100644 drivers/iio/adc/ti-tsc2046.c

-- 
2.29.2



Re: [PATCH v2 0/7] remove different PHY fixups

2021-03-23 Thread Oleksij Rempel
Hi Shawn,

ping, do this patches need some ACK from some one?

Regards,
Oleksij

On Tue, Mar 09, 2021 at 12:26:08PM +0100, Oleksij Rempel wrote:
> changes v2:
> - rebase against latest kernel
> - fix networking on RIoTBoard
> 
> This patch series tries to remove most of the imx6 and imx7 board
> specific PHY configuration via fixup, as this breaks the PHYs when
> connected to switch chips or USB Ethernet MACs.
> 
> Each patch has the possibility to break boards, but contains a
> recommendation to fix the problem in a more portable and future-proof
> way.
> 
> regards,
> Oleksij
> 
> Oleksij Rempel (7):
>   ARM: imx6q: remove PHY fixup for KSZ9031
>   ARM: imx6q: remove TX clock delay of ar8031_phy_fixup()
>   ARM: imx6q: remove hand crafted PHY power up in ar8035_phy_fixup()
>   ARM: imx6q: remove clk-out fixup for the Atheros AR8031 and AR8035
> PHYs
>   ARM: imx6q: remove Atheros AR8035 SmartEEE fixup
>   ARM: imx6sx: remove Atheros AR8031 PHY fixup
>   ARM: imx7d: remove Atheros AR8031 PHY fixup
> 
>  arch/arm/boot/dts/imx6dl-riotboard.dts  |  2 +
>  arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts |  2 +-
>  arch/arm/mach-imx/mach-imx6q.c  | 85 -
>  arch/arm/mach-imx/mach-imx6sx.c | 26 
>  arch/arm/mach-imx/mach-imx7d.c  | 22 ---
>  5 files changed, 3 insertions(+), 134 deletions(-)
> 
> -- 
> 2.29.2
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


[PATCH v4 1/3] dt-bindings:iio:adc: add generic settling-time-us and oversampling-ratio channel properties

2021-03-22 Thread Oleksij Rempel
Settling time and over sampling is a typical challenge for different IIO ADC
devices. So, introduce channel specific settling-time-us and oversampling-ratio
properties to cover this use case.

Signed-off-by: Oleksij Rempel 
---
 Documentation/devicetree/bindings/iio/adc/adc.yaml | 9 +
 1 file changed, 9 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml 
b/Documentation/devicetree/bindings/iio/adc/adc.yaml
index 912a7635edc4..66fd4b45f097 100644
--- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
@@ -39,4 +39,13 @@ properties:
   The first value specifies the positive input pin, the second
   specifies the negative input pin.
 
+  settling-time-us:
+$ref: /schemas/types.yaml#/definitions/uint32
+description:
+  Time between enabling the channel and firs stable readings.
+
+  oversampling-ratio:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: Number of data samples which are averaged for each read.
+
 additionalProperties: true
-- 
2.29.2



[PATCH v4 2/3] dt-bindings:iio:adc: add documentation for TI TSC2046 controller

2021-03-22 Thread Oleksij Rempel
Add a binding documentation for the TI TSC2046 touchscreen controllers
ADC functionality.

Signed-off-by: Oleksij Rempel 
Reviewed-by: Rob Herring 
---
 .../bindings/iio/adc/ti,tsc2046.yaml  | 115 ++
 1 file changed, 115 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml

diff --git a/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml 
b/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
new file mode 100644
index ..601d69971d84
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/ti,tsc2046.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments TSC2046 touch screen controller.
+
+maintainers:
+  - Oleksij Rempel 
+
+description: |
+  TSC2046 is a touch screen controller with 8 channels ADC.
+
+properties:
+  compatible:
+enum:
+  - ti,tsc2046e-adc
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  spi-max-frequency: true
+
+  "#io-channel-cells":
+const: 1
+
+  '#address-cells':
+const: 1
+
+  '#size-cells':
+const: 0
+
+required:
+  - compatible
+  - reg
+
+patternProperties:
+  "^channel@[0-7]$":
+$ref: "adc.yaml"
+type: object
+
+properties:
+  reg:
+description: |
+  The channel number. It can have up to 8 channels
+items:
+  minimum: 0
+  maximum: 7
+
+  settling-time-us: true
+  oversampling-ratio: true
+
+required:
+  - reg
+
+additionalProperties: false
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+spi {
+#address-cells = <1>;
+#size-cells = <0>;
+
+adc@0 {
+compatible = "ti,tsc2046e-adc";
+reg = <0>;
+spi-max-frequency = <100>;
+interrupts-extended = < 20 IRQ_TYPE_LEVEL_LOW>;
+#io-channel-cells = <1>;
+
+#address-cells = <1>;
+#size-cells = <0>;
+
+channel@0 {
+  reg = <0>;
+};
+channel@1 {
+  reg = <1>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@2 {
+  reg = <2>;
+};
+channel@3 {
+  reg = <3>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@4 {
+  reg = <4>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@5 {
+  reg = <5>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@6 {
+  reg = <6>;
+};
+channel@7 {
+  reg = <7>;
+};
+};
+};
+...
-- 
2.29.2



[PATCH v4 0/3] mainline ti tsc2046 adc driver

2021-03-22 Thread Oleksij Rempel
changes v4:
- spell fixes
- add more comments
- make code more readable
- move scan_buf to the priv
- use FIELD_GET to extract ADC data
- make some multi line code as one line
- do not use atomic API for trig_more_count
- fix build warning on 64bit system
- add NULL check for the devm_kasprintf()
- use return devm_iio_device_register(), without additional error
  printing.

changes v3:
- different spell fixes
- add some notes about driver structure
- rename the trigger to point on the touchscreen nature of it
- rename DT binding to oversampling-ratio
- make sure we have some defaults in case no DT property is set

changes v2:
- rework and extend DT binding properties
- remove touchscreen related code from the IIO ADC driver
- make trigger be active longer then IRQ is requesting. This is needed
  to get "inactive" samples
- make oversampling and settle time configurable

TI TSC2046 is a touchscreen controller based on 8 channel ADC. Since most of
this ADC based touchscreen controller share same set of challenges, it
is better keep then as simple IIO ADC devices attached to a generic
resistive-adc-touch driver.

This driver can replace drivers/input/touchscreen/ads7846.c and has
following advantages over it:
- less code to maintain
- shared code paths (resistive-adc-touch, iio-hwmon, etc)
- can be used as plain IIO ADC to investigate signaling issues or test
  real capacity of the plates and attached low-pass filters
  (or use the touchscreen as a microphone if you like ;) )

Oleksij Rempel (3):
  dt-bindings:iio:adc: add generic settling-time-us and
oversampling-ratio channel properties
  dt-bindings:iio:adc: add documentation for TI TSC2046 controller
  iio: adc: add ADC driver for the TI TSC2046 controller

 .../devicetree/bindings/iio/adc/adc.yaml  |   9 +
 .../bindings/iio/adc/ti,tsc2046.yaml  | 115 +++
 MAINTAINERS   |   8 +
 drivers/iio/adc/Kconfig   |  12 +
 drivers/iio/adc/Makefile  |   1 +
 drivers/iio/adc/ti-tsc2046.c  | 726 ++
 6 files changed, 871 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
 create mode 100644 drivers/iio/adc/ti-tsc2046.c

-- 
2.29.2



[PATCH v4 3/3] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-22 Thread Oleksij Rempel
Basically the TI TSC2046 touchscreen controller is 8 channel ADC optimized for
the touchscreen use case. By implementing it as an IIO ADC device, we can
make use of resistive-adc-touch and iio-hwmon drivers.

Polled readings are currently not implemented to keep this patch small, so
iio-hwmon will not work out of the box for now.

So far, this driver was tested with a custom version of resistive-adc-touch 
driver,
since it needs to be extended to make use of Z1 and Z2 channels. The X/Y
are working without additional changes.

Signed-off-by: Oleksij Rempel 
Reviewed-by: Andy Shevchenko 
---
 MAINTAINERS  |   8 +
 drivers/iio/adc/Kconfig  |  12 +
 drivers/iio/adc/Makefile |   1 +
 drivers/iio/adc/ti-tsc2046.c | 726 +++
 4 files changed, 747 insertions(+)
 create mode 100644 drivers/iio/adc/ti-tsc2046.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 9a9bf18bba00..e288fae26cde 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18013,6 +18013,14 @@ S: Supported
 F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt
 F: drivers/nfc/trf7970a.c
 
+TI TSC2046 ADC DRIVER
+M: Oleksij Rempel 
+R: ker...@pengutronix.de
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
+F: drivers/iio/adc/ti-tsc2046.c
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi 
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 769381b05b9a..6fe8d1046b4b 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1188,6 +1188,18 @@ config TI_TLC4541
  This driver can also be built as a module. If so, the module will be
  called ti-tlc4541.
 
+config TI_TSC2046
+   tristate "Texas Instruments TSC2046 ADC driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to build support for ADC functionality of Texas
+ Instruments TSC2046 touch screen controller.
+
+ This driver can also be built as a module. If so, the module will be
+ called ti-tsc2046.
+
 config TWL4030_MADC
tristate "TWL4030 MADC (Monitoring A/D Converter)"
depends on TWL4030_CORE
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index a226657d19c0..f70d877c555a 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o
 obj-$(CONFIG_TI_ADS131E08) += ti-ads131e08.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
 obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o
+obj-$(CONFIG_TI_TSC2046) += ti-tsc2046.o
 obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
 obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
 obj-$(CONFIG_VF610_ADC) += vf610_adc.o
diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c
new file mode 100644
index ..7fe3c677ab1c
--- /dev/null
+++ b/drivers/iio/adc/ti-tsc2046.c
@@ -0,0 +1,726 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Texas Instruments TSC2046 SPI ADC driver
+ *
+ * Copyright (c) 2021 Oleksij Rempel , Pengutronix
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * The PENIRQ of TSC2046 controller is implemented as level shifter attached to
+ * the X+ line. If voltage of the X+ line reaches a specific level the IRQ will
+ * be activated or deactivated.
+ * To make this kind of IRQ reusable as trigger following additions were
+ * implemented:
+ * - rate limiting:
+ *   For typical touchscreen use case, we need to trigger about each 10ms.
+ * - hrtimer:
+ *   Continue triggering at least once after the IRQ was deactivated. Then
+ *   deactivate this trigger to stop sampling in order to reduce power
+ *   consumption.
+ */
+
+#define TI_TSC2046_NAME"tsc2046"
+
+/* This driver doesn't aim at the peak continuous sample rate */
+#defineTI_TSC2046_MAX_SAMPLE_RATE  125000
+#defineTI_TSC2046_SAMPLE_BITS \
+   BITS_PER_TYPE(struct tsc2046_adc_atom)
+#defineTI_TSC2046_MAX_CLK_FREQ \
+   (TI_TSC2046_MAX_SAMPLE_RATE * TI_TSC2046_SAMPLE_BITS)
+
+#define TI_TSC2046_SAMPLE_INTERVAL_US  1
+
+#define TI_TSC2046_START   BIT(7)
+#define TI_TSC2046_ADDRGENMASK(6, 4)
+#define TI_TSC2046_ADDR_TEMP1  7
+#define TI_TSC2046_ADDR_AUX6
+#define TI_TSC2046_ADDR_X  5
+#define TI_TSC2046_ADDR_Z2 4
+#define TI_TSC2046_ADDR_Z1 3
+#define TI_TSC2046_ADDR_VBAT   2
+#define TI_TSC2046_ADDR_Y  1
+#define TI_TSC2046_ADDR_TEMP0  0
+
+/*
+ * The mode bit sets the resolution of the ADC. With this bit low, the next
+ * conversion 

Re: [PATCH v3 3/3] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-22 Thread Oleksij Rempel
On Mon, Mar 22, 2021 at 03:41:22PM +0200, Andy Shevchenko wrote:
> On Mon, Mar 22, 2021 at 12:30 PM Oleksij Rempel  
> wrote:
> > On Fri, Mar 19, 2021 at 07:42:41PM +0200, Andy Shevchenko wrote:
> > > On Fri, Mar 19, 2021 at 4:45 PM Oleksij Rempel  
> > > wrote:
> 
> ...
> 
> > > > +static u16 tsc2046_adc_get_value(struct tsc2046_adc_atom *buf)
> > > > +{
> > > > +   /* Last 3 bits on the wire are empty */
> > >
> > > Last?! You meant Least significant?
> >
> > ACK. LSB
> >
> > > Also, don't we lose precision if a new compatible chip appears that
> > > does fill those bits?
> >
> > ACK. All of controllers supported by this driver:
> > drivers/input/touchscreen/ads7846.c:
> > - ti,tsc2046
> > - ti,ads7843
> > - ti,ads7845
> > - ti,ads7846
> > - ti,ads7873 (hm, there is no ti,ads7873, is it actually analog devices 
> > AD7873?)
> >
> > support 8- or 12-bit resolution. Only 12 bit mode is supported by this
> > driver. It is possible that some one can produce a resistive touchscreen
> > controller based on X > 12bit ADC, but this will probably not increase 
> > precision
> > of this construction (there is a lot of noise any ways...). With other
> > words, it is possible, but not probably that some one will really do it.
> >
> > > Perhaps define the constant and put a comment why it's like this.
> 
> Okay, and what happens here is something like cutting LSBs, but it
> sounds strange to me. If you get 16 bit values, the MSBs should not be
> used?
> 
> So, a good comment is required to explain the logic behind.
> 
> > > > +   return get_unaligned_be16(>data) >> 3;
> > > > +}
> 
> ...
> 
> > > > +static size_t tsc2046_adc_group_set_layout(struct tsc2046_adc_priv 
> > > > *priv,
> > > > +  unsigned int group,
> > > > +  unsigned int ch_idx)
> > > > +{
> > > > +   struct tsc2046_adc_ch_cfg *ch = >ch_cfg[ch_idx];
> > > > +   struct tsc2046_adc_group_layout *prev, *cur;
> > > > +   unsigned int max_count, count_skip;
> > > > +   unsigned int offset = 0;
> > > > +
> > > > +   if (group) {
> > > > +   prev = >l[group - 1];
> > > > +   offset = prev->offset + prev->count;
> > > > +   }
> > >
> > > I guess you may easily refactor this by supplying a pointer to the
> > > current layout + current size.
> >
> > Sure, but this will not make code more readable and it will not affect
> > the performance. Are there any other reason to do it? Just to make one
> > line instead of two?
> 
> It's still N - 1 unneeded checks and code is slightly harder to read.

fixed

> > > > +   cur = >l[group];
> > >
> > > Also, can you move it down closer to the (single?) caller.
> > >
> > > > +}
> 
> ...
> 
> > > > +   dev_err_ratelimited(dev, "SPI transfer filed: %pe\n",
> > > > +   ERR_PTR(ret));
> > >
> > > One line?
> >
> > it will exceed the 80 char rule
> 
> It's fine here.

fixed

> ...
> 
> > > > +   spin_lock_irqsave(>trig_lock, flags);
> > > > +
> > > > +   disable_irq_nosync(priv->spi->irq);
> > >
> > > > +   atomic_inc(>trig_more_count);
> > >
> > > You already have a spin lock, do you need to use the atomic API?
> >
> > I can only pass review comment from my other driver:
> > Memory locations that are concurrently accessed needs to be
> > marked as such, otherwise the compiler is allowed to funky stuff:
> > https://lore.kernel.org/lkml/CAGzjT4ez+gWr3BFQsEr-wma+vs6UZNJ+mRARx_BWoAKEJSsN=w...@mail.gmail.com/
> >
> > And here is one more link:
> > https://lwn.net/Articles/793253/#How%20Real%20Is%20All%20This?
> >
> > Starting with commit 62e8a3258bda atomic API is using READ/WRITE_ONCE,
> > so I assume, I do nothing wrong by using it. Correct?
> 
> Hmm... What I don't understand here is why you need a second level of
> atomicity. spin lock already makes this access atomic (at least I have
> checked couple of places and in both the variable is being accessed
> under spin lock).

fixed

> > > > +   iio_trigger_poll(priv->trig);
> > > > +
> > > 

Re: [PATCH v3 3/3] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-22 Thread Oleksij Rempel
Hi,

On Sat, Mar 20, 2021 at 03:46:01PM +, Jonathan Cameron wrote:
> On Fri, 19 Mar 2021 15:45:09 +0100
> Oleksij Rempel  wrote:
> 
> > Basically the TI TSC2046 touchscreen controller is 8 channel ADC optimized 
> > for
> > the touchscreen use case. By implementing it as an IIO ADC device, we can
> > make use of resistive-adc-touch and iio-hwmon drivers.
> > 
> > So far, this driver was tested with a custom version of resistive-adc-touch 
> > driver,
> > since it needs to be extended to make use of Z1 and Z2 channels. The X/Y
> > are working without additional changes.
> > 
> > Signed-off-by: Oleksij Rempel 
> > Reviewed-by: Andy Shevchenko 
> Not a lot to add to Andy's review.  A few minor things inline.
> Biggest one is I think we should call out that we expect to add single
> channel polled reading + scales etc in future to enable the iio-hwmon
> usecase.
> 
> Jonathan
> 
> > ---
> >  MAINTAINERS  |   8 +
> >  drivers/iio/adc/Kconfig  |  12 +
> >  drivers/iio/adc/Makefile |   1 +
> >  drivers/iio/adc/ti-tsc2046.c | 728 +++
> >  4 files changed, 749 insertions(+)
> >  create mode 100644 drivers/iio/adc/ti-tsc2046.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 0455cfd5c76c..2ea85a5bb4dd 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -18002,6 +18002,14 @@ S: Supported
> >  F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt
> >  F: drivers/nfc/trf7970a.c
> >  
> > +TI TSC2046 ADC DRIVER
> > +M: Oleksij Rempel 
> > +R: ker...@pengutronix.de
> > +L: linux-...@vger.kernel.org
> > +S: Maintained
> > +F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
> > +F: drivers/iio/adc/ti-tsc2046.c
> > +
> >  TI TWL4030 SERIES SOC CODEC DRIVER
> >  M: Peter Ujfalusi 
> >  L: alsa-de...@alsa-project.org (moderated for non-subscribers)
> ...
> > diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c
> > new file mode 100644
> > index ..c8c0dd9087c5
> > --- /dev/null
> > +++ b/drivers/iio/adc/ti-tsc2046.c
> > @@ -0,0 +1,728 @@
> > +/*
> > + * The PENIRQ of TSC2046 controller is implemented as level shifter 
> > attached to
> > + * the X+ line. If voltage of the X+ line reaches a specific level the IRQ 
> > will
> > + * be activated or deactivated.
> > + * To make this kind of IRQ reusable as trigger following additions were
> > + * implemented:
> > + * - rate limiting:
> > + *   For typical touchscreen use case, we need to trigger about each 10ms.
> > + * - hrtimer:
> > + *   Continue triggering at least once after the IRQ was deactivated. Then
> > + *   deactivate this trigger to stop sampling in order to reduce power
> > + *   consumption.
> > + */
> 
> Good description :)
> 
> ...
> 
> 
> > +
> > +struct tsc2046_adc_scan_buf {
> > +   /* Scan data for each channel */
> > +   u16 data[TI_TSC2046_MAX_CHAN];
> > +   /* Timestamp */
> > +   s64 ts __aligned(8);
> > +};
> 
> ...
> 
> > +struct tsc2046_adc_priv {
> > +   struct spi_device *spi;
> > +   const struct tsc2046_adc_dcfg *dcfg;
> > +
> > +   struct iio_trigger *trig;
> > +   struct hrtimer trig_timer;
> > +   spinlock_t trig_lock;
> > +   atomic_t trig_more_count;
> > +
> > +   struct spi_transfer xfer;
> > +   struct spi_message msg;
> > +
> > +   struct tsc2046_adc_scan_buf scan_buf;
> 
> Given the type tsc2046_adc_scan_buf is never used for anything else
> you could make things more compact by using 
>   struct {
>   } scan_buf; 
> 
> > +   /*
> > +* Lock to protect the layout and the spi transfer buffer.
> > +* tsc2046_adc_group_layout can be changed within update_scan_mode(),
> > +* in this case the l[] and tx/rx buffer will be out of sync to each
> > +* other.
> > +*/
> > +   struct mutex slock;
> > +   struct tsc2046_adc_group_layout l[TI_TSC2046_MAX_CHAN];
> > +   struct tsc2046_adc_atom *rx;
> > +   struct tsc2046_adc_atom *tx;
> > +
> > +   struct tsc2046_adc_atom *rx_one;
> > +   struct tsc2046_adc_atom *tx_one;
> > +
> > +   unsigned int count;
> > +   unsigned int groups;
> > +   u32 effective_speed_hz;
> > +   u32 scan_interval_us;
> > +   u32 time_per_scan_us;
> > +   u32 time_per_bit_ns;
> > +
> > +   struct tsc2046_adc_ch_cfg ch_cfg[TI_TSC2046_MAX_CHAN];
> > +};
> > +

Re: [PATCH v3 3/3] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-22 Thread Oleksij Rempel
On Fri, Mar 19, 2021 at 07:42:41PM +0200, Andy Shevchenko wrote:
> On Fri, Mar 19, 2021 at 4:45 PM Oleksij Rempel  
> wrote:
> >
> > Basically the TI TSC2046 touchscreen controller is 8 channel ADC optimized 
> > for
> > the touchscreen use case. By implementing it as an IIO ADC device, we can
> > make use of resistive-adc-touch and iio-hwmon drivers.
> >
> > So far, this driver was tested with a custom version of resistive-adc-touch 
> > driver,
> > since it needs to be extended to make use of Z1 and Z2 channels. The X/Y
> > are working without additional changes.
> 
> Since kbuild bot found some issues and it will be v4, some additional
> comments from me below.
> ...
> 
> > +#defineTI_TSC2046_SAMPLE_BITS \
> > +   (sizeof(struct tsc2046_adc_atom) * BITS_PER_BYTE)
> 
> Isn't it something like BITS_PER_TYPE(struct ...) ?

sounds good.

> ...
> 
> > +struct tsc2046_adc_atom {
> > +   /*
> > +* Command transmitted to the controller. This filed is empty on 
> > the RX
> > +* buffer.
> > +*/
> > +   u8 cmd;
> > +   /*
> > +* Data received from the controller. This filed is empty for the TX
> > +* buffer
> > +*/
> > +   __be16 data;
> > +} __packed;
> 
> filed -> field in both cases above.

done

> ...
> 
> > +   /*
> > +* Lock to protect the layout and the spi transfer buffer.
> 
> SPI
> 
> > +* tsc2046_adc_group_layout can be changed within 
> > update_scan_mode(),
> > +* in this case the l[] and tx/rx buffer will be out of sync to each
> > +* other.
> > +*/
> 
> ...
> 
> > +static unsigned int tsc2046_adc_time_to_count(struct tsc2046_adc_priv 
> > *priv,
> > + unsigned long time)
> > +{
> > +   unsigned int bit_count, sample_count;
> > +
> > +   bit_count = DIV_ROUND_UP(time * NSEC_PER_USEC, 
> > priv->time_per_bit_ns);
> 
> Does it survive 32-bit builds?

ACK. I develop and test it on 32bit ARM

> > +   sample_count = DIV_ROUND_UP(bit_count, TI_TSC2046_SAMPLE_BITS);
> > +
> > +   dev_dbg(>spi->dev, "Effective speed %u, time per bit: %u, 
> > count bits: %u, count samples: %u\n",
> > +   priv->effective_speed_hz, priv->time_per_bit_ns,
> > +   bit_count, sample_count);
> > +
> > +   return sample_count;
> > +}
> 
> ...
> 
> > +   /*
> > +* if PD bits are 0, controller will automatically disable ADC, 
> > VREF and
> > +* enable IRQ.
> > +*/
> > +   if (keep_power)
> > +   pd = TI_TSC2046_PD0_ADC_ON;
> > +   else
> > +   pd = 0;
> 
> Can be ternary on one line, but it's up to you.

ACK. I'll keep it

> ...
> 
> > +static u16 tsc2046_adc_get_value(struct tsc2046_adc_atom *buf)
> > +{
> > +   /* Last 3 bits on the wire are empty */
> 
> Last?! You meant Least significant?

ACK. LSB

> Also, don't we lose precision if a new compatible chip appears that
> does fill those bits?

ACK. All of controllers supported by this driver:
drivers/input/touchscreen/ads7846.c:
- ti,tsc2046
- ti,ads7843
- ti,ads7845
- ti,ads7846
- ti,ads7873 (hm, there is no ti,ads7873, is it actually analog devices AD7873?)

support 8- or 12-bit resolution. Only 12 bit mode is supported by this
driver. It is possible that some one can produce a resistive touchscreen
controller based on X > 12bit ADC, but this will probably not increase precision
of this construction (there is a lot of noise any ways...). With other
words, it is possible, but not probably that some one will really do it.

> Perhaps define the constant and put a comment why it's like this.
> 
> > +   return get_unaligned_be16(>data) >> 3;
> > +}
> 
> ...
> 
> > +static size_t tsc2046_adc_group_set_layout(struct tsc2046_adc_priv *priv,
> > +  unsigned int group,
> > +  unsigned int ch_idx)
> > +{
> > +   struct tsc2046_adc_ch_cfg *ch = >ch_cfg[ch_idx];
> > +   struct tsc2046_adc_group_layout *prev, *cur;
> > +   unsigned int max_count, count_skip;
> > +   unsigned int offset = 0;
> > +
> > +   if (group) {
> > +   prev = >l[group - 1];
> > +   offset = prev->offset + prev->count;
> > +   }
> 
> I guess you may easily refactor this by supply

[PATCH v3 3/3] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-19 Thread Oleksij Rempel
Basically the TI TSC2046 touchscreen controller is 8 channel ADC optimized for
the touchscreen use case. By implementing it as an IIO ADC device, we can
make use of resistive-adc-touch and iio-hwmon drivers.

So far, this driver was tested with a custom version of resistive-adc-touch 
driver,
since it needs to be extended to make use of Z1 and Z2 channels. The X/Y
are working without additional changes.

Signed-off-by: Oleksij Rempel 
Reviewed-by: Andy Shevchenko 
---
 MAINTAINERS  |   8 +
 drivers/iio/adc/Kconfig  |  12 +
 drivers/iio/adc/Makefile |   1 +
 drivers/iio/adc/ti-tsc2046.c | 728 +++
 4 files changed, 749 insertions(+)
 create mode 100644 drivers/iio/adc/ti-tsc2046.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 0455cfd5c76c..2ea85a5bb4dd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18002,6 +18002,14 @@ S: Supported
 F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt
 F: drivers/nfc/trf7970a.c
 
+TI TSC2046 ADC DRIVER
+M: Oleksij Rempel 
+R: ker...@pengutronix.de
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
+F: drivers/iio/adc/ti-tsc2046.c
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi 
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index bf7d22fa4be2..a2898108f418 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1175,6 +1175,18 @@ config TI_TLC4541
  This driver can also be built as a module. If so, the module will be
  called ti-tlc4541.
 
+config TI_TSC2046
+   tristate "Texas Instruments TSC2046 ADC driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to build support for ADC functionality of Texas
+ Instruments TSC2046 touch screen controller.
+
+ This driver can also be built as a module. If so, the module will be
+ called ti-tsc2046.
+
 config TWL4030_MADC
tristate "TWL4030 MADC (Monitoring A/D Converter)"
depends on TWL4030_CORE
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 5fca90ada0ec..440e18ac6780 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -105,6 +105,7 @@ obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o
 obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
 obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o
+obj-$(CONFIG_TI_TSC2046) += ti-tsc2046.o
 obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
 obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
 obj-$(CONFIG_VF610_ADC) += vf610_adc.o
diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c
new file mode 100644
index ..c8c0dd9087c5
--- /dev/null
+++ b/drivers/iio/adc/ti-tsc2046.c
@@ -0,0 +1,728 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Texas Instruments TSC2046 SPI ADC driver
+ *
+ * Copyright (c) 2021 Oleksij Rempel , Pengutronix
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * The PENIRQ of TSC2046 controller is implemented as level shifter attached to
+ * the X+ line. If voltage of the X+ line reaches a specific level the IRQ will
+ * be activated or deactivated.
+ * To make this kind of IRQ reusable as trigger following additions were
+ * implemented:
+ * - rate limiting:
+ *   For typical touchscreen use case, we need to trigger about each 10ms.
+ * - hrtimer:
+ *   Continue triggering at least once after the IRQ was deactivated. Then
+ *   deactivate this trigger to stop sampling in order to reduce power
+ *   consumption.
+ */
+
+#define TI_TSC2046_NAME"tsc2046"
+
+/* This driver doesn't aim at the peak continuous sample rate */
+#defineTI_TSC2046_MAX_SAMPLE_RATE  125000
+#defineTI_TSC2046_SAMPLE_BITS \
+   (sizeof(struct tsc2046_adc_atom) * BITS_PER_BYTE)
+#defineTI_TSC2046_MAX_CLK_FREQ \
+   (TI_TSC2046_MAX_SAMPLE_RATE * TI_TSC2046_SAMPLE_BITS)
+
+#define TI_TSC2046_SAMPLE_INTERVAL_US  1
+
+#define TI_TSC2046_START   BIT(7)
+#define TI_TSC2046_ADDRGENMASK(6, 4)
+#define TI_TSC2046_ADDR_TEMP1  7
+#define TI_TSC2046_ADDR_AUX6
+#define TI_TSC2046_ADDR_X  5
+#define TI_TSC2046_ADDR_Z2 4
+#define TI_TSC2046_ADDR_Z1 3
+#define TI_TSC2046_ADDR_VBAT   2
+#define TI_TSC2046_ADDR_Y  1
+#define TI_TSC2046_ADDR_TEMP0  0
+
+/*
+ * The mode bit sets the resolution of the ADC. With this bit low, the next
+ * conversion has 12-bit resolution, whereas with this bit high, the next
+ * conversion has 8-bit resolution. This driver is opt

[PATCH v3 2/3] dt-bindings:iio:adc: add documentation for TI TSC2046 controller

2021-03-19 Thread Oleksij Rempel
Add a binding documentation for the TI TSC2046 touchscreen controllers
ADC functionality.

Signed-off-by: Oleksij Rempel 
Reviewed-by: Rob Herring 
---
 .../bindings/iio/adc/ti,tsc2046.yaml  | 115 ++
 1 file changed, 115 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml

diff --git a/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml 
b/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
new file mode 100644
index ..601d69971d84
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/ti,tsc2046.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments TSC2046 touch screen controller.
+
+maintainers:
+  - Oleksij Rempel 
+
+description: |
+  TSC2046 is a touch screen controller with 8 channels ADC.
+
+properties:
+  compatible:
+enum:
+  - ti,tsc2046e-adc
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  spi-max-frequency: true
+
+  "#io-channel-cells":
+const: 1
+
+  '#address-cells':
+const: 1
+
+  '#size-cells':
+const: 0
+
+required:
+  - compatible
+  - reg
+
+patternProperties:
+  "^channel@[0-7]$":
+$ref: "adc.yaml"
+type: object
+
+properties:
+  reg:
+description: |
+  The channel number. It can have up to 8 channels
+items:
+  minimum: 0
+  maximum: 7
+
+  settling-time-us: true
+  oversampling-ratio: true
+
+required:
+  - reg
+
+additionalProperties: false
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+spi {
+#address-cells = <1>;
+#size-cells = <0>;
+
+adc@0 {
+compatible = "ti,tsc2046e-adc";
+reg = <0>;
+spi-max-frequency = <100>;
+interrupts-extended = < 20 IRQ_TYPE_LEVEL_LOW>;
+#io-channel-cells = <1>;
+
+#address-cells = <1>;
+#size-cells = <0>;
+
+channel@0 {
+  reg = <0>;
+};
+channel@1 {
+  reg = <1>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@2 {
+  reg = <2>;
+};
+channel@3 {
+  reg = <3>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@4 {
+  reg = <4>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@5 {
+  reg = <5>;
+  settling-time-us = <700>;
+  oversampling-ratio = <5>;
+};
+channel@6 {
+  reg = <6>;
+};
+channel@7 {
+  reg = <7>;
+};
+};
+};
+...
-- 
2.29.2



[PATCH v3 1/3] dt-bindings:iio:adc: add generic settling-time-us and oversampling-ratio channel properties

2021-03-19 Thread Oleksij Rempel
Settling time and over sampling is a typical challenge for different IIO ADC
devices. So, introduce channel specific settling-time-us and oversampling-ratio
properties to cover this use case.

Signed-off-by: Oleksij Rempel 
---
 Documentation/devicetree/bindings/iio/adc/adc.yaml | 9 +
 1 file changed, 9 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml 
b/Documentation/devicetree/bindings/iio/adc/adc.yaml
index 912a7635edc4..66fd4b45f097 100644
--- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
@@ -39,4 +39,13 @@ properties:
   The first value specifies the positive input pin, the second
   specifies the negative input pin.
 
+  settling-time-us:
+$ref: /schemas/types.yaml#/definitions/uint32
+description:
+  Time between enabling the channel and firs stable readings.
+
+  oversampling-ratio:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: Number of data samples which are averaged for each read.
+
 additionalProperties: true
-- 
2.29.2



[PATCH v3 0/3] mainline ti tsc2046 adc driver

2021-03-19 Thread Oleksij Rempel
changes v3:
- different spell fixes
- add some notes about driver structure
- rename the trigger to point on the touchscreen nature of it
- rename DT binding to oversampling-ratio
- make sure we have some defaults in case no DT property is set

changes v2:
- rework and extend DT binding properties
- remove touchscreen related code from the IIO ADC driver
- make trigger be active longer then IRQ is requesting. This is needed
  to get "inactive" samples
- make oversampling and settle time configurable

TI TSC2046 is a touchscreen controller based on 8 channel ADC. Since most of
this ADC based touchscreen controller share same set of challenges, it
is better keep then as simple IIO ADC devices attached to a generic
resistive-adc-touch driver.

This driver can replace drivers/input/touchscreen/ads7846.c and has
following advantages over it:
- less code to maintain
- shared code paths (resistive-adc-touch, iio-hwmon, etc)
- can be used as plain IIO ADC to investigate signaling issues or test
  real capacity of the plates and attached low-pass filters
  (or use the touchscreen as a microphone if you like ;) )

Oleksij Rempel (3):
  dt-bindings:iio:adc: add generic settling-time-us and
oversampling-ratio channel properties
  dt-bindings:iio:adc: add documentation for TI TSC2046 controller
  iio: adc: add ADC driver for the TI TSC2046 controller

 .../devicetree/bindings/iio/adc/adc.yaml  |   9 +
 .../bindings/iio/adc/ti,tsc2046.yaml  | 115 +++
 MAINTAINERS   |   8 +
 drivers/iio/adc/Kconfig   |  12 +
 drivers/iio/adc/Makefile  |   1 +
 drivers/iio/adc/ti-tsc2046.c  | 728 ++
 6 files changed, 873 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
 create mode 100644 drivers/iio/adc/ti-tsc2046.c

-- 
2.29.2



Re: [PATCH v2 3/3] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-15 Thread Oleksij Rempel
Hi,

On Sat, Mar 13, 2021 at 04:11:19PM +, Jonathan Cameron wrote:
> On Fri, 12 Mar 2021 11:55:15 +0100
> Oleksij Rempel  wrote:
> 
> > Basically the TI TSC2046 touchscreen controller is 8 channel ADC optimized 
> > for
> > the touchscreen use case. By implementing it as IIO ADC device, we can
> > make use of resistive-adc-touch and iio-hwmon drivers.
> > 
> > So far, this driver was tested with custom version of resistive-adc-touch 
> > driver,
> > since it need to be extended to make use of Z1 and Z2 channels. The X/Y
> > are working without additional changes.
> > 
> > Signed-off-by: Oleksij Rempel 
> 
> So the flow in here is still rather non obvious and touchscreen specific.
> Please add some documentation on what the trigger actually is. It seems
> to be some combination of an hrtimer and a interrupt driven trigger.
> I 'think' the idea is to ensure you get one 'no touch' measurement once
> touch is removed?


Yes, this IRQ line is just a voltage level converter integrated in to
controller. As soon voltage level reaches some threshold the IRQ level
is changed. It means, the IRQ is inactive as soon as nothing is pressing
on the screen, or the channel is changed. Since we need more sample and not so
frequent, I made this construction of rate limited IRQ with extra triggering on
the end.

Potentially we can use hrtimer trigger, especially if the IRQ line
is not attached or can't be used for some reason. But for most use cases
this trigger will provide better power efficiency.

I can imagine, that in case of field board diagnostic, we may need some extra
functionality. So the workflow will look like:
- unbind the touchscreen driver
- disable oversampling
- disable settling time
- attach sysfs trigger
- enable one of channels
- start grabbing data over IIO char dev

But this functionality will need some more work and currently has lowest
prio.

> I guess we don't need the performance but I was a bit surprised that I didn't
> see this doing overlapping of the previous read out with the config for the
> next sample.

I can't follow here. Can you please explain.

> Anyhow, overall this looks pretty good to me.  Add that a bit of documentation
> for the trigger to the comments at the top of the file and tidy up the last
> few things inline.

ok

> It's a bit unusual as ADC drivers go, but not so strange that it worries
> me that much.

:)

> Thanks,
> 
> Jonathan
> 
> > ---
> >  MAINTAINERS  |   8 +
> >  drivers/iio/adc/Kconfig  |  12 +
> >  drivers/iio/adc/Makefile |   1 +
> >  drivers/iio/adc/ti-tsc2046.c | 713 +++
> >  4 files changed, 734 insertions(+)
> >  create mode 100644 drivers/iio/adc/ti-tsc2046.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 3fea1a934b32..2d33c6442a55 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -17852,6 +17852,14 @@ S: Supported
> >  F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt
> >  F: drivers/nfc/trf7970a.c
> >  
> > +TI TSC2046 ADC DRIVER
> > +M: Oleksij Rempel 
> > +R: ker...@pengutronix.de
> > +L: linux-...@vger.kernel.org
> > +S: Maintained
> > +F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
> > +F: drivers/iio/adc/ti-tsc2046.c
> > +
> >  TI TWL4030 SERIES SOC CODEC DRIVER
> >  M: Peter Ujfalusi 
> >  L: alsa-de...@alsa-project.org (moderated for non-subscribers)
> > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> > index 15587a1bc80d..6ad6f04dfd20 100644
> > --- a/drivers/iio/adc/Kconfig
> > +++ b/drivers/iio/adc/Kconfig
> > @@ -1175,6 +1175,18 @@ config TI_TLC4541
> >   This driver can also be built as a module. If so, the module will be
> >   called ti-tlc4541.
> >  
> > +config TI_TSC2046
> > +   tristate "Texas Instruments TSC2046 ADC driver"
> > +   depends on SPI
> > +   select IIO_BUFFER
> > +   select IIO_TRIGGERED_BUFFER
> > +   help
> > + Say yes here to build support for ADC functionality of Texas
> > + Instruments TSC2046 touch screen controller.
> > +
> > + This driver can also be built as a module. If so, the module will be
> > + called ti-tsc2046.
> > +
> >  config TWL4030_MADC
> > tristate "TWL4030 MADC (Monitoring A/D Converter)"
> > depends on TWL4030_CORE
> > diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> > index 5fca90ada0ec..440e18ac6780 100644
> > --- a/drivers/iio/adc/Makefile
> > +++ b/drivers/iio/adc/Makefile
> > @@ -105,6 +105,7 @@ obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o
> >  obj-$(CONFIG_TI_

[PATCH v2 0/3] mainline ti tsc2046 adc driver

2021-03-12 Thread Oleksij Rempel
changes v2:
- rework and extend DT binding properties
- remove touchscreen related code from the IIO ADC driver
- make trigger be active longer then IRQ is requesting. This is needed
  to get "inactive" samples
- make oversampling and settle time configurable

TI TSC2046 is a touchscreen controller based on 8 channel ADC. Since most of
this ADC based touchscreen controller share same set of challenges, it
is better keep then as simple IIO ADC devices attached to a generic
resistive-adc-touch driver.

This driver can replace drivers/input/touchscreen/ads7846.c and has
following advantages over it:
- less code to maintain
- shared code paths (resistive-adc-touch, iio-hwmon, etc)
- can be used as plain IIO ADC to investigate signaling issues or test
  real capacity of the plates and attached low-pass filters
  (or use the touchscreen as a microphone if you like ;) )

Oleksij Rempel (3):
  dt-bindings:iio:adc: add generic settling-time-us and average-samples
channel properties
  dt-bindings:iio:adc: add documentation for TI TSC2046 controller
  iio: adc: add ADC driver for the TI TSC2046 controller

 .../devicetree/bindings/iio/adc/adc.yaml  |   9 +
 .../bindings/iio/adc/ti,tsc2046.yaml  | 115 +++
 MAINTAINERS   |   8 +
 drivers/iio/adc/Kconfig   |  12 +
 drivers/iio/adc/Makefile  |   1 +
 drivers/iio/adc/ti-tsc2046.c  | 713 ++
 6 files changed, 858 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
 create mode 100644 drivers/iio/adc/ti-tsc2046.c

-- 
2.29.2



[PATCH v2 3/3] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-12 Thread Oleksij Rempel
Basically the TI TSC2046 touchscreen controller is 8 channel ADC optimized for
the touchscreen use case. By implementing it as IIO ADC device, we can
make use of resistive-adc-touch and iio-hwmon drivers.

So far, this driver was tested with custom version of resistive-adc-touch 
driver,
since it need to be extended to make use of Z1 and Z2 channels. The X/Y
are working without additional changes.

Signed-off-by: Oleksij Rempel 
---
 MAINTAINERS  |   8 +
 drivers/iio/adc/Kconfig  |  12 +
 drivers/iio/adc/Makefile |   1 +
 drivers/iio/adc/ti-tsc2046.c | 713 +++
 4 files changed, 734 insertions(+)
 create mode 100644 drivers/iio/adc/ti-tsc2046.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 3fea1a934b32..2d33c6442a55 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17852,6 +17852,14 @@ S: Supported
 F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt
 F: drivers/nfc/trf7970a.c
 
+TI TSC2046 ADC DRIVER
+M: Oleksij Rempel 
+R: ker...@pengutronix.de
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
+F: drivers/iio/adc/ti-tsc2046.c
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi 
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 15587a1bc80d..6ad6f04dfd20 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1175,6 +1175,18 @@ config TI_TLC4541
  This driver can also be built as a module. If so, the module will be
  called ti-tlc4541.
 
+config TI_TSC2046
+   tristate "Texas Instruments TSC2046 ADC driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to build support for ADC functionality of Texas
+ Instruments TSC2046 touch screen controller.
+
+ This driver can also be built as a module. If so, the module will be
+ called ti-tsc2046.
+
 config TWL4030_MADC
tristate "TWL4030 MADC (Monitoring A/D Converter)"
depends on TWL4030_CORE
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 5fca90ada0ec..440e18ac6780 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -105,6 +105,7 @@ obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o
 obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
 obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o
+obj-$(CONFIG_TI_TSC2046) += ti-tsc2046.o
 obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
 obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
 obj-$(CONFIG_VF610_ADC) += vf610_adc.o
diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c
new file mode 100644
index ..7c3ae9181164
--- /dev/null
+++ b/drivers/iio/adc/ti-tsc2046.c
@@ -0,0 +1,713 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Texas Instruments TSC2046 SPI ADC driver
+ *
+ * Copyright (c) 2021 Oleksij Rempel , Pengutronix
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#define TI_TSC2046_NAME"tsc2046"
+
+/* This driver doesn't aim at the peak continuous sample rate */
+#defineTI_TSC2046_MAX_SAMPLE_RATE  125000
+#defineTI_TSC2046_SAMPLE_BITS  (8 /*cmd*/ + 16 
/*sample*/)
+#defineTI_TSC2046_MAX_CLK_FREQ \
+   (TI_TSC2046_MAX_SAMPLE_RATE * TI_TSC2046_SAMPLE_BITS)
+
+#define TI_TSC2046_SAMPLE_INTERVAL_US  1
+
+#define TI_TSC2046_START   BIT(7)
+#define TI_TSC2046_ADDRGENMASK(6, 4)
+#define TI_TSC2046_ADDR_TEMP1  7
+#define TI_TSC2046_ADDR_AUX6
+#define TI_TSC2046_ADDR_X  5
+#define TI_TSC2046_ADDR_Z2 4
+#define TI_TSC2046_ADDR_Z1 3
+#define TI_TSC2046_ADDR_VBAT   2
+#define TI_TSC2046_ADDR_Y  1
+#define TI_TSC2046_ADDR_TEMP0  0
+
+/*
+ * The mode bit sets the resolution of the ADC. With this bit low, the next
+ * conversion has 12-bit resolution, whereas with this bit high, the next
+ * conversion has 8-bit resolution. This driver is optimized for 12-bit mode.
+ * So, for this driver, this bit should stay zero.
+ */
+#define TI_TSC2046_8BIT_MODE   BIT(3)
+
+/*
+ * SER/DFR - The SER/DFR bit controls the reference mode, either single-ended
+ * (high) or differential (low).
+ */
+#define TI_TSC2046_SER BIT(2)
+
+/*
+ * If VREF_ON and ADC_ON are both zero, then the chip operates in
+ * auto-wake/suspend mode. In most case this bits should stay zero.
+ */
+#define TI_TSC2046_PD1_VREF_ON BIT(1)
+#define TI_TSC2046_PD0_ADC_ON  BIT(0)
+
+#define TI_TSC2046_MAX_CHAN8
+
+/* Rep

[PATCH v2 1/3] dt-bindings:iio:adc: add generic settling-time-us and average-samples channel properties

2021-03-12 Thread Oleksij Rempel
Settling time and over sampling is a typical challenge for different IIO ADC
devices. So, introduce channel specific settling-time-us and average-samples
properties to cover this use case.

Signed-off-by: Oleksij Rempel 
---
 Documentation/devicetree/bindings/iio/adc/adc.yaml | 9 +
 1 file changed, 9 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml 
b/Documentation/devicetree/bindings/iio/adc/adc.yaml
index 912a7635edc4..c748f6573027 100644
--- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
@@ -39,4 +39,13 @@ properties:
   The first value specifies the positive input pin, the second
   specifies the negative input pin.
 
+  settling-time-us:
+$ref: /schemas/types.yaml#/definitions/uint32
+description:
+  Time between enabling the channel and firs stable readings.
+
+  average-samples:
+$ref: /schemas/types.yaml#/definitions/uint32
+description: Number of data samples which are averaged for each read.
+
 additionalProperties: true
-- 
2.29.2



[PATCH v2 2/3] dt-bindings:iio:adc: add documentation for TI TSC2046 controller

2021-03-12 Thread Oleksij Rempel
Add a binding documentation for the TI TSC2046 touchscreen controllers
ADC functionality.

Signed-off-by: Oleksij Rempel 
---
 .../bindings/iio/adc/ti,tsc2046.yaml  | 115 ++
 1 file changed, 115 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml

diff --git a/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml 
b/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
new file mode 100644
index ..4f705dc0f639
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/ti,tsc2046.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments TSC2046 touch screen controller.
+
+maintainers:
+  - Oleksij Rempel 
+
+description: |
+  TSC2046 is a touch screen controller with 8 channels ADC.
+
+properties:
+  compatible:
+enum:
+  - ti,tsc2046e-adc
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  spi-max-frequency: true
+
+  "#io-channel-cells":
+const: 1
+
+  '#address-cells':
+const: 1
+
+  '#size-cells':
+const: 0
+
+required:
+  - compatible
+  - reg
+
+patternProperties:
+  "^channel@[0-7]$":
+$ref: "adc.yaml"
+type: object
+
+properties:
+  reg:
+description: |
+  The channel number. It can have up to 8 channels
+items:
+  minimum: 0
+  maximum: 7
+
+  settling-time-us: true
+  average-samples: true
+
+required:
+  - reg
+
+additionalProperties: false
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+spi {
+#address-cells = <1>;
+#size-cells = <0>;
+
+adc@0 {
+compatible = "ti,tsc2046e-adc";
+reg = <0>;
+spi-max-frequency = <100>;
+interrupts-extended = < 20 IRQ_TYPE_LEVEL_LOW>;
+#io-channel-cells = <1>;
+
+#address-cells = <1>;
+#size-cells = <0>;
+
+channel@0 {
+  reg = <0>;
+};
+channel@1 {
+  reg = <1>;
+  settling-time-us = <700>;
+  average-samples = <5>;
+};
+channel@2 {
+  reg = <2>;
+};
+channel@3 {
+  reg = <3>;
+  settling-time-us = <700>;
+  average-samples = <5>;
+};
+channel@4 {
+  reg = <4>;
+  settling-time-us = <700>;
+  average-samples = <5>;
+};
+channel@5 {
+  reg = <5>;
+  settling-time-us = <700>;
+  average-samples = <5>;
+};
+channel@6 {
+  reg = <6>;
+};
+channel@7 {
+  reg = <7>;
+};
+};
+};
+...
-- 
2.29.2



Re: [PATCH v4 2/7] MIPS: Loongson64: Distinguish firmware dependencies DTB/LEFI

2021-03-10 Thread Oleksij Rempel
Am 10.03.21 um 16:58 schrieb Jiaxun Yang:
>
>
> 在 2021/3/10 21:26, Oleksij Rempel 写道:
> [...]
>> I would like to understand, why it is impossible. Do fw_arg0 provide memory 
>> address or some kind of
>> count/size? Can it be negative?
>>
>> We already had same situation with ARM and it was fixed. Why this can't be 
>> done for MIPS or LS?
>
> Well we can fix it for future MIPS systems but not present Loongson.
>
> Actually I've talked to several Chinese MIPS chip vendors and they
> all agreed to unify the booting protcol.
>
> I raised the same question to Loongson ~3 years ago but got
> negative response.
> The idea got reject in a recent private discussions with Loongson
> about 2K1000 upstream stuff.
>
> Also I realized Loongson's chip comes with too many ISA level
> custom designs which makes it impossible to use MIPS generic
> kernel.
>  
>
>>>> This protocol is described here on page 15, "3. Boot protocols"
>>>> https://docplayer.net/62444141-Unified-hosting-interface-md01069-reference-manual.html
>>>>
>>>> According to this protocol, you should have:
>>>> fw_arg0 = -2
>>>> fw_arg1 = Virtual (kseg0) address of Device Tree Blob
>>>>
>>>> This would made LS a first grade resident for many boot loaders and
>>>> save a lot of needles headaches.
>>>>
>>> Loongson is stepping away from MIPS and it seems like they're going to use 
>>> EDK-II for their Loongarch.
>>>
>> It seems to be UEFI related, it seems to be not related to the CPU arch, or 
>> do i'm missing something?
> I meant they won't invest much to MIPS based chips :-(
>> In any case, if this is true, then it means, that Loongsoon is about to drop 
>> support for old boot
>> loaders (PMON?) and do new thing (one more boot protocol?). So 
>> argumentation, we upstream old own
>> protocol, but will drop it to make some thing new is not really good example 
>> :)
> Yes, actually many new Loongson desktop machines (3A3000/3A4000) are shipped
> with UEFI and relies on second stage bootloader to convert to old boot
> protocol.
>
> I'm againt to upstraming the "new" protocol as it's non-standard UEFI
> with many
> nonsense design.
>
>
>>> TBH I've checked Loongson's PMON code and realized it can't be ported to 
>>> other projects easily.
>>> Tons of unregonized assembly code.
>>>
>> No need to port it. Here is example of working clean code:
>> https://git.pengutronix.de/cgit/barebox/tree/arch/mips/boards/loongson-ls1b/lowlevel.S
> I've ported U-Boot to LS1C as well. But LS1B/LS1C is Loongson32.
> Loongson64 based systems like LS2K is much more complex than it.
> The bootloader is fullfilled with assembly and mostly undocumented.
> LS2K's PMON contains ~50k lines of assembly.

OK, i hope i'll never have customers using this chips. Are there any
reason why do we wont to keep it alive? :D


--
Regards,
Oleksij


Re: [PATCH v4 2/7] MIPS: Loongson64: Distinguish firmware dependencies DTB/LEFI

2021-03-10 Thread Oleksij Rempel
Am 10.03.21 um 13:12 schrieb Jiaxun Yang:
>
>
> On Wed, Mar 10, 2021, at 6:57 PM, Oleksij Rempel wrote:
>> Hi,
>>
>> Am 10.03.21 um 08:56 schrieb Qing Zhang:
>>> Add DTB boot support, only support Loongson-2K1000 processor
>>> for now, determine whether to use the built-in DTB or the DTB
>>> from the firmware by checking the range of CKSEG0 and XKPHYS.
>>> loongson_fw_interface will be used in the future.
>>>
>>> Signed-off-by: Jiaxun Yang 
>>> Signed-off-by: Qing Zhang 
>>> Tested-by: Ming Wang 
>>> ---
>>>
>>> v3-v4: Standard submission of information
>>>Fix error handling
>>>
>>>  .../include/asm/mach-loongson64/boot_param.h |  6 ++
>>>  arch/mips/include/asm/mach-loongson64/loongson.h |  3 ++-
>>>  arch/mips/loongson64/env.c   | 13 -
>>>  arch/mips/loongson64/init.c  | 16 ++--
>>>  4 files changed, 34 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h 
>>> b/arch/mips/include/asm/mach-loongson64/boot_param.h
>>> index 4592841b6b0c..43737401dc06 100644
>>> --- a/arch/mips/include/asm/mach-loongson64/boot_param.h
>>> +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
>>> @@ -198,7 +198,13 @@ enum loongson_bridge_type {
>>> VIRTUAL = 3
>>>  };
>>>
>>> +enum loongson_fw_interface {
>>> +   LOONGSON_LEFI,
>>> +   LOONGSON_DTB,
>>> +};
>>> +
>>>  struct loongson_system_configuration {
>>> +   enum loongson_fw_interface fw_interface;
>>> u32 nr_cpus;
>>> u32 nr_nodes;
>>> int cores_per_node;
>>> diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h 
>>> b/arch/mips/include/asm/mach-loongson64/loongson.h
>>> index ac1c20e172a2..3f885fa26ba6 100644
>>> --- a/arch/mips/include/asm/mach-loongson64/loongson.h
>>> +++ b/arch/mips/include/asm/mach-loongson64/loongson.h
>>> @@ -23,7 +23,8 @@ extern u32 memsize, highmemsize;
>>>  extern const struct plat_smp_ops loongson3_smp_ops;
>>>
>>>  /* loongson-specific command line, env and memory initialization */
>>> -extern void __init prom_init_env(void);
>>> +extern void __init prom_dtb_init_env(void);
>>> +extern void __init prom_lefi_init_env(void);
>>>  extern void __init szmem(unsigned int node);
>>>  extern void *loongson_fdt_blob;
>>>
>>> diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c
>>> index 51a5d050a94c..e7d3a06175e3 100644
>>> --- a/arch/mips/loongson64/env.c
>>> +++ b/arch/mips/loongson64/env.c
>>> @@ -43,7 +43,18 @@ const char *get_system_type(void)
>>> return "Generic Loongson64 System";
>>>  }
>>>
>>> -void __init prom_init_env(void)
>>> +
>>> +void __init prom_dtb_init_env(void)
>>> +{
>>> +   if ((fw_arg2 < CKSEG0 || fw_arg2 > CKSEG1)
>>> +   && (fw_arg2 < XKPHYS || fw_arg2 > XKSEG))
>>> +
>>> +   loongson_fdt_blob = __dtb_loongson64_2core_2k1000_begin;
>>> +   else
>>> +   loongson_fdt_blob = (void *)fw_arg2;
>>> +}
>>> +
>>> +void __init prom_lefi_init_env(void)
>>>  {
>>> struct boot_params *boot_p;
>>> struct loongson_params *loongson_p;
>>> diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
>>> index cfa788bca871..ed280b73bf89 100644
>>> --- a/arch/mips/loongson64/init.c
>>> +++ b/arch/mips/loongson64/init.c
>>> @@ -52,6 +52,10 @@ void __init szmem(unsigned int node)
>>> static unsigned long num_physpages;
>>> u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
>>>
>>> +   /* Otherwise come from DTB */
>>> +   if (loongson_sysconf.fw_interface != LOONGSON_LEFI)
>>> +   return;
>>> +
>>> /* Parse memory information and activate */
>>> for (i = 0; i < loongson_memmap->nr_map; i++) {
>>> node_id = loongson_memmap->map[i].node_id;
>>> @@ -94,12 +98,20 @@ static void __init prom_init_memory(void)
>>>  void __init prom_init(void)
>>>  {
>>> fw_init_cmdline();
>>> -   prom_init_env();
>>> +
>>> +   if (fw_arg2 == 0 || (fdt_magic(fw_arg2) == FDT_MAGIC)) {
>>> +   loongson_sysconf.fw_interface = LOONGSON_DTB

Re: [PATCH v4 2/7] MIPS: Loongson64: Distinguish firmware dependencies DTB/LEFI

2021-03-10 Thread Oleksij Rempel
Hi,

Am 10.03.21 um 08:56 schrieb Qing Zhang:
> Add DTB boot support, only support Loongson-2K1000 processor
> for now, determine whether to use the built-in DTB or the DTB
> from the firmware by checking the range of CKSEG0 and XKPHYS.
> loongson_fw_interface will be used in the future.
>
> Signed-off-by: Jiaxun Yang 
> Signed-off-by: Qing Zhang 
> Tested-by: Ming Wang 
> ---
>
> v3-v4: Standard submission of information
>Fix error handling
>
>  .../include/asm/mach-loongson64/boot_param.h |  6 ++
>  arch/mips/include/asm/mach-loongson64/loongson.h |  3 ++-
>  arch/mips/loongson64/env.c   | 13 -
>  arch/mips/loongson64/init.c  | 16 ++--
>  4 files changed, 34 insertions(+), 4 deletions(-)
>
> diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h 
> b/arch/mips/include/asm/mach-loongson64/boot_param.h
> index 4592841b6b0c..43737401dc06 100644
> --- a/arch/mips/include/asm/mach-loongson64/boot_param.h
> +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
> @@ -198,7 +198,13 @@ enum loongson_bridge_type {
>   VIRTUAL = 3
>  };
>
> +enum loongson_fw_interface {
> + LOONGSON_LEFI,
> + LOONGSON_DTB,
> +};
> +
>  struct loongson_system_configuration {
> + enum loongson_fw_interface fw_interface;
>   u32 nr_cpus;
>   u32 nr_nodes;
>   int cores_per_node;
> diff --git a/arch/mips/include/asm/mach-loongson64/loongson.h 
> b/arch/mips/include/asm/mach-loongson64/loongson.h
> index ac1c20e172a2..3f885fa26ba6 100644
> --- a/arch/mips/include/asm/mach-loongson64/loongson.h
> +++ b/arch/mips/include/asm/mach-loongson64/loongson.h
> @@ -23,7 +23,8 @@ extern u32 memsize, highmemsize;
>  extern const struct plat_smp_ops loongson3_smp_ops;
>
>  /* loongson-specific command line, env and memory initialization */
> -extern void __init prom_init_env(void);
> +extern void __init prom_dtb_init_env(void);
> +extern void __init prom_lefi_init_env(void);
>  extern void __init szmem(unsigned int node);
>  extern void *loongson_fdt_blob;
>
> diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c
> index 51a5d050a94c..e7d3a06175e3 100644
> --- a/arch/mips/loongson64/env.c
> +++ b/arch/mips/loongson64/env.c
> @@ -43,7 +43,18 @@ const char *get_system_type(void)
>   return "Generic Loongson64 System";
>  }
>
> -void __init prom_init_env(void)
> +
> +void __init prom_dtb_init_env(void)
> +{
> + if ((fw_arg2 < CKSEG0 || fw_arg2 > CKSEG1)
> + && (fw_arg2 < XKPHYS || fw_arg2 > XKSEG))
> +
> + loongson_fdt_blob = __dtb_loongson64_2core_2k1000_begin;
> + else
> + loongson_fdt_blob = (void *)fw_arg2;
> +}
> +
> +void __init prom_lefi_init_env(void)
>  {
>   struct boot_params *boot_p;
>   struct loongson_params *loongson_p;
> diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
> index cfa788bca871..ed280b73bf89 100644
> --- a/arch/mips/loongson64/init.c
> +++ b/arch/mips/loongson64/init.c
> @@ -52,6 +52,10 @@ void __init szmem(unsigned int node)
>   static unsigned long num_physpages;
>   u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
>
> + /* Otherwise come from DTB */
> + if (loongson_sysconf.fw_interface != LOONGSON_LEFI)
> + return;
> +
>   /* Parse memory information and activate */
>   for (i = 0; i < loongson_memmap->nr_map; i++) {
>   node_id = loongson_memmap->map[i].node_id;
> @@ -94,12 +98,20 @@ static void __init prom_init_memory(void)
>  void __init prom_init(void)
>  {
>   fw_init_cmdline();
> - prom_init_env();
> +
> + if (fw_arg2 == 0 || (fdt_magic(fw_arg2) == FDT_MAGIC)) {
> + loongson_sysconf.fw_interface = LOONGSON_DTB;
> + prom_dtb_init_env();
> + } else {
> + loongson_sysconf.fw_interface = LOONGSON_LEFI;
> + prom_lefi_init_env();
> + }

Is it possible to make it compatible with MIPS UHI boot protocol? So boot 
loaders will be able to
handle Loongson kernel images as any other MIPS kernel images?

This protocol is described here on page 15, "3. Boot protocols"
https://docplayer.net/62444141-Unified-hosting-interface-md01069-reference-manual.html

According to this protocol, you should have:
fw_arg0 = -2
fw_arg1 = Virtual (kseg0) address of Device Tree Blob

This would made LS a first grade resident for many boot loaders and save a lot 
of needles headaches.

--
Regards,
Oleksij


Re: [PATCH v1 2/2] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-09 Thread Oleksij Rempel
On Tue, Mar 09, 2021 at 01:46:55PM +0200, Andy Shevchenko wrote:
> On Tue, Mar 9, 2021 at 1:42 PM Oleksij Rempel  wrote:
> > On Tue, Mar 09, 2021 at 01:05:27PM +0200, Andy Shevchenko wrote:
> > > On Fri, Mar 5, 2021 at 9:05 PM Jonathan Cameron
> > >  wrote:
> > > >
> > > > On Fri, 5 Mar 2021 14:38:13 +0100
> > > > Oleksij Rempel  wrote:
> > > >
> > > > > Basically the TI TSC2046 touchscreen controller is 8 channel ADC 
> > > > > optimized for
> > > > > the touchscreen use case. By implementing it as IIO ADC device, we can
> > > > > make use of resistive-adc-touch and iio-hwmon drivers.
> > > > >
> > > > > So far, this driver was tested with custom version of 
> > > > > resistive-adc-touch driver,
> > > > > since it need to be extended to make use of Z1 and Z2 channels. The 
> > > > > X/Y
> > > > > are working without additional changes.
> > > > >
> > > > > Signed-off-by: Oleksij Rempel 
> > > >
> > > > Hi Oleksij,
> > > >
> > > > To consider this as a possible long term route instead of just making 
> > > > this
> > > > a touchscreen driver, we'll want to see those mods to the 
> > > > resistive-adc-touch.
> > > > Of course that doesn't stop review of this in the meantime.
> > > >
> > > > There are quite a few things in here that feel pretty specific to the 
> > > > touchscreen
> > > > usecase. That makes me wonder if this is a sensible approach or not.
> > >
> > > I'm wondering if this has any similarities with existing drivers under
> > > drivers/input/touchscreen.
> >
> > Yes, for example: drivers/input/touchscreen/ads7846.c
> 
> Then I have a few questions here:
> 1/ why the above mentioned driver can't be extended to cover this?

It is not possible to keep old device tree binding compatible with the
new driver at least not for currently existing abstraction: ADC +
touchscreen node.

It is too expensive to overwrite the old driver, we do not have enough time and
resource to do it. I lardy spend some weeks to do it and I would need a
many more weeks to make it by tiny slices without solving actual
problem. Many resistive touchscreen driver should share a lot of code.

Since there is already existing IIO based components, it seems to me
better to spend available resource and making it properly in a way,
which reflect modern best practices.

> 2/ or why is the proposed driver named after the touchscreen instead
> of the real AD/C chip behind it?

I do not understand this question. The proposed driver is named after
the chip which provides ADC functionality, In this case, it is TSC2046.
The touchscreen is a separate physical module.

The idea of this proposition is to keep physically separate components
separately on the kernel side.

> 3/ maybe we can introduce a simple AD/C driver under IIO for that?

There are already simple ADC drivers for that:
iio-hwmon: drivers/hwmon/iio_hwmon.c
resistive-adc-touch: drivers/input/touchscreen/resistive-adc-touch.c

This two driver + the proposed one, will replace functionality of ads7846.c

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


Re: [PATCH v1 2/2] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-09 Thread Oleksij Rempel
On Tue, Mar 09, 2021 at 01:05:27PM +0200, Andy Shevchenko wrote:
> On Fri, Mar 5, 2021 at 9:05 PM Jonathan Cameron
>  wrote:
> >
> > On Fri, 5 Mar 2021 14:38:13 +0100
> > Oleksij Rempel  wrote:
> >
> > > Basically the TI TSC2046 touchscreen controller is 8 channel ADC 
> > > optimized for
> > > the touchscreen use case. By implementing it as IIO ADC device, we can
> > > make use of resistive-adc-touch and iio-hwmon drivers.
> > >
> > > So far, this driver was tested with custom version of resistive-adc-touch 
> > > driver,
> > > since it need to be extended to make use of Z1 and Z2 channels. The X/Y
> > > are working without additional changes.
> > >
> > > Signed-off-by: Oleksij Rempel 
> >
> > Hi Oleksij,
> >
> > To consider this as a possible long term route instead of just making this
> > a touchscreen driver, we'll want to see those mods to the 
> > resistive-adc-touch.
> > Of course that doesn't stop review of this in the meantime.
> >
> > There are quite a few things in here that feel pretty specific to the 
> > touchscreen
> > usecase. That makes me wonder if this is a sensible approach or not.
> 
> I'm wondering if this has any similarities with existing drivers under
> drivers/input/touchscreen.

Yes, for example: drivers/input/touchscreen/ads7846.c

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


Re: [PATCH v1 2/2] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-09 Thread Oleksij Rempel
Hi Jonathan,

On Sat, Mar 06, 2021 at 02:59:59PM +, Jonathan Cameron wrote:
> On Sat, 6 Mar 2021 14:28:52 +0100
> Oleksij Rempel  wrote:
> 
> > On Fri, Mar 05, 2021 at 07:02:39PM +, Jonathan Cameron wrote:
> > > On Fri, 5 Mar 2021 14:38:13 +0100
> > > Oleksij Rempel  wrote:
> > >   
> > > > Basically the TI TSC2046 touchscreen controller is 8 channel ADC 
> > > > optimized for
> > > > the touchscreen use case. By implementing it as IIO ADC device, we can
> > > > make use of resistive-adc-touch and iio-hwmon drivers.
> > > > 
> > > > So far, this driver was tested with custom version of 
> > > > resistive-adc-touch driver,
> > > > since it need to be extended to make use of Z1 and Z2 channels. The X/Y
> > > > are working without additional changes.
> > > > 
> > > > Signed-off-by: Oleksij Rempel   
> > > 
> > > Hi Oleksij,
> > > 
> > > To consider this as a possible long term route instead of just making this
> > > a touchscreen driver, we'll want to see those mods to the 
> > > resistive-adc-touch.
> > > Of course that doesn't stop review of this in the meantime.  
> > 
> > ok.
> > 
> > I had following issues with the existing resistive-adc-touch driver:
> > - the buffer layout is not configurable over DT or i didn't understood
> >   how to properly configure it
> > - the "pressure" channel provide pre processed data driver or
> >   controller, this information cannot be extracted directly from the
> >   touchscreen plates.
> > 
> > I did following changes to make it work for my use case:
> > 
> > --- a/drivers/input/touchscreen/resistive-adc-touch.c
> > +++ b/drivers/input/touchscreen/resistive-adc-touch.c
> > @@ -44,15 +44,34 @@ static int grts_cb(const void *data, void *private)
> >  {
> > const u16 *touch_info = data;
> > struct grts_state *st = private;
> > -   unsigned int x, y, press = 0x0;
> > +   unsigned int x, y, press = 0x0, z1, z2;
> > +   unsigned int Rt;
> >  
> > /* channel data coming in buffer in the order below */
> > -   x = touch_info[0];
> > -   y = touch_info[1];
> > +   // TODO: make sure we get buffers in proper order
> 
> Ah.  So to figure this out we'll need to read some more info about the
> channels.  The phandle order for the touchscreen binding
> should probably be specified (if it's not already) and that should let
> us establish the ordering of channels. 

Ack. So this should be done in the touchscreen driver and can be done
later?

> > +   x = touch_info[3];
> > +   z2 = touch_info[2];
> > +   z1 = touch_info[1];
> > +   y = touch_info[0];
> > +
> > +   if (z1) {
> > +   Rt = z2;
> 
> So for this we are going to need to define it in a generic fashion - probably
> via a mode + coefficients in DT?

I assume, mode will be needed any way, coefficients can stay as is and
if we get some different use case add an overwrite binding to the
devicetree.

> > +   Rt -= z1;
> > +   Rt *= 800;
> > +   //Rt *= ts->x_plate_ohms;
> > +   Rt = DIV_ROUND_CLOSEST(Rt, 16);
> > +   Rt *= x;
> > +   Rt /= z1;
> > +   Rt = DIV_ROUND_CLOSEST(Rt, 256);
> > +   } else
> > +   Rt = 0x400;
> > +
> > if (st->pressure)
> > -   press = touch_info[2];
> > +   press = Rt;
> >  
> > -   if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
> > +   //printk("%s:%i: x: %x, y %x, z1: %x, z2: %x, press: %x\n", __func__, 
> > __LINE__, x, y, z1, z2, press);
> > +   //if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
> > +   if ((!x && !y) || (st->pressure && (press > 0x350))) {
> > /* report end of touch */
> > input_report_key(st->input, BTN_TOUCH, 0);
> > input_sync(st->input);
> > @@ -116,7 +135,7 @@ static int grts_probe(struct platform_device *pdev)
> > }
> >  
> > chan = >iio_chans[0];
> > -   st->pressure = false;
> > +   st->pressure = true;
> > while (chan && chan->indio_dev) {
> >  
> > 
> > 
> > > There are quite a few things in here that feel pretty specific to the 
> > > touchscreen
> > > usecase. That makes me wonder if this is a sensible approach or not.  
> > 
> > I'm sure it is the right way to go. Here is w

Re: [PATCH v1 2/2] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-09 Thread Oleksij Rempel
On Sun, Mar 07, 2021 at 03:05:31PM -0800, Dmitry Torokhov wrote:
> Hi Oleksij,
> 
> On Fri, Mar 05, 2021 at 02:38:13PM +0100, Oleksij Rempel wrote:
> > +
> > +   /* TODO: remove IRQ_NOAUTOEN after needed patches are mainline */
> > +   irq_set_status_flags(spi->irq, IRQ_NOAUTOEN);
> > +   ret = devm_request_threaded_irq(dev, spi->irq,
> > +   NULL,
> > +   _adc_irq,
> > +   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> > +   name, indio_dev);
> 
> I'd recommend dropping IRQF_TRIGGER_LOW and only using IRQF_ONESHOT and
> rely on the platform (ACPI, DT) to specify trigger polarity according to
> how device is wired in a given system. In general I believe newer
> drivers should not specify interrupt triggers themselves.

Ok, thx. Sounds good.

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


[PATCH v2 0/7] remove different PHY fixups

2021-03-09 Thread Oleksij Rempel
changes v2:
- rebase against latest kernel
- fix networking on RIoTBoard

This patch series tries to remove most of the imx6 and imx7 board
specific PHY configuration via fixup, as this breaks the PHYs when
connected to switch chips or USB Ethernet MACs.

Each patch has the possibility to break boards, but contains a
recommendation to fix the problem in a more portable and future-proof
way.

regards,
Oleksij

Oleksij Rempel (7):
  ARM: imx6q: remove PHY fixup for KSZ9031
  ARM: imx6q: remove TX clock delay of ar8031_phy_fixup()
  ARM: imx6q: remove hand crafted PHY power up in ar8035_phy_fixup()
  ARM: imx6q: remove clk-out fixup for the Atheros AR8031 and AR8035
PHYs
  ARM: imx6q: remove Atheros AR8035 SmartEEE fixup
  ARM: imx6sx: remove Atheros AR8031 PHY fixup
  ARM: imx7d: remove Atheros AR8031 PHY fixup

 arch/arm/boot/dts/imx6dl-riotboard.dts  |  2 +
 arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts |  2 +-
 arch/arm/mach-imx/mach-imx6q.c  | 85 -
 arch/arm/mach-imx/mach-imx6sx.c | 26 
 arch/arm/mach-imx/mach-imx7d.c  | 22 ---
 5 files changed, 3 insertions(+), 134 deletions(-)

-- 
2.29.2



[PATCH v2 4/7] ARM: imx6q: remove clk-out fixup for the Atheros AR8031 and AR8035 PHYs

2021-03-09 Thread Oleksij Rempel
This configuration should be set over device tree.

If this patch breaks network functionality on your system, enable the
AT803X_PHY driver and set following device tree property in the PHY
node:

qca,clk-out-frequency = <12500>;

Signed-off-by: Oleksij Rempel 
---
 arch/arm/boot/dts/imx6dl-riotboard.dts |  2 ++
 arch/arm/mach-imx/mach-imx6q.c | 30 --
 2 files changed, 2 insertions(+), 30 deletions(-)

diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts 
b/arch/arm/boot/dts/imx6dl-riotboard.dts
index 065d3ab0f50a..e7d9bfbfd0e4 100644
--- a/arch/arm/boot/dts/imx6dl-riotboard.dts
+++ b/arch/arm/boot/dts/imx6dl-riotboard.dts
@@ -106,6 +106,8 @@ rgmii_phy: ethernet-phy@4 {
reset-gpios = < 31 GPIO_ACTIVE_LOW>;
reset-assert-us = <1>;
reset-deassert-us = <1000>;
+   qca,smarteee-tw-us-1g = <24>;
+   qca,clk-out-frequency = <12500>;
};
};
 };
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 4c840e116003..d12b571a61ac 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -68,25 +68,6 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8609, 
ventana_pciesw_early_fixup);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8606, ventana_pciesw_early_fixup);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8604, ventana_pciesw_early_fixup);
 
-static int ar8031_phy_fixup(struct phy_device *dev)
-{
-   u16 val;
-
-   /* To enable AR8031 output a 125MHz clk from CLK_25M */
-   phy_write(dev, 0xd, 0x7);
-   phy_write(dev, 0xe, 0x8016);
-   phy_write(dev, 0xd, 0x4007);
-
-   val = phy_read(dev, 0xe);
-   val &= 0xffe3;
-   val |= 0x18;
-   phy_write(dev, 0xe, val);
-
-   return 0;
-}
-
-#define PHY_ID_AR8031  0x004dd074
-
 static int ar8035_phy_fixup(struct phy_device *dev)
 {
u16 val;
@@ -101,15 +82,6 @@ static int ar8035_phy_fixup(struct phy_device *dev)
val = phy_read(dev, 0xe);
phy_write(dev, 0xe, val & ~(1 << 8));
 
-   /*
-* Enable 125MHz clock from CLK_25M on the AR8031.  This
-* is fed in to the IMX6 on the ENET_REF_CLK (V22) pad.
-* Also, introduce a tx clock delay.
-*
-* This is the same as is the AR8031 fixup.
-*/
-   ar8031_phy_fixup(dev);
-
return 0;
 }
 
@@ -120,8 +92,6 @@ static void __init imx6q_enet_phy_init(void)
if (IS_BUILTIN(CONFIG_PHYLIB)) {
phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
ksz9021rn_phy_fixup);
-   phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffef,
-   ar8031_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_AR8035, 0xffef,
ar8035_phy_fixup);
}
-- 
2.29.2



[PATCH v2 1/7] ARM: imx6q: remove PHY fixup for KSZ9031

2021-03-09 Thread Oleksij Rempel
Starting with:

bcf3440c6dd7 ("net: phy: micrel: add phy-mode support for the KSZ9031 PHY")

the micrel phy driver started respecting phy-mode for the KSZ9031 PHY.
At least with kernel v5.8 configuration provided by this fixup was
overwritten by the micrel driver.

This fixup was providing following configuration:

RX path: 2.58ns delay
rx -0.42 (left shift) + rx_clk  +0.96ns (right shift) =
1,38 + 1,2 internal RX delay = 2.58ns
TX path: 0.96ns delay
tx (no delay) + tx_clk 0.96ns (right shift) = 0.96ns

This configuration is outside of the recommended RGMII clock skew delays
and about in the middle of: rgmii-idrx and rgmii-id

Since most embedded systems do not have enough place to introduce
significant clock skew, rgmii-id is the way to go.

In case this patch breaks network functionality on your system, build
kernel with enabled MICREL_PHY. If it is still not working then try
following device tree options:
1. Set (or change) phy-mode in DT to:
   phy-mode = "rgmii-id";
   This actives internal delay for both RX and TX.
1. Set (or change) phy-mode in DT to:
   phy-mode = "rgmii-idrx";
   This actives internal delay for RX only.
3. Use following DT properties:
   phy-mode = "rgmii";
   txen-skew-psec = <0>;
   rxdv-skew-psec = <0>;
   rxd0-skew-psec = <0>;
   rxd1-skew-psec = <0>;
   rxd2-skew-psec = <0>;
   rxd3-skew-psec = <0>;
   rxc-skew-psec = <1860>;
   txc-skew-psec = <1860>;
   This activates the internal delays for RX and TX, with the value as
   the fixup that is removed in this patch.

Signed-off-by: Oleksij Rempel 
Acked-by: Philippe Schenker 
---
 arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts |  2 +-
 arch/arm/mach-imx/mach-imx6q.c  | 23 ---
 2 files changed, 1 insertion(+), 24 deletions(-)

diff --git a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts 
b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
index fa2307d8ce86..c713ac03b3b9 100644
--- a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
+++ b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
@@ -112,7 +112,7 @@ flash: m25p80@0 {
  {
pinctrl-names = "default";
pinctrl-0 = <_enet>;
-   phy-mode = "rgmii";
+   phy-mode = "rgmii-id";
phy-reset-gpios = < 25 GPIO_ACTIVE_LOW>;
phy-supply = <_1v2_eth>;
status = "okay";
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 703998ebb52e..78205f90da27 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -40,27 +40,6 @@ static int ksz9021rn_phy_fixup(struct phy_device *phydev)
return 0;
 }
 
-static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
-{
-   phy_write(dev, 0x0d, device);
-   phy_write(dev, 0x0e, reg);
-   phy_write(dev, 0x0d, (1 << 14) | device);
-   phy_write(dev, 0x0e, val);
-}
-
-static int ksz9031rn_phy_fixup(struct phy_device *dev)
-{
-   /*
-* min rx data delay, max rx/tx clock delay,
-* min rx/tx control delay
-*/
-   mmd_write_reg(dev, 2, 4, 0);
-   mmd_write_reg(dev, 2, 5, 0);
-   mmd_write_reg(dev, 2, 8, 0x003ff);
-
-   return 0;
-}
-
 /*
  * fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High
  * as they are used for slots1-7 PERST#
@@ -152,8 +131,6 @@ static void __init imx6q_enet_phy_init(void)
if (IS_BUILTIN(CONFIG_PHYLIB)) {
phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
ksz9021rn_phy_fixup);
-   phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
-   ksz9031rn_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffef,
ar8031_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_AR8035, 0xffef,
-- 
2.29.2



[PATCH v2 6/7] ARM: imx6sx: remove Atheros AR8031 PHY fixup

2021-03-09 Thread Oleksij Rempel
If this patch breaks your system, enable AT803X_PHY driver and add a PHY
node to the board device tree:

phy-connection-type = "rgmii-txid"; (or rgmii-id)
ethernet-phy@X {
reg = <0xX>;

qca,clk-out-frequency = <12500>;

vddio-supply = <>;

vddio: vddio-regulator {
regulator-name = "VDDIO";
regulator-min-microvolt = <180>;
regulator-max-microvolt = <180>;
};

vddh: vddh-regulator {
regulator-name = "VDDH";
};
};

Signed-off-by: Oleksij Rempel 
---
 arch/arm/mach-imx/mach-imx6sx.c | 26 --
 1 file changed, 26 deletions(-)

diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 781e2a94fdd7..e65ed5218f53 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -15,31 +15,6 @@
 #include "common.h"
 #include "cpuidle.h"
 
-static int ar8031_phy_fixup(struct phy_device *dev)
-{
-   u16 val;
-
-   /* Set RGMII IO voltage to 1.8V */
-   phy_write(dev, 0x1d, 0x1f);
-   phy_write(dev, 0x1e, 0x8);
-
-   /* introduce tx clock delay */
-   phy_write(dev, 0x1d, 0x5);
-   val = phy_read(dev, 0x1e);
-   val |= 0x0100;
-   phy_write(dev, 0x1e, val);
-
-   return 0;
-}
-
-#define PHY_ID_AR8031   0x004dd074
-static void __init imx6sx_enet_phy_init(void)
-{
-   if (IS_BUILTIN(CONFIG_PHYLIB))
-   phy_register_fixup_for_uid(PHY_ID_AR8031, 0x,
-  ar8031_phy_fixup);
-}
-
 static void __init imx6sx_enet_clk_sel(void)
 {
struct regmap *gpr;
@@ -57,7 +32,6 @@ static void __init imx6sx_enet_clk_sel(void)
 
 static inline void imx6sx_enet_init(void)
 {
-   imx6sx_enet_phy_init();
imx6sx_enet_clk_sel();
 }
 
-- 
2.29.2



[PATCH v2 3/7] ARM: imx6q: remove hand crafted PHY power up in ar8035_phy_fixup()

2021-03-09 Thread Oleksij Rempel
The at803x_resume() handler in the at803x.c PHY driver powers up the PHY
properly, so remove this fixup.

If this patch breaks your system, enable the AT803X_PHY driver.

Signed-off-by: Oleksij Rempel 
---
 arch/arm/mach-imx/mach-imx6q.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 1abefe7e1c3a..4c840e116003 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -110,11 +110,6 @@ static int ar8035_phy_fixup(struct phy_device *dev)
 */
ar8031_phy_fixup(dev);
 
-   /*check phy power*/
-   val = phy_read(dev, 0x0);
-   if (val & BMCR_PDOWN)
-   phy_write(dev, 0x0, val & ~BMCR_PDOWN);
-
return 0;
 }
 
-- 
2.29.2



[PATCH v2 5/7] ARM: imx6q: remove Atheros AR8035 SmartEEE fixup

2021-03-09 Thread Oleksij Rempel
This fixup removes the Lpi_en bit.

If this patch breaks functionality of your board, use following device
tree properties: qca,smarteee-tw-us-1g and qca,smarteee-tw-us-100m.

For example:

ethernet-phy@X {
reg = <0xX>;
qca,smarteee-tw-us-1g = <24>;

};

Signed-off-by: Oleksij Rempel 
---
 arch/arm/mach-imx/mach-imx6q.c | 21 -
 1 file changed, 21 deletions(-)

diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index d12b571a61ac..c9d7c29d95e1 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -68,32 +68,11 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8609, 
ventana_pciesw_early_fixup);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8606, ventana_pciesw_early_fixup);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8604, ventana_pciesw_early_fixup);
 
-static int ar8035_phy_fixup(struct phy_device *dev)
-{
-   u16 val;
-
-   /* Ar803x phy SmartEEE feature cause link status generates glitch,
-* which cause ethernet link down/up issue, so disable SmartEEE
-*/
-   phy_write(dev, 0xd, 0x3);
-   phy_write(dev, 0xe, 0x805d);
-   phy_write(dev, 0xd, 0x4003);
-
-   val = phy_read(dev, 0xe);
-   phy_write(dev, 0xe, val & ~(1 << 8));
-
-   return 0;
-}
-
-#define PHY_ID_AR8035 0x004dd072
-
 static void __init imx6q_enet_phy_init(void)
 {
if (IS_BUILTIN(CONFIG_PHYLIB)) {
phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
ksz9021rn_phy_fixup);
-   phy_register_fixup_for_uid(PHY_ID_AR8035, 0xffef,
-   ar8035_phy_fixup);
}
 }
 
-- 
2.29.2



[PATCH v2 7/7] ARM: imx7d: remove Atheros AR8031 PHY fixup

2021-03-09 Thread Oleksij Rempel
This fixup configures the IO voltage and disables the SmartEEE
functionality.

If this patch breaks your system, enable AT803X_PHY driver and configure
the PHY by the device tree:

phy-connection-type = "rgmii-id";
ethernet-phy@X {
reg = <0xX>;

qca,smarteee-tw-us-1g = <24>;

vddio-supply = <>;

vddio: vddio-regulator {
regulator-name = "VDDIO";
regulator-min-microvolt = <180>;
regulator-max-microvolt = <180>;
};

vddh: vddh-regulator {
regulator-name = "VDDH";
};
};

Signed-off-by: Oleksij Rempel 
---
 arch/arm/mach-imx/mach-imx7d.c | 22 --
 1 file changed, 22 deletions(-)

diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c
index 879c35929a13..ccf64ddf8b7e 100644
--- a/arch/arm/mach-imx/mach-imx7d.c
+++ b/arch/arm/mach-imx/mach-imx7d.c
@@ -14,25 +14,6 @@
 
 #include "common.h"
 
-static int ar8031_phy_fixup(struct phy_device *dev)
-{
-   u16 val;
-
-   /* Set RGMII IO voltage to 1.8V */
-   phy_write(dev, 0x1d, 0x1f);
-   phy_write(dev, 0x1e, 0x8);
-
-   /* disable phy AR8031 SmartEEE function. */
-   phy_write(dev, 0xd, 0x3);
-   phy_write(dev, 0xe, 0x805d);
-   phy_write(dev, 0xd, 0x4003);
-   val = phy_read(dev, 0xe);
-   val &= ~(0x1 << 8);
-   phy_write(dev, 0xe, val);
-
-   return 0;
-}
-
 static int bcm54220_phy_fixup(struct phy_device *dev)
 {
/* enable RXC skew select RGMII copper mode */
@@ -44,14 +25,11 @@ static int bcm54220_phy_fixup(struct phy_device *dev)
return 0;
 }
 
-#define PHY_ID_AR8031  0x004dd074
 #define PHY_ID_BCM542200x600d8589
 
 static void __init imx7d_enet_phy_init(void)
 {
if (IS_BUILTIN(CONFIG_PHYLIB)) {
-   phy_register_fixup_for_uid(PHY_ID_AR8031, 0x,
-  ar8031_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_BCM54220, 0x,
   bcm54220_phy_fixup);
}
-- 
2.29.2



[PATCH v2 2/7] ARM: imx6q: remove TX clock delay of ar8031_phy_fixup()

2021-03-09 Thread Oleksij Rempel
In case the at803x PHY driver is activated in the kernel, the TX clock
fixup is overwritten by at803x_config_init(), in this case no additional
device tree changes are needed.

If this patch breaks your system, please enable AT803X_PHY driver and
add the following device tree property to the PHY node:

phy-mode = "rgmii-txid";

Signed-off-by: Oleksij Rempel 
---
 arch/arm/mach-imx/mach-imx6q.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 78205f90da27..1abefe7e1c3a 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -82,12 +82,6 @@ static int ar8031_phy_fixup(struct phy_device *dev)
val |= 0x18;
phy_write(dev, 0xe, val);
 
-   /* introduce tx clock delay */
-   phy_write(dev, 0x1d, 0x5);
-   val = phy_read(dev, 0x1e);
-   val |= 0x0100;
-   phy_write(dev, 0x1e, val);
-
return 0;
 }
 
-- 
2.29.2



Re: [PATCH v1 2/2] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-06 Thread Oleksij Rempel
On Fri, Mar 05, 2021 at 07:02:39PM +, Jonathan Cameron wrote:
> On Fri, 5 Mar 2021 14:38:13 +0100
> Oleksij Rempel  wrote:
> 
> > Basically the TI TSC2046 touchscreen controller is 8 channel ADC optimized 
> > for
> > the touchscreen use case. By implementing it as IIO ADC device, we can
> > make use of resistive-adc-touch and iio-hwmon drivers.
> > 
> > So far, this driver was tested with custom version of resistive-adc-touch 
> > driver,
> > since it need to be extended to make use of Z1 and Z2 channels. The X/Y
> > are working without additional changes.
> > 
> > Signed-off-by: Oleksij Rempel 
> 
> Hi Oleksij,
> 
> To consider this as a possible long term route instead of just making this
> a touchscreen driver, we'll want to see those mods to the resistive-adc-touch.
> Of course that doesn't stop review of this in the meantime.

ok.

I had following issues with the existing resistive-adc-touch driver:
- the buffer layout is not configurable over DT or i didn't understood
  how to properly configure it
- the "pressure" channel provide pre processed data driver or
  controller, this information cannot be extracted directly from the
  touchscreen plates.

I did following changes to make it work for my use case:

--- a/drivers/input/touchscreen/resistive-adc-touch.c
+++ b/drivers/input/touchscreen/resistive-adc-touch.c
@@ -44,15 +44,34 @@ static int grts_cb(const void *data, void *private)
 {
const u16 *touch_info = data;
struct grts_state *st = private;
-   unsigned int x, y, press = 0x0;
+   unsigned int x, y, press = 0x0, z1, z2;
+   unsigned int Rt;
 
/* channel data coming in buffer in the order below */
-   x = touch_info[0];
-   y = touch_info[1];
+   // TODO: make sure we get buffers in proper order
+   x = touch_info[3];
+   z2 = touch_info[2];
+   z1 = touch_info[1];
+   y = touch_info[0];
+
+   if (z1) {
+   Rt = z2;
+   Rt -= z1;
+   Rt *= 800;
+   //Rt *= ts->x_plate_ohms;
+   Rt = DIV_ROUND_CLOSEST(Rt, 16);
+   Rt *= x;
+   Rt /= z1;
+   Rt = DIV_ROUND_CLOSEST(Rt, 256);
+   } else
+   Rt = 0x400;
+
if (st->pressure)
-   press = touch_info[2];
+   press = Rt;
 
-   if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
+   //printk("%s:%i: x: %x, y %x, z1: %x, z2: %x, press: %x\n", __func__, 
__LINE__, x, y, z1, z2, press);
+   //if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
+   if ((!x && !y) || (st->pressure && (press > 0x350))) {
/* report end of touch */
input_report_key(st->input, BTN_TOUCH, 0);
input_sync(st->input);
@@ -116,7 +135,7 @@ static int grts_probe(struct platform_device *pdev)
}
 
chan = >iio_chans[0];
-   st->pressure = false;
+   st->pressure = true;
while (chan && chan->indio_dev) {
 


> There are quite a few things in here that feel pretty specific to the 
> touchscreen
> usecase. That makes me wonder if this is a sensible approach or not.

I'm sure it is the right way to go. Here is why:

A typical resistive touchscreen can be described as 2 resistors (plates)
shorted to each other on pressure:

  o Y+
  |
  #
  #
  # / shorted on pressure
  |/
o---###---+---###--o
X-|X+
  #
  #
  #
  |
  o Y-


To find the location of shorted circuit (finger position) we need to
measure voltage on different points of the circuit:
- to get X-position, apply voltage on X+/X- and measure voltage on Y+
- to get Y-position, apply voltage on Y+/Y- and measure voltage on X+

Measuring the "pressure" is a bit more tricky:
- apply voltage on X-/Y+ and measure on X+ and Y-, so we will get Z1 and
  Z2
- will need to know real plate resistance to do following calculation:
  Rtouch = Rx-plate * (X-position / 4096) * (Z2/Z1 - 1)

There is is still more points which share all resistive touchscreens:
- they have parasitic capacitance, so it take some time between
  switching to voltage on and usable measurements
- they act as antenna, so we measure different kind of electrical noise
- we have low-frequency mechanical waves on the plates which can trigger
  some bounce artifacts
- the results will change depending on the temperature and the supply
  voltage. So we need to monitor both of them to adjust our results.

To handle this issues we need to skip some samples until voltage is
settled, we need to apply some simple digital low-pass filter to
reduce the noise and add some corrections if we are able to measure

[PATCH v1 2/2] iio: adc: add ADC driver for the TI TSC2046 controller

2021-03-05 Thread Oleksij Rempel
Basically the TI TSC2046 touchscreen controller is 8 channel ADC optimized for
the touchscreen use case. By implementing it as IIO ADC device, we can
make use of resistive-adc-touch and iio-hwmon drivers.

So far, this driver was tested with custom version of resistive-adc-touch 
driver,
since it need to be extended to make use of Z1 and Z2 channels. The X/Y
are working without additional changes.

Signed-off-by: Oleksij Rempel 
---
 MAINTAINERS  |   8 +
 drivers/iio/adc/Kconfig  |  12 +
 drivers/iio/adc/Makefile |   1 +
 drivers/iio/adc/ti-tsc2046.c | 652 +++
 4 files changed, 673 insertions(+)
 create mode 100644 drivers/iio/adc/ti-tsc2046.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 3fea1a934b32..2d33c6442a55 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17852,6 +17852,14 @@ S: Supported
 F: Documentation/devicetree/bindings/net/nfc/trf7970a.txt
 F: drivers/nfc/trf7970a.c
 
+TI TSC2046 ADC DRIVER
+M: Oleksij Rempel 
+R: ker...@pengutronix.de
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
+F: drivers/iio/adc/ti-tsc2046.c
+
 TI TWL4030 SERIES SOC CODEC DRIVER
 M: Peter Ujfalusi 
 L: alsa-de...@alsa-project.org (moderated for non-subscribers)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 15587a1bc80d..6ad6f04dfd20 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1175,6 +1175,18 @@ config TI_TLC4541
  This driver can also be built as a module. If so, the module will be
  called ti-tlc4541.
 
+config TI_TSC2046
+   tristate "Texas Instruments TSC2046 ADC driver"
+   depends on SPI
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
+   help
+ Say yes here to build support for ADC functionality of Texas
+ Instruments TSC2046 touch screen controller.
+
+ This driver can also be built as a module. If so, the module will be
+ called ti-tsc2046.
+
 config TWL4030_MADC
tristate "TWL4030 MADC (Monitoring A/D Converter)"
depends on TWL4030_CORE
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 5fca90ada0ec..440e18ac6780 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -105,6 +105,7 @@ obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o
 obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
 obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o
+obj-$(CONFIG_TI_TSC2046) += ti-tsc2046.o
 obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
 obj-$(CONFIG_TWL6030_GPADC) += twl6030-gpadc.o
 obj-$(CONFIG_VF610_ADC) += vf610_adc.o
diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c
new file mode 100644
index ..e119e7c31fa7
--- /dev/null
+++ b/drivers/iio/adc/ti-tsc2046.c
@@ -0,0 +1,652 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Texas Instruments TSC2046 SPI ADC driver
+ *
+ * Copyright (c) 2021 Oleksij Rempel , Pengutronix
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TI_TSC2046_NAME"tsc2046"
+
+/* this driver doesn't aim at the peak continuous sample rate */
+#defineTI_TSC2046_MAX_SAMPLE_RATE  125000
+#defineTI_TSC2046_SAMPLE_BITS  (8 /*cmd*/ + 16 
/*sample*/)
+#defineTI_TSC2046_MAX_CLK_FREQ \
+   (TI_TSC2046_MAX_SAMPLE_RATE * TI_TSC2046_SAMPLE_BITS)
+
+/*
+ * Default settling time. This time depends on the:
+ * - PCB design
+ * - touch plates size, temperature, etc
+ * - initial power state of the ADC
+ *
+ * Since most values higher than 100us seems to be good, it make sense to
+ * have some default value. These values were measuring get by testing on a
+ * PLYM2M board at 2MHz SPI CLK rate.
+ *
+ * Sometimes there are extra signal filter capacitors on the touchscreen
+ * signals, which make it 10 or 100 times worse.
+ */
+#define TI_TSC2046_SETTLING_TIME_XYZ_DEF_US700
+/* Oversampling count for the low-pass filter */
+#define TI_TSC2046_SAMPLES_XYZ_DEF 5
+/* Default sample interval */
+#define TI_TSC2046_SAMPLE_INTERVAL_US  1
+
+#define TI_TSC2046_START   BIT(7)
+#define TI_TSC2046_ADDRGENMASK(6, 4)
+#define TI_TSC2046_ADDR_TEMP1  7
+#define TI_TSC2046_ADDR_AUX6
+#define TI_TSC2046_ADDR_X  5
+#define TI_TSC2046_ADDR_Z2 4
+#define TI_TSC2046_ADDR_Z1 3
+#define TI_TSC2046_ADDR_VBAT   2
+#define TI_TSC2046_ADDR_Y  1
+#define TI_TSC2046_ADDR_TEMP0  0
+
+/*
+ * The mode bit sets the resolution of the ADC. With this bit low, the next
+ * conversion has 12-bit resolution, whereas with this bit high, the next
+ * conversion has 8-bit resolu

[PATCH v1 1/2] dt-bindings:iio:adc: add documentation for TI TSC2046 controller

2021-03-05 Thread Oleksij Rempel
Add a binding documentation for the TI TSC2046 touchscreen controllers
ADC functionality.

Signed-off-by: Oleksij Rempel 
---
 .../bindings/iio/adc/ti,tsc2046.yaml  | 52 +++
 1 file changed, 52 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml

diff --git a/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml 
b/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
new file mode 100644
index ..cd1dd40f84df
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/ti,tsc2046.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments TSC2046 touch screen controller.
+
+maintainers:
+  - Oleksij Rempel 
+
+description: |
+  TSC2046 is a touch screen controller with 8 channels ADC.
+
+properties:
+  compatible:
+enum:
+  - ti,tsc2046e-adc
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  spi-max-frequency: true
+
+  "#io-channel-cells":
+const: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+spi {
+#address-cells = <1>;
+#size-cells = <0>;
+
+adc@0 {
+compatible = "ti,tsc2046e-adc";
+reg = <0>;
+spi-max-frequency = <100>;
+interrupts-extended = < 20 IRQ_TYPE_LEVEL_LOW>;
+#io-channel-cells = <1>;
+};
+};
+...
-- 
2.29.2



[PATCH v1 0/2] mainline ti tsc2046 adc driver

2021-03-05 Thread Oleksij Rempel
TI TSC2046 is a touchscreen controller based on 8 channel ADC. Since most of
this ADC based touchscreen controller share same set of challenges, it
is better keep then as simple IIO ADC devices attached to a generic
resistive-adc-touch driver.

This driver can replace drivers/input/touchscreen/ads7846.c and has
following advantages over it:
- less code to maintain
- shared code paths (resistive-adc-touch, iio-hwmon, etc)
- can be used as plain IIO ADC to investigate signaling issues or test
  real capacity of the plates and attached low-pass filters
  (or use the touchscreen as a microphone if you like ;) )

Oleksij Rempel (2):
  dt-bindings:iio:adc: add documentation for TI TSC2046 controller
  iio: adc: add ADC driver for the TI TSC2046 controller

 .../bindings/iio/adc/ti,tsc2046.yaml  |  52 ++
 MAINTAINERS   |   8 +
 drivers/iio/adc/Kconfig   |  12 +
 drivers/iio/adc/Makefile  |   1 +
 drivers/iio/adc/ti-tsc2046.c  | 652 ++
 5 files changed, 725 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tsc2046.yaml
 create mode 100644 drivers/iio/adc/ti-tsc2046.c

-- 
2.29.2



[PATCH v8 2/2] counter: add IRQ or GPIO based counter

2021-03-01 Thread Oleksij Rempel
Add simple IRQ or GPIO base counter. This device is used to measure
rotation speed of some agricultural devices, so no high frequency on the
counter pin is expected.

The maximal measurement frequency depends on the CPU and system load. On
the idle iMX6S I was able to measure up to 20kHz without count drops.

Signed-off-by: Oleksij Rempel 
Reviewed-by: Ahmad Fatoum 
---
 MAINTAINERS |   7 +
 drivers/counter/Kconfig |  10 ++
 drivers/counter/Makefile|   1 +
 drivers/counter/interrupt-cnt.c | 244 
 4 files changed, 262 insertions(+)
 create mode 100644 drivers/counter/interrupt-cnt.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a50a543e3c81..ad0a4455afec 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9217,6 +9217,13 @@ F:   include/dt-bindings/interconnect/
 F: include/linux/interconnect-provider.h
 F: include/linux/interconnect.h
 
+INTERRUPT COUNTER DRIVER
+M: Oleksij Rempel 
+R: Pengutronix Kernel Team 
+L: linux-...@vger.kernel.org
+F: Documentation/devicetree/bindings/counter/interrupt-counter.yaml
+F: drivers/counter/interrupt-cnt.c
+
 INVENSENSE ICM-426xx IMU DRIVER
 M: Jean-Baptiste Maneyrol 
 L: linux-...@vger.kernel.org
diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
index 2de53ab0dd25..dcad13229134 100644
--- a/drivers/counter/Kconfig
+++ b/drivers/counter/Kconfig
@@ -29,6 +29,16 @@ config 104_QUAD_8
  The base port addresses for the devices may be configured via the base
  array module parameter.
 
+config INTERRUPT_CNT
+   tristate "Interrupt counter driver"
+   depends on GPIOLIB
+   help
+ Select this option to enable interrupt counter driver. Any interrupt
+ source can be used by this driver as the event source.
+
+ To compile this driver as a module, choose M here: the
+ module will be called interrupt-cnt.
+
 config STM32_TIMER_CNT
tristate "STM32 Timer encoder counter driver"
depends on MFD_STM32_TIMERS || COMPILE_TEST
diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
index 0a393f71e481..cb646ed2f039 100644
--- a/drivers/counter/Makefile
+++ b/drivers/counter/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_COUNTER) += counter.o
 
 obj-$(CONFIG_104_QUAD_8)   += 104-quad-8.o
+obj-$(CONFIG_INTERRUPT_CNT)+= interrupt-cnt.o
 obj-$(CONFIG_STM32_TIMER_CNT)  += stm32-timer-cnt.o
 obj-$(CONFIG_STM32_LPTIMER_CNT)+= stm32-lptimer-cnt.o
 obj-$(CONFIG_TI_EQEP)  += ti-eqep.o
diff --git a/drivers/counter/interrupt-cnt.c b/drivers/counter/interrupt-cnt.c
new file mode 100644
index ..a99ee7996977
--- /dev/null
+++ b/drivers/counter/interrupt-cnt.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Pengutronix, Oleksij Rempel 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define INTERRUPT_CNT_NAME "interrupt-cnt"
+
+struct interrupt_cnt_priv {
+   atomic_t count;
+   struct counter_device counter;
+   struct gpio_desc *gpio;
+   int irq;
+   bool enabled;
+   struct counter_signal signals;
+   struct counter_synapse synapses;
+   struct counter_count cnts;
+};
+
+static irqreturn_t interrupt_cnt_isr(int irq, void *dev_id)
+{
+   struct interrupt_cnt_priv *priv = dev_id;
+
+   atomic_inc(>count);
+
+   return IRQ_HANDLED;
+}
+
+static ssize_t interrupt_cnt_enable_read(struct counter_device *counter,
+struct counter_count *count,
+void *private, char *buf)
+{
+   struct interrupt_cnt_priv *priv = counter->priv;
+
+   return sysfs_emit(buf, "%d\n", priv->enabled);
+}
+
+static ssize_t interrupt_cnt_enable_write(struct counter_device *counter,
+ struct counter_count *count,
+ void *private, const char *buf,
+ size_t len)
+{
+   struct interrupt_cnt_priv *priv = counter->priv;
+   bool enable;
+   ssize_t ret;
+
+   ret = kstrtobool(buf, );
+   if (ret)
+   return ret;
+
+   if (priv->enabled == enable)
+   return len;
+
+   if (enable) {
+   priv->enabled = true;
+   enable_irq(priv->irq);
+   } else {
+   disable_irq(priv->irq);
+   priv->enabled = false;
+   }
+
+   return len;
+}
+
+static const struct counter_count_ext interrupt_cnt_ext[] = {
+   {
+   .name = "enable",
+   .read = interrupt_cnt_enable_read,
+   .write = interrupt_cnt_enable_write,
+   },
+};
+
+static enum counter_synapse_action interrupt_cnt_synapse_actionss[] = {
+   COUNTER_SYNAPSE_ACTION_RISING_ED

[PATCH v8 1/2] dt-bindings: counter: add interrupt-counter binding

2021-03-01 Thread Oleksij Rempel
Add binding for the interrupt counter node

Signed-off-by: Oleksij Rempel 
Reviewed-by: Linus Walleij 
---
 .../bindings/counter/interrupt-counter.yaml   | 62 +++
 1 file changed, 62 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/counter/interrupt-counter.yaml

diff --git a/Documentation/devicetree/bindings/counter/interrupt-counter.yaml 
b/Documentation/devicetree/bindings/counter/interrupt-counter.yaml
new file mode 100644
index ..fd075d104631
--- /dev/null
+++ b/Documentation/devicetree/bindings/counter/interrupt-counter.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/counter/interrupt-counter.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Interrupt counter
+
+maintainers:
+  - Oleksij Rempel 
+
+description: |
+  A generic interrupt counter to measure interrupt frequency. It was developed
+  and used for agricultural devices to measure rotation speed of wheels or
+  other tools. Since the direction of rotation is not important, only one
+  signal line is needed.
+  Interrupts or gpios are required. If both are defined, the interrupt will
+  take precedence for counting interrupts.
+
+properties:
+  compatible:
+const: interrupt-counter
+
+  interrupts:
+maxItems: 1
+
+  gpios:
+maxItems: 1
+
+required:
+  - compatible
+
+anyOf:
+  - required: [ interrupts-extended ]
+  - required: [ interrupts ]
+  - required: [ gpios ]
+
+additionalProperties: false
+
+examples:
+  - |
+
+#include 
+#include 
+
+counter-0 {
+compatible = "interrupt-counter";
+interrupts-extended = < 0 IRQ_TYPE_EDGE_RISING>;
+};
+
+counter-1 {
+compatible = "interrupt-counter";
+gpios = < 2 GPIO_ACTIVE_HIGH>;
+};
+
+counter-2 {
+compatible = "interrupt-counter";
+interrupts-extended = < 2 IRQ_TYPE_EDGE_RISING>;
+gpios = < 2 GPIO_ACTIVE_HIGH>;
+};
+
+...
-- 
2.29.2



[PATCH v8 0/2] add support for GPIO or IRQ based event counter

2021-03-01 Thread Oleksij Rempel
changes v8:
- use use enum index instead of enum value for the counter function
- register signal unconditionally and return error is signal revel is
  read 

changes v7:
- make most of structs dynamically allocatable to assign IRQ based
  description to the signal
- assign dev name instead for driver name to the IRQ

changes v6:
- rename it to interrupt-counter
- driver fixes
- device tree fixes

changes v5:
- rename it to event counter, since it support different event sources
- make it work with gpio-only or irq-only configuration
- update yaml binding

changes v4:
- use IRQ_NOAUTOEN to not enable IRQ by default
- rename gpio_ from name pattern and make this driver work any IRQ
  source.

changes v3:
- convert counter to atomic_t

changes v2:
- add commas
- avoid possible unhandled interrupts in the enable path
- do not use of_ specific gpio functions

Add support for GPIO based pulse counter. For now it can only count
pulses. With counter char device support, we will be able to attach
timestamps and measure actual pulse frequency.

Never the less, it is better to mainline this driver now (before chardev
patches go mainline), to provide developers additional use case for the counter
framework with chardev support.

Oleksij Rempel (2):
  dt-bindings: counter: add interrupt-counter binding
  counter: add IRQ or GPIO based counter

 .../bindings/counter/interrupt-counter.yaml   |  62 +
 MAINTAINERS   |   7 +
 drivers/counter/Kconfig   |  10 +
 drivers/counter/Makefile  |   1 +
 drivers/counter/interrupt-cnt.c   | 244 ++
 5 files changed, 324 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/counter/interrupt-counter.yaml
 create mode 100644 drivers/counter/interrupt-cnt.c

-- 
2.29.2



Re: [PATCH v7 2/2] counter: add IRQ or GPIO based counter

2021-02-26 Thread Oleksij Rempel
Hi,

On Fri, Feb 26, 2021 at 06:45:20PM +0900, William Breathitt Gray wrote:
> On Fri, Feb 26, 2021 at 10:08:30AM +0100, Oleksij Rempel wrote:
> > Add simple IRQ or GPIO base counter. This device is used to measure
> > rotation speed of some agricultural devices, so no high frequency on the
> > counter pin is expected.
> > 
> > The maximal measurement frequency depends on the CPU and system load. On
> > the idle iMX6S I was able to measure up to 20kHz without count drops.
> > 
> > Signed-off-by: Oleksij Rempel 
> > Reviewed-by: Ahmad Fatoum 
> 
> Hi Oleksij,
> 
> We're almost there, but I spotted a couple of mistakes below.
> 
> > ---
> >  MAINTAINERS |   7 +
> >  drivers/counter/Kconfig |  10 ++
> >  drivers/counter/Makefile|   1 +
> >  drivers/counter/interrupt-cnt.c | 243 
> >  4 files changed, 261 insertions(+)
> >  create mode 100644 drivers/counter/interrupt-cnt.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index a50a543e3c81..ad0a4455afec 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -9217,6 +9217,13 @@ F:   include/dt-bindings/interconnect/
> >  F: include/linux/interconnect-provider.h
> >  F: include/linux/interconnect.h
> >  
> > +INTERRUPT COUNTER DRIVER
> > +M: Oleksij Rempel 
> > +R: Pengutronix Kernel Team 
> > +L: linux-...@vger.kernel.org
> > +F: Documentation/devicetree/bindings/counter/interrupt-counter.yaml
> > +F: drivers/counter/interrupt-cnt.c
> > +
> >  INVENSENSE ICM-426xx IMU DRIVER
> >  M: Jean-Baptiste Maneyrol 
> >  L: linux-...@vger.kernel.org
> > diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
> > index 2de53ab0dd25..dcad13229134 100644
> > --- a/drivers/counter/Kconfig
> > +++ b/drivers/counter/Kconfig
> > @@ -29,6 +29,16 @@ config 104_QUAD_8
> >   The base port addresses for the devices may be configured via the base
> >   array module parameter.
> >  
> > +config INTERRUPT_CNT
> > +   tristate "Interrupt counter driver"
> > +   depends on GPIOLIB
> > +   help
> > + Select this option to enable interrupt counter driver. Any interrupt
> > + source can be used by this driver as the event source.
> > +
> > + To compile this driver as a module, choose M here: the
> > + module will be called interrupt-cnt.
> > +
> >  config STM32_TIMER_CNT
> > tristate "STM32 Timer encoder counter driver"
> > depends on MFD_STM32_TIMERS || COMPILE_TEST
> > diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
> > index 0a393f71e481..cb646ed2f039 100644
> > --- a/drivers/counter/Makefile
> > +++ b/drivers/counter/Makefile
> > @@ -6,6 +6,7 @@
> >  obj-$(CONFIG_COUNTER) += counter.o
> >  
> >  obj-$(CONFIG_104_QUAD_8)   += 104-quad-8.o
> > +obj-$(CONFIG_INTERRUPT_CNT)+= interrupt-cnt.o
> >  obj-$(CONFIG_STM32_TIMER_CNT)  += stm32-timer-cnt.o
> >  obj-$(CONFIG_STM32_LPTIMER_CNT)+= stm32-lptimer-cnt.o
> >  obj-$(CONFIG_TI_EQEP)  += ti-eqep.o
> > diff --git a/drivers/counter/interrupt-cnt.c 
> > b/drivers/counter/interrupt-cnt.c
> > new file mode 100644
> > index ..550383b6b591
> > --- /dev/null
> > +++ b/drivers/counter/interrupt-cnt.c
> > @@ -0,0 +1,243 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2021 Pengutronix, Oleksij Rempel 
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#define INTERRUPT_CNT_NAME "interrupt-cnt"
> > +
> > +struct interrupt_cnt_priv {
> > +   atomic_t count;
> > +   struct counter_device counter;
> > +   struct gpio_desc *gpio;
> > +   int irq;
> > +   bool enabled;
> > +   struct counter_signal signals;
> > +   struct counter_synapse synapses;
> > +   struct counter_count cnts;
> > +};
> > +
> > +static irqreturn_t interrupt_cnt_isr(int irq, void *dev_id)
> > +{
> > +   struct interrupt_cnt_priv *priv = dev_id;
> > +
> > +   atomic_inc(>count);
> > +
> > +   return IRQ_HANDLED;
> > +}
> > +
> > +static ssize_t interrupt_cnt_enable_read(struct counter_device *counter,
> > +struct counter_count *count,
> > +void *private, char *buf)
> > +{
> > +   struct interrupt_cnt_pr

[PATCH net v4 1/1] can: can_skb_set_owner(): fix ref counting if socket was closed before setting skb ownership

2021-02-26 Thread Oleksij Rempel
There are two ref count variables controlling the free()ing of a socket:
- struct sock::sk_refcnt - which is changed by sock_hold()/sock_put()
- struct sock::sk_wmem_alloc - which accounts the memory allocated by
  the skbs in the send path.

In case there are still TX skbs on the fly and the socket() is closed,
the struct sock::sk_refcnt reaches 0. In the TX-path the CAN stack
clones an "echo" skb, calls sock_hold() on the original socket and
references it. This produces the following back trace:

| WARNING: CPU: 0 PID: 280 at lib/refcount.c:25 
refcount_warn_saturate+0x114/0x134
| refcount_t: addition on 0; use-after-free.
| Modules linked in: coda_vpu(E) v4l2_jpeg(E) videobuf2_vmalloc(E) imx_vdoa(E)
| CPU: 0 PID: 280 Comm: test_can.sh Tainted: GE 
5.11.0-04577-gf8ff6603c617 #203
| Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
| Backtrace:
| [<80bafea4>] (dump_backtrace) from [<80bb0280>] (show_stack+0x20/0x24) 
r7: r6:600f0113 r5: r4:81441220
| [<80bb0260>] (show_stack) from [<80bb593c>] (dump_stack+0xa0/0xc8)
| [<80bb589c>] (dump_stack) from [<8012b268>] (__warn+0xd4/0x114) r9:0019 
r8:80f4a8c2 r7:83e4150c r6: r5:0009 r4:80528f90
| [<8012b194>] (__warn) from [<80bb09c4>] (warn_slowpath_fmt+0x88/0xc8) 
r9:83f26400 r8:80f4a8d1 r7:0009 r6:80528f90 r5:0019 r4:80f4a8c2
| [<80bb0940>] (warn_slowpath_fmt) from [<80528f90>] 
(refcount_warn_saturate+0x114/0x134) r8: r7: r6:82b44000 
r5:834e5600 r4:83f4d540
| [<80528e7c>] (refcount_warn_saturate) from [<8079a4c8>] 
(__refcount_add.constprop.0+0x4c/0x50)
| [<8079a47c>] (__refcount_add.constprop.0) from [<8079a57c>] 
(can_put_echo_skb+0xb0/0x13c)
| [<8079a4cc>] (can_put_echo_skb) from [<8079ba98>] 
(flexcan_start_xmit+0x1c4/0x230) r9:0010 r8:83f48610 r7:0fdc 
r6:0c08 r5:82b44000 r4:834e5600
| [<8079b8d4>] (flexcan_start_xmit) from [<80969078>] 
(netdev_start_xmit+0x44/0x70) r9:814c0ba0 r8:80c8790c r7: r6:834e5600 
r5:82b44000 r4:82ab1f00
| [<80969034>] (netdev_start_xmit) from [<809725a4>] 
(dev_hard_start_xmit+0x19c/0x318) r9:814c0ba0 r8: r7:82ab1f00 
r6:82b44000 r5: r4:834e5600
| [<80972408>] (dev_hard_start_xmit) from [<809c6584>] 
(sch_direct_xmit+0xcc/0x264) r10:834e5600 r9: r8: r7:82b44000 
r6:82ab1f00 r5:834e5600 r4:83f27400
| [<809c64b8>] (sch_direct_xmit) from [<809c6c0c>] (__qdisc_run+0x4f0/0x534)

To fix this problem, only set skb ownership to sockets which have still
a ref count > 0.

Cc: Oliver Hartkopp 
Cc: Andre Naujoks 
Suggested-by: Eric Dumazet 
Fixes: 0ae89beb283a ("can: add destructor for self generated skbs")
Signed-off-by: Oleksij Rempel 
---
 include/linux/can/skb.h | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 685f34cfba20..d82018cc0d0b 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -65,8 +65,12 @@ static inline void can_skb_reserve(struct sk_buff *skb)
 
 static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)
 {
-   if (sk) {
-   sock_hold(sk);
+   /*
+* If the socket has already been closed by user space, the refcount may
+* already be 0 (and the socket will be freed after the last TX skb has
+* been freed). So only increase socket refcount if the refcount is > 0.
+*/
+   if (sk && refcount_inc_not_zero(>sk_refcnt)) {
skb->destructor = sock_efree;
skb->sk = sk;
}
-- 
2.29.2



[PATCH v7 2/2] counter: add IRQ or GPIO based counter

2021-02-26 Thread Oleksij Rempel
Add simple IRQ or GPIO base counter. This device is used to measure
rotation speed of some agricultural devices, so no high frequency on the
counter pin is expected.

The maximal measurement frequency depends on the CPU and system load. On
the idle iMX6S I was able to measure up to 20kHz without count drops.

Signed-off-by: Oleksij Rempel 
Reviewed-by: Ahmad Fatoum 
---
 MAINTAINERS |   7 +
 drivers/counter/Kconfig |  10 ++
 drivers/counter/Makefile|   1 +
 drivers/counter/interrupt-cnt.c | 243 
 4 files changed, 261 insertions(+)
 create mode 100644 drivers/counter/interrupt-cnt.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a50a543e3c81..ad0a4455afec 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9217,6 +9217,13 @@ F:   include/dt-bindings/interconnect/
 F: include/linux/interconnect-provider.h
 F: include/linux/interconnect.h
 
+INTERRUPT COUNTER DRIVER
+M: Oleksij Rempel 
+R: Pengutronix Kernel Team 
+L: linux-...@vger.kernel.org
+F: Documentation/devicetree/bindings/counter/interrupt-counter.yaml
+F: drivers/counter/interrupt-cnt.c
+
 INVENSENSE ICM-426xx IMU DRIVER
 M: Jean-Baptiste Maneyrol 
 L: linux-...@vger.kernel.org
diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
index 2de53ab0dd25..dcad13229134 100644
--- a/drivers/counter/Kconfig
+++ b/drivers/counter/Kconfig
@@ -29,6 +29,16 @@ config 104_QUAD_8
  The base port addresses for the devices may be configured via the base
  array module parameter.
 
+config INTERRUPT_CNT
+   tristate "Interrupt counter driver"
+   depends on GPIOLIB
+   help
+ Select this option to enable interrupt counter driver. Any interrupt
+ source can be used by this driver as the event source.
+
+ To compile this driver as a module, choose M here: the
+ module will be called interrupt-cnt.
+
 config STM32_TIMER_CNT
tristate "STM32 Timer encoder counter driver"
depends on MFD_STM32_TIMERS || COMPILE_TEST
diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
index 0a393f71e481..cb646ed2f039 100644
--- a/drivers/counter/Makefile
+++ b/drivers/counter/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_COUNTER) += counter.o
 
 obj-$(CONFIG_104_QUAD_8)   += 104-quad-8.o
+obj-$(CONFIG_INTERRUPT_CNT)+= interrupt-cnt.o
 obj-$(CONFIG_STM32_TIMER_CNT)  += stm32-timer-cnt.o
 obj-$(CONFIG_STM32_LPTIMER_CNT)+= stm32-lptimer-cnt.o
 obj-$(CONFIG_TI_EQEP)  += ti-eqep.o
diff --git a/drivers/counter/interrupt-cnt.c b/drivers/counter/interrupt-cnt.c
new file mode 100644
index ..550383b6b591
--- /dev/null
+++ b/drivers/counter/interrupt-cnt.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Pengutronix, Oleksij Rempel 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define INTERRUPT_CNT_NAME "interrupt-cnt"
+
+struct interrupt_cnt_priv {
+   atomic_t count;
+   struct counter_device counter;
+   struct gpio_desc *gpio;
+   int irq;
+   bool enabled;
+   struct counter_signal signals;
+   struct counter_synapse synapses;
+   struct counter_count cnts;
+};
+
+static irqreturn_t interrupt_cnt_isr(int irq, void *dev_id)
+{
+   struct interrupt_cnt_priv *priv = dev_id;
+
+   atomic_inc(>count);
+
+   return IRQ_HANDLED;
+}
+
+static ssize_t interrupt_cnt_enable_read(struct counter_device *counter,
+struct counter_count *count,
+void *private, char *buf)
+{
+   struct interrupt_cnt_priv *priv = counter->priv;
+
+   return sysfs_emit(buf, "%d\n", priv->enabled);
+}
+
+static ssize_t interrupt_cnt_enable_write(struct counter_device *counter,
+ struct counter_count *count,
+ void *private, const char *buf,
+ size_t len)
+{
+   struct interrupt_cnt_priv *priv = counter->priv;
+   bool enable;
+   ssize_t ret;
+
+   ret = kstrtobool(buf, );
+   if (ret)
+   return ret;
+
+   if (priv->enabled == enable)
+   return len;
+
+   if (enable) {
+   priv->enabled = true;
+   enable_irq(priv->irq);
+   } else {
+   disable_irq(priv->irq);
+   priv->enabled = false;
+   }
+
+   return len;
+}
+
+static const struct counter_count_ext interrupt_cnt_ext[] = {
+   {
+   .name = "enable",
+   .read = interrupt_cnt_enable_read,
+   .write = interrupt_cnt_enable_write,
+   },
+};
+
+static enum counter_synapse_action interrupt_cnt_synapse_actionss[] = {
+   COUNTER_SYNAPSE_ACTION_RISING_ED

[PATCH v7 1/2] dt-bindings: counter: add interrupt-counter binding

2021-02-26 Thread Oleksij Rempel
Add binding for the interrupt counter node

Signed-off-by: Oleksij Rempel 
Reviewed-by: Linus Walleij 
---
 .../bindings/counter/interrupt-counter.yaml   | 62 +++
 1 file changed, 62 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/counter/interrupt-counter.yaml

diff --git a/Documentation/devicetree/bindings/counter/interrupt-counter.yaml 
b/Documentation/devicetree/bindings/counter/interrupt-counter.yaml
new file mode 100644
index ..fd075d104631
--- /dev/null
+++ b/Documentation/devicetree/bindings/counter/interrupt-counter.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/counter/interrupt-counter.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Interrupt counter
+
+maintainers:
+  - Oleksij Rempel 
+
+description: |
+  A generic interrupt counter to measure interrupt frequency. It was developed
+  and used for agricultural devices to measure rotation speed of wheels or
+  other tools. Since the direction of rotation is not important, only one
+  signal line is needed.
+  Interrupts or gpios are required. If both are defined, the interrupt will
+  take precedence for counting interrupts.
+
+properties:
+  compatible:
+const: interrupt-counter
+
+  interrupts:
+maxItems: 1
+
+  gpios:
+maxItems: 1
+
+required:
+  - compatible
+
+anyOf:
+  - required: [ interrupts-extended ]
+  - required: [ interrupts ]
+  - required: [ gpios ]
+
+additionalProperties: false
+
+examples:
+  - |
+
+#include 
+#include 
+
+counter-0 {
+compatible = "interrupt-counter";
+interrupts-extended = < 0 IRQ_TYPE_EDGE_RISING>;
+};
+
+counter-1 {
+compatible = "interrupt-counter";
+gpios = < 2 GPIO_ACTIVE_HIGH>;
+};
+
+counter-2 {
+compatible = "interrupt-counter";
+interrupts-extended = < 2 IRQ_TYPE_EDGE_RISING>;
+gpios = < 2 GPIO_ACTIVE_HIGH>;
+};
+
+...
-- 
2.29.2



[PATCH v7 0/2] add support for GPIO or IRQ based evemt counter

2021-02-26 Thread Oleksij Rempel
changes v7:
- make most of structs dynamically allocatable to assign IRQ based
  description to the signal
- assign dev name instead for driver name to the IRQ

changes v6:
- rename it to interrupt-counter
- driver fixes
- device tree fixes

changes v5:
- rename it to event counter, since it support different event sources
- make it work with gpio-only or irq-only configuration
- update yaml binding

changes v4:
- use IRQ_NOAUTOEN to not enable IRQ by default
- rename gpio_ from name pattern and make this driver work any IRQ
  source.

changes v3:
- convert counter to atomic_t

changes v2:
- add commas
- avoid possible unhandled interrupts in the enable path
- do not use of_ specific gpio functions

Add support for GPIO based pulse counter. For now it can only count
pulses. With counter char device support, we will be able to attach
timestamps and measure actual pulse frequency.

Never the less, it is better to mainline this driver now (before chardev
patches go mainline), to provide developers additional use case for the counter
framework with chardev support.

Oleksij Rempel (2):
  dt-bindings: counter: add interrupt-counter binding
  counter: add IRQ or GPIO based counter

 .../bindings/counter/interrupt-counter.yaml   |  62 +
 MAINTAINERS   |   7 +
 drivers/counter/Kconfig   |  10 +
 drivers/counter/Makefile  |   1 +
 drivers/counter/interrupt-cnt.c   | 243 ++
 5 files changed, 323 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/counter/interrupt-counter.yaml
 create mode 100644 drivers/counter/interrupt-cnt.c

-- 
2.29.2



Re: [PATCH v5 2/2] counter: add IRQ or GPIO based event counter

2021-02-25 Thread Oleksij Rempel
On Wed, Feb 24, 2021 at 05:20:21PM +0900, William Breathitt Gray wrote:
> On Wed, Feb 24, 2021 at 05:11:03PM +0900, William Breathitt Gray wrote:
> > On Wed, Feb 24, 2021 at 08:35:06AM +0100, Oleksij Rempel wrote:
> > > On Wed, Feb 24, 2021 at 11:34:06AM +0900, William Breathitt Gray wrote:
> > > > Alternatively, we can take a more generic approach: ignore the GPIO
> > > > names and focus solely on the IRQ lines; because the GPIO lines will
> > > > always be tied to respective IRQ lines here, using the IRQ as the basis
> > > > of the name should always be valid. The "name" member of the struct
> > > > irq_chip can work for this. I haven't tested this, but I think something
> > > > like this would work:
> > > > 
> > > > cnt_signals[0].name = irq_get_chip(priv->irq)->name;
> > > 
> > > ok, i'll take a look at it.
> > 
> > If that doesn't work, then use devm_kasprintf() to generate the name
> > based on the IRQ line number. The idea here is that the user should be
> > able to identify that the Signal component for this Count is the
> > respective IRQ.
> > 
> > William Breathitt Gray
> 
> I realized that these irq_chip names are often just the device name
> which isn't very useful either. :-(
> 
> In that case, I suppose we really are just left with generating the name
> based on the IRQ line number then. This should be fine then:
> 
>   cnt_signals[0].name = devm_kasprintf(dev, GFP_KERNEL, "IRQ %d",
>priv->irq);
>   if (!cnt_signals[0].name)
>   return -ENOMEM;
> 
> I think this would make it clear to the user that this Signal is the
> respective IRQ (whether sourced from GPIO or not).

ack, with one correction. cnt_signals should be allocated, otherwise
this value will be set per driver not per device.

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


[PATCH net v3 1/1] can: can_skb_set_owner(): fix ref counting if socket was closed before setting skb ownership

2021-02-24 Thread Oleksij Rempel
There are two ref count variables controlling the free()ing of a socket:
- struct sock::sk_refcnt - which is changed by sock_hold()/sock_put()
- struct sock::sk_wmem_alloc - which accounts the memory allocated by
  the skbs in the send path.

In case there are still TX skbs on the fly and the socket() is closed,
the struct sock::sk_refcnt reaches 0. In the TX-path the CAN stack
clones an "echo" skb, calls sock_hold() on the original socket and
references it. This produces the following back trace:

| WARNING: CPU: 0 PID: 280 at lib/refcount.c:25 
refcount_warn_saturate+0x114/0x134
| refcount_t: addition on 0; use-after-free.
| Modules linked in: coda_vpu(E) v4l2_jpeg(E) videobuf2_vmalloc(E) imx_vdoa(E)
| CPU: 0 PID: 280 Comm: test_can.sh Tainted: GE 
5.11.0-04577-gf8ff6603c617 #203
| Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
| Backtrace:
| [<80bafea4>] (dump_backtrace) from [<80bb0280>] (show_stack+0x20/0x24) 
r7: r6:600f0113 r5: r4:81441220
| [<80bb0260>] (show_stack) from [<80bb593c>] (dump_stack+0xa0/0xc8)
| [<80bb589c>] (dump_stack) from [<8012b268>] (__warn+0xd4/0x114) r9:0019 
r8:80f4a8c2 r7:83e4150c r6: r5:0009 r4:80528f90
| [<8012b194>] (__warn) from [<80bb09c4>] (warn_slowpath_fmt+0x88/0xc8) 
r9:83f26400 r8:80f4a8d1 r7:0009 r6:80528f90 r5:0019 r4:80f4a8c2
| [<80bb0940>] (warn_slowpath_fmt) from [<80528f90>] 
(refcount_warn_saturate+0x114/0x134) r8: r7: r6:82b44000 
r5:834e5600 r4:83f4d540
| [<80528e7c>] (refcount_warn_saturate) from [<8079a4c8>] 
(__refcount_add.constprop.0+0x4c/0x50)
| [<8079a47c>] (__refcount_add.constprop.0) from [<8079a57c>] 
(can_put_echo_skb+0xb0/0x13c)
| [<8079a4cc>] (can_put_echo_skb) from [<8079ba98>] 
(flexcan_start_xmit+0x1c4/0x230) r9:0010 r8:83f48610 r7:0fdc 
r6:0c08 r5:82b44000 r4:834e5600
| [<8079b8d4>] (flexcan_start_xmit) from [<80969078>] 
(netdev_start_xmit+0x44/0x70) r9:814c0ba0 r8:80c8790c r7: r6:834e5600 
r5:82b44000 r4:82ab1f00
| [<80969034>] (netdev_start_xmit) from [<809725a4>] 
(dev_hard_start_xmit+0x19c/0x318) r9:814c0ba0 r8: r7:82ab1f00 
r6:82b44000 r5: r4:834e5600
| [<80972408>] (dev_hard_start_xmit) from [<809c6584>] 
(sch_direct_xmit+0xcc/0x264) r10:834e5600 r9: r8: r7:82b44000 
r6:82ab1f00 r5:834e5600 r4:83f27400
| [<809c64b8>] (sch_direct_xmit) from [<809c6c0c>] (__qdisc_run+0x4f0/0x534)

To fix this problem, only set skb ownership to sockets which have still
a ref count > 0.

Cc: Oliver Hartkopp 
Cc: Andre Naujoks 
Suggested-by: Eric Dumazet 
Fixes: 0ae89beb283a ("can: add destructor for self generated skbs")
Signed-off-by: Oleksij Rempel 
---
 include/linux/can/skb.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 685f34cfba20..655f33aa99e3 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -65,8 +65,7 @@ static inline void can_skb_reserve(struct sk_buff *skb)
 
 static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)
 {
-   if (sk) {
-   sock_hold(sk);
+   if (sk && refcount_inc_not_zero(>sk_refcnt)) {
skb->destructor = sock_efree;
skb->sk = sk;
}
-- 
2.29.2



Re: [PATCH v5 2/2] counter: add IRQ or GPIO based event counter

2021-02-23 Thread Oleksij Rempel
Hello William,

On Wed, Feb 24, 2021 at 11:34:06AM +0900, William Breathitt Gray wrote:
> On Tue, Feb 23, 2021 at 06:45:16PM +0100, Oleksij Rempel wrote:
> > Hello William,
> > 
> > Here is cooled down technical answer. Excuse me for over reacting.
> 
> Hello Oleksij,
> 
> Let me apologize too if I offended you in some way in with previous
> response, I assure you that was not my intention. I truly do believe
> this is a useful driver to have in the kernel and I want to make that
> happen; my concerns with your patch are purely technical in nature and 
> I'm certain we can find a solution working together.

No problem :)

> > On Tue, Feb 23, 2021 at 11:06:56AM +0100, Oleksij Rempel wrote:
> > > On Mon, Feb 22, 2021 at 10:43:00AM +0900, William Breathitt Gray wrote:
> > > > On Mon, Feb 15, 2021 at 10:17:37AM +0100, Oleksij Rempel wrote:
> > > > > > > +static irqreturn_t event_cnt_isr(int irq, void *dev_id)
> > > > > > > +{
> > > > > > > + struct event_cnt_priv *priv = dev_id;
> > > > > > > +
> > > > > > > + atomic_inc(>count);
> > > > > > 
> > > > > > This is just used to count the number of interrupts right? I wonder 
> > > > > > if
> > > > > > we can do this smarter. For example, the kernel already keeps track 
> > > > > > of
> > > > > > number of interrupts that has occurred for any particular IRQ line 
> > > > > > on a
> > > > > > CPU (see the 'kstat_irqs' member of struct irq_desc, and the
> > > > > > show_interrupts() function in kernel/irq/proc.c). Would it make 
> > > > > > sense to
> > > > > > simply store the initial interrupt count on driver load or 
> > > > > > enablement,
> > > > > > and then return the difference during a count_read() callback?
> > > > > 
> > > > > This driver do not makes a lot of sense without your chardev patches. 
> > > > > As
> > > > > soon as this patches go mainline, this driver will be able to send
> > > > > event with a timestamp and counter state to the user space.
> > > > > 
> > > > > With other words, we will need an irq handler anyway. In this case we
> > > > > can't save more RAM or CPU cycles by using system irq counters.
> > > > 
> > > > It's true that this driver will need an IRQ handler when the timestamp
> > > > functionality is added, but deriving the count value is different matter
> > > > regardless. There's already code in the kernel to retrieve the number of
> > > > interrupts, so it makes sense that we use that rather than rolling our
> > > > own -- at the very least to ensure the value we provide to users is
> > > > consistent with the ones already provided by other areas of the kernel.
> > 
> > The value provided by the driver is consistent only if it is not
> > overwritten by user. The driver provides an interface to reset/overwrite it.
> > At least after this step the value is not consistent.
> 
> I wasn't clear here so I apologize. What I would like is for this driver
> to maintain its own local count value derived from kstat_irqs_usr(). So
> for example, you can use the "count" member of your struct
> interrupt_cnt_priv to maintain this value (it can be unsigned int
> instead of atomic_t):
> 
> static int interrupt_cnt_read(struct counter_device *counter,
> struct counter_count *count, unsigned long *val)
> {
>   struct interrupt_cnt_priv *priv = counter->priv;
> 
>   *val = kstat_irqs_usr(priv->irq) - priv->count;
> 
>   return 0;
> }
> 
> static int interrupt_cnt_write(struct counter_device *counter,
>  struct counter_count *count,
>  const unsigned long val)
> {
>   struct interrupt_cnt_priv *priv = counter->priv;
> 
>   /* kstat_irqs_usr() returns unsigned int */
>   if (val != (unsigned int)val)
>   return -ERANGE;
> 
>   priv->count = val;
> 
>   return 0;
> }

I understand this part. There is no need to spend extra CPU cycles if
the interrupt was already counted. Just read it on user request and
calculate the offset if needed.

As soon as timestamp support is available, I will need to go back to
local counter, because the kstat_irqs_usr() will take a lot more CPU
cycles compared to private counter (it sums over all CPU local
counters). So it's better to increm

Re: [PATCH v5 2/2] counter: add IRQ or GPIO based event counter

2021-02-23 Thread Oleksij Rempel
Hello William,

Here is cooled down technical answer. Excuse me for over reacting.

On Tue, Feb 23, 2021 at 11:06:56AM +0100, Oleksij Rempel wrote:
> On Mon, Feb 22, 2021 at 10:43:00AM +0900, William Breathitt Gray wrote:
> > On Mon, Feb 15, 2021 at 10:17:37AM +0100, Oleksij Rempel wrote:
> > > > > +static irqreturn_t event_cnt_isr(int irq, void *dev_id)
> > > > > +{
> > > > > + struct event_cnt_priv *priv = dev_id;
> > > > > +
> > > > > + atomic_inc(>count);
> > > > 
> > > > This is just used to count the number of interrupts right? I wonder if
> > > > we can do this smarter. For example, the kernel already keeps track of
> > > > number of interrupts that has occurred for any particular IRQ line on a
> > > > CPU (see the 'kstat_irqs' member of struct irq_desc, and the
> > > > show_interrupts() function in kernel/irq/proc.c). Would it make sense to
> > > > simply store the initial interrupt count on driver load or enablement,
> > > > and then return the difference during a count_read() callback?
> > > 
> > > This driver do not makes a lot of sense without your chardev patches. As
> > > soon as this patches go mainline, this driver will be able to send
> > > event with a timestamp and counter state to the user space.
> > > 
> > > With other words, we will need an irq handler anyway. In this case we
> > > can't save more RAM or CPU cycles by using system irq counters.
> > 
> > It's true that this driver will need an IRQ handler when the timestamp
> > functionality is added, but deriving the count value is different matter
> > regardless. There's already code in the kernel to retrieve the number of
> > interrupts, so it makes sense that we use that rather than rolling our
> > own -- at the very least to ensure the value we provide to users is
> > consistent with the ones already provided by other areas of the kernel.

The value provided by the driver is consistent only if it is not
overwritten by user. The driver provides an interface to reset/overwrite it.
At least after this step the value is not consistent.

> We are talking about one or two code lines. If we will take some
> duplication search engine, it will find that major part of the kernel
> is matching against it.
> 
> Newer the less, this driver provides a way to reset the counter. Why
> should we drop this functionality no advantage?
> 
> > To that end, I'd like to see your cnt_isr() function removed for this
> > patchset (you can bring it back once timestamp support is added).

It make no sense to request an interrupt without interrupt service
routine.

https://elixir.bootlin.com/linux/latest/source/kernel/irq/manage.c#L2072if
if (!handler) {
if (!thread_fn)
return -EINVAL;

As you can see, requesting an irq need at least handler or thread_fn.

enable_irq: this will explode at least here:
https://elixir.bootlin.com/linux/latest/source/kernel/irq/manage.c#L778

If he have no IRQ handler and some how was able to enable it, at
some point this IRQ will be disabled by this code:
https://elixir.bootlin.com/linux/latest/source/kernel/irq/spurious.c#L410
if (unlikely(desc->irqs_unhandled > 99900)) {
/*
 * The interrupt is stuck
 */
__report_bad_irq(desc, action_ret);
/*
 * Now kill the IRQ
 */
printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
desc->istate |= IRQS_SPURIOUS_DISABLED;
desc->depth++;
irq_disable(desc);

With current code, we can't request or enable IRQ without cnt_isr(). Not
that it is not possible, but it make no sense to me.

> Are you suggesting to enable IRQ without interrupt handler? May be i'm
> missing some thing.. I do not understand it.
> 
> > Reimplement your cnt_read/cnt_write() functions to instead use
> > kstat_irqs_usr() from  to get the current number of
> > interrupts the IRQ line and use it to derive your count value for this
> > driver.

irq descriptor has 3 counters:
- irq_count: this value can be reset any time by the kernel at least by
  the note_interrupt()
- irqs_unhandled: this value is increased in case of missing irq
  handler. Or if handler has returns IRQ_NONE.
- tot_count: this value should not be reset.

Non of this values is suitable for cnt_read() and cnt_write(). Only
tot_count would be suitable if cnt_write() is removed. I do not see it
as acceptable option.

For this driver, we still need extra counter, where only this driver is
responsible for writing to it.

> I can follow the counter read way, b

Re: [PATCH v5 2/2] counter: add IRQ or GPIO based event counter

2021-02-23 Thread Oleksij Rempel
On Mon, Feb 22, 2021 at 10:43:00AM +0900, William Breathitt Gray wrote:
> On Mon, Feb 15, 2021 at 10:17:37AM +0100, Oleksij Rempel wrote:
> > > > +static irqreturn_t event_cnt_isr(int irq, void *dev_id)
> > > > +{
> > > > +   struct event_cnt_priv *priv = dev_id;
> > > > +
> > > > +   atomic_inc(>count);
> > > 
> > > This is just used to count the number of interrupts right? I wonder if
> > > we can do this smarter. For example, the kernel already keeps track of
> > > number of interrupts that has occurred for any particular IRQ line on a
> > > CPU (see the 'kstat_irqs' member of struct irq_desc, and the
> > > show_interrupts() function in kernel/irq/proc.c). Would it make sense to
> > > simply store the initial interrupt count on driver load or enablement,
> > > and then return the difference during a count_read() callback?
> > 
> > This driver do not makes a lot of sense without your chardev patches. As
> > soon as this patches go mainline, this driver will be able to send
> > event with a timestamp and counter state to the user space.
> > 
> > With other words, we will need an irq handler anyway. In this case we
> > can't save more RAM or CPU cycles by using system irq counters.
> 
> It's true that this driver will need an IRQ handler when the timestamp
> functionality is added, but deriving the count value is different matter
> regardless. There's already code in the kernel to retrieve the number of
> interrupts, so it makes sense that we use that rather than rolling our
> own -- at the very least to ensure the value we provide to users is
> consistent with the ones already provided by other areas of the kernel.

We are talking about one or two code lines. If we will take some
duplication search engine, it will find that major part of the kernel
is matching against it.

Newer the less, this driver provides a way to reset the counter. Why
should we drop this functionality no advantage?

> To that end, I'd like to see your cnt_isr() function removed for this
> patchset (you can bring it back once timestamp support is added).

Are you suggesting to enable IRQ without interrupt handler? May be i'm
missing some thing.. I do not understand it.

> Reimplement your cnt_read/cnt_write() functions to instead use
> kstat_irqs_usr() from  to get the current number of
> interrupts the IRQ line and use it to derive your count value for this
> driver.

I can follow the counter read way, but overwriting system wide counter
for local use is bad idea.

> > > > +static struct counter_signal event_cnt_signals[] = {
> > > > +   {
> > > > +   .id = 0,
> > > > +   .name = "Channel 0 signal",
> > > 
> > > You should choose a more description name for this Signal;
> > > "Channel 0 signal" isn't very useful information for the user. Is this
> > > signal the respective GPIO line state?
> > 
> > Sounds plausible. How about "Channel 0, GPIO line state"?
> 
> Ideally, this would match the GPIO name (or I suppose the IRQ number if
> not a GPIO line). So in your probe() function you can do something like
> this I believe:
> 
>   cnt_signals[0].name = priv->gpio->name;

to make this possible, i would need hack gpiolib framework and add
name/label exporter. But after endless rounds of pingponging me for
renaming the driver and removing interrupt handler, i feel like we are
not having serious discussion for mainlining this driver.

Is it some expensive way to prepare me for 1. April joke?

> Of course, you should first check whether this is a GPIO line or IRQ
> line and set the name accordingly.

Please, let's stop bike-shed for now. This driver has no limitless
budget. If there are serious problem, I would love to fix it, but if we
still discussing name of the driver or how to misuse kernel interrupt
handling, then it makes no sense to continue.

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


Re: [PATCH v6 0/2] add support for GPIO or IRQ based evemt counter

2021-02-22 Thread Oleksij Rempel
Hi William,

On Mon, Feb 22, 2021 at 10:48:56AM +0900, William Breathitt Gray wrote:
> On Tue, Feb 16, 2021 at 09:13:54AM +0100, Oleksij Rempel wrote:
> > changes v6:
> > - rename it to interrupt-counter
> 
> Hi Oleksij,
> 
> Sorry to nitpick again, I think "irq-counter" as Jonathan suggested in
> an earlier review would be a better name afterall. Would you be able to
> rename this driver to use that name instead?

I would prefer not to rename it. IRQ (Interrupt Request) is a signal
outside of the system. Below some frequency rate, amount of counted
ISR (interrupt service routine) calls or events would be equal to the actual
IRQs. If frequency is too high, we will count ISR, but not IRQs. In
any case, interrupt-counter is more or leas neutral, without triggering
too many wrong assumptions.

Regards,
Oleksij
-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


[PATCH net v4 1/1] net: introduce CAN specific pointer in the struct net_device

2021-02-22 Thread Oleksij Rempel
Since 20dd3850bcf8 ("can: Speed up CAN frame receiption by using
ml_priv") the CAN framework uses per device specific data in the AF_CAN
protocol. For this purpose the struct net_device->ml_priv is used. Later
the ml_priv usage in CAN was extended for other users, one of them being
CAN_J1939.

Later in the kernel ml_priv was converted to an union, used by other
drivers. E.g. the tun driver started storing it's stats pointer.

Since tun devices can claim to be a CAN device, CAN specific protocols
will wrongly interpret this pointer, which will cause system crashes.
Mostly this issue is visible in the CAN_J1939 stack.

To fix this issue, we request a dedicated CAN pointer within the
net_device struct.

Reported-by: syzbot+5138c4dd15a0401be...@syzkaller.appspotmail.com
Fixes: 20dd3850bcf8 ("can: Speed up CAN frame receiption by using ml_priv")
Fixes: ffd956eef69b ("can: introduce CAN midlayer private and allocate it 
automatically")
Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol")
Fixes: 497a5757ce4e ("tun: switch to net core provided statistics counters")
Signed-off-by: Oleksij Rempel 
---
 drivers/net/can/dev/dev.c  |  4 +++-
 drivers/net/can/slcan.c|  4 +++-
 drivers/net/can/vcan.c |  2 +-
 drivers/net/can/vxcan.c|  6 +-
 include/linux/can/can-ml.h | 12 
 include/linux/netdevice.h  | 34 +-
 net/can/af_can.c   | 34 ++
 net/can/j1939/main.c   | 22 --
 net/can/j1939/socket.c | 13 -
 net/can/proc.c | 19 +--
 10 files changed, 84 insertions(+), 66 deletions(-)

diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index d9281ae853f8..311d8564d611 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -239,6 +239,7 @@ void can_setup(struct net_device *dev)
 struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
unsigned int txqs, unsigned int rxqs)
 {
+   struct can_ml_priv *can_ml;
struct net_device *dev;
struct can_priv *priv;
int size;
@@ -270,7 +271,8 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, 
unsigned int echo_skb_max,
priv = netdev_priv(dev);
priv->dev = dev;
 
-   dev->ml_priv = (void *)priv + ALIGN(sizeof_priv, NETDEV_ALIGN);
+   can_ml = (void *)priv + ALIGN(sizeof_priv, NETDEV_ALIGN);
+   can_set_ml_priv(dev, can_ml);
 
if (echo_skb_max) {
priv->echo_skb_max = echo_skb_max;
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index a1bd1be09548..30c8d53c9745 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -516,6 +516,7 @@ static struct slcan *slc_alloc(void)
int i;
char name[IFNAMSIZ];
struct net_device *dev = NULL;
+   struct can_ml_priv *can_ml;
struct slcan   *sl;
int size;
 
@@ -538,7 +539,8 @@ static struct slcan *slc_alloc(void)
 
dev->base_addr  = i;
sl = netdev_priv(dev);
-   dev->ml_priv = (void *)sl + ALIGN(sizeof(*sl), NETDEV_ALIGN);
+   can_ml = (void *)sl + ALIGN(sizeof(*sl), NETDEV_ALIGN);
+   can_set_ml_priv(dev, can_ml);
 
/* Initialize channel control data */
sl->magic = SLCAN_MAGIC;
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
index 39ca14b0585d..067705e2850b 100644
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -153,7 +153,7 @@ static void vcan_setup(struct net_device *dev)
dev->addr_len   = 0;
dev->tx_queue_len   = 0;
dev->flags  = IFF_NOARP;
-   dev->ml_priv= netdev_priv(dev);
+   can_set_ml_priv(dev, netdev_priv(dev));
 
/* set flags according to driver capabilities */
if (echo)
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
index f9a524c5f6d6..8861a7d875e7 100644
--- a/drivers/net/can/vxcan.c
+++ b/drivers/net/can/vxcan.c
@@ -141,6 +141,8 @@ static const struct net_device_ops vxcan_netdev_ops = {
 
 static void vxcan_setup(struct net_device *dev)
 {
+   struct can_ml_priv *can_ml;
+
dev->type   = ARPHRD_CAN;
dev->mtu= CANFD_MTU;
dev->hard_header_len= 0;
@@ -149,7 +151,9 @@ static void vxcan_setup(struct net_device *dev)
dev->flags  = (IFF_NOARP|IFF_ECHO);
dev->netdev_ops = _netdev_ops;
dev->needs_free_netdev  = true;
-   dev->ml_priv= netdev_priv(dev) + ALIGN(sizeof(struct 
vxcan_priv), NETDEV_ALIGN);
+
+   can_ml = netdev_priv(dev) + ALIGN(sizeof(struct vxcan_priv), 
NETDEV_ALIGN);
+   can_set_ml_priv(dev, can_ml);
 }
 
 /* forward declaration for rtnl_create_link() */
diff --git a/include/linux/can/can-ml.h b/include/linux/can/can-ml.h
i

Re: [PATCH net v3] net: introduce CAN specific pointer in the struct net_device

2021-02-22 Thread Oleksij Rempel
Hi Jakub,

On Mon, Feb 22, 2021 at 05:30:12PM -0800, Jakub Kicinski wrote:
> On Mon, 22 Feb 2021 16:02:51 +0100 Oleksij Rempel wrote:
> > Since 20dd3850bcf8 ("can: Speed up CAN frame receiption by using
> > ml_priv") the CAN framework uses per device specific data in the AF_CAN
> > protocol. For this purpose the struct net_device->ml_priv is used. Later
> > the ml_priv usage in CAN was extended for other users, one of them being
> > CAN_J1939.
> > 
> > Later in the kernel ml_priv was converted to an union, used by other
> > drivers. E.g. the tun driver started storing it's stats pointer.
> > 
> > Since tun devices can claim to be a CAN device, CAN specific protocols
> > will wrongly interpret this pointer, which will cause system crashes.
> > Mostly this issue is visible in the CAN_J1939 stack.
> > 
> > To fix this issue, we request a dedicated CAN pointer within the
> > net_device struct.
> > 
> > Reported-by: syzbot+5138c4dd15a0401be...@syzkaller.appspotmail.com
> > Fixes: 20dd3850bcf8 ("can: Speed up CAN frame receiption by using ml_priv")
> > Fixes: ffd956eef69b ("can: introduce CAN midlayer private and allocate it 
> > automatically")
> > Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol")
> > Fixes: 497a5757ce4e ("tun: switch to net core provided statistics counters")
> > Signed-off-by: Oleksij Rempel 
> 
> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > index ddf4cfc12615..6e25c6f0f190 100644
> > --- a/include/linux/netdevice.h
> > +++ b/include/linux/netdevice.h
> > @@ -1584,6 +1584,16 @@ enum netdev_priv_flags {
> >  #define IFF_L3MDEV_RX_HANDLER  IFF_L3MDEV_RX_HANDLER
> >  #define IFF_LIVE_RENAME_OK IFF_LIVE_RENAME_OK
> >  
> > +/**
> > + * enum netdev_ml_priv_type -  net_device ml_priv_type
> > + *
> > + * This enum specifies the type of the struct net_device::ml_priv pointer.
> > + */
> 
> kdoc (scripts/kernel-doc -none include/linux/netdevice.h) is not happy
> about the fact enum values are not defined. Perhaps they will be
> sufficiently self-explanatory to not bother documenting?
> 
> Maybe just:
> 
> /* Specifies the type of the struct net_device::ml_priv pointer */
> 
> ?

sounds good, done.

> > +enum netdev_ml_priv_type {
> > +   ML_PRIV_NONE,
> > +   ML_PRIV_CAN,
> > +};
> > +
> >  /**
> >   * struct net_device - The DEVICE structure.
> >   *
> > @@ -1779,6 +1789,7 @@ enum netdev_priv_flags {
> >   * @nd_net:Network namespace this network device 
> > is inside
> >   *
> >   * @ml_priv:   Mid-layer private
> > +   @ml_priv_type:  Mid-layer private type
> 
> missing '*' at the start of the line

done

> >   * @lstats:Loopback statistics
> >   * @tstats:Tunnel statistics
> >   * @dstats:Dummy statistics
> > @@ -2094,8 +2105,10 @@ struct net_device {
> > possible_net_t  nd_net;
> >  
> > /* mid-layer private */
> > +   void*ml_priv;
> > +   enum netdev_ml_priv_typeml_priv_type;
> > +
> > union {
> > -   void*ml_priv;
> > struct pcpu_lstats __percpu *lstats;
> > struct pcpu_sw_netstats __percpu*tstats;
> > struct pcpu_dstats __percpu *dstats;
> > @@ -2286,6 +2299,29 @@ static inline void netdev_reset_rx_headroom(struct 
> > net_device *dev)
> > netdev_set_rx_headroom(dev, -1);
> >  }
> >  
> > +static inline void *netdev_get_ml_priv(struct net_device *dev,
> > +  enum netdev_ml_priv_type type)
> > +{
> > +   if (dev->ml_priv_type != type)
> > +   return NULL;
> > +
> > +   return dev->ml_priv;
> > +}
> > +
> > +static inline void netdev_set_ml_priv(struct net_device *dev,
> > + void *ml_priv,
> > + enum netdev_ml_priv_type type)
> > +{
> > +   WARN_ONCE(dev->ml_priv_type && dev->ml_priv_type != type,
> > + "Overwriting already set ml_priv_type (%u) with different 
> > ml_priv_type (%u)!\n",
> > + dev->ml_priv_type, type);
> > +   WARN_ONCE(!dev->ml_priv_type && dev->ml_priv,
> > + "Overwriting already set ml_priv and ml_priv_type is 
> > ML_PRIV_NONE!\n&q

[PATCH net v2 2/2] can: fix ref count warning if socket was closed before skb was cloned

2021-02-22 Thread Oleksij Rempel
There are two ref count variables controlling the free()ing of a socket:
- struct sock::sk_refcnt - which is changed by sock_hold()/sock_put()
- struct sock::sk_wmem_alloc - which accounts the memory allocated by
  the skbs in the send path.

If the socket is closed the struct sock::sk_refcnt will finally reach 0
and sk_free() is called. Which then calls
refcount_dec_and_test(>sk_wmem_alloc). If sk_wmem_alloc reaches 0
the socket is actually free()ed.

In case there are still TX skbs on the fly and the socket() is closed,
the struct sock::sk_refcnt reaches 0. In the TX-path the CAN stack
clones an "echo" skb, calls sock_hold() on the original socket and
references it. This produces the following back trace:

| WARNING: CPU: 0 PID: 280 at lib/refcount.c:25 
refcount_warn_saturate+0x114/0x134
| refcount_t: addition on 0; use-after-free.
| Modules linked in: coda_vpu(E) v4l2_jpeg(E) videobuf2_vmalloc(E) imx_vdoa(E)
| CPU: 0 PID: 280 Comm: test_can.sh Tainted: GE 
5.11.0-04577-gf8ff6603c617 #203
| Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
| Backtrace:
| [<80bafea4>] (dump_backtrace) from [<80bb0280>] (show_stack+0x20/0x24) 
r7: r6:600f0113 r5: r4:81441220
| [<80bb0260>] (show_stack) from [<80bb593c>] (dump_stack+0xa0/0xc8)
| [<80bb589c>] (dump_stack) from [<8012b268>] (__warn+0xd4/0x114) r9:0019 
r8:80f4a8c2 r7:83e4150c r6: r5:0009 r4:80528f90
| [<8012b194>] (__warn) from [<80bb09c4>] (warn_slowpath_fmt+0x88/0xc8) 
r9:83f26400 r8:80f4a8d1 r7:0009 r6:80528f90 r5:0019 r4:80f4a8c2
| [<80bb0940>] (warn_slowpath_fmt) from [<80528f90>] 
(refcount_warn_saturate+0x114/0x134) r8: r7: r6:82b44000 
r5:834e5600 r4:83f4d540
| [<80528e7c>] (refcount_warn_saturate) from [<8079a4c8>] 
(__refcount_add.constprop.0+0x4c/0x50)
| [<8079a47c>] (__refcount_add.constprop.0) from [<8079a57c>] 
(can_put_echo_skb+0xb0/0x13c)
| [<8079a4cc>] (can_put_echo_skb) from [<8079ba98>] 
(flexcan_start_xmit+0x1c4/0x230) r9:0010 r8:83f48610 r7:0fdc 
r6:0c08 r5:82b44000 r4:834e5600
| [<8079b8d4>] (flexcan_start_xmit) from [<80969078>] 
(netdev_start_xmit+0x44/0x70) r9:814c0ba0 r8:80c8790c r7: r6:834e5600 
r5:82b44000 r4:82ab1f00
| [<80969034>] (netdev_start_xmit) from [<809725a4>] 
(dev_hard_start_xmit+0x19c/0x318) r9:814c0ba0 r8: r7:82ab1f00 
r6:82b44000 r5: r4:834e5600
| [<80972408>] (dev_hard_start_xmit) from [<809c6584>] 
(sch_direct_xmit+0xcc/0x264) r10:834e5600 r9: r8: r7:82b44000 
r6:82ab1f00 r5:834e5600 r4:83f27400
| [<809c64b8>] (sch_direct_xmit) from [<809c6c0c>] (__qdisc_run+0x4f0/0x534)

To fix this problem, we have to take into account, that the socket
technically still there but should not used (by any new skbs) any more.
The function skb_clone_sk_optional() (introduced in the previous patch)
takes care of this. It will only clone the skb, if the sk is set and the
refcount has not reached 0.

Cc: Oliver Hartkopp 
Cc: Andre Naujoks 
Cc: Eric Dumazet 
Fixes: 0ae89beb283a ("can: add destructor for self generated skbs")
Signed-off-by: Oleksij Rempel 
---
 include/linux/can/skb.h   | 3 +--
 net/can/af_can.c  | 6 +++---
 net/can/j1939/main.c  | 3 +--
 net/can/j1939/socket.c| 3 +--
 net/can/j1939/transport.c | 4 +---
 5 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 685f34cfba20..bc1af38697a2 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -79,13 +79,12 @@ static inline struct sk_buff *can_create_echo_skb(struct 
sk_buff *skb)
 {
struct sk_buff *nskb;
 
-   nskb = skb_clone(skb, GFP_ATOMIC);
+   nskb = skb_clone_sk_optional(skb);
if (unlikely(!nskb)) {
kfree_skb(skb);
return NULL;
}
 
-   can_skb_set_owner(nskb, skb->sk);
consume_skb(skb);
return nskb;
 }
diff --git a/net/can/af_can.c b/net/can/af_can.c
index cce2af10eb3e..9e1bd60e7e1b 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -251,20 +251,20 @@ int can_send(struct sk_buff *skb, int loop)
 * its own. Example: can_raw sockopt CAN_RAW_RECV_OWN_MSGS
 * Therefore we have to ensure that skb->sk remains the
 * reference to the originating sock by restoring skb->sk
-* after each skb_clone() or skb_orphan() usage.
+* after each skb_clone() or skb_orphan() usage -
+* skb_clone_sk_optional() takes care of that.
 */
 
if (!(skb->dev->flags & IFF_ECHO)) {
/* If the interface is not capable to do loopback
 * itself, we do it here.
 */
-   

[PATCH net v2 1/2] skbuff: skb_clone_sk_optional(): add function to always clone a skb and increase refcount on sk if valid

2021-02-22 Thread Oleksij Rempel
There already the function skb_clone_sk(), which clones the skb, but
only if the sk is valid.

There are several users in the networking stack, which always need a
clone of a skb with the sk refcount incremented (but only if the sk is
valid). This patch adds such a function.

Signed-off-by: Oleksij Rempel 
---
 include/linux/skbuff.h |  1 +
 net/core/skbuff.c  | 27 +++
 2 files changed, 28 insertions(+)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6d0a33d1c0db..99d552017508 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3874,6 +3874,7 @@ static inline void skb_metadata_clear(struct sk_buff *skb)
skb_metadata_set(skb, 0);
 }
 
+struct sk_buff *skb_clone_sk_optional(struct sk_buff *skb);
 struct sk_buff *skb_clone_sk(struct sk_buff *skb);
 
 #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 545a472273a5..97341f173fb0 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4671,6 +4671,33 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk)
 }
 EXPORT_SYMBOL(sock_dequeue_err_skb);
 
+/**
+ * skb_clone_sk_optional - create clone of skb, and take reference to socket if
+ * socket is referenced in original skb
+ * @skb: the skb to clone
+ *
+ * This function always creates a clone of a buffer. If it that holds a valid
+ * reference on sk_refcnt this is increased.
+ */
+struct sk_buff *skb_clone_sk_optional(struct sk_buff *skb)
+{
+   struct sock *sk = skb->sk;
+   struct sk_buff *clone;
+
+   clone = skb_clone(skb, GFP_ATOMIC);
+   if (!clone)
+   return NULL;
+
+   if (!sk || !refcount_inc_not_zero(>sk_refcnt))
+   return clone;
+
+   clone->sk = sk;
+   clone->destructor = sock_efree;
+
+   return clone;
+}
+EXPORT_SYMBOL(skb_clone_sk_optional);
+
 /**
  * skb_clone_sk - create clone of skb, and take reference to socket
  * @skb: the skb to clone
-- 
2.29.2



  1   2   3   4   5   6   7   8   9   10   >